ReactOS  0.4.14-dev-614-gbfd8a84
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)] ==
115  UNICODE_NULL)
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  *--*/
197 NTSTATUS
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 
290 Quickie:
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  *--*/
307  _In_ EFI_DEVICE_PATH_PROTOCOL *DevicePath
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  *--*/
346 NTSTATUS
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 */
426  case MEDIA_DEVICE_PATH:
427 
428  /* Extract the disk path and check if it's a physical disk */
429  DiskPath = (HARDDRIVE_DEVICE_PATH*)DeviceNode;
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  *--*/
511 NTSTATUS
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);
542  Status = EfiInitTranslateDevicePath(DevicePath,
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 
556 Quickie:
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  *--*/
598 VOID
600  __in EFI_SYSTEM_TABLE *SystemTable,
603  __in EFI_DEVICE_PATH *DevicePath,
605  __in PWCHAR LoadOptions,
606  __in ULONG LoadOptionsSize,
607  __in ULONG Flags,
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;
779  Status = EfiInitpConvertEfiDevicePath(OsDevicePath,
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 
840 Quickie:
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 */
937  EfiInitpCreateApplicationEntry(SystemTable,
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 */
955  RtlCopyMemory(EfiInitScratch.AppEntry + ConsumedSize,
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 */
965  RtlZeroMemory(EfiInitScratch.AppEntry + ConsumedSize,
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);
977  FirmwareData->Version = BL_FIRMWARE_DESCRIPTOR_VERSION;
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  *--*/
1008 EFI_STATUS
1009 EFIAPI
1011  _In_ EFI_HANDLE ImageHandle,
1012  _In_ EFI_SYSTEM_TABLE *SystemTable
1013  )
1014 {
1015  NTSTATUS Status;
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 */
1032  return EfiGetEfiStatusCode(Status);
1033 }
1034 
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble * u
Definition: glfuncs.h:240
IN CINT OUT PVOID IN ULONG OUT PULONG ResultLength
Definition: conport.c:47
#define BL_APPLICATION_FLAG_CONVERTED_FROM_EFI
Definition: bl.h:52
NTSTATUS NTAPI BmMain(_In_ PBOOT_APPLICATION_PARAMETER_BLOCK BootParameters)
Definition: bootmgr.c:2736
#define ACPI_DEVICE_PATH
Definition: DevicePath.h:175
static PWSTR GuidString
Definition: apphelp.c:91
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
#define HW_MEMMAP_DP
Definition: DevicePath.h:114
NTSTATUS EfiInitpAppendPathString(_In_ PWCHAR PathString, _In_ ULONG MaximumLength, _In_ PWCHAR NewPathString, _In_ ULONG NewPathLength, _Out_ PULONG ResultLength)
Definition: efiemu.c:92
ULONG DescriptorSize
Definition: bl.h:803
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
Definition: bl.h:248
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:225
UCHAR Path[ANYSIZE_ARRAY]
Definition: bl.h:986
#define EISA_PNP_ID(_PNPId)
Definition: DevicePath.h:240
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
_CONST_RETURN wchar_t *__cdecl wcsstr(_In_z_ const wchar_t *_Str, _In_z_ const wchar_t *_SubStr)
ULONG Version
Definition: bl.h:817
DeviceType
Definition: mmdrv.h:41
EFI_STATUS EFIAPI EfiEntry(_In_ EFI_HANDLE ImageHandle, _In_ EFI_SYSTEM_TABLE *SystemTable)
Definition: efiemu.c:1010
#define HARDWARE_DEVICE_PATH
Definition: DevicePath.h:73
LONG NTSTATUS
Definition: precomp.h:26
struct _BOOT_APPLICATION_PARAMETER_BLOCK_SCRATCH BOOT_APPLICATION_PARAMETER_BLOCK_SCRATCH
struct _BL_MEMORY_DESCRIPTOR BL_MEMORY_DESCRIPTOR
#define BOOT_APPLICATION_SIGNATURE_2
Definition: bl.h:57
ULONG NextEntryOffset
Definition: bl.h:851
#define MSG_MAC_ADDR_DP
Definition: DevicePath.h:520
uint16_t * PWCHAR
Definition: typedefs.h:54
NTSTATUS EfiInitTranslateDevicePath(_In_ EFI_DEVICE_PATH_PROTOCOL *DevicePath, _In_ PBL_DEVICE_DESCRIPTOR DeviceEntry)
Definition: efiemu.c:347
struct _BL_WINDOWS_LOAD_OPTIONS * PBL_WINDOWS_LOAD_OPTIONS
#define MESSAGING_DEVICE_PATH
Definition: DevicePath.h:291
PCWSTR FilePath
#define BL_APP_ENTRY_SIGNATURE
Definition: bl.h:54
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
uint32_t ULONG_PTR
Definition: typedefs.h:63
static IN ULONG IN PWSTR OUT PCWSTR OUT PBOOLEAN OUT PATH_TYPE_AND_UNKNOWN * PathType
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
WCHAR LoadOptions[ANYSIZE_ARRAY]
Definition: bl.h:995
BL_MEMORY_TYPE Type
Definition: bl.h:842
Definition: bl.h:855
#define UNICODE_NULL
#define STATUS_INTEGER_OVERFLOW
Definition: ntstatus.h:371
EFI_HANDLE ImageHandle
Definition: bl.h:811
#define OBJ_NAME_PATH_SEPARATOR
Definition: arcname_tests.c:25
FORCEINLINE UINTN DevicePathNodeLength(_In_ PVOID Node)
Definition: DevicePath.h:1179
FORCEINLINE BOOLEAN IsDevicePathEndType(_In_ PVOID Node)
Definition: DevicePath.h:1199
EFI_STATUS EfiGetEfiStatusCode(_In_ NTSTATUS Status)
Definition: firmware.c:2474
EFI_PHYSICAL_ADDRESS StartingAddress
Definition: DevicePath.h:128
#define __out
Definition: dbghelp.h:62
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
#define _Out_
Definition: no_sal2.h:323
ULONGLONG PageCount
Definition: bl.h:840
#define MEDIA_HARDDRIVE_DP
Definition: DevicePath.h:847
BL_DEVICE_DESCRIPTOR DeviceDescriptor
Definition: bcd.h:298
void * PVOID
Definition: retypes.h:9
struct _BL_DEVICE_DESCRIPTOR BL_DEVICE_DESCRIPTOR
EFI_HANDLE_PROTOCOL HandleProtocol
Definition: UefiSpec.h:1832
Definition: bl.h:251
struct _BL_WINDOWS_LOAD_OPTIONS BL_WINDOWS_LOAD_OPTIONS
#define MSG_IPv4_DP
Definition: DevicePath.h:536
CHAR Signature[8]
Definition: bl.h:991
const KSDEVICE_DESCRIPTOR DeviceDescriptor
Definition: splitter.c:257
#define BOOT_MEMORY_TRANSLATION_TYPE_PHYSICAL
Definition: bl.h:59
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define BL_FIRMWARE_DESCRIPTOR_VERSION
Definition: bl.h:65
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
struct _BL_RETURN_ARGUMENTS BL_RETURN_ARGUMENTS
int strncmp(const char *String1, const char *String2, ACPI_SIZE Count)
Definition: utclib.c:534
NTSYSAPI NTSTATUS WINAPI RtlGUIDFromString(PUNICODE_STRING, GUID *)
struct _BL_FIRMWARE_DESCRIPTOR BL_FIRMWARE_DESCRIPTOR
#define MEDIA_CDROM_DP
Definition: DevicePath.h:902
ULONG DescriptorOffset
Definition: bl.h:804
#define SIGNATURE_TYPE_MBR
Definition: DevicePath.h:896
struct _BL_BCD_OPTION BL_BCD_OPTION
Definition: Node.h:9
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define BOOT_APPLICATION_VERSION
Definition: bl.h:62
EFI_DEVICE_PATH_PROTOCOL * EfiInitpGetDeviceNode(_In_ EFI_DEVICE_PATH_PROTOCOL *DevicePath)
Definition: efiemu.c:306
#define MEDIA_DEVICE_PATH
Definition: DevicePath.h:842
unsigned char UCHAR
Definition: xmlstorage.h:181
static const WCHAR L[]
Definition: oid.c:1250
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:31
#define PAGE_SIZE
Definition: env_spec_w32.h:49
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:359
EFI_PHYSICAL_ADDRESS EndingAddress
Definition: DevicePath.h:132
EFI_GUID EfiDevicePathProtocol
Definition: firmware.c:31
ULONG BlpApplicationFlags
Definition: bootlib.c:21
Status
Definition: gdiplustypes.h:24
PBOOT_APPLICATION_PARAMETER_BLOCK EfiInitCreateInputParametersEx(_In_ EFI_HANDLE ImageHandle, _In_ EFI_SYSTEM_TABLE *SystemTable)
Definition: efiemu.c:862
#define _In_
Definition: no_sal2.h:204
UnicodeString MaximumLength
Definition: rtlfuncs.h:2982
#define EFIAPI
ULONGLONG BasePage
Definition: bl.h:831
PRTL_UNICODE_STRING_BUFFER Path
ULONG BlGetBootOptionSize(_In_ PBL_BCD_OPTION BcdOption)
Definition: bcdopt.c:115
Definition: bl.h:286
EFI_GUID EfiLoadedImageProtocol
Definition: firmware.c:30
#define EFI_SUCCESS
Definition: UefiBaseType.h:120
ULONG Version
Definition: bl.h:800
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:254
unsigned int * PULONG
Definition: retypes.h:1
NTSTATUS EfiInitpConvertEfiFilePath(_In_ EFI_DEVICE_PATH_PROTOCOL *DevicePath, _In_ ULONG PathType, _In_ PBL_BCD_OPTION Option, _In_ ULONG MaximumLength)
Definition: efiemu.c:198
#define BL_MEMORY_DATA_VERSION
Definition: bl.h:63
ULONG MdListOffset
Definition: bl.h:801
EFI_SYSTEM_TABLE * SystemTable
Definition: bl.h:812
NTSTATUS EfiInitpConvertEfiDevicePath(_In_ EFI_DEVICE_PATH_PROTOCOL *DevicePath, _In_ ULONG DeviceType, _In_ PBL_BCD_OPTION Option, _In_ ULONG MaximumLength)
Definition: efiemu.c:512
struct _BCD_DEVICE_OPTION * PBCD_DEVICE_OPTION
#define EFI_IMAGE_MACHINE_IA32
Definition: UefiBaseType.h:222
#define BOOT_APPLICATION_SIGNATURE_1
Definition: bl.h:56
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
unsigned int ULONG
Definition: retypes.h:1
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
BOOT_APPLICATION_PARAMETER_BLOCK_SCRATCH EfiInitScratch
Definition: efiemu.c:25
#define ULONG_PTR
Definition: config.h:101
#define ALIGN_UP_BY(size, align)
#define SIGNATURE_TYPE_GUID
Definition: DevicePath.h:897
#define BL_RETURN_ARGUMENTS_VERSION
Definition: bl.h:64
#define BL_APPLICATION_ENTRY_FLAG_NO_GUID
Definition: bl.h:69
return STATUS_SUCCESS
Definition: btrfs.c:2938
#define __in
Definition: dbghelp.h:35
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
_In_ NDIS_STATUS _In_ ULONG _In_ USHORT _In_opt_ PVOID _In_ ULONG DataSize
Definition: ndis.h:4751
base of all file and directory entries
Definition: entries.h:82
FORCEINLINE EFI_DEVICE_PATH_PROTOCOL * NextDevicePathNode(_In_ PVOID Node)
Definition: DevicePath.h:1189
#define MEDIA_FILEPATH_DP
Definition: DevicePath.h:931
ULONG DescriptorCount
Definition: bl.h:802