]> git.proxmox.com Git - mirror_edk2.git/blob - ShellPkg/Library/UefiShellCommandLib/ConsistMapping.c
ShellPkg/ConsistMapping.c: Handle memory allocation failure
[mirror_edk2.git] / ShellPkg / Library / UefiShellCommandLib / ConsistMapping.c
1 /** @file
2 Main file for support of shell consist mapping.
3
4 Copyright (c) 2005 - 2016, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12 **/
13
14 #include "UefiShellCommandLib.h"
15 #include <Library/DevicePathLib.h>
16 #include <Library/SortLib.h>
17 #include <Library/UefiLib.h>
18 #include <Protocol/UsbIo.h>
19 #include <Protocol/BlockIo.h>
20 #include <Protocol/SimpleFileSystem.h>
21
22
23
24 typedef enum {
25 MTDTypeUnknown,
26 MTDTypeFloppy,
27 MTDTypeHardDisk,
28 MTDTypeCDRom,
29 MTDTypeEnd
30 } MTD_TYPE;
31
32 typedef struct {
33 CHAR16 *Str;
34 UINTN Len;
35 } POOL_PRINT;
36
37 typedef struct {
38 UINTN Hi;
39 MTD_TYPE Mtd;
40 POOL_PRINT Csd;
41 BOOLEAN Digital;
42 } DEVICE_CONSIST_MAPPING_INFO;
43
44 typedef struct {
45 MTD_TYPE MTDType;
46 CHAR16 *Name;
47 } MTD_NAME;
48
49 /**
50 Serial Decode function.
51
52 @param DevPath The Device path info.
53 @param MapInfo The map info.
54 @param OrigDevPath The original device path protocol.
55
56 @retval EFI_OUT_OF_RESOURCES Out of resources.
57 @retval EFI_SUCCESS The appending was successful.
58 **/
59 typedef
60 EFI_STATUS
61 (*SERIAL_DECODE_FUNCTION) (
62 EFI_DEVICE_PATH_PROTOCOL *DevPath,
63 DEVICE_CONSIST_MAPPING_INFO *MapInfo,
64 EFI_DEVICE_PATH_PROTOCOL *OrigDevPath
65 );
66
67 typedef struct {
68 UINT8 Type;
69 UINT8 SubType;
70 SERIAL_DECODE_FUNCTION SerialFun;
71 INTN (EFIAPI *CompareFun) (EFI_DEVICE_PATH_PROTOCOL *DevPath, EFI_DEVICE_PATH_PROTOCOL *DevPath2);
72 } DEV_PATH_CONSIST_MAPPING_TABLE;
73
74
75 /**
76 Concatenates a formatted unicode string to allocated pool.
77 The caller must free the resulting buffer.
78
79 @param Str Tracks the allocated pool, size in use, and amount of pool allocated.
80 @param Fmt The format string
81 @param ... The data will be printed.
82
83 @retval EFI_SUCCESS The string is concatenated successfully.
84 @retval EFI_OUT_OF_RESOURCES Out of resources.
85
86 **/
87 EFI_STATUS
88 CatPrint (
89 IN OUT POOL_PRINT *Str,
90 IN CHAR16 *Fmt,
91 ...
92 )
93 {
94 UINT16 *AppendStr;
95 VA_LIST Args;
96 UINTN StringSize;
97 CHAR16 *NewStr;
98
99 AppendStr = AllocateZeroPool (0x1000);
100 if (AppendStr == NULL) {
101 return EFI_OUT_OF_RESOURCES;
102 }
103
104 VA_START (Args, Fmt);
105 UnicodeVSPrint (AppendStr, 0x1000, Fmt, Args);
106 VA_END (Args);
107 if (NULL == Str->Str) {
108 StringSize = StrSize (AppendStr);
109 NewStr = AllocateZeroPool (StringSize);
110 } else {
111 StringSize = StrSize (AppendStr);
112 StringSize += (StrSize (Str->Str) - sizeof (UINT16));
113
114 NewStr = ReallocatePool (
115 StrSize (Str->Str),
116 StringSize,
117 Str->Str
118 );
119 }
120 if (NewStr == NULL) {
121 FreePool (AppendStr);
122 return EFI_OUT_OF_RESOURCES;
123 }
124
125 Str->Str = NewStr;
126 StrCatS (Str->Str, StringSize/sizeof(CHAR16), AppendStr);
127 Str->Len = StringSize;
128
129 FreePool (AppendStr);
130 return EFI_SUCCESS;
131 }
132
133 MTD_NAME mMTDName[] = {
134 {
135 MTDTypeUnknown,
136 L"F"
137 },
138 {
139 MTDTypeFloppy,
140 L"FP"
141 },
142 {
143 MTDTypeHardDisk,
144 L"HD"
145 },
146 {
147 MTDTypeCDRom,
148 L"CD"
149 },
150 {
151 MTDTypeEnd,
152 NULL
153 }
154 };
155
156 /**
157 Function to append a 64 bit number / 25 onto the string.
158
159 @param[in, out] Str The string so append onto.
160 @param[in] Num The number to divide and append.
161
162 @retval EFI_OUT_OF_RESOURCES Out of resources.
163 @retval EFI_SUCCESS The appending was successful.
164 **/
165 EFI_STATUS
166 AppendCSDNum2 (
167 IN OUT POOL_PRINT *Str,
168 IN UINT64 Num
169 )
170 {
171 EFI_STATUS Status;
172 UINT64 Result;
173 UINT32 Rem;
174
175 ASSERT (Str != NULL);
176
177 Result = DivU64x32Remainder (Num, 25, &Rem);
178 if (Result > 0) {
179 Status = AppendCSDNum2 (Str, Result);
180 if (EFI_ERROR (Status)) {
181 return Status;
182 }
183 }
184
185 return CatPrint (Str, L"%c", Rem + 'a');
186 }
187
188 /**
189 Function to append a 64 bit number onto the mapping info.
190
191 @param[in, out] MappingItem The mapping info object to append onto.
192 @param[in] Num The info to append.
193
194 @retval EFI_OUT_OF_RESOURCES Out of resources.
195 @retval EFI_SUCCESS The appending was successful.
196
197 **/
198 EFI_STATUS
199 AppendCSDNum (
200 IN OUT DEVICE_CONSIST_MAPPING_INFO *MappingItem,
201 IN UINT64 Num
202 )
203 {
204 EFI_STATUS Status;
205 ASSERT (MappingItem != NULL);
206
207 if (MappingItem->Digital) {
208 Status = CatPrint (&MappingItem->Csd, L"%ld", Num);
209 } else {
210 Status = AppendCSDNum2 (&MappingItem->Csd, Num);
211 }
212
213 if (!EFI_ERROR (Status)) {
214 MappingItem->Digital = (BOOLEAN) !(MappingItem->Digital);
215 }
216
217 return Status;
218 }
219
220 /**
221 Function to append string into the mapping info.
222
223 @param[in, out] MappingItem The mapping info object to append onto.
224 @param[in] Str The info to append.
225
226 @retval EFI_OUT_OF_RESOURCES Out of resources.
227 @retval EFI_SUCCESS The appending was successful.
228 **/
229 EFI_STATUS
230 AppendCSDStr (
231 IN OUT DEVICE_CONSIST_MAPPING_INFO *MappingItem,
232 IN CHAR16 *Str
233 )
234 {
235 CHAR16 *Index;
236 EFI_STATUS Status;
237
238 ASSERT (Str != NULL && MappingItem != NULL);
239
240 Status = EFI_SUCCESS;
241
242 if (MappingItem->Digital) {
243 //
244 // To aVOID mult-meaning, the mapping is:
245 // 0 1 2 3 4 5 6 7 8 9 a b c d e f
246 // 0 16 2 3 4 5 6 7 8 9 10 11 12 13 14 15
247 //
248 for (Index = Str; *Index != 0; Index++) {
249 switch (*Index) {
250 case '0':
251 case '2':
252 case '3':
253 case '4':
254 case '5':
255 case '6':
256 case '7':
257 case '8':
258 case '9':
259 Status = CatPrint (&MappingItem->Csd, L"%c", *Index);
260 break;
261
262 case '1':
263 Status = CatPrint (&MappingItem->Csd, L"16");
264 break;
265
266 case 'a':
267 case 'b':
268 case 'c':
269 case 'd':
270 case 'e':
271 case 'f':
272 Status = CatPrint (&MappingItem->Csd, L"1%c", *Index - 'a' + '0');
273 break;
274
275 case 'A':
276 case 'B':
277 case 'C':
278 case 'D':
279 case 'E':
280 case 'F':
281 Status = CatPrint (&MappingItem->Csd, L"1%c", *Index - 'A' + '0');
282 break;
283 }
284
285 if (EFI_ERROR (Status)) {
286 return Status;
287 }
288 }
289 } else {
290 for (Index = Str; *Index != 0; Index++) {
291 //
292 // The mapping is:
293 // 0 1 2 3 4 5 6 7 8 9 a b c d e f
294 // a b c d e f g h i j k l m n o p
295 //
296 if (*Index >= '0' && *Index <= '9') {
297 Status = CatPrint (&MappingItem->Csd, L"%c", *Index - '0' + 'a');
298 } else if (*Index >= 'a' && *Index <= 'f') {
299 Status = CatPrint (&MappingItem->Csd, L"%c", *Index - 'a' + 'k');
300 } else if (*Index >= 'A' && *Index <= 'F') {
301 Status = CatPrint (&MappingItem->Csd, L"%c", *Index - 'A' + 'k');
302 }
303
304 if (EFI_ERROR (Status)) {
305 return Status;
306 }
307 }
308 }
309
310 MappingItem->Digital = (BOOLEAN)!(MappingItem->Digital);
311
312 return (EFI_SUCCESS);
313 }
314
315 /**
316 Function to append a Guid to the mapping item.
317
318 @param[in, out] MappingItem The item to append onto.
319 @param[in] Guid The guid to append.
320
321 @retval EFI_OUT_OF_RESOURCES Out of resources.
322 @retval EFI_SUCCESS The appending was successful.
323 **/
324 EFI_STATUS
325 AppendCSDGuid (
326 DEVICE_CONSIST_MAPPING_INFO *MappingItem,
327 EFI_GUID *Guid
328 )
329 {
330 CHAR16 Buffer[64];
331
332 ASSERT (Guid != NULL && MappingItem != NULL);
333
334 UnicodeSPrint (
335 Buffer,
336 0,
337 L"%g",
338 Guid
339 );
340
341 return AppendCSDStr (MappingItem, Buffer);
342 }
343
344 /**
345 Function to compare 2 APCI device paths.
346
347 @param[in] DevicePath1 The first device path to compare.
348 @param[in] DevicePath2 The second device path to compare.
349
350 @retval 0 The device paths represent the same device.
351 @return Non zero if the devices are different, zero otherwise.
352 **/
353 INTN
354 EFIAPI
355 DevPathCompareAcpi (
356 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath1,
357 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath2
358 )
359 {
360 ACPI_HID_DEVICE_PATH *Acpi1;
361 ACPI_HID_DEVICE_PATH *Acpi2;
362
363 if (DevicePath1 == NULL || DevicePath2 == NULL) {
364 return (-2);
365 }
366
367 Acpi1 = (ACPI_HID_DEVICE_PATH *) DevicePath1;
368 Acpi2 = (ACPI_HID_DEVICE_PATH *) DevicePath2;
369 if (Acpi1->HID > Acpi2->HID || (Acpi1->HID == Acpi2->HID && Acpi1->UID > Acpi2->UID)) {
370 return 1;
371 }
372
373 if (Acpi1->HID == Acpi2->HID && Acpi1->UID == Acpi2->UID) {
374 return 0;
375 }
376
377 return -1;
378 }
379
380 /**
381 Function to compare 2 PCI device paths.
382
383 @param[in] DevicePath1 The first device path to compare.
384 @param[in] DevicePath2 The second device path to compare.
385
386 @retval 0 The device paths represent the same device.
387 @return Non zero if the devices are different, zero otherwise.
388 **/
389 INTN
390 EFIAPI
391 DevPathComparePci (
392 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath1,
393 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath2
394 )
395 {
396 PCI_DEVICE_PATH *Pci1;
397 PCI_DEVICE_PATH *Pci2;
398
399 ASSERT(DevicePath1 != NULL);
400 ASSERT(DevicePath2 != NULL);
401
402 Pci1 = (PCI_DEVICE_PATH *) DevicePath1;
403 Pci2 = (PCI_DEVICE_PATH *) DevicePath2;
404 if (Pci1->Device > Pci2->Device || (Pci1->Device == Pci2->Device && Pci1->Function > Pci2->Function)) {
405 return 1;
406 }
407
408 if (Pci1->Device == Pci2->Device && Pci1->Function == Pci2->Function) {
409 return 0;
410 }
411
412 return -1;
413 }
414
415 /**
416 Do a comparison on 2 device paths.
417
418 @param[in] DevicePath1 The first device path.
419 @param[in] DevicePath2 The second device path.
420
421 @retval 0 The 2 device paths are the same.
422 @retval <0 DevicePath2 is greater than DevicePath1.
423 @retval >0 DevicePath1 is greater than DevicePath2.
424 **/
425 INTN
426 EFIAPI
427 DevPathCompareDefault (
428 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath1,
429 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath2
430 )
431 {
432 UINTN DevPathSize1;
433 UINTN DevPathSize2;
434
435 ASSERT(DevicePath1 != NULL);
436 ASSERT(DevicePath2 != NULL);
437
438 DevPathSize1 = DevicePathNodeLength (DevicePath1);
439 DevPathSize2 = DevicePathNodeLength (DevicePath2);
440 if (DevPathSize1 > DevPathSize2) {
441 return 1;
442 } else if (DevPathSize1 < DevPathSize2) {
443 return -1;
444 } else {
445 return CompareMem (DevicePath1, DevicePath2, DevPathSize1);
446 }
447 }
448
449 /**
450 DevicePathNode must be SerialHDD Channel type and this will populate the MappingItem.
451
452 @param[in] DevicePathNode The node to get info on.
453 @param[in] MappingItem The info item to populate.
454 @param[in] DevicePath Ignored.
455
456 @retval EFI_OUT_OF_RESOURCES Out of resources.
457 @retval EFI_SUCCESS The appending was successful.
458 **/
459 EFI_STATUS
460 DevPathSerialHardDrive (
461 IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode,
462 IN DEVICE_CONSIST_MAPPING_INFO *MappingItem,
463 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
464 )
465 {
466 HARDDRIVE_DEVICE_PATH *Hd;
467
468 ASSERT(DevicePathNode != NULL);
469 ASSERT(MappingItem != NULL);
470
471 Hd = (HARDDRIVE_DEVICE_PATH *) DevicePathNode;
472 if (MappingItem->Mtd == MTDTypeUnknown) {
473 MappingItem->Mtd = MTDTypeHardDisk;
474 }
475
476 return AppendCSDNum (MappingItem, Hd->PartitionNumber);
477 }
478
479 /**
480 DevicePathNode must be SerialAtapi Channel type and this will populate the MappingItem.
481
482 @param[in] DevicePathNode The node to get info on.
483 @param[in] MappingItem The info item to populate.
484 @param[in] DevicePath Ignored.
485
486 @retval EFI_OUT_OF_RESOURCES Out of resources.
487 @retval EFI_SUCCESS The appending was successful.
488 **/
489 EFI_STATUS
490 DevPathSerialAtapi (
491 IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode,
492 IN DEVICE_CONSIST_MAPPING_INFO *MappingItem,
493 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
494 )
495 {
496 ATAPI_DEVICE_PATH *Atapi;
497
498 ASSERT(DevicePathNode != NULL);
499 ASSERT(MappingItem != NULL);
500
501 Atapi = (ATAPI_DEVICE_PATH *) DevicePathNode;
502 return AppendCSDNum (MappingItem, (Atapi->PrimarySecondary * 2 + Atapi->SlaveMaster));
503 }
504
505 /**
506 DevicePathNode must be SerialCDROM Channel type and this will populate the MappingItem.
507
508 @param[in] DevicePathNode The node to get info on.
509 @param[in] MappingItem The info item to populate.
510 @param[in] DevicePath Ignored.
511
512 @retval EFI_OUT_OF_RESOURCES Out of resources.
513 @retval EFI_SUCCESS The appending was successful.
514 **/
515 EFI_STATUS
516 DevPathSerialCdRom (
517 IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode,
518 IN DEVICE_CONSIST_MAPPING_INFO *MappingItem,
519 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
520 )
521 {
522 CDROM_DEVICE_PATH *Cd;
523
524 ASSERT(DevicePathNode != NULL);
525 ASSERT(MappingItem != NULL);
526
527 Cd = (CDROM_DEVICE_PATH *) DevicePathNode;
528 MappingItem->Mtd = MTDTypeCDRom;
529 return AppendCSDNum (MappingItem, Cd->BootEntry);
530 }
531
532 /**
533 DevicePathNode must be SerialFibre Channel type and this will populate the MappingItem.
534
535 @param[in] DevicePathNode The node to get info on.
536 @param[in] MappingItem The info item to populate.
537 @param[in] DevicePath Ignored.
538
539 @retval EFI_OUT_OF_RESOURCES Out of resources.
540 @retval EFI_SUCCESS The appending was successful.
541 **/
542 EFI_STATUS
543 DevPathSerialFibre (
544 IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode,
545 IN DEVICE_CONSIST_MAPPING_INFO *MappingItem,
546 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
547 )
548 {
549 EFI_STATUS Status;
550 FIBRECHANNEL_DEVICE_PATH *Fibre;
551
552 ASSERT(DevicePathNode != NULL);
553 ASSERT(MappingItem != NULL);
554
555 Fibre = (FIBRECHANNEL_DEVICE_PATH *) DevicePathNode;
556 Status = AppendCSDNum (MappingItem, Fibre->WWN);
557 if (!EFI_ERROR (Status)) {
558 Status = AppendCSDNum (MappingItem, Fibre->Lun);
559 }
560 return Status;
561 }
562
563 /**
564 DevicePathNode must be SerialUart type and this will populate the MappingItem.
565
566 @param[in] DevicePathNode The node to get info on.
567 @param[in] MappingItem The info item to populate.
568 @param[in] DevicePath Ignored.
569
570 @retval EFI_OUT_OF_RESOURCES Out of resources.
571 @retval EFI_SUCCESS The appending was successful.
572 **/
573 EFI_STATUS
574 DevPathSerialUart (
575 IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode,
576 IN DEVICE_CONSIST_MAPPING_INFO *MappingItem,
577 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
578 )
579 {
580 EFI_STATUS Status;
581 UART_DEVICE_PATH *Uart;
582
583 ASSERT(DevicePathNode != NULL);
584 ASSERT(MappingItem != NULL);
585
586 Uart = (UART_DEVICE_PATH *) DevicePathNode;
587 Status = AppendCSDNum (MappingItem, Uart->BaudRate);
588 if (!EFI_ERROR (Status)) {
589 Status = AppendCSDNum (MappingItem, Uart->DataBits);
590 }
591 if (!EFI_ERROR (Status)) {
592 Status = AppendCSDNum (MappingItem, Uart->Parity);
593 }
594 if (!EFI_ERROR (Status)) {
595 Status = AppendCSDNum (MappingItem, Uart->StopBits);
596 }
597 return Status;
598 }
599
600 /**
601 DevicePathNode must be SerialUSB type and this will populate the MappingItem.
602
603 @param[in] DevicePathNode The node to get info on.
604 @param[in] MappingItem The info item to populate.
605 @param[in] DevicePath Ignored.
606
607 @retval EFI_OUT_OF_RESOURCES Out of resources.
608 @retval EFI_SUCCESS The appending was successful.
609 **/
610 EFI_STATUS
611 DevPathSerialUsb (
612 IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode,
613 IN DEVICE_CONSIST_MAPPING_INFO *MappingItem,
614 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
615 )
616 {
617 USB_DEVICE_PATH *Usb;
618 EFI_USB_IO_PROTOCOL *UsbIo;
619 EFI_HANDLE TempHandle;
620 EFI_STATUS Status;
621 USB_INTERFACE_DESCRIPTOR InterfaceDesc;
622
623
624 ASSERT(DevicePathNode != NULL);
625 ASSERT(MappingItem != NULL);
626
627 Usb = (USB_DEVICE_PATH *) DevicePathNode;
628 Status = AppendCSDNum (MappingItem, Usb->ParentPortNumber);
629 if (!EFI_ERROR (Status)) {
630 Status = AppendCSDNum (MappingItem, Usb->InterfaceNumber);
631 }
632
633 if (EFI_ERROR (Status)) {
634 return Status;
635 }
636
637 if (PcdGetBool(PcdUsbExtendedDecode)) {
638 Status = gBS->LocateDevicePath( &gEfiUsbIoProtocolGuid, &DevicePath, &TempHandle );
639 UsbIo = NULL;
640 if (!EFI_ERROR(Status)) {
641 Status = gBS->OpenProtocol(TempHandle, &gEfiUsbIoProtocolGuid, (VOID**)&UsbIo, gImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
642 }
643
644 if (!EFI_ERROR(Status)) {
645 ASSERT(UsbIo != NULL);
646 Status = UsbIo->UsbGetInterfaceDescriptor(UsbIo, &InterfaceDesc);
647 if (!EFI_ERROR(Status)) {
648 if (InterfaceDesc.InterfaceClass == USB_MASS_STORE_CLASS && MappingItem->Mtd == MTDTypeUnknown) {
649 switch (InterfaceDesc.InterfaceSubClass){
650 case USB_MASS_STORE_SCSI:
651 MappingItem->Mtd = MTDTypeHardDisk;
652 break;
653 case USB_MASS_STORE_8070I:
654 case USB_MASS_STORE_UFI:
655 MappingItem->Mtd = MTDTypeFloppy;
656 break;
657 case USB_MASS_STORE_8020I:
658 MappingItem->Mtd = MTDTypeCDRom;
659 break;
660 }
661 }
662 }
663 }
664 }
665 return Status;
666 }
667
668 /**
669 DevicePathNode must be SerialVendor type and this will populate the MappingItem.
670
671 @param[in] DevicePathNode The node to get info on.
672 @param[in] MappingItem The info item to populate.
673 @param[in] DevicePath Ignored.
674
675 @retval EFI_OUT_OF_RESOURCES Out of resources.
676 @retval EFI_SUCCESS The appending was successful.
677 **/
678 EFI_STATUS
679 DevPathSerialVendor (
680 IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode,
681 IN DEVICE_CONSIST_MAPPING_INFO *MappingItem,
682 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
683 )
684 {
685 EFI_STATUS Status;
686 VENDOR_DEVICE_PATH *Vendor;
687 SAS_DEVICE_PATH *Sas;
688 UINTN TargetNameLength;
689 UINTN Index;
690 CHAR16 *Buffer;
691 CHAR16 *NewBuffer;
692
693 ASSERT(DevicePathNode != NULL);
694 ASSERT(MappingItem != NULL);
695
696 Vendor = (VENDOR_DEVICE_PATH *) DevicePathNode;
697 Status = AppendCSDGuid (MappingItem, &Vendor->Guid);
698 if (EFI_ERROR (Status)) {
699 return Status;
700 }
701
702 if (CompareGuid (&gEfiSasDevicePathGuid, &Vendor->Guid)) {
703 Sas = (SAS_DEVICE_PATH *) Vendor;
704 Status = AppendCSDNum (MappingItem, Sas->SasAddress);
705 if (!EFI_ERROR (Status)) {
706 Status = AppendCSDNum (MappingItem, Sas->Lun);
707 }
708 if (!EFI_ERROR (Status)) {
709 Status = AppendCSDNum (MappingItem, Sas->DeviceTopology);
710 }
711 if (!EFI_ERROR (Status)) {
712 Status = AppendCSDNum (MappingItem, Sas->RelativeTargetPort);
713 }
714 } else {
715 TargetNameLength = MIN(DevicePathNodeLength (DevicePathNode) - sizeof (VENDOR_DEVICE_PATH), PcdGet32(PcdShellVendorExtendedDecode));
716 if (TargetNameLength != 0) {
717 //
718 // String is 2 chars per data byte, plus NULL terminator
719 //
720 Buffer = AllocateZeroPool (((TargetNameLength * 2) + 1) * sizeof(CHAR16));
721 if (Buffer == NULL) {
722 return EFI_OUT_OF_RESOURCES;
723 }
724
725 //
726 // Build the string data
727 //
728 for (Index = 0; Index < TargetNameLength; Index++) {
729 NewBuffer = CatSPrint (Buffer, L"%02x", *((UINT8*)Vendor + sizeof (VENDOR_DEVICE_PATH) + Index));
730 if (NewBuffer == NULL) {
731 Status = EFI_OUT_OF_RESOURCES;
732 break;
733 }
734 Buffer = NewBuffer;
735 }
736
737 //
738 // Append the new data block
739 //
740 if (!EFI_ERROR (Status)) {
741 Status = AppendCSDStr (MappingItem, Buffer);
742 }
743
744 FreePool(Buffer);
745 }
746 }
747 return Status;
748 }
749
750 /**
751 DevicePathNode must be SerialLun type and this will populate the MappingItem.
752
753 @param[in] DevicePathNode The node to get info on.
754 @param[in] MappingItem The info item to populate.
755 @param[in] DevicePath Ignored.
756
757 @retval EFI_OUT_OF_RESOURCES Out of resources.
758 @retval EFI_SUCCESS The appending was successful.
759 **/
760 EFI_STATUS
761 DevPathSerialLun (
762 IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode,
763 IN DEVICE_CONSIST_MAPPING_INFO *MappingItem,
764 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
765 )
766 {
767 DEVICE_LOGICAL_UNIT_DEVICE_PATH *Lun;
768
769 ASSERT(DevicePathNode != NULL);
770 ASSERT(MappingItem != NULL);
771
772 Lun = (DEVICE_LOGICAL_UNIT_DEVICE_PATH *) DevicePathNode;
773 return AppendCSDNum (MappingItem, Lun->Lun);
774 }
775
776 /**
777 DevicePathNode must be SerialSata type and this will populate the MappingItem.
778
779 @param[in] DevicePathNode The node to get info on.
780 @param[in] MappingItem The info item to populate.
781 @param[in] DevicePath Ignored.
782
783 @retval EFI_OUT_OF_RESOURCES Out of resources.
784 @retval EFI_SUCCESS The appending was successful.
785 **/
786 EFI_STATUS
787 DevPathSerialSata (
788 IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode,
789 IN DEVICE_CONSIST_MAPPING_INFO *MappingItem,
790 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
791 )
792 {
793 EFI_STATUS Status;
794 SATA_DEVICE_PATH *Sata;
795
796 ASSERT(DevicePathNode != NULL);
797 ASSERT(MappingItem != NULL);
798
799 Sata = (SATA_DEVICE_PATH *) DevicePathNode;
800 Status = AppendCSDNum (MappingItem, Sata->HBAPortNumber);
801 if (!EFI_ERROR (Status)) {
802 Status = AppendCSDNum (MappingItem, Sata->PortMultiplierPortNumber);
803 }
804 if (!EFI_ERROR (Status)) {
805 Status = AppendCSDNum (MappingItem, Sata->Lun);
806 }
807 return Status;
808 }
809
810 /**
811 DevicePathNode must be SerialSCSI type and this will populate the MappingItem.
812
813 @param[in] DevicePathNode The node to get info on.
814 @param[in] MappingItem The info item to populate.
815 @param[in] DevicePath Ignored.
816
817 @retval EFI_OUT_OF_RESOURCES Out of resources.
818 @retval EFI_SUCCESS The appending was successful.
819 **/
820 EFI_STATUS
821 DevPathSerialIScsi (
822 IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode,
823 IN DEVICE_CONSIST_MAPPING_INFO *MappingItem,
824 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
825 )
826 {
827 EFI_STATUS Status;
828 ISCSI_DEVICE_PATH *IScsi;
829 UINT8 *IScsiTargetName;
830 CHAR16 *TargetName;
831 UINTN TargetNameLength;
832 UINTN Index;
833
834 ASSERT(DevicePathNode != NULL);
835 ASSERT(MappingItem != NULL);
836
837 Status = EFI_SUCCESS;
838
839 if (PcdGetBool(PcdShellDecodeIScsiMapNames)) {
840 IScsi = (ISCSI_DEVICE_PATH *) DevicePathNode;
841 Status = AppendCSDNum (MappingItem, IScsi->NetworkProtocol);
842 if (!EFI_ERROR (Status)) {
843 Status = AppendCSDNum (MappingItem, IScsi->LoginOption);
844 }
845 if (!EFI_ERROR (Status)) {
846 Status = AppendCSDNum (MappingItem, IScsi->Lun);
847 }
848 if (!EFI_ERROR (Status)) {
849 Status = AppendCSDNum (MappingItem, IScsi->TargetPortalGroupTag);
850 }
851 if (EFI_ERROR (Status)) {
852 return Status;
853 }
854 TargetNameLength = DevicePathNodeLength (DevicePathNode) - sizeof (ISCSI_DEVICE_PATH);
855 if (TargetNameLength > 0) {
856 TargetName = AllocateZeroPool ((TargetNameLength + 1) * sizeof (CHAR16));
857 if (TargetName == NULL) {
858 Status = EFI_OUT_OF_RESOURCES;
859 } else {
860 IScsiTargetName = (UINT8 *) (IScsi + 1);
861 for (Index = 0; Index < TargetNameLength; Index++) {
862 TargetName[Index] = (CHAR16) IScsiTargetName[Index];
863 }
864 Status = AppendCSDStr (MappingItem, TargetName);
865 FreePool (TargetName);
866 }
867 }
868 }
869 return Status;
870 }
871
872 /**
873 DevicePathNode must be SerialI20 type and this will populate the MappingItem.
874
875 @param[in] DevicePathNode The node to get info on.
876 @param[in] MappingItem The info item to populate.
877 @param[in] DevicePath Ignored.
878
879 @retval EFI_OUT_OF_RESOURCES Out of resources.
880 @retval EFI_SUCCESS The appending was successful.
881 **/
882 EFI_STATUS
883 DevPathSerialI2O (
884 IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode,
885 IN DEVICE_CONSIST_MAPPING_INFO *MappingItem,
886 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
887 )
888 {
889 I2O_DEVICE_PATH *DevicePath_I20;
890
891 ASSERT(DevicePathNode != NULL);
892 ASSERT(MappingItem != NULL);
893
894 DevicePath_I20 = (I2O_DEVICE_PATH *) DevicePathNode;
895 return AppendCSDNum (MappingItem, DevicePath_I20->Tid);
896 }
897
898 /**
899 DevicePathNode must be Mac Address type and this will populate the MappingItem.
900
901 @param[in] DevicePathNode The node to get info on.
902 @param[in] MappingItem The info item to populate.
903 @param[in] DevicePath Ignored.
904
905 @retval EFI_OUT_OF_RESOURCES Out of resources.
906 @retval EFI_SUCCESS The appending was successful.
907 **/
908 EFI_STATUS
909 DevPathSerialMacAddr (
910 IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode,
911 IN DEVICE_CONSIST_MAPPING_INFO *MappingItem,
912 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
913 )
914 {
915 MAC_ADDR_DEVICE_PATH *Mac;
916 UINTN HwAddressSize;
917 UINTN Index;
918 CHAR16 Buffer[64];
919 CHAR16 *PBuffer;
920
921 ASSERT(DevicePathNode != NULL);
922 ASSERT(MappingItem != NULL);
923
924 Mac = (MAC_ADDR_DEVICE_PATH *) DevicePathNode;
925
926 HwAddressSize = sizeof (EFI_MAC_ADDRESS);
927 if (Mac->IfType == 0x01 || Mac->IfType == 0x00) {
928 HwAddressSize = 6;
929 }
930
931 for (Index = 0, PBuffer = Buffer; Index < HwAddressSize; Index++, PBuffer += 2) {
932 UnicodeSPrint (PBuffer, 0, L"%02x", (UINTN) Mac->MacAddress.Addr[Index]);
933 }
934
935 return AppendCSDStr (MappingItem, Buffer);
936 }
937
938 /**
939 DevicePathNode must be InfiniBand type and this will populate the MappingItem.
940
941 @param[in] DevicePathNode The node to get info on.
942 @param[in] MappingItem The info item to populate.
943 @param[in] DevicePath Ignored.
944
945 @retval EFI_OUT_OF_RESOURCES Out of resources.
946 @retval EFI_SUCCESS The appending was successful.
947 **/
948 EFI_STATUS
949 DevPathSerialInfiniBand (
950 IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode,
951 IN DEVICE_CONSIST_MAPPING_INFO *MappingItem,
952 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
953 )
954 {
955 EFI_STATUS Status;
956 INFINIBAND_DEVICE_PATH *InfiniBand;
957 UINTN Index;
958 CHAR16 Buffer[64];
959 CHAR16 *PBuffer;
960
961 ASSERT(DevicePathNode != NULL);
962 ASSERT(MappingItem != NULL);
963
964 InfiniBand = (INFINIBAND_DEVICE_PATH *) DevicePathNode;
965 for (Index = 0, PBuffer = Buffer; Index < 16; Index++, PBuffer += 2) {
966 UnicodeSPrint (PBuffer, 0, L"%02x", (UINTN) InfiniBand->PortGid[Index]);
967 }
968
969 Status = AppendCSDStr (MappingItem, Buffer);
970 if (!EFI_ERROR (Status)) {
971 Status = AppendCSDNum (MappingItem, InfiniBand->ServiceId);
972 }
973 if (!EFI_ERROR (Status)) {
974 Status = AppendCSDNum (MappingItem, InfiniBand->TargetPortId);
975 }
976 if (!EFI_ERROR (Status)) {
977 Status = AppendCSDNum (MappingItem, InfiniBand->DeviceId);
978 }
979 return Status;
980 }
981
982 /**
983 DevicePathNode must be IPv4 type and this will populate the MappingItem.
984
985 @param[in] DevicePathNode The node to get info on.
986 @param[in] MappingItem The info item to populate.
987 @param[in] DevicePath Ignored.
988
989 @retval EFI_OUT_OF_RESOURCES Out of resources.
990 @retval EFI_SUCCESS The appending was successful.
991 **/
992 EFI_STATUS
993 DevPathSerialIPv4 (
994 IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode,
995 IN DEVICE_CONSIST_MAPPING_INFO *MappingItem,
996 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
997 )
998 {
999 EFI_STATUS Status;
1000 IPv4_DEVICE_PATH *Ip;
1001 CHAR16 Buffer[10];
1002
1003 ASSERT(DevicePathNode != NULL);
1004 ASSERT(MappingItem != NULL);
1005
1006 Ip = (IPv4_DEVICE_PATH *) DevicePathNode;
1007 UnicodeSPrint (
1008 Buffer,
1009 0,
1010 L"%02x%02x%02x%02x",
1011 (UINTN) Ip->LocalIpAddress.Addr[0],
1012 (UINTN) Ip->LocalIpAddress.Addr[1],
1013 (UINTN) Ip->LocalIpAddress.Addr[2],
1014 (UINTN) Ip->LocalIpAddress.Addr[3]
1015 );
1016 Status = AppendCSDStr (MappingItem, Buffer);
1017 if (!EFI_ERROR (Status)) {
1018 Status = AppendCSDNum (MappingItem, Ip->LocalPort);
1019 }
1020 if (!EFI_ERROR (Status)) {
1021 UnicodeSPrint (
1022 Buffer,
1023 0,
1024 L"%02x%02x%02x%02x",
1025 (UINTN) Ip->RemoteIpAddress.Addr[0],
1026 (UINTN) Ip->RemoteIpAddress.Addr[1],
1027 (UINTN) Ip->RemoteIpAddress.Addr[2],
1028 (UINTN) Ip->RemoteIpAddress.Addr[3]
1029 );
1030 Status = AppendCSDStr (MappingItem, Buffer);
1031 }
1032 if (!EFI_ERROR (Status)) {
1033 Status = AppendCSDNum (MappingItem, Ip->RemotePort);
1034 }
1035 return Status;
1036 }
1037
1038 /**
1039 DevicePathNode must be IPv6 type and this will populate the MappingItem.
1040
1041 @param[in] DevicePathNode The node to get info on.
1042 @param[in] MappingItem The info item to populate.
1043 @param[in] DevicePath Ignored.
1044
1045 @retval EFI_OUT_OF_RESOURCES Out of resources.
1046 @retval EFI_SUCCESS The appending was successful.
1047 **/
1048 EFI_STATUS
1049 DevPathSerialIPv6 (
1050 IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode,
1051 IN DEVICE_CONSIST_MAPPING_INFO *MappingItem,
1052 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
1053 )
1054 {
1055 EFI_STATUS Status;
1056 IPv6_DEVICE_PATH *Ip;
1057 UINTN Index;
1058 CHAR16 Buffer[64];
1059 CHAR16 *PBuffer;
1060
1061 ASSERT(DevicePathNode != NULL);
1062 ASSERT(MappingItem != NULL);
1063
1064 Ip = (IPv6_DEVICE_PATH *) DevicePathNode;
1065 for (Index = 0, PBuffer = Buffer; Index < 16; Index++, PBuffer += 2) {
1066 UnicodeSPrint (PBuffer, 0, L"%02x", (UINTN) Ip->LocalIpAddress.Addr[Index]);
1067 }
1068
1069 Status = AppendCSDStr (MappingItem, Buffer);
1070 if (!EFI_ERROR (Status)) {
1071 Status = AppendCSDNum (MappingItem, Ip->LocalPort);
1072 }
1073 if (!EFI_ERROR (Status)) {
1074 for (Index = 0, PBuffer = Buffer; Index < 16; Index++, PBuffer += 2) {
1075 UnicodeSPrint (PBuffer, 0, L"%02x", (UINTN) Ip->RemoteIpAddress.Addr[Index]);
1076 }
1077
1078 Status = AppendCSDStr (MappingItem, Buffer);
1079 }
1080 if (!EFI_ERROR (Status)) {
1081 Status = AppendCSDNum (MappingItem, Ip->RemotePort);
1082 }
1083 return Status;
1084 }
1085
1086 /**
1087 DevicePathNode must be SCSI type and this will populate the MappingItem.
1088
1089 @param[in] DevicePathNode The node to get info on.
1090 @param[in] MappingItem The info item to populate.
1091 @param[in] DevicePath Ignored.
1092
1093 @retval EFI_OUT_OF_RESOURCES Out of resources.
1094 @retval EFI_SUCCESS The appending was successful.
1095 **/
1096 EFI_STATUS
1097 DevPathSerialScsi (
1098 IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode,
1099 IN DEVICE_CONSIST_MAPPING_INFO *MappingItem,
1100 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
1101 )
1102 {
1103 EFI_STATUS Status;
1104 SCSI_DEVICE_PATH *Scsi;
1105
1106 ASSERT(DevicePathNode != NULL);
1107 ASSERT(MappingItem != NULL);
1108
1109 Scsi = (SCSI_DEVICE_PATH *) DevicePathNode;
1110 Status = AppendCSDNum (MappingItem, Scsi->Pun);
1111 if (!EFI_ERROR (Status)) {
1112 Status = AppendCSDNum (MappingItem, Scsi->Lun);
1113 }
1114 return Status;
1115 }
1116
1117 /**
1118 DevicePathNode must be 1394 type and this will populate the MappingItem.
1119
1120 @param[in] DevicePathNode The node to get info on.
1121 @param[in] MappingItem The info item to populate.
1122 @param[in] DevicePath Ignored.
1123
1124 @retval EFI_OUT_OF_RESOURCES Out of resources.
1125 @retval EFI_SUCCESS The appending was successful.
1126 **/
1127 EFI_STATUS
1128 DevPathSerial1394 (
1129 IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode,
1130 IN DEVICE_CONSIST_MAPPING_INFO *MappingItem,
1131 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
1132 )
1133 {
1134 F1394_DEVICE_PATH *DevicePath_F1394;
1135 CHAR16 Buffer[20];
1136
1137 ASSERT(DevicePathNode != NULL);
1138 ASSERT(MappingItem != NULL);
1139
1140 DevicePath_F1394 = (F1394_DEVICE_PATH *) DevicePathNode;
1141 UnicodeSPrint (Buffer, 0, L"%lx", DevicePath_F1394->Guid);
1142 return AppendCSDStr (MappingItem, Buffer);
1143 }
1144
1145 /**
1146 If the node is floppy type then populate the MappingItem.
1147
1148 @param[in] DevicePathNode The node to get info on.
1149 @param[in] MappingItem The info item to populate.
1150 @param[in] DevicePath Ignored.
1151
1152 @retval EFI_OUT_OF_RESOURCES Out of resources.
1153 @retval EFI_SUCCESS The appending was successful.
1154 **/
1155 EFI_STATUS
1156 DevPathSerialAcpi (
1157 IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode,
1158 IN DEVICE_CONSIST_MAPPING_INFO *MappingItem,
1159 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
1160 )
1161 {
1162 ACPI_HID_DEVICE_PATH *Acpi;
1163
1164 ASSERT(DevicePathNode != NULL);
1165 ASSERT(MappingItem != NULL);
1166
1167 Acpi = (ACPI_HID_DEVICE_PATH *) DevicePathNode;
1168 if ((Acpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {
1169 if (EISA_ID_TO_NUM (Acpi->HID) == 0x0604) {
1170 MappingItem->Mtd = MTDTypeFloppy;
1171 return AppendCSDNum (MappingItem, Acpi->UID);
1172 }
1173 }
1174 return EFI_SUCCESS;
1175 }
1176
1177 /**
1178 Empty function used for unknown devices.
1179
1180 @param[in] DevicePathNode Ignored.
1181 @param[in] MappingItem Ignored.
1182 @param[in] DevicePath Ignored.
1183
1184 @retval EFI_OUT_OF_RESOURCES Out of resources.
1185 @retval EFI_SUCCESS The appending was successful.
1186 **/
1187 EFI_STATUS
1188 DevPathSerialDefault (
1189 IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode,
1190 IN DEVICE_CONSIST_MAPPING_INFO *MappingItem,
1191 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
1192 )
1193 {
1194 return EFI_SUCCESS;
1195 }
1196
1197 DEV_PATH_CONSIST_MAPPING_TABLE DevPathConsistMappingTable[] = {
1198 {
1199 HARDWARE_DEVICE_PATH,
1200 HW_PCI_DP,
1201 DevPathSerialDefault,
1202 DevPathComparePci
1203 },
1204 {
1205 ACPI_DEVICE_PATH,
1206 ACPI_DP,
1207 DevPathSerialAcpi,
1208 DevPathCompareAcpi
1209 },
1210 {
1211 MESSAGING_DEVICE_PATH,
1212 MSG_ATAPI_DP,
1213 DevPathSerialAtapi,
1214 DevPathCompareDefault
1215 },
1216 {
1217 MESSAGING_DEVICE_PATH,
1218 MSG_SCSI_DP,
1219 DevPathSerialScsi,
1220 DevPathCompareDefault
1221 },
1222 {
1223 MESSAGING_DEVICE_PATH,
1224 MSG_FIBRECHANNEL_DP,
1225 DevPathSerialFibre,
1226 DevPathCompareDefault
1227 },
1228 {
1229 MESSAGING_DEVICE_PATH,
1230 MSG_1394_DP,
1231 DevPathSerial1394,
1232 DevPathCompareDefault
1233 },
1234 {
1235 MESSAGING_DEVICE_PATH,
1236 MSG_USB_DP,
1237 DevPathSerialUsb,
1238 DevPathCompareDefault
1239 },
1240 {
1241 MESSAGING_DEVICE_PATH,
1242 MSG_I2O_DP,
1243 DevPathSerialI2O,
1244 DevPathCompareDefault
1245 },
1246 {
1247 MESSAGING_DEVICE_PATH,
1248 MSG_MAC_ADDR_DP,
1249 DevPathSerialMacAddr,
1250 DevPathCompareDefault
1251 },
1252 {
1253 MESSAGING_DEVICE_PATH,
1254 MSG_IPv4_DP,
1255 DevPathSerialIPv4,
1256 DevPathCompareDefault
1257 },
1258 {
1259 MESSAGING_DEVICE_PATH,
1260 MSG_IPv6_DP,
1261 DevPathSerialIPv6,
1262 DevPathCompareDefault
1263 },
1264 {
1265 MESSAGING_DEVICE_PATH,
1266 MSG_INFINIBAND_DP,
1267 DevPathSerialInfiniBand,
1268 DevPathCompareDefault
1269 },
1270 {
1271 MESSAGING_DEVICE_PATH,
1272 MSG_UART_DP,
1273 DevPathSerialUart,
1274 DevPathCompareDefault
1275 },
1276 {
1277 MESSAGING_DEVICE_PATH,
1278 MSG_VENDOR_DP,
1279 DevPathSerialVendor,
1280 DevPathCompareDefault
1281 },
1282 {
1283 MESSAGING_DEVICE_PATH,
1284 MSG_DEVICE_LOGICAL_UNIT_DP,
1285 DevPathSerialLun,
1286 DevPathCompareDefault
1287 },
1288 {
1289 MESSAGING_DEVICE_PATH,
1290 MSG_SATA_DP,
1291 DevPathSerialSata,
1292 DevPathCompareDefault
1293 },
1294 {
1295 MESSAGING_DEVICE_PATH,
1296 MSG_ISCSI_DP,
1297 DevPathSerialIScsi,
1298 DevPathCompareDefault
1299 },
1300 {
1301 MEDIA_DEVICE_PATH,
1302 MEDIA_HARDDRIVE_DP,
1303 DevPathSerialHardDrive,
1304 DevPathCompareDefault
1305 },
1306 {
1307 MEDIA_DEVICE_PATH,
1308 MEDIA_CDROM_DP,
1309 DevPathSerialCdRom,
1310 DevPathCompareDefault
1311 },
1312 {
1313 MEDIA_DEVICE_PATH,
1314 MEDIA_VENDOR_DP,
1315 DevPathSerialVendor,
1316 DevPathCompareDefault
1317 },
1318 {
1319 0,
1320 0,
1321 NULL,
1322 NULL
1323 }
1324 };
1325
1326 /**
1327 Function to determine if a device path node is Hi or not.
1328
1329 @param[in] DevicePathNode The node to check.
1330
1331 @retval TRUE The node is Hi.
1332 @retval FALSE The node is not Hi.
1333 **/
1334 BOOLEAN
1335 EFIAPI
1336 IsHIDevicePathNode (
1337 IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode
1338 )
1339 {
1340 ACPI_HID_DEVICE_PATH *Acpi;
1341
1342 ASSERT(DevicePathNode != NULL);
1343
1344 if (DevicePathNode->Type == HARDWARE_DEVICE_PATH) {
1345 return TRUE;
1346 }
1347
1348 if (DevicePathNode->Type == ACPI_DEVICE_PATH) {
1349 Acpi = (ACPI_HID_DEVICE_PATH *) DevicePathNode;
1350 switch (EISA_ID_TO_NUM (Acpi->HID)) {
1351 case 0x0301:
1352 case 0x0401:
1353 case 0x0501:
1354 case 0x0604:
1355 return FALSE;
1356 }
1357
1358 return TRUE;
1359 }
1360
1361 return FALSE;
1362 }
1363
1364 /**
1365 Function to convert a standard device path structure into a Hi version.
1366
1367 @param[in] DevicePath The device path to convert.
1368
1369 @return the device path portion that is Hi.
1370 **/
1371 EFI_DEVICE_PATH_PROTOCOL *
1372 EFIAPI
1373 GetHIDevicePath (
1374 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
1375 )
1376 {
1377 UINTN NonHIDevicePathNodeCount;
1378 UINTN Index;
1379 EFI_DEV_PATH Node;
1380 EFI_DEVICE_PATH_PROTOCOL *HIDevicePath;
1381 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
1382
1383 ASSERT(DevicePath != NULL);
1384
1385 NonHIDevicePathNodeCount = 0;
1386
1387 HIDevicePath = AllocateZeroPool (sizeof (EFI_DEVICE_PATH_PROTOCOL));
1388 SetDevicePathEndNode (HIDevicePath);
1389
1390 Node.DevPath.Type = END_DEVICE_PATH_TYPE;
1391 Node.DevPath.SubType = END_INSTANCE_DEVICE_PATH_SUBTYPE;
1392 Node.DevPath.Length[0] = (UINT8)sizeof (EFI_DEVICE_PATH_PROTOCOL);
1393 Node.DevPath.Length[1] = 0;
1394
1395 while (!IsDevicePathEnd (DevicePath)) {
1396 if (IsHIDevicePathNode (DevicePath)) {
1397 for (Index = 0; Index < NonHIDevicePathNodeCount; Index++) {
1398 TempDevicePath = AppendDevicePathNode (HIDevicePath, &Node.DevPath);
1399 FreePool (HIDevicePath);
1400 HIDevicePath = TempDevicePath;
1401 }
1402
1403 TempDevicePath = AppendDevicePathNode (HIDevicePath, DevicePath);
1404 FreePool (HIDevicePath);
1405 HIDevicePath = TempDevicePath;
1406 } else {
1407 NonHIDevicePathNodeCount++;
1408 }
1409 //
1410 // Next device path node
1411 //
1412 DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) NextDevicePathNode (DevicePath);
1413 }
1414
1415 return HIDevicePath;
1416 }
1417
1418 /**
1419 Function to walk the device path looking for a dumpable node.
1420
1421 @param[in] MappingItem The Item to fill with data.
1422 @param[in] DevicePath The path of the item to get data on.
1423
1424 @return EFI_SUCCESS Always returns success.
1425 **/
1426 EFI_STATUS
1427 EFIAPI
1428 GetDeviceConsistMappingInfo (
1429 IN DEVICE_CONSIST_MAPPING_INFO *MappingItem,
1430 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
1431 )
1432 {
1433 EFI_STATUS Status;
1434 SERIAL_DECODE_FUNCTION SerialFun;
1435 UINTN Index;
1436 EFI_DEVICE_PATH_PROTOCOL *OriginalDevicePath;
1437
1438 ASSERT(DevicePath != NULL);
1439 ASSERT(MappingItem != NULL);
1440
1441 SetMem (&MappingItem->Csd, sizeof (POOL_PRINT), 0);
1442 OriginalDevicePath = DevicePath;
1443
1444 while (!IsDevicePathEnd (DevicePath)) {
1445 //
1446 // Find the handler to dump this device path node and
1447 // initialize with generic function in case nothing is found
1448 //
1449 for (SerialFun = DevPathSerialDefault, Index = 0; DevPathConsistMappingTable[Index].SerialFun != NULL; Index += 1) {
1450
1451 if (DevicePathType (DevicePath) == DevPathConsistMappingTable[Index].Type &&
1452 DevicePathSubType (DevicePath) == DevPathConsistMappingTable[Index].SubType
1453 ) {
1454 SerialFun = DevPathConsistMappingTable[Index].SerialFun;
1455 break;
1456 }
1457 }
1458
1459 Status = SerialFun (DevicePath, MappingItem, OriginalDevicePath);
1460 if (EFI_ERROR (Status)) {
1461 SHELL_FREE_NON_NULL (MappingItem->Csd.Str);
1462 return Status;
1463 }
1464
1465 //
1466 // Next device path node
1467 //
1468 DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) NextDevicePathNode (DevicePath);
1469 }
1470
1471 return EFI_SUCCESS;
1472 }
1473
1474 /**
1475 Function to initialize the table for creating consistent map names.
1476
1477 @param[out] Table The pointer to pointer to pointer to DevicePathProtocol object.
1478
1479 @retval EFI_SUCCESS The table was created successfully.
1480 **/
1481 EFI_STATUS
1482 EFIAPI
1483 ShellCommandConsistMappingInitialize (
1484 OUT EFI_DEVICE_PATH_PROTOCOL ***Table
1485 )
1486 {
1487 EFI_HANDLE *HandleBuffer;
1488 UINTN HandleNum;
1489 UINTN HandleLoop;
1490 EFI_DEVICE_PATH_PROTOCOL **TempTable;
1491 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
1492 EFI_DEVICE_PATH_PROTOCOL *HIDevicePath;
1493 EFI_BLOCK_IO_PROTOCOL *BlockIo;
1494 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *SimpleFileSystem;
1495 UINTN Index;
1496 EFI_STATUS Status;
1497
1498 HandleBuffer = NULL;
1499
1500 Status = gBS->LocateHandleBuffer (
1501 ByProtocol,
1502 &gEfiDevicePathProtocolGuid,
1503 NULL,
1504 &HandleNum,
1505 &HandleBuffer
1506 );
1507 ASSERT_EFI_ERROR(Status);
1508
1509 TempTable = AllocateZeroPool ((HandleNum + 1) * sizeof (EFI_DEVICE_PATH_PROTOCOL *));
1510 if (TempTable == NULL) {
1511 return EFI_OUT_OF_RESOURCES;
1512 }
1513
1514 for (HandleLoop = 0 ; HandleLoop < HandleNum ; HandleLoop++) {
1515 DevicePath = DevicePathFromHandle (HandleBuffer[HandleLoop]);
1516 if (DevicePath == NULL) {
1517 continue;
1518 }
1519
1520 HIDevicePath = GetHIDevicePath (DevicePath);
1521 if (HIDevicePath == NULL) {
1522 continue;
1523 }
1524
1525 Status = gBS->HandleProtocol( HandleBuffer[HandleLoop],
1526 &gEfiBlockIoProtocolGuid,
1527 (VOID **)&BlockIo
1528 );
1529 if (EFI_ERROR(Status)) {
1530 Status = gBS->HandleProtocol( HandleBuffer[HandleLoop],
1531 &gEfiSimpleFileSystemProtocolGuid,
1532 (VOID **)&SimpleFileSystem
1533 );
1534 if (EFI_ERROR(Status)) {
1535 FreePool (HIDevicePath);
1536 continue;
1537 }
1538 }
1539
1540 for (Index = 0; TempTable[Index] != NULL; Index++) {
1541 if (DevicePathCompare (&TempTable[Index], &HIDevicePath) == 0) {
1542 FreePool (HIDevicePath);
1543 break;
1544 }
1545 }
1546
1547 if (TempTable[Index] == NULL) {
1548 TempTable[Index] = HIDevicePath;
1549 }
1550 }
1551
1552 for (Index = 0; TempTable[Index] != NULL; Index++);
1553 PerformQuickSort(TempTable, Index, sizeof(EFI_DEVICE_PATH_PROTOCOL*), DevicePathCompare);
1554 *Table = TempTable;
1555
1556 if (HandleBuffer != NULL) {
1557 FreePool (HandleBuffer);
1558 }
1559
1560 return EFI_SUCCESS;
1561 }
1562
1563 /**
1564 Function to uninitialize the table for creating consistent map names.
1565
1566 The parameter must have been received from ShellCommandConsistMappingInitialize.
1567
1568 @param[out] Table The pointer to pointer to DevicePathProtocol object.
1569
1570 @retval EFI_SUCCESS The table was deleted successfully.
1571 **/
1572 EFI_STATUS
1573 EFIAPI
1574 ShellCommandConsistMappingUnInitialize (
1575 EFI_DEVICE_PATH_PROTOCOL **Table
1576 )
1577 {
1578 UINTN Index;
1579
1580 ASSERT(Table != NULL);
1581
1582 for (Index = 0; Table[Index] != NULL; Index++) {
1583 FreePool (Table[Index]);
1584 }
1585
1586 FreePool (Table);
1587 return EFI_SUCCESS;
1588 }
1589
1590 /**
1591 Create a consistent mapped name for the device specified by DevicePath
1592 based on the Table.
1593
1594 This must be called after ShellCommandConsistMappingInitialize() and
1595 before ShellCommandConsistMappingUnInitialize() is called.
1596
1597 @param[in] DevicePath The pointer to the dev path for the device.
1598 @param[in] Table The Table of mapping information.
1599
1600 @retval NULL A consistent mapped name could not be created.
1601 @return A pointer to a string allocated from pool with the device name.
1602 **/
1603 CHAR16 *
1604 EFIAPI
1605 ShellCommandConsistMappingGenMappingName (
1606 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
1607 IN EFI_DEVICE_PATH_PROTOCOL **Table
1608 )
1609 {
1610 EFI_STATUS Status;
1611 POOL_PRINT Str;
1612 DEVICE_CONSIST_MAPPING_INFO MappingInfo;
1613 EFI_DEVICE_PATH_PROTOCOL *HIDevicePath;
1614 UINTN Index;
1615 CHAR16 *NewStr;
1616
1617 ASSERT(DevicePath != NULL);
1618 ASSERT(Table != NULL);
1619
1620 HIDevicePath = GetHIDevicePath (DevicePath);
1621 if (HIDevicePath == NULL) {
1622 return NULL;
1623 }
1624
1625 for (Index = 0; Table[Index] != NULL; Index++) {
1626 if (DevicePathCompare (&Table[Index], &HIDevicePath) == 0) {
1627 break;
1628 }
1629 }
1630
1631 FreePool (HIDevicePath);
1632 if (Table[Index] == NULL) {
1633 return NULL;
1634 }
1635
1636 MappingInfo.Hi = Index;
1637 MappingInfo.Mtd = MTDTypeUnknown;
1638 MappingInfo.Digital = FALSE;
1639
1640 Status = GetDeviceConsistMappingInfo (&MappingInfo, DevicePath);
1641 if (EFI_ERROR (Status)) {
1642 return NULL;
1643 }
1644
1645 SetMem (&Str, sizeof (Str), 0);
1646 for (Index = 0; mMTDName[Index].MTDType != MTDTypeEnd; Index++) {
1647 if (MappingInfo.Mtd == mMTDName[Index].MTDType) {
1648 break;
1649 }
1650 }
1651
1652 if (mMTDName[Index].MTDType != MTDTypeEnd) {
1653 Status = CatPrint (&Str, L"%s", mMTDName[Index].Name);
1654 }
1655
1656 if (!EFI_ERROR (Status)) {
1657 Status = CatPrint (&Str, L"%d", (UINTN) MappingInfo.Hi);
1658 }
1659 if (!EFI_ERROR (Status) && MappingInfo.Csd.Str != NULL) {
1660 Status = CatPrint (&Str, L"%s", MappingInfo.Csd.Str);
1661 FreePool (MappingInfo.Csd.Str);
1662 }
1663
1664 if (!EFI_ERROR (Status) && Str.Str != NULL) {
1665 Status = CatPrint (&Str, L":");
1666 }
1667 if (EFI_ERROR (Status)) {
1668 SHELL_FREE_NON_NULL (Str.Str);
1669 return NULL;
1670 }
1671
1672 NewStr = ReallocatePool (Str.Len * sizeof (CHAR16), (Str.Len + 1) * sizeof (CHAR16), Str.Str);
1673 if (NewStr == NULL) {
1674 SHELL_FREE_NON_NULL (Str.Str);
1675 return (NULL);
1676 }
1677 NewStr[Str.Len] = CHAR_NULL;
1678 return NewStr;
1679 }
1680
1681 /**
1682 Function to search the list of mappings for the node on the list based on the key.
1683
1684 @param[in] MapKey String Key to search for on the map
1685
1686 @return the node on the list.
1687 **/
1688 SHELL_MAP_LIST *
1689 EFIAPI
1690 ShellCommandFindMapItem (
1691 IN CONST CHAR16 *MapKey
1692 )
1693 {
1694 SHELL_MAP_LIST *MapListItem;
1695
1696 for ( MapListItem = (SHELL_MAP_LIST *)GetFirstNode(&gShellMapList.Link)
1697 ; !IsNull(&gShellMapList.Link, &MapListItem->Link)
1698 ; MapListItem = (SHELL_MAP_LIST *)GetNextNode(&gShellMapList.Link, &MapListItem->Link)
1699 ){
1700 if (gUnicodeCollation->StriColl(gUnicodeCollation,MapListItem->MapName,(CHAR16*)MapKey) == 0) {
1701 return (MapListItem);
1702 }
1703 }
1704 return (NULL);
1705 }
1706
1707