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.

764 lines
24 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. ntsetup.c
  5. Abstract:
  6. This module is the tail-end of the OS loader program. It performs all
  7. IA64 specific allocations and initialize. The OS loader invokes this
  8. this routine immediately before calling the loaded kernel image.
  9. Author:
  10. Allen Kay (akay) 19-May-1999
  11. based on MIPS version by John Vert (jvert) 20-Jun-1991
  12. Environment:
  13. Kernel mode
  14. Revision History:
  15. --*/
  16. #include "bldr.h"
  17. #include "stdio.h"
  18. #include "bootia64.h"
  19. #include "sal.h"
  20. #include "efi.h"
  21. #include "fpswa.h"
  22. #include "extern.h"
  23. #include <stdlib.h>
  24. //
  25. // Define macro to round structure size to next 16-byte boundary
  26. //
  27. #undef ROUND_UP
  28. #define ROUND_UP(x) ((sizeof(x) + 15) & (~15))
  29. #define MIN(_a,_b) (((_a) <= (_b)) ? (_a) : (_b))
  30. #define MAX(_a,_b) (((_a) <= (_b)) ? (_b) : (_a))
  31. //
  32. // Configuration Data Header
  33. // The following structure is copied from fw\mips\oli2msft.h
  34. // NOTE shielint - Somehow, this structure got incorporated into
  35. // firmware EISA configuration data. We need to know the size of the
  36. // header and remove it before writing eisa configuration data to
  37. // registry.
  38. //
  39. typedef struct _CONFIGURATION_DATA_HEADER {
  40. USHORT Version;
  41. USHORT Revision;
  42. PCHAR Type;
  43. PCHAR Vendor;
  44. PCHAR ProductName;
  45. PCHAR SerialNumber;
  46. } CONFIGURATION_DATA_HEADER;
  47. #define CONFIGURATION_DATA_HEADER_SIZE sizeof(CONFIGURATION_DATA_HEADER)
  48. //
  49. // Global Definition: This structure value is setup in sumain.c
  50. //
  51. TR_INFO ItrInfo[8], DtrInfo[8];
  52. extern ULONGLONG MemoryMapKey;
  53. extern ULONG BlPlatformPropertiesEfiFlags;
  54. //
  55. // Internal function references
  56. //
  57. VOID
  58. BlQueryImplementationAndRevision (
  59. OUT PULONG ProcessorId,
  60. OUT PULONG FloatingId
  61. );
  62. VOID
  63. BlTrCleanUp (
  64. );
  65. VOID
  66. BlPostProcessLoadOptions(
  67. PCHAR szOsLoadOptions
  68. );
  69. VOID
  70. BlpRemapReserve (
  71. VOID
  72. );
  73. ARC_STATUS
  74. BlSetupForNt(
  75. IN PLOADER_PARAMETER_BLOCK BlLoaderBlock
  76. )
  77. /*++
  78. Routine Description:
  79. This function initializes the IA64 specific kernel data structures
  80. required by the NT system.
  81. Arguments:
  82. BlLoaderBlock - Supplies the address of the loader parameter block.
  83. Return Value:
  84. ESUCCESS is returned if the setup is successfully complete. Otherwise,
  85. an unsuccessful status is returned.
  86. --*/
  87. {
  88. ULONG KernelPage;
  89. ULONGLONG PrcbPage;
  90. ARC_STATUS Status;
  91. PHARDWARE_PTE Pde;
  92. PHARDWARE_PTE HalPT;
  93. ULONG HalPteOffset;
  94. PLIST_ENTRY NextMd;
  95. PMEMORY_ALLOCATION_DESCRIPTOR MemoryDescriptor;
  96. PKLDR_DATA_TABLE_ENTRY BiosDataTableEntry;
  97. EFI_MEMORY_DESCRIPTOR * MemoryMap = NULL;
  98. ULONGLONG MemoryMapSize = 0;
  99. ULONGLONG MapKey;
  100. ULONGLONG DescriptorSize;
  101. ULONG DescriptorVersion;
  102. ULONG LastDescriptor;
  103. EFI_STATUS EfiStatus;
  104. EFI_GUID FpswaId = EFI_INTEL_FPSWA;
  105. EFI_HANDLE FpswaImage;
  106. FPSWA_INTERFACE *FpswaInterface = NULL;
  107. ULONGLONG BufferSize;
  108. BOOLEAN FpswaFound = FALSE;
  109. //
  110. // Change LoaderReserve memory back to LoaderFirmwareTemporary.
  111. //
  112. BlpRemapReserve();
  113. //
  114. // Allocate DPC stack pages for the boot processor.
  115. //
  116. Status = BlAllocateDescriptor(LoaderStartupDpcStack,
  117. 0,
  118. (KERNEL_BSTORE_SIZE + KERNEL_STACK_SIZE) >> PAGE_SHIFT,
  119. &KernelPage);
  120. if (Status != ESUCCESS) {
  121. return(Status);
  122. }
  123. BlLoaderBlock->u.Ia64.InterruptStack =
  124. (KSEG0_BASE | (KernelPage << PAGE_SHIFT)) + KERNEL_STACK_SIZE;
  125. //
  126. // Allocate kernel stack pages for the boot processor idle thread.
  127. //
  128. Status = BlAllocateDescriptor(LoaderStartupKernelStack,
  129. 0,
  130. (KERNEL_BSTORE_SIZE + KERNEL_STACK_SIZE) >> PAGE_SHIFT,
  131. &KernelPage);
  132. if (Status != ESUCCESS) {
  133. return(Status);
  134. }
  135. BlLoaderBlock->KernelStack =
  136. (KSEG0_BASE | (KernelPage << PAGE_SHIFT)) + KERNEL_STACK_SIZE;
  137. //
  138. // Allocate panic stack pages for the boot processor.
  139. //
  140. Status = BlAllocateDescriptor(LoaderStartupPanicStack,
  141. 0,
  142. (KERNEL_BSTORE_SIZE + KERNEL_STACK_SIZE) >> PAGE_SHIFT,
  143. &KernelPage);
  144. if (Status != ESUCCESS) {
  145. return(Status);
  146. }
  147. BlLoaderBlock->u.Ia64.PanicStack =
  148. (KSEG0_BASE | (KernelPage << PAGE_SHIFT)) + KERNEL_STACK_SIZE;
  149. //
  150. // Allocate and zero two pages for the PCR.
  151. //
  152. Status = BlAllocateDescriptor(LoaderStartupPcrPage,
  153. 0,
  154. 2,
  155. (PULONG) &BlLoaderBlock->u.Ia64.PcrPage);
  156. if (Status != ESUCCESS) {
  157. return(Status);
  158. }
  159. BlLoaderBlock->u.Ia64.PcrPage2 = BlLoaderBlock->u.Ia64.PcrPage + 1;
  160. RtlZeroMemory((PVOID)(KSEG0_BASE | (BlLoaderBlock->u.Ia64.PcrPage << PAGE_SHIFT)),
  161. PAGE_SIZE * 2);
  162. //
  163. // Allocate and zero four pages for the PDR and one page of memory for
  164. // the initial processor block, idle process, and idle thread structures.
  165. //
  166. Status = BlAllocateDescriptor(LoaderStartupPdrPage,
  167. 0,
  168. 3,
  169. (PULONG) &BlLoaderBlock->u.Ia64.PdrPage);
  170. if (Status != ESUCCESS) {
  171. return(Status);
  172. }
  173. RtlZeroMemory((PVOID)(KSEG0_BASE | (BlLoaderBlock->u.Ia64.PdrPage << PAGE_SHIFT)),
  174. PAGE_SIZE * 3);
  175. //
  176. // The storage for processor control block, the idle thread object, and
  177. // the idle thread process object are allocated from the third page of the
  178. // PDR allocation. The addresses of these data structures are computed
  179. // and stored in the loader parameter block and the memory is zeroed.
  180. //
  181. PrcbPage = BlLoaderBlock->u.Ia64.PdrPage + 1;
  182. if ((PAGE_SIZE * 2) >= (ROUND_UP(KPRCB) + ROUND_UP(EPROCESS) + ROUND_UP(ETHREAD))) {
  183. BlLoaderBlock->Prcb = KSEG0_BASE | (PrcbPage << PAGE_SHIFT);
  184. BlLoaderBlock->Process = BlLoaderBlock->Prcb + ROUND_UP(KPRCB);
  185. BlLoaderBlock->Thread = BlLoaderBlock->Process + ROUND_UP(EPROCESS);
  186. } else {
  187. return(ENOMEM);
  188. }
  189. Status = BlAllocateDescriptor(LoaderStartupPdrPage,
  190. 0,
  191. 1,
  192. &KernelPage);
  193. if (Status != ESUCCESS) {
  194. return(Status);
  195. }
  196. RtlZeroMemory((PVOID)(KSEG0_BASE | ((ULONGLONG) KernelPage << PAGE_SHIFT)),
  197. PAGE_SIZE * 1);
  198. //
  199. // Add the address of the PAL to the list of Firmware Symbols
  200. //
  201. Status = BlAllocateFirmwareTableEntry(
  202. "Efi-PAL",
  203. "\\System\\Firmware\\Efi-PAL",
  204. (PVOID) Pal.VirtualAddress,
  205. (ULONG) (Pal.PageSizeMemoryDescriptor << EFI_PAGE_SHIFT),
  206. &BiosDataTableEntry
  207. );
  208. if (Status != ESUCCESS) {
  209. BlPrint(TEXT("BlSetupForNt: Failed to Add EFI-PAL to Firmware Table.\n"));
  210. }
  211. //
  212. // Setup last two entries in the page directory table for HAL and
  213. // allocate page tables for them.
  214. //
  215. Pde = (PHARDWARE_PTE) (KSEG0_BASE|((ULONG_PTR)((BlLoaderBlock->u.Ia64.PdrPage) << PAGE_SHIFT)));
  216. Pde[(KIPCR & 0xffffffff) >> PDI_SHIFT].PageFrameNumber = (ULONG) KernelPage;
  217. Pde[(KIPCR & 0xffffffff) >> PDI_SHIFT].Valid = 1;
  218. Pde[(KIPCR & 0xffffffff) >> PDI_SHIFT].Cache = 0;
  219. Pde[(KIPCR & 0xffffffff) >> PDI_SHIFT].Accessed = 1;
  220. Pde[(KIPCR & 0xffffffff) >> PDI_SHIFT].Dirty = 1;
  221. Pde[(KIPCR & 0xffffffff) >> PDI_SHIFT].Execute = 1;
  222. Pde[(KIPCR & 0xffffffff) >> PDI_SHIFT].Write = 1;
  223. Pde[(KIPCR & 0xffffffff) >> PDI_SHIFT].CopyOnWrite = 1;
  224. //
  225. // 0xFFC00000 is the starting virtual address of Pde[2046].
  226. //
  227. HalPT = (PHARDWARE_PTE)(KSEG0_BASE|((ULONG_PTR) KernelPage << PAGE_SHIFT));
  228. HalPteOffset = GetPteOffset(KI_USER_SHARED_DATA & 0xffffffff);
  229. HalPT[HalPteOffset].PageFrameNumber = BlLoaderBlock->u.Ia64.PcrPage2;
  230. HalPT[HalPteOffset].Valid = 1;
  231. HalPT[HalPteOffset].Cache = 0;
  232. HalPT[HalPteOffset].Accessed = 1;
  233. HalPT[HalPteOffset].Dirty = 1;
  234. HalPT[HalPteOffset].Execute = 1;
  235. HalPT[HalPteOffset].Write = 1;
  236. HalPT[HalPteOffset].CopyOnWrite = 1;
  237. //
  238. // Fill in the rest of the loader block fields.
  239. //
  240. BlLoaderBlock->u.Ia64.AcpiRsdt = (ULONG_PTR) AcpiTable;
  241. BlLoaderBlock->u.Ia64.WakeupVector = WakeupVector;
  242. //
  243. // Fill the ItrInfo and DtrInfo fields
  244. //
  245. BlLoaderBlock->u.Ia64.EfiSystemTable = (ULONG_PTR) EfiST;
  246. RtlCopyMemory(&BlLoaderBlock->u.Ia64.Pal, &Pal, sizeof(TR_INFO));
  247. RtlCopyMemory(&BlLoaderBlock->u.Ia64.Sal, &Sal, sizeof(TR_INFO));
  248. RtlCopyMemory(&BlLoaderBlock->u.Ia64.SalGP, &SalGP, sizeof(TR_INFO));
  249. //
  250. // Fill the Os Loader base for initial OS TR purge.
  251. //
  252. {
  253. ULONGLONG address = OsLoaderBase & ~((1<<PS_4M)-1);
  254. BlLoaderBlock->u.Ia64.ItrInfo[ITR_LOADER_INDEX].Index = ITR_LOADER_INDEX;
  255. BlLoaderBlock->u.Ia64.ItrInfo[ITR_LOADER_INDEX].PageSize = PS_4M;
  256. BlLoaderBlock->u.Ia64.ItrInfo[ITR_LOADER_INDEX].VirtualAddress = address; // 1:1 mapping
  257. BlLoaderBlock->u.Ia64.ItrInfo[ITR_LOADER_INDEX].PhysicalAddress = address;
  258. BlLoaderBlock->u.Ia64.ItrInfo[ITR_LOADER_INDEX].Valid = TRUE;
  259. BlLoaderBlock->u.Ia64.DtrInfo[DTR_LOADER_INDEX].Index = DTR_LOADER_INDEX;
  260. BlLoaderBlock->u.Ia64.DtrInfo[DTR_LOADER_INDEX].PageSize = PS_4M;
  261. BlLoaderBlock->u.Ia64.DtrInfo[DTR_LOADER_INDEX].VirtualAddress = address; // 1:1 mapping
  262. BlLoaderBlock->u.Ia64.DtrInfo[DTR_LOADER_INDEX].PhysicalAddress = address;
  263. BlLoaderBlock->u.Ia64.DtrInfo[DTR_LOADER_INDEX].Valid = TRUE;
  264. }
  265. //
  266. // Fill in ItrInfo and DtrInfo for DRIVER0
  267. //
  268. BlLoaderBlock->u.Ia64.ItrInfo[ITR_DRIVER0_INDEX].Index = ITR_DRIVER0_INDEX;
  269. BlLoaderBlock->u.Ia64.ItrInfo[ITR_DRIVER0_INDEX].PageSize = PS_64M;
  270. BlLoaderBlock->u.Ia64.ItrInfo[ITR_DRIVER0_INDEX].VirtualAddress = KSEG0_BASE + BL_64M;
  271. BlLoaderBlock->u.Ia64.ItrInfo[ITR_DRIVER0_INDEX].PhysicalAddress = BL_64M;
  272. BlLoaderBlock->u.Ia64.ItrInfo[ITR_DRIVER0_INDEX].Valid = TRUE;
  273. BlLoaderBlock->u.Ia64.DtrInfo[DTR_DRIVER0_INDEX].Index = DTR_DRIVER0_INDEX;
  274. BlLoaderBlock->u.Ia64.DtrInfo[DTR_DRIVER0_INDEX].PageSize = PS_64M;
  275. BlLoaderBlock->u.Ia64.DtrInfo[DTR_DRIVER0_INDEX].VirtualAddress = KSEG0_BASE + BL_64M;
  276. BlLoaderBlock->u.Ia64.DtrInfo[DTR_DRIVER0_INDEX].PhysicalAddress = BL_64M;
  277. BlLoaderBlock->u.Ia64.DtrInfo[DTR_DRIVER0_INDEX].Valid = TRUE;
  278. //
  279. // Fill in ItrInfo and DtrInfo for DRIVER1
  280. //
  281. BlLoaderBlock->u.Ia64.ItrInfo[ITR_DRIVER1_INDEX].Index = ITR_DRIVER1_INDEX;
  282. BlLoaderBlock->u.Ia64.ItrInfo[ITR_DRIVER1_INDEX].PageSize = 0;
  283. BlLoaderBlock->u.Ia64.ItrInfo[ITR_DRIVER1_INDEX].VirtualAddress = 0;
  284. BlLoaderBlock->u.Ia64.ItrInfo[ITR_DRIVER1_INDEX].PhysicalAddress = 0;
  285. BlLoaderBlock->u.Ia64.ItrInfo[ITR_DRIVER1_INDEX].Valid = FALSE;
  286. BlLoaderBlock->u.Ia64.DtrInfo[DTR_DRIVER1_INDEX].Index = DTR_DRIVER1_INDEX;
  287. BlLoaderBlock->u.Ia64.DtrInfo[DTR_DRIVER1_INDEX].PageSize = 0;
  288. BlLoaderBlock->u.Ia64.DtrInfo[DTR_DRIVER1_INDEX].VirtualAddress = 0;
  289. BlLoaderBlock->u.Ia64.DtrInfo[DTR_DRIVER1_INDEX].PhysicalAddress = 0;
  290. BlLoaderBlock->u.Ia64.DtrInfo[DTR_DRIVER1_INDEX].Valid = FALSE;
  291. //
  292. // Fill in ItrInfo and DtrInfo for KERNEL
  293. //
  294. BlLoaderBlock->u.Ia64.ItrInfo[ITR_KERNEL_INDEX].Index = ITR_KERNEL_INDEX;
  295. BlLoaderBlock->u.Ia64.ItrInfo[ITR_KERNEL_INDEX].PageSize = PS_16M;
  296. BlLoaderBlock->u.Ia64.ItrInfo[ITR_KERNEL_INDEX].VirtualAddress = KSEG0_BASE + BL_48M;
  297. BlLoaderBlock->u.Ia64.ItrInfo[ITR_KERNEL_INDEX].PhysicalAddress = BL_48M;
  298. BlLoaderBlock->u.Ia64.ItrInfo[ITR_KERNEL_INDEX].Valid = TRUE;
  299. BlLoaderBlock->u.Ia64.DtrInfo[DTR_KERNEL_INDEX].Index = DTR_KERNEL_INDEX;
  300. BlLoaderBlock->u.Ia64.DtrInfo[DTR_KERNEL_INDEX].PageSize = PS_16M;
  301. BlLoaderBlock->u.Ia64.DtrInfo[DTR_KERNEL_INDEX].VirtualAddress = KSEG0_BASE + BL_48M;
  302. BlLoaderBlock->u.Ia64.DtrInfo[DTR_KERNEL_INDEX].PhysicalAddress = BL_48M;
  303. BlLoaderBlock->u.Ia64.DtrInfo[DTR_KERNEL_INDEX].Valid = TRUE;
  304. //
  305. // Fill in ItrInfo and DtrInfo for IO port
  306. //
  307. BlLoaderBlock->u.Ia64.DtrInfo[DTR_IO_PORT_INDEX].Index = DTR_IO_PORT_INDEX;
  308. BlLoaderBlock->u.Ia64.DtrInfo[DTR_IO_PORT_INDEX].PageSize = (ULONG) IoPortTrPs;
  309. BlLoaderBlock->u.Ia64.DtrInfo[DTR_IO_PORT_INDEX].VirtualAddress = VIRTUAL_IO_BASE;
  310. BlLoaderBlock->u.Ia64.DtrInfo[DTR_IO_PORT_INDEX].PhysicalAddress = IoPortPhysicalBase;
  311. BlLoaderBlock->u.Ia64.DtrInfo[DTR_IO_PORT_INDEX].Valid = TRUE;
  312. //
  313. // Flush all caches.
  314. //
  315. if (SYSTEM_BLOCK->FirmwareVectorLength > (sizeof(PVOID) * FlushAllCachesRoutine)) {
  316. ArcFlushAllCaches();
  317. }
  318. //
  319. // make memory map by TR's unavailable for kernel use.
  320. //
  321. NextMd = BlLoaderBlock->MemoryDescriptorListHead.Flink;
  322. while (NextMd != &BlLoaderBlock->MemoryDescriptorListHead) {
  323. MemoryDescriptor = CONTAINING_RECORD(NextMd,
  324. MEMORY_ALLOCATION_DESCRIPTOR,
  325. ListEntry);
  326. //
  327. // lock down pages we don't want the kernel to use.
  328. // NB. The only reason we need to lock down LoaderLoadedProgram because
  329. // there is static data in the loader image that the kernel uses.
  330. //
  331. if ((MemoryDescriptor->MemoryType == LoaderLoadedProgram) ||
  332. (MemoryDescriptor->MemoryType == LoaderOsloaderStack)) {
  333. MemoryDescriptor->MemoryType = LoaderFirmwarePermanent;
  334. }
  335. //
  336. // we've marked lots of memory as off limits to trick our allocator
  337. // into allocating memory at a specific location (which is necessary to
  338. // get hte kernel loaded at the right location, etc.). We do this by
  339. // marking the page type as LoaderSystemBlock. Now that we're done
  340. // allocating memory, we can restore all of the LoaderSystemBlock pages
  341. // to LoaderFree, so that the kernel can use this memory.
  342. //
  343. if (MemoryDescriptor->MemoryType == LoaderSystemBlock) {
  344. MemoryDescriptor->MemoryType = LoaderFree;
  345. }
  346. NextMd = MemoryDescriptor->ListEntry.Flink;
  347. }
  348. //
  349. // Go to physical mode before making EFI calls.
  350. //
  351. FlipToPhysical();
  352. //
  353. // Get processor configuration information
  354. //
  355. ReadProcessorConfigInfo( &BlLoaderBlock->u.Ia64.ProcessorConfigInfo );
  356. //
  357. // Get FP assist handle
  358. //
  359. BufferSize = sizeof(FpswaImage);
  360. EfiStatus = EfiBS->LocateHandle(ByProtocol,
  361. &FpswaId,
  362. NULL,
  363. &BufferSize,
  364. &FpswaImage
  365. );
  366. if (!EFI_ERROR(EfiStatus)) {
  367. //
  368. // Get FP assist protocol interface.
  369. //
  370. EfiStatus = EfiBS->HandleProtocol(FpswaImage, &FpswaId, &FpswaInterface);
  371. if (EFI_ERROR(EfiStatus)) {
  372. EfiPrint(L"BlSetupForNt: Could not get FP assist entry point\n");
  373. EfiBS->Exit(EfiImageHandle, EfiStatus, 0, 0);
  374. }
  375. FpswaFound = TRUE;
  376. }
  377. #if 1
  378. //
  379. // The following code must be fixed to handle ExitBootServices() failing
  380. // because the memory map has changed in between calls to GetMemoryMap and
  381. // the call to ExitBootServices(). We should also walk the EFI memory map
  382. // and correlate it against the MemoryDescriptorList to ensure that all of
  383. // the memory is properly accounted for.
  384. //
  385. //
  386. // reconstruct the arc memory descriptors,
  387. // this time do it for the rest of memory (we only did the
  388. // first 80 mb last time.)
  389. // then we need to insert the new descriptors into
  390. // the loaderblock's memory descriptor list.
  391. //
  392. EfiStatus = EfiBS->GetMemoryMap (
  393. &MemoryMapSize,
  394. MemoryMap,
  395. &MapKey,
  396. &DescriptorSize,
  397. (UINT32 *)&DescriptorVersion
  398. );
  399. if (EfiStatus != EFI_BUFFER_TOO_SMALL) {
  400. EfiPrint(L"BlSetupForNt: GetMemoryMap failed\r\n");
  401. EfiBS->Exit(EfiImageHandle, EfiStatus, 0, 0);
  402. }
  403. FlipToVirtual();
  404. Status = BlAllocateAlignedDescriptor(LoaderOsloaderHeap,
  405. 0,
  406. (ULONG) BYTES_TO_PAGES(MemoryMapSize),
  407. 0,
  408. &KernelPage);
  409. if (Status != ESUCCESS) {
  410. return(Status);
  411. }
  412. FlipToPhysical();
  413. //
  414. // We need a physical address for EFI, and the hal expects a physical
  415. // address as well.
  416. //
  417. MemoryMap = (PVOID)(ULONGLONG)((ULONGLONG)KernelPage << PAGE_SHIFT);
  418. EfiStatus = EfiBS->GetMemoryMap (
  419. &MemoryMapSize,
  420. MemoryMap,
  421. &MapKey,
  422. &DescriptorSize,
  423. (UINT32 *)&DescriptorVersion
  424. );
  425. if (EFI_ERROR(EfiStatus)) {
  426. EfiPrint(L"BlSetupForNt: GetMemoryMap failed\r\n");
  427. EfiBS->Exit(EfiImageHandle, EfiStatus, 0, 0);
  428. }
  429. //
  430. // Reuse the MDArray from before.
  431. // zero it out, so we don't coalesce with the last entry in
  432. // the previous MDArray.
  433. //
  434. RtlZeroMemory(MDArray, MaxDescriptors * sizeof(MEMORY_DESCRIPTOR));
  435. NumberDescriptors = 0;
  436. //
  437. // now we can construct the arc memory descriptors
  438. //
  439. ConstructArcMemoryDescriptors(MemoryMap,
  440. MDArray,
  441. MemoryMapSize,
  442. DescriptorSize,
  443. BL_DRIVER_RANGE_HIGH << PAGE_SHIFT, // start at 128 mb
  444. (ULONGLONG)-1 // don't have an upper boundary
  445. );
  446. #if DBG_MEMORY
  447. PrintArcMemoryDescriptorList(MDArray,
  448. NumberDescriptors
  449. );
  450. #endif
  451. FlipToVirtual();
  452. //
  453. // insert the newly constructed arc memory descriptors into
  454. // the loader block memory descriptor list
  455. //
  456. for (LastDescriptor = 0; LastDescriptor < NumberDescriptors; LastDescriptor++) {
  457. PMEMORY_ALLOCATION_DESCRIPTOR AllocationDescriptor;
  458. //
  459. // this could potentially be bad... we are allocated memory in between
  460. // our last memory map call and EFI exit boot services.
  461. //
  462. AllocationDescriptor =
  463. (PMEMORY_ALLOCATION_DESCRIPTOR)BlAllocateHeap(
  464. sizeof(MEMORY_ALLOCATION_DESCRIPTOR));
  465. if (AllocationDescriptor == NULL) {
  466. DBGTRACE( TEXT("Couldn't allocate heap for memory allocation descriptor\r\n"));
  467. return ENOMEM;
  468. }
  469. AllocationDescriptor->MemoryType =
  470. (TYPE_OF_MEMORY)MDArray[LastDescriptor].MemoryType;
  471. if (MDArray[LastDescriptor].MemoryType == MemoryFreeContiguous ||
  472. MDArray[LastDescriptor].MemoryType == LoaderFirmwareTemporary) {
  473. AllocationDescriptor->MemoryType = LoaderFree;
  474. }
  475. else if (MDArray[LastDescriptor].MemoryType == MemorySpecialMemory) {
  476. AllocationDescriptor->MemoryType = LoaderSpecialMemory;
  477. }
  478. AllocationDescriptor->BasePage = MDArray[LastDescriptor].BasePage;
  479. AllocationDescriptor->PageCount = MDArray[LastDescriptor].PageCount;
  480. BlInsertDescriptor(AllocationDescriptor);
  481. }
  482. //
  483. // Post process Load Options. If the user used the /maxmem
  484. // switch, we will need to truncate the MemoryDescriptorList
  485. // here since memory descriptors over 80GB were just added.
  486. //
  487. BlPostProcessLoadOptions(BlLoaderBlock->LoadOptions);
  488. #if DBG_MEMORY
  489. NextMd = BlLoaderBlock->MemoryDescriptorListHead.Flink;
  490. while (NextMd != &BlLoaderBlock->MemoryDescriptorListHead) {
  491. MemoryDescriptor = CONTAINING_RECORD(NextMd,
  492. MEMORY_ALLOCATION_DESCRIPTOR,
  493. ListEntry);
  494. wsprintf(DebugBuffer,
  495. L"basepage 0x%x pagecount 0x%x memorytype 0x%x\r\n",
  496. MemoryDescriptor->BasePage,
  497. MemoryDescriptor->PageCount,
  498. MemoryDescriptor->MemoryType
  499. );
  500. EfiPrint(DebugBuffer);
  501. NextMd = MemoryDescriptor->ListEntry.Flink;
  502. }
  503. wsprintf(DebugBuffer,
  504. L"MemoryMap 0x%x MemoryMapPage 0x%x\r\n",
  505. (ULONGLONG)MemoryMap,
  506. (ULONGLONG)MemoryMap >> PAGE_SHIFT
  507. );
  508. EfiPrint(DebugBuffer);
  509. #endif
  510. FlipToPhysical();
  511. //
  512. // Call EFI exit boot services. No more Efi calls to boot services
  513. // API's will be called beyond this point.
  514. //
  515. EfiStatus = EfiBS->ExitBootServices (
  516. EfiImageHandle,
  517. MapKey
  518. );
  519. if (EFI_ERROR(EfiStatus)) {
  520. EfiPrint(L"BlSetupForNt: ExitBootServices failed\r\n");
  521. EfiBS->Exit(EfiImageHandle, EfiStatus, 0, 0);
  522. }
  523. #endif
  524. //
  525. // Go back to virtual mode.
  526. //
  527. FlipToVirtual();
  528. //
  529. // Pass EFI memory descriptor Parameters to kernel through OS
  530. // loader block.
  531. //
  532. BlLoaderBlock->u.Ia64.EfiMemMapParam.MemoryMapSize = MemoryMapSize;
  533. BlLoaderBlock->u.Ia64.EfiMemMapParam.MemoryMap = (PUCHAR) MemoryMap;
  534. BlLoaderBlock->u.Ia64.EfiMemMapParam.MapKey = MapKey;
  535. BlLoaderBlock->u.Ia64.EfiMemMapParam.DescriptorSize = DescriptorSize;
  536. BlLoaderBlock->u.Ia64.EfiMemMapParam.DescriptorVersion = DescriptorVersion;
  537. BlLoaderBlock->u.Ia64.EfiMemMapParam.InitialPlatformPropertiesEfiFlags = BlPlatformPropertiesEfiFlags;
  538. if (FpswaFound) {
  539. BlLoaderBlock->u.Ia64.FpswaInterface = (ULONG_PTR) FpswaInterface;
  540. } else {
  541. BlLoaderBlock->u.Ia64.FpswaInterface = (ULONG_PTR) NULL;
  542. }
  543. //
  544. // Clean up TR's used by boot loader but not needed by ntoskrnl.
  545. //
  546. BlTrCleanUp();
  547. //
  548. // Flush the memory range where kernel, hal, and the drivers are
  549. // loaded into.
  550. //
  551. PioICacheFlush(KSEG0_BASE+BL_48M, BL_80M);
  552. return(ESUCCESS);
  553. }
  554. //
  555. // Convert remaining LoaderReserve to MemoryFirmwareTemporary.
  556. //
  557. //
  558. VOID
  559. BlpRemapReserve (
  560. VOID
  561. )
  562. {
  563. PMEMORY_ALLOCATION_DESCRIPTOR NextDescriptor;
  564. PLIST_ENTRY NextEntry;
  565. NextEntry = BlLoaderBlock->MemoryDescriptorListHead.Flink;
  566. while (NextEntry != &BlLoaderBlock->MemoryDescriptorListHead) {
  567. NextDescriptor = CONTAINING_RECORD(NextEntry,
  568. MEMORY_ALLOCATION_DESCRIPTOR,
  569. ListEntry);
  570. if ((NextDescriptor->MemoryType == LoaderReserve)) {
  571. NextDescriptor->MemoryType = LoaderFirmwareTemporary;
  572. }
  573. NextEntry = NextEntry->Flink;
  574. }
  575. return;
  576. }
  577. VOID
  578. BlPostProcessLoadOptions(
  579. PCHAR szOsLoadOptions
  580. )
  581. /*++
  582. Routine Description:
  583. The routine does any necessary work for the Load Options
  584. when setting up to transfer to the kernel.
  585. The memory descriptor list needs to be truncated when the user uses /maxmem
  586. Arguments:
  587. szOsLoadOptions - string with the user defined Load Options
  588. Return Value:
  589. none
  590. --*/
  591. {
  592. PCHAR p;
  593. ULONG MaxMemory;
  594. ULONG MaxPage;
  595. //
  596. // Process MAXMEM (Value is the highest physical
  597. // address to be used (in MB).
  598. //
  599. if( (p = strstr( szOsLoadOptions, "/MAXMEM=" )) != NULL ) {
  600. MaxMemory = atoi( p + sizeof("/MAXMEM=") - 1 );
  601. MaxPage = MaxMemory * ((1024 * 1024) / PAGE_SIZE) - 1;
  602. BlTruncateDescriptors(MaxPage);
  603. }
  604. }