Skip to content

Latest commit

 

History

History
1278 lines (982 loc) · 47.4 KB

PITCHME.md

File metadata and controls

1278 lines (982 loc) · 47.4 KB

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




UEFI & EDK II Training

How to Write a UEFI Driver Lab - Windows


See also LabGuide.md for Copy&Paste examples in labs
tianocore.org

Note: PITCHME.md for UEFI / EDK II Training UEFI Driver Porting Lab - Windows

Copyright (c) 2020, 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 w/ Windows emulation using UEFI Shell 2.0

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

@color[yellow]( Note: Since this is a lab, to follow examples for copy & paste, use the following Markdown link ) LabGuide.md

---?image=/assets/images/slides/Slide_LabSec.JPG @title[Lab1 UEFI Driver Template Lab]

Lab 1: UEFI Driver Template


Use this lab, if you’re not able to create a UEFI Driver Template using the UEFI Driver Wizard.
Skip if LAB 1 UEFI Driver Wizard completed successfully
 

---?image=/assets/images/slides/Slide4.JPG @title[Lab 1: Get UEFI Driver Template]

@size[1.1em](Lab 1: Get UEFI Driver Template )

If UEFI Driver Wizard does not work:

  • 1.   Copy the directory "`UefiDriverTemplate`" from
         `. . ./FW/LabSampleCode/ to C:/FW/edk2-ws/edk2`
  • 2.   Rename Directory UefiDriverTemplate to MyWizardDriver

Note: This UEFI Driver example was created from the UEFI Driver Wizard Lab Review UEFI Driver Wizard Lab for which protocols are getting produced and which protocols are being consumed.

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

@size[1.1em](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 EmulatorPkg project.
Build the UEFI Driver from the Driver Wizard
 

@title[Compile a UEFI Driver?]

@size[1.1em](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 EmulatorPkg Labs
  • Open `C:/FW/edk2-ws/edk2/EmulatorPkg/EmulatorPkg.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
  • Save and close the file
        `C:/FW/edk2-ws/edk2/EmulatorPkg/EmulatorPkg.dsc`

@title[Lab 2 Build and Test Driver]

Lab 2: Build and Test Driver

Open a VS Command Prompt and type: `cd C:/FW/edk2-ws/edk2` then
  C:/FW/edk2-ws/edk2> edksetup

Build `MyWizardDriver`

  C:/FW/edk2-ws/edk2> Build
  C:/FW/edk2-ws/edk2> Build Run

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

Build ERRORS: Copy the solution files from `~/FW/LabSampleCode/LabSolutions/LessonC.1` to `C:/FW/edk2-ws/edk2/MyWizardDriver`

Note: continue to next slide

---?image=/assets/images/slides/Slide9.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/Slide10.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/Slide11.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 - right
Type:  `drivers` again

Notice results of `unload` command

Exit, type `FS0:/ >` `Reset`

Note:

END of Lab 2

---?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   `C:/FW/edk2-ws/edk2/MyWizardDriver/ComponentName.c`
  • Change   the string returned by the driver from `MyWizardDriver` to:
        @size[.8em](` 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:
      `C:/FW/edk2-ws/edk2/MyWizardDriver/ComponentName.c`

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

Lab 3: Build and Test Driver


Build the MyWizardDriver

  C:/FW/edk2-ws/edk2> Build
  C:/FW/edk2-ws/edk2> Build Run

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, type `FS0:/ >` `Reset`

Note: Lab 3 finished

---?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/Slide16.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-west span-20 ]







@fa[star gp-bullet-ltgreen]

@snapend

@snap[north-west span-20 ]











@fa[star gp-bullet-gold]

@snapend

@snap[north-east span-85 ]



@coloryellow
Determines if a driver supports a controller

@snapend

@snap[north-east span-85 ]







@coloryellow
Starts a driver on a controller & Installs Protocols

@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/Slide17.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   `C:/FW/edk2-ws/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 paste (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 style="list-style-type:disc; line-height:0.7;">
   <li><span style="font-size:0.68em" ><b>Open</b>&nbsp;&nbsp;</span><span style="font-size:0.7em" > `C:/FW/edk2/MyWizardDriver/MyWizardDriver.h`</span></li>
   <li><span style="font-size:0.68em" ><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>

```C++
// Produced Protocols
//
#include <Protocol/SerialIo.h>
  • Review   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
  • // 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>

    Note:


    @title[Lab 4: Update the Start ]

    Lab 4: Update the `Start()`

    • Copy & Paste   the following in `MyWizardDriver.c` after the
      @size[.8em]("`#include "MyWizardDriver.h`") line:
    • #define  DUMMY_SIZE 100*16		// Dummy buffer
      CHAR16	*DummyBufferfromStart = NULL;
      <li><span style="font-size:0.68em" ><b>Locate</b>&nbsp;&nbsp;</span><span style="font-size:0.68em" > ` MyWizardDriverDriverBindingStart()`,  the start function for this driver and comment out the "`//`" in the line <br><span style="background-color: #101010">"`return EFI_UNSUPPORTED;` "</span></span></li>
      
    EFI_STATUS
    EFIAPI
    MyWizardDriverDriverBindingStart (
      IN EFI_DRIVER_BINDING_PROTOCOL  *This,
      IN EFI_HANDLE                   ControllerHandle,
      IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL
      )
    {
      // return EFI_UNSUPPORTED;
    }

    Note:


    @title[Lab 4: Update Start 02 ]

    Lab 4: Update Start Add Code

    Copy & Paste   the following code for the start function ` MyWizardDriverDriverBindingStart()`:

    ```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;
    
    <ul style="list-style-type:disc; line-height:0.7;">
     <li><span style="font-size:0.65em" >Notice the Library calls to `AllocateZeroPool()` and `SetMem16()`</span></li>
     <li><span style="font-size:0.65em" >The `Start()` function is where there would be calls to<br> "`gBS->InstallMultipleProtocolInterfaces()`"</span></li>
    </ul>
    
    
    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/Slide24.JPG
    @title[Lab 4: Debugging before Testing the Driver ]
    <p align="right"><span class="gold" >Lab 4: Debugging before Testing the Driver</span></p>
    <br>
    <span style="font-size:0.8em" >UEFI drivers can use the EDK II debug library </span><br>
    
    <div class="left1">
    <ul style="list-style-type:none; line-height:0.7;">
      <li>@fa[book gp-bullet-gold]<span style="font-size:0.6em" >&nbsp;&nbsp;`DEBUG( )`	 include - `[DebugLib.h]`</span></li><br>
      <li><span style="font-size:0.6em" >`DEBUG()` Macro statements can show status progress interest points throughout  the driver code</span></li>
    </ul>
    </div>
    <div class="right1">
    <span style="font-size:0.8em" >&nbsp;</span>
    </div>
    
    
    ---
    @title[Lab 4: Add Debug statements supported ]
    <p align="right"><span class="gold" >Lab 4: Add Debug Statements `Supported()`</span></p>
    <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> macros for the supported function:</span>
    ```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 ]

    Lab 4: Add Debug Statements `Start()`


    Copy & Paste   the following `DEBUG` macro for the Start function just before the @size[.8em](` return EFI_SUCCESS; `) statement ```C++ DEBUG ((EFI_D_INFO, "\r\n***\r\n[MyWizardDriver] Buffer 0x%p\r\n", DummyBufferfromStart)); return EFI_SUCCESS; ``` Note: This debug macro displays the memory address of the allocated buffer on the debug console

    Save   C:/FW/edk2-ws/edk2/MyWizardDriver/MyWizardDriver.c

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

    Lab 4: Build and Test Driver


    Build the MyWizardDriver

    ```shell C:/FW/edk2-ws/edk2> Build C:/FW/edk2-ws/edk2> Build Run ```

    Load the UEFI Driver from the shell

      @size[.8em](`Shell> `)@size[.8em](` fs0:`)
      @size[.8em](`FS0:\> `)@size[.8em](`load MyWizardDriver.efi`)

    Note:

    Same as slide

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

    Lab 4: Build and Test Driver

    @snap[north-west span-60 ]


    • Check the VS 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, type `FS0:/ >` `Reset`

    @snap[south-east span-55]

    Note: use the right-side scroll bar with mouse to scroll back to see the “Supported SUCCESS”
     

    @snapend

    Note: Finished Lab 4

    ---?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 in the Start 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. 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. `Supported()` make a call to a new function to set/get the new NVRam Variable
    4. 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" > "`C:/FW/edk2-ws/edk2/MyWizardDriver/MyWizardDriver.c`"</span><br>
    <p style="line-height:80%"><span style="font-size:0.68em" ><b>Copy & Paste</b>&nbsp;&nbsp;</span><span style="font-size:0.65em" > the following  4 lines after the "`#include MyWizardDriver.h`" statement: </span></p>
    ```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 
    

    Note: Same as slide


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

    Lab 5: Update MyWizardDriver.c


    Locate   "`MyWizardDriverDriverBindingStart ()`" function
    Copy & Paste   at the beginning of the start function to declare a local variable ```C++ EFI_STATUS Status; // Declare a local variable Status
    <p style="line-height:70%"><span style="font-size:0.8em" ><b>Copy & Paste</b>&nbsp;&nbsp;</span><span style="font-size:0.65em" > the 5 lines: 1) new call to "`CreateNVVariable();`" 
      2-6) `if` statement with DEBUG just befor the linke  "`return EFI_SUCCESS`"  as below: </span></p>
    
    ```C++
    		Status = CreateNVVariable();
    		if (EFI_ERROR(Status)) {
    		DEBUG((EFI_D_ERROR, "[MyWizardDriver] NV Variable already created \r\n"));
    	}
    	else {
    		DEBUG((EFI_D_ERROR, "[MyWizardDriver] Created NV Variable in the Start \r\n"));
            }
    
    
    	return EFI_SUCCESS;
    

    Note:

    copy paste


    @title[Lab 5: Add new function ]

    Lab 5: Update MyWizardDriver.c

    Copy & Paste   the new function before the call to "`MyWizardDriverDriverEntryPoint()`" ```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]
    <p align="right"><span class="gold" >Lab 5: Update MyWizardDriver.h</span></p>
    <span style="font-size:0.8em" ><b>Open</b>&nbsp;&nbsp;</span><span style="font-size:0.7em" > "`C:/FW/edk2-ws/edk2/MyWizardDriver/MyWizardDriver.h`"</span><br>
    <p style="line-height:70%"><span style="font-size:0.8em" ><b>Copy & Paste</b>&nbsp;&nbsp;</span><span style="font-size:0.65em" > the following "#include" after the list of library include statements: </span></p>
    ```C++
    // Libraries
    // . . .
    #include <Library/UefiRuntimeServicesTableLib.h>
    

    Copy & Paste   the following "#include" after the list of protocol include statements:

    ```C++ // Produced Protocols // . . . #include "MyWizardDriverNVDataStruc.h" ``` Save   "`C:/FW/edk2-ws/edk2/MyWizardDriver/MyWizardDriver.h`"
    Save   "`C:/FW/edk2-ws/edk2/MyWizardDriver/MyWizardDriver.c`"

    Note:

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

    Lab 5: Build and Test Driver

    Build the MyWizardDriver

      C:/FW/edk2-ws/edk2> Build
      C:/FW/edk2-ws/edk2> Build Run
    

    Load the UEFI Driver
       Shell> fs0:
       FS0:\>  load MyWizardDriver.efi

    Observe the Buffer address returned by the debug statement in the VS Command window

    Note:

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

    Lab 5: Verify Driver


    Use the Buffer address pointer in the previous slide then use the "`mem`" command
    At the Shell prompt, type   `FS0:\> ` `mem 0x0587f010`
    Observe the Buffer is filled with the letter "B" or 0x0042





    Note:

    Same as slide

    ---?image=/assets/images/slides/Slide38.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, type FS0:/ > Reset

    Note:

    End of Lab 5

    ---?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   "`C:/FW/edk2-ws/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>
    <p style="line-height:80%"><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></p>
    ```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

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

    Lab 6: Build and Test Driver

    Build the MyWizardDriver

      C:/FW/edk2-ws/edk2> Build
      C:/FW/edk2-ws/edk2> Build Run

    Load the UEFI Driver

       `Shell> ``fs0:`
       `FS0:\> ` `load MyWizardDriver.efi`


    Observe the Buffer address is at `0x0587f010` as this slide example

    Note:

    Same as slide

    ---?image=/assets/images/slides/Slide43.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 0x0587f010`
    Observe the buffer was filled with the "0x0042"

    Note:

    Same as slide

    ---?image=/assets/images/slides/Slide44.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

    Type `Drivers` again to verify

    Note:

    Same as slide

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

    Lab 6: Verify Unload


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

    Observe the buffer is now NOT filled






    Exit, type `FS0:/ >` `Reset`

    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 w/ Windows emulation 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) 2020, Intel Corporation. All rights reserved.
    **/