TianoCore EDK2 master
Loading...
Searching...
No Matches
BmBootDescription.c
Go to the documentation of this file.
1
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
17CONST UINT16 mBmUsbLangId = 0x0409; // English
18CHAR16 mBmUefiPrefix[] = L"UEFI ";
19
20CHAR16 mBootDescGenericManufacturer[] = L"Generic";
21CHAR16 mBootDescSd[] = L"SD Device";
22CHAR16 mBootDescEmmc[] = L"eMMC Device";
23CHAR16 mBootDescEmmcUserData[] = L"eMMC User Data";
24CHAR16 mBootDescEmmcBoot1[] = L"eMMC Boot 1";
25CHAR16 mBootDescEmmcBoot2[] = L"eMMC Boot 2";
26CHAR16 mBootDescEmmcGp1[] = L"eMMC GP 1";
27CHAR16 mBootDescEmmcGp2[] = L"eMMC GP 2";
28CHAR16 mBootDescEmmcGp3[] = L"eMMC GP 3";
29CHAR16 mBootDescEmmcGp4[] = L"eMMC GP 4";
30
31typedef struct {
32 UINT8 Id;
33 CHAR16 *Name;
35
36BM_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
60BM_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
78LIST_ENTRY mPlatformBootDescriptionHandlers = INITIALIZE_LIST_HEAD_VARIABLE (mPlatformBootDescriptionHandlers);
79
98BM_BOOT_TYPE
100 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
101 )
102{
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
118 if (DevicePathSubType (Node) == HW_CONTROLLER_DP) {
119 return BmHardwareDeviceBoot;
120 }
121
122 break;
123
125 //
126 // Skip LUN device node
127 //
128 NextNode = Node;
129 do {
130 NextNode = NextDevicePathNode (NextNode);
131 } while (
132 (DevicePathType (NextNode) == MESSAGING_DEVICE_PATH) &&
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
171VOID
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
194VOID
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
220CHAR16 *
222 IN UINT8 Id,
223 IN BOOLEAN IsMmc
224 )
225{
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
250CHAR16 *
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
288CHAR16 *
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
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
339CHAR16 *
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
503CHAR16 *
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;
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
607CHAR16 *
609 IN EFI_HANDLE Handle
610 )
611{
612 EFI_STATUS Status;
613 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
615 VLAN_DEVICE_PATH *Vlan;
618 CHAR16 *Description;
619 UINTN DescriptionSize;
620
621 Status = gBS->OpenProtocol (
622 Handle,
623 &gEfiLoadFileProtocolGuid,
624 NULL,
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,
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);
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
764CHAR16 *
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
811CHAR16 *
813 IN EFI_HANDLE Handle
814 )
815{
816 EFI_STATUS Status;
818 EFI_DEV_PATH_PTR DevicePath;
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
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' ';
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
919CHAR16 *
921 IN EFI_HANDLE Handle
922 )
923{
924 EFI_STATUS Status;
925 CHAR16 *Description;
926 EFI_BLOCK_IO_PROTOCOL *BlockIo;
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
986EFIAPI
989 )
990{
991 LIST_ENTRY *Link;
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
1016BM_GET_BOOT_DESCRIPTION mBmBootDescriptionHandlers[] = {
1023};
1024
1032CHAR16 *
1034 IN EFI_HANDLE Handle
1035 )
1036{
1037 LIST_ENTRY *Link;
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
1093VOID
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);
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}
UINT64 UINTN
BOOLEAN EFIAPI IsNull(IN CONST LIST_ENTRY *List, IN CONST LIST_ENTRY *Node)
Definition: LinkedList.c:443
UINTN EFIAPI StrSize(IN CONST CHAR16 *String)
Definition: String.c:72
RETURN_STATUS EFIAPI StrCpyS(OUT CHAR16 *Destination, IN UINTN DestMax, IN CONST CHAR16 *Source)
Definition: SafeString.c:226
LIST_ENTRY *EFIAPI GetNextNode(IN CONST LIST_ENTRY *List, IN CONST LIST_ENTRY *Node)
Definition: LinkedList.c:333
INTN EFIAPI StrCmp(IN CONST CHAR16 *FirstString, IN CONST CHAR16 *SecondString)
Definition: String.c:109
LIST_ENTRY *EFIAPI GetFirstNode(IN CONST LIST_ENTRY *List)
Definition: LinkedList.c:298
RETURN_STATUS EFIAPI StrCatS(IN OUT CHAR16 *Destination, IN UINTN DestMax, IN CONST CHAR16 *Source)
Definition: SafeString.c:405
#define INITIALIZE_LIST_HEAD_VARIABLE(ListHead)
Definition: BaseLib.h:2904
RETURN_STATUS EFIAPI AsciiStrToUnicodeStrS(IN CONST CHAR8 *Source, OUT CHAR16 *Destination, IN UINTN DestMax)
Definition: SafeString.c:2873
LIST_ENTRY *EFIAPI InsertTailList(IN OUT LIST_ENTRY *ListHead, IN OUT LIST_ENTRY *Entry)
Definition: LinkedList.c:259
BOOLEAN EFIAPI CompareGuid(IN CONST GUID *Guid1, IN CONST GUID *Guid2)
Definition: MemLibGuid.c:73
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
CHAR16 * BmGetNvmeDescription(IN EFI_HANDLE Handle)
VOID BmMakeBootOptionDescriptionUnique(EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions, UINTN BootOptionCount)
CHAR16 * BmGetSdMmcManufacturerName(IN UINT8 Id, IN BOOLEAN IsMmc)
CHAR16 * BmGetLoadFileDescription(IN EFI_HANDLE Handle)
CHAR16 * BmGetEmmcTypeDescription(CONTROLLER_DEVICE_PATH *DevicePath)
CHAR16 * BmGetNetworkDescription(IN EFI_HANDLE Handle)
CHAR16 * BmGetUsbDescription(IN EFI_HANDLE Handle)
CHAR16 * BmGetSdMmcDescription(IN CHAR16 *ManufacturerName, IN UINT8 *ProductName, IN UINT8 ProductNameLength, IN UINT8 SerialNumber[4], IN CHAR16 *DeviceType)
CHAR16 * BmGetBootDescription(IN EFI_HANDLE Handle)
BM_BOOT_TYPE BmDevicePathType(IN EFI_DEVICE_PATH_PROTOCOL *DevicePath)
CHAR16 * BmGetDescriptionFromDiskInfo(IN EFI_HANDLE Handle)
VOID BmEliminateExtraSpaces(IN CHAR16 *Str)
CHAR16 * BmGetMiscDescription(IN EFI_HANDLE Handle)
EFI_STATUS EFIAPI EfiBootManagerRegisterBootDescriptionHandler(IN EFI_BOOT_MANAGER_BOOT_DESCRIPTION_HANDLER Handler)
VOID BmSwapBytes(IN UINT8 *Source, IN UINTN Length)
#define MSG_IPv6_DP
Definition: DevicePath.h:607
#define MSG_IPv4_DP
Definition: DevicePath.h:566
#define MEDIA_FILEPATH_DP
Definition: DevicePath.h:1098
#define HARDWARE_DEVICE_PATH
Definition: DevicePath.h:68
#define MSG_SCSI_DP
Definition: DevicePath.h:346
#define MSG_DEVICE_LOGICAL_UNIT_DP
Definition: DevicePath.h:498
#define MSG_NVME_NAMESPACE_DP
Definition: DevicePath.h:833
#define MSG_SD_DP
Definition: DevicePath.h:907
#define MSG_URI_DP
Definition: DevicePath.h:879
#define MSG_ATAPI_DP
Definition: DevicePath.h:326
#define ACPI_DEVICE_PATH
Definition: DevicePath.h:190
#define MSG_DNS_DP
Definition: DevicePath.h:863
#define MSG_EMMC_DP
Definition: DevicePath.h:916
#define MSG_USB_DP
Definition: DevicePath.h:418
#define MSG_MAC_ADDR_DP
Definition: DevicePath.h:550
#define MSG_SATA_DP
Definition: DevicePath.h:510
#define MSG_VLAN_DP
Definition: DevicePath.h:964
#define MSG_WIFI_DP
Definition: DevicePath.h:988
#define MESSAGING_DEVICE_PATH
Definition: DevicePath.h:321
#define HW_CONTROLLER_DP
Definition: DevicePath.h:154
UINT8 EFIAPI DevicePathType(IN CONST VOID *Node)
UINT8 EFIAPI DevicePathSubType(IN CONST VOID *Node)
BOOLEAN EFIAPI IsDevicePathEnd(IN CONST VOID *Node)
EFI_DEVICE_PATH_PROTOCOL *EFIAPI NextDevicePathNode(IN CONST VOID *Node)
EFI_DEVICE_PATH_PROTOCOL *EFIAPI DevicePathFromHandle(IN EFI_HANDLE Handle)
BOOLEAN EFIAPI IsDevicePathEndType(IN CONST VOID *Node)
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
VOID *EFIAPI AllocateCopyPool(IN UINTN AllocationSize, IN CONST VOID *Buffer)
RETURN_STATUS EFIAPI UnicodeValueToStringS(IN OUT CHAR16 *Buffer, IN UINTN BufferSize, IN UINTN Flags, IN INT64 Value, IN UINTN Width)
Definition: PrintLib.c:652
UINTN EFIAPI UnicodeSPrint(OUT CHAR16 *StartOfBuffer, IN UINTN BufferSize, IN CONST CHAR16 *FormatString,...)
Definition: PrintLib.c:408
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define ARRAY_SIZE(Array)
Definition: Base.h:1393
#define IN
Definition: Base.h:279
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
#define CR(Record, TYPE, Field, TestSignature)
Definition: DebugLib.h:659
VOID *EFIAPI AllocatePool(IN UINTN AllocationSize)
#define MAXIMUM_VALUE_CHARACTERS
Definition: PrintLib.h:189
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
CHAR16 *(EFIAPI * EFI_BOOT_MANAGER_BOOT_DESCRIPTION_HANDLER)(IN EFI_HANDLE Handle, IN CONST CHAR16 *DefaultDescription)
EFI_HANDLE gImageHandle
EFI_BOOT_SERVICES * gBS
#define EFI_TIMER_PERIOD_SECONDS(Seconds)
Definition: UefiLib.h:98
EFI_DISK_INFO_INQUIRY Inquiry
Definition: DiskInfo.h:194
EFI_DISK_INFO_IDENTIFY Identify
Definition: DiskInfo.h:199
CHAR8 SerialNo[20]
word 10~19
Definition: Atapi.h:192
CHAR8 ModelName[40]
word 27~46
Definition: Atapi.h:195
Definition: Emmc.h:71
EFI_MAC_ADDRESS MacAddress
Definition: DevicePath.h:556
Definition: Sd.h:66