1 | /** @file
|
---|
2 | Library functions which relate with boot option description.
|
---|
3 |
|
---|
4 | Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
|
---|
5 | (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
|
---|
6 | SPDX-License-Identifier: BSD-2-Clause-Patent
|
---|
7 |
|
---|
8 | **/
|
---|
9 |
|
---|
10 | #include "InternalBm.h"
|
---|
11 |
|
---|
12 | #define VENDOR_IDENTIFICATION_OFFSET 3
|
---|
13 | #define VENDOR_IDENTIFICATION_LENGTH 8
|
---|
14 | #define PRODUCT_IDENTIFICATION_OFFSET 11
|
---|
15 | #define PRODUCT_IDENTIFICATION_LENGTH 16
|
---|
16 |
|
---|
17 | CONST UINT16 mBmUsbLangId = 0x0409; // English
|
---|
18 | CHAR16 mBmUefiPrefix[] = L"UEFI ";
|
---|
19 |
|
---|
20 | CHAR16 mBootDescGenericManufacturer[] = L"Generic";
|
---|
21 | CHAR16 mBootDescSd[] = L"SD Device";
|
---|
22 | CHAR16 mBootDescEmmc[] = L"eMMC Device";
|
---|
23 | CHAR16 mBootDescEmmcUserData[] = L"eMMC User Data";
|
---|
24 | CHAR16 mBootDescEmmcBoot1[] = L"eMMC Boot 1";
|
---|
25 | CHAR16 mBootDescEmmcBoot2[] = L"eMMC Boot 2";
|
---|
26 | CHAR16 mBootDescEmmcGp1[] = L"eMMC GP 1";
|
---|
27 | CHAR16 mBootDescEmmcGp2[] = L"eMMC GP 2";
|
---|
28 | CHAR16 mBootDescEmmcGp3[] = L"eMMC GP 3";
|
---|
29 | CHAR16 mBootDescEmmcGp4[] = L"eMMC GP 4";
|
---|
30 |
|
---|
31 | typedef struct {
|
---|
32 | UINT8 Id;
|
---|
33 | CHAR16 *Name;
|
---|
34 | } BM_SDMMC_MANUFACTURER;
|
---|
35 |
|
---|
36 | BM_SDMMC_MANUFACTURER mSdManufacturers[] = {
|
---|
37 | { 0x01, L"Panasonic" },
|
---|
38 | { 0x02, L"Toshiba/Kingston/Viking" },
|
---|
39 | { 0x03, L"SanDisk" },
|
---|
40 | { 0x08, L"Silicon Power" },
|
---|
41 | { 0x18, L"Infineon" },
|
---|
42 | { 0x1b, L"Transcend/Samsung" },
|
---|
43 | { 0x1c, L"Transcend" },
|
---|
44 | { 0x1d, L"Corsair/AData" },
|
---|
45 | { 0x1e, L"Transcend" },
|
---|
46 | { 0x1f, L"Kingston" },
|
---|
47 | { 0x27, L"Delkin/Phison" },
|
---|
48 | { 0x28, L"Lexar" },
|
---|
49 | { 0x30, L"SanDisk" },
|
---|
50 | { 0x31, L"Silicon Power" },
|
---|
51 | { 0x33, L"STMicroelectronics" },
|
---|
52 | { 0x41, L"Kingston" },
|
---|
53 | { 0x6f, L"STMicroelectronics" },
|
---|
54 | { 0x74, L"Transcend" },
|
---|
55 | { 0x76, L"Patriot" },
|
---|
56 | { 0x82, L"Gobe/Sony" },
|
---|
57 | { 0x9c, L"Angelbird/Hoodman" },
|
---|
58 | };
|
---|
59 |
|
---|
60 | BM_SDMMC_MANUFACTURER mMmcManufacturers[] = {
|
---|
61 | { 0x00, L"SanDisk" },
|
---|
62 | { 0x02, L"Kingston/SanDisk" },
|
---|
63 | { 0x03, L"Toshiba" },
|
---|
64 | { 0x11, L"Toshiba" },
|
---|
65 | { 0x13, L"Micron" },
|
---|
66 | { 0x15, L"Samsung" },
|
---|
67 | { 0x37, L"KingMax" },
|
---|
68 | { 0x44, L"ATP" },
|
---|
69 | { 0x45, L"SanDisk" },
|
---|
70 | { 0x2c, L"Kingston" },
|
---|
71 | { 0x70, L"Kingston" },
|
---|
72 | { 0x88, L"Foresee" },
|
---|
73 | { 0x9b, L"YMTC" },
|
---|
74 | { 0xd6, L"Foresee" },
|
---|
75 | { 0xfe, L"Micron" },
|
---|
76 | };
|
---|
77 |
|
---|
78 | LIST_ENTRY mPlatformBootDescriptionHandlers = INITIALIZE_LIST_HEAD_VARIABLE (mPlatformBootDescriptionHandlers);
|
---|
79 |
|
---|
80 | /**
|
---|
81 | For a bootable Device path, return its boot type.
|
---|
82 |
|
---|
83 | @param DevicePath The bootable device Path to check
|
---|
84 |
|
---|
85 | @retval AcpiFloppyBoot If given device path contains ACPI_DEVICE_PATH type device path node
|
---|
86 | which HID is floppy device.
|
---|
87 | @retval MessageAtapiBoot If given device path contains MESSAGING_DEVICE_PATH type device path node
|
---|
88 | and its last device path node's subtype is MSG_ATAPI_DP.
|
---|
89 | @retval MessageSataBoot If given device path contains MESSAGING_DEVICE_PATH type device path node
|
---|
90 | and its last device path node's subtype is MSG_SATA_DP.
|
---|
91 | @retval MessageScsiBoot If given device path contains MESSAGING_DEVICE_PATH type device path node
|
---|
92 | and its last device path node's subtype is MSG_SCSI_DP.
|
---|
93 | @retval MessageUsbBoot If given device path contains MESSAGING_DEVICE_PATH type device path node
|
---|
94 | and its last device path node's subtype is MSG_USB_DP.
|
---|
95 | @retval BmMiscBoot If tiven device path doesn't match the above condition.
|
---|
96 |
|
---|
97 | **/
|
---|
98 | BM_BOOT_TYPE
|
---|
99 | BmDevicePathType (
|
---|
100 | IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
|
---|
101 | )
|
---|
102 | {
|
---|
103 | EFI_DEVICE_PATH_PROTOCOL *Node;
|
---|
104 | EFI_DEVICE_PATH_PROTOCOL *NextNode;
|
---|
105 |
|
---|
106 | ASSERT (DevicePath != NULL);
|
---|
107 |
|
---|
108 | for (Node = DevicePath; !IsDevicePathEndType (Node); Node = NextDevicePathNode (Node)) {
|
---|
109 | switch (DevicePathType (Node)) {
|
---|
110 | case ACPI_DEVICE_PATH:
|
---|
111 | if (EISA_ID_TO_NUM (((ACPI_HID_DEVICE_PATH *)Node)->HID) == 0x0604) {
|
---|
112 | return BmAcpiFloppyBoot;
|
---|
113 | }
|
---|
114 |
|
---|
115 | break;
|
---|
116 |
|
---|
117 | case HARDWARE_DEVICE_PATH:
|
---|
118 | if (DevicePathSubType (Node) == HW_CONTROLLER_DP) {
|
---|
119 | return BmHardwareDeviceBoot;
|
---|
120 | }
|
---|
121 |
|
---|
122 | break;
|
---|
123 |
|
---|
124 | case MESSAGING_DEVICE_PATH:
|
---|
125 | //
|
---|
126 | // Skip LUN device node
|
---|
127 | //
|
---|
128 | NextNode = Node;
|
---|
129 | do {
|
---|
130 | NextNode = NextDevicePathNode (NextNode);
|
---|
131 | } while (
|
---|
132 | (DevicePathType (NextNode) == MESSAGING_DEVICE_PATH) &&
|
---|
133 | (DevicePathSubType (NextNode) == MSG_DEVICE_LOGICAL_UNIT_DP)
|
---|
134 | );
|
---|
135 |
|
---|
136 | //
|
---|
137 | // If the device path not only point to driver device, it is not a messaging device path,
|
---|
138 | //
|
---|
139 | if (!IsDevicePathEndType (NextNode)) {
|
---|
140 | continue;
|
---|
141 | }
|
---|
142 |
|
---|
143 | switch (DevicePathSubType (Node)) {
|
---|
144 | case MSG_ATAPI_DP:
|
---|
145 | return BmMessageAtapiBoot;
|
---|
146 | break;
|
---|
147 |
|
---|
148 | case MSG_SATA_DP:
|
---|
149 | return BmMessageSataBoot;
|
---|
150 | break;
|
---|
151 |
|
---|
152 | case MSG_USB_DP:
|
---|
153 | return BmMessageUsbBoot;
|
---|
154 | break;
|
---|
155 |
|
---|
156 | case MSG_SCSI_DP:
|
---|
157 | return BmMessageScsiBoot;
|
---|
158 | break;
|
---|
159 | }
|
---|
160 | }
|
---|
161 | }
|
---|
162 |
|
---|
163 | return BmMiscBoot;
|
---|
164 | }
|
---|
165 |
|
---|
166 | /**
|
---|
167 | Eliminate the extra spaces in the Str to one space.
|
---|
168 |
|
---|
169 | @param Str Input string info.
|
---|
170 | **/
|
---|
171 | VOID
|
---|
172 | BmEliminateExtraSpaces (
|
---|
173 | IN CHAR16 *Str
|
---|
174 | )
|
---|
175 | {
|
---|
176 | UINTN Index;
|
---|
177 | UINTN ActualIndex;
|
---|
178 |
|
---|
179 | for (Index = 0, ActualIndex = 0; Str[Index] != L'\0'; Index++) {
|
---|
180 | if ((Str[Index] != L' ') || ((ActualIndex > 0) && (Str[ActualIndex - 1] != L' '))) {
|
---|
181 | Str[ActualIndex++] = Str[Index];
|
---|
182 | }
|
---|
183 | }
|
---|
184 |
|
---|
185 | Str[ActualIndex] = L'\0';
|
---|
186 | }
|
---|
187 |
|
---|
188 | /**
|
---|
189 | Swap a byte array.
|
---|
190 |
|
---|
191 | @param Source Input byte array.
|
---|
192 | @param Length The size of Source in bytes.
|
---|
193 | **/
|
---|
194 | VOID
|
---|
195 | BmSwapBytes (
|
---|
196 | IN UINT8 *Source,
|
---|
197 | IN UINTN Length
|
---|
198 | )
|
---|
199 | {
|
---|
200 | UINTN Index;
|
---|
201 | UINT8 Temp;
|
---|
202 | UINTN Count;
|
---|
203 |
|
---|
204 | Count = Length / 2;
|
---|
205 | for (Index = 0; Index < Count; ++Index) {
|
---|
206 | Temp = Source[Index];
|
---|
207 | Source[Index] = Source[Length - 1 - Index];
|
---|
208 | Source[Length - 1 - Index] = Temp;
|
---|
209 | }
|
---|
210 | }
|
---|
211 |
|
---|
212 | /**
|
---|
213 | Get the SD/MMC manufacturer name from an ID.
|
---|
214 |
|
---|
215 | @param Id Manufacturer ID.
|
---|
216 | @param IsMmc Boolean indicating whether the ID is for SD or eMMC.
|
---|
217 |
|
---|
218 | @return The manufacturer string.
|
---|
219 | **/
|
---|
220 | CHAR16 *
|
---|
221 | BmGetSdMmcManufacturerName (
|
---|
222 | IN UINT8 Id,
|
---|
223 | IN BOOLEAN IsMmc
|
---|
224 | )
|
---|
225 | {
|
---|
226 | BM_SDMMC_MANUFACTURER *List;
|
---|
227 | UINT8 Count;
|
---|
228 | UINTN Index;
|
---|
229 |
|
---|
230 | List = IsMmc ? mMmcManufacturers : mSdManufacturers;
|
---|
231 | Count = IsMmc ? ARRAY_SIZE (mMmcManufacturers)
|
---|
232 | : ARRAY_SIZE (mSdManufacturers);
|
---|
233 |
|
---|
234 | for (Index = 0; Index < Count; ++Index) {
|
---|
235 | if (List[Index].Id == Id) {
|
---|
236 | return List[Index].Name;
|
---|
237 | }
|
---|
238 | }
|
---|
239 |
|
---|
240 | return mBootDescGenericManufacturer;
|
---|
241 | }
|
---|
242 |
|
---|
243 | /**
|
---|
244 | Get the eMMC partition type from a controller path.
|
---|
245 |
|
---|
246 | @param DevicePath Pointer to a CONTROLLER_DEVICE_PATH.
|
---|
247 |
|
---|
248 | @return The description string.
|
---|
249 | **/
|
---|
250 | CHAR16 *
|
---|
251 | BmGetEmmcTypeDescription (
|
---|
252 | CONTROLLER_DEVICE_PATH *DevicePath
|
---|
253 | )
|
---|
254 | {
|
---|
255 | switch (DevicePath->ControllerNumber) {
|
---|
256 | case EmmcPartitionUserData:
|
---|
257 | return mBootDescEmmcUserData;
|
---|
258 | case EmmcPartitionBoot1:
|
---|
259 | return mBootDescEmmcBoot1;
|
---|
260 | case EmmcPartitionBoot2:
|
---|
261 | return mBootDescEmmcBoot2;
|
---|
262 | case EmmcPartitionGP1:
|
---|
263 | return mBootDescEmmcGp1;
|
---|
264 | case EmmcPartitionGP2:
|
---|
265 | return mBootDescEmmcGp2;
|
---|
266 | case EmmcPartitionGP3:
|
---|
267 | return mBootDescEmmcGp3;
|
---|
268 | case EmmcPartitionGP4:
|
---|
269 | return mBootDescEmmcGp4;
|
---|
270 | default:
|
---|
271 | break;
|
---|
272 | }
|
---|
273 |
|
---|
274 | return mBootDescEmmc;
|
---|
275 | }
|
---|
276 |
|
---|
277 | /**
|
---|
278 | Get an SD/MMC boot description.
|
---|
279 |
|
---|
280 | @param ManufacturerName Manufacturer name string.
|
---|
281 | @param ProductName Product name from CID.
|
---|
282 | @param ProductNameLength Length of ProductName.
|
---|
283 | @param SerialNumber Serial number from CID.
|
---|
284 | @param DeviceType Device type string (e.g. SD or an eMMC partition).
|
---|
285 |
|
---|
286 | @return The description string.
|
---|
287 | **/
|
---|
288 | CHAR16 *
|
---|
289 | BmGetSdMmcDescription (
|
---|
290 | IN CHAR16 *ManufacturerName,
|
---|
291 | IN UINT8 *ProductName,
|
---|
292 | IN UINT8 ProductNameLength,
|
---|
293 | IN UINT8 SerialNumber[4],
|
---|
294 | IN CHAR16 *DeviceType
|
---|
295 | )
|
---|
296 | {
|
---|
297 | CHAR16 *Desc;
|
---|
298 | UINTN DescSize;
|
---|
299 |
|
---|
300 | DescSize = StrSize (ManufacturerName) - sizeof (CHAR16) // "Samsung"
|
---|
301 | + sizeof (CHAR16) // " "
|
---|
302 | + ProductNameLength * sizeof (CHAR16) // "BJTD4R"
|
---|
303 | + sizeof (CHAR16) // " "
|
---|
304 | + sizeof (UINT32) * 2 * sizeof (CHAR16) // "00000000"
|
---|
305 | + sizeof (CHAR16) // " "
|
---|
306 | + StrSize (DeviceType); // "eMMC User Data\0"
|
---|
307 |
|
---|
308 | Desc = AllocateZeroPool (DescSize);
|
---|
309 | if (Desc == NULL) {
|
---|
310 | return NULL;
|
---|
311 | }
|
---|
312 |
|
---|
313 | BmSwapBytes (ProductName, ProductNameLength);
|
---|
314 |
|
---|
315 | UnicodeSPrint (
|
---|
316 | Desc,
|
---|
317 | DescSize,
|
---|
318 | L"%s %.*a %02x%02x%02x%02x %s",
|
---|
319 | ManufacturerName,
|
---|
320 | ProductNameLength,
|
---|
321 | ProductName,
|
---|
322 | SerialNumber[0],
|
---|
323 | SerialNumber[1],
|
---|
324 | SerialNumber[2],
|
---|
325 | SerialNumber[3],
|
---|
326 | DeviceType
|
---|
327 | );
|
---|
328 |
|
---|
329 | return Desc;
|
---|
330 | }
|
---|
331 |
|
---|
332 | /**
|
---|
333 | Try to get the controller's ATA/ATAPI description.
|
---|
334 |
|
---|
335 | @param Handle Controller handle.
|
---|
336 |
|
---|
337 | @return The description string.
|
---|
338 | **/
|
---|
339 | CHAR16 *
|
---|
340 | BmGetDescriptionFromDiskInfo (
|
---|
341 | IN EFI_HANDLE Handle
|
---|
342 | )
|
---|
343 | {
|
---|
344 | UINTN Index;
|
---|
345 | EFI_STATUS Status;
|
---|
346 | EFI_DISK_INFO_PROTOCOL *DiskInfo;
|
---|
347 | UINT32 BufferSize;
|
---|
348 | EFI_ATAPI_IDENTIFY_DATA IdentifyData;
|
---|
349 | EFI_SCSI_INQUIRY_DATA InquiryData;
|
---|
350 | SD_CID SdCid;
|
---|
351 | EMMC_CID EmmcCid;
|
---|
352 | CHAR16 *Description;
|
---|
353 | UINTN Length;
|
---|
354 | CONST UINTN ModelNameLength = 40;
|
---|
355 | CONST UINTN SerialNumberLength = 20;
|
---|
356 | CHAR8 *StrPtr;
|
---|
357 | UINT8 Temp;
|
---|
358 | EFI_DEVICE_PATH_PROTOCOL *DevicePath;
|
---|
359 |
|
---|
360 | Description = NULL;
|
---|
361 |
|
---|
362 | Status = gBS->HandleProtocol (
|
---|
363 | Handle,
|
---|
364 | &gEfiDiskInfoProtocolGuid,
|
---|
365 | (VOID **)&DiskInfo
|
---|
366 | );
|
---|
367 | if (EFI_ERROR (Status)) {
|
---|
368 | return NULL;
|
---|
369 | }
|
---|
370 |
|
---|
371 | if (CompareGuid (&DiskInfo->Interface, &gEfiDiskInfoAhciInterfaceGuid) ||
|
---|
372 | CompareGuid (&DiskInfo->Interface, &gEfiDiskInfoIdeInterfaceGuid))
|
---|
373 | {
|
---|
374 | BufferSize = sizeof (EFI_ATAPI_IDENTIFY_DATA);
|
---|
375 | Status = DiskInfo->Identify (
|
---|
376 | DiskInfo,
|
---|
377 | &IdentifyData,
|
---|
378 | &BufferSize
|
---|
379 | );
|
---|
380 | if (!EFI_ERROR (Status)) {
|
---|
381 | Description = AllocateZeroPool ((ModelNameLength + SerialNumberLength + 2) * sizeof (CHAR16));
|
---|
382 | ASSERT (Description != NULL);
|
---|
383 | for (Index = 0; Index + 1 < ModelNameLength; Index += 2) {
|
---|
384 | Description[Index] = (CHAR16)IdentifyData.ModelName[Index + 1];
|
---|
385 | Description[Index + 1] = (CHAR16)IdentifyData.ModelName[Index];
|
---|
386 | }
|
---|
387 |
|
---|
388 | Length = Index;
|
---|
389 | Description[Length++] = L' ';
|
---|
390 |
|
---|
391 | for (Index = 0; Index + 1 < SerialNumberLength; Index += 2) {
|
---|
392 | Description[Length + Index] = (CHAR16)IdentifyData.SerialNo[Index + 1];
|
---|
393 | Description[Length + Index + 1] = (CHAR16)IdentifyData.SerialNo[Index];
|
---|
394 | }
|
---|
395 |
|
---|
396 | Length += Index;
|
---|
397 | Description[Length++] = L'\0';
|
---|
398 | ASSERT (Length == ModelNameLength + SerialNumberLength + 2);
|
---|
399 |
|
---|
400 | BmEliminateExtraSpaces (Description);
|
---|
401 | }
|
---|
402 | } else if (CompareGuid (&DiskInfo->Interface, &gEfiDiskInfoScsiInterfaceGuid) ||
|
---|
403 | CompareGuid (&DiskInfo->Interface, &gEfiDiskInfoUfsInterfaceGuid))
|
---|
404 | {
|
---|
405 | BufferSize = sizeof (EFI_SCSI_INQUIRY_DATA);
|
---|
406 | Status = DiskInfo->Inquiry (
|
---|
407 | DiskInfo,
|
---|
408 | &InquiryData,
|
---|
409 | &BufferSize
|
---|
410 | );
|
---|
411 | if (!EFI_ERROR (Status)) {
|
---|
412 | Description = AllocateZeroPool ((VENDOR_IDENTIFICATION_LENGTH + PRODUCT_IDENTIFICATION_LENGTH + 2) * sizeof (CHAR16));
|
---|
413 | ASSERT (Description != NULL);
|
---|
414 |
|
---|
415 | //
|
---|
416 | // Per SCSI spec, EFI_SCSI_INQUIRY_DATA.Reserved_5_95[3 - 10] save the Verdor identification
|
---|
417 | // EFI_SCSI_INQUIRY_DATA.Reserved_5_95[11 - 26] save the product identification,
|
---|
418 | // Here combine the vendor identification and product identification to the description.
|
---|
419 | //
|
---|
420 | StrPtr = (CHAR8 *)(&InquiryData.Reserved_5_95[VENDOR_IDENTIFICATION_OFFSET]);
|
---|
421 | Temp = StrPtr[VENDOR_IDENTIFICATION_LENGTH];
|
---|
422 | StrPtr[VENDOR_IDENTIFICATION_LENGTH] = '\0';
|
---|
423 | AsciiStrToUnicodeStrS (StrPtr, Description, VENDOR_IDENTIFICATION_LENGTH + 1);
|
---|
424 | StrPtr[VENDOR_IDENTIFICATION_LENGTH] = Temp;
|
---|
425 |
|
---|
426 | //
|
---|
427 | // Add one space at the middle of vendor information and product information.
|
---|
428 | //
|
---|
429 | Description[VENDOR_IDENTIFICATION_LENGTH] = L' ';
|
---|
430 |
|
---|
431 | StrPtr = (CHAR8 *)(&InquiryData.Reserved_5_95[PRODUCT_IDENTIFICATION_OFFSET]);
|
---|
432 | StrPtr[PRODUCT_IDENTIFICATION_LENGTH] = '\0';
|
---|
433 | AsciiStrToUnicodeStrS (StrPtr, Description + VENDOR_IDENTIFICATION_LENGTH + 1, PRODUCT_IDENTIFICATION_LENGTH + 1);
|
---|
434 |
|
---|
435 | BmEliminateExtraSpaces (Description);
|
---|
436 | }
|
---|
437 | } else if (CompareGuid (&DiskInfo->Interface, &gEfiDiskInfoSdMmcInterfaceGuid)) {
|
---|
438 | DevicePath = DevicePathFromHandle (Handle);
|
---|
439 | if (DevicePath == NULL) {
|
---|
440 | return NULL;
|
---|
441 | }
|
---|
442 |
|
---|
443 | while (!IsDevicePathEnd (DevicePath) && (DevicePathType (DevicePath) != MESSAGING_DEVICE_PATH)) {
|
---|
444 | DevicePath = NextDevicePathNode (DevicePath);
|
---|
445 | }
|
---|
446 |
|
---|
447 | if (IsDevicePathEnd (DevicePath)) {
|
---|
448 | return NULL;
|
---|
449 | }
|
---|
450 |
|
---|
451 | if (DevicePathSubType (DevicePath) == MSG_SD_DP) {
|
---|
452 | BufferSize = sizeof (SD_CID);
|
---|
453 | Status = DiskInfo->Inquiry (DiskInfo, &SdCid, &BufferSize);
|
---|
454 | if (EFI_ERROR (Status)) {
|
---|
455 | return NULL;
|
---|
456 | }
|
---|
457 |
|
---|
458 | Description = BmGetSdMmcDescription (
|
---|
459 | BmGetSdMmcManufacturerName (SdCid.ManufacturerId, FALSE),
|
---|
460 | SdCid.ProductName,
|
---|
461 | ARRAY_SIZE (SdCid.ProductName),
|
---|
462 | SdCid.ProductSerialNumber,
|
---|
463 | mBootDescSd
|
---|
464 | );
|
---|
465 | } else if (DevicePathSubType (DevicePath) == MSG_EMMC_DP) {
|
---|
466 | BufferSize = sizeof (EMMC_CID);
|
---|
467 | Status = DiskInfo->Inquiry (DiskInfo, &EmmcCid, &BufferSize);
|
---|
468 | if (EFI_ERROR (Status)) {
|
---|
469 | return NULL;
|
---|
470 | }
|
---|
471 |
|
---|
472 | Description = mBootDescEmmc;
|
---|
473 |
|
---|
474 | DevicePath = NextDevicePathNode (DevicePath);
|
---|
475 | if (DevicePath->SubType == HW_CONTROLLER_DP) {
|
---|
476 | Description = BmGetEmmcTypeDescription ((CONTROLLER_DEVICE_PATH *)DevicePath);
|
---|
477 | }
|
---|
478 |
|
---|
479 | Description = BmGetSdMmcDescription (
|
---|
480 | BmGetSdMmcManufacturerName (EmmcCid.ManufacturerId, TRUE),
|
---|
481 | EmmcCid.ProductName,
|
---|
482 | ARRAY_SIZE (EmmcCid.ProductName),
|
---|
483 | EmmcCid.ProductSerialNumber,
|
---|
484 | Description
|
---|
485 | );
|
---|
486 | } else {
|
---|
487 | return NULL;
|
---|
488 | }
|
---|
489 |
|
---|
490 | Description = AllocateCopyPool (StrSize (Description), Description);
|
---|
491 | }
|
---|
492 |
|
---|
493 | return Description;
|
---|
494 | }
|
---|
495 |
|
---|
496 | /**
|
---|
497 | Try to get the controller's USB description.
|
---|
498 |
|
---|
499 | @param Handle Controller handle.
|
---|
500 |
|
---|
501 | @return The description string.
|
---|
502 | **/
|
---|
503 | CHAR16 *
|
---|
504 | BmGetUsbDescription (
|
---|
505 | IN EFI_HANDLE Handle
|
---|
506 | )
|
---|
507 | {
|
---|
508 | EFI_STATUS Status;
|
---|
509 | EFI_USB_IO_PROTOCOL *UsbIo;
|
---|
510 | CHAR16 NullChar;
|
---|
511 | CHAR16 *Manufacturer;
|
---|
512 | CHAR16 *Product;
|
---|
513 | CHAR16 *SerialNumber;
|
---|
514 | CHAR16 *Description;
|
---|
515 | EFI_USB_DEVICE_DESCRIPTOR DevDesc;
|
---|
516 | UINTN DescMaxSize;
|
---|
517 |
|
---|
518 | Status = gBS->HandleProtocol (
|
---|
519 | Handle,
|
---|
520 | &gEfiUsbIoProtocolGuid,
|
---|
521 | (VOID **)&UsbIo
|
---|
522 | );
|
---|
523 | if (EFI_ERROR (Status)) {
|
---|
524 | return NULL;
|
---|
525 | }
|
---|
526 |
|
---|
527 | NullChar = L'\0';
|
---|
528 |
|
---|
529 | Status = UsbIo->UsbGetDeviceDescriptor (UsbIo, &DevDesc);
|
---|
530 | if (EFI_ERROR (Status)) {
|
---|
531 | return NULL;
|
---|
532 | }
|
---|
533 |
|
---|
534 | Status = UsbIo->UsbGetStringDescriptor (
|
---|
535 | UsbIo,
|
---|
536 | mBmUsbLangId,
|
---|
537 | DevDesc.StrManufacturer,
|
---|
538 | &Manufacturer
|
---|
539 | );
|
---|
540 | if (EFI_ERROR (Status)) {
|
---|
541 | Manufacturer = &NullChar;
|
---|
542 | }
|
---|
543 |
|
---|
544 | Status = UsbIo->UsbGetStringDescriptor (
|
---|
545 | UsbIo,
|
---|
546 | mBmUsbLangId,
|
---|
547 | DevDesc.StrProduct,
|
---|
548 | &Product
|
---|
549 | );
|
---|
550 | if (EFI_ERROR (Status)) {
|
---|
551 | Product = &NullChar;
|
---|
552 | }
|
---|
553 |
|
---|
554 | Status = UsbIo->UsbGetStringDescriptor (
|
---|
555 | UsbIo,
|
---|
556 | mBmUsbLangId,
|
---|
557 | DevDesc.StrSerialNumber,
|
---|
558 | &SerialNumber
|
---|
559 | );
|
---|
560 | if (EFI_ERROR (Status)) {
|
---|
561 | SerialNumber = &NullChar;
|
---|
562 | }
|
---|
563 |
|
---|
564 | if ((Manufacturer == &NullChar) &&
|
---|
565 | (Product == &NullChar) &&
|
---|
566 | (SerialNumber == &NullChar)
|
---|
567 | )
|
---|
568 | {
|
---|
569 | return NULL;
|
---|
570 | }
|
---|
571 |
|
---|
572 | DescMaxSize = StrSize (Manufacturer) + StrSize (Product) + StrSize (SerialNumber);
|
---|
573 | Description = AllocateZeroPool (DescMaxSize);
|
---|
574 | ASSERT (Description != NULL);
|
---|
575 | StrCatS (Description, DescMaxSize/sizeof (CHAR16), Manufacturer);
|
---|
576 | StrCatS (Description, DescMaxSize/sizeof (CHAR16), L" ");
|
---|
577 |
|
---|
578 | StrCatS (Description, DescMaxSize/sizeof (CHAR16), Product);
|
---|
579 | StrCatS (Description, DescMaxSize/sizeof (CHAR16), L" ");
|
---|
580 |
|
---|
581 | StrCatS (Description, DescMaxSize/sizeof (CHAR16), SerialNumber);
|
---|
582 |
|
---|
583 | if (Manufacturer != &NullChar) {
|
---|
584 | FreePool (Manufacturer);
|
---|
585 | }
|
---|
586 |
|
---|
587 | if (Product != &NullChar) {
|
---|
588 | FreePool (Product);
|
---|
589 | }
|
---|
590 |
|
---|
591 | if (SerialNumber != &NullChar) {
|
---|
592 | FreePool (SerialNumber);
|
---|
593 | }
|
---|
594 |
|
---|
595 | BmEliminateExtraSpaces (Description);
|
---|
596 |
|
---|
597 | return Description;
|
---|
598 | }
|
---|
599 |
|
---|
600 | /**
|
---|
601 | Return the description for network boot device.
|
---|
602 |
|
---|
603 | @param Handle Controller handle.
|
---|
604 |
|
---|
605 | @return The description string.
|
---|
606 | **/
|
---|
607 | CHAR16 *
|
---|
608 | BmGetNetworkDescription (
|
---|
609 | IN EFI_HANDLE Handle
|
---|
610 | )
|
---|
611 | {
|
---|
612 | EFI_STATUS Status;
|
---|
613 | EFI_DEVICE_PATH_PROTOCOL *DevicePath;
|
---|
614 | MAC_ADDR_DEVICE_PATH *Mac;
|
---|
615 | VLAN_DEVICE_PATH *Vlan;
|
---|
616 | EFI_DEVICE_PATH_PROTOCOL *Ip;
|
---|
617 | EFI_DEVICE_PATH_PROTOCOL *Uri;
|
---|
618 | CHAR16 *Description;
|
---|
619 | UINTN DescriptionSize;
|
---|
620 |
|
---|
621 | Status = gBS->OpenProtocol (
|
---|
622 | Handle,
|
---|
623 | &gEfiLoadFileProtocolGuid,
|
---|
624 | NULL,
|
---|
625 | gImageHandle,
|
---|
626 | Handle,
|
---|
627 | EFI_OPEN_PROTOCOL_TEST_PROTOCOL
|
---|
628 | );
|
---|
629 | if (EFI_ERROR (Status)) {
|
---|
630 | return NULL;
|
---|
631 | }
|
---|
632 |
|
---|
633 | Status = gBS->OpenProtocol (
|
---|
634 | Handle,
|
---|
635 | &gEfiDevicePathProtocolGuid,
|
---|
636 | (VOID **)&DevicePath,
|
---|
637 | gImageHandle,
|
---|
638 | Handle,
|
---|
639 | EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
---|
640 | );
|
---|
641 | if (EFI_ERROR (Status) || (DevicePath == NULL)) {
|
---|
642 | return NULL;
|
---|
643 | }
|
---|
644 |
|
---|
645 | //
|
---|
646 | // The PXE device path is like:
|
---|
647 | // ....../Mac(...)[/Vlan(...)][/Wi-Fi(...)]
|
---|
648 | // ....../Mac(...)[/Vlan(...)][/Wi-Fi(...)]/IPv4(...)
|
---|
649 | // ....../Mac(...)[/Vlan(...)][/Wi-Fi(...)]/IPv6(...)
|
---|
650 | //
|
---|
651 | // The HTTP device path is like:
|
---|
652 | // ....../Mac(...)[/Vlan(...)][/Wi-Fi(...)]/IPv4(...)[/Dns(...)]/Uri(...)
|
---|
653 | // ....../Mac(...)[/Vlan(...)][/Wi-Fi(...)]/IPv6(...)[/Dns(...)]/Uri(...)
|
---|
654 | //
|
---|
655 | while (!IsDevicePathEnd (DevicePath) &&
|
---|
656 | ((DevicePathType (DevicePath) != MESSAGING_DEVICE_PATH) ||
|
---|
657 | (DevicePathSubType (DevicePath) != MSG_MAC_ADDR_DP))
|
---|
658 | )
|
---|
659 | {
|
---|
660 | DevicePath = NextDevicePathNode (DevicePath);
|
---|
661 | }
|
---|
662 |
|
---|
663 | if (IsDevicePathEnd (DevicePath)) {
|
---|
664 | return NULL;
|
---|
665 | }
|
---|
666 |
|
---|
667 | Mac = (MAC_ADDR_DEVICE_PATH *)DevicePath;
|
---|
668 | DevicePath = NextDevicePathNode (DevicePath);
|
---|
669 |
|
---|
670 | //
|
---|
671 | // Locate the optional Vlan node
|
---|
672 | //
|
---|
673 | if ((DevicePathType (DevicePath) == MESSAGING_DEVICE_PATH) &&
|
---|
674 | (DevicePathSubType (DevicePath) == MSG_VLAN_DP)
|
---|
675 | )
|
---|
676 | {
|
---|
677 | Vlan = (VLAN_DEVICE_PATH *)DevicePath;
|
---|
678 | DevicePath = NextDevicePathNode (DevicePath);
|
---|
679 | } else {
|
---|
680 | Vlan = NULL;
|
---|
681 | }
|
---|
682 |
|
---|
683 | //
|
---|
684 | // Skip the optional Wi-Fi node
|
---|
685 | //
|
---|
686 | if ((DevicePathType (DevicePath) == MESSAGING_DEVICE_PATH) &&
|
---|
687 | (DevicePathSubType (DevicePath) == MSG_WIFI_DP)
|
---|
688 | )
|
---|
689 | {
|
---|
690 | DevicePath = NextDevicePathNode (DevicePath);
|
---|
691 | }
|
---|
692 |
|
---|
693 | //
|
---|
694 | // Locate the IP node
|
---|
695 | //
|
---|
696 | if ((DevicePathType (DevicePath) == MESSAGING_DEVICE_PATH) &&
|
---|
697 | ((DevicePathSubType (DevicePath) == MSG_IPv4_DP) ||
|
---|
698 | (DevicePathSubType (DevicePath) == MSG_IPv6_DP))
|
---|
699 | )
|
---|
700 | {
|
---|
701 | Ip = DevicePath;
|
---|
702 | DevicePath = NextDevicePathNode (DevicePath);
|
---|
703 | } else {
|
---|
704 | Ip = NULL;
|
---|
705 | }
|
---|
706 |
|
---|
707 | //
|
---|
708 | // Skip the optional DNS node
|
---|
709 | //
|
---|
710 | if ((DevicePathType (DevicePath) == MESSAGING_DEVICE_PATH) &&
|
---|
711 | (DevicePathSubType (DevicePath) == MSG_DNS_DP)
|
---|
712 | )
|
---|
713 | {
|
---|
714 | DevicePath = NextDevicePathNode (DevicePath);
|
---|
715 | }
|
---|
716 |
|
---|
717 | //
|
---|
718 | // Locate the URI node
|
---|
719 | //
|
---|
720 | if ((DevicePathType (DevicePath) == MESSAGING_DEVICE_PATH) &&
|
---|
721 | (DevicePathSubType (DevicePath) == MSG_URI_DP)
|
---|
722 | )
|
---|
723 | {
|
---|
724 | Uri = DevicePath;
|
---|
725 | DevicePath = NextDevicePathNode (DevicePath);
|
---|
726 | } else {
|
---|
727 | Uri = NULL;
|
---|
728 | }
|
---|
729 |
|
---|
730 | //
|
---|
731 | // Build description like below:
|
---|
732 | // "PXEv6 (MAC:112233445566 VLAN1)"
|
---|
733 | // "HTTPv4 (MAC:112233445566)"
|
---|
734 | //
|
---|
735 | DescriptionSize = sizeof (L"HTTPv6 (MAC:112233445566 VLAN65535)");
|
---|
736 | Description = AllocatePool (DescriptionSize);
|
---|
737 | ASSERT (Description != NULL);
|
---|
738 | UnicodeSPrint (
|
---|
739 | Description,
|
---|
740 | DescriptionSize,
|
---|
741 | (Vlan == NULL) ?
|
---|
742 | L"%sv%d (MAC:%02x%02x%02x%02x%02x%02x)" :
|
---|
743 | L"%sv%d (MAC:%02x%02x%02x%02x%02x%02x VLAN%d)",
|
---|
744 | (Uri == NULL) ? L"PXE" : L"HTTP",
|
---|
745 | ((Ip == NULL) || (DevicePathSubType (Ip) == MSG_IPv4_DP)) ? 4 : 6,
|
---|
746 | Mac->MacAddress.Addr[0],
|
---|
747 | Mac->MacAddress.Addr[1],
|
---|
748 | Mac->MacAddress.Addr[2],
|
---|
749 | Mac->MacAddress.Addr[3],
|
---|
750 | Mac->MacAddress.Addr[4],
|
---|
751 | Mac->MacAddress.Addr[5],
|
---|
752 | (Vlan == NULL) ? 0 : Vlan->VlanId
|
---|
753 | );
|
---|
754 | return Description;
|
---|
755 | }
|
---|
756 |
|
---|
757 | /**
|
---|
758 | Return the boot description for LoadFile
|
---|
759 |
|
---|
760 | @param Handle Controller handle.
|
---|
761 |
|
---|
762 | @return The description string.
|
---|
763 | **/
|
---|
764 | CHAR16 *
|
---|
765 | BmGetLoadFileDescription (
|
---|
766 | IN EFI_HANDLE Handle
|
---|
767 | )
|
---|
768 | {
|
---|
769 | EFI_STATUS Status;
|
---|
770 | EFI_DEVICE_PATH_PROTOCOL *FilePath;
|
---|
771 | EFI_DEVICE_PATH_PROTOCOL *DevicePathNode;
|
---|
772 | CHAR16 *Description;
|
---|
773 | EFI_LOAD_FILE_PROTOCOL *LoadFile;
|
---|
774 |
|
---|
775 | Status = gBS->HandleProtocol (Handle, &gEfiLoadFileProtocolGuid, (VOID **)&LoadFile);
|
---|
776 | if (EFI_ERROR (Status)) {
|
---|
777 | return NULL;
|
---|
778 | }
|
---|
779 |
|
---|
780 | //
|
---|
781 | // Get the file name
|
---|
782 | //
|
---|
783 | Description = NULL;
|
---|
784 | Status = gBS->HandleProtocol (Handle, &gEfiDevicePathProtocolGuid, (VOID **)&FilePath);
|
---|
785 | if (!EFI_ERROR (Status)) {
|
---|
786 | DevicePathNode = FilePath;
|
---|
787 | while (!IsDevicePathEnd (DevicePathNode)) {
|
---|
788 | if ((DevicePathNode->Type == MEDIA_DEVICE_PATH) && (DevicePathNode->SubType == MEDIA_FILEPATH_DP)) {
|
---|
789 | Description = (CHAR16 *)(DevicePathNode + 1);
|
---|
790 | break;
|
---|
791 | }
|
---|
792 |
|
---|
793 | DevicePathNode = NextDevicePathNode (DevicePathNode);
|
---|
794 | }
|
---|
795 | }
|
---|
796 |
|
---|
797 | if (Description != NULL) {
|
---|
798 | return AllocateCopyPool (StrSize (Description), Description);
|
---|
799 | }
|
---|
800 |
|
---|
801 | return NULL;
|
---|
802 | }
|
---|
803 |
|
---|
804 | /**
|
---|
805 | Return the boot description for NVME boot device.
|
---|
806 |
|
---|
807 | @param Handle Controller handle.
|
---|
808 |
|
---|
809 | @return The description string.
|
---|
810 | **/
|
---|
811 | CHAR16 *
|
---|
812 | BmGetNvmeDescription (
|
---|
813 | IN EFI_HANDLE Handle
|
---|
814 | )
|
---|
815 | {
|
---|
816 | EFI_STATUS Status;
|
---|
817 | EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL *NvmePassthru;
|
---|
818 | EFI_DEV_PATH_PTR DevicePath;
|
---|
819 | EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket;
|
---|
820 | EFI_NVM_EXPRESS_COMMAND Command;
|
---|
821 | EFI_NVM_EXPRESS_COMPLETION Completion;
|
---|
822 | NVME_ADMIN_CONTROLLER_DATA ControllerData;
|
---|
823 | CHAR16 *Description;
|
---|
824 | CHAR16 *Char;
|
---|
825 | UINTN Index;
|
---|
826 |
|
---|
827 | Status = gBS->HandleProtocol (Handle, &gEfiDevicePathProtocolGuid, (VOID **)&DevicePath.DevPath);
|
---|
828 | if (EFI_ERROR (Status)) {
|
---|
829 | return NULL;
|
---|
830 | }
|
---|
831 |
|
---|
832 | Status = gBS->LocateDevicePath (&gEfiNvmExpressPassThruProtocolGuid, &DevicePath.DevPath, &Handle);
|
---|
833 | if (EFI_ERROR (Status) ||
|
---|
834 | (DevicePathType (DevicePath.DevPath) != MESSAGING_DEVICE_PATH) ||
|
---|
835 | (DevicePathSubType (DevicePath.DevPath) != MSG_NVME_NAMESPACE_DP))
|
---|
836 | {
|
---|
837 | //
|
---|
838 | // Do not return description when the Handle is not a child of NVME controller.
|
---|
839 | //
|
---|
840 | return NULL;
|
---|
841 | }
|
---|
842 |
|
---|
843 | //
|
---|
844 | // Send ADMIN_IDENTIFY command to NVME controller to get the model and serial number.
|
---|
845 | //
|
---|
846 | Status = gBS->HandleProtocol (Handle, &gEfiNvmExpressPassThruProtocolGuid, (VOID **)&NvmePassthru);
|
---|
847 | ASSERT_EFI_ERROR (Status);
|
---|
848 |
|
---|
849 | ZeroMem (&CommandPacket, sizeof (EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
|
---|
850 | ZeroMem (&Command, sizeof (EFI_NVM_EXPRESS_COMMAND));
|
---|
851 | ZeroMem (&Completion, sizeof (EFI_NVM_EXPRESS_COMPLETION));
|
---|
852 |
|
---|
853 | Command.Cdw0.Opcode = NVME_ADMIN_IDENTIFY_CMD;
|
---|
854 | //
|
---|
855 | // According to Nvm Express 1.1 spec Figure 38, When not used, the field shall be cleared to 0h.
|
---|
856 | // For the Identify command, the Namespace Identifier is only used for the Namespace data structure.
|
---|
857 | //
|
---|
858 | Command.Nsid = 0;
|
---|
859 | CommandPacket.NvmeCmd = &Command;
|
---|
860 | CommandPacket.NvmeCompletion = &Completion;
|
---|
861 | CommandPacket.TransferBuffer = &ControllerData;
|
---|
862 | CommandPacket.TransferLength = sizeof (ControllerData);
|
---|
863 | CommandPacket.CommandTimeout = EFI_TIMER_PERIOD_SECONDS (5);
|
---|
864 | CommandPacket.QueueType = NVME_ADMIN_QUEUE;
|
---|
865 | //
|
---|
866 | // Set bit 0 (Cns bit) to 1 to identify a controller
|
---|
867 | //
|
---|
868 | Command.Cdw10 = 1;
|
---|
869 | Command.Flags = CDW10_VALID;
|
---|
870 |
|
---|
871 | Status = NvmePassthru->PassThru (
|
---|
872 | NvmePassthru,
|
---|
873 | 0,
|
---|
874 | &CommandPacket,
|
---|
875 | NULL
|
---|
876 | );
|
---|
877 | if (EFI_ERROR (Status)) {
|
---|
878 | return NULL;
|
---|
879 | }
|
---|
880 |
|
---|
881 | Description = AllocateZeroPool (
|
---|
882 | (ARRAY_SIZE (ControllerData.Mn) + 1
|
---|
883 | + ARRAY_SIZE (ControllerData.Sn) + 1
|
---|
884 | + MAXIMUM_VALUE_CHARACTERS + 1
|
---|
885 | ) * sizeof (CHAR16)
|
---|
886 | );
|
---|
887 | if (Description != NULL) {
|
---|
888 | Char = Description;
|
---|
889 | for (Index = 0; Index < ARRAY_SIZE (ControllerData.Mn); Index++) {
|
---|
890 | *(Char++) = (CHAR16)ControllerData.Mn[Index];
|
---|
891 | }
|
---|
892 |
|
---|
893 | *(Char++) = L' ';
|
---|
894 | for (Index = 0; Index < ARRAY_SIZE (ControllerData.Sn); Index++) {
|
---|
895 | *(Char++) = (CHAR16)ControllerData.Sn[Index];
|
---|
896 | }
|
---|
897 |
|
---|
898 | *(Char++) = L' ';
|
---|
899 | UnicodeValueToStringS (
|
---|
900 | Char,
|
---|
901 | sizeof (CHAR16) * (MAXIMUM_VALUE_CHARACTERS + 1),
|
---|
902 | 0,
|
---|
903 | DevicePath.NvmeNamespace->NamespaceId,
|
---|
904 | 0
|
---|
905 | );
|
---|
906 | BmEliminateExtraSpaces (Description);
|
---|
907 | }
|
---|
908 |
|
---|
909 | return Description;
|
---|
910 | }
|
---|
911 |
|
---|
912 | /**
|
---|
913 | Return the boot description for the controller based on the type.
|
---|
914 |
|
---|
915 | @param Handle Controller handle.
|
---|
916 |
|
---|
917 | @return The description string.
|
---|
918 | **/
|
---|
919 | CHAR16 *
|
---|
920 | BmGetMiscDescription (
|
---|
921 | IN EFI_HANDLE Handle
|
---|
922 | )
|
---|
923 | {
|
---|
924 | EFI_STATUS Status;
|
---|
925 | CHAR16 *Description;
|
---|
926 | EFI_BLOCK_IO_PROTOCOL *BlockIo;
|
---|
927 | EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Fs;
|
---|
928 |
|
---|
929 | switch (BmDevicePathType (DevicePathFromHandle (Handle))) {
|
---|
930 | case BmAcpiFloppyBoot:
|
---|
931 | Description = L"Floppy";
|
---|
932 | break;
|
---|
933 |
|
---|
934 | case BmMessageAtapiBoot:
|
---|
935 | case BmMessageSataBoot:
|
---|
936 | Status = gBS->HandleProtocol (Handle, &gEfiBlockIoProtocolGuid, (VOID **)&BlockIo);
|
---|
937 | ASSERT_EFI_ERROR (Status);
|
---|
938 | //
|
---|
939 | // Assume a removable SATA device should be the DVD/CD device
|
---|
940 | //
|
---|
941 | Description = BlockIo->Media->RemovableMedia ? L"DVD/CDROM" : L"Hard Drive";
|
---|
942 | break;
|
---|
943 |
|
---|
944 | case BmMessageUsbBoot:
|
---|
945 | Description = L"USB Device";
|
---|
946 | break;
|
---|
947 |
|
---|
948 | case BmMessageScsiBoot:
|
---|
949 | Description = L"SCSI Device";
|
---|
950 | break;
|
---|
951 |
|
---|
952 | case BmHardwareDeviceBoot:
|
---|
953 | Status = gBS->HandleProtocol (Handle, &gEfiBlockIoProtocolGuid, (VOID **)&BlockIo);
|
---|
954 | if (!EFI_ERROR (Status)) {
|
---|
955 | Description = BlockIo->Media->RemovableMedia ? L"Removable Disk" : L"Hard Drive";
|
---|
956 | } else {
|
---|
957 | Description = L"Misc Device";
|
---|
958 | }
|
---|
959 |
|
---|
960 | break;
|
---|
961 |
|
---|
962 | default:
|
---|
963 | Status = gBS->HandleProtocol (Handle, &gEfiSimpleFileSystemProtocolGuid, (VOID **)&Fs);
|
---|
964 | if (!EFI_ERROR (Status)) {
|
---|
965 | Description = L"Non-Block Boot Device";
|
---|
966 | } else {
|
---|
967 | Description = L"Misc Device";
|
---|
968 | }
|
---|
969 |
|
---|
970 | break;
|
---|
971 | }
|
---|
972 |
|
---|
973 | return AllocateCopyPool (StrSize (Description), Description);
|
---|
974 | }
|
---|
975 |
|
---|
976 | /**
|
---|
977 | Register the platform provided boot description handler.
|
---|
978 |
|
---|
979 | @param Handler The platform provided boot description handler
|
---|
980 |
|
---|
981 | @retval EFI_SUCCESS The handler was registered successfully.
|
---|
982 | @retval EFI_ALREADY_STARTED The handler was already registered.
|
---|
983 | @retval EFI_OUT_OF_RESOURCES There is not enough resource to perform the registration.
|
---|
984 | **/
|
---|
985 | EFI_STATUS
|
---|
986 | EFIAPI
|
---|
987 | EfiBootManagerRegisterBootDescriptionHandler (
|
---|
988 | IN EFI_BOOT_MANAGER_BOOT_DESCRIPTION_HANDLER Handler
|
---|
989 | )
|
---|
990 | {
|
---|
991 | LIST_ENTRY *Link;
|
---|
992 | BM_BOOT_DESCRIPTION_ENTRY *Entry;
|
---|
993 |
|
---|
994 | for ( Link = GetFirstNode (&mPlatformBootDescriptionHandlers)
|
---|
995 | ; !IsNull (&mPlatformBootDescriptionHandlers, Link)
|
---|
996 | ; Link = GetNextNode (&mPlatformBootDescriptionHandlers, Link)
|
---|
997 | )
|
---|
998 | {
|
---|
999 | Entry = CR (Link, BM_BOOT_DESCRIPTION_ENTRY, Link, BM_BOOT_DESCRIPTION_ENTRY_SIGNATURE);
|
---|
1000 | if (Entry->Handler == Handler) {
|
---|
1001 | return EFI_ALREADY_STARTED;
|
---|
1002 | }
|
---|
1003 | }
|
---|
1004 |
|
---|
1005 | Entry = AllocatePool (sizeof (BM_BOOT_DESCRIPTION_ENTRY));
|
---|
1006 | if (Entry == NULL) {
|
---|
1007 | return EFI_OUT_OF_RESOURCES;
|
---|
1008 | }
|
---|
1009 |
|
---|
1010 | Entry->Signature = BM_BOOT_DESCRIPTION_ENTRY_SIGNATURE;
|
---|
1011 | Entry->Handler = Handler;
|
---|
1012 | InsertTailList (&mPlatformBootDescriptionHandlers, &Entry->Link);
|
---|
1013 | return EFI_SUCCESS;
|
---|
1014 | }
|
---|
1015 |
|
---|
1016 | BM_GET_BOOT_DESCRIPTION mBmBootDescriptionHandlers[] = {
|
---|
1017 | BmGetUsbDescription,
|
---|
1018 | BmGetDescriptionFromDiskInfo,
|
---|
1019 | BmGetNetworkDescription,
|
---|
1020 | BmGetLoadFileDescription,
|
---|
1021 | BmGetNvmeDescription,
|
---|
1022 | BmGetMiscDescription
|
---|
1023 | };
|
---|
1024 |
|
---|
1025 | /**
|
---|
1026 | Return the boot description for the controller.
|
---|
1027 |
|
---|
1028 | @param Handle Controller handle.
|
---|
1029 |
|
---|
1030 | @return The description string.
|
---|
1031 | **/
|
---|
1032 | CHAR16 *
|
---|
1033 | BmGetBootDescription (
|
---|
1034 | IN EFI_HANDLE Handle
|
---|
1035 | )
|
---|
1036 | {
|
---|
1037 | LIST_ENTRY *Link;
|
---|
1038 | BM_BOOT_DESCRIPTION_ENTRY *Entry;
|
---|
1039 | CHAR16 *Description;
|
---|
1040 | CHAR16 *DefaultDescription;
|
---|
1041 | CHAR16 *Temp;
|
---|
1042 | UINTN Index;
|
---|
1043 |
|
---|
1044 | //
|
---|
1045 | // Firstly get the default boot description
|
---|
1046 | //
|
---|
1047 | DefaultDescription = NULL;
|
---|
1048 | for (Index = 0; Index < ARRAY_SIZE (mBmBootDescriptionHandlers); Index++) {
|
---|
1049 | DefaultDescription = mBmBootDescriptionHandlers[Index](Handle);
|
---|
1050 | if (DefaultDescription != NULL) {
|
---|
1051 | //
|
---|
1052 | // Avoid description confusion between UEFI & Legacy boot option by adding "UEFI " prefix
|
---|
1053 | // ONLY for core provided boot description handler.
|
---|
1054 | //
|
---|
1055 | Temp = AllocatePool (StrSize (DefaultDescription) + sizeof (mBmUefiPrefix));
|
---|
1056 | ASSERT (Temp != NULL);
|
---|
1057 | StrCpyS (Temp, (StrSize (DefaultDescription) + sizeof (mBmUefiPrefix)) / sizeof (CHAR16), mBmUefiPrefix);
|
---|
1058 | StrCatS (Temp, (StrSize (DefaultDescription) + sizeof (mBmUefiPrefix)) / sizeof (CHAR16), DefaultDescription);
|
---|
1059 | FreePool (DefaultDescription);
|
---|
1060 | DefaultDescription = Temp;
|
---|
1061 | break;
|
---|
1062 | }
|
---|
1063 | }
|
---|
1064 |
|
---|
1065 | ASSERT (DefaultDescription != NULL);
|
---|
1066 |
|
---|
1067 | //
|
---|
1068 | // Secondly query platform for the better boot description
|
---|
1069 | //
|
---|
1070 | for ( Link = GetFirstNode (&mPlatformBootDescriptionHandlers)
|
---|
1071 | ; !IsNull (&mPlatformBootDescriptionHandlers, Link)
|
---|
1072 | ; Link = GetNextNode (&mPlatformBootDescriptionHandlers, Link)
|
---|
1073 | )
|
---|
1074 | {
|
---|
1075 | Entry = CR (Link, BM_BOOT_DESCRIPTION_ENTRY, Link, BM_BOOT_DESCRIPTION_ENTRY_SIGNATURE);
|
---|
1076 | Description = Entry->Handler (Handle, DefaultDescription);
|
---|
1077 | if (Description != NULL) {
|
---|
1078 | FreePool (DefaultDescription);
|
---|
1079 | return Description;
|
---|
1080 | }
|
---|
1081 | }
|
---|
1082 |
|
---|
1083 | return DefaultDescription;
|
---|
1084 | }
|
---|
1085 |
|
---|
1086 | /**
|
---|
1087 | Enumerate all boot option descriptions and append " 2"/" 3"/... to make
|
---|
1088 | unique description.
|
---|
1089 |
|
---|
1090 | @param BootOptions Array of boot options.
|
---|
1091 | @param BootOptionCount Count of boot options.
|
---|
1092 | **/
|
---|
1093 | VOID
|
---|
1094 | BmMakeBootOptionDescriptionUnique (
|
---|
1095 | EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions,
|
---|
1096 | UINTN BootOptionCount
|
---|
1097 | )
|
---|
1098 | {
|
---|
1099 | UINTN Base;
|
---|
1100 | UINTN Index;
|
---|
1101 | UINTN DescriptionSize;
|
---|
1102 | UINTN MaxSuffixSize;
|
---|
1103 | BOOLEAN *Visited;
|
---|
1104 | UINTN MatchCount;
|
---|
1105 |
|
---|
1106 | if (BootOptionCount == 0) {
|
---|
1107 | return;
|
---|
1108 | }
|
---|
1109 |
|
---|
1110 | //
|
---|
1111 | // Calculate the maximum buffer size for the number suffix.
|
---|
1112 | // The initial sizeof (CHAR16) is for the blank space before the number.
|
---|
1113 | //
|
---|
1114 | MaxSuffixSize = sizeof (CHAR16);
|
---|
1115 | for (Index = BootOptionCount; Index != 0; Index = Index / 10) {
|
---|
1116 | MaxSuffixSize += sizeof (CHAR16);
|
---|
1117 | }
|
---|
1118 |
|
---|
1119 | Visited = AllocateZeroPool (sizeof (BOOLEAN) * BootOptionCount);
|
---|
1120 | ASSERT (Visited != NULL);
|
---|
1121 |
|
---|
1122 | for (Base = 0; Base < BootOptionCount; Base++) {
|
---|
1123 | if (!Visited[Base]) {
|
---|
1124 | MatchCount = 1;
|
---|
1125 | Visited[Base] = TRUE;
|
---|
1126 | DescriptionSize = StrSize (BootOptions[Base].Description);
|
---|
1127 | for (Index = Base + 1; Index < BootOptionCount; Index++) {
|
---|
1128 | if (!Visited[Index] && (StrCmp (BootOptions[Base].Description, BootOptions[Index].Description) == 0)) {
|
---|
1129 | Visited[Index] = TRUE;
|
---|
1130 | MatchCount++;
|
---|
1131 | FreePool (BootOptions[Index].Description);
|
---|
1132 | BootOptions[Index].Description = AllocatePool (DescriptionSize + MaxSuffixSize);
|
---|
1133 | UnicodeSPrint (
|
---|
1134 | BootOptions[Index].Description,
|
---|
1135 | DescriptionSize + MaxSuffixSize,
|
---|
1136 | L"%s %d",
|
---|
1137 | BootOptions[Base].Description,
|
---|
1138 | MatchCount
|
---|
1139 | );
|
---|
1140 | }
|
---|
1141 | }
|
---|
1142 | }
|
---|
1143 | }
|
---|
1144 |
|
---|
1145 | FreePool (Visited);
|
---|
1146 | }
|
---|