Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

547 lines
12 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. peldr.c
  5. Abstract:
  6. This module implements the code to load a PE format image into memory
  7. and relocate it if necessary.
  8. Author:
  9. David N. Cutler (davec) 10-May-1991
  10. Environment:
  11. Kernel mode only.
  12. Revision History:
  13. --*/
  14. #include "bldr.h"
  15. #include "string.h"
  16. #include "ntimage.h"
  17. #if defined(_GAMBIT_)
  18. #include "ssc.h"
  19. #endif // defined(_GAMBIT_)
  20. //
  21. // Define image prefetch cache structure used in BlLoadImage. Images
  22. // are read as a whole into an allocated buffer and read requests in
  23. // BlLoadImage are satisfied by copying from this buffer if the
  24. // prefetch is successful. I chose to read the whole file in at once
  25. // to simplify code but it limits [although not in practice] the size of
  26. // files that can be prefetched this way, as opposed to prefetching chunks
  27. // of the file at a time.
  28. //
  29. typedef struct _IMAGE_PREFETCH_CACHE {
  30. ULONG FileId; // FileId that has been prefetched.
  31. LARGE_INTEGER Position; // Current position in the file.
  32. ULONG ValidDataLength; // Length of data that was prefetched.
  33. PUCHAR Data; // Pointer to cached data.
  34. } IMAGE_PREFETCH_CACHE, *PIMAGE_PREFETCH_CACHE;
  35. //
  36. // The next two defines are used in allocating memory for the image
  37. // cache to direct the allocator into using memory above 1MB and to make
  38. // the allocated memory 64KB aligned. They are in terms of number of pages.
  39. //
  40. #define BL_IMAGE_ABOVE_1MB (0x200000 >> PAGE_SHIFT)
  41. #define BL_IMAGE_64KB_ALIGNED (0x10000 >> PAGE_SHIFT)
  42. //
  43. // Define forward referenced prototypes.
  44. //
  45. USHORT
  46. ChkSum(
  47. ULONG PartialSum,
  48. PUSHORT Source,
  49. ULONG Length
  50. );
  51. ARC_STATUS
  52. BlImageInitCache(
  53. IN PIMAGE_PREFETCH_CACHE pCache,
  54. ULONG FileId
  55. );
  56. ARC_STATUS
  57. BlImageRead(
  58. IN PIMAGE_PREFETCH_CACHE pCache,
  59. IN ULONG FileId,
  60. OUT PVOID Buffer,
  61. IN ULONG Length,
  62. OUT PULONG pCount
  63. );
  64. ARC_STATUS
  65. BlImageSeek(
  66. IN PIMAGE_PREFETCH_CACHE pCache,
  67. IN ULONG FileId,
  68. IN PLARGE_INTEGER pOffset,
  69. IN SEEK_MODE SeekMode
  70. );
  71. VOID
  72. BlImageFreeCache(
  73. IN PIMAGE_PREFETCH_CACHE pCache,
  74. ULONG FileId
  75. );
  76. #if defined(_X86AMD64_)
  77. //
  78. // Build the 32-bit version of BlLoadImage
  79. //
  80. #undef IMAGE_DEFINITIONS
  81. #define IMAGE_DEFINITIONS 32
  82. #undef BlLoadImageEx
  83. #define BlLoadImageEx BlLoadImage32Ex
  84. #include <ximagdef.h>
  85. #include "amd64\amd64prv.h"
  86. #include "peldrt.c"
  87. //
  88. // Build the 64-bit version of BlLoadImage
  89. //
  90. #undef IMAGE_DEFINITIONS
  91. #define IMAGE_DEFINITIONS 64
  92. #undef BlLoadImageEx
  93. #define BlLoadImageEx BlLoadImage64Ex
  94. #include <ximagdef.h>
  95. #include "peldrt.c"
  96. #undef BlLoadImageEx
  97. #else // _X86AMD64_
  98. //
  99. // Non-x86 platforms build only the native version
  100. //
  101. #define IMAGE_NT_HEADER(x) RtlImageNtHeader(x)
  102. #include "peldrt.c"
  103. #endif // _X86AMD64_
  104. ARC_STATUS
  105. BlImageInitCache(
  106. IN PIMAGE_PREFETCH_CACHE pCache,
  107. ULONG FileId
  108. )
  109. /*++
  110. Routine Description:
  111. Attempt to allocate memory and prefetch a file. Setup pCache
  112. structure so it can be passed to BlImageRead/Seek to either copy
  113. from the cache if prefetch was successful or read from the disk as
  114. normal. The file must be opened read only and should not be closed
  115. or modified before calling BlImageFreeCache. The file position of
  116. FileId is reset to the beginning of the file on success, and is
  117. undefined on failure. pCache is always setup so it can be used in
  118. BlImage* I/O functions. If the file could not be prefetched, the
  119. cache's ValidDataLength will be set to 0 and the I/O functions
  120. will simply call the Bl* I/O functions [e.g. BlImageRead calls
  121. BlRead]. Note that the whole file is prefetched at once and this
  122. puts a limit on the size of files that can be prefetched via this
  123. cache since boot loader memory is limited. This limit is not hit
  124. in practice though.
  125. Arguments:
  126. pCache - Cache structure to setup.
  127. FileId - File to prefetch.
  128. Return Value:
  129. ESUCCESS if everything was successful .
  130. Appropriate ARC_STATUS if there was a problem.
  131. --*/
  132. {
  133. ARC_STATUS Status = ESUCCESS;
  134. FILE_INFORMATION FileInfo;
  135. ULONG FileSize;
  136. ULONG ActualBase = 0;
  137. PVOID CacheBufBase = NULL;
  138. ULONG ReadCount;
  139. LARGE_INTEGER SeekPosition;
  140. //
  141. // Initialize fields of the cache structure.
  142. //
  143. pCache->Data = 0;
  144. pCache->ValidDataLength = 0;
  145. pCache->Position.QuadPart = 0;
  146. pCache->FileId = FileId;
  147. //
  148. // Get file size.
  149. //
  150. Status = BlGetFileInformation(FileId, &FileInfo);
  151. if (Status != ESUCCESS) {
  152. goto cleanup;
  153. }
  154. //
  155. // Check if file is too big. File size is at
  156. // FileInfo.EndingAddress.
  157. //
  158. if (FileInfo.EndingAddress.HighPart != 0) {
  159. Status = E2BIG;
  160. goto cleanup;
  161. }
  162. FileSize = FileInfo.EndingAddress.LowPart;
  163. //
  164. // Allocate memory for the cache. In order to avoid fragmenting memory
  165. // terribly, temporarily change the allocation policy to HighestFit. This
  166. // causes the drivers to get loaded from the bottom up, while the cache
  167. // is always at the top of free memory.
  168. //
  169. Status = BlAllocateAlignedDescriptor(LoaderFirmwareTemporary,
  170. 0,
  171. (FileSize >> PAGE_SHIFT) + 1,
  172. BL_IMAGE_64KB_ALIGNED,
  173. &ActualBase);
  174. if (Status != ESUCCESS) {
  175. Status = ENOMEM;
  176. goto cleanup;
  177. }
  178. CacheBufBase = (PVOID) (KSEG0_BASE | (ActualBase << PAGE_SHIFT));
  179. //
  180. // Read the file into the prefetch buffer.
  181. //
  182. SeekPosition.QuadPart = 0;
  183. Status = BlSeek(FileId, &SeekPosition, SeekAbsolute);
  184. if (Status != ESUCCESS) {
  185. goto cleanup;
  186. }
  187. Status = BlRead(FileId, CacheBufBase, FileSize, &ReadCount);
  188. if (Status != ESUCCESS) {
  189. goto cleanup;
  190. }
  191. if (ReadCount != FileSize) {
  192. Status = EIO;
  193. goto cleanup;
  194. }
  195. //
  196. // Reset file position back to beginning.
  197. //
  198. SeekPosition.QuadPart = 0;
  199. Status = BlSeek(FileId, &SeekPosition, SeekAbsolute);
  200. if (Status != ESUCCESS) {
  201. goto cleanup;
  202. }
  203. //
  204. // The file was successfully prefetched.
  205. //
  206. pCache->Data = CacheBufBase;
  207. CacheBufBase = NULL;
  208. pCache->ValidDataLength = FileSize;
  209. cleanup:
  210. if ((CacheBufBase != NULL) && (ActualBase != 0)) {
  211. BlFreeDescriptor(ActualBase);
  212. }
  213. return Status;
  214. }
  215. ARC_STATUS
  216. BlImageRead(
  217. IN PIMAGE_PREFETCH_CACHE pCache,
  218. IN ULONG FileId,
  219. OUT PVOID Buffer,
  220. IN ULONG Length,
  221. OUT PULONG pCount
  222. )
  223. /*++
  224. Routine Description:
  225. A wrapper for BlRead. Checks to see if the request can be
  226. satisfied from pCache first. If not calls BlRead.
  227. Arguments:
  228. pCache - Prefetch Cache for FileId
  229. FileId, Buffer, Length, Count - BlRead parameters
  230. Return Value:
  231. Status that would be returned by BlRead.
  232. --*/
  233. {
  234. LONG AdjustedLength;
  235. //
  236. // If the cache buffer does not exist or the cached size is 0,
  237. // hand over the call to BlRead.
  238. //
  239. if (!pCache->Data || !pCache->ValidDataLength) {
  240. return BlRead(FileId, Buffer, Length, pCount);
  241. }
  242. //
  243. // Clear read bytes count.
  244. //
  245. *pCount = 0;
  246. //
  247. // Determine how many bytes we can copy from our current position till
  248. // EOF, if there is not Length bytes.
  249. //
  250. AdjustedLength = (LONG)pCache->ValidDataLength - (LONG)pCache->Position.LowPart;
  251. if (AdjustedLength < 0) {
  252. AdjustedLength = 0;
  253. }
  254. AdjustedLength = ((ULONG)AdjustedLength < Length) ? AdjustedLength : Length;
  255. //
  256. // Copy AdjustedLength bytes into target buffer and advance the file position.
  257. //
  258. RtlCopyMemory(Buffer, pCache->Data + pCache->Position.LowPart, AdjustedLength);
  259. pCache->Position.LowPart += AdjustedLength;
  260. //
  261. // Update number of bytes read.
  262. //
  263. *pCount = AdjustedLength;
  264. return ESUCCESS;
  265. }
  266. ARC_STATUS
  267. BlImageSeek(
  268. IN PIMAGE_PREFETCH_CACHE pCache,
  269. IN ULONG FileId,
  270. IN PLARGE_INTEGER pOffset,
  271. IN SEEK_MODE SeekMode
  272. )
  273. /*++
  274. Routine Description:
  275. A wrapper for BlSeek. Calls BlSeek and if successful, updates the
  276. position in the cache structure as well. We call BlSeek to update
  277. the file position as well because at any time the cache may be
  278. freed or invalidated and we have to be able to continue calling on
  279. Bl* I/O functions transparently.
  280. Arguments:
  281. pCache - Prefetch Cache for FileId.
  282. FileId, Offset, SeekMode - BlSeek parameters.
  283. Return Value:
  284. Status that would be returned by BlSeek.
  285. --*/
  286. {
  287. ARC_STATUS Status;
  288. //
  289. // Do not allow setting position to too big. We do not open such
  290. // files anyway and the boot loader file systems and other places
  291. // in the boot loader I/O system do not handle it.
  292. //
  293. if (pOffset->HighPart != 0) {
  294. return E2BIG;
  295. }
  296. //
  297. // Try to update file position.
  298. //
  299. Status = BlSeek(FileId, pOffset, SeekMode);
  300. if (Status != ESUCCESS) {
  301. return Status;
  302. }
  303. //
  304. // Update the position in cached buffer. We don't perform
  305. // checks since BlSeek accepted the new offset.
  306. //
  307. pCache->Position.QuadPart = pOffset->QuadPart;
  308. return Status;
  309. }
  310. VOID
  311. BlImageFreeCache(
  312. IN PIMAGE_PREFETCH_CACHE pCache,
  313. ULONG FileId
  314. )
  315. /*++
  316. Routine Description:
  317. Free the memory allocated for the prefetch cache for FileId in
  318. pCache. Sets ValidDataLength to 0 to stop caching.
  319. Arguments:
  320. pCache - Cache structure to setup
  321. FileId - File that was opened read-only to be cached.
  322. Return Value:
  323. None.
  324. --*/
  325. {
  326. ULONG DescBase;
  327. UNREFERENCED_PARAMETER( FileId );
  328. //
  329. // NOTE: ValidDataLength may be zero, but we still allocate at least
  330. // a page and we have to free that.
  331. //
  332. if (pCache->Data) {
  333. DescBase = (ULONG)((ULONG_PTR)pCache->Data & (~KSEG0_BASE));
  334. BlFreeDescriptor(DescBase >> PAGE_SHIFT);
  335. pCache->Data = NULL;
  336. }
  337. pCache->ValidDataLength = 0;
  338. return;
  339. }
  340. #if defined(_X86AMD64_)
  341. ARC_STATUS
  342. BlLoadImageEx(
  343. IN ULONG DeviceId,
  344. IN TYPE_OF_MEMORY MemoryType,
  345. IN PCHAR LoadFile,
  346. IN USHORT ImageType,
  347. IN OPTIONAL ULONG PreferredAlignment,
  348. IN OPTIONAL ULONG PreferredBasePage,
  349. OUT PVOID *ImageBase
  350. )
  351. /*++
  352. Routine Description:
  353. This routine attempts to load the specified file from the specified
  354. device.
  355. Arguments:
  356. DeviceId - Supplies the file table index of the device to load the
  357. specified image file from.
  358. MemoryType - Supplies the type of memory to to be assigned to the
  359. allocated memory descriptor.
  360. BootFile - Supplies a pointer to string descriptor for the name of
  361. the file to load.
  362. ImageType - Supplies the type of image that is expected.
  363. PreferredAlignment - If present, supplies the preferred image alignment.
  364. PreferredBasePage - If present, supplies the preferred base page which will
  365. override the image base address
  366. ImageBase - Supplies a pointer to a variable that receives the
  367. address of the image base.
  368. Return Value:
  369. ESUCCESS is returned if the specified image file is loaded
  370. successfully. Otherwise, an unsuccessful status is returned
  371. that describes the reason for failure.
  372. --*/
  373. {
  374. ARC_STATUS status;
  375. if (BlAmd64UseLongMode == FALSE) {
  376. status = BlLoadImage32Ex( DeviceId,
  377. MemoryType,
  378. LoadFile,
  379. ImageType,
  380. PreferredAlignment,
  381. PreferredBasePage,
  382. ImageBase );
  383. } else {
  384. status = BlLoadImage64Ex( DeviceId,
  385. MemoryType,
  386. LoadFile,
  387. ImageType,
  388. PreferredAlignment,
  389. PreferredBasePage,
  390. ImageBase );
  391. }
  392. return status;
  393. }
  394. #endif // _X86AMD64_