---?image=assets/images/gitpitch-audience.jpg
@title[UEFI_Driver_Porting 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:
-
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 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]
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
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 - Save and close the file `~src/edk2/OvmfPkg/OvmfPkgX64.dsc`
```
# Add new modules here
MyWizardDriver/MyWizardDriver.inf{
DebugLib|MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.inf
}
```
@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 . ```
``` 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:
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`
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
@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`
- Save and close the file: `~/src/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 }
};
```
@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 shellAt the Shell prompt, type `Shell> ``fs0:`
Type: `FS0:\> ` `load MyWizardDriver.efi`
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
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
@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
@snap[north-west span-20 ]
@fa[star gp-bullet-gold]
@snapend@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/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;` "
- copy and past (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>
<li><span style="font-size:0.8em" ><b>Open</b> </span><span style="font-size:0.7em" > `~/src/edk2/MyWizardDriver/MyWizardDriver.h`</span></li>
<li><span style="font-size:0.8em" ><b>Notice</b> </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> </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> </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> </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> </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> </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
- Create .h file with new `typedef` definition and its own `GUID`
- Include the new .h file in the driver's top .h file
- `EntryPoint()` Init new buffer for NVRam Variable
- `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 ```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> </span><span style="font-size:0.7em" > "`~/src/edk2/MyWizardDriver/MyWizardDriver.c`"</span><br>
<span style="font-size:0.8em" ><b>Copy & Paste</b> </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> </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`
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
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> </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>
<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>
```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`
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`
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`
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`
Exit QEMU
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 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]
---?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) 2018, Intel Corporation. All rights reserved.
**/