bootim.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890
  1. /*++
  2. Copyright (c) 2014 Minoca Corp.
  3. This file is licensed under the terms of the GNU General Public License
  4. version 3. Alternative licensing terms are available. Contact
  5. info@minocacorp.com for details. See the LICENSE file at the root of this
  6. project for complete licensing information.
  7. Module Name:
  8. bootim.c
  9. Abstract:
  10. This module implements the underlying support routines for the image
  11. library to be run in the boot environment.
  12. Author:
  13. Evan Green 21-Feb-2014
  14. Environment:
  15. Boot
  16. --*/
  17. //
  18. // ------------------------------------------------------------------- Includes
  19. //
  20. #include <minoca/kernel/kernel.h>
  21. #include <minoca/lib/fat/fat.h>
  22. #include "firmware.h"
  23. #include "bootlib.h"
  24. #include "bootman.h"
  25. //
  26. // ---------------------------------------------------------------- Definitions
  27. //
  28. //
  29. // ------------------------------------------------------ Data Type Definitions
  30. //
  31. /*++
  32. Structure Description:
  33. This structure stores information about an opened file in the boot
  34. environment.
  35. Members:
  36. FileName - Stores a pointer to the name of the file.
  37. FileNameSize - Stores the size of the file name string including the null
  38. terminator.
  39. LoadedFileBuffer - Stores a pointer to the buffer containing the file.
  40. FileSize - Stores the size of the loaded file, in bytes.
  41. --*/
  42. typedef struct _BOOT_FILE_HANDLE {
  43. PSTR FileName;
  44. ULONG FileNameSize;
  45. PVOID LoadedFileBuffer;
  46. UINTN FileSize;
  47. } BOOT_FILE_HANDLE, *PBOOT_FILE_HANDLE;
  48. //
  49. // ----------------------------------------------- Internal Function Prototypes
  50. //
  51. PVOID
  52. BmpImAllocateMemory (
  53. ULONG Size,
  54. ULONG Tag
  55. );
  56. VOID
  57. BmpImFreeMemory (
  58. PVOID Allocation
  59. );
  60. KSTATUS
  61. BmpImOpenFile (
  62. PVOID SystemContext,
  63. PCSTR BinaryName,
  64. PIMAGE_FILE_INFORMATION File
  65. );
  66. VOID
  67. BmpImCloseFile (
  68. PIMAGE_FILE_INFORMATION File
  69. );
  70. KSTATUS
  71. BmpImLoadFile (
  72. PIMAGE_FILE_INFORMATION File,
  73. PIMAGE_BUFFER Buffer
  74. );
  75. VOID
  76. BmpImUnloadBuffer (
  77. PIMAGE_FILE_INFORMATION File,
  78. PIMAGE_BUFFER Buffer
  79. );
  80. KSTATUS
  81. BmpImAllocateAddressSpace (
  82. PLOADED_IMAGE Image
  83. );
  84. VOID
  85. BmpImFreeAddressSpace (
  86. PLOADED_IMAGE Image
  87. );
  88. KSTATUS
  89. BmpImMapImageSegment (
  90. HANDLE AddressSpaceHandle,
  91. PVOID AddressSpaceAllocation,
  92. PIMAGE_FILE_INFORMATION File,
  93. ULONGLONG FileOffset,
  94. PIMAGE_SEGMENT Segment,
  95. PIMAGE_SEGMENT PreviousSegment
  96. );
  97. VOID
  98. BmpImUnmapImageSegment (
  99. HANDLE AddressSpaceHandle,
  100. PIMAGE_SEGMENT Segment
  101. );
  102. KSTATUS
  103. BmpImNotifyImageLoad (
  104. PLOADED_IMAGE Image
  105. );
  106. VOID
  107. BmpImNotifyImageUnload (
  108. PLOADED_IMAGE Image
  109. );
  110. VOID
  111. BmpImInvalidateInstructionCacheRegion (
  112. PVOID Address,
  113. ULONG Size
  114. );
  115. //
  116. // -------------------------------------------------------------------- Globals
  117. //
  118. //
  119. // Store a pointer to the boot device.
  120. //
  121. PVOID BmBootDevice;
  122. //
  123. // Store a pointer to the selected boot entry.
  124. //
  125. PBOOT_ENTRY BmBootEntry;
  126. //
  127. // Store the IDs of the directories to try when opening an image file.
  128. //
  129. FILE_ID BmSystemDirectoryId;
  130. //
  131. // Define the image library function table.
  132. //
  133. IM_IMPORT_TABLE BmImageFunctionTable = {
  134. BmpImAllocateMemory,
  135. BmpImFreeMemory,
  136. BmpImOpenFile,
  137. BmpImCloseFile,
  138. BmpImLoadFile,
  139. NULL,
  140. BmpImUnloadBuffer,
  141. BmpImAllocateAddressSpace,
  142. BmpImFreeAddressSpace,
  143. BmpImMapImageSegment,
  144. BmpImUnmapImageSegment,
  145. BmpImNotifyImageLoad,
  146. BmpImNotifyImageUnload,
  147. BmpImInvalidateInstructionCacheRegion,
  148. NULL,
  149. NULL,
  150. NULL
  151. };
  152. //
  153. // ------------------------------------------------------------------ Functions
  154. //
  155. KSTATUS
  156. BmpInitializeImageSupport (
  157. PVOID BootDevice,
  158. PBOOT_ENTRY BootEntry
  159. )
  160. /*++
  161. Routine Description:
  162. This routine initializes the image library for use in the boot manager.
  163. Arguments:
  164. BootDevice - Supplies a pointer to the boot volume token, used for loading
  165. images from disk.
  166. BootEntry - Supplies a pointer to the selected boot entry.
  167. Return Value:
  168. Status code.
  169. --*/
  170. {
  171. FILE_PROPERTIES Properties;
  172. KSTATUS Status;
  173. INITIALIZE_LIST_HEAD(&BmLoadedImageList);
  174. BmBootDevice = BootDevice;
  175. BmBootEntry = BootEntry;
  176. //
  177. // Open up the directories to search.
  178. //
  179. Status = BoLookupPath(BmBootDevice,
  180. NULL,
  181. BootEntry->SystemPath,
  182. &Properties);
  183. if (!KSUCCESS(Status)) {
  184. goto InitializeImageSupportEnd;
  185. }
  186. BmSystemDirectoryId = Properties.FileId;
  187. Status = ImInitialize(&BmImageFunctionTable);
  188. if (!KSUCCESS(Status)) {
  189. goto InitializeImageSupportEnd;
  190. }
  191. Status = STATUS_SUCCESS;
  192. InitializeImageSupportEnd:
  193. return Status;
  194. }
  195. //
  196. // --------------------------------------------------------- Internal Functions
  197. //
  198. PVOID
  199. BmpImAllocateMemory (
  200. ULONG Size,
  201. ULONG Tag
  202. )
  203. /*++
  204. Routine Description:
  205. This routine allocates memory from the boot environment for the image
  206. library.
  207. Arguments:
  208. Size - Supplies the number of bytes required for the memory allocation.
  209. Tag - Supplies a 32-bit ASCII identifier used to tag the memroy allocation.
  210. Return Value:
  211. Returns a pointer to the memory allocation on success.
  212. NULL on failure.
  213. --*/
  214. {
  215. return BoAllocateMemory(Size);
  216. }
  217. VOID
  218. BmpImFreeMemory (
  219. PVOID Allocation
  220. )
  221. /*++
  222. Routine Description:
  223. This routine frees memory to the boot environment allocated by the image
  224. library.
  225. Arguments:
  226. Allocation - Supplies a pointer the allocation to free.
  227. Return Value:
  228. None.
  229. --*/
  230. {
  231. BoFreeMemory(Allocation);
  232. return;
  233. }
  234. KSTATUS
  235. BmpImOpenFile (
  236. PVOID SystemContext,
  237. PCSTR BinaryName,
  238. PIMAGE_FILE_INFORMATION File
  239. )
  240. /*++
  241. Routine Description:
  242. This routine opens a file.
  243. Arguments:
  244. SystemContext - Supplies the context pointer passed to the load executable
  245. function.
  246. BinaryName - Supplies the name of the executable image to open.
  247. File - Supplies a pointer where the information for the file including its
  248. open handle will be returned.
  249. Return Value:
  250. Status code.
  251. --*/
  252. {
  253. PBOOT_FILE_HANDLE BootFileHandle;
  254. KSTATUS Status;
  255. BootFileHandle = BoAllocateMemory(sizeof(BOOT_FILE_HANDLE));
  256. if (BootFileHandle == NULL) {
  257. Status = STATUS_INSUFFICIENT_RESOURCES;
  258. goto OpenFileEnd;
  259. }
  260. RtlZeroMemory(BootFileHandle, sizeof(BOOT_FILE_HANDLE));
  261. BootFileHandle->FileNameSize = RtlStringLength(BinaryName) + 1;
  262. BootFileHandle->FileName = BoAllocateMemory(BootFileHandle->FileNameSize);
  263. if (BootFileHandle->FileName == NULL) {
  264. Status = STATUS_INSUFFICIENT_RESOURCES;
  265. goto OpenFileEnd;
  266. }
  267. RtlCopyMemory(BootFileHandle->FileName,
  268. BinaryName,
  269. BootFileHandle->FileNameSize);
  270. //
  271. // Open the file enough to make sure it's there, but don't actually load
  272. // it just now.
  273. //
  274. Status = BoLoadFile(BmBootDevice,
  275. &BmSystemDirectoryId,
  276. BootFileHandle->FileName,
  277. NULL,
  278. &(BootFileHandle->FileSize),
  279. &(File->ModificationDate));
  280. if (!KSUCCESS(Status)) {
  281. goto OpenFileEnd;
  282. }
  283. File->Size = BootFileHandle->FileSize;
  284. File->DeviceId = 0;
  285. File->FileId = 0;
  286. OpenFileEnd:
  287. if (!KSUCCESS(Status)) {
  288. if (BootFileHandle != NULL) {
  289. if (BootFileHandle->FileName != NULL) {
  290. BoFreeMemory(BootFileHandle->FileName);
  291. }
  292. BoFreeMemory(BootFileHandle);
  293. BootFileHandle = INVALID_HANDLE;
  294. }
  295. }
  296. File->Handle = BootFileHandle;
  297. return Status;
  298. }
  299. VOID
  300. BmpImCloseFile (
  301. PIMAGE_FILE_INFORMATION File
  302. )
  303. /*++
  304. Routine Description:
  305. This routine closes an open file, invalidating any memory mappings to it.
  306. Arguments:
  307. File - Supplies a pointer to the file information.
  308. Return Value:
  309. None.
  310. --*/
  311. {
  312. PBOOT_FILE_HANDLE BootFileHandle;
  313. BootFileHandle = (PBOOT_FILE_HANDLE)(File->Handle);
  314. ASSERT(BootFileHandle->LoadedFileBuffer == NULL);
  315. if (BootFileHandle->FileName != NULL) {
  316. BoFreeMemory(BootFileHandle->FileName);
  317. }
  318. BoFreeMemory(BootFileHandle);
  319. return;
  320. }
  321. KSTATUS
  322. BmpImLoadFile (
  323. PIMAGE_FILE_INFORMATION File,
  324. PIMAGE_BUFFER Buffer
  325. )
  326. /*++
  327. Routine Description:
  328. This routine loads an entire file into memory so the image library can
  329. access it.
  330. Arguments:
  331. File - Supplies a pointer to the file information.
  332. Buffer - Supplies a pointer where the buffer will be returned on success.
  333. Return Value:
  334. Status code.
  335. --*/
  336. {
  337. PBOOT_FILE_HANDLE BootFileHandle;
  338. KSTATUS Status;
  339. BootFileHandle = (PBOOT_FILE_HANDLE)(File->Handle);
  340. if (BootFileHandle->LoadedFileBuffer == NULL) {
  341. Status = BoLoadFile(BmBootDevice,
  342. &BmSystemDirectoryId,
  343. BootFileHandle->FileName,
  344. &(BootFileHandle->LoadedFileBuffer),
  345. NULL,
  346. NULL);
  347. if (!KSUCCESS(Status)) {
  348. goto ImLoadFileEnd;
  349. }
  350. }
  351. Status = STATUS_SUCCESS;
  352. ImLoadFileEnd:
  353. if (KSUCCESS(Status)) {
  354. Buffer->Data = BootFileHandle->LoadedFileBuffer;
  355. Buffer->Size = BootFileHandle->FileSize;
  356. }
  357. return Status;
  358. }
  359. VOID
  360. BmpImUnloadBuffer (
  361. PIMAGE_FILE_INFORMATION File,
  362. PIMAGE_BUFFER Buffer
  363. )
  364. /*++
  365. Routine Description:
  366. This routine unloads a file and frees the buffer associated with a load
  367. image call.
  368. Arguments:
  369. File - Supplies a pointer to the file information.
  370. Buffer - Supplies the buffer returned by the load file function.
  371. Return Value:
  372. None.
  373. --*/
  374. {
  375. PBOOT_FILE_HANDLE BootFileHandle;
  376. BootFileHandle = (PBOOT_FILE_HANDLE)(File->Handle);
  377. if (BootFileHandle->LoadedFileBuffer != NULL) {
  378. BoFreeMemory(BootFileHandle->LoadedFileBuffer);
  379. BootFileHandle->LoadedFileBuffer = NULL;
  380. }
  381. return;
  382. }
  383. KSTATUS
  384. BmpImAllocateAddressSpace (
  385. PLOADED_IMAGE Image
  386. )
  387. /*++
  388. Routine Description:
  389. This routine allocates a section of virtual address space that an image
  390. can be mapped in to.
  391. Arguments:
  392. Image - Supplies a pointer to the image being loaded. The system context,
  393. size, file information, load flags, and preferred virtual address will
  394. be initialized. This routine should set up the loaded image buffer,
  395. loaded lowest address, and allocator handle if needed.
  396. Return Value:
  397. Status code.
  398. --*/
  399. {
  400. UINTN AlignedSize;
  401. UINTN PageOffset;
  402. UINTN PageSize;
  403. PHYSICAL_ADDRESS PhysicalAddress;
  404. PVOID PreferredAddress;
  405. KSTATUS Status;
  406. PreferredAddress = Image->PreferredLowestAddress;
  407. PageSize = MmPageSize();
  408. PageOffset = (UINTN)PreferredAddress -
  409. ALIGN_RANGE_DOWN((UINTN)PreferredAddress, PageSize);
  410. AlignedSize = ALIGN_RANGE_UP(Image->Size + PageOffset, PageSize);
  411. //
  412. // Allocate pages from the boot environment. This memory backs a boot
  413. // application image, so it is marked as loader temporary.
  414. //
  415. Status = FwAllocatePages(&PhysicalAddress,
  416. AlignedSize,
  417. PageSize,
  418. MemoryTypeLoaderTemporary);
  419. if (!KSUCCESS(Status)) {
  420. goto AllocateAddressSpaceEnd;
  421. }
  422. ASSERT((UINTN)PhysicalAddress == PhysicalAddress);
  423. Image->BaseDifference = (PhysicalAddress + PageOffset) -
  424. (UINTN)PreferredAddress;
  425. Image->LoadedImageBuffer = (PVOID)(UINTN)(PhysicalAddress + PageOffset);
  426. AllocateAddressSpaceEnd:
  427. return Status;
  428. }
  429. VOID
  430. BmpImFreeAddressSpace (
  431. PLOADED_IMAGE Image
  432. )
  433. /*++
  434. Routine Description:
  435. This routine frees a section of virtual address space that was previously
  436. allocated.
  437. Arguments:
  438. Image - Supplies a pointer to the loaded (or partially loaded) image.
  439. Return Value:
  440. None.
  441. --*/
  442. {
  443. return;
  444. }
  445. KSTATUS
  446. BmpImMapImageSegment (
  447. HANDLE AddressSpaceHandle,
  448. PVOID AddressSpaceAllocation,
  449. PIMAGE_FILE_INFORMATION File,
  450. ULONGLONG FileOffset,
  451. PIMAGE_SEGMENT Segment,
  452. PIMAGE_SEGMENT PreviousSegment
  453. )
  454. /*++
  455. Routine Description:
  456. This routine maps a section of the image to the given virtual address.
  457. Arguments:
  458. AddressSpaceHandle - Supplies the handle used to claim the overall region
  459. of address space.
  460. AddressSpaceAllocation - Supplies the original lowest virtual address for
  461. this image.
  462. File - Supplies an optional pointer to the file being mapped. If this
  463. parameter is NULL, then a zeroed memory section is being mapped.
  464. FileOffset - Supplies the offset from the beginning of the file to the
  465. beginning of the mapping, in bytes.
  466. Segment - Supplies a pointer to the segment information to map. On output,
  467. the virtual address will contain the actual mapped address, and the
  468. mapping handle may be set.
  469. PreviousSegment - Supplies an optional pointer to the previous segment
  470. that was mapped, so this routine can handle overlap appropriately. This
  471. routine can assume that segments are always mapped in increasing order.
  472. Return Value:
  473. Status code.
  474. --*/
  475. {
  476. PBOOT_FILE_HANDLE BootFileHandle;
  477. PVOID Source;
  478. BootFileHandle = NULL;
  479. if (File != NULL) {
  480. BootFileHandle = (PBOOT_FILE_HANDLE)(File->Handle);
  481. }
  482. //
  483. // Copy from the file buffer plus the given offset.
  484. //
  485. if (Segment->FileSize != 0) {
  486. ASSERT((BootFileHandle != NULL) &&
  487. (FileOffset + Segment->FileSize < BootFileHandle->FileSize));
  488. Source = (PUCHAR)(BootFileHandle->LoadedFileBuffer) + FileOffset;
  489. RtlCopyMemory(Segment->VirtualAddress, Source, Segment->FileSize);
  490. }
  491. if (Segment->MemorySize > Segment->FileSize) {
  492. RtlZeroMemory(Segment->VirtualAddress + Segment->FileSize,
  493. Segment->MemorySize - Segment->FileSize);
  494. }
  495. return STATUS_SUCCESS;
  496. }
  497. VOID
  498. BmpImUnmapImageSegment (
  499. HANDLE AddressSpaceHandle,
  500. PIMAGE_SEGMENT Segment
  501. )
  502. /*++
  503. Routine Description:
  504. This routine maps unmaps an image segment.
  505. Arguments:
  506. AddressSpaceHandle - Supplies the handle used to claim the overall region
  507. of address space.
  508. Segment - Supplies a pointer to the segment information to unmap.
  509. Return Value:
  510. None.
  511. --*/
  512. {
  513. //
  514. // Unmapping is currently not implemented.
  515. //
  516. return;
  517. }
  518. KSTATUS
  519. BmpImNotifyImageLoad (
  520. PLOADED_IMAGE Image
  521. )
  522. /*++
  523. Routine Description:
  524. This routine notifies the primary consumer of the image library that an
  525. image has been loaded.
  526. Arguments:
  527. Image - Supplies the image that has just been loaded. This image should
  528. be subsequently returned to the image library upon requests for loaded
  529. images with the given name.
  530. Return Value:
  531. Status code. Failing status codes veto the image load.
  532. --*/
  533. {
  534. ULONG AllocationSize;
  535. PSTR FileName;
  536. PDEBUG_MODULE LoadedModule;
  537. ULONG NameSize;
  538. KSTATUS Status;
  539. FileName = RtlStringFindCharacterRight(Image->FileName, '/', -1);
  540. if (FileName != NULL) {
  541. FileName += 1;
  542. } else {
  543. FileName = Image->FileName;
  544. }
  545. NameSize = RtlStringLength(FileName) + 1;
  546. AllocationSize = sizeof(DEBUG_MODULE) +
  547. ((NameSize - ANYSIZE_ARRAY) * sizeof(CHAR));
  548. LoadedModule = BoAllocateMemory(AllocationSize);
  549. if (LoadedModule == NULL) {
  550. Status = STATUS_INSUFFICIENT_RESOURCES;
  551. goto NotifyImageLoadEnd;
  552. }
  553. RtlZeroMemory(LoadedModule, AllocationSize);
  554. //
  555. // Initialize the loaded image parameters.
  556. //
  557. RtlStringCopy(LoadedModule->BinaryName, FileName, NameSize);
  558. LoadedModule->StructureSize = AllocationSize;
  559. LoadedModule->Timestamp = Image->File.ModificationDate;
  560. LoadedModule->LowestAddress = Image->PreferredLowestAddress +
  561. Image->BaseDifference;
  562. LoadedModule->Size = Image->Size;
  563. LoadedModule->EntryPoint = Image->EntryPoint;
  564. LoadedModule->Image = Image;
  565. Image->DebuggerModule = LoadedModule;
  566. KdReportModuleChange(LoadedModule, TRUE);
  567. Status = STATUS_SUCCESS;
  568. NotifyImageLoadEnd:
  569. if (!KSUCCESS(Status)) {
  570. if (LoadedModule != NULL) {
  571. BoFreeMemory(LoadedModule);
  572. }
  573. }
  574. return Status;
  575. }
  576. VOID
  577. BmpImNotifyImageUnload (
  578. PLOADED_IMAGE Image
  579. )
  580. /*++
  581. Routine Description:
  582. This routine notifies the primary consumer of the image library that an
  583. image is about to be unloaded from memory. Once this routine returns, the
  584. image should not be referenced again as it will be freed.
  585. Arguments:
  586. Image - Supplies the image that is about to be unloaded.
  587. Return Value:
  588. None.
  589. --*/
  590. {
  591. PDEBUG_MODULE UnloadingModule;
  592. UnloadingModule = Image->DebuggerModule;
  593. Image->DebuggerModule = NULL;
  594. KdReportModuleChange(UnloadingModule, FALSE);
  595. BoFreeMemory(UnloadingModule);
  596. return;
  597. }
  598. VOID
  599. BmpImInvalidateInstructionCacheRegion (
  600. PVOID Address,
  601. ULONG Size
  602. )
  603. /*++
  604. Routine Description:
  605. This routine invalidates an instruction cache region after code has been
  606. modified.
  607. Arguments:
  608. Address - Supplies the virtual address of the revion to invalidate.
  609. Size - Supplies the number of bytes to invalidate.
  610. Return Value:
  611. None.
  612. --*/
  613. {
  614. return;
  615. }