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 PVOID 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 EfiPrintf(L
"TODO\r\n");
198 //return MmPapFreePages(File->BaseAddress, TRUE);
202 /* Return the final status */
207 BlImgUnallocateImageBuffer (
208 _In_ PVOID ImageBase
,
209 _In_ ULONG ImageSize
,
210 _In_ ULONG ImageFlags
213 EfiPrintf(L
"leaking the shit out of %p\r\n", ImageBase
);
214 return STATUS_NOT_IMPLEMENTED
;
218 BlImgAllocateImageBuffer (
219 _Inout_ PVOID
* ImageBuffer
,
220 _In_ ULONG MemoryType
,
221 _In_ ULONGLONG ImageSize
,
226 ULONGLONG Pages
, Size
;
227 PVOID MappedBase
, CurrentBuffer
;
229 PHYSICAL_ADDRESS PhysicalAddress
;
231 /* Read and reset the current buffer address */
232 CurrentBuffer
= *ImageBuffer
;
235 /* Align the image size to page */
236 Size
= ROUND_TO_PAGES(ImageSize
);
238 /* Not sure what this attribute does yet */
240 if (Flags
& BL_LOAD_IMG_UNKNOWN_BUFFER_FLAG
)
242 Attributes
= 0x10000;
245 /* Check if the caller wants a virtual buffer */
246 if (Flags
& BL_LOAD_IMG_VIRTUAL_BUFFER
)
248 /* Set the physical address to the current buffer */
249 PhysicalAddress
.QuadPart
= (ULONG_PTR
)CurrentBuffer
;
250 Pages
= Size
>> PAGE_SHIFT
;
252 /* Allocate the physical pages */
253 Status
= BlMmAllocatePhysicalPages(&PhysicalAddress
,
258 if (!NT_SUCCESS(Status
))
260 /* If that failed, remove allocation attributes */
261 PhysicalAddress
.QuadPart
= 0;
262 Attributes
&= ~BlMemoryValidAllocationAttributeMask
,
263 Status
= BlMmAllocatePhysicalPages(&PhysicalAddress
,
270 /* Check if either attempts succeeded */
271 if (!NT_SUCCESS(Status
))
276 /* Now map the physical buffer at the address requested */
277 MappedBase
= (PVOID
)PhysicalAddress
.LowPart
;
278 Status
= BlMmMapPhysicalAddressEx(&MappedBase
,
282 if (!NT_SUCCESS(Status
))
284 /* Free on failure if needed */
285 BlMmFreePhysicalPages(PhysicalAddress
);
291 /* Otherwise, allocate raw physical pages */
292 MappedBase
= CurrentBuffer
;
293 Pages
= Size
>> PAGE_SHIFT
;
294 Status
= MmPapAllocatePagesInRange(&MappedBase
,
301 if (!NT_SUCCESS(Status
))
303 /* If that failed, try without allocation attributes */
305 Attributes
&= ~BlMemoryValidAllocationAttributeMask
,
306 Status
= MmPapAllocatePagesInRange(&MappedBase
,
315 /* Check if either attempts succeeded */
316 if (!NT_SUCCESS(Status
))
322 /* Success path, returned allocated address */
323 *ImageBuffer
= MappedBase
;
324 return STATUS_SUCCESS
;
328 BlImgLoadImageWithProgress2 (
330 _In_ BL_MEMORY_TYPE MemoryType
,
331 _In_ PWCHAR FileName
,
332 _Inout_ PVOID
* MappedBase
,
333 _Inout_ PULONG MappedSize
,
334 _In_ ULONG ImageFlags
,
335 _In_ BOOLEAN ShowProgress
,
336 _Out_opt_ PUCHAR
* HashBuffer
,
337 _Out_opt_ PULONG HashSize
341 PVOID BaseAddress
, Buffer
;
342 ULONG RemainingLength
, CurrentSize
, ImageSize
, ReadSize
;
343 BOOLEAN ComputeSignature
, ComputeHash
, Completed
;
344 BL_IMG_FILE FileHandle
;
345 ULONGLONG ByteOffset
;
346 PHYSICAL_ADDRESS PhysicalAddress
;
348 /* Initialize variables */
352 RtlZeroMemory(&FileHandle
, sizeof(FileHandle
));
354 /* Check for missing parameters */
357 Status
= STATUS_INVALID_PARAMETER
;
362 Status
= STATUS_INVALID_PARAMETER
;
367 Status
= STATUS_INVALID_PARAMETER
;
371 /* Check if the image buffer is being provided */
372 if (ImageFlags
& BL_LOAD_IMG_EXISTING_BUFFER
)
374 /* An existing base must already exist */
377 Status
= STATUS_INVALID_PARAMETER
;
382 /* Check of a hash is being requested */
383 if (ImageFlags
& BL_LOAD_IMG_COMPUTE_HASH
)
385 /* Make sure we can return the hash */
388 Status
= STATUS_INVALID_PARAMETER
;
393 Status
= STATUS_INVALID_PARAMETER
;
398 /* Check for invalid combination of parameters */
399 if ((ImageFlags
& BL_LOAD_IMG_COMPUTE_HASH
) && (ImageFlags
& 0x270))
401 Status
= STATUS_INVALID_PARAMETER
;
405 /* Initialize hash if requested by caller */
411 /* Do the same for the hash size */
417 /* Open the image file */
418 Status
= ImgpOpenFile(DeviceId
, FileName
, DeviceId
, &FileHandle
);
419 if (!NT_SUCCESS(Status
))
421 EfiPrintf(L
"Error opening file: %lx\r\n", Status
);
425 /* Get the size of the image */
426 Status
= ImgpGetFileSize(&FileHandle
, &ImageSize
);
427 if (!NT_SUCCESS(Status
))
429 EfiPrintf(L
"Error getting file size: %lx\r\n", Status
);
433 /* Read the current base address */
434 BaseAddress
= *MappedBase
;
435 if (ImageFlags
& BL_LOAD_IMG_EXISTING_BUFFER
)
437 /* Check if the current buffer is too small */
438 if (*MappedSize
< ImageSize
)
440 /* Return the required size of the buffer */
441 *MappedSize
= ImageSize
;
442 Status
= STATUS_BUFFER_TOO_SMALL
;
447 /* A buffer was not provided, allocate one ourselves */
448 Status
= BlImgAllocateImageBuffer(&BaseAddress
,
454 /* Bail out if allocation failed */
455 if (!NT_SUCCESS(Status
))
460 /* Set the initial byte offset and length to read */
461 RemainingLength
= ImageSize
;
463 Buffer
= BaseAddress
;
465 /* Update the initial progress */
469 BlUtlUpdateProgress(0, &Completed
);
470 ShowProgress
&= (Completed
!= 0) - 1;
473 /* Set the chunk size for each read */
475 if (ReadSize
> ImageSize
)
477 ReadSize
= ImageSize
;
480 /* Check if we should compute hash and/or signatures */
481 ComputeSignature
= ImageFlags
& BL_LOAD_IMG_COMPUTE_SIGNATURE
;
482 if ((ComputeSignature
) || (ImageFlags
& BL_LOAD_IMG_COMPUTE_HASH
))
485 // todo: crypto is hard
488 /* Begin the read loop */
489 while (RemainingLength
)
491 /* Check if we've got more than a chunk left to read */
492 if (RemainingLength
> ReadSize
)
495 CurrentSize
= ReadSize
;
499 /* Read only what's left */
500 CurrentSize
= RemainingLength
;
504 Status
= ImgpReadAtFileOffset(&FileHandle
,
509 if (!NT_SUCCESS(Status
))
514 /* Check if we need to compute the hash of this chunk */
517 // todo: crypto is hard
520 /* Update our position and read information */
521 Buffer
= (PVOID
)((ULONG_PTR
)Buffer
+ CurrentSize
);
522 RemainingLength
-= CurrentSize
;
523 ByteOffset
+= CurrentSize
;
525 /* Check if we should update the progress bar */
528 /* Compute new percentage completed, check if we're done */
529 BlUtlUpdateProgress(100 - 100 * RemainingLength
/ ImageSize
,
531 ShowProgress
&= (Completed
!= 0) - 1;
535 /* Is the read fully complete? We need to finalize the hash if requested */
536 if (ComputeHash
!= RemainingLength
)
538 // todo: CRYPTO IS HARD
541 /* Success path, return back the buffer and the size of the image */
542 *MappedBase
= BaseAddress
;
543 *MappedSize
= ImageSize
;
546 /* Close the file handle */
547 ImgpCloseFile(&FileHandle
);
549 /* Check if we failed and had allocated a buffer */
550 if (!(NT_SUCCESS(Status
)) &&
552 !(ImageFlags
& BL_LOAD_IMG_EXISTING_BUFFER
))
554 /* Check what kind of buffer we had allocated */
555 if (ImageFlags
& BL_LOAD_IMG_VIRTUAL_BUFFER
)
557 /* Unmap and free the virtual buffer */
558 PhysicalAddress
.QuadPart
= (ULONG_PTR
)BaseAddress
;
559 BlMmUnmapVirtualAddressEx(BaseAddress
, ImageSize
);
560 BlMmFreePhysicalPages(PhysicalAddress
);
564 /* Free the physical buffer */
565 //MmPapFreePages(VirtualAddress, 1);
566 EfiPrintf(L
"Leaking memory\r\n");
570 /* If we hadn't gotten to 100% yet, do it now */
573 BlUtlUpdateProgress(100, &Completed
);
576 /* Return the final status */
580 PIMAGE_SECTION_HEADER
582 _In_ PVOID ImageBase
,
586 PIMAGE_SECTION_HEADER FoundSection
;
588 PIMAGE_SECTION_HEADER SectionHeader
;
589 PIMAGE_NT_HEADERS NtHeader
;
595 /* Make sure the image is valid */
596 Status
= RtlImageNtHeaderEx(0, ImageBase
, ImageSize
, &NtHeader
);
597 if (NT_SUCCESS(Status
))
599 /* Get the first section and loop through them all */
600 SectionHeader
= IMAGE_FIRST_SECTION(NtHeader
);
601 for (i
= 0; i
< NtHeader
->FileHeader
.NumberOfSections
; i
++)
603 /* Check if this is the resource section */
604 if (!_stricmp((PCCH
)SectionHeader
->Name
, ".rsrc"))
606 /* Yep, we're done */
607 FoundSection
= SectionHeader
;
611 /* Nope, keep going */
616 /* Return the matching section */
621 BlImgQueryCodeIntegrityBootOptions (
622 _In_ PBL_LOADED_APPLICATION_ENTRY ApplicationEntry
,
623 _Out_ PBOOLEAN IntegrityChecksDisabled
,
624 _Out_ PBOOLEAN TestSigning
631 /* Check if /DISABLEINTEGRITYCHECKS is on */
632 Status
= BlGetBootOptionBoolean(ApplicationEntry
->BcdData
,
633 BcdLibraryBoolean_DisableIntegrityChecks
,
635 *IntegrityChecksDisabled
= NT_SUCCESS(Status
) && (Value
);
637 /* Check if /TESTSIGNING is on */
638 Status
= BlGetBootOptionBoolean(ApplicationEntry
->BcdData
,
639 BcdLibraryBoolean_AllowPrereleaseSignatures
,
641 *TestSigning
= NT_SUCCESS(Status
) && (Value
);
646 _In_ PVOID ImageBase
,
647 _In_ ULONG ImageSize
,
648 _In_ ULONG ImageFlags
651 /* Check for missing parameters */
652 if (!(ImageSize
) || !(ImageBase
))
655 return STATUS_INVALID_PARAMETER
;
658 /* Unallocate the image buffer */
659 return BlImgUnallocateImageBuffer(ImageBase
, ImageSize
, ImageFlags
);
664 _In_ PBL_IMG_FILE ImageFile
,
665 _In_ BL_MEMORY_TYPE MemoryType
,
666 _Inout_ PVOID
* ImageBase
,
667 _Out_opt_ PULONG ImageSize
,
668 _Inout_opt_ PVOID Hash
,
673 ULONG FileSize
, HeaderSize
;
674 BL_IMG_FILE LocalFileBuffer
;
675 PBL_IMG_FILE LocalFile
;
676 PVOID VirtualAddress
, PreferredBase
, ImageBuffer
, CertBuffer
, HashBuffer
;
677 ULONGLONG VirtualSize
;
678 PIMAGE_DATA_DIRECTORY CertDirectory
;
679 PHYSICAL_ADDRESS PhysicalAddress
;
680 PIMAGE_NT_HEADERS NtHeaders
;
681 USHORT SectionCount
, CheckSum
, PartialSum
, FinalSum
;
682 PIMAGE_SECTION_HEADER Section
;
683 ULONG_PTR EndOfHeaders
, SectionStart
, Slack
, SectionEnd
;
684 ULONG i
, SectionSize
, RawSize
, BytesRead
, RemainingLength
, Offset
, AlignSize
;
685 BOOLEAN First
, ImageHashValid
;
686 UCHAR LocalBuffer
[1024];
687 UCHAR TrustedBootInformation
[52];
688 ULONG WorkaroundForBinutils
;
690 /* Initialize locals */
691 WorkaroundForBinutils
= 0;
696 VirtualAddress
= NULL
;
698 CertDirectory
= NULL
;
702 ImageHashValid
= FALSE
;
703 RtlZeroMemory(&TrustedBootInformation
, sizeof(TrustedBootInformation
));
705 /* Get the size of the image */
706 Status
= ImgpGetFileSize(ImageFile
, &FileSize
);
707 if (!NT_SUCCESS(Status
))
709 return STATUS_FILE_INVALID
;
712 /* Allocate a flat buffer for it */
713 Status
= BlImgAllocateImageBuffer(&ImageBuffer
, BlLoaderData
, FileSize
, 0);
714 if (!NT_SUCCESS(Status
))
719 /* Read the whole file flat for now */
720 Status
= ImgpReadAtFileOffset(ImageFile
, FileSize
, 0, ImageBuffer
, NULL
);
721 if (!NT_SUCCESS(Status
))
726 /* Build a local file handle */
727 LocalFile
= &LocalFileBuffer
;
728 LocalFileBuffer
.FileName
= ImageFile
->FileName
;
729 LocalFileBuffer
.Flags
= BL_IMG_MEMORY_FILE
| BL_IMG_VALID_FILE
;
730 LocalFileBuffer
.BaseAddress
= ImageBuffer
;
731 LocalFileBuffer
.FileSize
= FileSize
;
733 /* Get the NT headers of the file */
734 Status
= RtlImageNtHeaderEx(0, ImageBuffer
, FileSize
, &NtHeaders
);
735 if (!NT_SUCCESS(Status
))
740 /* Check if we should validate the machine type */
741 if (Flags
& BL_LOAD_PE_IMG_CHECK_MACHINE
)
743 /* Is it different than our current machine type? */
745 if (NtHeaders
->FileHeader
.Machine
!= IMAGE_FILE_MACHINE_AMD64
)
747 if (NtHeaders
->FileHeader
.Machine
!= IMAGE_FILE_MACHINE_I386
)
750 /* Is it x86 (implying we are x64) ? */
751 if (NtHeaders
->FileHeader
.Machine
== IMAGE_FILE_MACHINE_I386
)
753 /* Return special error code */
754 Status
= STATUS_INVALID_IMAGE_WIN_32
;
756 else if (NtHeaders
->FileHeader
.Machine
== IMAGE_FILE_MACHINE_AMD64
)
758 /* Otherwise, it's x64 but we are x86 */
759 Status
= STATUS_INVALID_IMAGE_WIN_64
;
763 /* Or it's ARM or something... */
764 Status
= STATUS_INVALID_IMAGE_FORMAT
;
767 /* Return with the distinguished error code */
772 /* Check if we should validate the subsystem */
773 if (Flags
& BL_LOAD_PE_IMG_CHECK_SUBSYSTEM
)
775 /* It must be a Windows boot Application */
776 if (NtHeaders
->OptionalHeader
.Subsystem
!=
777 IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION
)
779 Status
= STATUS_INVALID_IMAGE_FORMAT
;
784 /* Check if we should validate the /INTEGRITYCHECK flag */
785 if (Flags
& BL_LOAD_PE_IMG_CHECK_FORCED_INTEGRITY
)
787 /* Check if it's there */
788 if (!(NtHeaders
->OptionalHeader
.DllCharacteristics
&
789 IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY
))
791 /* Nope, fail otherwise */
792 Status
= STATUS_INVALID_IMAGE_FORMAT
;
797 /* Check if we should compute the image hash */
798 if ((Flags
& BL_LOAD_PE_IMG_COMPUTE_HASH
) || (Hash
))
800 EfiPrintf(L
"No hash support\r\n");
803 /* Read the current base address, if any */
804 VirtualAddress
= *ImageBase
;
806 /* Get the virtual size of the image */
807 VirtualSize
= NtHeaders
->OptionalHeader
.SizeOfImage
;
809 /* Safely align the virtual size to a page */
810 Status
= RtlULongLongAdd(VirtualSize
,
813 if (!NT_SUCCESS(Status
))
817 VirtualSize
= ALIGN_DOWN_BY(VirtualSize
, PAGE_SIZE
);
819 /* Make sure the image isn't larger than 4GB */
820 if (VirtualSize
> ULONG_MAX
)
822 Status
= STATUS_INVALID_IMAGE_FORMAT
;
826 /* Check if we have a buffer already */
827 if (Flags
& BL_LOAD_IMG_EXISTING_BUFFER
)
829 /* Check if it's too small */
830 if (*ImageSize
< VirtualSize
)
832 /* Fail, letting the caller know how big to make it */
833 *ImageSize
= VirtualSize
;
834 Status
= STATUS_BUFFER_TOO_SMALL
;
839 /* Allocate the buffer with the flags and type the caller wants */
840 Status
= BlImgAllocateImageBuffer(&VirtualAddress
,
846 /* Bail out if allocation failed, or existing buffer is too small */
847 if (!NT_SUCCESS(Status
))
852 /* Read the size of the headers */
853 HeaderSize
= NtHeaders
->OptionalHeader
.SizeOfHeaders
;
854 if (VirtualSize
< HeaderSize
)
856 /* Bail out if they're bigger than the image! */
857 Status
= STATUS_INVALID_IMAGE_FORMAT
;
861 /* Now read the header into the buffer */
862 Status
= ImgpReadAtFileOffset(LocalFile
, HeaderSize
, 0, VirtualAddress
, NULL
);
863 if (!NT_SUCCESS(Status
))
868 /* Get the NT headers of the file */
869 Status
= RtlImageNtHeaderEx(0, VirtualAddress
, HeaderSize
, &NtHeaders
);
870 if (!NT_SUCCESS(Status
))
877 /* Record how many sections we have */
878 SectionCount
= NtHeaders
->FileHeader
.NumberOfSections
;
880 /* Capture the current checksum and reset it */
881 CheckSum
= NtHeaders
->OptionalHeader
.CheckSum
;
882 NtHeaders
->OptionalHeader
.CheckSum
= 0;
884 /* Calculate the checksum of the header, and restore the original one */
885 PartialSum
= BlUtlCheckSum(0,
888 BL_UTL_CHECKSUM_COMPLEMENT
|
889 BL_UTL_CHECKSUM_USHORT_BUFFER
);
890 NtHeaders
->OptionalHeader
.CheckSum
= CheckSum
;
892 /* Record our current position (right after the headers) */
893 EndOfHeaders
= (ULONG_PTR
)VirtualAddress
+ HeaderSize
;
895 /* Get the first section and iterate through each one */
896 Section
= IMAGE_FIRST_SECTION(NtHeaders
);
897 for (i
= 0; i
< SectionCount
; i
++)
899 /* Compute where this section starts */
900 SectionStart
= (ULONG_PTR
)VirtualAddress
+ Section
->VirtualAddress
;
902 /* Make sure that the section fits within the image */
903 if ((VirtualSize
< Section
->VirtualAddress
) ||
904 ((PVOID
)SectionStart
< VirtualAddress
))
906 EfiPrintf(L
"fail 1\r\n");
907 Status
= STATUS_INVALID_IMAGE_FORMAT
;
911 /* Check if there's slack space between header end and the section */
912 if (!(First
) && (EndOfHeaders
< SectionStart
))
915 Slack
= SectionStart
- EndOfHeaders
;
916 RtlZeroMemory((PVOID
)EndOfHeaders
, Slack
);
919 /* Get the section virtual size and the raw size */
920 SectionSize
= Section
->Misc
.VirtualSize
;
921 RawSize
= Section
->SizeOfRawData
;
923 /* Safely align the raw size by 2 */
924 Status
= RtlULongAdd(RawSize
, 1, &AlignSize
);
925 if (!NT_SUCCESS(Status
))
929 AlignSize
= ALIGN_DOWN_BY(AlignSize
, 2);
931 /* IF we don't have a virtual size, use the raw size */
934 SectionSize
= RawSize
;
937 /* If we don't have raw data, ignore the raw size */
938 if (!Section
->PointerToRawData
)
942 else if (SectionSize
< RawSize
)
944 /* And if the virtual size is smaller, use it as the final size */
945 RawSize
= SectionSize
;
948 /* Make sure that the section doesn't overflow in memory */
949 Status
= RtlULongAdd(Section
->VirtualAddress
,
952 if (!NT_SUCCESS(Status
))
954 EfiPrintf(L
"fail 21\r\n");
955 Status
= STATUS_INVALID_IMAGE_FORMAT
;
959 /* Make sure that it fits within the image */
960 if (VirtualSize
< SectionEnd
)
962 Status
= STATUS_INVALID_IMAGE_FORMAT
;
966 /* Make sure it doesn't overflow on disk */
967 Status
= RtlULongAdd(Section
->VirtualAddress
,
970 if (!NT_SUCCESS(Status
))
972 EfiPrintf(L
"fail 31\r\n");
973 Status
= STATUS_INVALID_IMAGE_FORMAT
;
977 /* Make sure that it fits within the disk image as well */
978 if (VirtualSize
< SectionEnd
)
980 Status
= STATUS_INVALID_IMAGE_FORMAT
;
984 /* So does this section have a valid size after all? */
987 /* Are we in the first iteration? */
990 /* FUCK YOU BINUTILS */
991 if (NtHeaders
->OptionalHeader
.MajorLinkerVersion
< 7)
993 if ((*(PULONG
)&Section
->Name
== 'ler.') && (RawSize
< AlignSize
))
995 /* Piece of shit won't build relocations when you tell it to,
996 * either by using --emit-relocs or --dynamicbase. People online
997 * have found out that by using -pie-executable you can get this
998 * to happen, but then it turns out that the .reloc section is
999 * incorrectly sized, and results in a corrupt PE. However, they
1000 * still compute the checksum using the correct value. What idiots.
1002 WorkaroundForBinutils
= AlignSize
- RawSize
;
1003 AlignSize
-= WorkaroundForBinutils
;
1007 /* Yes, read the section data */
1008 Status
= ImgpReadAtFileOffset(LocalFile
,
1010 Section
->PointerToRawData
,
1011 (PVOID
)SectionStart
,
1013 if (!NT_SUCCESS(Status
))
1018 /* Update our current offset */
1019 Offset
= AlignSize
+ Section
->PointerToRawData
;
1021 /* Update the checksum to include this section */
1022 PartialSum
= BlUtlCheckSum(PartialSum
,
1023 (PUCHAR
)SectionStart
,
1025 BL_UTL_CHECKSUM_COMPLEMENT
|
1026 BL_UTL_CHECKSUM_USHORT_BUFFER
);
1027 AlignSize
+= WorkaroundForBinutils
;
1031 /* Are we in the first iteration? */
1034 /* Is there space at the end of the section? */
1035 if (RawSize
< SectionSize
)
1037 /* Zero out the slack space that's there */
1038 Slack
= SectionSize
- RawSize
;
1039 RtlZeroMemory((PVOID
)(SectionStart
+ RawSize
), Slack
);
1042 /* Update our tail offset */
1043 EndOfHeaders
= SectionStart
+ SectionSize
;
1046 /* Move to the next section */
1050 /* Are we in the first iteration? */
1053 /* Go to the end of the file */
1054 SectionStart
= (ULONG_PTR
)VirtualAddress
+ VirtualSize
;
1056 /* Is there still some slack space left? */
1057 if (EndOfHeaders
< SectionStart
)
1060 Slack
= SectionStart
- EndOfHeaders
;
1061 RtlZeroMemory((PVOID
)EndOfHeaders
, Slack
);
1065 /* Did the first iteration complete OK? */
1066 if ((NT_SUCCESS(Status
)) && !(First
))
1068 /* Check how many non-image bytes are left in the file */
1069 RemainingLength
= FileSize
- Offset
;
1070 while (RemainingLength
)
1072 /* See if the read will fit into our local buffer */
1073 if (RemainingLength
>= sizeof(LocalBuffer
))
1076 BytesRead
= sizeof(LocalBuffer
);
1080 /* Yes, but there's less to read */
1081 BytesRead
= RemainingLength
;
1084 /* Read 1024 bytes into the local buffer */
1085 Status
= ImgpReadAtFileOffset(LocalFile
,
1090 if (!(NT_SUCCESS(Status
)) || !(BytesRead
))
1092 Status
= STATUS_FILE_INVALID
;
1096 /* Advance the offset and reduce the length */
1097 RemainingLength
-= BytesRead
;
1098 Offset
+= BytesRead
;
1100 /* Compute the checksum of this leftover space */
1101 PartialSum
= BlUtlCheckSum(PartialSum
,
1104 BL_UTL_CHECKSUM_COMPLEMENT
|
1105 BL_UTL_CHECKSUM_USHORT_BUFFER
);
1108 /* Finally, calculate the final checksum and compare it */
1109 FinalSum
= FileSize
+ PartialSum
+ WorkaroundForBinutils
;
1110 if ((FinalSum
!= CheckSum
) && (PartialSum
== 0xFFFF))
1112 /* It hit overflow, so set it to the file size */
1113 FinalSum
= FileSize
;
1116 /* If the checksum doesn't match, and caller is enforcing, bail out */
1117 if ((FinalSum
!= CheckSum
) &&
1118 !(Flags
& BL_LOAD_PE_IMG_IGNORE_CHECKSUM_MISMATCH
))
1120 Status
= STATUS_IMAGE_CHECKSUM_MISMATCH
;
1125 /* Check if the .rsrc section should be checked with the filename */
1126 if (Flags
& BL_LOAD_PE_IMG_VALIDATE_ORIGINAL_FILENAME
)
1128 EfiPrintf(L
"Not yet supported\r\n");
1129 Status
= 0xC0430007; // STATUS_SECUREBOOT_FILE_REPLACED
1133 /* Check if we should relocate */
1134 if (!(Flags
& BL_LOAD_PE_IMG_SKIP_RELOCATIONS
))
1136 /* Check if we loaded at a different address */
1137 PreferredBase
= (PVOID
)NtHeaders
->OptionalHeader
.ImageBase
;
1138 if (VirtualAddress
!= PreferredBase
)
1140 /* Yep -- do relocations */
1141 Status
= LdrRelocateImage(VirtualAddress
,
1142 "Boot Environment Library",
1144 STATUS_UNSUCCESSFUL
,
1145 STATUS_INVALID_IMAGE_FORMAT
);
1146 if (!NT_SUCCESS(Status
))
1155 /* Check if the image hash was valid */
1156 if (!ImageHashValid
)
1158 /* Send a TPM/SI notification without a context */
1159 BlEnNotifyEvent(0x10000002, NULL
);
1162 /* Now send a TPM/SI notification with the hash of the loaded image */
1163 BlMmTranslateVirtualAddress(VirtualAddress
, &Context
.ImageBase
);
1164 Context
.HashAlgorithm
= HashAlgorithm
;
1165 Context
.HashSize
= HashSize
;
1166 Context
.FileName
= ImageFile
->FileName
;
1167 Context
.ImageSize
= VirtualSize
;
1168 Context
.HashValid
= ImageHashValid
;
1169 Context
.Hash
= Hash
;
1170 BlEnNotifyEvent(0x10000002, &Context
);
1173 /* Return the loaded address to the caller */
1174 *ImageBase
= VirtualAddress
;
1176 /* If the caller wanted the image size, return it too */
1179 *ImageSize
= VirtualSize
;
1183 /* Check if we computed the image hash OK */
1186 /* Then free the information that ImgpValidateImageHash set up */
1187 EfiPrintf(L
"leadking trusted boot\r\n");
1188 //ImgpDestroyTrustedBootInformation(&TrustedBootInformation);
1191 /* Check if we had a hash buffer */
1195 EfiPrintf(L
"Leadking hash: %p\r\n", HashBuffer
);
1196 //MmPapFreePages(HashBuffer, TRUE);
1199 /* Check if we have a certificate directory */
1200 if ((CertBuffer
) && (CertDirectory
))
1203 BlImgUnallocateImageBuffer(CertBuffer
, CertDirectory
->Size
, 0);
1206 /* Check if we had an image buffer allocated */
1207 if ((ImageBuffer
) && (FileSize
))
1210 BlImgUnallocateImageBuffer(ImageBuffer
, FileSize
, 0);
1213 /* Check if we had a local file handle */
1217 ImgpCloseFile(LocalFile
);
1220 /* Check if this is the failure path */
1221 if (!NT_SUCCESS(Status
))
1223 /* Check if we had started mapping in the image already */
1224 if ((VirtualAddress
) && !(Flags
& BL_LOAD_PE_IMG_EXISTING_BUFFER
))
1226 /* Into a virtual buffer? */
1227 if (Flags
& BL_LOAD_PE_IMG_VIRTUAL_BUFFER
)
1229 /* Unmap and free it */
1230 BlMmUnmapVirtualAddressEx(VirtualAddress
, VirtualSize
);
1231 PhysicalAddress
.QuadPart
= (ULONG_PTR
)VirtualAddress
;
1232 BlMmFreePhysicalPages(PhysicalAddress
);
1236 /* Into a physical buffer -- free it */
1237 EfiPrintf(L
"Leaking physical pages\r\n");
1238 // MmPapFreePages(VirtualAddress, TRUE);
1243 /* Return back to caller */
1248 BlImgLoadPEImageEx (
1249 _In_ ULONG DeviceId
,
1250 _In_ BL_MEMORY_TYPE MemoryType
,
1252 _Out_ PVOID
* ImageBase
,
1253 _Out_ PULONG ImageSize
,
1258 BL_IMG_FILE ImageFile
;
1261 /* Initialize the image file structure */
1262 ImageFile
.Flags
= 0;
1263 ImageFile
.FileName
= NULL
;
1265 /* Check if the required parameter are missing */
1266 if (!(ImageBase
) || !(Path
))
1268 return STATUS_INVALID_PARAMETER
;
1271 /* If we are loading a pre-allocated image, make sure we have it */
1272 if ((Flags
& BL_LOAD_IMG_EXISTING_BUFFER
) && (!(*ImageBase
) || !(ImageSize
)))
1274 return STATUS_INVALID_PARAMETER
;
1277 /* Load the file from disk */
1278 Status
= ImgpOpenFile(DeviceId
, Path
, 0, &ImageFile
);
1279 if (NT_SUCCESS(Status
))
1281 /* If that worked, do the PE parsing */
1282 Status
= ImgpLoadPEImage(&ImageFile
,
1290 /* Close the image file and return back to caller */
1291 ImgpCloseFile(&ImageFile
);
1296 BlImgLoadBootApplication (
1297 _In_ PBL_LOADED_APPLICATION_ENTRY BootEntry
,
1298 _Out_ PULONG AppHandle
1302 PULONGLONG AllowedList
;
1303 ULONGLONG AllowedCount
;
1304 ULONG i
, DeviceId
, ImageSize
, Flags
, ListSize
;
1305 LARGE_INTEGER Frequency
;
1306 PVOID UnlockCode
, ImageBase
;
1307 PBL_DEVICE_DESCRIPTOR Device
, BitLockerDevice
;
1309 PBL_APPLICATION_ENTRY AppEntry
;
1310 PBL_IMG_FILE ImageFile
;
1311 BOOLEAN DisableIntegrity
, TestSigning
;
1313 PBL_IMAGE_APPLICATION_ENTRY ImageAppEntry
;
1315 /* Initialize all locals */
1316 BitLockerDevice
= NULL
;
1321 ImageAppEntry
= NULL
;
1327 /* Check for "allowed in-memory settings" */
1328 Status
= BlpGetBootOptionIntegerList(BootEntry
->BcdData
,
1329 BcdLibraryIntegerList_AllowedInMemorySettings
,
1333 if (Status
== STATUS_SUCCESS
)
1335 /* Loop through the list of allowed setting */
1336 for (i
= 0; i
< AllowedCount
; i
++)
1338 /* Find the super undocumented one */
1339 if (AllowedList
[i
] == BcdLibraryInteger_UndocumentedMagic
)
1341 /* If it's present, append the current perf frequence to it */
1342 BlTimeQueryPerformanceCounter(&Frequency
);
1343 BlAppendBootOptionInteger(BootEntry
,
1344 BcdLibraryInteger_UndocumentedMagic
,
1345 Frequency
.QuadPart
);
1350 #if BL_BITLOCKER_SUPPORT
1351 /* Do bitlocker stuff */
1352 Status
= BlFveSecureBootUnlockBootDevice(BootEntry
, &BitLockerDevice
, &UnlockCode
);
1353 if (!NT_SUCCESS(Status
))
1359 /* Get the device on which this application is on*/
1360 Status
= BlGetBootOptionDevice(BootEntry
->BcdData
,
1361 BcdLibraryDevice_ApplicationDevice
,
1364 if (!NT_SUCCESS(Status
))
1369 /* Get the path of the application */
1370 Status
= BlGetBootOptionString(BootEntry
->BcdData
,
1371 BcdLibraryString_ApplicationPath
,
1373 if (!NT_SUCCESS(Status
))
1378 /* Open the device */
1379 Status
= BlpDeviceOpen(Device
,
1380 BL_DEVICE_READ_ACCESS
,
1383 if (!NT_SUCCESS(Status
))
1388 /* Check for integrity BCD options */
1389 BlImgQueryCodeIntegrityBootOptions(BootEntry
,
1394 RtlZeroMemory(&Context
, sizeof(Context
);
1395 Context
.BootEntry
= BootEntry
;
1396 BlEnNotifyEvent(0x10000003, &Context
);
1399 /* Enable signing and hashing checks if integrity is enabled */
1401 if (!DisableIntegrity
)
1406 /* Now call the PE loader to load the image */
1407 Status
= BlImgLoadPEImageEx(DeviceId
,
1414 if (!NT_SUCCESS(Status
))
1420 /* Check if we should notify the debugger of load */
1421 if (BdDebugTransitions
)
1425 Status
= BlBdInitialize();
1426 if (NT_SUCCESS(Status
))
1428 /* Check if it's enabled */
1429 if (BlBdDebuggerEnabled())
1431 /* Send it an image load notification */
1432 BdDebuggerNotPresent
= FALSE
;
1433 RtlInitUnicodeString(&PathString
, Path
);
1434 BlBdLoadImageSymbols(&PathString
, ImageBase
);
1440 #if BL_BITLOCKER_SUPPORT
1441 /* Do bitlocker stuff */
1442 Status
= BlSecureBootCheckPolicyOnFveDevice(BitLockerDevice
);
1443 if (!NT_SUCCESS(Status
))
1449 #if BL_BITLOCKER_SUPPORT
1450 /* Do bitlocker stuff */
1451 Status
= BlFveSecureBootCheckpointBootApp(BootEntry
, BitLockerDevice
, Hash
, UnlockCode
);
1452 if (!NT_SUCCESS(Status
))
1458 /* Get the BCD option size */
1459 ListSize
= BlGetBootOptionListSize(BootEntry
->BcdData
);
1461 /* Allocate an entry with all the BCD options */
1462 AppEntry
= BlMmAllocateHeap(ListSize
+ sizeof(*AppEntry
));
1465 Status
= STATUS_NO_MEMORY
;
1470 RtlZeroMemory(AppEntry
, sizeof(*AppEntry
));
1473 strcpy(AppEntry
->Signature
, "BTAPENT");
1474 AppEntry
->Guid
= BootEntry
->Guid
;
1475 AppEntry
->Flags
= BootEntry
->Flags
;
1477 /* Copy the BCD options */
1478 RtlCopyMemory(&AppEntry
->BcdData
, BootEntry
->BcdData
, ListSize
);
1480 /* Allocate the image entry */
1481 ImageAppEntry
= BlMmAllocateHeap(sizeof(*ImageAppEntry
));
1484 Status
= STATUS_NO_MEMORY
;
1489 ImageAppEntry
->ImageBase
= ImageBase
;
1490 ImageAppEntry
->ImageSize
= ImageSize
;
1491 ImageAppEntry
->AppEntry
= AppEntry
;
1493 /* Check if this is the first entry */
1494 if (!IapTableEntries
)
1496 /* Allocate two entries */
1497 IapAllocatedTableEntries
= 0;
1498 IapTableEntries
= 2;
1499 IapImageTable
= BlMmAllocateHeap(IapTableEntries
* sizeof(PVOID
));
1502 Status
= STATUS_NO_MEMORY
;
1506 /* Zero out the entries for now */
1507 RtlZeroMemory(IapImageTable
, IapTableEntries
* sizeof(PVOID
));
1510 /* Set this entry into the table */
1511 Status
= BlTblSetEntry(&IapImageTable
,
1515 TblDoNotPurgeEntry
);
1518 /* Is the device open? Close it if so */
1521 BlDeviceClose(DeviceId
);
1524 /* Is there an allocated device? Free it */
1527 BlMmFreeHeap(Device
);
1530 /* Is there an allocated path? Free it */
1536 /* Is there a bitlocker device? Free it */
1537 if (BitLockerDevice
)
1539 BlMmFreeHeap(BitLockerDevice
);
1542 /* Is there a bitlocker unlock code? Free it */
1545 BlMmFreeHeap(UnlockCode
);
1548 /* Did we succeed in creating an entry? */
1549 if (NT_SUCCESS(Status
))
1551 /* Remember there's one more in the table */
1552 IapAllocatedTableEntries
++;
1554 /* Return success */
1558 /* Did we load an image after all? */
1562 BlImgUnLoadImage(ImageBase
, ImageSize
, 0);
1565 /* Did we allocate an app entry? Free it */
1568 BlMmFreeHeap(AppEntry
);
1571 /* Do we have an image file entry? Free it */
1574 BlMmFreeHeap(ImageFile
);
1577 /* Do we no longer have a single entry in the table? */
1578 if (!(IapAllocatedTableEntries
) && (IapImageTable
))
1580 /* Free and destroy the table */
1581 BlMmFreeHeap(IapImageTable
);
1582 IapTableEntries
= 0;
1583 IapImageTable
= NULL
;
1586 /* Return the failure code */
1591 BlpPdParseReturnArguments (
1592 _In_ PBL_RETURN_ARGUMENTS ReturnArguments
1595 /* Check if any custom data was returned */
1596 if (ReturnArguments
->DataPage
== 0)
1598 /* Nope, nothing to do */
1599 return STATUS_SUCCESS
;
1602 /* Yes, we have to parse it */
1603 EfiPrintf(L
"Return arguments not supported\r\n");
1604 return STATUS_NOT_IMPLEMENTED
;
1609 _In_ PLIST_ENTRY MemoryMap
,
1610 _In_ PBL_IMAGE_PARAMETERS ImageParameters
,
1611 _In_ ULONG WhichTypes
,
1615 return STATUS_SUCCESS
;
1619 ImgpInitializeBootApplicationParameters (
1620 _In_ PBL_IMAGE_PARAMETERS ImageParameters
,
1621 _In_ PBL_APPLICATION_ENTRY AppEntry
,
1622 _In_ PVOID ImageBase
,
1623 _In_ ULONG ImageSize
1627 PIMAGE_NT_HEADERS NtHeaders
;
1628 BL_IMAGE_PARAMETERS MemoryParameters
;
1629 LIST_ENTRY MemoryList
;
1631 Status
= RtlImageNtHeaderEx(0, ImageBase
, ImageSize
, &NtHeaders
);
1632 if (!NT_SUCCESS(Status
))
1637 MemoryParameters
.BufferSize
= 0;
1639 Status
= BlMmGetMemoryMap(&MemoryList
,
1641 BL_MM_INCLUDE_FIRMWARE_MEMORY
|
1642 BL_MM_INCLUDE_MAPPED_ALLOCATED
|
1643 BL_MM_INCLUDE_MAPPED_UNALLOCATED
|
1644 BL_MM_INCLUDE_UNMAPPED_ALLOCATED
|
1645 BL_MM_INCLUDE_RESERVED_ALLOCATED
,
1647 if ((Status
!= STATUS_BUFFER_TOO_SMALL
) && (Status
!= STATUS_SUCCESS
))
1652 return STATUS_SUCCESS
;
1656 ImgArchEfiStartBootApplication (
1657 _In_ PBL_APPLICATION_ENTRY AppEntry
,
1658 _In_ PVOID ImageBase
,
1659 _In_ ULONG ImageSize
,
1660 _In_ PBL_RETURN_ARGUMENTS ReturnArguments
1663 KDESCRIPTOR Gdt
, Idt
;
1664 ULONG BootSizeNeeded
;
1667 PIMAGE_NT_HEADERS NtHeaders
;
1668 PVOID NewStack
, NewGdt
, NewIdt
;
1669 BL_IMAGE_PARAMETERS Parameters
;
1671 /* Read the current IDT and GDT */
1675 /* Allocate space for the IDT, GDT, and 24 pages of stack */
1676 BootSizeNeeded
= (ULONG
)PAGE_ALIGN(Idt
.Limit
+ Gdt
.Limit
+ 1 + 25 * PAGE_SIZE
);
1677 Status
= MmPapAllocatePagesInRange(&BootData
,
1679 BootSizeNeeded
>> PAGE_SHIFT
,
1684 if (!NT_SUCCESS(Status
))
1689 /* Zero the boot data */
1690 RtlZeroMemory(BootData
, BootSizeNeeded
);
1692 /* Set the new stack, GDT and IDT */
1693 NewStack
= (PVOID
)((ULONG_PTR
)BootData
+ (24 * PAGE_SIZE
) - 8);
1694 NewGdt
= (PVOID
)((ULONG_PTR
)BootData
+ (24 * PAGE_SIZE
));
1695 NewIdt
= (PVOID
)((ULONG_PTR
)BootData
+ (24 * PAGE_SIZE
) + Gdt
.Limit
+ 1);
1697 /* Copy the current (firmware) GDT and IDT */
1698 RtlCopyMemory(NewGdt
, (PVOID
)Gdt
.Base
, Gdt
.Limit
+ 1);
1699 RtlCopyMemory(NewIdt
, (PVOID
)Idt
.Base
, Idt
.Limit
+ 1);
1701 /* Read the NT headers so that we can get the entrypoint later on */
1702 RtlImageNtHeaderEx(0, ImageBase
, ImageSize
, &NtHeaders
);
1704 /* Prepare the application parameters */
1705 RtlZeroMemory(&Parameters
, sizeof(Parameters
));
1706 Status
= ImgpInitializeBootApplicationParameters(&Parameters
,
1710 if (NT_SUCCESS(Status
))
1712 /* Set the firmware GDT/IDT as the one the application will use */
1713 BootAppGdtRegister
= Gdt
;
1714 BootAppIdtRegister
= Idt
;
1716 /* Set the entrypoint, parameters, and stack */
1717 BootApp32EntryRoutine
= (PVOID
)((ULONG_PTR
)ImageBase
+
1718 NtHeaders
->OptionalHeader
.
1719 AddressOfEntryPoint
);
1720 BootApp32Parameters
= Parameters
.Buffer
;
1721 BootApp32Stack
= NewStack
;
1724 /* Disable the kernel debugger */
1727 /* Not yet implemented. This is the last step! */
1728 EfiPrintf(L
"EFI APPLICATION START!!!\r\n");
1731 Archx86TransferTo32BitApplicationAsm();
1733 /* Not yet implemented. This is the last step! */
1734 EfiPrintf(L
"EFI APPLICATION RETURNED!!!\r\n");
1735 EfiStall(100000000);
1738 /* Re-enable the kernel debugger */
1744 /* Check if we had boot data allocated */
1748 //MmPapFreePages(bootData, TRUE);
1752 return STATUS_NOT_IMPLEMENTED
;
1756 BlImgStartBootApplication (
1757 _In_ ULONG AppHandle
,
1758 _Inout_opt_ PBL_RETURN_ARGUMENTS ReturnArguments
1761 PBL_IMAGE_APPLICATION_ENTRY ImageAppEntry
;
1762 BL_RETURN_ARGUMENTS LocalReturnArgs
;
1763 PBL_FILE_SYSTEM_ENTRY FileSystem
;
1764 PLIST_ENTRY NextEntry
, ListHead
;
1767 /* Check if we don't have an argument structure */
1768 if (!ReturnArguments
)
1770 /* Initialize a local copy and use it instead */
1771 LocalReturnArgs
.Version
= BL_RETURN_ARGUMENTS_VERSION
;
1772 LocalReturnArgs
.Status
= STATUS_SUCCESS
;
1773 LocalReturnArgs
.Flags
= 0;
1774 LocalReturnArgs
.DataPage
= 0;
1775 LocalReturnArgs
.DataSize
= 0;
1776 ReturnArguments
= &LocalReturnArgs
;
1779 /* Make sure the handle index is valid */
1780 if (IapTableEntries
<= AppHandle
)
1782 return STATUS_INVALID_PARAMETER
;
1785 /* Get the entry for this handle, making sure it exists */
1786 ImageAppEntry
= IapImageTable
[AppHandle
];
1789 return STATUS_INVALID_PARAMETER
;
1792 /* Loop the registered file systems */
1793 ListHead
= &RegisteredFileSystems
;
1794 NextEntry
= RegisteredFileSystems
.Flink
;
1795 while (NextEntry
!= ListHead
)
1797 /* Get the filesystem entry */
1798 FileSystem
= CONTAINING_RECORD(NextEntry
,
1799 BL_FILE_SYSTEM_ENTRY
,
1802 /* See if it has a purge callback */
1803 if (FileSystem
->PurgeCallback
)
1806 FileSystem
->PurgeCallback();
1809 /* Move to the next entry */
1810 NextEntry
= NextEntry
->Flink
;
1813 /* TODO -- flush the block I/O cache too */
1814 //BlockIoPurgeCache();
1816 /* Call into EFI land to start the boot application */
1817 Status
= ImgArchEfiStartBootApplication(ImageAppEntry
->AppEntry
,
1818 ImageAppEntry
->ImageBase
,
1819 ImageAppEntry
->ImageSize
,
1822 /* Parse any arguments we got on the way back */
1823 BlpPdParseReturnArguments(ReturnArguments
);
1825 #if BL_BITLOCKER_SUPPORT
1826 /* Bitlocker stuff */
1827 FvebpCheckAllPartitions(TRUE
);
1831 /* Notify a TPM/SI event */
1832 BlEnNotifyEvent(0x10000005, NULL
);
1835 /* Reset the display */
1836 BlpDisplayReinitialize();
1838 /* TODO -- reset ETW */
1839 //BlpLogInitialize();
1846 BlImgUnloadBootApplication (
1847 _In_ ULONG AppHandle
1850 PBL_IMAGE_APPLICATION_ENTRY ImageAppEntry
;
1853 /* Make sure the handle index is valid */
1854 if (IapTableEntries
<= AppHandle
)
1856 return STATUS_INVALID_PARAMETER
;
1859 /* Get the entry for this handle, making sure it exists */
1860 ImageAppEntry
= IapImageTable
[AppHandle
];
1863 return STATUS_INVALID_PARAMETER
;
1866 /* Unload the image */
1867 Status
= BlImgUnLoadImage(ImageAppEntry
->ImageBase
,
1868 ImageAppEntry
->ImageSize
,
1870 if (NT_SUCCESS(Status
))
1872 /* Normalize the success code */
1873 Status
= STATUS_SUCCESS
;
1877 /* Normalize the failure code */
1878 Status
= STATUS_MEMORY_NOT_ALLOCATED
;
1881 /* Free the entry and the image entry as well */
1882 BlMmFreeHeap(ImageAppEntry
->AppEntry
);
1883 BlMmFreeHeap(ImageAppEntry
);
1885 /* Clear the handle */
1886 IapImageTable
[AppHandle
] = NULL
;
1888 /* Free one entry */
1889 if (!(--IapAllocatedTableEntries
))
1891 /* There are no more, so get rid of the table itself */
1892 BlMmFreeHeap(IapImageTable
);
1893 IapImageTable
= NULL
;
1894 IapTableEntries
= 0;