2 * COPYRIGHT: See COPYING.ARM in the top level directory
3 * PROJECT: ReactOS UEFI Boot Library
4 * FILE: boot/environ/lib/misc/image.c
5 * PURPOSE: Boot Library Image Routines
6 * PROGRAMMER: Alex Ionescu (alex.ionescu@reactos.org)
9 /* INCLUDES ******************************************************************/
14 /* DATA VARIABLES ************************************************************/
16 ULONG IapAllocatedTableEntries
;
17 ULONG IapTableEntries
;
20 KDESCRIPTOR GdtRegister
;
21 KDESCRIPTOR IdtRegister
;
22 KDESCRIPTOR BootAppGdtRegister
;
23 KDESCRIPTOR BootAppIdtRegister
;
24 PVOID BootApp32EntryRoutine
;
25 PBOOT_APPLICATION_PARAMETER_BLOCK BootApp32Parameters
;
28 /* FUNCTIONS *****************************************************************/
32 _In_ PBL_IMG_FILE File
,
38 BL_FILE_INFORMATION FileInformation
;
40 /* Check if the file was memory mapped */
41 if (File
->Flags
& BL_IMG_MEMORY_FILE
)
43 /* Just read the size of the mapping */
44 Size
= File
->FileSize
;
48 /* Do file I/O to get the file size */
49 Status
= BlFileGetInformation(File
->FileId
,
51 if (!NT_SUCCESS(Status
))
56 /* We only support files less than 4GB in the Image Mapped */
57 Size
= FileInformation
.Size
;
58 if (FileInformation
.Size
> ULONG_MAX
)
60 return STATUS_NOT_SUPPORTED
;
64 /* Return the size and success */
66 return STATUS_SUCCESS
;
70 ImgpReadAtFileOffset (
71 _In_ PBL_IMG_FILE File
,
73 _In_ ULONGLONG ByteOffset
,
75 _Out_ PULONG BytesReturned
80 /* Check what if this is a mapped file or not */
81 if (File
->Flags
& BL_IMG_MEMORY_FILE
)
83 /* Check if the boundaries are within the file size */
84 if ((ByteOffset
+ Size
) <= File
->FileSize
)
86 /* Yep, copy into the caller-supplied buffer */
88 (PVOID
)((ULONG_PTR
)File
->BaseAddress
+ (ULONG_PTR
)ByteOffset
),
91 /* If caller wanted to know, return the size copied */
94 *BytesReturned
= Size
;
98 Status
= STATUS_SUCCESS
;
103 Status
= STATUS_INVALID_PARAMETER
;
108 /* Issue the file I/O instead */
109 Status
= BlFileReadAtOffsetEx(File
->FileId
,
117 /* Return the final status */
124 _In_ PWCHAR FileName
,
126 _Out_ PBL_IMG_FILE NewFile
131 ULONGLONG RemoteFileSize
;
132 PVOID RemoteFileAddress
;
135 /* First, try to see if BD has this file remotely */
136 Status
= BlBdPullRemoteFile(FileName
,
139 if (NT_SUCCESS(Status
))
141 /* Yep, get the file size and make sure it's < 4GB */
142 FileSize
= RemoteFileSize
;
143 if (RemoteFileSize
<= ULONG_MAX
)
145 /* Remember this is a memory mapped remote file */
146 NewFile
->Flags
|= (BL_IMG_MEMORY_FILE
| BL_IMG_REMOTE_FILE
);
147 NewFile
->FileSize
= FileSize
;
148 NewFile
->BaseAddress
= RemoteFileAddress
;
153 /* Use File I/O instead */
154 Status
= BlFileOpen(DeviceId
,
158 if (!NT_SUCCESS(Status
))
160 /* Bail out on failure */
164 /* Make sure nobody thinks this is a memory file */
165 NewFile
->Flags
&= ~BL_IMG_MEMORY_FILE
;
166 NewFile
->FileId
= FileId
;
169 /* Set common data for both memory and I/O based file */
170 NewFile
->Flags
|= BL_IMG_VALID_FILE
;
171 NewFile
->FileName
= FileName
;
177 _In_ PBL_IMG_FILE File
182 /* Make sure this is a valid file, otherwise no-op */
183 Status
= STATUS_SUCCESS
;
184 if (File
->Flags
& BL_IMG_VALID_FILE
)
186 /* Is this a memory mapped file? */
187 if (!(File
->Flags
& BL_IMG_MEMORY_FILE
))
189 /* Nope, close the file handle */
190 return BlFileClose(File
->FileId
);
193 /* Is this a remote file? */
194 if (File
->Flags
& BL_IMG_REMOTE_FILE
)
196 /* Then only free the memory in that scenario */
197 return MmPapFreePages(File
->BaseAddress
, BL_MM_INCLUDE_MAPPED_ALLOCATED
);
201 /* Return the final status */
206 BlImgUnallocateImageBuffer (
207 _In_ PVOID ImageBase
,
208 _In_ ULONG ImageSize
,
209 _In_ ULONG ImageFlags
212 PHYSICAL_ADDRESS PhysicalAddress
;
215 /* Make sure required parameters are present */
216 if (!(ImageBase
) || !(ImageSize
))
218 return STATUS_INVALID_PARAMETER
;
221 /* Check if this was a physical allocation */
222 if (!(ImageFlags
& BL_LOAD_IMG_VIRTUAL_BUFFER
))
224 return MmPapFreePages(ImageBase
, BL_MM_INCLUDE_MAPPED_ALLOCATED
);
227 /* It's virtual, so translate it first */
228 if (!BlMmTranslateVirtualAddress(ImageBase
, &PhysicalAddress
))
230 return STATUS_INVALID_PARAMETER
;
233 /* Unmap the virtual mapping */
234 Status
= BlMmUnmapVirtualAddressEx(ImageBase
, ROUND_TO_PAGES(ImageSize
));
235 if (NT_SUCCESS(Status
))
237 /* Now free the physical pages */
238 Status
= BlMmFreePhysicalPages(PhysicalAddress
);
246 BlImgAllocateImageBuffer (
247 _Inout_ PVOID
* ImageBuffer
,
248 _In_ ULONG MemoryType
,
249 _In_ ULONGLONG ImageSize
,
254 ULONGLONG Pages
, Size
;
255 PVOID MappedBase
, CurrentBuffer
;
257 PHYSICAL_ADDRESS PhysicalAddress
;
259 /* Read and reset the current buffer address */
260 CurrentBuffer
= *ImageBuffer
;
263 /* Align the image size to page */
264 Size
= ROUND_TO_PAGES(ImageSize
);
266 /* Not sure what this attribute does yet */
268 if (Flags
& BL_LOAD_IMG_UNKNOWN_BUFFER_FLAG
)
270 Attributes
= 0x10000;
273 /* Check if the caller wants a virtual buffer */
274 if (Flags
& BL_LOAD_IMG_VIRTUAL_BUFFER
)
276 /* Set the physical address to the current buffer */
277 PhysicalAddress
.QuadPart
= (ULONG_PTR
)CurrentBuffer
;
278 Pages
= Size
>> PAGE_SHIFT
;
280 /* Allocate the physical pages */
281 Status
= BlMmAllocatePhysicalPages(&PhysicalAddress
,
286 if (!NT_SUCCESS(Status
))
288 /* If that failed, remove allocation attributes */
289 PhysicalAddress
.QuadPart
= 0;
290 Attributes
&= ~BlMemoryValidAllocationAttributeMask
,
291 Status
= BlMmAllocatePhysicalPages(&PhysicalAddress
,
298 /* Check if either attempts succeeded */
299 if (!NT_SUCCESS(Status
))
304 /* Now map the physical buffer at the address requested */
305 MappedBase
= (PVOID
)PhysicalAddress
.LowPart
;
306 Status
= BlMmMapPhysicalAddressEx(&MappedBase
,
310 if (!NT_SUCCESS(Status
))
312 /* Free on failure if needed */
313 BlMmFreePhysicalPages(PhysicalAddress
);
319 /* Otherwise, allocate raw physical pages */
320 MappedBase
= CurrentBuffer
;
321 Pages
= Size
>> PAGE_SHIFT
;
322 Status
= MmPapAllocatePagesInRange(&MappedBase
,
329 if (!NT_SUCCESS(Status
))
331 /* If that failed, try without allocation attributes */
333 Attributes
&= ~BlMemoryValidAllocationAttributeMask
,
334 Status
= MmPapAllocatePagesInRange(&MappedBase
,
343 /* Check if either attempts succeeded */
344 if (!NT_SUCCESS(Status
))
350 /* Success path, returned allocated address */
351 *ImageBuffer
= MappedBase
;
352 return STATUS_SUCCESS
;
356 BlImgLoadImageWithProgress2 (
358 _In_ BL_MEMORY_TYPE MemoryType
,
359 _In_ PWCHAR FileName
,
360 _Inout_ PVOID
* MappedBase
,
361 _Inout_ PULONG MappedSize
,
362 _In_ ULONG ImageFlags
,
363 _In_ BOOLEAN ShowProgress
,
364 _Out_opt_ PUCHAR
* HashBuffer
,
365 _Out_opt_ PULONG HashSize
369 PVOID BaseAddress
, Buffer
;
370 ULONG RemainingLength
, CurrentSize
, ImageSize
, ReadSize
;
371 BOOLEAN ComputeSignature
, ComputeHash
, Completed
;
372 BL_IMG_FILE FileHandle
;
373 ULONGLONG ByteOffset
;
374 PHYSICAL_ADDRESS PhysicalAddress
;
376 /* Initialize variables */
380 RtlZeroMemory(&FileHandle
, sizeof(FileHandle
));
382 /* Check for missing parameters */
385 Status
= STATUS_INVALID_PARAMETER
;
390 Status
= STATUS_INVALID_PARAMETER
;
395 Status
= STATUS_INVALID_PARAMETER
;
399 /* Check if the image buffer is being provided */
400 if (ImageFlags
& BL_LOAD_IMG_EXISTING_BUFFER
)
402 /* An existing base must already exist */
405 Status
= STATUS_INVALID_PARAMETER
;
410 /* Check of a hash is being requested */
411 if (ImageFlags
& BL_LOAD_IMG_COMPUTE_HASH
)
413 /* Make sure we can return the hash */
416 Status
= STATUS_INVALID_PARAMETER
;
421 Status
= STATUS_INVALID_PARAMETER
;
426 /* Check for invalid combination of parameters */
427 if ((ImageFlags
& BL_LOAD_IMG_COMPUTE_HASH
) && (ImageFlags
& 0x270))
429 Status
= STATUS_INVALID_PARAMETER
;
433 /* Initialize hash if requested by caller */
439 /* Do the same for the hash size */
445 /* Open the image file */
446 Status
= ImgpOpenFile(DeviceId
, FileName
, DeviceId
, &FileHandle
);
447 if (!NT_SUCCESS(Status
))
449 EfiPrintf(L
"Error opening file: %lx\r\n", Status
);
453 /* Get the size of the image */
454 Status
= ImgpGetFileSize(&FileHandle
, &ImageSize
);
455 if (!NT_SUCCESS(Status
))
457 EfiPrintf(L
"Error getting file size: %lx\r\n", Status
);
461 /* Read the current base address */
462 BaseAddress
= *MappedBase
;
463 if (ImageFlags
& BL_LOAD_IMG_EXISTING_BUFFER
)
465 /* Check if the current buffer is too small */
466 if (*MappedSize
< ImageSize
)
468 /* Return the required size of the buffer */
469 *MappedSize
= ImageSize
;
470 Status
= STATUS_BUFFER_TOO_SMALL
;
475 /* A buffer was not provided, allocate one ourselves */
476 Status
= BlImgAllocateImageBuffer(&BaseAddress
,
482 /* Bail out if allocation failed */
483 if (!NT_SUCCESS(Status
))
488 /* Set the initial byte offset and length to read */
489 RemainingLength
= ImageSize
;
491 Buffer
= BaseAddress
;
493 /* Update the initial progress */
497 BlUtlUpdateProgress(0, &Completed
);
498 ShowProgress
&= (Completed
!= 0) - 1;
501 /* Set the chunk size for each read */
503 if (ReadSize
> ImageSize
)
505 ReadSize
= ImageSize
;
508 /* Check if we should compute hash and/or signatures */
509 ComputeSignature
= ImageFlags
& BL_LOAD_IMG_COMPUTE_SIGNATURE
;
511 if ((ComputeSignature
) || (ImageFlags
& BL_LOAD_IMG_COMPUTE_HASH
))
514 // todo: crypto is hard
517 /* Begin the read loop */
518 while (RemainingLength
)
520 /* Check if we've got more than a chunk left to read */
521 if (RemainingLength
> ReadSize
)
524 CurrentSize
= ReadSize
;
528 /* Read only what's left */
529 CurrentSize
= RemainingLength
;
533 Status
= ImgpReadAtFileOffset(&FileHandle
,
538 if (!NT_SUCCESS(Status
))
543 /* Check if we need to compute the hash of this chunk */
546 // todo: crypto is hard
549 /* Update our position and read information */
550 Buffer
= (PVOID
)((ULONG_PTR
)Buffer
+ CurrentSize
);
551 RemainingLength
-= CurrentSize
;
552 ByteOffset
+= CurrentSize
;
554 /* Check if we should update the progress bar */
557 /* Compute new percentage completed, check if we're done */
558 BlUtlUpdateProgress(100 - 100 * RemainingLength
/ ImageSize
,
560 ShowProgress
&= (Completed
!= 0) - 1;
564 /* Is the read fully complete? We need to finalize the hash if requested */
567 // todo: CRYPTO IS HARD
570 /* Success path, return back the buffer and the size of the image */
571 *MappedBase
= BaseAddress
;
572 *MappedSize
= ImageSize
;
575 /* Close the file handle */
576 ImgpCloseFile(&FileHandle
);
578 /* Check if we failed and had allocated a buffer */
579 if (!(NT_SUCCESS(Status
)) &&
581 !(ImageFlags
& BL_LOAD_IMG_EXISTING_BUFFER
))
583 /* Check what kind of buffer we had allocated */
584 if (ImageFlags
& BL_LOAD_IMG_VIRTUAL_BUFFER
)
586 /* Unmap and free the virtual buffer */
587 PhysicalAddress
.QuadPart
= (ULONG_PTR
)BaseAddress
;
588 BlMmUnmapVirtualAddressEx(BaseAddress
, ImageSize
);
589 BlMmFreePhysicalPages(PhysicalAddress
);
593 /* Free the physical buffer */
594 MmPapFreePages(BaseAddress
, BL_MM_INCLUDE_MAPPED_ALLOCATED
);
598 /* If we hadn't gotten to 100% yet, do it now */
601 BlUtlUpdateProgress(100, &Completed
);
604 /* Return the final status */
608 PIMAGE_SECTION_HEADER
610 _In_ PVOID ImageBase
,
614 PIMAGE_SECTION_HEADER FoundSection
;
616 PIMAGE_SECTION_HEADER SectionHeader
;
617 PIMAGE_NT_HEADERS NtHeader
;
623 /* Make sure the image is valid */
624 Status
= RtlImageNtHeaderEx(0, ImageBase
, ImageSize
, &NtHeader
);
625 if (NT_SUCCESS(Status
))
627 /* Get the first section and loop through them all */
628 SectionHeader
= IMAGE_FIRST_SECTION(NtHeader
);
629 for (i
= 0; i
< NtHeader
->FileHeader
.NumberOfSections
; i
++)
631 /* Check if this is the resource section */
632 if (!_stricmp((PCCH
)SectionHeader
->Name
, ".rsrc"))
634 /* Yep, we're done */
635 FoundSection
= SectionHeader
;
639 /* Nope, keep going */
644 /* Return the matching section */
649 BlImgQueryCodeIntegrityBootOptions (
650 _In_ PBL_LOADED_APPLICATION_ENTRY ApplicationEntry
,
651 _Out_ PBOOLEAN IntegrityChecksDisabled
,
652 _Out_ PBOOLEAN TestSigning
659 /* Check if /DISABLEINTEGRITYCHECKS is on */
660 Status
= BlGetBootOptionBoolean(ApplicationEntry
->BcdData
,
661 BcdLibraryBoolean_DisableIntegrityChecks
,
663 *IntegrityChecksDisabled
= NT_SUCCESS(Status
) && (Value
);
665 /* Check if /TESTSIGNING is on */
666 Status
= BlGetBootOptionBoolean(ApplicationEntry
->BcdData
,
667 BcdLibraryBoolean_AllowPrereleaseSignatures
,
669 *TestSigning
= NT_SUCCESS(Status
) && (Value
);
674 _In_ PVOID ImageBase
,
675 _In_ ULONG ImageSize
,
676 _In_ ULONG ImageFlags
679 /* Check for missing parameters */
680 if (!(ImageSize
) || !(ImageBase
))
683 return STATUS_INVALID_PARAMETER
;
686 /* Unallocate the image buffer */
687 return BlImgUnallocateImageBuffer(ImageBase
, ImageSize
, ImageFlags
);
692 _In_ PBL_IMG_FILE ImageFile
,
693 _In_ BL_MEMORY_TYPE MemoryType
,
694 _Inout_ PVOID
* ImageBase
,
695 _Out_opt_ PULONG ImageSize
,
696 _Inout_opt_ PVOID Hash
,
701 ULONG FileSize
, HeaderSize
;
702 BL_IMG_FILE LocalFileBuffer
;
703 PBL_IMG_FILE LocalFile
;
704 PVOID VirtualAddress
, PreferredBase
, ImageBuffer
, CertBuffer
, HashBuffer
;
705 ULONGLONG VirtualSize
;
706 PIMAGE_DATA_DIRECTORY CertDirectory
;
707 PHYSICAL_ADDRESS PhysicalAddress
;
708 PIMAGE_NT_HEADERS NtHeaders
;
709 USHORT SectionCount
, CheckSum
, PartialSum
, FinalSum
;
710 PIMAGE_SECTION_HEADER Section
;
711 ULONG_PTR EndOfHeaders
, SectionStart
, Slack
, SectionEnd
;
712 ULONG i
, SectionSize
, RawSize
, BytesRead
, RemainingLength
, Offset
, AlignSize
;
713 BOOLEAN First
, ImageHashValid
;
714 UCHAR LocalBuffer
[1024];
715 UCHAR TrustedBootInformation
[52];
716 ULONG WorkaroundForBinutils
;
718 /* Initialize locals */
719 WorkaroundForBinutils
= 0;
724 VirtualAddress
= NULL
;
726 CertDirectory
= NULL
;
730 ImageHashValid
= FALSE
;
731 RtlZeroMemory(&TrustedBootInformation
, sizeof(TrustedBootInformation
));
733 /* Get the size of the image */
734 Status
= ImgpGetFileSize(ImageFile
, &FileSize
);
735 if (!NT_SUCCESS(Status
))
737 return STATUS_FILE_INVALID
;
740 /* Allocate a flat buffer for it */
741 Status
= BlImgAllocateImageBuffer(&ImageBuffer
, BlLoaderData
, FileSize
, 0);
742 if (!NT_SUCCESS(Status
))
747 /* Read the whole file flat for now */
748 Status
= ImgpReadAtFileOffset(ImageFile
, FileSize
, 0, ImageBuffer
, NULL
);
749 if (!NT_SUCCESS(Status
))
754 /* Build a local file handle */
755 LocalFile
= &LocalFileBuffer
;
756 LocalFileBuffer
.FileName
= ImageFile
->FileName
;
757 LocalFileBuffer
.Flags
= BL_IMG_MEMORY_FILE
| BL_IMG_VALID_FILE
;
758 LocalFileBuffer
.BaseAddress
= ImageBuffer
;
759 LocalFileBuffer
.FileSize
= FileSize
;
761 /* Get the NT headers of the file */
762 Status
= RtlImageNtHeaderEx(0, ImageBuffer
, FileSize
, &NtHeaders
);
763 if (!NT_SUCCESS(Status
))
768 /* Check if we should validate the machine type */
769 if (Flags
& BL_LOAD_PE_IMG_CHECK_MACHINE
)
771 /* Is it different than our current machine type? */
773 if (NtHeaders
->FileHeader
.Machine
!= IMAGE_FILE_MACHINE_AMD64
)
775 if (NtHeaders
->FileHeader
.Machine
!= IMAGE_FILE_MACHINE_I386
)
778 /* Is it x86 (implying we are x64) ? */
779 if (NtHeaders
->FileHeader
.Machine
== IMAGE_FILE_MACHINE_I386
)
781 /* Return special error code */
782 Status
= STATUS_INVALID_IMAGE_WIN_32
;
784 else if (NtHeaders
->FileHeader
.Machine
== IMAGE_FILE_MACHINE_AMD64
)
786 /* Otherwise, it's x64 but we are x86 */
787 Status
= STATUS_INVALID_IMAGE_WIN_64
;
791 /* Or it's ARM or something... */
792 Status
= STATUS_INVALID_IMAGE_FORMAT
;
795 /* Return with the distinguished error code */
800 /* Check if we should validate the subsystem */
801 if (Flags
& BL_LOAD_PE_IMG_CHECK_SUBSYSTEM
)
803 /* It must be a Windows boot Application */
804 if (NtHeaders
->OptionalHeader
.Subsystem
!=
805 IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION
)
807 Status
= STATUS_INVALID_IMAGE_FORMAT
;
812 /* Check if we should validate the /INTEGRITYCHECK flag */
813 if (Flags
& BL_LOAD_PE_IMG_CHECK_FORCED_INTEGRITY
)
815 /* Check if it's there */
816 if (!(NtHeaders
->OptionalHeader
.DllCharacteristics
&
817 IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY
))
819 /* Nope, fail otherwise */
820 Status
= STATUS_INVALID_IMAGE_FORMAT
;
825 /* Check if we should compute the image hash */
826 if ((Flags
& BL_LOAD_PE_IMG_COMPUTE_HASH
) || (Hash
))
828 EfiPrintf(L
"No hash support\r\n");
831 /* Read the current base address, if any */
832 VirtualAddress
= *ImageBase
;
834 /* Get the virtual size of the image */
835 VirtualSize
= NtHeaders
->OptionalHeader
.SizeOfImage
;
837 /* Safely align the virtual size to a page */
838 Status
= RtlULongLongAdd(VirtualSize
,
841 if (!NT_SUCCESS(Status
))
845 VirtualSize
= ALIGN_DOWN_BY(VirtualSize
, PAGE_SIZE
);
847 /* Make sure the image isn't larger than 4GB */
848 if (VirtualSize
> ULONG_MAX
)
850 Status
= STATUS_INVALID_IMAGE_FORMAT
;
854 /* Check if we have a buffer already */
855 if (Flags
& BL_LOAD_IMG_EXISTING_BUFFER
)
857 /* Check if it's too small */
858 if (*ImageSize
< VirtualSize
)
860 /* Fail, letting the caller know how big to make it */
861 *ImageSize
= VirtualSize
;
862 Status
= STATUS_BUFFER_TOO_SMALL
;
867 /* Allocate the buffer with the flags and type the caller wants */
868 Status
= BlImgAllocateImageBuffer(&VirtualAddress
,
874 /* Bail out if allocation failed, or existing buffer is too small */
875 if (!NT_SUCCESS(Status
))
880 /* Read the size of the headers */
881 HeaderSize
= NtHeaders
->OptionalHeader
.SizeOfHeaders
;
882 if (VirtualSize
< HeaderSize
)
884 /* Bail out if they're bigger than the image! */
885 Status
= STATUS_INVALID_IMAGE_FORMAT
;
889 /* Now read the header into the buffer */
890 Status
= ImgpReadAtFileOffset(LocalFile
, HeaderSize
, 0, VirtualAddress
, NULL
);
891 if (!NT_SUCCESS(Status
))
896 /* Get the NT headers of the file */
897 Status
= RtlImageNtHeaderEx(0, VirtualAddress
, HeaderSize
, &NtHeaders
);
898 if (!NT_SUCCESS(Status
))
905 /* Record how many sections we have */
906 SectionCount
= NtHeaders
->FileHeader
.NumberOfSections
;
908 /* Capture the current checksum and reset it */
909 CheckSum
= NtHeaders
->OptionalHeader
.CheckSum
;
910 NtHeaders
->OptionalHeader
.CheckSum
= 0;
912 /* Calculate the checksum of the header, and restore the original one */
913 PartialSum
= BlUtlCheckSum(0,
916 BL_UTL_CHECKSUM_COMPLEMENT
|
917 BL_UTL_CHECKSUM_USHORT_BUFFER
);
918 NtHeaders
->OptionalHeader
.CheckSum
= CheckSum
;
920 /* Record our current position (right after the headers) */
921 EndOfHeaders
= (ULONG_PTR
)VirtualAddress
+ HeaderSize
;
923 /* Get the first section and iterate through each one */
924 Section
= IMAGE_FIRST_SECTION(NtHeaders
);
925 for (i
= 0; i
< SectionCount
; i
++)
927 /* Compute where this section starts */
928 SectionStart
= (ULONG_PTR
)VirtualAddress
+ Section
->VirtualAddress
;
930 /* Make sure that the section fits within the image */
931 if ((VirtualSize
< Section
->VirtualAddress
) ||
932 ((PVOID
)SectionStart
< VirtualAddress
))
934 EfiPrintf(L
"fail 1\r\n");
935 Status
= STATUS_INVALID_IMAGE_FORMAT
;
939 /* Check if there's slack space between header end and the section */
940 if (!(First
) && (EndOfHeaders
< SectionStart
))
943 Slack
= SectionStart
- EndOfHeaders
;
944 RtlZeroMemory((PVOID
)EndOfHeaders
, Slack
);
947 /* Get the section virtual size and the raw size */
948 SectionSize
= Section
->Misc
.VirtualSize
;
949 RawSize
= Section
->SizeOfRawData
;
951 /* Safely align the raw size by 2 */
952 Status
= RtlULongAdd(RawSize
, 1, &AlignSize
);
953 if (!NT_SUCCESS(Status
))
957 AlignSize
= ALIGN_DOWN_BY(AlignSize
, 2);
959 /* IF we don't have a virtual size, use the raw size */
962 SectionSize
= RawSize
;
965 /* If we don't have raw data, ignore the raw size */
966 if (!Section
->PointerToRawData
)
970 else if (SectionSize
< RawSize
)
972 /* And if the virtual size is smaller, use it as the final size */
973 RawSize
= SectionSize
;
976 /* Make sure that the section doesn't overflow in memory */
977 Status
= RtlULongAdd(Section
->VirtualAddress
,
980 if (!NT_SUCCESS(Status
))
982 EfiPrintf(L
"fail 21\r\n");
983 Status
= STATUS_INVALID_IMAGE_FORMAT
;
987 /* Make sure that it fits within the image */
988 if (VirtualSize
< SectionEnd
)
990 Status
= STATUS_INVALID_IMAGE_FORMAT
;
994 /* Make sure it doesn't overflow on disk */
995 Status
= RtlULongAdd(Section
->VirtualAddress
,
998 if (!NT_SUCCESS(Status
))
1000 EfiPrintf(L
"fail 31\r\n");
1001 Status
= STATUS_INVALID_IMAGE_FORMAT
;
1005 /* Make sure that it fits within the disk image as well */
1006 if (VirtualSize
< SectionEnd
)
1008 Status
= STATUS_INVALID_IMAGE_FORMAT
;
1012 /* So does this section have a valid size after all? */
1015 /* Are we in the first iteration? */
1018 /* FUCK YOU BINUTILS */
1019 if (NtHeaders
->OptionalHeader
.MajorLinkerVersion
< 7)
1021 if ((*(PULONG
)&Section
->Name
== 'ler.') && (RawSize
< AlignSize
))
1023 /* Piece of shit won't build relocations when you tell it to,
1024 * either by using --emit-relocs or --dynamicbase. People online
1025 * have found out that by using -pie-executable you can get this
1026 * to happen, but then it turns out that the .reloc section is
1027 * incorrectly sized, and results in a corrupt PE. However, they
1028 * still compute the checksum using the correct value. What idiots.
1030 WorkaroundForBinutils
= AlignSize
- RawSize
;
1031 AlignSize
-= WorkaroundForBinutils
;
1035 /* Yes, read the section data */
1036 Status
= ImgpReadAtFileOffset(LocalFile
,
1038 Section
->PointerToRawData
,
1039 (PVOID
)SectionStart
,
1041 if (!NT_SUCCESS(Status
))
1046 /* Update our current offset */
1047 Offset
= AlignSize
+ Section
->PointerToRawData
;
1049 /* Update the checksum to include this section */
1050 PartialSum
= BlUtlCheckSum(PartialSum
,
1051 (PUCHAR
)SectionStart
,
1053 BL_UTL_CHECKSUM_COMPLEMENT
|
1054 BL_UTL_CHECKSUM_USHORT_BUFFER
);
1055 AlignSize
+= WorkaroundForBinutils
;
1059 /* Are we in the first iteration? */
1062 /* Is there space at the end of the section? */
1063 if (RawSize
< SectionSize
)
1065 /* Zero out the slack space that's there */
1066 Slack
= SectionSize
- RawSize
;
1067 RtlZeroMemory((PVOID
)(SectionStart
+ RawSize
), Slack
);
1070 /* Update our tail offset */
1071 EndOfHeaders
= SectionStart
+ SectionSize
;
1074 /* Move to the next section */
1078 /* Are we in the first iteration? */
1081 /* Go to the end of the file */
1082 SectionStart
= (ULONG_PTR
)VirtualAddress
+ VirtualSize
;
1084 /* Is there still some slack space left? */
1085 if (EndOfHeaders
< SectionStart
)
1088 Slack
= SectionStart
- EndOfHeaders
;
1089 RtlZeroMemory((PVOID
)EndOfHeaders
, Slack
);
1093 /* Did the first iteration complete OK? */
1094 if ((NT_SUCCESS(Status
)) && !(First
))
1096 /* Check how many non-image bytes are left in the file */
1097 RemainingLength
= FileSize
- Offset
;
1098 while (RemainingLength
)
1100 /* See if the read will fit into our local buffer */
1101 if (RemainingLength
>= sizeof(LocalBuffer
))
1104 BytesRead
= sizeof(LocalBuffer
);
1108 /* Yes, but there's less to read */
1109 BytesRead
= RemainingLength
;
1112 /* Read 1024 bytes into the local buffer */
1113 Status
= ImgpReadAtFileOffset(LocalFile
,
1118 if (!(NT_SUCCESS(Status
)) || !(BytesRead
))
1120 Status
= STATUS_FILE_INVALID
;
1124 /* Advance the offset and reduce the length */
1125 RemainingLength
-= BytesRead
;
1126 Offset
+= BytesRead
;
1128 /* Compute the checksum of this leftover space */
1129 PartialSum
= BlUtlCheckSum(PartialSum
,
1132 BL_UTL_CHECKSUM_COMPLEMENT
|
1133 BL_UTL_CHECKSUM_USHORT_BUFFER
);
1136 /* Finally, calculate the final checksum and compare it */
1137 FinalSum
= FileSize
+ PartialSum
+ WorkaroundForBinutils
;
1138 if ((FinalSum
!= CheckSum
) && (PartialSum
== 0xFFFF))
1140 /* It hit overflow, so set it to the file size */
1141 FinalSum
= FileSize
;
1144 /* If the checksum doesn't match, and caller is enforcing, bail out */
1145 if ((FinalSum
!= CheckSum
) &&
1146 !(Flags
& BL_LOAD_PE_IMG_IGNORE_CHECKSUM_MISMATCH
))
1148 Status
= STATUS_IMAGE_CHECKSUM_MISMATCH
;
1153 /* Check if the .rsrc section should be checked with the filename */
1154 if (Flags
& BL_LOAD_PE_IMG_VALIDATE_ORIGINAL_FILENAME
)
1156 EfiPrintf(L
"Not yet supported\r\n");
1157 Status
= 0xC0430007; // STATUS_SECUREBOOT_FILE_REPLACED
1161 /* Check if we should relocate */
1162 if (!(Flags
& BL_LOAD_PE_IMG_SKIP_RELOCATIONS
))
1164 /* Check if we loaded at a different address */
1165 PreferredBase
= (PVOID
)NtHeaders
->OptionalHeader
.ImageBase
;
1166 if (VirtualAddress
!= PreferredBase
)
1168 /* Yep -- do relocations */
1169 Status
= LdrRelocateImage(VirtualAddress
,
1170 "Boot Environment Library",
1172 STATUS_UNSUCCESSFUL
,
1173 STATUS_INVALID_IMAGE_FORMAT
);
1174 if (!NT_SUCCESS(Status
))
1183 /* Check if the image hash was valid */
1184 if (!ImageHashValid
)
1186 /* Send a TPM/SI notification without a context */
1187 BlEnNotifyEvent(0x10000002, NULL
);
1190 /* Now send a TPM/SI notification with the hash of the loaded image */
1191 BlMmTranslateVirtualAddress(VirtualAddress
, &Context
.ImageBase
);
1192 Context
.HashAlgorithm
= HashAlgorithm
;
1193 Context
.HashSize
= HashSize
;
1194 Context
.FileName
= ImageFile
->FileName
;
1195 Context
.ImageSize
= VirtualSize
;
1196 Context
.HashValid
= ImageHashValid
;
1197 Context
.Hash
= Hash
;
1198 BlEnNotifyEvent(0x10000002, &Context
);
1201 /* Return the loaded address to the caller */
1202 *ImageBase
= VirtualAddress
;
1204 /* If the caller wanted the image size, return it too */
1207 *ImageSize
= VirtualSize
;
1211 /* Check if we computed the image hash OK */
1214 /* Then free the information that ImgpValidateImageHash set up */
1215 EfiPrintf(L
"leadking trusted boot\r\n");
1216 //ImgpDestroyTrustedBootInformation(&TrustedBootInformation);
1219 /* Check if we had a hash buffer */
1223 MmPapFreePages(HashBuffer
, BL_MM_INCLUDE_MAPPED_ALLOCATED
);
1226 /* Check if we have a certificate directory */
1227 if ((CertBuffer
) && (CertDirectory
))
1230 BlImgUnallocateImageBuffer(CertBuffer
, CertDirectory
->Size
, 0);
1233 /* Check if we had an image buffer allocated */
1234 if ((ImageBuffer
) && (FileSize
))
1237 BlImgUnallocateImageBuffer(ImageBuffer
, FileSize
, 0);
1240 /* Check if we had a local file handle */
1244 ImgpCloseFile(LocalFile
);
1247 /* Check if this is the failure path */
1248 if (!NT_SUCCESS(Status
))
1250 /* Check if we had started mapping in the image already */
1251 if ((VirtualAddress
) && !(Flags
& BL_LOAD_PE_IMG_EXISTING_BUFFER
))
1253 /* Into a virtual buffer? */
1254 if (Flags
& BL_LOAD_PE_IMG_VIRTUAL_BUFFER
)
1256 /* Unmap and free it */
1257 BlMmUnmapVirtualAddressEx(VirtualAddress
, VirtualSize
);
1258 PhysicalAddress
.QuadPart
= (ULONG_PTR
)VirtualAddress
;
1259 BlMmFreePhysicalPages(PhysicalAddress
);
1263 /* Into a physical buffer -- free it */
1264 MmPapFreePages(VirtualAddress
, BL_MM_INCLUDE_MAPPED_ALLOCATED
);
1269 /* Return back to caller */
1274 BlImgLoadPEImageEx (
1275 _In_ ULONG DeviceId
,
1276 _In_ BL_MEMORY_TYPE MemoryType
,
1278 _Out_ PVOID
* ImageBase
,
1279 _Out_ PULONG ImageSize
,
1284 BL_IMG_FILE ImageFile
;
1287 /* Initialize the image file structure */
1288 ImageFile
.Flags
= 0;
1289 ImageFile
.FileName
= NULL
;
1291 /* Check if the required parameter are missing */
1292 if (!(ImageBase
) || !(Path
))
1294 return STATUS_INVALID_PARAMETER
;
1297 /* If we are loading a pre-allocated image, make sure we have it */
1298 if ((Flags
& BL_LOAD_IMG_EXISTING_BUFFER
) && (!(*ImageBase
) || !(ImageSize
)))
1300 return STATUS_INVALID_PARAMETER
;
1303 /* Load the file from disk */
1304 Status
= ImgpOpenFile(DeviceId
, Path
, 0, &ImageFile
);
1305 if (NT_SUCCESS(Status
))
1307 /* If that worked, do the PE parsing */
1308 Status
= ImgpLoadPEImage(&ImageFile
,
1316 /* Close the image file and return back to caller */
1317 ImgpCloseFile(&ImageFile
);
1322 BlImgLoadBootApplication (
1323 _In_ PBL_LOADED_APPLICATION_ENTRY BootEntry
,
1324 _Out_ PULONG AppHandle
1328 PULONGLONG AllowedList
;
1329 ULONGLONG AllowedCount
;
1330 ULONG i
, DeviceId
, ImageSize
, Flags
, ListSize
;
1331 LARGE_INTEGER Frequency
;
1332 PVOID UnlockCode
, ImageBase
;
1333 PBL_DEVICE_DESCRIPTOR Device
, BitLockerDevice
;
1335 PBL_APPLICATION_ENTRY AppEntry
;
1336 PBL_IMG_FILE ImageFile
;
1337 BOOLEAN DisableIntegrity
, TestSigning
;
1339 PBL_IMAGE_APPLICATION_ENTRY ImageAppEntry
;
1341 /* Initialize all locals */
1342 BitLockerDevice
= NULL
;
1347 ImageAppEntry
= NULL
;
1353 /* Check for "allowed in-memory settings" */
1354 Status
= BlpGetBootOptionIntegerList(BootEntry
->BcdData
,
1355 BcdLibraryIntegerList_AllowedInMemorySettings
,
1359 if (Status
== STATUS_SUCCESS
)
1361 /* Loop through the list of allowed setting */
1362 for (i
= 0; i
< AllowedCount
; i
++)
1364 /* Find the super undocumented one */
1365 if (AllowedList
[i
] == BcdLibraryInteger_UndocumentedMagic
)
1367 /* If it's present, append the current perf frequence to it */
1368 BlTimeQueryPerformanceCounter(&Frequency
);
1369 BlAppendBootOptionInteger(BootEntry
,
1370 BcdLibraryInteger_UndocumentedMagic
,
1371 Frequency
.QuadPart
);
1376 #if BL_BITLOCKER_SUPPORT
1377 /* Do bitlocker stuff */
1378 Status
= BlFveSecureBootUnlockBootDevice(BootEntry
, &BitLockerDevice
, &UnlockCode
);
1379 if (!NT_SUCCESS(Status
))
1385 /* Get the device on which this application is on*/
1386 Status
= BlGetBootOptionDevice(BootEntry
->BcdData
,
1387 BcdLibraryDevice_ApplicationDevice
,
1390 if (!NT_SUCCESS(Status
))
1395 /* Get the path of the application */
1396 Status
= BlGetBootOptionString(BootEntry
->BcdData
,
1397 BcdLibraryString_ApplicationPath
,
1399 if (!NT_SUCCESS(Status
))
1404 /* Open the device */
1405 Status
= BlpDeviceOpen(Device
,
1406 BL_DEVICE_READ_ACCESS
,
1409 if (!NT_SUCCESS(Status
))
1414 /* Check for integrity BCD options */
1415 BlImgQueryCodeIntegrityBootOptions(BootEntry
,
1420 RtlZeroMemory(&Context
, sizeof(Context
);
1421 Context
.BootEntry
= BootEntry
;
1422 BlEnNotifyEvent(0x10000003, &Context
);
1425 /* Enable signing and hashing checks if integrity is enabled */
1427 if (!DisableIntegrity
)
1432 /* Now call the PE loader to load the image */
1433 Status
= BlImgLoadPEImageEx(DeviceId
,
1440 if (!NT_SUCCESS(Status
))
1446 /* Check if we should notify the debugger of load */
1447 if (BdDebugTransitions
)
1451 Status
= BlBdInitialize();
1452 if (NT_SUCCESS(Status
))
1454 /* Check if it's enabled */
1455 if (BlBdDebuggerEnabled())
1457 /* Send it an image load notification */
1458 BdDebuggerNotPresent
= FALSE
;
1459 RtlInitUnicodeString(&PathString
, Path
);
1460 BlBdLoadImageSymbols(&PathString
, ImageBase
);
1466 #if BL_BITLOCKER_SUPPORT
1467 /* Do bitlocker stuff */
1468 Status
= BlSecureBootCheckPolicyOnFveDevice(BitLockerDevice
);
1469 if (!NT_SUCCESS(Status
))
1475 #if BL_BITLOCKER_SUPPORT
1476 /* Do bitlocker stuff */
1477 Status
= BlFveSecureBootCheckpointBootApp(BootEntry
, BitLockerDevice
, Hash
, UnlockCode
);
1478 if (!NT_SUCCESS(Status
))
1484 /* Get the BCD option size */
1485 ListSize
= BlGetBootOptionListSize(BootEntry
->BcdData
);
1487 /* Allocate an entry with all the BCD options */
1488 AppEntry
= BlMmAllocateHeap(ListSize
+ sizeof(*AppEntry
));
1491 Status
= STATUS_NO_MEMORY
;
1496 RtlZeroMemory(AppEntry
, sizeof(*AppEntry
));
1499 strcpy(AppEntry
->Signature
, "BTAPENT");
1500 AppEntry
->Guid
= BootEntry
->Guid
;
1501 AppEntry
->Flags
= BootEntry
->Flags
;
1503 /* Copy the BCD options */
1504 RtlCopyMemory(&AppEntry
->BcdData
, BootEntry
->BcdData
, ListSize
);
1506 /* Allocate the image entry */
1507 ImageAppEntry
= BlMmAllocateHeap(sizeof(*ImageAppEntry
));
1510 Status
= STATUS_NO_MEMORY
;
1515 ImageAppEntry
->ImageBase
= ImageBase
;
1516 ImageAppEntry
->ImageSize
= ImageSize
;
1517 ImageAppEntry
->AppEntry
= AppEntry
;
1519 /* Check if this is the first entry */
1520 if (!IapTableEntries
)
1522 /* Allocate two entries */
1523 IapAllocatedTableEntries
= 0;
1524 IapTableEntries
= 2;
1525 IapImageTable
= BlMmAllocateHeap(IapTableEntries
* sizeof(PVOID
));
1528 Status
= STATUS_NO_MEMORY
;
1532 /* Zero out the entries for now */
1533 RtlZeroMemory(IapImageTable
, IapTableEntries
* sizeof(PVOID
));
1536 /* Set this entry into the table */
1537 Status
= BlTblSetEntry(&IapImageTable
,
1541 TblDoNotPurgeEntry
);
1544 /* Is the device open? Close it if so */
1547 BlDeviceClose(DeviceId
);
1550 /* Is there an allocated device? Free it */
1553 BlMmFreeHeap(Device
);
1556 /* Is there an allocated path? Free it */
1562 /* Is there a bitlocker device? Free it */
1563 if (BitLockerDevice
)
1565 BlMmFreeHeap(BitLockerDevice
);
1568 /* Is there a bitlocker unlock code? Free it */
1571 BlMmFreeHeap(UnlockCode
);
1574 /* Did we succeed in creating an entry? */
1575 if (NT_SUCCESS(Status
))
1577 /* Remember there's one more in the table */
1578 IapAllocatedTableEntries
++;
1580 /* Return success */
1584 /* Did we load an image after all? */
1588 BlImgUnLoadImage(ImageBase
, ImageSize
, 0);
1591 /* Did we allocate an app entry? Free it */
1594 BlMmFreeHeap(AppEntry
);
1597 /* Do we have an image file entry? Free it */
1600 BlMmFreeHeap(ImageFile
);
1603 /* Do we no longer have a single entry in the table? */
1604 if (!(IapAllocatedTableEntries
) && (IapImageTable
))
1606 /* Free and destroy the table */
1607 BlMmFreeHeap(IapImageTable
);
1608 IapTableEntries
= 0;
1609 IapImageTable
= NULL
;
1612 /* Return the failure code */
1617 BlpPdParseReturnArguments (
1618 _In_ PBL_RETURN_ARGUMENTS ReturnArguments
1621 /* Check if any custom data was returned */
1622 if (ReturnArguments
->DataPage
== 0)
1624 /* Nope, nothing to do */
1625 return STATUS_SUCCESS
;
1628 /* Yes, we have to parse it */
1629 EfiPrintf(L
"Return arguments not supported\r\n");
1630 return STATUS_NOT_IMPLEMENTED
;
1634 ImgpCopyApplicationBootDevice (
1635 __in PBL_DEVICE_DESCRIPTOR DestinationDevice
,
1636 __in PBL_DEVICE_DESCRIPTOR SourceDevice
1639 /* Is this a partition device? */
1640 if (SourceDevice
->DeviceType
!= PartitionDevice
)
1642 /* It's not -- a simple copy will do */
1643 RtlCopyMemory(DestinationDevice
, SourceDevice
, SourceDevice
->Size
);
1644 return STATUS_SUCCESS
;
1648 EfiPrintf(L
"Partition copy not supported\r\n");
1649 return STATUS_NOT_IMPLEMENTED
;
1654 ImgpInitializeBootApplicationParameters (
1655 _In_ PBL_IMAGE_PARAMETERS ImageParameters
,
1656 _In_ PBL_APPLICATION_ENTRY AppEntry
,
1657 _In_ PVOID ImageBase
,
1658 _In_ ULONG ImageSize
1662 PIMAGE_NT_HEADERS NtHeaders
;
1663 BL_IMAGE_PARAMETERS MemoryParameters
;
1664 LIST_ENTRY MemoryList
;
1665 PBL_FIRMWARE_DESCRIPTOR FirmwareParameters
;
1666 PBL_DEVICE_DESCRIPTOR BootDevice
;
1667 PBL_MEMORY_DATA MemoryData
;
1668 PBL_APPLICATION_ENTRY BootAppEntry
;
1669 PBL_RETURN_ARGUMENTS ReturnArguments
;
1670 PBOOT_APPLICATION_PARAMETER_BLOCK ParameterBlock
;
1671 ULONG EntrySize
, BufferSize
;
1673 /* Get the image headers and validate it */
1674 Status
= RtlImageNtHeaderEx(0, ImageBase
, ImageSize
, &NtHeaders
);
1675 if (!NT_SUCCESS(Status
))
1680 /* Get the size of the entire non-firmware, allocated, memory map */
1681 MemoryParameters
.BufferSize
= 0;
1682 Status
= BlMmGetMemoryMap(&MemoryList
,
1684 BL_MM_INCLUDE_PERSISTENT_MEMORY
|
1685 BL_MM_INCLUDE_MAPPED_ALLOCATED
|
1686 BL_MM_INCLUDE_MAPPED_UNALLOCATED
|
1687 BL_MM_INCLUDE_UNMAPPED_ALLOCATED
|
1688 BL_MM_INCLUDE_RESERVED_ALLOCATED
,
1690 if ((Status
!= STATUS_BUFFER_TOO_SMALL
) && (Status
!= STATUS_SUCCESS
))
1692 /* We failed due to an unknown reason -- bail out */
1696 /* Compute the list of the BCD plus the application entry */
1697 EntrySize
= BlGetBootOptionListSize(&AppEntry
->BcdData
) +
1698 FIELD_OFFSET(BL_APPLICATION_ENTRY
, BcdData
);
1700 /* Compute the total size required for the entire structure */
1701 BufferSize
= EntrySize
+
1702 BlpBootDevice
->Size
+
1703 MemoryParameters
.BufferSize
+
1704 sizeof(*ReturnArguments
) +
1705 sizeof(*MemoryData
) +
1706 sizeof(*FirmwareParameters
) +
1707 sizeof(*ParameterBlock
);
1709 /* Check if this gives us enough space */
1710 if (ImageParameters
->BufferSize
< BufferSize
)
1712 /* It does not -- free the existing buffer */
1713 if (ImageParameters
->BufferSize
)
1715 BlMmFreeHeap(ImageParameters
->Buffer
);
1718 /* Allocate a new buffer of sufficient size */
1719 ImageParameters
->BufferSize
= BufferSize
;
1720 ImageParameters
->Buffer
= BlMmAllocateHeap(BufferSize
);
1721 if (!ImageParameters
->Buffer
)
1723 /* Bail out if we couldn't allocate it */
1724 return STATUS_NO_MEMORY
;
1728 /* Zero out the parameter block */
1729 ParameterBlock
= (PBOOT_APPLICATION_PARAMETER_BLOCK
)ImageParameters
->Buffer
;
1730 RtlZeroMemory(ParameterBlock
, BufferSize
);
1733 ParameterBlock
->Version
= BOOT_APPLICATION_VERSION
;
1734 ParameterBlock
->Size
= BufferSize
;
1735 ParameterBlock
->Signature
[0] = BOOT_APPLICATION_SIGNATURE_1
;
1736 ParameterBlock
->Signature
[1] = BOOT_APPLICATION_SIGNATURE_2
;
1737 ParameterBlock
->MemoryTranslationType
= MmTranslationType
;
1738 ParameterBlock
->ImageType
= IMAGE_FILE_MACHINE_I386
;
1739 ParameterBlock
->ImageBase
= (ULONG_PTR
)ImageBase
;
1740 ParameterBlock
->ImageSize
= NtHeaders
->OptionalHeader
.SizeOfImage
;
1742 /* Get the offset to the memory data */
1743 ParameterBlock
->MemoryDataOffset
= sizeof(*ParameterBlock
);
1746 MemoryData
= (PBL_MEMORY_DATA
)((ULONG_PTR
)ParameterBlock
+
1747 ParameterBlock
->MemoryDataOffset
);
1748 MemoryData
->Version
= BL_MEMORY_DATA_VERSION
;
1749 MemoryData
->MdListOffset
= sizeof(*MemoryData
);
1750 MemoryData
->DescriptorSize
= sizeof(BL_MEMORY_DESCRIPTOR
);
1751 MemoryData
->DescriptorOffset
= FIELD_OFFSET(BL_MEMORY_DESCRIPTOR
, BasePage
);
1753 /* And populate the memory map */
1754 MemoryParameters
.Buffer
= MemoryData
+ 1;
1755 Status
= BlMmGetMemoryMap(&MemoryList
,
1757 BL_MM_INCLUDE_PERSISTENT_MEMORY
|
1758 BL_MM_INCLUDE_MAPPED_ALLOCATED
|
1759 BL_MM_INCLUDE_MAPPED_UNALLOCATED
|
1760 BL_MM_INCLUDE_UNMAPPED_ALLOCATED
|
1761 BL_MM_INCLUDE_RESERVED_ALLOCATED
,
1763 if (!NT_SUCCESS(Status
))
1768 /* Now that we have the map, indicate the number of descriptors */
1769 MemoryData
->DescriptorCount
= MemoryParameters
.ActualSize
/
1770 MemoryData
->DescriptorSize
;
1772 /* Get the offset to the application entry */
1773 ParameterBlock
->AppEntryOffset
= ParameterBlock
->MemoryDataOffset
+
1774 MemoryData
->MdListOffset
+
1775 MemoryParameters
.BufferSize
;
1778 BootAppEntry
= (PBL_APPLICATION_ENTRY
)((ULONG_PTR
)ParameterBlock
+
1779 ParameterBlock
->AppEntryOffset
);
1780 RtlCopyMemory(BootAppEntry
, AppEntry
, EntrySize
);
1782 /* Get the offset to the boot device */
1783 ParameterBlock
->BootDeviceOffset
= ParameterBlock
->AppEntryOffset
+
1787 BootDevice
= (PBL_DEVICE_DESCRIPTOR
)((ULONG_PTR
)ParameterBlock
+
1788 ParameterBlock
->BootDeviceOffset
);
1789 Status
= ImgpCopyApplicationBootDevice(BootDevice
, BlpBootDevice
);
1790 if (!NT_SUCCESS(Status
))
1795 /* Get the offset to the firmware data */
1796 ParameterBlock
->FirmwareParametersOffset
= ParameterBlock
->BootDeviceOffset
+
1800 FirmwareParameters
= (PBL_FIRMWARE_DESCRIPTOR
)((ULONG_PTR
)ParameterBlock
+
1802 FirmwareParametersOffset
);
1803 Status
= BlFwGetParameters(FirmwareParameters
);
1804 if (!NT_SUCCESS(Status
))
1809 /* Get the offset to the return arguments */
1810 ParameterBlock
->ReturnArgumentsOffset
= ParameterBlock
->FirmwareParametersOffset
+
1811 sizeof(BL_FIRMWARE_DESCRIPTOR
);
1814 ReturnArguments
= (PBL_RETURN_ARGUMENTS
)((ULONG_PTR
)ParameterBlock
+
1816 ReturnArgumentsOffset
);
1817 ReturnArguments
->Version
= BL_RETURN_ARGUMENTS_VERSION
;
1818 ReturnArguments
->DataPage
= 0;
1819 ReturnArguments
->DataSize
= 0;
1821 /* Structure complete */
1822 ImageParameters
->ActualSize
= ParameterBlock
->ReturnArgumentsOffset
+
1823 sizeof(*ReturnArguments
);
1824 return STATUS_SUCCESS
;
1828 ImgArchEfiStartBootApplication (
1829 _In_ PBL_APPLICATION_ENTRY AppEntry
,
1830 _In_ PVOID ImageBase
,
1831 _In_ ULONG ImageSize
,
1832 _In_ PBL_RETURN_ARGUMENTS ReturnArguments
1835 KDESCRIPTOR Gdt
, Idt
;
1836 ULONG BootSizeNeeded
;
1839 PIMAGE_NT_HEADERS NtHeaders
;
1840 PVOID NewStack
, NewGdt
, NewIdt
;
1841 BL_IMAGE_PARAMETERS Parameters
;
1843 /* Read the current IDT and GDT */
1847 /* Allocate space for the IDT, GDT, and 24 pages of stack */
1848 BootSizeNeeded
= (ULONG
)PAGE_ALIGN(Idt
.Limit
+ Gdt
.Limit
+ 1 + 25 * PAGE_SIZE
);
1849 Status
= MmPapAllocatePagesInRange(&BootData
,
1851 BootSizeNeeded
>> PAGE_SHIFT
,
1856 if (!NT_SUCCESS(Status
))
1861 /* Zero the boot data */
1862 RtlZeroMemory(BootData
, BootSizeNeeded
);
1864 /* Set the new stack, GDT and IDT */
1865 NewStack
= (PVOID
)((ULONG_PTR
)BootData
+ (24 * PAGE_SIZE
) - 8);
1866 NewGdt
= (PVOID
)((ULONG_PTR
)BootData
+ (24 * PAGE_SIZE
));
1867 NewIdt
= (PVOID
)((ULONG_PTR
)BootData
+ (24 * PAGE_SIZE
) + Gdt
.Limit
+ 1);
1869 /* Copy the current (firmware) GDT and IDT */
1870 RtlCopyMemory(NewGdt
, (PVOID
)Gdt
.Base
, Gdt
.Limit
+ 1);
1871 RtlCopyMemory(NewIdt
, (PVOID
)Idt
.Base
, Idt
.Limit
+ 1);
1873 /* Read the NT headers so that we can get the entrypoint later on */
1874 RtlImageNtHeaderEx(0, ImageBase
, ImageSize
, &NtHeaders
);
1876 /* Prepare the application parameters */
1877 RtlZeroMemory(&Parameters
, sizeof(Parameters
));
1878 Status
= ImgpInitializeBootApplicationParameters(&Parameters
,
1882 if (NT_SUCCESS(Status
))
1884 /* Set the firmware GDT/IDT as the one the application will use */
1885 BootAppGdtRegister
= Gdt
;
1886 BootAppIdtRegister
= Idt
;
1888 /* Set the entrypoint, parameters, and stack */
1889 BootApp32EntryRoutine
= (PVOID
)((ULONG_PTR
)ImageBase
+
1890 NtHeaders
->OptionalHeader
.
1891 AddressOfEntryPoint
);
1892 BootApp32Parameters
= Parameters
.Buffer
;
1893 BootApp32Stack
= NewStack
;
1896 /* Disable the kernel debugger */
1900 Archx86TransferTo32BitApplicationAsm();
1902 /* Not yet implemented. This is the last step! */
1903 EfiPrintf(L
"EFI APPLICATION RETURNED!!!\r\n");
1904 EfiStall(100000000);
1907 /* Re-enable the kernel debugger */
1913 /* Check if we had boot data allocated */
1917 MmPapFreePages(BootData
, BL_MM_INCLUDE_MAPPED_ALLOCATED
);
1921 return STATUS_NOT_IMPLEMENTED
;
1925 BlImgStartBootApplication (
1926 _In_ ULONG AppHandle
,
1927 _Inout_opt_ PBL_RETURN_ARGUMENTS ReturnArguments
1930 PBL_IMAGE_APPLICATION_ENTRY ImageAppEntry
;
1931 BL_RETURN_ARGUMENTS LocalReturnArgs
;
1932 PBL_FILE_SYSTEM_ENTRY FileSystem
;
1933 PLIST_ENTRY NextEntry
, ListHead
;
1936 /* Check if we don't have an argument structure */
1937 if (!ReturnArguments
)
1939 /* Initialize a local copy and use it instead */
1940 LocalReturnArgs
.Version
= BL_RETURN_ARGUMENTS_VERSION
;
1941 LocalReturnArgs
.Status
= STATUS_SUCCESS
;
1942 LocalReturnArgs
.Flags
= 0;
1943 LocalReturnArgs
.DataPage
= 0;
1944 LocalReturnArgs
.DataSize
= 0;
1945 ReturnArguments
= &LocalReturnArgs
;
1948 /* Make sure the handle index is valid */
1949 if (IapTableEntries
<= AppHandle
)
1951 return STATUS_INVALID_PARAMETER
;
1954 /* Get the entry for this handle, making sure it exists */
1955 ImageAppEntry
= IapImageTable
[AppHandle
];
1958 return STATUS_INVALID_PARAMETER
;
1961 /* Loop the registered file systems */
1962 ListHead
= &RegisteredFileSystems
;
1963 NextEntry
= RegisteredFileSystems
.Flink
;
1964 while (NextEntry
!= ListHead
)
1966 /* Get the filesystem entry */
1967 FileSystem
= CONTAINING_RECORD(NextEntry
,
1968 BL_FILE_SYSTEM_ENTRY
,
1971 /* See if it has a purge callback */
1972 if (FileSystem
->PurgeCallback
)
1975 FileSystem
->PurgeCallback();
1978 /* Move to the next entry */
1979 NextEntry
= NextEntry
->Flink
;
1982 /* TODO -- flush the block I/O cache too */
1983 //BlockIoPurgeCache();
1985 /* Call into EFI land to start the boot application */
1986 Status
= ImgArchEfiStartBootApplication(ImageAppEntry
->AppEntry
,
1987 ImageAppEntry
->ImageBase
,
1988 ImageAppEntry
->ImageSize
,
1991 /* Parse any arguments we got on the way back */
1992 BlpPdParseReturnArguments(ReturnArguments
);
1994 #if BL_BITLOCKER_SUPPORT
1995 /* Bitlocker stuff */
1996 FvebpCheckAllPartitions(TRUE
);
2000 /* Notify a TPM/SI event */
2001 BlEnNotifyEvent(0x10000005, NULL
);
2004 /* Reset the display */
2005 BlpDisplayReinitialize();
2007 /* TODO -- reset ETW */
2008 //BlpLogInitialize();
2015 BlImgUnloadBootApplication (
2016 _In_ ULONG AppHandle
2019 PBL_IMAGE_APPLICATION_ENTRY ImageAppEntry
;
2022 /* Make sure the handle index is valid */
2023 if (IapTableEntries
<= AppHandle
)
2025 return STATUS_INVALID_PARAMETER
;
2028 /* Get the entry for this handle, making sure it exists */
2029 ImageAppEntry
= IapImageTable
[AppHandle
];
2032 return STATUS_INVALID_PARAMETER
;
2035 /* Unload the image */
2036 Status
= BlImgUnLoadImage(ImageAppEntry
->ImageBase
,
2037 ImageAppEntry
->ImageSize
,
2039 if (NT_SUCCESS(Status
))
2041 /* Normalize the success code */
2042 Status
= STATUS_SUCCESS
;
2046 /* Normalize the failure code */
2047 Status
= STATUS_MEMORY_NOT_ALLOCATED
;
2050 /* Free the entry and the image entry as well */
2051 BlMmFreeHeap(ImageAppEntry
->AppEntry
);
2052 BlMmFreeHeap(ImageAppEntry
);
2054 /* Clear the handle */
2055 IapImageTable
[AppHandle
] = NULL
;
2057 /* Free one entry */
2058 if (!(--IapAllocatedTableEntries
))
2060 /* There are no more, so get rid of the table itself */
2061 BlMmFreeHeap(IapImageTable
);
2062 IapImageTable
= NULL
;
2063 IapTableEntries
= 0;