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
;
21 KDESCRIPTOR GdtRegister
;
22 KDESCRIPTOR IdtRegister
;
23 KDESCRIPTOR BootAppGdtRegister
;
24 KDESCRIPTOR BootAppIdtRegister
;
25 PVOID BootApp32EntryRoutine
;
26 PBOOT_APPLICATION_PARAMETER_BLOCK BootApp32Parameters
;
30 /* FUNCTIONS *****************************************************************/
34 _In_ PBL_IMG_FILE File
,
40 BL_FILE_INFORMATION FileInformation
;
42 /* Check if the file was memory mapped */
43 if (File
->Flags
& BL_IMG_MEMORY_FILE
)
45 /* Just read the size of the mapping */
46 Size
= File
->FileSize
;
50 /* Do file I/O to get the file size */
51 Status
= BlFileGetInformation(File
->FileId
,
53 if (!NT_SUCCESS(Status
))
58 /* We only support files less than 4GB in the Image Mapped */
59 Size
= FileInformation
.Size
;
60 if (FileInformation
.Size
> ULONG_MAX
)
62 return STATUS_NOT_SUPPORTED
;
66 /* Return the size and success */
68 return STATUS_SUCCESS
;
72 ImgpReadAtFileOffset (
73 _In_ PBL_IMG_FILE File
,
75 _In_ ULONGLONG ByteOffset
,
77 _Out_ PULONG BytesReturned
82 /* Check what if this is a mapped file or not */
83 if (File
->Flags
& BL_IMG_MEMORY_FILE
)
85 /* Check if the boundaries are within the file size */
86 if ((ByteOffset
+ Size
) <= File
->FileSize
)
88 /* Yep, copy into the caller-supplied buffer */
90 (PVOID
)((ULONG_PTR
)File
->BaseAddress
+ (ULONG_PTR
)ByteOffset
),
93 /* If caller wanted to know, return the size copied */
96 *BytesReturned
= Size
;
100 Status
= STATUS_SUCCESS
;
105 Status
= STATUS_INVALID_PARAMETER
;
110 /* Issue the file I/O instead */
111 Status
= BlFileReadAtOffsetEx(File
->FileId
,
119 /* Return the final status */
126 _In_ PWCHAR FileName
,
128 _Out_ PBL_IMG_FILE NewFile
133 ULONGLONG RemoteFileSize
;
134 PVOID RemoteFileAddress
;
137 /* First, try to see if BD has this file remotely */
138 Status
= BlBdPullRemoteFile(FileName
,
141 if (NT_SUCCESS(Status
))
143 /* Yep, get the file size and make sure it's < 4GB */
144 FileSize
= RemoteFileSize
;
145 if (RemoteFileSize
<= ULONG_MAX
)
147 /* Remember this is a memory mapped remote file */
148 NewFile
->Flags
|= (BL_IMG_MEMORY_FILE
| BL_IMG_REMOTE_FILE
);
149 NewFile
->FileSize
= FileSize
;
150 NewFile
->BaseAddress
= RemoteFileAddress
;
155 /* Use File I/O instead */
156 Status
= BlFileOpen(DeviceId
,
160 if (!NT_SUCCESS(Status
))
162 /* Bail out on failure */
166 /* Make sure nobody thinks this is a memory file */
167 NewFile
->Flags
&= ~BL_IMG_MEMORY_FILE
;
168 NewFile
->FileId
= FileId
;
171 /* Set common data for both memory and I/O based file */
172 NewFile
->Flags
|= BL_IMG_VALID_FILE
;
173 NewFile
->FileName
= FileName
;
179 _In_ PBL_IMG_FILE File
184 /* Make sure this is a valid file, otherwise no-op */
185 Status
= STATUS_SUCCESS
;
186 if (File
->Flags
& BL_IMG_VALID_FILE
)
188 /* Is this a memory mapped file? */
189 if (!(File
->Flags
& BL_IMG_MEMORY_FILE
))
191 /* Nope, close the file handle */
192 return BlFileClose(File
->FileId
);
195 /* Is this a remote file? */
196 if (File
->Flags
& BL_IMG_REMOTE_FILE
)
198 /* Then only free the memory in that scenario */
199 return MmPapFreePages(File
->BaseAddress
, BL_MM_INCLUDE_MAPPED_ALLOCATED
);
203 /* Return the final status */
208 BlImgUnallocateImageBuffer (
209 _In_ PVOID ImageBase
,
210 _In_ ULONG ImageSize
,
211 _In_ ULONG ImageFlags
214 PHYSICAL_ADDRESS PhysicalAddress
;
217 /* Make sure required parameters are present */
218 if (!(ImageBase
) || !(ImageSize
))
220 return STATUS_INVALID_PARAMETER
;
223 /* Check if this was a physical allocation */
224 if (!(ImageFlags
& BL_LOAD_IMG_VIRTUAL_BUFFER
))
226 return MmPapFreePages(ImageBase
, BL_MM_INCLUDE_MAPPED_ALLOCATED
);
229 /* It's virtual, so translate it first */
230 if (!BlMmTranslateVirtualAddress(ImageBase
, &PhysicalAddress
))
232 return STATUS_INVALID_PARAMETER
;
235 /* Unmap the virtual mapping */
236 Status
= BlMmUnmapVirtualAddressEx(ImageBase
, ROUND_TO_PAGES(ImageSize
));
237 if (NT_SUCCESS(Status
))
239 /* Now free the physical pages */
240 Status
= BlMmFreePhysicalPages(PhysicalAddress
);
248 BlImgAllocateImageBuffer (
249 _Inout_ PVOID
* ImageBuffer
,
250 _In_ ULONG MemoryType
,
251 _In_ ULONGLONG ImageSize
,
256 ULONGLONG Pages
, Size
;
257 PVOID MappedBase
, CurrentBuffer
;
259 PHYSICAL_ADDRESS PhysicalAddress
;
261 /* Read and reset the current buffer address */
262 CurrentBuffer
= *ImageBuffer
;
265 /* Align the image size to page */
266 Size
= ROUND_TO_PAGES(ImageSize
);
268 /* Not sure what this attribute does yet */
270 if (Flags
& BL_LOAD_IMG_UNKNOWN_BUFFER_FLAG
)
272 Attributes
= 0x10000;
275 /* Check if the caller wants a virtual buffer */
276 if (Flags
& BL_LOAD_IMG_VIRTUAL_BUFFER
)
278 /* Set the physical address to the current buffer */
279 PhysicalAddress
.QuadPart
= (ULONG_PTR
)CurrentBuffer
;
280 Pages
= Size
>> PAGE_SHIFT
;
282 /* Allocate the physical pages */
283 Status
= BlMmAllocatePhysicalPages(&PhysicalAddress
,
288 if (!NT_SUCCESS(Status
))
290 /* If that failed, remove allocation attributes */
291 PhysicalAddress
.QuadPart
= 0;
292 Attributes
&= ~BlMemoryValidAllocationAttributeMask
,
293 Status
= BlMmAllocatePhysicalPages(&PhysicalAddress
,
300 /* Check if either attempts succeeded */
301 if (!NT_SUCCESS(Status
))
306 /* Now map the physical buffer at the address requested */
307 MappedBase
= (PVOID
)PhysicalAddress
.LowPart
;
308 Status
= BlMmMapPhysicalAddressEx(&MappedBase
,
312 if (!NT_SUCCESS(Status
))
314 /* Free on failure if needed */
315 BlMmFreePhysicalPages(PhysicalAddress
);
321 /* Otherwise, allocate raw physical pages */
322 MappedBase
= CurrentBuffer
;
323 Pages
= Size
>> PAGE_SHIFT
;
324 Status
= MmPapAllocatePagesInRange(&MappedBase
,
331 if (!NT_SUCCESS(Status
))
333 /* If that failed, try without allocation attributes */
335 Attributes
&= ~BlMemoryValidAllocationAttributeMask
,
336 Status
= MmPapAllocatePagesInRange(&MappedBase
,
345 /* Check if either attempts succeeded */
346 if (!NT_SUCCESS(Status
))
352 /* Success path, returned allocated address */
353 *ImageBuffer
= MappedBase
;
354 return STATUS_SUCCESS
;
358 BlImgLoadImageWithProgress2 (
360 _In_ BL_MEMORY_TYPE MemoryType
,
361 _In_ PWCHAR FileName
,
362 _Inout_ PVOID
* MappedBase
,
363 _Inout_ PULONG MappedSize
,
364 _In_ ULONG ImageFlags
,
365 _In_ BOOLEAN ShowProgress
,
366 _Out_opt_ PUCHAR
* HashBuffer
,
367 _Out_opt_ PULONG HashSize
371 PVOID BaseAddress
, Buffer
;
372 ULONG RemainingLength
, CurrentSize
, ImageSize
, ReadSize
;
373 BOOLEAN ComputeSignature
, ComputeHash
, Completed
;
374 BL_IMG_FILE FileHandle
;
375 ULONGLONG ByteOffset
;
376 PHYSICAL_ADDRESS PhysicalAddress
;
378 /* Initialize variables */
382 RtlZeroMemory(&FileHandle
, sizeof(FileHandle
));
384 /* Check for missing parameters */
387 Status
= STATUS_INVALID_PARAMETER
;
392 Status
= STATUS_INVALID_PARAMETER
;
397 Status
= STATUS_INVALID_PARAMETER
;
401 /* Check if the image buffer is being provided */
402 if (ImageFlags
& BL_LOAD_IMG_EXISTING_BUFFER
)
404 /* An existing base must already exist */
407 Status
= STATUS_INVALID_PARAMETER
;
412 /* Check of a hash is being requested */
413 if (ImageFlags
& BL_LOAD_IMG_COMPUTE_HASH
)
415 /* Make sure we can return the hash */
418 Status
= STATUS_INVALID_PARAMETER
;
423 Status
= STATUS_INVALID_PARAMETER
;
428 /* Check for invalid combination of parameters */
429 if ((ImageFlags
& BL_LOAD_IMG_COMPUTE_HASH
) && (ImageFlags
& 0x270))
431 Status
= STATUS_INVALID_PARAMETER
;
435 /* Initialize hash if requested by caller */
441 /* Do the same for the hash size */
447 /* Open the image file */
448 Status
= ImgpOpenFile(DeviceId
, FileName
, DeviceId
, &FileHandle
);
449 if (!NT_SUCCESS(Status
))
451 EfiPrintf(L
"Error opening file: %lx\r\n", Status
);
455 /* Get the size of the image */
456 Status
= ImgpGetFileSize(&FileHandle
, &ImageSize
);
457 if (!NT_SUCCESS(Status
))
459 EfiPrintf(L
"Error getting file size: %lx\r\n", Status
);
463 /* Read the current base address */
464 BaseAddress
= *MappedBase
;
465 if (ImageFlags
& BL_LOAD_IMG_EXISTING_BUFFER
)
467 /* Check if the current buffer is too small */
468 if (*MappedSize
< ImageSize
)
470 /* Return the required size of the buffer */
471 *MappedSize
= ImageSize
;
472 Status
= STATUS_BUFFER_TOO_SMALL
;
477 /* A buffer was not provided, allocate one ourselves */
478 Status
= BlImgAllocateImageBuffer(&BaseAddress
,
484 /* Bail out if allocation failed */
485 if (!NT_SUCCESS(Status
))
490 /* Set the initial byte offset and length to read */
491 RemainingLength
= ImageSize
;
493 Buffer
= BaseAddress
;
495 /* Update the initial progress */
499 BlUtlUpdateProgress(0, &Completed
);
500 ShowProgress
&= (Completed
!= 0) - 1;
503 /* Set the chunk size for each read */
505 if (ReadSize
> ImageSize
)
507 ReadSize
= ImageSize
;
510 /* Check if we should compute hash and/or signatures */
511 ComputeSignature
= ImageFlags
& BL_LOAD_IMG_COMPUTE_SIGNATURE
;
513 if ((ComputeSignature
) || (ImageFlags
& BL_LOAD_IMG_COMPUTE_HASH
))
516 // todo: crypto is hard
519 /* Begin the read loop */
520 while (RemainingLength
)
522 /* Check if we've got more than a chunk left to read */
523 if (RemainingLength
> ReadSize
)
526 CurrentSize
= ReadSize
;
530 /* Read only what's left */
531 CurrentSize
= RemainingLength
;
535 Status
= ImgpReadAtFileOffset(&FileHandle
,
540 if (!NT_SUCCESS(Status
))
545 /* Check if we need to compute the hash of this chunk */
548 // todo: crypto is hard
551 /* Update our position and read information */
552 Buffer
= (PVOID
)((ULONG_PTR
)Buffer
+ CurrentSize
);
553 RemainingLength
-= CurrentSize
;
554 ByteOffset
+= CurrentSize
;
556 /* Check if we should update the progress bar */
559 /* Compute new percentage completed, check if we're done */
560 BlUtlUpdateProgress(100 - 100 * RemainingLength
/ ImageSize
,
562 ShowProgress
&= (Completed
!= 0) - 1;
566 /* Is the read fully complete? We need to finalize the hash if requested */
569 // todo: CRYPTO IS HARD
572 /* Success path, return back the buffer and the size of the image */
573 *MappedBase
= BaseAddress
;
574 *MappedSize
= ImageSize
;
577 /* Close the file handle */
578 ImgpCloseFile(&FileHandle
);
580 /* Check if we failed and had allocated a buffer */
581 if (!(NT_SUCCESS(Status
)) &&
583 !(ImageFlags
& BL_LOAD_IMG_EXISTING_BUFFER
))
585 /* Check what kind of buffer we had allocated */
586 if (ImageFlags
& BL_LOAD_IMG_VIRTUAL_BUFFER
)
588 /* Unmap and free the virtual buffer */
589 PhysicalAddress
.QuadPart
= (ULONG_PTR
)BaseAddress
;
590 BlMmUnmapVirtualAddressEx(BaseAddress
, ImageSize
);
591 BlMmFreePhysicalPages(PhysicalAddress
);
595 /* Free the physical buffer */
596 MmPapFreePages(BaseAddress
, BL_MM_INCLUDE_MAPPED_ALLOCATED
);
600 /* If we hadn't gotten to 100% yet, do it now */
603 BlUtlUpdateProgress(100, &Completed
);
606 /* Return the final status */
610 PIMAGE_SECTION_HEADER
612 _In_ PVOID ImageBase
,
616 PIMAGE_SECTION_HEADER FoundSection
;
618 PIMAGE_SECTION_HEADER SectionHeader
;
619 PIMAGE_NT_HEADERS NtHeader
;
625 /* Make sure the image is valid */
626 Status
= RtlImageNtHeaderEx(0, ImageBase
, ImageSize
, &NtHeader
);
627 if (NT_SUCCESS(Status
))
629 /* Get the first section and loop through them all */
630 SectionHeader
= IMAGE_FIRST_SECTION(NtHeader
);
631 for (i
= 0; i
< NtHeader
->FileHeader
.NumberOfSections
; i
++)
633 /* Check if this is the resource section */
634 if (!_stricmp((PCCH
)SectionHeader
->Name
, ".rsrc"))
636 /* Yep, we're done */
637 FoundSection
= SectionHeader
;
641 /* Nope, keep going */
646 /* Return the matching section */
651 BlImgQueryCodeIntegrityBootOptions (
652 _In_ PBL_LOADED_APPLICATION_ENTRY ApplicationEntry
,
653 _Out_ PBOOLEAN IntegrityChecksDisabled
,
654 _Out_ PBOOLEAN TestSigning
661 /* Check if /DISABLEINTEGRITYCHECKS is on */
662 Status
= BlGetBootOptionBoolean(ApplicationEntry
->BcdData
,
663 BcdLibraryBoolean_DisableIntegrityChecks
,
665 *IntegrityChecksDisabled
= NT_SUCCESS(Status
) && (Value
);
667 /* Check if /TESTSIGNING is on */
668 Status
= BlGetBootOptionBoolean(ApplicationEntry
->BcdData
,
669 BcdLibraryBoolean_AllowPrereleaseSignatures
,
671 *TestSigning
= NT_SUCCESS(Status
) && (Value
);
676 _In_ PVOID ImageBase
,
677 _In_ ULONG ImageSize
,
678 _In_ ULONG ImageFlags
681 /* Check for missing parameters */
682 if (!(ImageSize
) || !(ImageBase
))
685 return STATUS_INVALID_PARAMETER
;
688 /* Unallocate the image buffer */
689 return BlImgUnallocateImageBuffer(ImageBase
, ImageSize
, ImageFlags
);
694 _In_ PBL_IMG_FILE ImageFile
,
695 _In_ BL_MEMORY_TYPE MemoryType
,
696 _Inout_ PVOID
* ImageBase
,
697 _Out_opt_ PULONG ImageSize
,
698 _Inout_opt_ PVOID Hash
,
703 ULONG FileSize
, HeaderSize
;
704 BL_IMG_FILE LocalFileBuffer
;
705 PBL_IMG_FILE LocalFile
;
706 PVOID VirtualAddress
, PreferredBase
, ImageBuffer
, CertBuffer
, HashBuffer
;
707 ULONGLONG VirtualSize
;
708 PIMAGE_DATA_DIRECTORY CertDirectory
;
709 PHYSICAL_ADDRESS PhysicalAddress
;
710 PIMAGE_NT_HEADERS NtHeaders
;
711 USHORT SectionCount
, CheckSum
, PartialSum
, FinalSum
;
712 PIMAGE_SECTION_HEADER Section
;
713 ULONG_PTR EndOfHeaders
, SectionStart
, Slack
, SectionEnd
;
714 ULONG i
, SectionSize
, RawSize
, BytesRead
, RemainingLength
, Offset
, AlignSize
;
715 BOOLEAN First
, ImageHashValid
;
716 UCHAR LocalBuffer
[1024];
717 UCHAR TrustedBootInformation
[52];
718 ULONG WorkaroundForBinutils
;
720 /* Initialize locals */
721 WorkaroundForBinutils
= 0;
726 VirtualAddress
= NULL
;
728 CertDirectory
= NULL
;
732 ImageHashValid
= FALSE
;
733 RtlZeroMemory(&TrustedBootInformation
, sizeof(TrustedBootInformation
));
735 /* Get the size of the image */
736 Status
= ImgpGetFileSize(ImageFile
, &FileSize
);
737 if (!NT_SUCCESS(Status
))
739 return STATUS_FILE_INVALID
;
742 /* Allocate a flat buffer for it */
743 Status
= BlImgAllocateImageBuffer(&ImageBuffer
, BlLoaderData
, FileSize
, 0);
744 if (!NT_SUCCESS(Status
))
749 /* Read the whole file flat for now */
750 Status
= ImgpReadAtFileOffset(ImageFile
, FileSize
, 0, ImageBuffer
, NULL
);
751 if (!NT_SUCCESS(Status
))
756 /* Build a local file handle */
757 LocalFile
= &LocalFileBuffer
;
758 LocalFileBuffer
.FileName
= ImageFile
->FileName
;
759 LocalFileBuffer
.Flags
= BL_IMG_MEMORY_FILE
| BL_IMG_VALID_FILE
;
760 LocalFileBuffer
.BaseAddress
= ImageBuffer
;
761 LocalFileBuffer
.FileSize
= FileSize
;
763 /* Get the NT headers of the file */
764 Status
= RtlImageNtHeaderEx(0, ImageBuffer
, FileSize
, &NtHeaders
);
765 if (!NT_SUCCESS(Status
))
770 /* Check if we should validate the machine type */
771 if (Flags
& BL_LOAD_PE_IMG_CHECK_MACHINE
)
773 /* Is it different than our current machine type? */
775 if (NtHeaders
->FileHeader
.Machine
!= IMAGE_FILE_MACHINE_AMD64
)
777 if (NtHeaders
->FileHeader
.Machine
!= IMAGE_FILE_MACHINE_I386
)
780 /* Is it x86 (implying we are x64) ? */
781 if (NtHeaders
->FileHeader
.Machine
== IMAGE_FILE_MACHINE_I386
)
783 /* Return special error code */
784 Status
= STATUS_INVALID_IMAGE_WIN_32
;
786 else if (NtHeaders
->FileHeader
.Machine
== IMAGE_FILE_MACHINE_AMD64
)
788 /* Otherwise, it's x64 but we are x86 */
789 Status
= STATUS_INVALID_IMAGE_WIN_64
;
793 /* Or it's ARM or something... */
794 Status
= STATUS_INVALID_IMAGE_FORMAT
;
797 /* Return with the distinguished error code */
802 /* Check if we should validate the subsystem */
803 if (Flags
& BL_LOAD_PE_IMG_CHECK_SUBSYSTEM
)
805 /* It must be a Windows boot Application */
806 if (NtHeaders
->OptionalHeader
.Subsystem
!=
807 IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION
)
809 Status
= STATUS_INVALID_IMAGE_FORMAT
;
814 /* Check if we should validate the /INTEGRITYCHECK flag */
815 if (Flags
& BL_LOAD_PE_IMG_CHECK_FORCED_INTEGRITY
)
817 /* Check if it's there */
818 if (!(NtHeaders
->OptionalHeader
.DllCharacteristics
&
819 IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY
))
821 /* Nope, fail otherwise */
822 Status
= STATUS_INVALID_IMAGE_FORMAT
;
827 /* Check if we should compute the image hash */
828 if ((Flags
& BL_LOAD_PE_IMG_COMPUTE_HASH
) || (Hash
))
830 EfiPrintf(L
"No hash support\r\n");
833 /* Read the current base address, if any */
834 VirtualAddress
= *ImageBase
;
836 /* Get the virtual size of the image */
837 VirtualSize
= NtHeaders
->OptionalHeader
.SizeOfImage
;
839 /* Safely align the virtual size to a page */
840 Status
= RtlULongLongAdd(VirtualSize
,
843 if (!NT_SUCCESS(Status
))
847 VirtualSize
= ALIGN_DOWN_BY(VirtualSize
, PAGE_SIZE
);
849 /* Make sure the image isn't larger than 4GB */
850 if (VirtualSize
> ULONG_MAX
)
852 Status
= STATUS_INVALID_IMAGE_FORMAT
;
856 /* Check if we have a buffer already */
857 if (Flags
& BL_LOAD_IMG_EXISTING_BUFFER
)
859 /* Check if it's too small */
860 if (*ImageSize
< VirtualSize
)
862 /* Fail, letting the caller know how big to make it */
863 *ImageSize
= VirtualSize
;
864 Status
= STATUS_BUFFER_TOO_SMALL
;
869 /* Allocate the buffer with the flags and type the caller wants */
870 Status
= BlImgAllocateImageBuffer(&VirtualAddress
,
876 /* Bail out if allocation failed, or existing buffer is too small */
877 if (!NT_SUCCESS(Status
))
882 /* Read the size of the headers */
883 HeaderSize
= NtHeaders
->OptionalHeader
.SizeOfHeaders
;
884 if (VirtualSize
< HeaderSize
)
886 /* Bail out if they're bigger than the image! */
887 Status
= STATUS_INVALID_IMAGE_FORMAT
;
891 /* Now read the header into the buffer */
892 Status
= ImgpReadAtFileOffset(LocalFile
, HeaderSize
, 0, VirtualAddress
, NULL
);
893 if (!NT_SUCCESS(Status
))
898 /* Get the NT headers of the file */
899 Status
= RtlImageNtHeaderEx(0, VirtualAddress
, HeaderSize
, &NtHeaders
);
900 if (!NT_SUCCESS(Status
))
907 /* Record how many sections we have */
908 SectionCount
= NtHeaders
->FileHeader
.NumberOfSections
;
910 /* Capture the current checksum and reset it */
911 CheckSum
= NtHeaders
->OptionalHeader
.CheckSum
;
912 NtHeaders
->OptionalHeader
.CheckSum
= 0;
914 /* Calculate the checksum of the header, and restore the original one */
915 PartialSum
= BlUtlCheckSum(0,
918 BL_UTL_CHECKSUM_COMPLEMENT
|
919 BL_UTL_CHECKSUM_USHORT_BUFFER
);
920 NtHeaders
->OptionalHeader
.CheckSum
= CheckSum
;
922 /* Record our current position (right after the headers) */
923 EndOfHeaders
= (ULONG_PTR
)VirtualAddress
+ HeaderSize
;
925 /* Get the first section and iterate through each one */
926 Section
= IMAGE_FIRST_SECTION(NtHeaders
);
927 for (i
= 0; i
< SectionCount
; i
++)
929 /* Compute where this section starts */
930 SectionStart
= (ULONG_PTR
)VirtualAddress
+ Section
->VirtualAddress
;
932 /* Make sure that the section fits within the image */
933 if ((VirtualSize
< Section
->VirtualAddress
) ||
934 ((PVOID
)SectionStart
< VirtualAddress
))
936 EfiPrintf(L
"fail 1\r\n");
937 Status
= STATUS_INVALID_IMAGE_FORMAT
;
941 /* Check if there's slack space between header end and the section */
942 if (!(First
) && (EndOfHeaders
< SectionStart
))
945 Slack
= SectionStart
- EndOfHeaders
;
946 RtlZeroMemory((PVOID
)EndOfHeaders
, Slack
);
949 /* Get the section virtual size and the raw size */
950 SectionSize
= Section
->Misc
.VirtualSize
;
951 RawSize
= Section
->SizeOfRawData
;
953 /* Safely align the raw size by 2 */
954 Status
= RtlULongAdd(RawSize
, 1, &AlignSize
);
955 if (!NT_SUCCESS(Status
))
959 AlignSize
= ALIGN_DOWN_BY(AlignSize
, 2);
961 /* IF we don't have a virtual size, use the raw size */
964 SectionSize
= RawSize
;
967 /* If we don't have raw data, ignore the raw size */
968 if (!Section
->PointerToRawData
)
972 else if (SectionSize
< RawSize
)
974 /* And if the virtual size is smaller, use it as the final size */
975 RawSize
= SectionSize
;
978 /* Make sure that the section doesn't overflow in memory */
979 Status
= RtlULongAdd(Section
->VirtualAddress
,
982 if (!NT_SUCCESS(Status
))
984 EfiPrintf(L
"fail 21\r\n");
985 Status
= STATUS_INVALID_IMAGE_FORMAT
;
989 /* Make sure that it fits within the image */
990 if (VirtualSize
< SectionEnd
)
992 Status
= STATUS_INVALID_IMAGE_FORMAT
;
996 /* Make sure it doesn't overflow on disk */
997 Status
= RtlULongAdd(Section
->VirtualAddress
,
1000 if (!NT_SUCCESS(Status
))
1002 EfiPrintf(L
"fail 31\r\n");
1003 Status
= STATUS_INVALID_IMAGE_FORMAT
;
1007 /* Make sure that it fits within the disk image as well */
1008 if (VirtualSize
< SectionEnd
)
1010 Status
= STATUS_INVALID_IMAGE_FORMAT
;
1014 /* So does this section have a valid size after all? */
1017 /* Are we in the first iteration? */
1020 /* FUCK YOU BINUTILS */
1021 if (NtHeaders
->OptionalHeader
.MajorLinkerVersion
< 7)
1023 if ((*(PULONG
)&Section
->Name
== 'ler.') && (RawSize
< AlignSize
))
1025 /* Piece of shit won't build relocations when you tell it to,
1026 * either by using --emit-relocs or --dynamicbase. People online
1027 * have found out that by using -pie-executable you can get this
1028 * to happen, but then it turns out that the .reloc section is
1029 * incorrectly sized, and results in a corrupt PE. However, they
1030 * still compute the checksum using the correct value. What idiots.
1032 WorkaroundForBinutils
= AlignSize
- RawSize
;
1033 AlignSize
-= WorkaroundForBinutils
;
1037 /* Yes, read the section data */
1038 Status
= ImgpReadAtFileOffset(LocalFile
,
1040 Section
->PointerToRawData
,
1041 (PVOID
)SectionStart
,
1043 if (!NT_SUCCESS(Status
))
1048 /* Update our current offset */
1049 Offset
= AlignSize
+ Section
->PointerToRawData
;
1051 /* Update the checksum to include this section */
1052 PartialSum
= BlUtlCheckSum(PartialSum
,
1053 (PUCHAR
)SectionStart
,
1055 BL_UTL_CHECKSUM_COMPLEMENT
|
1056 BL_UTL_CHECKSUM_USHORT_BUFFER
);
1057 AlignSize
+= WorkaroundForBinutils
;
1061 /* Are we in the first iteration? */
1064 /* Is there space at the end of the section? */
1065 if (RawSize
< SectionSize
)
1067 /* Zero out the slack space that's there */
1068 Slack
= SectionSize
- RawSize
;
1069 RtlZeroMemory((PVOID
)(SectionStart
+ RawSize
), Slack
);
1072 /* Update our tail offset */
1073 EndOfHeaders
= SectionStart
+ SectionSize
;
1076 /* Move to the next section */
1080 /* Are we in the first iteration? */
1083 /* Go to the end of the file */
1084 SectionStart
= (ULONG_PTR
)VirtualAddress
+ VirtualSize
;
1086 /* Is there still some slack space left? */
1087 if (EndOfHeaders
< SectionStart
)
1090 Slack
= SectionStart
- EndOfHeaders
;
1091 RtlZeroMemory((PVOID
)EndOfHeaders
, Slack
);
1095 /* Did the first iteration complete OK? */
1096 if ((NT_SUCCESS(Status
)) && !(First
))
1098 /* Check how many non-image bytes are left in the file */
1099 RemainingLength
= FileSize
- Offset
;
1100 while (RemainingLength
)
1102 /* See if the read will fit into our local buffer */
1103 if (RemainingLength
>= sizeof(LocalBuffer
))
1106 BytesRead
= sizeof(LocalBuffer
);
1110 /* Yes, but there's less to read */
1111 BytesRead
= RemainingLength
;
1114 /* Read 1024 bytes into the local buffer */
1115 Status
= ImgpReadAtFileOffset(LocalFile
,
1120 if (!(NT_SUCCESS(Status
)) || !(BytesRead
))
1122 Status
= STATUS_FILE_INVALID
;
1126 /* Advance the offset and reduce the length */
1127 RemainingLength
-= BytesRead
;
1128 Offset
+= BytesRead
;
1130 /* Compute the checksum of this leftover space */
1131 PartialSum
= BlUtlCheckSum(PartialSum
,
1134 BL_UTL_CHECKSUM_COMPLEMENT
|
1135 BL_UTL_CHECKSUM_USHORT_BUFFER
);
1138 /* Finally, calculate the final checksum and compare it */
1139 FinalSum
= FileSize
+ PartialSum
+ WorkaroundForBinutils
;
1140 if ((FinalSum
!= CheckSum
) && (PartialSum
== 0xFFFF))
1142 /* It hit overflow, so set it to the file size */
1143 FinalSum
= FileSize
;
1146 /* If the checksum doesn't match, and caller is enforcing, bail out */
1147 if ((FinalSum
!= CheckSum
) &&
1148 !(Flags
& BL_LOAD_PE_IMG_IGNORE_CHECKSUM_MISMATCH
))
1150 Status
= STATUS_IMAGE_CHECKSUM_MISMATCH
;
1155 /* Check if the .rsrc section should be checked with the filename */
1156 if (Flags
& BL_LOAD_PE_IMG_VALIDATE_ORIGINAL_FILENAME
)
1158 EfiPrintf(L
"Not yet supported\r\n");
1159 Status
= 0xC0430007; // STATUS_SECUREBOOT_FILE_REPLACED
1163 /* Check if we should relocate */
1164 if (!(Flags
& BL_LOAD_PE_IMG_SKIP_RELOCATIONS
))
1166 /* Check if we loaded at a different address */
1167 PreferredBase
= (PVOID
)NtHeaders
->OptionalHeader
.ImageBase
;
1168 if (VirtualAddress
!= PreferredBase
)
1170 /* Yep -- do relocations */
1171 Status
= LdrRelocateImage(VirtualAddress
,
1172 "Boot Environment Library",
1174 STATUS_UNSUCCESSFUL
,
1175 STATUS_INVALID_IMAGE_FORMAT
);
1176 if (!NT_SUCCESS(Status
))
1185 /* Check if the image hash was valid */
1186 if (!ImageHashValid
)
1188 /* Send a TPM/SI notification without a context */
1189 BlEnNotifyEvent(0x10000002, NULL
);
1192 /* Now send a TPM/SI notification with the hash of the loaded image */
1193 BlMmTranslateVirtualAddress(VirtualAddress
, &Context
.ImageBase
);
1194 Context
.HashAlgorithm
= HashAlgorithm
;
1195 Context
.HashSize
= HashSize
;
1196 Context
.FileName
= ImageFile
->FileName
;
1197 Context
.ImageSize
= VirtualSize
;
1198 Context
.HashValid
= ImageHashValid
;
1199 Context
.Hash
= Hash
;
1200 BlEnNotifyEvent(0x10000002, &Context
);
1203 /* Return the loaded address to the caller */
1204 *ImageBase
= VirtualAddress
;
1206 /* If the caller wanted the image size, return it too */
1209 *ImageSize
= VirtualSize
;
1213 /* Check if we computed the image hash OK */
1216 /* Then free the information that ImgpValidateImageHash set up */
1217 EfiPrintf(L
"leadking trusted boot\r\n");
1218 //ImgpDestroyTrustedBootInformation(&TrustedBootInformation);
1221 /* Check if we had a hash buffer */
1225 MmPapFreePages(HashBuffer
, BL_MM_INCLUDE_MAPPED_ALLOCATED
);
1228 /* Check if we have a certificate directory */
1229 if ((CertBuffer
) && (CertDirectory
))
1232 BlImgUnallocateImageBuffer(CertBuffer
, CertDirectory
->Size
, 0);
1235 /* Check if we had an image buffer allocated */
1236 if ((ImageBuffer
) && (FileSize
))
1239 BlImgUnallocateImageBuffer(ImageBuffer
, FileSize
, 0);
1242 /* Check if we had a local file handle */
1246 ImgpCloseFile(LocalFile
);
1249 /* Check if this is the failure path */
1250 if (!NT_SUCCESS(Status
))
1252 /* Check if we had started mapping in the image already */
1253 if ((VirtualAddress
) && !(Flags
& BL_LOAD_PE_IMG_EXISTING_BUFFER
))
1255 /* Into a virtual buffer? */
1256 if (Flags
& BL_LOAD_PE_IMG_VIRTUAL_BUFFER
)
1258 /* Unmap and free it */
1259 BlMmUnmapVirtualAddressEx(VirtualAddress
, VirtualSize
);
1260 PhysicalAddress
.QuadPart
= (ULONG_PTR
)VirtualAddress
;
1261 BlMmFreePhysicalPages(PhysicalAddress
);
1265 /* Into a physical buffer -- free it */
1266 MmPapFreePages(VirtualAddress
, BL_MM_INCLUDE_MAPPED_ALLOCATED
);
1271 /* Return back to caller */
1276 BlImgLoadPEImageEx (
1277 _In_ ULONG DeviceId
,
1278 _In_ BL_MEMORY_TYPE MemoryType
,
1280 _Out_ PVOID
* ImageBase
,
1281 _Out_ PULONG ImageSize
,
1286 BL_IMG_FILE ImageFile
;
1289 /* Initialize the image file structure */
1290 ImageFile
.Flags
= 0;
1291 ImageFile
.FileName
= NULL
;
1293 /* Check if the required parameter are missing */
1294 if (!(ImageBase
) || !(Path
))
1296 return STATUS_INVALID_PARAMETER
;
1299 /* If we are loading a pre-allocated image, make sure we have it */
1300 if ((Flags
& BL_LOAD_IMG_EXISTING_BUFFER
) && (!(*ImageBase
) || !(ImageSize
)))
1302 return STATUS_INVALID_PARAMETER
;
1305 /* Load the file from disk */
1306 Status
= ImgpOpenFile(DeviceId
, Path
, 0, &ImageFile
);
1307 if (NT_SUCCESS(Status
))
1309 /* If that worked, do the PE parsing */
1310 Status
= ImgpLoadPEImage(&ImageFile
,
1318 /* Close the image file and return back to caller */
1319 ImgpCloseFile(&ImageFile
);
1324 BlImgLoadBootApplication (
1325 _In_ PBL_LOADED_APPLICATION_ENTRY BootEntry
,
1326 _Out_ PULONG AppHandle
1330 PULONGLONG AllowedList
;
1331 ULONGLONG AllowedCount
;
1332 ULONG i
, DeviceId
, ImageSize
, Flags
, ListSize
;
1333 LARGE_INTEGER Frequency
;
1334 PVOID UnlockCode
, ImageBase
;
1335 PBL_DEVICE_DESCRIPTOR Device
, BitLockerDevice
;
1337 PBL_APPLICATION_ENTRY AppEntry
;
1338 PBL_IMG_FILE ImageFile
;
1339 BOOLEAN DisableIntegrity
, TestSigning
;
1341 PBL_IMAGE_APPLICATION_ENTRY ImageAppEntry
;
1343 /* Initialize all locals */
1344 BitLockerDevice
= NULL
;
1349 ImageAppEntry
= NULL
;
1355 /* Check for "allowed in-memory settings" */
1356 Status
= BlpGetBootOptionIntegerList(BootEntry
->BcdData
,
1357 BcdLibraryIntegerList_AllowedInMemorySettings
,
1361 if (Status
== STATUS_SUCCESS
)
1363 /* Loop through the list of allowed setting */
1364 for (i
= 0; i
< AllowedCount
; i
++)
1366 /* Find the super undocumented one */
1367 if (AllowedList
[i
] == BcdLibraryInteger_UndocumentedMagic
)
1369 /* If it's present, append the current perf frequence to it */
1370 BlTimeQueryPerformanceCounter(&Frequency
);
1371 BlAppendBootOptionInteger(BootEntry
,
1372 BcdLibraryInteger_UndocumentedMagic
,
1373 Frequency
.QuadPart
);
1378 #if BL_BITLOCKER_SUPPORT
1379 /* Do bitlocker stuff */
1380 Status
= BlFveSecureBootUnlockBootDevice(BootEntry
, &BitLockerDevice
, &UnlockCode
);
1381 if (!NT_SUCCESS(Status
))
1387 /* Get the device on which this application is on*/
1388 Status
= BlGetBootOptionDevice(BootEntry
->BcdData
,
1389 BcdLibraryDevice_ApplicationDevice
,
1392 if (!NT_SUCCESS(Status
))
1397 /* Get the path of the application */
1398 Status
= BlGetBootOptionString(BootEntry
->BcdData
,
1399 BcdLibraryString_ApplicationPath
,
1401 if (!NT_SUCCESS(Status
))
1406 /* Open the device */
1407 Status
= BlpDeviceOpen(Device
,
1408 BL_DEVICE_READ_ACCESS
,
1411 if (!NT_SUCCESS(Status
))
1416 /* Check for integrity BCD options */
1417 BlImgQueryCodeIntegrityBootOptions(BootEntry
,
1422 RtlZeroMemory(&Context
, sizeof(Context
);
1423 Context
.BootEntry
= BootEntry
;
1424 BlEnNotifyEvent(0x10000003, &Context
);
1427 /* Enable signing and hashing checks if integrity is enabled */
1429 if (!DisableIntegrity
)
1434 /* Now call the PE loader to load the image */
1435 Status
= BlImgLoadPEImageEx(DeviceId
,
1442 if (!NT_SUCCESS(Status
))
1448 /* Check if we should notify the debugger of load */
1449 if (BdDebugTransitions
)
1453 Status
= BlBdInitialize();
1454 if (NT_SUCCESS(Status
))
1456 /* Check if it's enabled */
1457 if (BlBdDebuggerEnabled())
1459 /* Send it an image load notification */
1460 BdDebuggerNotPresent
= FALSE
;
1461 RtlInitUnicodeString(&PathString
, Path
);
1462 BlBdLoadImageSymbols(&PathString
, ImageBase
);
1468 #if BL_BITLOCKER_SUPPORT
1469 /* Do bitlocker stuff */
1470 Status
= BlSecureBootCheckPolicyOnFveDevice(BitLockerDevice
);
1471 if (!NT_SUCCESS(Status
))
1477 #if BL_BITLOCKER_SUPPORT
1478 /* Do bitlocker stuff */
1479 Status
= BlFveSecureBootCheckpointBootApp(BootEntry
, BitLockerDevice
, Hash
, UnlockCode
);
1480 if (!NT_SUCCESS(Status
))
1486 /* Get the BCD option size */
1487 ListSize
= BlGetBootOptionListSize(BootEntry
->BcdData
);
1489 /* Allocate an entry with all the BCD options */
1490 AppEntry
= BlMmAllocateHeap(ListSize
+ sizeof(*AppEntry
));
1493 Status
= STATUS_NO_MEMORY
;
1498 RtlZeroMemory(AppEntry
, sizeof(*AppEntry
));
1501 strcpy(AppEntry
->Signature
, "BTAPENT");
1502 AppEntry
->Guid
= BootEntry
->Guid
;
1503 AppEntry
->Flags
= BootEntry
->Flags
;
1505 /* Copy the BCD options */
1506 RtlCopyMemory(&AppEntry
->BcdData
, BootEntry
->BcdData
, ListSize
);
1508 /* Allocate the image entry */
1509 ImageAppEntry
= BlMmAllocateHeap(sizeof(*ImageAppEntry
));
1512 Status
= STATUS_NO_MEMORY
;
1517 ImageAppEntry
->ImageBase
= ImageBase
;
1518 ImageAppEntry
->ImageSize
= ImageSize
;
1519 ImageAppEntry
->AppEntry
= AppEntry
;
1521 /* Check if this is the first entry */
1522 if (!IapTableEntries
)
1524 /* Allocate two entries */
1525 IapAllocatedTableEntries
= 0;
1526 IapTableEntries
= 2;
1527 IapImageTable
= BlMmAllocateHeap(IapTableEntries
* sizeof(PVOID
));
1530 Status
= STATUS_NO_MEMORY
;
1534 /* Zero out the entries for now */
1535 RtlZeroMemory(IapImageTable
, IapTableEntries
* sizeof(PVOID
));
1538 /* Set this entry into the table */
1539 Status
= BlTblSetEntry(&IapImageTable
,
1543 TblDoNotPurgeEntry
);
1546 /* Is the device open? Close it if so */
1549 BlDeviceClose(DeviceId
);
1552 /* Is there an allocated device? Free it */
1555 BlMmFreeHeap(Device
);
1558 /* Is there an allocated path? Free it */
1564 /* Is there a bitlocker device? Free it */
1565 if (BitLockerDevice
)
1567 BlMmFreeHeap(BitLockerDevice
);
1570 /* Is there a bitlocker unlock code? Free it */
1573 BlMmFreeHeap(UnlockCode
);
1576 /* Did we succeed in creating an entry? */
1577 if (NT_SUCCESS(Status
))
1579 /* Remember there's one more in the table */
1580 IapAllocatedTableEntries
++;
1582 /* Return success */
1586 /* Did we load an image after all? */
1590 BlImgUnLoadImage(ImageBase
, ImageSize
, 0);
1593 /* Did we allocate an app entry? Free it */
1596 BlMmFreeHeap(AppEntry
);
1599 /* Do we have an image file entry? Free it */
1602 BlMmFreeHeap(ImageFile
);
1605 /* Do we no longer have a single entry in the table? */
1606 if (!(IapAllocatedTableEntries
) && (IapImageTable
))
1608 /* Free and destroy the table */
1609 BlMmFreeHeap(IapImageTable
);
1610 IapTableEntries
= 0;
1611 IapImageTable
= NULL
;
1614 /* Return the failure code */
1619 BlpPdParseReturnArguments (
1620 _In_ PBL_RETURN_ARGUMENTS ReturnArguments
1623 /* Check if any custom data was returned */
1624 if (ReturnArguments
->DataPage
== 0)
1626 /* Nope, nothing to do */
1627 return STATUS_SUCCESS
;
1630 /* Yes, we have to parse it */
1631 EfiPrintf(L
"Return arguments not supported\r\n");
1632 return STATUS_NOT_IMPLEMENTED
;
1636 ImgpCopyApplicationBootDevice (
1637 __in PBL_DEVICE_DESCRIPTOR DestinationDevice
,
1638 __in PBL_DEVICE_DESCRIPTOR SourceDevice
1641 /* Is this a partition device? */
1642 if (SourceDevice
->DeviceType
!= PartitionDevice
)
1644 /* It's not -- a simple copy will do */
1645 RtlCopyMemory(DestinationDevice
, SourceDevice
, SourceDevice
->Size
);
1646 return STATUS_SUCCESS
;
1650 EfiPrintf(L
"Partition copy not supported\r\n");
1651 return STATUS_NOT_IMPLEMENTED
;
1656 ImgpInitializeBootApplicationParameters (
1657 _In_ PBL_IMAGE_PARAMETERS ImageParameters
,
1658 _In_ PBL_APPLICATION_ENTRY AppEntry
,
1659 _In_ PVOID ImageBase
,
1660 _In_ ULONG ImageSize
1664 PIMAGE_NT_HEADERS NtHeaders
;
1665 BL_IMAGE_PARAMETERS MemoryParameters
;
1666 LIST_ENTRY MemoryList
;
1667 PBL_FIRMWARE_DESCRIPTOR FirmwareParameters
;
1668 PBL_DEVICE_DESCRIPTOR BootDevice
;
1669 PBL_MEMORY_DATA MemoryData
;
1670 PBL_APPLICATION_ENTRY BootAppEntry
;
1671 PBL_RETURN_ARGUMENTS ReturnArguments
;
1672 PBOOT_APPLICATION_PARAMETER_BLOCK ParameterBlock
;
1673 ULONG EntrySize
, BufferSize
;
1675 /* Get the image headers and validate it */
1676 Status
= RtlImageNtHeaderEx(0, ImageBase
, ImageSize
, &NtHeaders
);
1677 if (!NT_SUCCESS(Status
))
1682 /* Get the size of the entire non-firmware, allocated, memory map */
1683 MemoryParameters
.BufferSize
= 0;
1684 Status
= BlMmGetMemoryMap(&MemoryList
,
1686 BL_MM_INCLUDE_PERSISTENT_MEMORY
|
1687 BL_MM_INCLUDE_MAPPED_ALLOCATED
|
1688 BL_MM_INCLUDE_MAPPED_UNALLOCATED
|
1689 BL_MM_INCLUDE_UNMAPPED_ALLOCATED
|
1690 BL_MM_INCLUDE_RESERVED_ALLOCATED
,
1692 if ((Status
!= STATUS_BUFFER_TOO_SMALL
) && (Status
!= STATUS_SUCCESS
))
1694 /* We failed due to an unknown reason -- bail out */
1698 /* Compute the list of the BCD plus the application entry */
1699 EntrySize
= BlGetBootOptionListSize(&AppEntry
->BcdData
) +
1700 FIELD_OFFSET(BL_APPLICATION_ENTRY
, BcdData
);
1702 /* Compute the total size required for the entire structure */
1703 BufferSize
= EntrySize
+
1704 BlpBootDevice
->Size
+
1705 MemoryParameters
.BufferSize
+
1706 sizeof(*ReturnArguments
) +
1707 sizeof(*MemoryData
) +
1708 sizeof(*FirmwareParameters
) +
1709 sizeof(*ParameterBlock
);
1711 /* Check if this gives us enough space */
1712 if (ImageParameters
->BufferSize
< BufferSize
)
1714 /* It does not -- free the existing buffer */
1715 if (ImageParameters
->BufferSize
)
1717 BlMmFreeHeap(ImageParameters
->Buffer
);
1720 /* Allocate a new buffer of sufficient size */
1721 ImageParameters
->BufferSize
= BufferSize
;
1722 ImageParameters
->Buffer
= BlMmAllocateHeap(BufferSize
);
1723 if (!ImageParameters
->Buffer
)
1725 /* Bail out if we couldn't allocate it */
1726 return STATUS_NO_MEMORY
;
1730 /* Zero out the parameter block */
1731 ParameterBlock
= (PBOOT_APPLICATION_PARAMETER_BLOCK
)ImageParameters
->Buffer
;
1732 RtlZeroMemory(ParameterBlock
, BufferSize
);
1735 ParameterBlock
->Version
= BOOT_APPLICATION_VERSION
;
1736 ParameterBlock
->Size
= BufferSize
;
1737 ParameterBlock
->Signature
[0] = BOOT_APPLICATION_SIGNATURE_1
;
1738 ParameterBlock
->Signature
[1] = BOOT_APPLICATION_SIGNATURE_2
;
1739 ParameterBlock
->MemoryTranslationType
= MmTranslationType
;
1740 ParameterBlock
->ImageType
= IMAGE_FILE_MACHINE_I386
;
1741 ParameterBlock
->ImageBase
= (ULONG_PTR
)ImageBase
;
1742 ParameterBlock
->ImageSize
= NtHeaders
->OptionalHeader
.SizeOfImage
;
1744 /* Get the offset to the memory data */
1745 ParameterBlock
->MemoryDataOffset
= sizeof(*ParameterBlock
);
1748 MemoryData
= (PBL_MEMORY_DATA
)((ULONG_PTR
)ParameterBlock
+
1749 ParameterBlock
->MemoryDataOffset
);
1750 MemoryData
->Version
= BL_MEMORY_DATA_VERSION
;
1751 MemoryData
->MdListOffset
= sizeof(*MemoryData
);
1752 MemoryData
->DescriptorSize
= sizeof(BL_MEMORY_DESCRIPTOR
);
1753 MemoryData
->DescriptorOffset
= FIELD_OFFSET(BL_MEMORY_DESCRIPTOR
, BasePage
);
1755 /* And populate the memory map */
1756 MemoryParameters
.Buffer
= MemoryData
+ 1;
1757 Status
= BlMmGetMemoryMap(&MemoryList
,
1759 BL_MM_INCLUDE_PERSISTENT_MEMORY
|
1760 BL_MM_INCLUDE_MAPPED_ALLOCATED
|
1761 BL_MM_INCLUDE_MAPPED_UNALLOCATED
|
1762 BL_MM_INCLUDE_UNMAPPED_ALLOCATED
|
1763 BL_MM_INCLUDE_RESERVED_ALLOCATED
,
1765 if (!NT_SUCCESS(Status
))
1770 /* Now that we have the map, indicate the number of descriptors */
1771 MemoryData
->DescriptorCount
= MemoryParameters
.ActualSize
/
1772 MemoryData
->DescriptorSize
;
1774 /* Get the offset to the application entry */
1775 ParameterBlock
->AppEntryOffset
= ParameterBlock
->MemoryDataOffset
+
1776 MemoryData
->MdListOffset
+
1777 MemoryParameters
.BufferSize
;
1780 BootAppEntry
= (PBL_APPLICATION_ENTRY
)((ULONG_PTR
)ParameterBlock
+
1781 ParameterBlock
->AppEntryOffset
);
1782 RtlCopyMemory(BootAppEntry
, AppEntry
, EntrySize
);
1784 /* Get the offset to the boot device */
1785 ParameterBlock
->BootDeviceOffset
= ParameterBlock
->AppEntryOffset
+
1789 BootDevice
= (PBL_DEVICE_DESCRIPTOR
)((ULONG_PTR
)ParameterBlock
+
1790 ParameterBlock
->BootDeviceOffset
);
1791 Status
= ImgpCopyApplicationBootDevice(BootDevice
, BlpBootDevice
);
1792 if (!NT_SUCCESS(Status
))
1797 /* Get the offset to the firmware data */
1798 ParameterBlock
->FirmwareParametersOffset
= ParameterBlock
->BootDeviceOffset
+
1802 FirmwareParameters
= (PBL_FIRMWARE_DESCRIPTOR
)((ULONG_PTR
)ParameterBlock
+
1804 FirmwareParametersOffset
);
1805 Status
= BlFwGetParameters(FirmwareParameters
);
1806 if (!NT_SUCCESS(Status
))
1811 /* Get the offset to the return arguments */
1812 ParameterBlock
->ReturnArgumentsOffset
= ParameterBlock
->FirmwareParametersOffset
+
1813 sizeof(BL_FIRMWARE_DESCRIPTOR
);
1816 ReturnArguments
= (PBL_RETURN_ARGUMENTS
)((ULONG_PTR
)ParameterBlock
+
1818 ReturnArgumentsOffset
);
1819 ReturnArguments
->Version
= BL_RETURN_ARGUMENTS_VERSION
;
1820 ReturnArguments
->DataPage
= 0;
1821 ReturnArguments
->DataSize
= 0;
1823 /* Structure complete */
1824 ImageParameters
->ActualSize
= ParameterBlock
->ReturnArgumentsOffset
+
1825 sizeof(*ReturnArguments
);
1826 return STATUS_SUCCESS
;
1830 ImgArchEfiStartBootApplication (
1831 _In_ PBL_APPLICATION_ENTRY AppEntry
,
1832 _In_ PVOID ImageBase
,
1833 _In_ ULONG ImageSize
,
1834 _In_ PBL_RETURN_ARGUMENTS ReturnArguments
1838 KDESCRIPTOR Gdt
, Idt
;
1839 ULONG BootSizeNeeded
;
1842 PIMAGE_NT_HEADERS NtHeaders
;
1843 PVOID NewStack
, NewGdt
, NewIdt
;
1844 BL_IMAGE_PARAMETERS Parameters
;
1846 /* Read the current IDT and GDT */
1850 /* Allocate space for the IDT, GDT, and 24 pages of stack */
1851 BootSizeNeeded
= (ULONG
)PAGE_ALIGN(Idt
.Limit
+ Gdt
.Limit
+ 1 + 25 * PAGE_SIZE
);
1852 Status
= MmPapAllocatePagesInRange(&BootData
,
1854 BootSizeNeeded
>> PAGE_SHIFT
,
1859 if (!NT_SUCCESS(Status
))
1864 /* Zero the boot data */
1865 RtlZeroMemory(BootData
, BootSizeNeeded
);
1867 /* Set the new stack, GDT and IDT */
1868 NewStack
= (PVOID
)((ULONG_PTR
)BootData
+ (24 * PAGE_SIZE
) - 8);
1869 NewGdt
= (PVOID
)((ULONG_PTR
)BootData
+ (24 * PAGE_SIZE
));
1870 NewIdt
= (PVOID
)((ULONG_PTR
)BootData
+ (24 * PAGE_SIZE
) + Gdt
.Limit
+ 1);
1872 /* Copy the current (firmware) GDT and IDT */
1873 RtlCopyMemory(NewGdt
, (PVOID
)Gdt
.Base
, Gdt
.Limit
+ 1);
1874 RtlCopyMemory(NewIdt
, (PVOID
)Idt
.Base
, Idt
.Limit
+ 1);
1876 /* Read the NT headers so that we can get the entrypoint later on */
1877 RtlImageNtHeaderEx(0, ImageBase
, ImageSize
, &NtHeaders
);
1879 /* Prepare the application parameters */
1880 RtlZeroMemory(&Parameters
, sizeof(Parameters
));
1881 Status
= ImgpInitializeBootApplicationParameters(&Parameters
,
1885 if (NT_SUCCESS(Status
))
1887 /* Set the firmware GDT/IDT as the one the application will use */
1888 BootAppGdtRegister
= Gdt
;
1889 BootAppIdtRegister
= Idt
;
1891 /* Set the entrypoint, parameters, and stack */
1892 BootApp32EntryRoutine
= (PVOID
)((ULONG_PTR
)ImageBase
+
1893 NtHeaders
->OptionalHeader
.
1894 AddressOfEntryPoint
);
1895 BootApp32Parameters
= Parameters
.Buffer
;
1896 BootApp32Stack
= NewStack
;
1899 /* Disable the kernel debugger */
1903 Archx86TransferTo32BitApplicationAsm();
1905 /* Not yet implemented. This is the last step! */
1906 EfiPrintf(L
"EFI APPLICATION RETURNED!!!\r\n");
1907 EfiStall(100000000);
1910 /* Re-enable the kernel debugger */
1916 /* Check if we had boot data allocated */
1920 MmPapFreePages(BootData
, BL_MM_INCLUDE_MAPPED_ALLOCATED
);
1923 EfiPrintf(L
"ImgArchEfiStartBootApplication not implemented for this platform.\r\n");
1927 return STATUS_NOT_IMPLEMENTED
;
1931 BlImgStartBootApplication (
1932 _In_ ULONG AppHandle
,
1933 _Inout_opt_ PBL_RETURN_ARGUMENTS ReturnArguments
1936 PBL_IMAGE_APPLICATION_ENTRY ImageAppEntry
;
1937 BL_RETURN_ARGUMENTS LocalReturnArgs
;
1938 PBL_FILE_SYSTEM_ENTRY FileSystem
;
1939 PLIST_ENTRY NextEntry
, ListHead
;
1942 /* Check if we don't have an argument structure */
1943 if (!ReturnArguments
)
1945 /* Initialize a local copy and use it instead */
1946 LocalReturnArgs
.Version
= BL_RETURN_ARGUMENTS_VERSION
;
1947 LocalReturnArgs
.Status
= STATUS_SUCCESS
;
1948 LocalReturnArgs
.Flags
= 0;
1949 LocalReturnArgs
.DataPage
= 0;
1950 LocalReturnArgs
.DataSize
= 0;
1951 ReturnArguments
= &LocalReturnArgs
;
1954 /* Make sure the handle index is valid */
1955 if (IapTableEntries
<= AppHandle
)
1957 return STATUS_INVALID_PARAMETER
;
1960 /* Get the entry for this handle, making sure it exists */
1961 ImageAppEntry
= IapImageTable
[AppHandle
];
1964 return STATUS_INVALID_PARAMETER
;
1967 /* Loop the registered file systems */
1968 ListHead
= &RegisteredFileSystems
;
1969 NextEntry
= RegisteredFileSystems
.Flink
;
1970 while (NextEntry
!= ListHead
)
1972 /* Get the filesystem entry */
1973 FileSystem
= CONTAINING_RECORD(NextEntry
,
1974 BL_FILE_SYSTEM_ENTRY
,
1977 /* See if it has a purge callback */
1978 if (FileSystem
->PurgeCallback
)
1981 FileSystem
->PurgeCallback();
1984 /* Move to the next entry */
1985 NextEntry
= NextEntry
->Flink
;
1988 /* TODO -- flush the block I/O cache too */
1989 //BlockIoPurgeCache();
1991 /* Call into EFI land to start the boot application */
1992 Status
= ImgArchEfiStartBootApplication(ImageAppEntry
->AppEntry
,
1993 ImageAppEntry
->ImageBase
,
1994 ImageAppEntry
->ImageSize
,
1997 /* Parse any arguments we got on the way back */
1998 BlpPdParseReturnArguments(ReturnArguments
);
2000 #if BL_BITLOCKER_SUPPORT
2001 /* Bitlocker stuff */
2002 FvebpCheckAllPartitions(TRUE
);
2006 /* Notify a TPM/SI event */
2007 BlEnNotifyEvent(0x10000005, NULL
);
2010 /* Reset the display */
2011 BlpDisplayReinitialize();
2013 /* TODO -- reset ETW */
2014 //BlpLogInitialize();
2021 BlImgUnloadBootApplication (
2022 _In_ ULONG AppHandle
2025 PBL_IMAGE_APPLICATION_ENTRY ImageAppEntry
;
2028 /* Make sure the handle index is valid */
2029 if (IapTableEntries
<= AppHandle
)
2031 return STATUS_INVALID_PARAMETER
;
2034 /* Get the entry for this handle, making sure it exists */
2035 ImageAppEntry
= IapImageTable
[AppHandle
];
2038 return STATUS_INVALID_PARAMETER
;
2041 /* Unload the image */
2042 Status
= BlImgUnLoadImage(ImageAppEntry
->ImageBase
,
2043 ImageAppEntry
->ImageSize
,
2045 if (NT_SUCCESS(Status
))
2047 /* Normalize the success code */
2048 Status
= STATUS_SUCCESS
;
2052 /* Normalize the failure code */
2053 Status
= STATUS_MEMORY_NOT_ALLOCATED
;
2056 /* Free the entry and the image entry as well */
2057 BlMmFreeHeap(ImageAppEntry
->AppEntry
);
2058 BlMmFreeHeap(ImageAppEntry
);
2060 /* Clear the handle */
2061 IapImageTable
[AppHandle
] = NULL
;
2063 /* Free one entry */
2064 if (!(--IapAllocatedTableEntries
))
2066 /* There are no more, so get rid of the table itself */
2067 BlMmFreeHeap(IapImageTable
);
2068 IapImageTable
= NULL
;
2069 IapTableEntries
= 0;