123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130 |
- /**
- Implement UnitTestBootLib using USB Class Boot option. This should be
- industry standard and should work on all platforms
- Copyright (c) Microsoft Corporation.<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
- **/
- #include <PiDxe.h>
- #include <Library/DebugLib.h>
- #include <Library/UefiRuntimeServicesTableLib.h>
- #include <Library/UefiBootManagerLib.h>
- #include <Library/DevicePathLib.h>
- #include <Protocol/DevicePath.h>
- #include <Library/MemoryAllocationLib.h>
- /**
- Set the boot manager to boot from a specific device on the next boot. This
- should be set only for the next boot and shouldn't require any manual clean up
- @retval EFI_SUCCESS Boot device for next boot was set.
- @retval EFI_UNSUPPORTED Setting the boot device for the next boot is not
- supportted.
- @retval Other Boot device for next boot can not be set.
- **/
- EFI_STATUS
- EFIAPI
- SetBootNextDevice (
- VOID
- )
- {
- EFI_STATUS Status;
- EFI_BOOT_MANAGER_LOAD_OPTION NewOption;
- UINT32 Attributes;
- UINT8 *OptionalData;
- UINT32 OptionalDataSize;
- UINT16 BootNextValue;
- USB_CLASS_DEVICE_PATH UsbDp;
- EFI_DEVICE_PATH_PROTOCOL *DpEnd;
- EFI_DEVICE_PATH_PROTOCOL *Dp;
- BOOLEAN NewOptionValid;
- OptionalData = NULL;
- OptionalDataSize = 0;
- BootNextValue = 0xABCD; // this should be a safe number...
- DpEnd = NULL;
- Dp = NULL;
- NewOptionValid = FALSE;
- UsbDp.Header.Length[0] = (UINT8)(sizeof (USB_CLASS_DEVICE_PATH) & 0xff);
- UsbDp.Header.Length[1] = (UINT8)(sizeof (USB_CLASS_DEVICE_PATH) >> 8);
- UsbDp.Header.Type = MESSAGING_DEVICE_PATH;
- UsbDp.Header.SubType = MSG_USB_CLASS_DP;
- UsbDp.VendorId = 0xFFFF;
- UsbDp.ProductId = 0xFFFF;
- UsbDp.DeviceClass = 0xFF;
- UsbDp.DeviceSubClass = 0xFF;
- UsbDp.DeviceProtocol = 0xFF;
- Attributes = LOAD_OPTION_ACTIVE;
- DpEnd = AppendDevicePathNode (NULL, NULL);
- if (DpEnd == NULL) {
- DEBUG ((DEBUG_ERROR, "%a: Unable to create device path. DpEnd is NULL.\n", __FUNCTION__));
- Status = EFI_OUT_OF_RESOURCES;
- goto CLEANUP;
- }
- // @MRT --- Is this memory leak because we lose the old Dp memory
- Dp = AppendDevicePathNode (
- DpEnd,
- (EFI_DEVICE_PATH_PROTOCOL *)&UsbDp
- );
- if (Dp == NULL) {
- DEBUG ((DEBUG_ERROR, "%a: Unable to create device path. Dp is NULL.\n", __FUNCTION__));
- Status = EFI_OUT_OF_RESOURCES;
- goto CLEANUP;
- }
- Status = EfiBootManagerInitializeLoadOption (
- &NewOption,
- (UINTN)BootNextValue,
- LoadOptionTypeBoot,
- Attributes,
- L"Generic USB Class Device",
- Dp,
- OptionalData,
- OptionalDataSize
- );
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "%a: Error creating load option. Status = %r\n", __FUNCTION__, Status));
- goto CLEANUP;
- }
- NewOptionValid = TRUE;
- DEBUG ((DEBUG_VERBOSE, "%a: Generic USB Class Device boot option created.\n", __FUNCTION__));
- Status = EfiBootManagerLoadOptionToVariable (&NewOption);
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "%a: Error Saving boot option NV variable. Status = %r\n", __FUNCTION__, Status));
- goto CLEANUP;
- }
- //
- // Set Boot Next
- //
- Status = gRT->SetVariable (
- L"BootNext",
- &gEfiGlobalVariableGuid,
- (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE),
- sizeof (BootNextValue),
- &(BootNextValue)
- );
- DEBUG ((DEBUG_VERBOSE, "%a - Set BootNext Status (%r)\n", __FUNCTION__, Status));
- CLEANUP:
- if (Dp != NULL) {
- FreePool (Dp);
- }
- if (DpEnd != NULL) {
- FreePool (DpEnd);
- }
- if (NewOptionValid) {
- EfiBootManagerFreeLoadOption (&NewOption);
- }
- return Status;
- }
|