ReactOS 0.4.15-dev-7906-g1b85a5f
efiemu.c
Go to the documentation of this file.
1/*
2 * COPYRIGHT: See COPYING.ARM in the top level directory
3 * PROJECT: ReactOS UEFI Boot Manager
4 * FILE: boot/environ/app/bootmgr/efiemu.c
5 * PURPOSE: UEFI Entrypoint for Boot Manager
6 * PROGRAMMER: Alex Ionescu (alex.ionescu@reactos.org)
7 */
8
9/* INCLUDES ******************************************************************/
10
11#include "bootmgr.h"
12
13/* DATA STRUCTURES ***********************************************************/
14
16{
22
23/* DATA VARIABLES ************************************************************/
24
26
27/* FUNCTIONS *****************************************************************/
28
29/*++
30 * @name AhCreateLoadOptionsList
31 *
32 * The AhCreateLoadOptionsList routine
33 *
34 * @param CommandLine
35 * UEFI Image Handle for the current loaded application.
36 *
37 * @param BootOptions
38 * Pointer to the UEFI System Table.
39 *
40 * @param MaximumLength
41 * Pointer to the UEFI System Table.
42 *
43 * @param OptionSize
44 * Pointer to the UEFI System Table.
45 *
46 * @param PreviousOption
47 * Pointer to the UEFI System Table.
48 *
49 * @param PreviousOptionSize
50 * Pointer to the UEFI System Table.
51 *
52 * @return None
53 *
54 *--*/
57 _In_ PWCHAR CommandLine,
60 _Out_ PULONG OptionSize,
61 _In_ PBL_BCD_OPTION* PreviousOption,
62 _In_ PULONG PreviousOptionSize
63 )
64{
66}
67
68/*++
69 * @name EfiInitpAppendPathString
70 *
71 * The EfiInitpAppendPathString routine
72 *
73 * @param DestinationPath
74 * UEFI Image Handle for the current loaded application.
75 *
76 * @param RemainingSize
77 * Pointer to the UEFI System Table.
78 *
79 * @param AppendPath
80 * Pointer to the UEFI System Table.
81 *
82 * @param AppendLength
83 * Pointer to the UEFI System Table.
84 *
85 * @param BytesAppended
86 * Pointer to the UEFI System Table.
87 *
88 * @return None
89 *
90 *--*/
93 _In_ PWCHAR PathString,
95 _In_ PWCHAR NewPathString,
96 _In_ ULONG NewPathLength,
98 )
99{
101 ULONG FinalPathLength;
102
103 /* We deal in Unicode, validate the length */
104 if (NewPathLength & 1)
105 {
107 }
108
109 /* Is the new element at least a character? */
111 if (NewPathLength >= sizeof(WCHAR))
112 {
113 /* Is the last character already a NULL character? */
114 if (NewPathString[(NewPathLength - sizeof(WCHAR)) / sizeof(WCHAR)] ==
116 {
117 /* Then we won't need to count it */
118 NewPathLength -= sizeof(UNICODE_NULL);
119 }
120
121 /* Was it more than just a NULL character? */
122 if (NewPathLength >= sizeof(WCHAR))
123 {
124 /* Yep -- but does it have a separator? */
125 if (*NewPathString == OBJ_NAME_PATH_SEPARATOR)
126 {
127 /* Skip it, we'll add our own later */
128 NewPathString++;
129 NewPathLength -= sizeof(OBJ_NAME_PATH_SEPARATOR);
130 }
131
132 /* Was it more than just a separator? */
133 if (NewPathLength >= sizeof(WCHAR))
134 {
135 /* Yep -- but does it end with a separator? */
136 if (NewPathString[(NewPathLength - sizeof(WCHAR)) / sizeof(WCHAR)] ==
138 {
139 /* That's something else we won't need for now */
140 NewPathLength -= sizeof(OBJ_NAME_PATH_SEPARATOR);
141 }
142 }
143 }
144 }
145
146 /* Check if anything needs to be appended after all */
147 if (NewPathLength != 0)
148 {
149 /* We will append the length of the new path element, plus a separator */
150 FinalPathLength = NewPathLength + sizeof(OBJ_NAME_PATH_SEPARATOR);
151 if (MaximumLength >= FinalPathLength)
152 {
153 /* Add a separator to the existing path*/
154 *PathString = OBJ_NAME_PATH_SEPARATOR;
155
156 /* Followed by the new path element */
157 RtlCopyMemory(PathString + 1, NewPathString, NewPathLength);
158
159 /* Return the number of bytes appended */
160 *ResultLength = FinalPathLength;
161 }
162 else
163 {
164 /* There's not enough space to do this */
166 }
167 }
168 else
169 {
170 /* Nothing to append */
171 *ResultLength = 0;
172 }
173
174 return Status;
175}
176
177/*++
178 * @name EfiInitpConvertEfiDevicePath
179 *
180 * The EfiInitpConvertEfiDevicePath routine
181 *
182 * @param DevicePath
183 * UEFI Image Handle for the current loaded application.
184 *
185 * @param DeviceType
186 * Pointer to the UEFI System Table.
187 *
188 * @param Option
189 * Pointer to the UEFI System Table.
190 *
191 * @param MaximumLength
192 * Pointer to the UEFI System Table.
193 *
194 * @return None
195 *
196 *--*/
199 _In_ EFI_DEVICE_PATH_PROTOCOL *DevicePath,
201 _In_ PBL_BCD_OPTION Option,
203 )
204{
205 ULONG BytesAppended, DataSize, StringLength;
206 PWCHAR StringEntry, PathString;
209
210 /* Make sure we have enough space for the option */
211 if (MaximumLength < sizeof(*Option))
212 {
214 }
215
216 /* Set the initial size of the option, and consume from our buffer */
217 DataSize = sizeof(*Option);
218 MaximumLength -= sizeof(*Option);
219
220 /* Zero out and fill the option header */
221 RtlZeroMemory(Option, DataSize);
222 Option->Type = PathType;
223 Option->DataOffset = sizeof(*Option);
224
225 /* Extract the string option */
226 StringEntry = (PWCHAR)(Option + 1);
227 PathString = StringEntry;
228
229 /* Start parsing the device path */
230 FilePath = (FILEPATH_DEVICE_PATH*)DevicePath;
232 {
233 /* Is this a file path? */
234 if ((FilePath->Header.Type == MEDIA_DEVICE_PATH) &&
235 (FilePath->Header.SubType == MEDIA_FILEPATH_DP))
236 {
237 /* Get the length of the file path string, avoiding overflow */
238 StringLength = DevicePathNodeLength(FilePath) -
240 if (StringLength < (ULONG)FIELD_OFFSET(FILEPATH_DEVICE_PATH, PathName))
241 {
243 goto Quickie;
244 }
245
246 /* Append this path string to the current path string */
247 Status = EfiInitpAppendPathString(PathString,
249 FilePath->PathName,
250 StringLength,
251 &BytesAppended);
252 if (!NT_SUCCESS(Status))
253 {
254 return Status;
255 }
256
257 /* Increase the size of the data, consume buffer space */
258 DataSize += BytesAppended;
259 MaximumLength -= BytesAppended;
260
261 /* Move to the next path string */
262 PathString = (PWCHAR)((ULONG_PTR)PathString + BytesAppended);
263 }
264
265 /* Move to the next path node */
267 }
268
269 /* Check if we still have space for a NULL-terminator */
270 if (MaximumLength < sizeof(UNICODE_NULL))
271 {
273 goto Quickie;
274 }
275
276 /* We do -- NULL-terminate the string */
277 *PathString = UNICODE_NULL;
278 DataSize += sizeof(UNICODE_NULL);
279
280 /* Check if all of this has amounted to a single NULL-char */
281 if (PathString == StringEntry)
282 {
283 /* Then this option is empty */
284 Option->Empty = TRUE;
285 }
286
287 /* Set the final size of the option */
288 Option->DataSize = DataSize;
289
290Quickie:
291 return STATUS_SUCCESS;
292}
293
294/*++
295 * @name EfiInitpGetDeviceNode
296 *
297 * The EfiInitpGetDeviceNode routine
298 *
299 * @param DevicePath
300 * UEFI Image Handle for the current loaded application.
301 *
302 * @return None
303 *
304 *--*/
308 )
309{
310 EFI_DEVICE_PATH_PROTOCOL* NextPath;
311
312 /* Check if we hit the end terminator */
313 if (IsDevicePathEndType(DevicePath))
314 {
315 return DevicePath;
316 }
317
318 /* Loop each device path, until we get to the end or to a file path device node */
319 for ((NextPath = NextDevicePathNode(DevicePath));
320 !(IsDevicePathEndType(NextPath)) && ((NextPath->Type != MEDIA_DEVICE_PATH) ||
321 (NextPath->SubType != MEDIA_FILEPATH_DP));
322 (NextPath = NextDevicePathNode(NextPath)))
323 {
324 /* Keep iterating down */
325 DevicePath = NextPath;
326 }
327
328 /* Return the path found */
329 return DevicePath;
330}
331
332/*++
333 * @name EfiInitTranslateDevicePath
334 *
335 * The EfiInitTranslateDevicePath routine
336 *
337 * @param DevicePath
338 * UEFI Image Handle for the current loaded application.
339 *
340 * @param DeviceEntry
341 * Pointer to the UEFI System Table.
342 *
343 * @return None
344 *
345 *--*/
348 _In_ EFI_DEVICE_PATH_PROTOCOL *DevicePath,
349 _In_ PBL_DEVICE_DESCRIPTOR DeviceEntry
350 )
351{
354 MEMMAP_DEVICE_PATH* MemDevicePath;
355 ACPI_HID_DEVICE_PATH *AcpiPath;
356 HARDDRIVE_DEVICE_PATH *DiskPath;
357
358 /* Assume failure */
360
361 /* Set size first */
362 DeviceEntry->Size = sizeof(*DeviceEntry);
363
364 /* Check if we are booting from a RAM Disk */
365 if ((DevicePath->Type == HARDWARE_DEVICE_PATH) &&
366 (DevicePath->SubType == HW_MEMMAP_DP))
367 {
368 /* Get the EFI data structure matching this */
369 MemDevicePath = (MEMMAP_DEVICE_PATH*)DevicePath;
370
371 /* Set the boot library specific device types */
372 DeviceEntry->DeviceType = LocalDevice;
373 DeviceEntry->Local.Type = RamDiskDevice;
374
375 /* Extract the base, size, and offset */
376 DeviceEntry->Local.RamDisk.ImageBase.QuadPart = MemDevicePath->StartingAddress;
377 DeviceEntry->Local.RamDisk.ImageSize.QuadPart = MemDevicePath->EndingAddress -
378 MemDevicePath->StartingAddress;
379 DeviceEntry->Local.RamDisk.ImageOffset = 0;
380 return STATUS_SUCCESS;
381 }
382
383 /* Otherwise, check what kind of device node this is */
384 DeviceNode = EfiInitpGetDeviceNode(DevicePath);
385 switch (DeviceNode->Type)
386 {
387 /* ACPI */
388 case ACPI_DEVICE_PATH:
389
390 /* We only support floppy drives */
391 AcpiPath = (ACPI_HID_DEVICE_PATH*)DeviceNode;
392 if ((AcpiPath->HID != EISA_PNP_ID(0x604)) &&
393 (AcpiPath->HID != EISA_PNP_ID(0x700)))
394 {
395 return Status;
396 }
397
398 /* Set the boot library specific device types */
399 DeviceEntry->DeviceType = LocalDevice;
400 DeviceEntry->Local.Type = FloppyDevice;
401
402 /* The ACPI UID is the drive number */
403 DeviceEntry->Local.FloppyDisk.DriveNumber = AcpiPath->UID;
404 return STATUS_SUCCESS;
405
406 /* Network, ATAPI, SCSI, USB */
408
409 /* Check if it's network */
410 if ((DeviceNode->SubType == MSG_MAC_ADDR_DP) ||
411 (DeviceNode->SubType == MSG_IPv4_DP))
412 {
413 /* Set the boot library specific device types */
414 DeviceEntry->DeviceType = UdpDevice;
415 DeviceEntry->Remote.Unknown = 256;
416 return STATUS_SUCCESS;
417 }
418
419 /* Other types should come in as MEDIA_DEVICE_PATH -- Windows assumes this is a floppy */
420 DeviceEntry->DeviceType = DiskDevice;
421 DeviceEntry->Local.Type = FloppyDevice;
422 DeviceEntry->Local.FloppyDisk.DriveNumber = 0;
423 return STATUS_SUCCESS;
424
425 /* Disk or CDROM */
427
428 /* Extract the disk path and check if it's a physical disk */
430 if (DeviceNode->SubType == MEDIA_HARDDRIVE_DP)
431 {
432 /* Check if this is an MBR partition */
433 if (DiskPath->SignatureType == SIGNATURE_TYPE_MBR)
434 {
435 /* Set that this is a local partition */
436 DeviceEntry->DeviceType = LegacyPartitionDevice;
437 DeviceEntry->Partition.Disk.Type = LocalDevice;
438
439 DeviceEntry->Partition.Disk.HardDisk.PartitionType = MbrPartition;
440 DeviceEntry->Partition.Disk.HardDisk.Mbr.PartitionSignature =
441 *(PULONG)&DiskPath->Signature[0];
442 DeviceEntry->Partition.Mbr.PartitionNumber = DiskPath->PartitionNumber;
443 return STATUS_SUCCESS;
444 }
445
446 /* Check if it's a GPT partition */
447 if (DiskPath->SignatureType == SIGNATURE_TYPE_GUID)
448 {
449 /* Set that this is a local disk */
450 DeviceEntry->DeviceType = PartitionDevice;
451 DeviceEntry->Partition.Disk.Type = LocalDevice;
452
453 /* Set GPT partition ID */
454 DeviceEntry->Partition.Disk.HardDisk.PartitionType = GptPartition;
455
456 /* Copy the signature GUID */
457 RtlCopyMemory(&DeviceEntry->Partition.Gpt.PartitionGuid,
458 DiskPath->Signature,
459 sizeof(GUID));
460
461 DeviceEntry->Flags |= 4u;
462 return STATUS_SUCCESS;
463 }
464
465 /* Otherwise, raw boot is not supported */
466 DeviceEntry->DeviceType = PartitionDevice;
467 DeviceEntry->Partition.Disk.Type = LocalDevice;
468 DeviceEntry->Partition.Disk.HardDisk.PartitionType = RawPartition;
469 DeviceEntry->Partition.Disk.HardDisk.Raw.DiskNumber = 0;
470 }
471 else if (DeviceNode->SubType == MEDIA_CDROM_DP)
472 {
473 /* Set the right type for a CDROM */
474 DeviceEntry->DeviceType = DiskDevice;
475 DeviceEntry->Local.Type = CdRomDevice;
476
477 /* Set the drive number to zero */
478 DeviceEntry->Local.FloppyDisk.DriveNumber = 0;
479 return STATUS_SUCCESS;
480 }
481
482 /* Fail anything else */
483 default:
484 break;
485 }
486
487 /* Return here only on failure */
488 return Status;
489}
490
491/*++
492 * @name EfiInitpConvertEfiDevicePath
493 *
494 * The EfiInitpConvertEfiDevicePath routine
495 *
496 * @param DevicePath
497 * UEFI Image Handle for the current loaded application.
498 *
499 * @param DeviceType
500 * Pointer to the UEFI System Table.
501 *
502 * @param Option
503 * Pointer to the UEFI System Table.
504 *
505 * @param MaximumLength
506 * Pointer to the UEFI System Table.
507 *
508 * @return None
509 *
510 *--*/
513 _In_ EFI_DEVICE_PATH_PROTOCOL *DevicePath,
515 _In_ PBL_BCD_OPTION Option,
517 )
518{
519 PBCD_DEVICE_OPTION BcdDevice;
521
522 /* Make sure we have enough space for the option */
523 if (MaximumLength < sizeof(*Option))
524 {
526 goto Quickie;
527 }
528
529 /* Zero out the option */
530 RtlZeroMemory(Option, sizeof(*Option));
531
532 /* Make sure we have enough space for the device entry */
533 if ((MaximumLength - sizeof(*Option)) <
535 {
537 goto Quickie;
538 }
539
540 /* Fill it out */
541 BcdDevice = (PBCD_DEVICE_OPTION)(Option + 1);
543 &BcdDevice->DeviceDescriptor);
544 if (!NT_SUCCESS(Status))
545 {
546 goto Quickie;
547 }
548
549 /* Fill out the rest of the option structure */
550 Option->DataOffset = sizeof(*Option);
551 Option->Type = DeviceType;
552 Option->DataSize = FIELD_OFFSET(BCD_DEVICE_OPTION, DeviceDescriptor) +
553 BcdDevice->DeviceDescriptor.Size;
555
556Quickie:
557 return Status;
558}
559
560/*++
561 * @name EfiInitpCreateApplicationEntry
562 *
563 * The EfiInitpCreateApplicationEntry routine
564 *
565 * @param SystemTable
566 * UEFI Image Handle for the current loaded application.
567 *
568 * @param Entry
569 * Pointer to the UEFI System Table.
570 *
571 * @param MaximumLength
572 * Pointer to the UEFI System Table.
573 *
574 * @param DevicePath
575 * Pointer to the UEFI System Table.
576 *
577 * @param FilePath
578 * Pointer to the UEFI System Table.
579 *
580 * @param LoadOptions
581 * Pointer to the UEFI System Table.
582 *
583 * @param LoadOptionsSize
584 * Pointer to the UEFI System Table.
585 *
586 * @param Flags
587 * Pointer to the UEFI System Table.
588 *
589 * @param ResultLength
590 * Pointer to the UEFI System Table.
591 *
592 * @param AppEntryDevice
593 * Pointer to the UEFI System Table.
594 *
595 * @return None
596 *
597 *--*/
598VOID
600 __in EFI_SYSTEM_TABLE *SystemTable,
603 __in EFI_DEVICE_PATH *DevicePath,
605 __in PWCHAR LoadOptions,
606 __in ULONG LoadOptionsSize,
609 __out PBL_DEVICE_DESCRIPTOR *AppEntryDevice
610 )
611{
612 PBL_WINDOWS_LOAD_OPTIONS WindowsOptions;
613 PWCHAR ObjectString, CommandLine;
614 PBL_BCD_OPTION Option, PreviousOption;
615 ULONG HeaderSize, TotalOptionSize, Size, CommandLineSize, RemainingSize;
618 GUID ObjectGuid;
619 PBCD_DEVICE_OPTION BcdDevice;
620 BOOLEAN HaveBinaryOptions, HaveGuid;
622 EFI_DEVICE_PATH *OsDevicePath;
623
624 /* Initialize everything */
625 TotalOptionSize = 0;
626 *AppEntryDevice = NULL;
627 HeaderSize = 0;
628
629 /* Check if the load options are in binary Windows format */
630 WindowsOptions = (PBL_WINDOWS_LOAD_OPTIONS)LoadOptions;
631 if ((WindowsOptions != NULL) &&
632 (LoadOptionsSize >= sizeof(BL_WINDOWS_LOAD_OPTIONS)) &&
633 (WindowsOptions->Length >= sizeof(BL_WINDOWS_LOAD_OPTIONS)) &&
634 !(strncmp(WindowsOptions->Signature, "WINDOWS", 7)))
635 {
636 /* They are, so firmware must have loaded us -- extract arguments */
637 CommandLine = WindowsOptions->LoadOptions;
638 CommandLineSize = LoadOptionsSize - FIELD_OFFSET(BL_WINDOWS_LOAD_OPTIONS,
639 LoadOptions);
640
641 /* Remember that we used binary options */
642 HaveBinaryOptions = TRUE;
643 }
644 else
645 {
646 /* Nope -- so treat them as raw command-line options */
647 CommandLine = LoadOptions;
648 CommandLineSize = LoadOptionsSize;
649
650 /* No binary options */
651 HaveBinaryOptions = FALSE;
652 }
653
654 /* EFI uses UTF-16LE, like NT, so convert to characters */
655 CommandLineSize /= sizeof(WCHAR);
656 if (CommandLineSize != 0)
657 {
658 /* And check if the options are not NULL-terminated */
659 if (wcsnlen(CommandLine, CommandLineSize) == CommandLineSize)
660 {
661 /* NULL-terminate them */
662 CommandLine[CommandLineSize - 1] = UNICODE_NULL;
663 }
664 }
665
666 /* Begin by making sure we at least have space for the app entry header */
667 RemainingSize = MaximumLength;
668 if (RemainingSize < sizeof(BL_APPLICATION_ENTRY))
669 {
671 goto Quickie;
672 }
673
674 /* On exit, return that we've at least consumed this much */
675 HeaderSize = FIELD_OFFSET(BL_APPLICATION_ENTRY, BcdData);
676
677 /* Zero out the header, and write down the signature */
680
681 /* Check if a BCD object was passed on the command-line */
682 ObjectString = wcsstr(CommandLine, L"BCDOBJECT=");
683 if (ObjectString != NULL)
684 {
685 /* Convert the BCD object to a GUID */
686 RtlInitUnicodeString(&GuidString, ObjectString + 10);
687 RtlGUIDFromString(&GuidString, &ObjectGuid);
688
689 /* Store it in the application entry */
690 Entry->Guid = ObjectGuid;
691
692 /* Remember one was passed */
693 HaveGuid = TRUE;
694 }
695 else
696 {
697 /* Remember that no identifier was passed */
699 HaveGuid = FALSE;
700 }
701
702 /* At this point, the header is consumed, and we must now handle BCD options */
703 RemainingSize -= FIELD_OFFSET(BL_APPLICATION_ENTRY, BcdData);
704
705 /* Convert the device path into a BCD option */
708 &Entry->BcdData,
709 RemainingSize);
710 if (!NT_SUCCESS(Status))
711 {
712 /* We failed, so mark the option as such and return an empty one */
713 Entry->BcdData.Empty = TRUE;
714 TotalOptionSize = sizeof(BL_BCD_OPTION);
715 goto Quickie;
716 }
717
718 /* Extract the device descriptor and return it */
719 BcdDevice = (PVOID)((ULONG_PTR)&Entry->BcdData + Entry->BcdData.DataOffset);
720 *AppEntryDevice = &BcdDevice->DeviceDescriptor;
721
722 /* Calculate how big this option was and consume that from the buffer */
723 TotalOptionSize = BlGetBootOptionSize(&Entry->BcdData);
724 RemainingSize -= TotalOptionSize;
725
726 /* Calculate where the next option should go */
727 Option = (PVOID)((ULONG_PTR)&Entry->BcdData + TotalOptionSize);
728
729 /* Check if we're PXE booting or not */
730 if ((*AppEntryDevice)->DeviceType == UdpDevice)
731 {
732 /* lol */
734 }
735 else
736 {
737 /* Convert the local file path into a BCD option */
740 Option,
741 RemainingSize);
742 }
743
744 /* Bail out on failure */
745 if (!NT_SUCCESS(Status))
746 {
747 goto Quickie;
748 }
749
750 /* The next option is right after this one */
751 Entry->BcdData.NextEntryOffset = TotalOptionSize;
752
753 /* Now compute the size of the next option, and add to the rolling sum */
754 Size = BlGetBootOptionSize(Option);
755 TotalOptionSize += Size;
756
757 /* Remember the previous option so we can update its next offset */
758 PreviousOption = Option;
759
760 /* Consume the option from the buffer */
761 RemainingSize -= Size;
762
763 /* Calculate where the next option should go */
764 Option = (PVOID)((ULONG_PTR)Option + Size);
765
766 /* Check if we were using binary options without a BCD GUID */
767 if ((HaveBinaryOptions) && !(HaveGuid))
768 {
769 /* Then this means we have to convert the OS paths to BCD too */
770 WindowsOptions = (PBL_WINDOWS_LOAD_OPTIONS)LoadOptions;
771 OsPath = (PVOID)((ULONG_PTR)WindowsOptions + WindowsOptions->OsPathOffset);
772
773 /* IS the OS path in EFI format? */
775 (OsPath->PathType == EfiPath))
776 {
777 /* Convert the device portion */
778 OsDevicePath = (EFI_DEVICE_PATH*)OsPath->Path;
781 Option,
782 RemainingSize);
783 if (!NT_SUCCESS(Status))
784 {
785 goto Quickie;
786 }
787
788 /* Update the offset of the previous option */
789 PreviousOption->NextEntryOffset = (ULONG_PTR)Option - (ULONG_PTR)&Entry->BcdData;
790
791 /* Now compute the size of the next option, and add to the rolling sum */
792 Size = BlGetBootOptionSize(Option);
793 TotalOptionSize += Size;
794
795 /* Remember the previous option so we can update its next offset */
796 PreviousOption = Option;
797
798 /* Consume the option from the buffer */
799 RemainingSize -= Size;
800
801 /* Calculate where the next option should go */
802 Option = (PVOID)((ULONG_PTR)Option + Size);
803
804 /* Convert the path option */
805 Status = EfiInitpConvertEfiFilePath(OsDevicePath,
807 Option,
808 RemainingSize);
809 if (!NT_SUCCESS(Status))
810 {
811 goto Quickie;
812 }
813
814 /* Update the offset of the previous option */
815 PreviousOption->NextEntryOffset = (ULONG_PTR)Option - (ULONG_PTR)&Entry->BcdData;
816
817 /* Now compute the size of the next option, and add to the rolling sum */
818 Size = BlGetBootOptionSize(Option);
819 TotalOptionSize += Size;
820
821 /* Remember the previous option so we can update its next offset */
822 PreviousOption = Option;
823
824 /* Consume the option from the buffer */
825 RemainingSize -= Size;
826
827 /* Calculate where the next option should go */
828 Option = (PVOID)((ULONG_PTR)Option + Size);
829 }
830 }
831
832 /* Now convert everything else */
833 AhCreateLoadOptionsList(CommandLine,
834 &Entry->BcdData,
835 RemainingSize,
836 &TotalOptionSize,
837 &PreviousOption,
838 &Size);
839
840Quickie:
841 /* Return the final size */
842 *ResultLength = HeaderSize + TotalOptionSize;
843}
844
845/*++
846 * @name EfiInitCreateInputParametersEx
847 *
848 * The EfiInitCreateInputParametersEx routine converts UEFI entrypoint
849 * parameters to the ones expected by Windows Boot Applications
850 *
851 * @param ImageHandle
852 * UEFI Image Handle for the current loaded application.
853 *
854 * @param SystemTable
855 * Pointer to the UEFI System Table.
856 *
857 * @return A PBOOT_APPLICATION_PARAMETER_BLOCK structure containing the data
858 * from UEFI, translated to the Boot Library-compatible format.
859 *
860 *--*/
863 _In_ EFI_HANDLE ImageHandle,
864 _In_ EFI_SYSTEM_TABLE *SystemTable
865 )
866{
867 EFI_BOOT_SERVICES* BootServices;
868 EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
869 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
870 PBL_FIRMWARE_DESCRIPTOR FirmwareData;
871 PBL_RETURN_ARGUMENTS ReturnArguments;
872 ULONG FirmwareOffset, ConsumedSize;
873 PBL_DEVICE_DESCRIPTOR AppDevice;
875
876 /* Initialize the header with the signature and version */
880
881 /* Set the image type to x86 */
883
884 /* Set the translation type to physical */
886
887 /* Indicate that the data was converted from EFI */
889
890 /* Grab the loaded image protocol, which has our base and size */
891 BootServices = SystemTable->BootServices;
892 Status = BootServices->HandleProtocol(ImageHandle,
894 (VOID**)&LoadedImage);
895 if (Status != EFI_SUCCESS)
896 {
897 return NULL;
898 }
899
900 /* Capture it in the boot application parameters */
901 EfiInitScratch.ImageBase = (ULONG_PTR)LoadedImage->ImageBase;
902 EfiInitScratch.ImageSize = (ULONG)LoadedImage->ImageSize;
903
904 /* Now grab our device path protocol, so we can convert the path later on */
905 Status = BootServices->HandleProtocol(LoadedImage->DeviceHandle,
907 (VOID**)&DevicePath);
908 if (Status != EFI_SUCCESS)
909 {
910 return NULL;
911 }
912
913 /* The built-in boot memory data comes right after our block */
914 EfiInitScratch.MemoryDataOffset =
916
917 /* Build the boot memory data structure, with 1 descriptor */
921 EfiInitScratch.MemoryDataOffset;
925
926 /* Build the memory entry descriptor for this image itself */
931
932 /* The built-in application entry comes right after the memory descriptor*/
933 EfiInitScratch.AppEntryOffset =
935
936 /* Go and build it */
939 sizeof(EfiInitScratch.AppEntry),
940 DevicePath,
941 LoadedImage->FilePath,
942 LoadedImage->LoadOptions,
943 LoadedImage->LoadOptionsSize,
945 &ConsumedSize,
946 &AppDevice);
947
948 /* Boot device information comes right after the application entry */
949 EfiInitScratch.BootDeviceOffset = ConsumedSize + EfiInitScratch.AppEntryOffset;
950
951 /* Check if we have a boot device */
952 if (AppDevice != NULL)
953 {
954 /* We do -- copy it */
956 AppDevice,
957 AppDevice->Size);
958
959 /* Firmware data follows right after the boot device entry */
960 FirmwareOffset = AppDevice->Size + EfiInitScratch.BootDeviceOffset;
961 }
962 else
963 {
964 /* We do not, so zero out the space where a full boot device structure would fit */
966 sizeof(BL_DEVICE_DESCRIPTOR));
967
968 /* And start the firmware data past that */
969 FirmwareOffset = EfiInitScratch.BootDeviceOffset + sizeof(BL_DEVICE_DESCRIPTOR);
970 }
971
972 /* Set the computed firmware data offset */
973 EfiInitScratch.FirmwareParametersOffset = FirmwareOffset;
974
975 /* Fill out the firmware data that's there */
976 FirmwareData = (PVOID)((ULONG_PTR)&EfiInitScratch + EfiInitScratch.FirmwareParametersOffset);
978 FirmwareData->ImageHandle = ImageHandle;
979 FirmwareData->SystemTable = SystemTable;
980
981 /* Finally, set the return argument offset */
982 EfiInitScratch.ReturnArgumentsOffset = FirmwareOffset + sizeof(BL_FIRMWARE_DESCRIPTOR);
983
984 /* And fill out the return argument data */
985 ReturnArguments = (PVOID)((ULONG_PTR)&EfiInitScratch + EfiInitScratch.ReturnArgumentsOffset);
986 ReturnArguments->Version = BL_RETURN_ARGUMENTS_VERSION;
987
988 /* We're done, compute the final size and return the block */
989 EfiInitScratch.Size = EfiInitScratch.ReturnArgumentsOffset + sizeof(BL_RETURN_ARGUMENTS);
991}
992
993/*++
994 * @name EfiEntry
995 *
996 * The EfiEntry routine implements the UEFI entrypoint for the application.
997 *
998 * @param ImageHandle
999 * UEFI Image Handle for the current loaded application.
1000 *
1001 * @param SystemTable
1002 * Pointer to the UEFI System Table.
1003 *
1004 * @return EFI_SUCCESS if the image was loaded correctly, relevant error code
1005 * otherwise.
1006 *
1007 *--*/
1009EFIAPI
1011 _In_ EFI_HANDLE ImageHandle,
1012 _In_ EFI_SYSTEM_TABLE *SystemTable
1013 )
1014{
1016 PBOOT_APPLICATION_PARAMETER_BLOCK BootParameters;
1017
1018 /* Convert EFI parameters to Windows Boot Application parameters */
1019 BootParameters = EfiInitCreateInputParametersEx(ImageHandle, SystemTable);
1020 if (BootParameters != NULL)
1021 {
1022 /* Conversion was good -- call the Boot Manager Entrypoint */
1023 Status = BmMain(BootParameters);
1024 }
1025 else
1026 {
1027 /* Conversion failed, bail out */
1029 }
1030
1031 /* Convert the NT status code to an EFI code */
1033}
1034
#define MSG_IPv4_DP
Definition: DevicePath.h:536
#define MEDIA_FILEPATH_DP
Definition: DevicePath.h:931
#define HARDWARE_DEVICE_PATH
Definition: DevicePath.h:73
#define MEDIA_DEVICE_PATH
Definition: DevicePath.h:842
#define MEDIA_CDROM_DP
Definition: DevicePath.h:902
FORCEINLINE EFI_DEVICE_PATH_PROTOCOL * NextDevicePathNode(_In_ PVOID Node)
Definition: DevicePath.h:1189
#define ACPI_DEVICE_PATH
Definition: DevicePath.h:175
#define SIGNATURE_TYPE_GUID
Definition: DevicePath.h:897
#define MEDIA_HARDDRIVE_DP
Definition: DevicePath.h:847
#define SIGNATURE_TYPE_MBR
Definition: DevicePath.h:896
#define MSG_MAC_ADDR_DP
Definition: DevicePath.h:520
#define EISA_PNP_ID(_PNPId)
Definition: DevicePath.h:240
FORCEINLINE UINTN DevicePathNodeLength(_In_ PVOID Node)
Definition: DevicePath.h:1179
FORCEINLINE BOOLEAN IsDevicePathEndType(_In_ PVOID Node)
Definition: DevicePath.h:1199
#define HW_MEMMAP_DP
Definition: DevicePath.h:114
#define MESSAGING_DEVICE_PATH
Definition: DevicePath.h:291
#define ALIGN_UP_BY(size, align)
@ DeviceNode
Definition: Node.h:9
PCWSTR FilePath
unsigned char BOOLEAN
#define EFIAPI
static IN ULONG IN PWSTR OUT PCWSTR OUT PBOOLEAN OUT PATH_TYPE_AND_UNKNOWN * PathType
PRTL_UNICODE_STRING_BUFFER Path
#define EFI_IMAGE_MACHINE_IA32
Definition: UefiBaseType.h:222
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:31
#define EFI_SUCCESS
Definition: UefiBaseType.h:120
int strncmp(const char *String1, const char *String2, ACPI_SIZE Count)
Definition: utclib.c:534
#define OBJ_NAME_PATH_SEPARATOR
Definition: arcname_tests.c:25
LONG NTSTATUS
Definition: precomp.h:26
@ BcdOSLoaderDevice_OSDevice
Definition: bcd.h:110
@ BcdOSLoaderString_SystemRoot
Definition: bcd.h:111
struct _BCD_DEVICE_OPTION * PBCD_DEVICE_OPTION
@ BcdLibraryDevice_ApplicationDevice
Definition: bcd.h:50
@ BcdLibraryString_ApplicationPath
Definition: bcd.h:51
struct _BL_MEMORY_DESCRIPTOR BL_MEMORY_DESCRIPTOR
struct _BL_FIRMWARE_DESCRIPTOR BL_FIRMWARE_DESCRIPTOR
#define BL_APPLICATION_FLAG_CONVERTED_FROM_EFI
Definition: bl.h:51
#define BL_FIRMWARE_DESCRIPTOR_VERSION
Definition: bl.h:64
struct _BL_WINDOWS_LOAD_OPTIONS BL_WINDOWS_LOAD_OPTIONS
@ BlLoaderMemory
Definition: bl.h:306
struct _BL_DEVICE_DESCRIPTOR BL_DEVICE_DESCRIPTOR
@ MbrPartition
Definition: bl.h:275
@ RawPartition
Definition: bl.h:276
@ GptPartition
Definition: bl.h:274
#define BOOT_APPLICATION_SIGNATURE_2
Definition: bl.h:56
EFI_GUID EfiDevicePathProtocol
Definition: firmware.c:31
#define BL_MEMORY_DATA_VERSION
Definition: bl.h:62
EFI_GUID EfiLoadedImageProtocol
Definition: firmware.c:30
@ EfiPath
Definition: bl.h:285
ULONG BlGetBootOptionSize(_In_ PBL_BCD_OPTION BcdOption)
Definition: bcdopt.c:115
@ BootOptions
Definition: bl.h:898
ULONG BlpApplicationFlags
Definition: bootlib.c:21
#define BL_APPLICATION_ENTRY_FLAG_NO_GUID
Definition: bl.h:68
#define BOOT_MEMORY_TRANSLATION_TYPE_PHYSICAL
Definition: bl.h:58
EFI_STATUS EfiGetEfiStatusCode(_In_ NTSTATUS Status)
Definition: firmware.c:2474
@ LegacyPartitionDevice
Definition: bl.h:248
@ DiskDevice
Definition: bl.h:247
@ PartitionDevice
Definition: bl.h:252
@ UdpDevice
Definition: bl.h:250
@ FloppyDevice
Definition: bl.h:262
@ RamDiskDevice
Definition: bl.h:264
@ LocalDevice
Definition: bl.h:261
@ CdRomDevice
Definition: bl.h:263
struct _BL_WINDOWS_LOAD_OPTIONS * PBL_WINDOWS_LOAD_OPTIONS
#define BOOT_APPLICATION_VERSION
Definition: bl.h:61
#define BL_APP_ENTRY_SIGNATURE
Definition: bl.h:53
#define BOOT_APPLICATION_SIGNATURE_1
Definition: bl.h:55
struct _BL_RETURN_ARGUMENTS BL_RETURN_ARGUMENTS
@ BlMemoryWriteBack
Definition: bl.h:349
struct _BL_BCD_OPTION BL_BCD_OPTION
#define BL_RETURN_ARGUMENTS_VERSION
Definition: bl.h:63
#define __in
Definition: dbghelp.h:35
#define __out
Definition: dbghelp.h:62
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define ULONG_PTR
Definition: config.h:101
struct _BOOT_APPLICATION_PARAMETER_BLOCK_SCRATCH BOOT_APPLICATION_PARAMETER_BLOCK_SCRATCH
BOOT_APPLICATION_PARAMETER_BLOCK_SCRATCH EfiInitScratch
Definition: efiemu.c:25
NTSTATUS EfiInitTranslateDevicePath(_In_ EFI_DEVICE_PATH_PROTOCOL *DevicePath, _In_ PBL_DEVICE_DESCRIPTOR DeviceEntry)
Definition: efiemu.c:347
NTSTATUS EfiInitpConvertEfiDevicePath(_In_ EFI_DEVICE_PATH_PROTOCOL *DevicePath, _In_ ULONG DeviceType, _In_ PBL_BCD_OPTION Option, _In_ ULONG MaximumLength)
Definition: efiemu.c:512
EFI_DEVICE_PATH_PROTOCOL * EfiInitpGetDeviceNode(_In_ EFI_DEVICE_PATH_PROTOCOL *DevicePath)
Definition: efiemu.c:306
NTSTATUS EfiInitpConvertEfiFilePath(_In_ EFI_DEVICE_PATH_PROTOCOL *DevicePath, _In_ ULONG PathType, _In_ PBL_BCD_OPTION Option, _In_ ULONG MaximumLength)
Definition: efiemu.c:198
VOID EfiInitpCreateApplicationEntry(__in EFI_SYSTEM_TABLE *SystemTable, __in PBL_APPLICATION_ENTRY Entry, __in ULONG MaximumLength, __in EFI_DEVICE_PATH *DevicePath, __in EFI_DEVICE_PATH *FilePath, __in PWCHAR LoadOptions, __in ULONG LoadOptionsSize, __in ULONG Flags, __out PULONG ResultLength, __out PBL_DEVICE_DESCRIPTOR *AppEntryDevice)
Definition: efiemu.c:599
NTSTATUS EfiInitpAppendPathString(_In_ PWCHAR PathString, _In_ ULONG MaximumLength, _In_ PWCHAR NewPathString, _In_ ULONG NewPathLength, _Out_ PULONG ResultLength)
Definition: efiemu.c:92
NTSTATUS AhCreateLoadOptionsList(_In_ PWCHAR CommandLine, _In_ PBL_BCD_OPTION BootOptions, _In_ ULONG MaximumLength, _Out_ PULONG OptionSize, _In_ PBL_BCD_OPTION *PreviousOption, _In_ PULONG PreviousOptionSize)
Definition: efiemu.c:56
PBOOT_APPLICATION_PARAMETER_BLOCK EfiInitCreateInputParametersEx(_In_ EFI_HANDLE ImageHandle, _In_ EFI_SYSTEM_TABLE *SystemTable)
Definition: efiemu.c:862
EFI_STATUS EFIAPI EfiEntry(_In_ EFI_HANDLE ImageHandle, _In_ EFI_SYSTEM_TABLE *SystemTable)
Definition: efiemu.c:1010
#define PAGE_SIZE
Definition: env_spec_w32.h:49
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
NTSTATUS NTAPI BmMain(_In_ PBOOT_APPLICATION_PARAMETER_BLOCK BootParameters)
Definition: bootmgr.c:2736
Status
Definition: gdiplustypes.h:25
_CONST_RETURN wchar_t *__cdecl wcsstr(_In_z_ const wchar_t *_Str, _In_z_ const wchar_t *_SubStr)
NTSYSAPI NTSTATUS WINAPI RtlGUIDFromString(PUNICODE_STRING, GUID *)
DeviceType
Definition: mmdrv.h:42
static PWSTR GuidString
Definition: apphelp.c:93
#define _Out_
Definition: ms_sal.h:345
#define _In_
Definition: ms_sal.h:308
_In_ NDIS_STATUS _In_ ULONG _In_ USHORT _In_opt_ PVOID _In_ ULONG DataSize
Definition: ndis.h:4755
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define UNICODE_NULL
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:239
#define STATUS_INTEGER_OVERFLOW
Definition: ntstatus.h:385
#define L(x)
Definition: ntvdm.h:50
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
const KSDEVICE_DESCRIPTOR DeviceDescriptor
Definition: splitter.c:257
EFI_HANDLE_PROTOCOL HandleProtocol
Definition: UefiSpec.h:1832
EFI_DEVICE_PATH_PROTOCOL * FilePath
that the EFI Image was loaded from.
Definition: LoadedImage.h:60
VOID * LoadOptions
A pointer to the image's binary load options.
Definition: LoadedImage.h:68
EFI_HANDLE DeviceHandle
The device handle that the EFI Image was loaded from.
Definition: LoadedImage.h:59
UINT32 LoadOptionsSize
The size in bytes of LoadOptions.
Definition: LoadedImage.h:67
UINT64 ImageSize
The size in bytes of the loaded image.
Definition: LoadedImage.h:74
VOID * ImageBase
The base address at which the image was loaded.
Definition: LoadedImage.h:73
base of all file and directory entries
Definition: entries.h:83
EFI_PHYSICAL_ADDRESS StartingAddress
Definition: DevicePath.h:128
EFI_PHYSICAL_ADDRESS EndingAddress
Definition: DevicePath.h:132
BL_DEVICE_DESCRIPTOR DeviceDescriptor
Definition: bcd.h:298
Definition: bl.h:855
ULONG NextEntryOffset
Definition: bl.h:850
UCHAR Path[ANYSIZE_ARRAY]
Definition: bl.h:985
EFI_HANDLE ImageHandle
Definition: bl.h:810
EFI_SYSTEM_TABLE * SystemTable
Definition: bl.h:811
ULONG DescriptorCount
Definition: bl.h:801
ULONG Version
Definition: bl.h:799
ULONG DescriptorSize
Definition: bl.h:802
ULONG MdListOffset
Definition: bl.h:800
ULONG DescriptorOffset
Definition: bl.h:803
ULONGLONG PageCount
Definition: bl.h:839
ULONGLONG BasePage
Definition: bl.h:830
BL_MEMORY_TYPE Type
Definition: bl.h:841
ULONG Version
Definition: bl.h:816
CHAR Signature[8]
Definition: bl.h:990
WCHAR LoadOptions[ANYSIZE_ARRAY]
Definition: bl.h:994
uint32_t * PULONG
Definition: typedefs.h:59
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
void * PVOID
Definition: typedefs.h:50
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
uint16_t * PWCHAR
Definition: typedefs.h:56
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
_Must_inspect_result_ _In_ WDFDEVICE _In_ DEVICE_REGISTRY_PROPERTY _In_ ULONG _Out_ PULONG ResultLength
Definition: wdfdevice.h:3776
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4533
_In_ WDFDMATRANSACTION _In_ size_t MaximumLength
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
unsigned char UCHAR
Definition: xmlstorage.h:181
__wchar_t WCHAR
Definition: xmlstorage.h:180