[BOOTLIB]: Rough sketches of BlImgLoadBootApplication, BlImgStartBootApplication...
[reactos.git] / reactos / boot / environ / lib / misc / image.c
1 /*
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)
7 */
8
9 /* INCLUDES ******************************************************************/
10
11 #include "bl.h"
12 #include <bcd.h>
13
14 /* DATA VARIABLES ************************************************************/
15
16 ULONG IapAllocatedTableEntries;
17 ULONG IapTableEntries;
18 PVOID* IapImageTable;
19
20 /* FUNCTIONS *****************************************************************/
21
22 NTSTATUS
23 ImgpGetFileSize (
24 _In_ PBL_IMG_FILE File,
25 _Out_ PULONG FileSize
26 )
27 {
28 NTSTATUS Status;
29 ULONG Size;
30 BL_FILE_INFORMATION FileInformation;
31
32 /* Check if the file was memory mapped */
33 if (File->Flags & BL_IMG_MEMORY_FILE)
34 {
35 /* Just read the size of the mapping */
36 Size = File->FileSize;
37 }
38 else
39 {
40 /* Do file I/O to get the file size */
41 Status = BlFileGetInformation(File->FileId,
42 &FileInformation);
43 if (!NT_SUCCESS(Status))
44 {
45 return Status;
46 }
47
48 /* We only support files less than 4GB in the Image Mapped */
49 Size = FileInformation.Size;
50 if (FileInformation.Size > ULONG_MAX)
51 {
52 return STATUS_NOT_SUPPORTED;
53 }
54 }
55
56 /* Return the size and success */
57 *FileSize = Size;
58 return STATUS_SUCCESS;
59 }
60
61 NTSTATUS
62 ImgpReadAtFileOffset (
63 _In_ PBL_IMG_FILE File,
64 _In_ ULONG Size,
65 _In_ ULONGLONG ByteOffset,
66 _In_ PVOID Buffer,
67 _Out_ PULONG BytesReturned
68 )
69 {
70 NTSTATUS Status;
71
72 /* Check what if this is a mapped file or not */
73 if (File->Flags & BL_IMG_MEMORY_FILE)
74 {
75 /* Check if the boundaries are within the file size */
76 if ((ByteOffset + Size) <= File->FileSize)
77 {
78 /* Yep, copy into the caller-supplied buffer */
79 RtlCopyMemory(Buffer,
80 (PVOID)((ULONG_PTR)File->BaseAddress + (ULONG_PTR)ByteOffset),
81 Size);
82
83 /* If caller wanted to know, return the size copied */
84 if (BytesReturned)
85 {
86 *BytesReturned = Size;
87 }
88
89 /* All good */
90 Status = STATUS_SUCCESS;
91 }
92 else
93 {
94 /* Doesn't fit */
95 Status = STATUS_INVALID_PARAMETER;
96 }
97 }
98 else
99 {
100 /* Issue the file I/O instead */
101 Status = BlFileReadAtOffsetEx(File->FileId,
102 Size,
103 ByteOffset,
104 Buffer,
105 BytesReturned,
106 0);
107 }
108
109 /* Return the final status */
110 return Status;
111 }
112
113 NTSTATUS
114 ImgpOpenFile (
115 _In_ ULONG DeviceId,
116 _In_ PWCHAR FileName,
117 _In_ ULONG Flags,
118 _Out_ PBL_IMG_FILE NewFile
119 )
120 {
121 NTSTATUS Status;
122 ULONG FileSize;
123 ULONGLONG RemoteFileSize;
124 PVOID RemoteFileAddress;
125 ULONG FileId;
126
127 /* First, try to see if BD has this file remotely */
128 Status = BlBdPullRemoteFile(FileName,
129 &RemoteFileAddress,
130 &RemoteFileSize);
131 if (NT_SUCCESS(Status))
132 {
133 /* Yep, get the file size and make sure it's < 4GB */
134 FileSize = RemoteFileSize;
135 if (RemoteFileSize <= ULONG_MAX)
136 {
137 /* Remember this is a memory mapped remote file */
138 NewFile->Flags |= (BL_IMG_MEMORY_FILE | BL_IMG_REMOTE_FILE);
139 NewFile->FileSize = FileSize;
140 NewFile->BaseAddress = RemoteFileAddress;
141 goto Quickie;
142 }
143 }
144
145 /* Use File I/O instead */
146 Status = BlFileOpen(DeviceId,
147 FileName,
148 BL_FILE_READ_ACCESS,
149 &FileId);
150 if (!NT_SUCCESS(Status))
151 {
152 /* Bail out on failure */
153 return Status;
154 }
155
156 /* Make sure nobody thinks this is a memory file */
157 NewFile->Flags &= ~BL_IMG_MEMORY_FILE;
158 NewFile->FileId = FileId;
159
160 Quickie:
161 /* Set common data for both memory and I/O based file */
162 NewFile->Flags |= BL_IMG_VALID_FILE;
163 NewFile->FileName = FileName;
164 return Status;
165 }
166
167 NTSTATUS
168 ImgpCloseFile (
169 _In_ PBL_IMG_FILE File
170 )
171 {
172 NTSTATUS Status;
173
174 /* Make sure this is a valid file, otherwise no-op */
175 Status = STATUS_SUCCESS;
176 if (File->Flags & BL_IMG_VALID_FILE)
177 {
178 /* Is this a memory mapped file? */
179 if (!(File->Flags & BL_IMG_MEMORY_FILE))
180 {
181 /* Nope, close the file handle */
182 return BlFileClose(File->FileId);
183 }
184
185 /* Is this a remote file? */
186 if (File->Flags & BL_IMG_REMOTE_FILE)
187 {
188 /* Then only free the memory in that scenario */
189 EfiPrintf(L"TODO\r\n");
190 //return MmPapFreePages(File->BaseAddress, TRUE);
191 }
192 }
193
194 /* Return the final status */
195 return Status;
196 }
197
198 NTSTATUS
199 BlImgUnallocateImageBuffer (
200 _In_ PVOID ImageBase,
201 _In_ ULONG ImageSize,
202 _In_ ULONG ImageFlags
203 )
204 {
205 EfiPrintf(L"leaking the shit out of %p\r\n", ImageBase);
206 return STATUS_NOT_IMPLEMENTED;
207 }
208
209 NTSTATUS
210 BlImgAllocateImageBuffer (
211 _Inout_ PVOID* ImageBuffer,
212 _In_ ULONG MemoryType,
213 _In_ ULONGLONG ImageSize,
214 _In_ ULONG Flags
215 )
216 {
217 ULONG Attributes;
218 ULONGLONG Pages, Size;
219 PVOID MappedBase, CurrentBuffer;
220 NTSTATUS Status;
221 PHYSICAL_ADDRESS PhysicalAddress;
222
223 /* Read and reset the current buffer address */
224 CurrentBuffer = *ImageBuffer;
225 *ImageBuffer = NULL;
226
227 /* Align the image size to page */
228 Size = ROUND_TO_PAGES(ImageSize);
229
230 /* Not sure what this attribute does yet */
231 Attributes = 0;
232 if (Flags & BL_LOAD_IMG_UNKNOWN_BUFFER_FLAG)
233 {
234 Attributes = 0x10000;
235 }
236
237 /* Check if the caller wants a virtual buffer */
238 if (Flags & BL_LOAD_IMG_VIRTUAL_BUFFER)
239 {
240 /* Set the physical address to the current buffer */
241 PhysicalAddress.QuadPart = (ULONG_PTR)CurrentBuffer;
242 Pages = Size >> PAGE_SHIFT;
243
244 /* Allocate the physical pages */
245 Status = BlMmAllocatePhysicalPages(&PhysicalAddress,
246 Pages,
247 MemoryType,
248 Attributes,
249 0);
250 if (!NT_SUCCESS(Status))
251 {
252 /* If that failed, remove allocation attributes */
253 PhysicalAddress.QuadPart = 0;
254 Attributes &= ~BlMemoryValidAllocationAttributeMask,
255 Status = BlMmAllocatePhysicalPages(&PhysicalAddress,
256 Pages,
257 MemoryType,
258 Attributes,
259 0);
260 }
261
262 /* Check if either attempts succeeded */
263 if (!NT_SUCCESS(Status))
264 {
265 return Status;
266 }
267
268 /* Now map the physical buffer at the address requested */
269 MappedBase = (PVOID)PhysicalAddress.LowPart;
270 Status = BlMmMapPhysicalAddressEx(&MappedBase,
271 BlMemoryFixed,
272 Size,
273 PhysicalAddress);
274 if (!NT_SUCCESS(Status))
275 {
276 /* Free on failure if needed */
277 BlMmFreePhysicalPages(PhysicalAddress);
278 return Status;
279 }
280 }
281 else
282 {
283 /* Otherwise, allocate raw physical pages */
284 MappedBase = CurrentBuffer;
285 Pages = Size >> PAGE_SHIFT;
286 Status = MmPapAllocatePagesInRange(&MappedBase,
287 MemoryType,
288 Pages,
289 Attributes,
290 0,
291 NULL,
292 0);
293 if (!NT_SUCCESS(Status))
294 {
295 /* If that failed, try without allocation attributes */
296 MappedBase = NULL;
297 Attributes &= ~BlMemoryValidAllocationAttributeMask,
298 Status = MmPapAllocatePagesInRange(&MappedBase,
299 MemoryType,
300 Pages,
301 Attributes,
302 0,
303 NULL,
304 0);
305 }
306
307 /* Check if either attempts succeeded */
308 if (!NT_SUCCESS(Status))
309 {
310 return Status;
311 }
312 }
313
314 /* Success path, returned allocated address */
315 *ImageBuffer = MappedBase;
316 return STATUS_SUCCESS;
317 }
318
319 NTSTATUS
320 BlImgLoadImageWithProgress2 (
321 _In_ ULONG DeviceId,
322 _In_ BL_MEMORY_TYPE MemoryType,
323 _In_ PWCHAR FileName,
324 _Inout_ PVOID* MappedBase,
325 _Inout_ PULONG MappedSize,
326 _In_ ULONG ImageFlags,
327 _In_ BOOLEAN ShowProgress,
328 _Out_opt_ PUCHAR* HashBuffer,
329 _Out_opt_ PULONG HashSize
330 )
331 {
332 NTSTATUS Status;
333 PVOID BaseAddress, Buffer;
334 ULONG RemainingLength, CurrentSize, ImageSize, ReadSize;
335 BOOLEAN ComputeSignature, ComputeHash, Completed;
336 BL_IMG_FILE FileHandle;
337 ULONGLONG ByteOffset;
338 PHYSICAL_ADDRESS PhysicalAddress;
339
340 /* Initialize variables */
341 BaseAddress = 0;
342 ImageSize = 0;
343 Completed = FALSE;
344 RtlZeroMemory(&FileHandle, sizeof(FileHandle));
345
346 /* Check for missing parameters */
347 if (!MappedBase)
348 {
349 Status = STATUS_INVALID_PARAMETER;
350 goto Quickie;
351 }
352 if (!FileName)
353 {
354 Status = STATUS_INVALID_PARAMETER;
355 goto Quickie;
356 }
357 if (!MappedSize)
358 {
359 Status = STATUS_INVALID_PARAMETER;
360 goto Quickie;
361 }
362
363 /* Check if the image buffer is being provided */
364 if (ImageFlags & BL_LOAD_IMG_EXISTING_BUFFER)
365 {
366 /* An existing base must already exist */
367 if (!(*MappedBase))
368 {
369 Status = STATUS_INVALID_PARAMETER;
370 goto Quickie;
371 }
372 }
373
374 /* Check of a hash is being requested */
375 if (ImageFlags & BL_LOAD_IMG_COMPUTE_HASH)
376 {
377 /* Make sure we can return the hash */
378 if (!HashBuffer)
379 {
380 Status = STATUS_INVALID_PARAMETER;
381 goto Quickie;
382 }
383 if (!HashSize)
384 {
385 Status = STATUS_INVALID_PARAMETER;
386 goto Quickie;
387 }
388 }
389
390 /* Check for invalid combination of parameters */
391 if ((ImageFlags & BL_LOAD_IMG_COMPUTE_HASH) && (ImageFlags & 0x270))
392 {
393 Status = STATUS_INVALID_PARAMETER;
394 goto Quickie;
395 }
396
397 /* Initialize hash if requested by caller */
398 if (HashBuffer)
399 {
400 *HashBuffer = 0;
401 }
402
403 /* Do the same for the hash size */
404 if (HashSize)
405 {
406 *HashSize = 0;
407 }
408
409 /* Open the image file */
410 Status = ImgpOpenFile(DeviceId, FileName, DeviceId, &FileHandle);
411 if (!NT_SUCCESS(Status))
412 {
413 EfiPrintf(L"Error opening file: %lx\r\n", Status);
414 goto Quickie;
415 }
416
417 /* Get the size of the image */
418 Status = ImgpGetFileSize(&FileHandle, &ImageSize);
419 if (!NT_SUCCESS(Status))
420 {
421 EfiPrintf(L"Error getting file size: %lx\r\n", Status);
422 goto Quickie;
423 }
424
425 /* Read the current base address */
426 BaseAddress = *MappedBase;
427 if (ImageFlags & BL_LOAD_IMG_EXISTING_BUFFER)
428 {
429 /* Check if the current buffer is too small */
430 if (*MappedSize < ImageSize)
431 {
432 /* Return the required size of the buffer */
433 *MappedSize = ImageSize;
434 Status = STATUS_BUFFER_TOO_SMALL;
435 }
436 }
437 else
438 {
439 /* A buffer was not provided, allocate one ourselves */
440 Status = BlImgAllocateImageBuffer(&BaseAddress,
441 MemoryType,
442 ImageSize,
443 ImageFlags);
444 }
445
446 /* Bail out if allocation failed */
447 if (!NT_SUCCESS(Status))
448 {
449 goto Quickie;
450 }
451
452 /* Set the initial byte offset and length to read */
453 RemainingLength = ImageSize;
454 ByteOffset = 0;
455 Buffer = BaseAddress;
456
457 /* Update the initial progress */
458 Completed = FALSE;
459 if (ShowProgress)
460 {
461 BlUtlUpdateProgress(0, &Completed);
462 ShowProgress &= (Completed != 0) - 1;
463 }
464
465 /* Set the chunk size for each read */
466 ReadSize = 0x100000;
467 if (ReadSize > ImageSize)
468 {
469 ReadSize = ImageSize;
470 }
471
472 /* Check if we should compute hash and/or signatures */
473 ComputeSignature = ImageFlags & BL_LOAD_IMG_COMPUTE_SIGNATURE;
474 if ((ComputeSignature) || (ImageFlags & BL_LOAD_IMG_COMPUTE_HASH))
475 {
476 ComputeHash = TRUE;
477 // todo: crypto is hard
478 }
479
480 /* Begin the read loop */
481 while (RemainingLength)
482 {
483 /* Check if we've got more than a chunk left to read */
484 if (RemainingLength > ReadSize)
485 {
486 /* Read a chunk*/
487 CurrentSize = ReadSize;
488 }
489 else
490 {
491 /* Read only what's left */
492 CurrentSize = RemainingLength;
493 }
494
495 /* Read the chunk */
496 Status = ImgpReadAtFileOffset(&FileHandle,
497 CurrentSize,
498 ByteOffset,
499 Buffer,
500 0);
501 if (!NT_SUCCESS(Status))
502 {
503 goto Quickie;
504 }
505
506 /* Check if we need to compute the hash of this chunk */
507 if (ComputeHash)
508 {
509 // todo: crypto is hard
510 }
511
512 /* Update our position and read information */
513 Buffer = (PVOID)((ULONG_PTR)Buffer + CurrentSize);
514 RemainingLength -= CurrentSize;
515 ByteOffset += CurrentSize;
516
517 /* Check if we should update the progress bar */
518 if (ShowProgress)
519 {
520 /* Compute new percentage completed, check if we're done */
521 BlUtlUpdateProgress(100 - 100 * RemainingLength / ImageSize,
522 &Completed);
523 ShowProgress &= (Completed != 0) - 1;
524 }
525 }
526
527 /* Is the read fully complete? We need to finalize the hash if requested */
528 if (ComputeHash != RemainingLength)
529 {
530 // todo: CRYPTO IS HARD
531 }
532
533 /* Success path, return back the buffer and the size of the image */
534 *MappedBase = BaseAddress;
535 *MappedSize = ImageSize;
536
537 Quickie:
538 /* Close the file handle */
539 ImgpCloseFile(&FileHandle);
540
541 /* Check if we failed and had allocated a buffer */
542 if (!(NT_SUCCESS(Status)) &&
543 (BaseAddress) &&
544 !(ImageFlags & BL_LOAD_IMG_EXISTING_BUFFER))
545 {
546 /* Check what kind of buffer we had allocated */
547 if (ImageFlags & BL_LOAD_IMG_VIRTUAL_BUFFER)
548 {
549 /* Unmap and free the virtual buffer */
550 PhysicalAddress.QuadPart = (ULONG_PTR)BaseAddress;
551 BlMmUnmapVirtualAddressEx(BaseAddress, ImageSize);
552 BlMmFreePhysicalPages(PhysicalAddress);
553 }
554 else
555 {
556 /* Free the physical buffer */
557 //MmPapFreePages(VirtualAddress, 1);
558 EfiPrintf(L"Leaking memory\r\n");
559 }
560 }
561
562 /* If we hadn't gotten to 100% yet, do it now */
563 if (ShowProgress)
564 {
565 BlUtlUpdateProgress(100, &Completed);
566 }
567
568 /* Return the final status */
569 return Status;
570 }
571
572 PIMAGE_SECTION_HEADER
573 BlImgFindSection (
574 _In_ PVOID ImageBase,
575 _In_ ULONG ImageSize
576 )
577 {
578 PIMAGE_SECTION_HEADER FoundSection;
579 ULONG i;
580 PIMAGE_SECTION_HEADER SectionHeader;
581 PIMAGE_NT_HEADERS NtHeader;
582 NTSTATUS Status;
583
584 /* Assume failure */
585 FoundSection = NULL;
586
587 /* Make sure the image is valid */
588 Status = RtlImageNtHeaderEx(0, ImageBase, ImageSize, &NtHeader);
589 if (NT_SUCCESS(Status))
590 {
591 /* Get the first section and loop through them all */
592 SectionHeader = IMAGE_FIRST_SECTION(NtHeader);
593 for (i = 0; i < NtHeader->FileHeader.NumberOfSections; i++)
594 {
595 /* Check if this is the resource section */
596 if (!_stricmp((PCCH)SectionHeader->Name, ".rsrc"))
597 {
598 /* Yep, we're done */
599 FoundSection = SectionHeader;
600 break;
601 }
602
603 /* Nope, keep going */
604 SectionHeader++;
605 }
606 }
607
608 /* Return the matching section */
609 return FoundSection;
610 }
611
612 VOID
613 BlImgQueryCodeIntegrityBootOptions (
614 _In_ PBL_LOADED_APPLICATION_ENTRY ApplicationEntry,
615 _Out_ PBOOLEAN IntegrityChecksDisabled,
616 _Out_ PBOOLEAN TestSigning
617 )
618 {
619
620 NTSTATUS Status;
621 BOOLEAN Value;
622
623 /* Check if /DISABLEINTEGRITYCHECKS is on */
624 Status = BlGetBootOptionBoolean(ApplicationEntry->BcdData,
625 BcdLibraryBoolean_DisableIntegrityChecks,
626 &Value);
627 *IntegrityChecksDisabled = NT_SUCCESS(Status) && (Value);
628
629 /* Check if /TESTSIGNING is on */
630 Status = BlGetBootOptionBoolean(ApplicationEntry->BcdData,
631 BcdLibraryBoolean_AllowPrereleaseSignatures,
632 &Value);
633 *TestSigning = NT_SUCCESS(Status) && (Value);
634 }
635
636 NTSTATUS
637 BlImgUnLoadImage (
638 _In_ PVOID ImageBase,
639 _In_ ULONG ImageSize,
640 _In_ ULONG ImageFlags
641 )
642 {
643 /* Check for missing parameters */
644 if (!(ImageSize) || !(ImageBase))
645 {
646 /* Bail out */
647 return STATUS_INVALID_PARAMETER;
648 }
649
650 /* Unallocate the image buffer */
651 return BlImgUnallocateImageBuffer(ImageBase, ImageSize, ImageFlags);
652 }
653
654 NTSTATUS
655 BlImgLoadPEImageEx (
656 _In_ ULONG DeviceId,
657 _In_ BL_MEMORY_TYPE MemoryType,
658 _In_ PWCHAR Path,
659 _Out_ PVOID* ImageBase,
660 _Out_ PULONG ImageSize,
661 _Out_ PVOID Hash,
662 _In_ ULONG Flags
663 )
664 {
665 EfiPrintf(L"PE not implemented\r\n");
666 return STATUS_NOT_IMPLEMENTED;
667 }
668
669 NTSTATUS
670 BlImgLoadBootApplication (
671 _In_ PBL_LOADED_APPLICATION_ENTRY BootEntry,
672 _Out_ PULONG AppHandle
673 )
674 {
675 NTSTATUS Status;
676 PULONGLONG AllowedList;
677 ULONGLONG AllowedCount;
678 ULONG i;
679 LARGE_INTEGER Frequency;
680 PVOID UnlockCode;
681 PBL_DEVICE_DESCRIPTOR Device, BitLockerDevice;
682 ULONG DeviceId;
683 PWCHAR Path;
684 PBL_APPLICATION_ENTRY AppEntry;
685 PBL_IMG_FILE ImageFile;
686 PVOID ImageBase;
687 ULONG ImageSize;
688 BOOLEAN DisableIntegrity, TestSigning;
689 UCHAR Hash[64];
690 ULONG Flags;
691 ULONG ListSize;
692 PBL_IMAGE_APPLICATION_ENTRY ImageAppEntry;
693
694 BitLockerDevice = NULL;
695 UnlockCode = NULL;
696 ImageFile = NULL;
697 DeviceId = -1;
698 Device = NULL;
699 ImageAppEntry = NULL;
700 Path = NULL;
701 ImageSize = 0;
702 ImageBase = NULL;
703
704 EfiPrintf(L"Loading application %p\r\n", BootEntry);
705
706 Status = BlpGetBootOptionIntegerList(BootEntry->BcdData,
707 BcdLibraryIntegerList_AllowedInMemorySettings,
708 &AllowedList,
709 &AllowedCount,
710 TRUE);
711 if (Status == STATUS_SUCCESS)
712 {
713 for (i = 0; i < AllowedCount; i++)
714 {
715 if (AllowedList[i] == BcdLibraryInteger_UndocumentedMagic)
716 {
717 BlTimeQueryPerformanceCounter(&Frequency);
718 BlAppendBootOptionInteger(BootEntry,
719 BcdLibraryInteger_UndocumentedMagic,
720 Frequency.QuadPart);
721 }
722 }
723 }
724
725 #if BL_BITLOCKER_SUPPORT
726 Status = BlFveSecureBootUnlockBootDevice(BootEntry, &BitLockerDevice, &UnlockCode);
727 #else
728 Status = STATUS_SUCCESS;
729 #endif
730 if (!NT_SUCCESS(Status))
731 {
732 goto Quickie;
733 }
734
735 Status = BlGetBootOptionDevice(BootEntry->BcdData, BcdLibraryDevice_ApplicationDevice, &Device, NULL);
736 if (!NT_SUCCESS(Status))
737 {
738 goto Quickie;
739 }
740
741 Status = BlGetBootOptionString(BootEntry->BcdData, BcdLibraryString_ApplicationPath, &Path);
742 if (!NT_SUCCESS(Status))
743 {
744 goto Quickie;
745 }
746
747 Status = BlpDeviceOpen(Device, BL_DEVICE_READ_ACCESS, 0, &DeviceId);
748 if (!NT_SUCCESS(Status))
749 {
750 goto Quickie;
751 }
752
753 BlImgQueryCodeIntegrityBootOptions(BootEntry, &DisableIntegrity, &TestSigning);
754
755 #if BL_TPM_SUPPORT
756 RtlZeroMemory(&Context, sizeof(Context);
757 Context.BootEntry = BootEntry;
758 BlEnNotifyEvent(0x10000003, &Context);
759 #endif
760
761 Flags = 0;
762 if (!DisableIntegrity)
763 {
764 Flags = 0x8070;
765 }
766
767 Status = BlImgLoadPEImageEx(DeviceId, BlLoaderMemory, Path, &ImageBase, &ImageSize, Hash, Flags);
768 if (!NT_SUCCESS(Status))
769 {
770 goto Quickie;
771 }
772
773 #if BL_KD_SUPPORT
774 if (BdDebugTransitions)
775 {
776 BdForceDebug = 1;
777 Status = BlBdInitialize();
778 if (NT_SUCCESS(Status))
779 {
780 if (BlBdDebuggerEnabled())
781 {
782 BdDebuggerNotPresent = FALSE;
783 RtlInitUnicodeString(&PathString, Path);
784 BlBdLoadImageSymbols(&PathString, ImageBase);
785 }
786 }
787 }
788 #endif
789
790 #if BL_BITLOCKER_SUPPORT
791 Status = BlSecureBootCheckPolicyOnFveDevice(BitLockerDevice);
792 #else
793 Status = STATUS_SUCCESS;
794 #endif
795 if (!NT_SUCCESS(Status))
796 {
797 goto Quickie;
798 }
799
800 #if BL_BITLOCKER_SUPPORT
801 Status = BlFveSecureBootCheckpointBootApp(BootEntry, BitLockerDevice, Hash, UnlockCode);
802 #else
803 Status = STATUS_SUCCESS;
804 #endif
805 if (!NT_SUCCESS(Status))
806 {
807 goto Quickie;
808 }
809
810 ListSize = BlGetBootOptionListSize(BootEntry->BcdData);
811
812 AppEntry = BlMmAllocateHeap(ListSize + sizeof(*AppEntry));
813 if (!AppEntry)
814 {
815 Status = STATUS_NO_MEMORY;
816 goto Quickie;
817 }
818
819 RtlZeroMemory(AppEntry, sizeof(AppEntry));
820
821 strcpy(AppEntry->Signature, "BTAPENT");
822 AppEntry->Guid = BootEntry->Guid;
823 AppEntry->Flags = BootEntry->Flags;
824 RtlCopyMemory(&AppEntry->BcdData, BootEntry->BcdData, ListSize);
825
826
827 ImageAppEntry = BlMmAllocateHeap(sizeof(*ImageAppEntry));
828 ImageAppEntry->ImageBase = ImageBase;
829 ImageAppEntry->ImageSize = ImageSize;
830 ImageAppEntry->AppEntry = AppEntry;
831
832 if (!IapTableEntries)
833 {
834 IapAllocatedTableEntries = 0;
835 IapTableEntries = 2;
836 IapImageTable = BlMmAllocateHeap(IapTableEntries * sizeof(PVOID));
837 if (!IapImageTable)
838 {
839 Status = STATUS_NO_MEMORY;
840 goto Quickie;
841 }
842
843 RtlZeroMemory(IapImageTable, sizeof(IapTableEntries * sizeof(PVOID)));
844 }
845
846 Status = BlTblSetEntry(&IapImageTable,
847 &IapTableEntries,
848 ImageAppEntry,
849 AppHandle,
850 TblDoNotPurgeEntry);
851
852 Quickie:
853 if (DeviceId != 1)
854 {
855 BlDeviceClose(DeviceId);
856 }
857
858 if (Device)
859 {
860 BlMmFreeHeap(Device);
861 }
862
863 if (Path)
864 {
865 BlMmFreeHeap(Path);
866 }
867
868 if (BitLockerDevice)
869 {
870 BlMmFreeHeap(BitLockerDevice);
871 }
872
873 if (UnlockCode)
874 {
875 BlMmFreeHeap(UnlockCode);
876 }
877
878 if (NT_SUCCESS(Status))
879 {
880 IapAllocatedTableEntries++;
881 }
882 else
883 {
884 if (ImageBase)
885 {
886 BlImgUnLoadImage(ImageBase, ImageSize, 0);
887 }
888
889 if (AppEntry)
890 {
891 BlMmFreeHeap(AppEntry);
892 }
893
894 if (ImageFile)
895 {
896 BlMmFreeHeap(ImageFile);
897 }
898
899 if (!(IapAllocatedTableEntries) && (IapImageTable))
900 {
901 BlMmFreeHeap(IapImageTable);
902 IapTableEntries = 0;
903 IapImageTable = NULL;
904 }
905 }
906
907 return Status;
908 }
909
910 NTSTATUS
911 BlpPdParseReturnArguments (
912 _In_ PBL_RETURN_ARGUMENTS ReturnArguments
913 )
914 {
915 if (ReturnArguments->DataPage == 0)
916 {
917 return STATUS_SUCCESS;
918 }
919
920 EfiPrintf(L"Return arguments not supported\r\n");
921 return STATUS_NOT_IMPLEMENTED;
922 }
923
924 NTSTATUS
925 BlImgStartBootApplication (
926 _In_ ULONG AppHandle,
927 _Inout_opt_ PBL_RETURN_ARGUMENTS ReturnArguments
928 )
929 {
930 PBL_IMAGE_APPLICATION_ENTRY ImageAppEntry;
931 BL_RETURN_ARGUMENTS LocalReturnArgs;
932 PBL_FILE_SYSTEM_ENTRY FileSystem;
933 PLIST_ENTRY NextEntry, ListHead;
934 NTSTATUS Status;
935
936 if (!ReturnArguments)
937 {
938 LocalReturnArgs.Version = 1;
939 LocalReturnArgs.Status = STATUS_SUCCESS;
940 LocalReturnArgs.Flags = 0;
941 LocalReturnArgs.DataPage = 0;
942 LocalReturnArgs.DataSize = 0;
943
944 ReturnArguments = &LocalReturnArgs;
945 }
946
947
948 if (IapTableEntries <= AppHandle)
949 {
950 return STATUS_INVALID_PARAMETER;
951 }
952
953 ImageAppEntry = IapImageTable[AppHandle];
954 if (!ImageAppEntry)
955 {
956 return STATUS_INVALID_PARAMETER;
957 }
958
959 ListHead = &RegisteredFileSystems;
960 NextEntry = RegisteredFileSystems.Flink;
961 while (NextEntry != ListHead)
962 {
963 FileSystem = CONTAINING_RECORD(NextEntry, BL_FILE_SYSTEM_ENTRY, ListEntry);
964
965 if (FileSystem->PurgeCallback)
966 {
967 FileSystem->PurgeCallback();
968 }
969
970 NextEntry = NextEntry->Flink;
971 }
972
973 /* TODO */
974 //BlockIoPurgeCache();
975
976 Status = ImgArchEfiStartBootApplication(ImageAppEntry->AppEntry,
977 ImageAppEntry->ImageBase,
978 ImageAppEntry->ImageSize,
979 ReturnArguments);
980
981 BlpPdParseReturnArguments(ReturnArguments);
982
983 #if BL_BITLOCKER_SUPPORT
984 FvebpCheckAllPartitions(TRUE);
985 #endif
986
987 #if BL_TPM_SUPPORT
988 BlEnNotifyEvent(0x10000005, NULL);
989 #endif
990
991 /* TODO */
992 //BlpDisplayReinitialize();
993
994 /* TODO */
995 //BlpLogInitialize();
996
997 return Status;
998 }
999
1000 NTSTATUS
1001 BlImgUnloadBootApplication (
1002 _In_ ULONG AppHandle
1003 )
1004 {
1005 PBL_IMAGE_APPLICATION_ENTRY ImageAppEntry; // esi@2
1006 NTSTATUS Status;
1007
1008 if (IapTableEntries <= AppHandle)
1009 {
1010 return STATUS_INVALID_PARAMETER;
1011 }
1012
1013 ImageAppEntry = IapImageTable[AppHandle];
1014 if (!ImageAppEntry)
1015 {
1016 return STATUS_INVALID_PARAMETER;
1017 }
1018
1019 Status = BlImgUnLoadImage(ImageAppEntry->ImageBase,
1020 ImageAppEntry->ImageSize,
1021 0);
1022 if (NT_SUCCESS(Status))
1023 {
1024 Status = STATUS_SUCCESS;
1025 }
1026 else
1027 {
1028 Status = STATUS_MEMORY_NOT_ALLOCATED;
1029 }
1030
1031 BlMmFreeHeap(ImageAppEntry->AppEntry);
1032 BlMmFreeHeap(ImageAppEntry);
1033
1034 IapImageTable[AppHandle] = NULL;
1035
1036 if (!(--IapAllocatedTableEntries))
1037 {
1038 BlMmFreeHeap(IapImageTable);
1039 IapImageTable = NULL;
1040 IapTableEntries = 0;
1041 }
1042
1043 return Status;
1044 }