Skip to content

Latest commit

 

History

History
1318 lines (1045 loc) · 47.2 KB

PITCHME.md

File metadata and controls

1318 lines (1045 loc) · 47.2 KB

---?image=assets/images/gitpitch-audience.jpg @title[UEFI_Driver_Porting Lab]




UEFI & EDK II Training

How to Write a UEFI Driver Lab


tianocore.org Note: PITCHME.md for UEFI / EDK II Training UEFI Driver Porting Lab

Copyright (c) 2018, Intel Corporation. All rights reserved.

Redistribution and use in source (original document form) and 'compiled' forms (converted to PDF, epub, HTML and other formats) with or without modification, are permitted provided that the following conditions are met:

  1. Redistributions of source code (original document form) must retain the above copyright notice, this list of conditions and the following disclaimer as the first lines of this file unmodified.

  2. Redistributions in compiled form (transformed to other DTDs, converted to PDF, epub, HTML and other formats) must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

THIS DOCUMENTATION IS PROVIDED BY TIANOCORE PROJECT "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL TIANOCORE PROJECT BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS DOCUMENTATION, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


@title[Lesson Objective]

<p align="center"Lesson Objective


  • @fa[certificate gp-bullet-green]  Compile a UEFI driver template created from
            UEFI Driver Wizard

  • @fa[certificate gp-bullet-cyan]  Test driver in QEMU using UEFI Shell 2.0

  • @fa[certificate gp-bullet-yellow]  Port code into the template driver

---?image=assets/images/binary-strings-black2.jpg @title[UEFI Driver Lab]






     UEFI Driver Porting Lab

        This Lab uses the template UEFI driver created by the
         UEFI Driver Wizard

---?image=/assets/images/slides/Slide_LabSec.JPG @title[Lab 2: Building a UEFI Driver]

Lab 2: Building a UEFI Driver


In this lab, you’ll build a UEFI Driver created by the UEFI Driver Wizard.
You will include the driver in the OVMF project.
Build the UEFI Driver from the Driver Wizard
 

@title[Compile a UEFI Driver?]

Compile a UEFI Driver


Two Ways to Compile a Driver

Standalone

In a Project

The build command directly compiles the .INF file

Include the .INF file in the project’s .DSC file

Results: The driver’s .EFI file is located in the Build directory

Results: The driver’s .EFI file is a part of the project in the Build directory

Note:

Standalone In a Project
The build command directly compiles the .INF file Include the .INF file in the project’s .DSC file
Results: The driver’s .EFI file is located in the Build directory Results: The driver’s .EFI file is a part of the project in the Build directory

@title[Lab2: Build the UEFI Driver?]

Lab 2: Build the UEFI Driver


  • Perform Lab Setup from previous Labs
  • Open `~src/edk2/OvmfPkg/OvmfPkgX64.dsc`
  • Add the following to the `[Components]` section:
    *Hint:*add to the last module in the `[Components]` section
  • ```
        # Add new modules here
       MyWizardDriver/MyWizardDriver.inf{
              DebugLib|MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.inf
       }
    ```
  • Save and close the file `~src/edk2/OvmfPkg/OvmfPkgX64.dsc`

@title[Lab 2 Build and Test Driver]

Lab 2: Build and Test Driver


Build MyWizardDriver – Cd to ~/src/edk2 dir ```shell bash$ . edksetup.sh bash$ build ```

Build error Known issue from UEFI Driver Wizard:
   ComponentName.c Line 148 col 74 needs “//” in front of “## TO_START

   bash$ build

Build ERRORS: Copy the solution files from ~/FW/LabSampleCode/LabSolutions/LessonC.1 to ~/src/edk2/MyWizardDriver

Note: continue to next slide

---?image=/assets/images/slides/Slide6.JPG @title[Lab 2 Build and Test Driver 02]

Lab 2: Build and Test Driver


Copy MyWizardDriver.efi to hda-contents ``` bash$ cd ~/run-ovmf/hda-contents bash$ cp ~/src/edk2/Build/OvmfX64/DEBUG_GCC5/X64/MyWizardDriver.efi . ```
Test by Invoking Qemu
```
  bash$ cd ~/run-ovmf
  bash$ . RunQemu.sh
```
Load the UEFI Driver from the shell
    At the Shell prompt, type  `fs0:`
    Type:  `load MyWizardDriver.efi`

Note:

Same as slide

---?image=/assets/images/slides/Slide7.JPG @title[Lab 2 Test Driver Drivers]

Lab 2: Test Driver


At the shell prompt Type: `drivers`
Verify the UEFI Shell loaded the new driver. The `drivers` command will display the driver information and a driver handle number ("a9" in the example screenshot )

Note:

Same as slide

---?image=/assets/images/slides/Slide8.JPG @title[Lab 2 Test Driver -Dh]

Lab 2: Test Driver


At the shell prompt using the handle from the `drivers` command, Type:  `dh -d a9`
Note: The value `a9` is the driver handle for MyWizardDriver. The handle value may change based on your system configuration.(see example screenshot - right)

Note:

Same as slide

---?image=/assets/images/slides/Slide9.JPG @title[Lab 2 Test Driver -unload]

Lab 2: Test Driver


At the shell prompt using the handle from the `drivers` command, Type:  `unload a9`
See example screenshot - below
Type:  `drivers` again

Notice results of `unload` command

Exit QEMU

Note:

Same as slide

---?image=/assets/images/slides/Slide_LabSec.JPG @title[Lab 3: Component Name Section]

Lab 3: Component Name


In this lab, you’ll change the information reported to the drivers command using the ComponentName and ComponentName2 protocols.
 

@title[Lab 3: Component Name ]

Lab 3: Component Name


  • Open   `~/src/edk2/MyWizardDriver/ComponentName.c`
  • Change   the string returned by the driver from `MyWizardDriver` to:     `UEFI Sample Driver`
  • ```
      /// Table of driver names
     ///
     GLOBAL_REMOVE_IF_UNREFERENCED 
     EFI_UNICODE_STRING_TABLE mMyWizardDriverDriverNameTable[] = {
       { "eng;en", (CHAR16 *)L"UEFI Sample Driver" },
       { NULL, NULL }
     };
    ```
  • Save and close the file: `~/src/edk2/MyWizardDriver/ComponentName.c`

@title[Lab 3 Build and Test Driver]

Lab 3: Build and Test Driver


Build MyWizardDriver – Cd to ~/src/edk2 dir ```shell bash$ build ``` Copy MyWizardDriver.efi to hda-contents ```shell bash$ cd ~/run-ovmf/hda-contents bash$ cp ~/src/edk2/Build/OvmfX64/DEBUG_GCC5/X64/MyWizardDriver.efi . ``` Test by Invoking Qemu ```shell bash$ cd ~/run-ovmf bash$ . RunQemu.sh ```

---?image=/assets/images/slides/Slide11.JPG @title[Lab 3 Build and Test Driver]

Lab 3: Build and Test Driver

Load the UEFI Driver from the shell
    At the Shell prompt, type  `Shell> ``fs0:`
    Type:  `FS0:\> ` `load MyWizardDriver.efi`

Type:  `drivers`
Observe the change in the string that the driver returned

Exit QEMU

Note:

Same as slide

---?image=/assets/images/slides/Slide_LabSec.JPG @title[Lab 4: Port Supported Section]

Lab 4: Porting the Supported & Start Functions


The UEFI Driver Wizard produced a starting point for driver porting … so now what?

In this lab, you’ll port the “Supported” and “Start” functions for the UEFI driver
 

---?image=/assets/images/slides/Slide17_1.JPG @title[Lab 4: Port Supported-Start]

Lab 4: Porting Supported and Start

        Review the Driver Binding Protocol

@snap[north-west span-20 ]



@fa[star gp-bullet-cyan]

@snapend

@snap[north-east span-85 ]



@coloryellow
Determines if a driver supports a controller

@snapend

@snap[north-west span-20 ]







@fa[star gp-bullet-ltgreen]

@snapend

@snap[north-east span-85 ]







@coloryellow
Starts a driver on a controller & Installs Protocols

@snapend

@snap[north-west span-20 ]











@fa[star gp-bullet-gold]

@snapend

@snap[north-east span-85 ]











@coloryellow
Stops a driver from managing a controller

@snapend

Note:

  • Supported ()
  • Start()
  • Stop()

Supported() - Checks if a driver supports a controller Check should not change hardware state of controller Minimize execution time, move complex I/O to Start() May be called for controller that is already managed Child is optionally specified

Start() - Starts a driver on a controller Can create ALL child handles or ONE child handle A driver is not required to support starting ONE child handle. It may always create ALL child handles.

Stop() - Stops a driver from managing a controller Destroys all specified child handles If no children are specified, controller is stopped immediately Stopping a bus controller requires two calls

tasks

  • Port Supported() to check for a specific protocol before returning ‘Success’
  • Port Start() to allocate a memory buffer and fill it with a specific value

@title[Lab 4: Supported Port]

Lab 4: The `Supported()` Port


The UEFI Driver Wizard produced a `Supported()` function but it only returns `EFI_UNSUPPORTED`
Supported Goals:
  • Checks if the driver supports the device for the specified controller handle
  • Associates the driver with the Serial I/O protocol
  • Helps locate a protocol’s specific GUID through UEFI Boot Services’ function

Note:

Same as slide

---?image=/assets/images/slides/Slide16.JPG @title[Lab 4: Help from Robust Libraries]

Lab 4: Help from Robust Libraries

EDK II has libraries to help with porting UEFI Drivers
  • @fa[book gp-bullet-gold]  `AllocateZeroPool()` include - `[MemoryAllocationLib.h]`

  • @fa[book gp-bullet-gold]  `SetMem16()` include - `[BaseMemoryLib.h]`







Check the MdePkg with libraries help file (.chm format)

Note:


@title[Lab 4: Update Supported ]

Lab 4: Update Supported


  • Open   `~/src/edk2/MyWizardDriver/MyWizardDriver.c`
  • Locate   ` MyWizardDriverDriverBindingSupported()`, the supported function for this driver and comment out the "`//`" in the line: "`return EFI_UNSUPPORTED;` "
  • ```
    EFI_STATUS
    EFIAPI
    MyWizardDriverDriverBindingSupported (
      IN EFI_DRIVER_BINDING_PROTOCOL  *This,
      IN EFI_HANDLE                   ControllerHandle,
      IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL
      )
    {
      // return EFI_UNSUPPORTED;
    }
    ```
  • copy and past (next slide)

Note:

This code checks for a specific protocol before returning a status for the supported function (EFI_SUCCESS if the protocol GUID exists).


@title[Lab 4: Update Supported 02 ]

Lab 4: Update Supported Add Code

Copy & Paste   the following code for the supported function ` MyWizardDriverDriverBindingSupported()`: ```C EFI_STATUS Status; EFI_SERIAL_IO_PROTOCOL *SerialIo; Status = gBS->OpenProtocol ( ControllerHandle, &gEfiSerialIoProtocolGuid, (VOID **) &SerialIo, This->DriverBindingHandle, ControllerHandle, EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE );

if (EFI_ERROR (Status)) { return Status; // Bail out if OpenProtocol returns an error }

// We're here because OpenProtocol was a success, so clean up
 gBS->CloseProtocol (
    ControllerHandle,
    &gEfiSerialIoProtocolGuid,
    This->DriverBindingHandle,
    ControllerHandle
    );

 return EFI_SUCCESS; 


---
@title[Lab 4: Notice UEFI Driver Wizard Includes  ]
<p align="right"><span class="gold" >Lab 4: Notice UEFI Driver Wizard Includes</span></p>
<ul>
   <li><span style="font-size:0.8em" ><b>Open</b>&nbsp;&nbsp;</span><span style="font-size:0.7em" > `~/src/edk2/MyWizardDriver/MyWizardDriver.h`</span></li>
   <li><span style="font-size:0.8em" ><b>Notice</b>&nbsp;&nbsp;</span><span style="font-size:0.7em" > the following include statement is already added by the driver wizard: </span></li>
<pre lang="c">

// Produced Protocols // #include <Protocol/SerialIo.h>

</pre>
   <li><span style="font-size:0.8em" ><b>Review</b>&nbsp;&nbsp;</span><span style="font-size:0.7em" > the Libraries section and see that UEFI Driver Wizard automatically includes library headers based on the form information. Also other common libary headers were included </span></li>
<pre lang="c">

// Libraries // #include <Library/UefiBootServicesTableLib.h> #include <Library/MemoryAllocationLib.h> #include <Library/BaseMemoryLib.h> #include <Library/BaseLib.h> #include <Library/UefiLib.h> #include <Library/DevicePathLib.h> #include <Library/DebugLib.h>

</pre>
</ul>

Note: 


---
@title[Lab 4: Update the Start  ]
<p align="right"><span class="gold" >Lab 4: Update the `Start()` </span></p>
<ul>
   <li><span style="font-size:0.8em" ><b>Copy & Paste</b>&nbsp;&nbsp;</span><span style="font-size:0.7em" > the following in  `MyWizardDriver.c` after the <br><span style="background-color: #101010">`#include “MyWizardDriver.h”` </span>line: </span></li>
<pre lang="c">

#define DUMMY_SIZE 100*16 // Dummy buffer CHAR16 *DummyBufferfromStart = NULL;

</pre>
    <li><span style="font-size:0.8em" ><b>Locate</b>&nbsp;&nbsp;</span><span style="font-size:0.7em" > ` MyWizardDriverDriverBindingStart()`,  the start function for this driver and comment out the "`//`" in the line <span style="background-color: #101010">"`return EFI_UNSUPPORTED;` "</span></span></li>
<pre lang="c">

EFI_STATUS EFIAPI MyWizardDriverDriverBindingStart ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE ControllerHandle, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL ) { // return EFI_UNSUPPORTED; }

</pre>
   
</ul>

Note: 


---
@title[Lab 4: Update Start 02 ]
<p align="right"><span class="gold" >Lab 4: Update Start Add Code </span></p>
<span style="font-size:0.8em" ><b>Copy & Paste</b>&nbsp;&nbsp;</span><span style="font-size:0.65em" > the following code for the start function ` MyWizardDriverDriverBindingStart()`:</span>
```C
	if (DummyBufferfromStart == NULL) {     // was buffer already allocated?
		DummyBufferfromStart = (CHAR16*)AllocateZeroPool (DUMMY_SIZE * sizeof(CHAR16));
	}

	if (DummyBufferfromStart == NULL) {
		return EFI_OUT_OF_RESOURCES;    // Exit if the buffer isn’t there
	}

	SetMem16 (DummyBufferfromStart, (DUMMY_SIZE * sizeof(CHAR16)), 0x0042);  // Fill buffer

	return EFI_SUCCESS;
  • Notice the Library calls to `AllocateZeroPool()` and `SetMem16()`
  • The `Start()` function is where there would be calls to "`gBS->InstallMultipleProtocolInterfaces()`"

Note:

  • This code checks for an allocated memory buffer. If the buffer doesn’t exist, memory will be allocated and filled with an initial value (0x0042).
  • this lab's start does not do anything useful but if it did it would make calls to gBS->InstallMultipleProtocolInterfaces() to produce potocols and manage other handle devices

---?image=/assets/images/slides/Slide18.JPG @title[Lab 4: Debugging before Testing the Driver ]

Lab 4: Debugging before Testing the Driver


UEFI drivers can use the EDK II debug library
  • @fa[book gp-bullet-gold]  `DEBUG( )` include - `[DebugLib.h]`

  • `DEBUG()` Macro statements can show status progress interest points throughout the driver code
 

@title[Lab 4: Add Debug statements supported ]

Lab 4: Add Debug Statements `Supported()`

Copy & Paste   the following `DEBUG ()` macros for the supported function: ```C Status = gBS->OpenProtocol( ControllerHandle, &gEfiSerialIoProtocolGuid, (VOID **)&SerialIo, This->DriverBindingHandle, ControllerHandle, EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE );
if (EFI_ERROR(Status)) {
   DEBUG((EFI_D_INFO, "[MyWizardDriver] Not Supported \r\n"));
   return Status; // Bail out if OpenProtocol returns an error
}

// We're here because OpenProtocol was a success, so clean up
gBS->CloseProtocol(
	ControllerHandle,
	&gEfiSerialIoProtocolGuid,
	This->DriverBindingHandle,
	ControllerHandle
	);
DEBUG((EFI_D_INFO, "[MyWizardDriver] Supported SUCCESS\r\n"));
return EFI_SUCCESS;
@[11](Copy / Paste DEBUG macro here. The `Status` variable depends on the output of the `OpenProtocol` function.)
@[22](Copy / Paste another DEBUG macro here. It is only display when the Supported function returns EFI_SUCCESS.)



---
@title[Lab 4: Add Debug statements start ]
<p align="right"><span class="gold" >Lab 4: Add Debug Statements `Start()`</span></p>
<br>
<span style="font-size:0.8em" ><b>Copy & Paste</b>&nbsp;&nbsp;</span><span style="font-size:0.7em" > the following <span style="background-color: #101010">`DEBUG`</span> macro for the Start function just before the <span style="background-color: #101010">`return EFI_SUCCESS;` </span>statement</span></span>
```C
  DEBUG ((EFI_D_INFO, "\r\n***\r\n[MyWizardDriver] Buffer 0x%08x\r\n", DummyBufferfromStart));
  return EFI_SUCCESS;

Note: This debug macro displays the memory address of the allocated buffer on the debug console

Save   ~/src/edk2/MyWizardDriver/MyWizardDriver.c


@title[Lab 4 Build and Test Driver]

Lab 4: Build and Test Driver


Build MyWizardDriver – Cd to ~/src/edk2 dir ```shell bash$ build ``` Copy MyWizardDriver.efi to hda-contents ```shell bash$ cd ~/run-ovmf/hda-contents bash$ cp ~/src/edk2/Build/OvmfX64/DEBUG_GCC5/X64/MyWizardDriver.efi . ``` Test by Invoking Qemu ```shell bash$ cd ~/run-ovmf bash$ . RunQemu.sh ```

---?image=/assets/images/slides/Slide20.JPG @title[Lab 4 Build and Test Driver 02]

Lab 4: Build and Test Driver


Load the UEFI Driver from the shell
    At the Shell prompt, type  `Shell> ``fs0:`
    Type:  `FS0:\> ` `load MyWizardDriver.efi`



Note:

Same as slide

---?image=/assets/images/slides/Slide21.JPG @title[Lab 4 Build and Test Driver 03]

Lab 4: Build and Test Driver


  • Check the QEMU debug console output.
  • Notice Debug messages indicate the driver did not return `EFI_SUCCESS` from the “`Supported()`” function most of the time.
  • See that the "`Start()`" function did get called and a Buffer was allocated.


Exit QEMU

---?image=/assets/images/slides/Slide_LabSec.JPG @title[Lab 5: Create NV Var Section]

Lab 5: Create a NVRAM Variable


  • In this lab you’ll create a non-volatile UEFI variable (NVRAM), and set and get the variable to return a successful supported function
  • Use Runtime services to "`SetVariable()`" and "`GetVariable()`"
 

Note:

On systems without a serial port, the code from previous lab will not work since the Serial Protocol GUID does not exist. This lab demonstrates another mechanism (also known as “a trick”) to return from the “Supported” function.

With QEMU there is a serial device so the driver’s start function would then start to manage the serial port by creating child handles.


@title[Lab 5: Create NV Var steps]

Lab 5: Adding a NVRAM Variable Steps


  1. Create .h file with new `typedef` definition and its own `GUID`
  2. Include the new .h file in the driver's top .h file
  3. `EntryPoint()` Init new buffer for NVRam Variable
  4. `Supported()` make a call to a new function to set/get the new NVRam Variable
  5. Before `EntryPoint()` add the new function `CreateNVVariable()` to the driver.c file.

@title[Lab 5: Create a new .h file ]

Lab 5: Create a new .h file

Create   a new file in your editor called: "`MyWizardDriverNVDataStruc.h`"
Copy, Paste and then Save this file   ```C++ #ifndef _MYWIZARDDRIVERNVDATASTRUC_H_ #define _MYWIZARDDRIVERNVDATASTRUC_H_ #include #include

#define MYWIZARDDRIVER_VAR_GUID
{
0x363729f9, 0x35fc, 0x40a6, 0xaf, 0xc8, 0xe8, 0xf5, 0x49, 0x11, 0xf1, 0xd6
}

#pragma pack(1) typedef struct {

UINT16  MyWizardDriverStringData[20];
UINT8   MyWizardDriverHexData;
UINT8   MyWizardDriverBaseAddress;
UINT8   MyWizardDriverChooseToEnable;

} MYWIZARDDRIVER_CONFIGURATION;

#pragma pack()

#endif


Note:

- In order to set, retrieve, and use the UEFI variable, it requires the GUID reference that you just added.

- another Note:  For this lab, you were provided a GUID file.  You can also generate a GUID through the UEFI Driver Wizard or Guidgenerator.com.  But for the purposes of the lab, use the one above.



---
@title[Lab 5: Add New Vars to .c ]
<p align="right"><span class="gold" >Lab 5: Update MyWizardDriver.c</span></p>
<br>
<span style="font-size:0.8em" ><b>Open</b>&nbsp;&nbsp;</span><span style="font-size:0.7em" > "`~/src/edk2/MyWizardDriver/MyWizardDriver.c`"</span><br>
<span style="font-size:0.8em" ><b>Copy & Paste</b>&nbsp;&nbsp;</span><span style="font-size:0.65em" > the following  4 lines after the `#include "MyWizardDriver.h"` statement: </span><br>
```C
#include "MyWizardDriver.h"

EFI_GUID   mMyWizardDriverVarGuid = MYWIZARDDRIVER_VAR_GUID;

CHAR16     mVariableName[] = L"MWD_NVData";  // Use Shell "Dmpstore" to see 
MYWIZARDDRIVER_CONFIGURATION   mMyWizDrv_Conf_buffer;
MYWIZARDDRIVER_CONFIGURATION   *mMyWizDrv_Conf = &mMyWizDrv_Conf_buffer;  //use the pointer 

@title[Lab 5: Update Suppport for new function ]

Lab 5: Update MyWizardDriver.c


Locate   "`MyWizardDriverDriverBindingSupported ()`" function
Comment out   the `DEBUG` macro statement and return statement as below:
Copy & Paste   the 2 lines: 1) new "`CreateNVVariable();`" call and 2) "`return`" as below:
```C if (EFI_ERROR(Status)) { //DEBUG((EFI_D_INFO, "[MyWizardDriver] Not Supported \r\n")); //return Status; // Bail out if OpenProtocol returns an error Status = CreateNVVariable(); if (EFI_ERROR(Status)) { DEBUG((EFI_D_ERROR, "[MyWizardDriver] Not Supported \r\n")); } return Status; // Status now depends on CreateNVVariable Function



---
@title[Lab 5: Add new function ]
<p align="right"><span class="gold" >Lab 5: Update MyWizardDriver.c</span></p>
<span style="font-size:0.7em" ><b>Copy & Paste</b>&nbsp;&nbsp;</span><span style="font-size:0.5em" > the new function before the call to 
      "`MyWizardDriverDriverEntryPoint()`" </span>
```c
EFI_STATUS
EFIAPI
CreateNVVariable()
{
	EFI_STATUS            	Status;
	UINTN                  BufferSize;

	BufferSize = sizeof (MYWIZARDDRIVER_CONFIGURATION);
	Status = gRT->GetVariable(
		mVariableName,
		&mMyWizardDriverVarGuid,
		NULL,
		&BufferSize,
		mMyWizDrv_Conf
		);
	if (EFI_ERROR(Status)) {  // Not definded yet so add it to the NV Variables.
		if (Status == EFI_NOT_FOUND) {
			Status = gRT->SetVariable(
				mVariableName,
				&mMyWizardDriverVarGuid,
				EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
				sizeof (MYWIZARDDRIVER_CONFIGURATION),
				mMyWizDrv_Conf   //  buffer is 000000  now for first time set
				);
			DEBUG((EFI_D_INFO, "[MyWizardDriver] Variable %s created in NVRam Var\r\n", mVariableName));
			return EFI_SUCCESS;
		}
	}
	// already defined once 
	return EFI_UNSUPPORTED;
}

@title[Lab 5: Update .h]

Lab 5: Update MyWizardDriver.h

Open   "`~/src/edk2/MyWizardDriver/MyWizardDriver.h`"
Copy & Paste   the following "#include" after the list of library include statements:
```C++ // Libraries // . . . #include ``` Copy & Paste   the following "#include" after the list of protocol include statements:
```C++ // Produced Protocols // . . . #include "MyWizardDriverNVDataStruc.h" ``` Save   "`~/src/edk2/MyWizardDriver/MyWizardDriver.h`"
Save   "`~/src/edk2/MyWizardDriver/MyWizardDriver.c`"

@title[Lab 5 Build and Test Driver]

Lab 5: Build and Test Driver


Build MyWizardDriver – Cd to ~/src/edk2 dir ```shell bash$ build ``` Copy MyWizardDriver.efi to hda-contents ```shell bash$ cd ~/run-ovmf/hda-contents bash$ cp ~/src/edk2/Build/OvmfX64/DEBUG_GCC5/X64/MyWizardDriver.efi . ``` Test by Invoking Qemu ```shell bash$ cd ~/run-ovmf bash$ . RunQemu.sh ```

---?image=/assets/images/slides/Slide25.JPG @title[Lab 5 Build Test Driver]

Lab 5: Test Driver


Load the UEFI Driver from the shell
    At the Shell prompt, type  `Shell> ``fs0:`
    Type:  `FS0:\> ` `load MyWizardDriver.efi`

Observe the Buffer address returned by the debug statement

Note:

Same as slide

---?image=/assets/images/slides/Slide26.JPG @title[Lab 5 Verify Driver]

Lab 5: Verify Driver


At the Shell prompt, type   `FS0:\> ` `mem 0x6808018`
Observe the Buffer is filled with the letter "B" or 0x0042




Note:

Same as slide

---?image=/assets/images/slides/Slide42.JPG @title[Lab 5 Verify NVRAM Driver]

Lab 5: Verify NVRAM Created by Driver


At the Shell prompt, type   `FS0:\> ``dmpstore -all -b`
Observe new the NVRAM variable "`MWD_NVData`" was created and filled with 0x00s






Exit QEMU

Note:

Same as slide

---?image=/assets/images/slides/Slide_LabSec.JPG @title[Lab 6: Port Stop and Unload]

Lab 6: Port Stop and Unload


In this lab, you’ll port the driver’s “Unload” and “Stop” functions to free any resources the driver allocated when it was loaded and started.
 

Note:


@title[Lab 6: Port the Unload]

Lab 6: Port the Unload function


Open   "`~/src/edk2/MyWizardDriver/MyWizardDriver.c`"
Locate   "`MyWizardDriverUnload ()`" function
Copy & Paste   the following "`if`" and "`DEBUG`" statements before the "`return EFI_SUCCESS;`" statement.
```C++ // Do any additional cleanup that is required for this driver // if (DummyBufferfromStart != NULL) { FreePool(DummyBufferfromStart); DEBUG((EFI_D_INFO, "[MyWizardDriver] Unload, clear buffer\r\n")); } DEBUG((EFI_D_INFO, "[MyWizardDriver] Unload success\r\n"));

return EFI_SUCCESS;


Note:

- The code will deallocate the buffer using the FreePool library function.
- Notice that the FreePool is called since there was an allocat call to get memory in the start function
- for the Unload similar "unwind" calls such as
  - free memory
  - Uninstall Protocol Interfaces
  - Disconnect Controller calls are made
  

---
@title[Lab 6: Port the Stop]
<p align="right"><span class="gold" >Lab 6: Port the Stop function</span></p>
<span style="font-size:0.8em" ><b>Locate</b>&nbsp;&nbsp;</span><span style="font-size:0.65em" > "`MyWizardDriverDriverBindingStop()`" function</span><br>
<span style="font-size:0.8em" ><b>Comment out</b>&nbsp;&nbsp;</span><span style="font-size:0.65em" > with "`//`" before the "`return EFI_UNSUPPORTED;`" statement.</span><br>
<span style="font-size:0.8em" ><b>Copy & Paste</b>&nbsp;&nbsp;</span><span style="font-size:0.65em" > the following "`if`"  and "`DEBUG`" statements in place of the "`return EFI_UNSUPPORTED;`" statement.</span>
```C++
	if (DummyBufferfromStart != NULL) {
		FreePool(DummyBufferfromStart);
		DEBUG((EFI_D_INFO, "[MyWizardDriver] Stop, clear buffer\r\n"));
	}

	DEBUG((EFI_D_INFO, "[MyWizardDriver] Stop, EFI_SUCCESS\r\n"));
	return EFI_SUCCESS;
  //  return EFI_UNSUPPORTED;
}

Save & Close  "MyWizardDriverDriver.c"

Note:

  • The code will deallocate the buffer using the FreePool library function.
  • This a duplicate of the check performed in the unload function, in case the stop function was executed prior to unload.
  • Notice that the FreePool is called since there was an allocat call to get memory in the start function
  • for the stop similar "unwind" calls to mimic same functions in the start
    • free memory for Alocate memory
    • Uninstall Protocol Interfaces for Install interfaces

@title[Lab 6 Build and Test Driver]

Lab 6: Build and Test Driver


Build MyWizardDriver – Cd to ~/src/edk2 dir ```shell bash$ build ``` Copy MyWizardDriver.efi to hda-contents ```shell bash$ cd ~/run-ovmf/hda-contents bash$ cp ~/src/edk2/Build/OvmfX64/DEBUG_GCC5/X64/MyWizardDriver.efi . ``` Test by Invoking Qemu ```shell bash$ cd ~/run-ovmf bash$ . RunQemu.sh ```

---?image=/assets/images/slides/Slide25.JPG @title[Lab 6 Build and Test Driver]

Lab 6: Build and Test Driver


Load the UEFI Driver from the shell
    At the Shell prompt, type  `Shell> ` `fs0:`
    Type:  `FS0:\> ` `load MyWizardDriver.efi`

Observe the buffer address is at `0x06808018` as this slide example

Note:

Same as slide

---?image=/assets/images/slides/Slide39.JPG @title[Lab 6 Verify Driver]

Lab 6: Verify Driver


At the Shell prompt, type  `FS0:\> ` `drivers`

Observe the handle is "`A9`" as this slide example
Type:  ` mem 0x06808018`
Observe the buffer was filled with the "0x0042"

Note:

Same as slide

---?image=/assets/images/slides/Slide40.JPG @title[Lab 6 Verify Unload]

Lab 6: Verify Unload


At the Shell prompt, type  `FS0:\> ` `unload a9`

Observe the DEBUG messages from the Unload

Note:

Same as slide

---?image=/assets/images/slides/Slide41.JPG @title[Lab 6 Verify Unload]

Lab 6: Verify Unload


At the Shell prompt, type  `FS0:\> ` `mem 0x06808018 -b`

Observe the buffer is now NOT filled





Exit QEMU

Note:

Same as slide


@title[Additional Porting]

Additional Porting

@snap[north-west span-95 fragment]



 

@box[bg-navy text-white rounded my-box-pad2 ](

Adding strings and forms to setup -(HII)
 

)
@snapend

@snap[north-west span-80 fragment]




 
 

@box[bg-royal text-white rounded my-box-pad2 ](

Publish & consume protocols
 

)
@snapend

@snap[north-west span-70 fragment]







 
 

@box[bg-purple-pp text-white rounded my-box-pad2 ](

Hardware initialization
 

)
@snapend

@snap[south-west span-90] Refer to the UEFI Drivers Writer’s Guide for more tips – Pdf link
@snapend

Note: Use the UEFI Driver Wizard to create a starting point for new drivers on EDK II


@title[Summary]

Summary


  • @fa[certificate gp-bullet-green]  Compile a UEFI driver template created from
            UEFI Driver Wizard

  • @fa[certificate gp-bullet-cyan]  Test driver in QEMU using UEFI Shell 2.0

  • @fa[certificate gp-bullet-yellow]  Port code into the template driver

---?image=assets/images/gitpitch-audience.jpg @title[Questions]
Questions

---?image=assets/images/gitpitch-audience.jpg @title[Logo Slide]


![Logo Slide](/assets/images/TianocoreLogo.png =10x)


@title[Acknowledgements]

Acknowledgements

/**
Redistribution and use in source (original document form) and 'compiled' forms (converted
to PDF, epub, HTML and other formats) with or without modification, are permitted provided
that the following conditions are met:

Redistributions of source code (original document form) must retain the above copyright 
notice, this list of conditions and the following disclaimer as the first lines of this 
file unmodified.

Redistributions in compiled form (transformed to other DTDs, converted to PDF, epub, HTML
and other formats) must reproduce the above copyright notice, this list of conditions and 
the following disclaimer in the documentation and/or other materials provided with the 
distribution.

THIS DOCUMENTATION IS PROVIDED BY TIANOCORE PROJECT "AS IS" AND ANY EXPRESS OR IMPLIED 
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL TIANOCORE PROJECT BE 
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
ARISING IN ANY WAY OUT OF THE USE OF THIS DOCUMENTATION, EVEN IF ADVISED OF THE POSSIBILITY 
OF SUCH DAMAGE.

Copyright (c) 2018, Intel Corporation. All rights reserved.
**/