---?image=assets/images/gitpitch-audience.jpg
@title[UEFI_Driver_Porting Lab]
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:
-
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.
@title[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
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)
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 - Save and close the file
`C:/FW/edk2-ws/edk2/EmulatorPkg/EmulatorPkg.dsc`
# Add new modules here
MyWizardDriver/MyWizardDriver.inf
@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`
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
@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 `) - Save and close the file:
`C:/FW/edk2-ws/edk2/MyWizardDriver/ComponentName.c`
/// Table of driver names
///
GLOBAL_REMOVE_IF_UNREFERENCED
EFI_UNICODE_STRING_TABLE mMyWizardDriverDriverNameTable[] = {
{ "eng;en", (CHAR16 *)L"UEFI Sample Driver" },
{ NULL, NULL }
};
---?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`
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
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
@snap[north-east span-85 ]
@coloryellow
Starts a driver on a controller & Installs Protocols
@snap[north-east span-85 ]
@coloryellow
Stops a driver from managing a controller
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
- 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;` " - copy and paste (next slide)
EFI_STATUS
EFIAPI
MyWizardDriverDriverBindingSupported (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
)
{
// return EFI_UNSUPPORTED;
}
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> </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> </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>
// 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> </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" > `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" > </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> </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”
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
- Create .h file with new `typedef` definition and its own `GUID`
- Include the new .h file in the driver's top .h file
- `Supported()` make a call to a new function to set/get the new NVRam Variable
- 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
#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> </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> </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> </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> </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> </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
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> </span><span style="font-size:0.65em" > "`MyWizardDriverDriverBindingStop()`" function</span><br>
<span style="font-size:0.8em" ><b>Comment out</b> </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> </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`
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`
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`
Exit, type `FS0:/ >` `Reset`
Note:
Same as slide
@title[Additional Porting]
Additional Porting
@snap[north-west span-95 fragment]
Adding strings and forms to setup -(HII)
@snapend
@snap[north-west span-80 fragment]
Publish & consume protocols
@snapend
@snap[north-west span-70 fragment]
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]
- @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]
---?image=assets/images/gitpitch-audience.jpg
@title[Logo Slide]
![Logo Slide](/assets/images/TianocoreLogo.png =10x)
@title[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.
**/