bootim.c 23 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136
  1. /*++
  2. Copyright (c) 2012 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 13-Oct-2012
  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 "loader.h"
  25. #include "paging.h"
  26. //
  27. // ---------------------------------------------------------------- Definitions
  28. //
  29. //
  30. // ------------------------------------------------------ Data Type Definitions
  31. //
  32. /*++
  33. Structure Description:
  34. This structure stores information about an opened file in the boot
  35. environment.
  36. Members:
  37. FileName - Stores a pointer to the name of the file.
  38. FileNameSize - Stores the size of the file name string including the null
  39. terminator.
  40. LoadedFileBuffer - Stores a pointer to the buffer containing the file.
  41. FileSize - Stores the size of the loaded file, in bytes.
  42. --*/
  43. typedef struct _BOOT_FILE_HANDLE {
  44. PSTR FileName;
  45. ULONG FileNameSize;
  46. PVOID LoadedFileBuffer;
  47. UINTN FileSize;
  48. } BOOT_FILE_HANDLE, *PBOOT_FILE_HANDLE;
  49. /*++
  50. Structure Description:
  51. This structure stores information about an allocation of virtual address
  52. space by the boot environment.
  53. Members:
  54. PhysicalAddress - Stores the physical address of the memory backing the
  55. allocation.
  56. VirtualAddress - Stores the virtual address of the allocation.
  57. --*/
  58. typedef struct _BOOT_ADDRESS_SPACE_ALLOCATION {
  59. PHYSICAL_ADDRESS PhysicalAddress;
  60. PVOID VirtualAddress;
  61. } BOOT_ADDRESS_SPACE_ALLOCATION, *PBOOT_ADDRESS_SPACE_ALLOCATION;
  62. //
  63. // ----------------------------------------------- Internal Function Prototypes
  64. //
  65. PVOID
  66. BopImAllocateMemory (
  67. ULONG Size,
  68. ULONG Tag
  69. );
  70. VOID
  71. BopImFreeMemory (
  72. PVOID Allocation
  73. );
  74. KSTATUS
  75. BopImOpenFile (
  76. PVOID SystemContext,
  77. PCSTR BinaryName,
  78. PIMAGE_FILE_INFORMATION File
  79. );
  80. VOID
  81. BopImCloseFile (
  82. PIMAGE_FILE_INFORMATION File
  83. );
  84. KSTATUS
  85. BopImLoadFile (
  86. PIMAGE_FILE_INFORMATION File,
  87. PIMAGE_BUFFER Buffer
  88. );
  89. VOID
  90. BopImUnloadBuffer (
  91. PIMAGE_FILE_INFORMATION File,
  92. PIMAGE_BUFFER Buffer
  93. );
  94. KSTATUS
  95. BopImAllocateAddressSpace (
  96. PLOADED_IMAGE Image
  97. );
  98. VOID
  99. BopImFreeAddressSpace (
  100. PLOADED_IMAGE Image
  101. );
  102. KSTATUS
  103. BopImMapImageSegment (
  104. HANDLE AddressSpaceHandle,
  105. PVOID AddressSpaceAllocation,
  106. PIMAGE_FILE_INFORMATION File,
  107. ULONGLONG FileOffset,
  108. PIMAGE_SEGMENT Segment,
  109. PIMAGE_SEGMENT PreviousSegment
  110. );
  111. VOID
  112. BopImUnmapImageSegment (
  113. HANDLE AddressSpaceHandle,
  114. PIMAGE_SEGMENT Segment
  115. );
  116. KSTATUS
  117. BopImNotifyImageLoad (
  118. PLOADED_IMAGE Image
  119. );
  120. VOID
  121. BopImNotifyImageUnload (
  122. PLOADED_IMAGE Image
  123. );
  124. VOID
  125. BopImInvalidateInstructionCacheRegion (
  126. PVOID Address,
  127. ULONG Size
  128. );
  129. PSTR
  130. BopImGetEnvironmentVariable (
  131. PSTR Variable
  132. );
  133. KSTATUS
  134. BopImFinalizeSegments (
  135. HANDLE AddressSpaceHandle,
  136. PIMAGE_SEGMENT Segments,
  137. UINTN SegmentCount
  138. );
  139. //
  140. // -------------------------------------------------------------------- Globals
  141. //
  142. //
  143. // Store a pointer to the boot device.
  144. //
  145. PBOOT_VOLUME BoBootDevice;
  146. //
  147. // Store the IDs of the directories to try when opening an image file.
  148. //
  149. FILE_ID BoDriversDirectoryId;
  150. FILE_ID BoSystemDirectoryId;
  151. //
  152. // Define the image library function table.
  153. //
  154. IM_IMPORT_TABLE BoImageFunctionTable = {
  155. BopImAllocateMemory,
  156. BopImFreeMemory,
  157. BopImOpenFile,
  158. BopImCloseFile,
  159. BopImLoadFile,
  160. NULL,
  161. BopImUnloadBuffer,
  162. BopImAllocateAddressSpace,
  163. BopImFreeAddressSpace,
  164. BopImMapImageSegment,
  165. BopImUnmapImageSegment,
  166. BopImNotifyImageLoad,
  167. BopImNotifyImageUnload,
  168. BopImInvalidateInstructionCacheRegion,
  169. BopImGetEnvironmentVariable,
  170. BopImFinalizeSegments,
  171. NULL
  172. };
  173. //
  174. // ------------------------------------------------------------------ Functions
  175. //
  176. KSTATUS
  177. BoInitializeImageSupport (
  178. PBOOT_VOLUME BootDevice,
  179. PBOOT_ENTRY BootEntry
  180. )
  181. /*++
  182. Routine Description:
  183. This routine initializes the image library for use in the boot
  184. environment.
  185. Arguments:
  186. BootDevice - Supplies a pointer to the boot volume token, used for loading
  187. images from disk.
  188. BootEntry - Supplies a pointer to the boot entry being launched.
  189. Return Value:
  190. Status code.
  191. --*/
  192. {
  193. PSTR DriversDirectoryPath;
  194. FILE_PROPERTIES Properties;
  195. KSTATUS Status;
  196. PCSTR SystemRootPath;
  197. INITIALIZE_LIST_HEAD(&BoLoadedImageList);
  198. //
  199. // Save the boot volume.
  200. //
  201. BoBootDevice = BootDevice;
  202. //
  203. // Open up the system root.
  204. //
  205. SystemRootPath = DEFAULT_SYSTEM_ROOT_PATH;
  206. if (BootEntry != NULL) {
  207. SystemRootPath = BootEntry->SystemPath;
  208. }
  209. Status = BoLookupPath(BootDevice, NULL, SystemRootPath, &Properties);
  210. if (!KSUCCESS(Status)) {
  211. goto InitializeImageSupportEnd;
  212. }
  213. BoSystemDirectoryId = Properties.FileId;
  214. //
  215. // Open up the drivers directory.
  216. //
  217. DriversDirectoryPath = DEFAULT_DRIVERS_DIRECTORY_PATH;
  218. Status = BoLookupPath(BootDevice,
  219. &BoSystemDirectoryId,
  220. DriversDirectoryPath,
  221. &Properties);
  222. if (!KSUCCESS(Status)) {
  223. goto InitializeImageSupportEnd;
  224. }
  225. BoDriversDirectoryId = Properties.FileId;
  226. Status = ImInitialize(&BoImageFunctionTable);
  227. if (!KSUCCESS(Status)) {
  228. goto InitializeImageSupportEnd;
  229. }
  230. Status = STATUS_SUCCESS;
  231. InitializeImageSupportEnd:
  232. return Status;
  233. }
  234. //
  235. // --------------------------------------------------------- Internal Functions
  236. //
  237. PVOID
  238. BopImAllocateMemory (
  239. ULONG Size,
  240. ULONG Tag
  241. )
  242. /*++
  243. Routine Description:
  244. This routine allocates memory from the boot environment for the image
  245. library.
  246. Arguments:
  247. Size - Supplies the number of bytes required for the memory allocation.
  248. Tag - Supplies a 32-bit ASCII identifier used to tag the memroy allocation.
  249. Return Value:
  250. Returns a pointer to the memory allocation on success.
  251. NULL on failure.
  252. --*/
  253. {
  254. return BoAllocateMemory(Size);
  255. }
  256. VOID
  257. BopImFreeMemory (
  258. PVOID Allocation
  259. )
  260. /*++
  261. Routine Description:
  262. This routine frees memory to the boot environment allocated by the image
  263. library.
  264. Arguments:
  265. Allocation - Supplies a pointer the allocation to free.
  266. Return Value:
  267. None.
  268. --*/
  269. {
  270. BoFreeMemory(Allocation);
  271. return;
  272. }
  273. KSTATUS
  274. BopImOpenFile (
  275. PVOID SystemContext,
  276. PCSTR BinaryName,
  277. PIMAGE_FILE_INFORMATION File
  278. )
  279. /*++
  280. Routine Description:
  281. This routine opens a file.
  282. Arguments:
  283. SystemContext - Supplies the context pointer passed to the load executable
  284. function.
  285. BinaryName - Supplies the name of the executable image to open.
  286. File - Supplies a pointer where the information for the file including its
  287. open handle will be returned.
  288. Return Value:
  289. Status code.
  290. --*/
  291. {
  292. PBOOT_FILE_HANDLE BootFileHandle;
  293. ULONGLONG LocalFileSize;
  294. FILE_PROPERTIES Properties;
  295. KSTATUS Status;
  296. BootFileHandle = BoAllocateMemory(sizeof(BOOT_FILE_HANDLE));
  297. if (BootFileHandle == NULL) {
  298. Status = STATUS_INSUFFICIENT_RESOURCES;
  299. goto OpenFileEnd;
  300. }
  301. RtlZeroMemory(BootFileHandle, sizeof(BOOT_FILE_HANDLE));
  302. BootFileHandle->FileNameSize = RtlStringLength(BinaryName) + 1;
  303. BootFileHandle->FileName = BoAllocateMemory(BootFileHandle->FileNameSize);
  304. if (BootFileHandle->FileName == NULL) {
  305. Status = STATUS_INSUFFICIENT_RESOURCES;
  306. goto OpenFileEnd;
  307. }
  308. RtlCopyMemory(BootFileHandle->FileName,
  309. BinaryName,
  310. BootFileHandle->FileNameSize);
  311. //
  312. // Open the file enough to make sure it's there, but don't actually load
  313. // it just now.
  314. //
  315. Status = BoLookupPath(BoBootDevice,
  316. &BoSystemDirectoryId,
  317. BootFileHandle->FileName,
  318. &Properties);
  319. if (Status == STATUS_PATH_NOT_FOUND) {
  320. Status = BoLookupPath(BoBootDevice,
  321. &BoDriversDirectoryId,
  322. BootFileHandle->FileName,
  323. &Properties);
  324. }
  325. if (!KSUCCESS(Status)) {
  326. goto OpenFileEnd;
  327. }
  328. if (Properties.Type != IoObjectRegularFile) {
  329. Status = STATUS_FILE_IS_DIRECTORY;
  330. goto OpenFileEnd;
  331. }
  332. LocalFileSize = Properties.Size;
  333. if ((UINTN)LocalFileSize != LocalFileSize) {
  334. Status = STATUS_FILE_CORRUPT;
  335. goto OpenFileEnd;
  336. }
  337. BootFileHandle->FileSize = (UINTN)LocalFileSize;
  338. File->Size = LocalFileSize;
  339. File->ModificationDate = Properties.ModifiedTime.Seconds;
  340. File->DeviceId = 0;
  341. File->FileId = 0;
  342. OpenFileEnd:
  343. if (!KSUCCESS(Status)) {
  344. if (BootFileHandle != NULL) {
  345. if (BootFileHandle->FileName != NULL) {
  346. BoFreeMemory(BootFileHandle->FileName);
  347. }
  348. BoFreeMemory(BootFileHandle);
  349. BootFileHandle = INVALID_HANDLE;
  350. }
  351. }
  352. File->Handle = BootFileHandle;
  353. return Status;
  354. }
  355. VOID
  356. BopImCloseFile (
  357. PIMAGE_FILE_INFORMATION File
  358. )
  359. /*++
  360. Routine Description:
  361. This routine closes an open file, invalidating any memory mappings to it.
  362. Arguments:
  363. File - Supplies a pointer to the file information.
  364. Return Value:
  365. None.
  366. --*/
  367. {
  368. PBOOT_FILE_HANDLE BootFileHandle;
  369. BootFileHandle = (PBOOT_FILE_HANDLE)(File->Handle);
  370. ASSERT(BootFileHandle->LoadedFileBuffer == NULL);
  371. if (BootFileHandle->FileName != NULL) {
  372. BoFreeMemory(BootFileHandle->FileName);
  373. }
  374. BoFreeMemory(BootFileHandle);
  375. return;
  376. }
  377. KSTATUS
  378. BopImLoadFile (
  379. PIMAGE_FILE_INFORMATION File,
  380. PIMAGE_BUFFER Buffer
  381. )
  382. /*++
  383. Routine Description:
  384. This routine loads an entire file into memory so the image library can
  385. access it.
  386. Arguments:
  387. File - Supplies a pointer to the file information.
  388. Buffer - Supplies a pointer where the buffer will be returned on success.
  389. Return Value:
  390. Status code.
  391. --*/
  392. {
  393. PBOOT_FILE_HANDLE BootFileHandle;
  394. KSTATUS Status;
  395. BootFileHandle = (PBOOT_FILE_HANDLE)(File->Handle);
  396. if (BootFileHandle->LoadedFileBuffer == NULL) {
  397. Status = BoLoadFile(BoBootDevice,
  398. &BoSystemDirectoryId,
  399. BootFileHandle->FileName,
  400. &(BootFileHandle->LoadedFileBuffer),
  401. NULL,
  402. NULL);
  403. if (Status == STATUS_PATH_NOT_FOUND) {
  404. Status = BoLoadFile(BoBootDevice,
  405. &BoDriversDirectoryId,
  406. BootFileHandle->FileName,
  407. &(BootFileHandle->LoadedFileBuffer),
  408. NULL,
  409. NULL);
  410. }
  411. if (!KSUCCESS(Status)) {
  412. goto ImLoadFileEnd;
  413. }
  414. }
  415. Status = STATUS_SUCCESS;
  416. ImLoadFileEnd:
  417. if (KSUCCESS(Status)) {
  418. Buffer->Data = BootFileHandle->LoadedFileBuffer;
  419. Buffer->Size = BootFileHandle->FileSize;
  420. }
  421. return Status;
  422. }
  423. VOID
  424. BopImUnloadBuffer (
  425. PIMAGE_FILE_INFORMATION File,
  426. PIMAGE_BUFFER Buffer
  427. )
  428. /*++
  429. Routine Description:
  430. This routine unloads a file buffer created from either the load file or
  431. read file function, and frees the buffer.
  432. Arguments:
  433. File - Supplies a pointer to the file information.
  434. Buffer - Supplies the buffer returned by the load file function.
  435. Return Value:
  436. None.
  437. --*/
  438. {
  439. PBOOT_FILE_HANDLE BootFileHandle;
  440. BootFileHandle = (PBOOT_FILE_HANDLE)(File->Handle);
  441. if (BootFileHandle->LoadedFileBuffer != NULL) {
  442. BoFreeMemory(BootFileHandle->LoadedFileBuffer);
  443. BootFileHandle->LoadedFileBuffer = NULL;
  444. }
  445. return;
  446. }
  447. KSTATUS
  448. BopImAllocateAddressSpace (
  449. PLOADED_IMAGE Image
  450. )
  451. /*++
  452. Routine Description:
  453. This routine allocates a section of virtual address space that an image
  454. can be mapped in to.
  455. Arguments:
  456. Image - Supplies a pointer to the image being loaded. The system context,
  457. size, file information, load flags, and preferred virtual address will
  458. be initialized. This routine should set up the loaded image buffer,
  459. loaded lowest address, and allocator handle if needed.
  460. Return Value:
  461. Status code.
  462. --*/
  463. {
  464. UINTN AlignedSize;
  465. PBOOT_ADDRESS_SPACE_ALLOCATION Allocation;
  466. UINTN PageOffset;
  467. UINTN PageSize;
  468. PVOID PreferredAddress;
  469. KSTATUS Status;
  470. Image->AllocatorHandle = INVALID_HANDLE;
  471. PreferredAddress = Image->PreferredLowestAddress;
  472. Allocation = BoAllocateMemory(sizeof(BOOT_ADDRESS_SPACE_ALLOCATION));
  473. if (Allocation == NULL) {
  474. Status = STATUS_INSUFFICIENT_RESOURCES;
  475. goto AllocateAddressSpaceEnd;
  476. }
  477. RtlZeroMemory(Allocation, sizeof(BOOT_ADDRESS_SPACE_ALLOCATION));
  478. PageSize = MmPageSize();
  479. PageOffset = (UINTN)PreferredAddress -
  480. ALIGN_RANGE_DOWN((UINTN)PreferredAddress, PageSize);
  481. AlignedSize = ALIGN_RANGE_UP(Image->Size + PageOffset, PageSize);
  482. //
  483. // Allocate pages from the boot environment. This memory backs a boot
  484. // driver image, so it is marked as loader permanent.
  485. //
  486. Status = FwAllocatePages(&(Allocation->PhysicalAddress),
  487. AlignedSize,
  488. PageSize,
  489. MemoryTypeLoaderPermanent);
  490. if (!KSUCCESS(Status)) {
  491. goto AllocateAddressSpaceEnd;
  492. }
  493. //
  494. // Map the memory to find out where it lands in virtual space.
  495. //
  496. Allocation->VirtualAddress = (PVOID)-1;
  497. Status = BoMapPhysicalAddress(&(Allocation->VirtualAddress),
  498. Allocation->PhysicalAddress,
  499. AlignedSize,
  500. MAP_FLAG_GLOBAL | MAP_FLAG_EXECUTE,
  501. MemoryTypeLoaderPermanent);
  502. if (!KSUCCESS(Status)) {
  503. goto AllocateAddressSpaceEnd;
  504. }
  505. AllocateAddressSpaceEnd:
  506. if (!KSUCCESS(Status)) {
  507. if (Allocation != NULL) {
  508. BoFreeMemory(Allocation);
  509. }
  510. } else {
  511. Image->AllocatorHandle = Allocation;
  512. Image->LoadedImageBuffer = (PVOID)(UINTN)Allocation->PhysicalAddress +
  513. PageOffset;
  514. Image->BaseDifference = Allocation->VirtualAddress + PageOffset -
  515. Image->PreferredLowestAddress;
  516. ASSERT((UINTN)Allocation->PhysicalAddress ==
  517. Allocation->PhysicalAddress);
  518. }
  519. return Status;
  520. }
  521. VOID
  522. BopImFreeAddressSpace (
  523. PLOADED_IMAGE Image
  524. )
  525. /*++
  526. Routine Description:
  527. This routine frees a section of virtual address space that was previously
  528. allocated.
  529. Arguments:
  530. Image - Supplies a pointer to the loaded (or partially loaded) image.
  531. Return Value:
  532. None.
  533. --*/
  534. {
  535. BoFreeMemory((PBOOT_ADDRESS_SPACE_ALLOCATION)(Image->AllocatorHandle));
  536. return;
  537. }
  538. KSTATUS
  539. BopImMapImageSegment (
  540. HANDLE AddressSpaceHandle,
  541. PVOID AddressSpaceAllocation,
  542. PIMAGE_FILE_INFORMATION File,
  543. ULONGLONG FileOffset,
  544. PIMAGE_SEGMENT Segment,
  545. PIMAGE_SEGMENT PreviousSegment
  546. )
  547. /*++
  548. Routine Description:
  549. This routine maps a section of the image to the given virtual address.
  550. Arguments:
  551. AddressSpaceHandle - Supplies the handle used to claim the overall region
  552. of address space.
  553. AddressSpaceAllocation - Supplies the original lowest virtual address for
  554. this image.
  555. File - Supplies an optional pointer to the file being mapped. If this
  556. parameter is NULL, then a zeroed memory section is being mapped.
  557. FileOffset - Supplies the offset from the beginning of the file to the
  558. beginning of the mapping, in bytes.
  559. Segment - Supplies a pointer to the segment information to map. On output,
  560. the virtual address will contain the actual mapped address, and the
  561. mapping handle may be set.
  562. PreviousSegment - Supplies an optional pointer to the previous segment
  563. that was mapped, so this routine can handle overlap appropriately. This
  564. routine can assume that segments are always mapped in increasing order.
  565. Return Value:
  566. Status code.
  567. --*/
  568. {
  569. PBOOT_FILE_HANDLE BootFileHandle;
  570. PVOID Destination;
  571. PBOOT_ADDRESS_SPACE_ALLOCATION Region;
  572. PVOID Source;
  573. Region = (PBOOT_ADDRESS_SPACE_ALLOCATION)AddressSpaceHandle;
  574. BootFileHandle = NULL;
  575. if (File != NULL) {
  576. BootFileHandle = (PBOOT_FILE_HANDLE)(File->Handle);
  577. }
  578. //
  579. // Copy to the physical address of the buffer plus the offset from the
  580. // base VA corresponding to that physical address.
  581. //
  582. ASSERT((UINTN)Region->PhysicalAddress == Region->PhysicalAddress);
  583. Destination = (PUCHAR)(UINTN)Region->PhysicalAddress +
  584. (UINTN)Segment->VirtualAddress -
  585. (UINTN)Region->VirtualAddress;
  586. //
  587. // Copy from the file buffer plus the given offset.
  588. //
  589. if (Segment->FileSize != 0) {
  590. ASSERT((BootFileHandle != NULL) &&
  591. (FileOffset + Segment->FileSize < BootFileHandle->FileSize));
  592. Source = (PUCHAR)(BootFileHandle->LoadedFileBuffer) + FileOffset;
  593. RtlCopyMemory(Destination, Source, Segment->FileSize);
  594. }
  595. if (Segment->MemorySize > Segment->FileSize) {
  596. RtlZeroMemory(Destination + Segment->FileSize,
  597. Segment->MemorySize - Segment->FileSize);
  598. }
  599. return STATUS_SUCCESS;
  600. }
  601. VOID
  602. BopImUnmapImageSegment (
  603. HANDLE AddressSpaceHandle,
  604. PIMAGE_SEGMENT Segment
  605. )
  606. /*++
  607. Routine Description:
  608. This routine maps unmaps an image segment.
  609. Arguments:
  610. AddressSpaceHandle - Supplies the handle used to claim the overall region
  611. of address space.
  612. Segment - Supplies a pointer to the segment information to unmap.
  613. Return Value:
  614. None.
  615. --*/
  616. {
  617. //
  618. // Unmapping is currently not implemented.
  619. //
  620. return;
  621. }
  622. KSTATUS
  623. BopImNotifyImageLoad (
  624. PLOADED_IMAGE Image
  625. )
  626. /*++
  627. Routine Description:
  628. This routine notifies the primary consumer of the image library that an
  629. image has been loaded.
  630. Arguments:
  631. Image - Supplies the image that has just been loaded. This image should
  632. be subsequently returned to the image library upon requests for loaded
  633. images with the given name.
  634. Return Value:
  635. Status code. Failing status codes veto the image load.
  636. --*/
  637. {
  638. ULONG AllocationSize;
  639. PSTR FileName;
  640. PDEBUG_MODULE LoadedModule;
  641. ULONG NameSize;
  642. KSTATUS Status;
  643. FileName = RtlStringFindCharacterRight(Image->FileName, '/', -1);
  644. if (FileName != NULL) {
  645. FileName += 1;
  646. } else {
  647. FileName = Image->FileName;
  648. }
  649. NameSize = RtlStringLength(FileName) + 1;
  650. AllocationSize = sizeof(DEBUG_MODULE) +
  651. ((NameSize - ANYSIZE_ARRAY) * sizeof(CHAR));
  652. LoadedModule = BoAllocateMemory(AllocationSize);
  653. if (LoadedModule == NULL) {
  654. Status = STATUS_INSUFFICIENT_RESOURCES;
  655. goto NotifyImageLoadEnd;
  656. }
  657. RtlZeroMemory(LoadedModule, AllocationSize);
  658. //
  659. // Initialize the loaded image parameters.
  660. //
  661. RtlStringCopy(LoadedModule->BinaryName, FileName, NameSize);
  662. LoadedModule->StructureSize = AllocationSize;
  663. LoadedModule->Timestamp = Image->File.ModificationDate;
  664. LoadedModule->LowestAddress = Image->PreferredLowestAddress +
  665. Image->BaseDifference;
  666. LoadedModule->Size = Image->Size;
  667. LoadedModule->EntryPoint = Image->EntryPoint;
  668. LoadedModule->Image = Image;
  669. Image->DebuggerModule = LoadedModule;
  670. KdReportModuleChange(LoadedModule, TRUE);
  671. Status = STATUS_SUCCESS;
  672. NotifyImageLoadEnd:
  673. if (!KSUCCESS(Status)) {
  674. if (LoadedModule != NULL) {
  675. BoFreeMemory(LoadedModule);
  676. }
  677. }
  678. return Status;
  679. }
  680. VOID
  681. BopImNotifyImageUnload (
  682. PLOADED_IMAGE Image
  683. )
  684. /*++
  685. Routine Description:
  686. This routine notifies the primary consumer of the image library that an
  687. image is about to be unloaded from memory. Once this routine returns, the
  688. image should not be referenced again as it will be freed.
  689. Arguments:
  690. Image - Supplies the image that is about to be unloaded.
  691. Return Value:
  692. None.
  693. --*/
  694. {
  695. PDEBUG_MODULE UnloadingModule;
  696. UnloadingModule = Image->DebuggerModule;
  697. Image->DebuggerModule = NULL;
  698. KdReportModuleChange(UnloadingModule, FALSE);
  699. BoFreeMemory(UnloadingModule);
  700. return;
  701. }
  702. VOID
  703. BopImInvalidateInstructionCacheRegion (
  704. PVOID Address,
  705. ULONG Size
  706. )
  707. /*++
  708. Routine Description:
  709. This routine invalidates an instruction cache region after code has been
  710. modified.
  711. Arguments:
  712. Address - Supplies the virtual address of the revion to invalidate.
  713. Size - Supplies the number of bytes to invalidate.
  714. Return Value:
  715. None.
  716. --*/
  717. {
  718. return;
  719. }
  720. PSTR
  721. BopImGetEnvironmentVariable (
  722. PSTR Variable
  723. )
  724. /*++
  725. Routine Description:
  726. This routine gets an environment variable value for the image library.
  727. Arguments:
  728. Variable - Supplies a pointer to a null terminated string containing the
  729. name of the variable to get.
  730. Return Value:
  731. Returns a pointer to the value of the environment variable. The image
  732. library will not free or modify this value.
  733. NULL if the given environment variable is not set.
  734. --*/
  735. {
  736. if (RtlAreStringsEqual(Variable, IMAGE_LOAD_LIBRARY_PATH_VARIABLE, -1) !=
  737. FALSE) {
  738. return ".";
  739. }
  740. return NULL;
  741. }
  742. KSTATUS
  743. BopImFinalizeSegments (
  744. HANDLE AddressSpaceHandle,
  745. PIMAGE_SEGMENT Segments,
  746. UINTN SegmentCount
  747. )
  748. /*++
  749. Routine Description:
  750. This routine applies the final memory protection attributes to the given
  751. segments. Read and execute bits can be applied at the time of mapping, but
  752. write protection may be applied here.
  753. Arguments:
  754. AddressSpaceHandle - Supplies the handle used to claim the overall region
  755. of address space.
  756. Segments - Supplies the final array of segments.
  757. SegmentCount - Supplies the number of segments.
  758. Return Value:
  759. Status code.
  760. --*/
  761. {
  762. UINTN End;
  763. ULONG MapFlags;
  764. UINTN PageSize;
  765. PIMAGE_SEGMENT Segment;
  766. UINTN SegmentIndex;
  767. UINTN Size;
  768. End = 0;
  769. PageSize = MmPageSize();
  770. for (SegmentIndex = 0; SegmentIndex < SegmentCount; SegmentIndex += 1) {
  771. Segment = &(Segments[SegmentIndex]);
  772. if (Segment->Type == ImageSegmentInvalid) {
  773. continue;
  774. }
  775. //
  776. // If the segment has no protection features, then there's nothing to
  777. // tighten up.
  778. //
  779. if ((Segment->Flags & IMAGE_MAP_FLAG_WRITE) != 0) {
  780. continue;
  781. }
  782. //
  783. // Compute the region whose protection should actually be changed.
  784. //
  785. End = (UINTN)(Segment->VirtualAddress) + Segment->MemorySize;
  786. End = ALIGN_RANGE_UP(End, PageSize);
  787. //
  788. // If the region has a real size, change its protection to read-only.
  789. //
  790. if (End > (UINTN)Segment->VirtualAddress) {
  791. Size = End - (UINTN)Segment->VirtualAddress;
  792. MapFlags = (MAP_FLAG_READ_ONLY << MAP_FLAG_PROTECT_SHIFT) |
  793. MAP_FLAG_READ_ONLY;
  794. BoChangeMappingAttributes(Segment->VirtualAddress, Size, MapFlags);
  795. }
  796. }
  797. return STATUS_SUCCESS;
  798. }