File: UnitTestBootLibUsbClass.c

package info (click to toggle)
edk2 2025.11-3
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 338,556 kB
  • sloc: ansic: 2,166,376; asm: 270,725; perl: 235,301; python: 149,839; sh: 34,744; cpp: 23,311; makefile: 3,326; pascal: 1,602; xml: 806; lisp: 35; ruby: 16; sed: 6; tcl: 4
file content (130 lines) | stat: -rw-r--r-- 4,105 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
/**
  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", __func__));
    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", __func__));
    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", __func__, Status));
    goto CLEANUP;
  }

  NewOptionValid = TRUE;
  DEBUG ((DEBUG_VERBOSE, "%a: Generic USB Class Device boot option created.\n", __func__));
  Status = EfiBootManagerLoadOptionToVariable (&NewOption);
  if (EFI_ERROR (Status)) {
    DEBUG ((DEBUG_ERROR, "%a: Error Saving boot option NV variable. Status = %r\n", __func__, 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", __func__, Status));

CLEANUP:
  if (Dp != NULL) {
    FreePool (Dp);
  }

  if (DpEnd != NULL) {
    FreePool (DpEnd);
  }

  if (NewOptionValid) {
    EfiBootManagerFreeLoadOption (&NewOption);
  }

  return Status;
}