Source code of Windows XP (NT5)
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.

1490 lines
48 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Copyright (c) 1998 Intel Corporation
  4. Module Name:
  5. sumain.c
  6. Abstract:
  7. SuMain() sets up NT specific data structures for OsLoader.c. This
  8. is necessary since we don't have the ARC firmware to do the work
  9. for us. SuMain() is call by SuSetup() which is an assembly level
  10. routine that does IA64 specific setup.
  11. Author:
  12. Allen Kay (akay) 19-May-95
  13. --*/
  14. #include "bldr.h"
  15. #include "sudata.h"
  16. #include "sal.h"
  17. #include "efi.h"
  18. #include "efip.h"
  19. #include "bootia64.h"
  20. #include "smbios.h"
  21. extern EFI_SYSTEM_TABLE *EfiST;
  22. //
  23. // External functions
  24. //
  25. extern VOID NtProcessStartup();
  26. extern VOID SuFillExportTable();
  27. extern VOID CpuSpecificWork();
  28. extern EFI_STATUS
  29. GetSystemConfigurationTable(
  30. IN EFI_GUID *TableGuid,
  31. IN OUT VOID **Table
  32. );
  33. //
  34. // Define export entry table.
  35. //
  36. PVOID ExportEntryTable[ExMaximumRoutine];
  37. // M E M O R Y D E S C R I P T O R
  38. //
  39. // Memory Descriptor - each contiguous block of physical memory is
  40. // described by a Memory Descriptor. The descriptors are a table, with
  41. // the last entry having a BlockBase and BlockSize of zero. A pointer
  42. // to the beginning of this table is passed as part of the BootContext
  43. // Record to the OS Loader.
  44. //
  45. BOOT_CONTEXT BootContext;
  46. //
  47. // Global EFI data
  48. //
  49. #define EFI_ARRAY_SIZE 100
  50. #define EFI_PAGE_SIZE 4096
  51. #define EFI_PAGE_SHIFT 12
  52. #define MEM_4K 0x1000
  53. #define MEM_8K 0x2000
  54. #define MEM_16K 0x4000
  55. #define MEM_64K 0x10000
  56. #define MEM_256K 0x40000
  57. #define MEM_1M 0x100000
  58. #define MEM_4M 0x400000
  59. #define MEM_16M 0x1000000
  60. #define MEM_64M 0x4000000
  61. #define MEM_256M 0x10000000
  62. EFI_HANDLE EfiImageHandle;
  63. EFI_SYSTEM_TABLE *EfiST;
  64. EFI_BOOT_SERVICES *EfiBS;
  65. EFI_RUNTIME_SERVICES *EfiRS;
  66. PSST_HEADER SalSystemTable;
  67. PVOID AcpiTable;
  68. PVOID SMBiosTable;
  69. //
  70. // contains the memory map key so we can compare the consistency of the memory map
  71. // at loader entry time to loader exit time.
  72. //
  73. ULONGLONG MemoryMapKey;
  74. //
  75. // EFI GUID defines
  76. //
  77. EFI_GUID EfiLoadedImageProtocol = LOADED_IMAGE_PROTOCOL;
  78. EFI_GUID EfiDevicePathProtocol = DEVICE_PATH_PROTOCOL;
  79. EFI_GUID EfiDeviceIoProtocol = DEVICE_IO_PROTOCOL;
  80. EFI_GUID EfiBlockIoProtocol = BLOCK_IO_PROTOCOL;
  81. EFI_GUID EfiDiskIoProtocol = DISK_IO_PROTOCOL;
  82. EFI_GUID EfiFilesystemProtocol = SIMPLE_FILE_SYSTEM_PROTOCOL;
  83. EFI_GUID AcpiTable_Guid = ACPI_TABLE_GUID;
  84. EFI_GUID SmbiosTableGuid = SMBIOS_TABLE_GUID;
  85. EFI_GUID SalSystemTableGuid = SAL_SYSTEM_TABLE_GUID;
  86. //
  87. // PAL, SAL, and IO port space data
  88. //
  89. ULONGLONG PalProcVirtual;
  90. ULONGLONG PalProcPhysical;
  91. ULONGLONG PalPhysicalBase = 0;
  92. ULONGLONG PalTrPs;
  93. ULONGLONG IoPortPhysicalBase;
  94. ULONGLONG IoPortTrPs;
  95. //
  96. // Function Prototypes
  97. //
  98. VOID
  99. GetPalProcEntryPoint(
  100. IN PSST_HEADER SalSystemTable
  101. );
  102. ULONG
  103. GetDevPathSize(
  104. IN EFI_DEVICE_PATH *DevPath
  105. );
  106. VOID
  107. ConstructMemoryDescriptors(
  108. VOID
  109. );
  110. MEMORY_TYPE
  111. EfiToArcType (
  112. UINT32 Type
  113. );
  114. VOID
  115. AdjustMemoryDescriptorSizes(
  116. VOID
  117. );
  118. #if DBG
  119. #define DBG_TRACE(_X) EfiST->ConOut->OutputString(EfiST->ConOut, (_X))
  120. #else
  121. #define DBG_TRACE(_X)
  122. #endif
  123. #ifdef FORCE_CD_BOOT
  124. EFI_HANDLE
  125. GetCd(
  126. );
  127. EFI_HANDLE
  128. GetCdTest(
  129. VOID
  130. );
  131. #endif // for FORCE_CD_BOOT
  132. VOID
  133. SuMain(
  134. IN EFI_HANDLE ImageHandle,
  135. IN EFI_SYSTEM_TABLE *SystemTable
  136. )
  137. /*++
  138. Routine Description:
  139. Main entrypoint of the SU module. Control is passed from the boot
  140. sector to startup.asm which does some run-time fixups on the stack
  141. and data segments and then passes control here.
  142. Arguments:
  143. None
  144. Returns:
  145. Does not return. Passes control to the OS loader
  146. --*/
  147. {
  148. PIMAGE_DOS_HEADER DosHeader;
  149. PIMAGE_NT_HEADERS NtHeader;
  150. PIMAGE_FILE_HEADER FileHeader;
  151. PIMAGE_OPTIONAL_HEADER OptionalHeader;
  152. PIMAGE_SECTION_HEADER SectionHeader;
  153. ULONG NumberOfSections;
  154. BOOLEAN ResourceFound = FALSE;
  155. ULONGLONG Source,Destination;
  156. ULONGLONG VirtualSize;
  157. ULONGLONG SizeOfRawData;
  158. USHORT Section;
  159. EFI_GUID EfiLoadedImageProtocol = LOADED_IMAGE_PROTOCOL;
  160. EFI_HANDLE EfiHandleArray[EFI_ARRAY_SIZE];
  161. ULONG EfiHandleArraySize = EFI_ARRAY_SIZE * sizeof(EFI_HANDLE);
  162. EFI_DEVICE_PATH *EfiDevicePath;
  163. EFI_LOADED_IMAGE *EfiImageInfo;
  164. EFI_HANDLE DeviceHandle;
  165. EFI_STATUS Status;
  166. EFI_DEVICE_PATH *DevicePath, *TestPath;
  167. EFI_DEVICE_PATH_ALIGNED TestPathAligned;
  168. HARDDRIVE_DEVICE_PATH *HdDevicePath;
  169. ACPI_HID_DEVICE_PATH *AcpiDevicePath;
  170. ATAPI_DEVICE_PATH *AtapiDevicePath;
  171. SCSI_DEVICE_PATH *ScsiDevicePath;
  172. IPv4_DEVICE_PATH *IpV4DevicePath;
  173. IPv6_DEVICE_PATH *IpV6DevicePath;
  174. UNKNOWN_DEVICE_VENDOR_DEVICE_PATH *UnknownDevicePath;
  175. UCHAR MemoryMap[EFI_PAGE_SIZE];
  176. ULONGLONG MemoryMapSize = EFI_PAGE_SIZE;
  177. EFI_MEMORY_DESCRIPTOR *EfiMd;
  178. ULONGLONG DescriptorSize;
  179. ULONG DescriptorVersion;
  180. ULONG i;
  181. ULONGLONG PalSize;
  182. ULONGLONG PalEnd;
  183. ULONGLONG IoPortSize;
  184. ULONGLONG MdPhysicalEnd;
  185. PBOOT_DEVICE_ATAPI BootDeviceAtapi;
  186. PBOOT_DEVICE_SCSI BootDeviceScsi;
  187. PBOOT_DEVICE_FLOPPY BootDeviceFloppy;
  188. PBOOT_DEVICE_IPv4 BootDeviceIpV4;
  189. PBOOT_DEVICE_IPv6 BootDeviceIpV6;
  190. PBOOT_DEVICE_UNKNOWN BootDeviceUnknown;
  191. PSMBIOS_EPS_HEADER SMBiosEPSHeader;
  192. PUCHAR SMBiosEPSPtr;
  193. UCHAR CheckSum;
  194. //
  195. // EFI global variables
  196. //
  197. EfiImageHandle = ImageHandle;
  198. EfiST = SystemTable;
  199. EfiBS = SystemTable->BootServices;
  200. EfiRS = SystemTable->RuntimeServices;
  201. DBG_TRACE(L"SuMain: entry\r\n");
  202. //
  203. // Get the SAL System Table
  204. //
  205. Status = GetSystemConfigurationTable(&SalSystemTableGuid, &SalSystemTable);
  206. if (EFI_ERROR(Status)) {
  207. EfiST->ConOut->OutputString(EfiST->ConOut,
  208. L"SuMain: HandleProtocol failed\n");
  209. EfiBS->Exit(EfiImageHandle, Status, 0, 0);
  210. }
  211. #if 0
  212. //
  213. // Get the MPS Table
  214. //
  215. Status = GetSystemConfigurationTable(&MpsTableGuid, &MpsTable);
  216. if (EFI_ERROR(Status)) {
  217. EfiST->ConOut->OutputString(EfiST->ConOut,
  218. L"SuMain: HandleProtocol failed\n");
  219. EfiBS->Exit(EfiImageHandle, Status, 0, 0);
  220. }
  221. #endif
  222. //
  223. // Get the ACPI Tables
  224. //
  225. //
  226. // Get the ACPI 2.0 Table, if present
  227. //
  228. //DbgPrint("Looking for ACPi 2.0\n");
  229. Status = GetSystemConfigurationTable(&AcpiTable_Guid, &AcpiTable);
  230. if (EFI_ERROR(Status)) {
  231. //DbgPrint("returned error\n");
  232. AcpiTable = NULL;
  233. }
  234. //DbgPrint("AcpiTable: %p\n", AcpiTable);
  235. if (!AcpiTable) {
  236. EfiST->ConOut->OutputString(EfiST->ConOut,
  237. L"SuMain: HandleProtocol failed\n");
  238. EfiBS->Exit(EfiImageHandle, Status, 0, 0);
  239. }
  240. //
  241. // Get the SMBIOS Table
  242. //
  243. Status = GetSystemConfigurationTable(&SmbiosTableGuid, &SMBiosTable);
  244. if (EFI_ERROR(Status)) {
  245. //DbgPrint("returned error\n");
  246. SMBiosTable = NULL;
  247. } else {
  248. //
  249. // Validate SMBIOS EPS Header
  250. //
  251. SMBiosEPSHeader = (PSMBIOS_EPS_HEADER)SMBiosTable;
  252. SMBiosEPSPtr = (PUCHAR)SMBiosTable;
  253. if ((*((PULONG)SMBiosEPSHeader->Signature) == SMBIOS_EPS_SIGNATURE) &&
  254. (SMBiosEPSHeader->Length >= sizeof(SMBIOS_EPS_HEADER)) &&
  255. (*((PULONG)SMBiosEPSHeader->Signature2) == DMI_EPS_SIGNATURE) &&
  256. (SMBiosEPSHeader->Signature2[4] == '_' ))
  257. {
  258. CheckSum = 0;
  259. for (i = 0; i < SMBiosEPSHeader->Length ; i++)
  260. {
  261. CheckSum += SMBiosEPSPtr[i];
  262. }
  263. if (CheckSum != 0)
  264. {
  265. DBG_TRACE(L"SMBios Table has bad checksum.....\n");
  266. SMBiosTable = NULL;
  267. } else {
  268. DBG_TRACE(L"SMBios Table has been validated.....\n");
  269. }
  270. } else {
  271. DBG_TRACE(L"SMBios Table is incorrectly formed.....\n");
  272. SMBiosTable = NULL;
  273. }
  274. }
  275. //
  276. // Get the image info for NTLDR
  277. //
  278. Status = EfiBS->HandleProtocol (
  279. ImageHandle,
  280. &EfiLoadedImageProtocol,
  281. &EfiImageInfo
  282. );
  283. if (EFI_ERROR(Status)) {
  284. EfiST->ConOut->OutputString(EfiST->ConOut,
  285. L"SuMain: HandleProtocol failed\n");
  286. EfiBS->Exit(EfiImageHandle, Status, 0, 0);
  287. }
  288. //
  289. // Get device path of the DeviceHandle associated with this image handle.
  290. //
  291. Status = EfiBS->HandleProtocol (
  292. EfiImageInfo->DeviceHandle,
  293. &EfiDevicePathProtocol,
  294. &DevicePath
  295. );
  296. if (EFI_ERROR(Status)) {
  297. EfiST->ConOut->OutputString(EfiST->ConOut,
  298. L"SuMain: HandleProtocol failed\r\n");
  299. EfiBS->Exit(EfiImageHandle, Status, 0, 0);
  300. }
  301. //
  302. // Get the MediaType and Partition information and save them in the
  303. // BootContext.
  304. //
  305. EfiAlignDp( &TestPathAligned,
  306. DevicePath,
  307. DevicePathNodeLength(DevicePath) );
  308. TestPath = (EFI_DEVICE_PATH *) &TestPathAligned;
  309. while (TestPath->Type != END_DEVICE_PATH_TYPE) {
  310. if (TestPath->Type == MESSAGING_DEVICE_PATH) {
  311. if (TestPath->SubType == MSG_ATAPI_DP) {
  312. AtapiDevicePath = (ATAPI_DEVICE_PATH *) TestPath;
  313. BootContext.BusType = BootBusAtapi;
  314. BootDeviceAtapi = (PBOOT_DEVICE_ATAPI) &(BootContext.BootDevice);
  315. BootDeviceAtapi->PrimarySecondary = AtapiDevicePath->PrimarySecondary;
  316. BootDeviceAtapi->SlaveMaster = AtapiDevicePath->SlaveMaster;
  317. BootDeviceAtapi->Lun = AtapiDevicePath->Lun;
  318. } else if (TestPath->SubType == MSG_SCSI_DP) {
  319. ScsiDevicePath = (SCSI_DEVICE_PATH *) TestPath;
  320. BootContext.BusType = BootBusScsi;
  321. BootDeviceScsi = (PBOOT_DEVICE_SCSI) &(BootContext.BootDevice);
  322. BootDeviceScsi->Pun = ScsiDevicePath->Pun;
  323. BootDeviceScsi->Lun = ScsiDevicePath->Lun;
  324. } else if (TestPath->SubType == MSG_MAC_ADDR_DP) {
  325. BootContext.MediaType = BootMediaTcpip;
  326. } else if (TestPath->SubType == MSG_IPv4_DP) {
  327. IpV4DevicePath = (IPv4_DEVICE_PATH *) TestPath;
  328. BootContext.MediaType = BootMediaTcpip;
  329. BootDeviceIpV4 = (PBOOT_DEVICE_IPv4) &(BootContext.BootDevice);
  330. BootDeviceIpV4->RemotePort = IpV4DevicePath->RemotePort;
  331. BootDeviceIpV4->LocalPort = IpV4DevicePath->LocalPort;
  332. RtlCopyMemory(&BootDeviceIpV4->Ip, &IpV4DevicePath->LocalIpAddress, sizeof(EFI_IPv4_ADDRESS));
  333. } else if (TestPath->SubType == MSG_IPv6_DP) {
  334. IpV6DevicePath = (IPv6_DEVICE_PATH *) TestPath;
  335. BootContext.MediaType = BootMediaTcpip;
  336. BootDeviceIpV6 = (PBOOT_DEVICE_IPv6) &(BootContext.BootDevice);
  337. BootDeviceIpV6->RemotePort = IpV6DevicePath->RemotePort;
  338. BootDeviceIpV6->LocalPort = IpV6DevicePath->LocalPort;
  339. #if 0
  340. BootDeviceIpV6->Ip = IpV6DevicePath->Ip;
  341. #endif
  342. }
  343. } else if (TestPath->Type == ACPI_DEVICE_PATH) {
  344. AcpiDevicePath = (ACPI_HID_DEVICE_PATH *) TestPath;
  345. if (AcpiDevicePath->HID == EISA_ID(PNP_EISA_ID_CONST, 0x0303)) {
  346. BootDeviceFloppy = (PBOOT_DEVICE_FLOPPY) &(BootContext.BootDevice);
  347. BootDeviceFloppy->DriveNumber = AcpiDevicePath->UID;
  348. }
  349. } else if (TestPath->Type == HARDWARE_DEVICE_PATH) {
  350. if (TestPath->SubType == HW_VENDOR_DP) {
  351. UnknownDevicePath = (UNKNOWN_DEVICE_VENDOR_DEVICE_PATH *) TestPath;
  352. BootDeviceUnknown = (PBOOT_DEVICE_UNKNOWN) &(BootContext.BootDevice);
  353. RtlCopyMemory( &(BootDeviceUnknown->Guid),
  354. &(UnknownDevicePath->DevicePath.Guid),
  355. sizeof(EFI_GUID));
  356. BootContext.BusType = BootBusVendor;
  357. BootDeviceUnknown->LegacyDriveLetter = UnknownDevicePath->LegacyDriveLetter;
  358. }
  359. } else if (TestPath->Type == MEDIA_DEVICE_PATH) {
  360. BootContext.MediaType = TestPath->SubType;
  361. if (TestPath->SubType == MEDIA_HARDDRIVE_DP) {
  362. HdDevicePath = (HARDDRIVE_DEVICE_PATH *) TestPath;
  363. BootContext.MediaType = BootMediaHardDisk;
  364. BootContext.PartitionNumber = (UCHAR) HdDevicePath->PartitionNumber;
  365. } else if (TestPath->SubType == MEDIA_CDROM_DP) {
  366. BootContext.MediaType = BootMediaCdrom;
  367. }
  368. }
  369. DevicePath = NextDevicePathNode(DevicePath);
  370. EfiAlignDp( &TestPathAligned,
  371. DevicePath,
  372. DevicePathNodeLength(DevicePath) );
  373. TestPath = (EFI_DEVICE_PATH *) &TestPathAligned;
  374. }
  375. #ifdef FORCE_CD_BOOT
  376. BootContext.MediaType = BootMediaCdrom;
  377. #endif
  378. //
  379. // Fill out the rest of BootContext fields
  380. //
  381. DosHeader = EfiImageInfo->ImageBase;
  382. NtHeader = (PIMAGE_NT_HEADERS) ((PUCHAR) DosHeader + DosHeader->e_lfanew);
  383. FileHeader = &(NtHeader->FileHeader);
  384. OptionalHeader = (PIMAGE_OPTIONAL_HEADER)
  385. ((PUCHAR)FileHeader + sizeof(IMAGE_FILE_HEADER));
  386. SectionHeader = (PIMAGE_SECTION_HEADER) ((PUCHAR)OptionalHeader +
  387. FileHeader->SizeOfOptionalHeader);
  388. BootContext.ExternalServicesTable = (PEXTERNAL_SERVICES_TABLE)
  389. &ExportEntryTable;
  390. BootContext.MachineType = MACHINE_TYPE_ISA;
  391. BootContext.OsLoaderBase = (ULONG_PTR)EfiImageInfo->ImageBase;
  392. BootContext.OsLoaderExports = (ULONG_PTR)EfiImageInfo->ImageBase +
  393. OptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
  394. //
  395. // Calculate the start address and the end address of OS loader.
  396. //
  397. BootContext.OsLoaderStart = (ULONG_PTR)EfiImageInfo->ImageBase +
  398. SectionHeader->VirtualAddress;
  399. BootContext.OsLoaderEnd = (ULONG_PTR)EfiImageInfo->ImageBase +
  400. SectionHeader->SizeOfRawData;
  401. for (Section=FileHeader->NumberOfSections ; Section-- ; SectionHeader++) {
  402. Destination = (ULONG_PTR)EfiImageInfo->ImageBase + SectionHeader->VirtualAddress;
  403. VirtualSize = SectionHeader->Misc.VirtualSize;
  404. SizeOfRawData = SectionHeader->SizeOfRawData;
  405. if (VirtualSize == 0) {
  406. VirtualSize = SizeOfRawData;
  407. }
  408. if (Destination < BootContext.OsLoaderStart) {
  409. BootContext.OsLoaderStart = Destination;
  410. }
  411. if (Destination+VirtualSize > BootContext.OsLoaderEnd) {
  412. BootContext.OsLoaderEnd = Destination+VirtualSize;
  413. }
  414. }
  415. //
  416. // Find .rsrc section
  417. //
  418. SectionHeader = (PIMAGE_SECTION_HEADER) ((PUCHAR)OptionalHeader +
  419. FileHeader->SizeOfOptionalHeader);
  420. NumberOfSections = FileHeader->NumberOfSections;
  421. while (NumberOfSections) {
  422. if (_stricmp(SectionHeader->Name, ".rsrc")==0) {
  423. BootContext.ResourceDirectory =
  424. (ULONGLONG) ((ULONG_PTR)EfiImageInfo->ImageBase + SectionHeader->VirtualAddress);
  425. BootContext.ResourceOffset = (ULONGLONG)((LONG)SectionHeader->VirtualAddress);
  426. ResourceFound = TRUE;
  427. }
  428. ++SectionHeader;
  429. --NumberOfSections;
  430. }
  431. if (ResourceFound == FALSE) {
  432. EfiST->ConOut->OutputString(EfiST->ConOut,
  433. L"SuMain: Resource section not found\n");
  434. EfiBS->Exit(EfiImageHandle, Status, 0, 0);
  435. }
  436. DBG_TRACE( L"SuMain: About to call NtProcessStartup\r\n");
  437. //
  438. // See if someone called us w/ a TFTP restart block.
  439. //
  440. if( EfiImageInfo->LoadOptionsSize == (sizeof(TFTP_RESTART_BLOCK)) ) {
  441. //
  442. // Likely. Make sure it's really a TFTP restart block and if so, go retrieve all
  443. // its contents.
  444. //
  445. if( EfiImageInfo->LoadOptions != NULL ) {
  446. extern TFTP_RESTART_BLOCK gTFTPRestartBlock;
  447. PTFTP_RESTART_BLOCK restartBlock = NULL;
  448. restartBlock = (PTFTP_RESTART_BLOCK)(EfiImageInfo->LoadOptions);
  449. RtlCopyMemory( &gTFTPRestartBlock,
  450. restartBlock,
  451. sizeof(TFTP_RESTART_BLOCK) );
  452. DBG_TRACE( L"SuMain: copied TFTP_RESTART_BLOCK into gTFTPRestartBlock\r\n");
  453. }
  454. }
  455. ConstructMemoryDescriptors( );
  456. GetPalProcEntryPoint( SalSystemTable );
  457. //
  458. // Applies CPU specific workarounds
  459. //
  460. CpuSpecificWork();
  461. SuFillExportTable( );
  462. NtProcessStartup( &BootContext );
  463. }
  464. VOID
  465. ConstructMemoryDescriptors(
  466. VOID
  467. )
  468. /*++
  469. Routine Description:
  470. Builds up memory descriptors for the OS loader. This routine queries EFI
  471. for it's memory map (a variable sized array of EFI_MEMORY_DESCRIPTOR's).
  472. It then allocates sufficient space for the MDArray global (a variable sized
  473. array of ARC-based MEMORY_DESCRIPTOR's.) The routine then maps the EFI
  474. memory map to the ARC memory map, carving out all of the conventional
  475. memory space for the EFI loader to help keep the memory map intact. We
  476. must leave behind some amount of memory for the EFI boot services to use,
  477. which we allocate as conventional memory in our map.
  478. Arguments:
  479. None
  480. Returns:
  481. Nothing. Fills in the MDArray global variable. If this routine encounters
  482. an error, it is treated as fatal and the program exits.
  483. --*/
  484. {
  485. EFI_STATUS Status;
  486. ULONGLONG MemoryMapSize = 0;
  487. EFI_MEMORY_DESCRIPTOR *EfiMd;
  488. ULONGLONG DescriptorSize;
  489. ULONG DescriptorVersion;
  490. ULONG i;
  491. ULONGLONG PalSize;
  492. ULONGLONG PalEnd;
  493. ULONGLONG IoPortSize;
  494. ULONGLONG MdPhysicalStart;
  495. ULONGLONG MdPhysicalEnd;
  496. ULONGLONG MdPhysicalSize;
  497. //
  498. // Get memory map info from EFI firmware
  499. //
  500. // To do this, we first find out how much space we need by calling
  501. // with an empty buffer.
  502. //
  503. EfiMd = NULL;
  504. Status = EfiBS->GetMemoryMap (
  505. &MemoryMapSize,
  506. EfiMd,
  507. &MemoryMapKey,
  508. &DescriptorSize,
  509. &DescriptorVersion
  510. );
  511. if (Status != EFI_BUFFER_TOO_SMALL) {
  512. EfiST->ConOut->OutputString(EfiST->ConOut,
  513. L"SuMain: GetMemoryMap failed\n");
  514. EfiBS->Exit(EfiImageHandle, Status, 0, 0);
  515. }
  516. //
  517. // We are going to make three extra allocations before we call GetMemoryMap
  518. // again, so add some extra space.
  519. //
  520. // 1. EfiMD
  521. // 2. MDarray
  522. // 3. Split out memory above and below 80MB (on ia64)
  523. //
  524. MemoryMapSize += 3*DescriptorSize;
  525. i = (ULONG) MemoryMapSize;
  526. //
  527. // now allocate space for the EFI-based memory map and assign it to the loader
  528. //
  529. Status = EfiBS->AllocatePool(EfiLoaderData,i,&EfiMd);
  530. if (EFI_ERROR(Status)) {
  531. DBG_TRACE( L"SuMain: AllocatePool failed\n");
  532. EfiBS->Exit(EfiImageHandle, Status, 0, 0);
  533. }
  534. //
  535. // now Allocate and zero the MDArray, which is the native loader memory
  536. // map which we need to map the EFI memory map to.
  537. //
  538. // The MDArray has one entry for each EFI_MEMORY_DESCRIPTOR, and each entry
  539. // is MEMORY_DESCRIPTOR large.
  540. //
  541. i=((ULONG)(MemoryMapSize / DescriptorSize)+1)*sizeof (MEMORY_DESCRIPTOR);
  542. Status = EfiBS->AllocatePool(EfiLoaderData,i,&MDArray);
  543. if (EFI_ERROR(Status)) {
  544. DBG_TRACE (L"SuMain: AllocatePool failed\n");
  545. EfiBS->Exit(EfiImageHandle, Status, 0, 0);
  546. }
  547. //
  548. // caution, this is 0 based!
  549. //
  550. MaxDescriptors = (ULONG)((MemoryMapSize / DescriptorSize)+1);
  551. RtlZeroMemory (MDArray,i);
  552. if ((EfiMd == NULL)) {
  553. DBG_TRACE (L"SuMain: Failed to Allocate Memory for the descriptor lists\n");
  554. EfiBS->Exit(EfiImageHandle, Status, 0, 0);
  555. }
  556. //
  557. // we have all of the memory allocated at this point, so retreive the
  558. // memory map again, which should succeed the second time.
  559. //
  560. Status = EfiBS->GetMemoryMap (
  561. &MemoryMapSize,
  562. EfiMd,
  563. &MemoryMapKey,
  564. &DescriptorSize,
  565. &DescriptorVersion
  566. );
  567. if (EFI_ERROR(Status)) {
  568. DBG_TRACE(L"SuMain: GetMemoryMap failed\n");
  569. EfiBS->Exit(EfiImageHandle, Status, 0, 0);
  570. }
  571. //
  572. // now walk the EFI_MEMORY_DESCRIPTOR array, mapping each
  573. // entry to an arc-based MEMORY_DESCRIPTOR.
  574. //
  575. // MemoryMapSize contains actual size of the memory descriptor array.
  576. //
  577. for (i = 0; MemoryMapSize > 0; i++) {
  578. #if DBG_MEMORY
  579. wsprintf( DebugBuffer,
  580. L"PageStart (%x), Size (%x), Type (%x)\r\n",
  581. (EfiMd->PhysicalStart >> EFI_PAGE_SHIFT),
  582. EfiMd->NumberOfPages,
  583. EfiMd->Type);
  584. EfiST->ConOut->OutputString( EfiST->ConOut, DebugBuffer);
  585. DBG_EFI_PAUSE();
  586. #endif
  587. if (EfiMd->NumberOfPages > 0) {
  588. MdPhysicalStart = EfiMd->PhysicalStart;
  589. MdPhysicalEnd = EfiMd->PhysicalStart + (EfiMd->NumberOfPages << EFI_PAGE_SHIFT);
  590. MdPhysicalSize = MdPhysicalEnd - MdPhysicalStart;
  591. #if DBG_MEMORY
  592. wsprintf( DebugBuffer,
  593. L"PageStart %x (%x), PageEnd %x (%x), Type (%x)\r\n",
  594. MdPhysicalStart, (EfiMd->PhysicalStart >> EFI_PAGE_SHIFT),
  595. MdPhysicalEnd, (EfiMd->PhysicalStart >>EFI_PAGE_SHIFT) + EfiMd->NumberOfPages,
  596. EfiMd->Type);
  597. EfiST->ConOut->OutputString( EfiST->ConOut, DebugBuffer);
  598. DBG_EFI_PAUSE();
  599. #endif
  600. //
  601. // Insert conventional memory descriptors with WB flag set
  602. // into NT loader memory descriptor list.
  603. //
  604. if ( (EfiMd->Type == EfiConventionalMemory) &&
  605. ((EfiMd->Attribute & EFI_MEMORY_WB) == EFI_MEMORY_WB) ) {
  606. ULONGLONG AmountOfMemory;
  607. ULONG NumberOfEfiPages;
  608. BOOLEAN FirstTime = TRUE;
  609. //
  610. // Allocate pages between the start and _80MB line for
  611. // the loader to manage. We don't use anything above this range, so
  612. // just leave that memory alone
  613. //
  614. if ((MdPhysicalStart < (_80MB << PAGE_SHIFT)) &&
  615. (MdPhysicalEnd > (_80MB << PAGE_SHIFT))) {
  616. AmountOfMemory = (_80MB << PAGE_SHIFT) - EfiMd->PhysicalStart;
  617. //
  618. // record the pages in EFI page size
  619. //
  620. NumberOfEfiPages = (ULONG)(AmountOfMemory >> EFI_PAGE_SHIFT);
  621. //
  622. // try to align it.
  623. //
  624. if ((NumberOfEfiPages % ((1 << PAGE_SHIFT) >> EFI_PAGE_SHIFT) != 0) &&
  625. (NumberOfEfiPages + (PAGE_SHIFT - EFI_PAGE_SHIFT) <= EfiMd->NumberOfPages )) {
  626. NumberOfEfiPages += (PAGE_SHIFT - EFI_PAGE_SHIFT);
  627. }
  628. Status = EfiBS->AllocatePages ( AllocateAddress,
  629. EfiLoaderData,
  630. NumberOfEfiPages,
  631. &(EfiMd->PhysicalStart) );
  632. #if DBG_MEMORY
  633. wsprintf( DebugBuffer,
  634. L"allocate pages @ %x size = %x\r\n",
  635. (EfiMd->PhysicalStart >> EFI_PAGE_SHIFT),
  636. NumberOfEfiPages);
  637. EfiST->ConOut->OutputString( EfiST->ConOut, DebugBuffer);
  638. DBG_EFI_PAUSE();
  639. #endif
  640. if (EFI_ERROR(Status)) {
  641. EfiST->ConOut->OutputString(EfiST->ConOut,
  642. L"SuMain: AllocPages failed\n");
  643. EfiBS->Exit(EfiImageHandle, Status, 0, 0);
  644. }
  645. MdPhysicalEnd = MdPhysicalStart + (NumberOfEfiPages << EFI_PAGE_SHIFT);
  646. MdPhysicalSize = MdPhysicalEnd - MdPhysicalStart;
  647. //
  648. // If PalPhysicalBase is not 0, then do not report the memory
  649. // from the end of PAL to the next larger page size to avoid
  650. // memory aliasing in the kernel.
  651. //
  652. // we assume that we get the PAL memory in the memory map
  653. // before any conventional memory
  654. //
  655. while (1) {
  656. if (PalPhysicalBase != 0) {
  657. //
  658. // If the descriptor is completely before or after
  659. // the PAL base, just insert it like a normal descriptor
  660. //
  661. if ( ((MdPhysicalStart < PalPhysicalBase) &&
  662. (MdPhysicalEnd <= PalPhysicalBase)) ||
  663. (MdPhysicalStart >= PalEnd)) {
  664. InsertDescriptor( (ULONG)(MdPhysicalStart >> EFI_PAGE_SHIFT),
  665. (ULONG)(MdPhysicalSize >> EFI_PAGE_SHIFT),
  666. MemoryFirmwareTemporary );
  667. }
  668. //
  669. // else the descriptors must somehow overlap (how
  670. // could this be possible?
  671. //
  672. else {
  673. if (MdPhysicalStart < PalPhysicalBase) {
  674. ASSERT( MdPhysicalEnd > PalPhysicalBase );
  675. EfiST->ConOut->OutputString(EfiST->ConOut,
  676. L"SuMain: overlapping descriptor with PAL #1\n");
  677. //
  678. // Insert a descriptor from the start of
  679. // the memory range to the start of the PAL
  680. // code
  681. //
  682. InsertDescriptor( (ULONG)(MdPhysicalStart >> EFI_PAGE_SHIFT),
  683. (ULONG)((PalPhysicalBase - MdPhysicalStart) >> EFI_PAGE_SHIFT),
  684. EfiToArcType(EfiMd->Type));
  685. }
  686. if (MdPhysicalEnd > PalEnd) {
  687. //
  688. // Insert a descriptor from the end of the
  689. // PAL code to the end of the memory range
  690. //
  691. InsertDescriptor( (ULONG)(PalEnd >> EFI_PAGE_SHIFT),
  692. (ULONG)((MdPhysicalEnd - PalEnd) >> EFI_PAGE_SHIFT),
  693. EfiToArcType(EfiMd->Type));
  694. }
  695. }
  696. } else {
  697. //
  698. // Insert the descriptor
  699. //
  700. // hack -- set the memory type to "permanent" so that we
  701. // don't merge it with the prior descriptor. We'll set it
  702. // back to the correct type after we return.
  703. //
  704. InsertDescriptor( (ULONG)(MdPhysicalStart >> EFI_PAGE_SHIFT),
  705. (ULONG)((ULONGLONG)MdPhysicalSize >> EFI_PAGE_SHIFT),
  706. FirstTime? LoaderFree : LoaderFirmwarePermanent);
  707. }
  708. if (!FirstTime) {
  709. MDArray[NumberDescriptors-1].MemoryType = LoaderFirmwareTemporary;
  710. break;
  711. } else {
  712. //
  713. // go through again with the rest of the memory descriptor
  714. //
  715. MdPhysicalEnd = MdPhysicalStart + (EfiMd->NumberOfPages << EFI_PAGE_SHIFT);
  716. MdPhysicalStart += MdPhysicalSize;
  717. MdPhysicalSize = MdPhysicalEnd - MdPhysicalStart;
  718. #if DBG_MEMORY
  719. wsprintf( DebugBuffer,
  720. L"change start @ %x --> @ %x size %x --> %x\r\n",
  721. (EfiMd->PhysicalStart >> EFI_PAGE_SHIFT),
  722. (MdPhysicalStart >> EFI_PAGE_SHIFT),
  723. EfiMd->NumberOfPages,
  724. (EfiMd->NumberOfPages-NumberOfEfiPages) );
  725. EfiST->ConOut->OutputString( EfiST->ConOut, DebugBuffer);
  726. DBG_EFI_PAUSE();
  727. #endif
  728. FirstTime = FALSE;
  729. }
  730. }
  731. } else {
  732. //
  733. // just insert it
  734. //
  735. InsertDescriptor( (ULONG)(MdPhysicalStart >> EFI_PAGE_SHIFT),
  736. (ULONG)((ULONGLONG)MdPhysicalSize >> EFI_PAGE_SHIFT),
  737. EfiToArcType(EfiMd->Type));
  738. }
  739. } else if ( (EfiMd->Type == EfiLoaderCode) ||
  740. (EfiMd->Type == EfiLoaderData) ) {
  741. //
  742. // just insert EfiLoaderCode and EfiLoaderData verbatim
  743. //
  744. InsertDescriptor( (ULONG)(MdPhysicalStart >> EFI_PAGE_SHIFT),
  745. (ULONG)(MdPhysicalSize >> EFI_PAGE_SHIFT),
  746. EfiToArcType(EfiMd->Type));
  747. } else if (EfiMd->Type == EfiPalCode) {
  748. //
  749. // save off the Pal stuff for later
  750. //
  751. PalPhysicalBase = EfiMd->PhysicalStart;
  752. PalSize = EfiMd->NumberOfPages << EFI_PAGE_SHIFT;
  753. PalEnd = EfiMd->PhysicalStart + PalSize;
  754. MEM_SIZE_TO_PS(PalSize, PalTrPs);
  755. } else if (EfiMd->Type == EfiMemoryMappedIOPortSpace) {
  756. //
  757. // save off the Io stuff for later
  758. //
  759. IoPortPhysicalBase = EfiMd->PhysicalStart;
  760. IoPortSize = EfiMd->NumberOfPages << EFI_PAGE_SHIFT;
  761. MEM_SIZE_TO_PS(IoPortSize, IoPortTrPs);
  762. } else if (EfiMd->Type == EfiMemoryMappedIO) {
  763. //
  764. // just ignore this type since it's not real memory -- the
  765. // system can use ACPI tables to get at this later on.
  766. //
  767. } else {
  768. //
  769. // some other type -- just insert it without any changes
  770. //
  771. InsertDescriptor( (ULONG)(MdPhysicalStart >> EFI_PAGE_SHIFT),
  772. (ULONG)(MdPhysicalSize >> EFI_PAGE_SHIFT),
  773. EfiToArcType(EfiMd->Type));
  774. }
  775. }
  776. EfiMd = (EFI_MEMORY_DESCRIPTOR *) ( (PUCHAR) EfiMd + DescriptorSize );
  777. MemoryMapSize -= DescriptorSize;
  778. }
  779. //
  780. // we've built the memory descriptors with EFI_PAGE_SIZE resolution.
  781. // if the page sizes don't match, we post-process it here to get the
  782. // resolution correct
  783. //
  784. if (PAGE_SHIFT != EFI_PAGE_SHIFT) {
  785. AdjustMemoryDescriptorSizes();
  786. }
  787. }
  788. VOID
  789. GetPalProcEntryPoint(
  790. IN PSST_HEADER SalSystemTable
  791. )
  792. {
  793. PVOID NextEntry;
  794. PPAL_SAL_ENTRY_POINT PalSalEntryPoint;
  795. PSAL_MEMORY_DESCRIPTOR PSalMem;
  796. ULONG PalFreeEnd;
  797. ULONGLONG PalProcOffset;
  798. ULONG i;
  799. //
  800. // Get PalProc entry point from SAL System Table
  801. //
  802. NextEntry = (PUCHAR) SalSystemTable + sizeof(SST_HEADER);
  803. for (i = 0; i < SalSystemTable->EntryCount; i++) {
  804. switch ( *(PUCHAR)NextEntry ) {
  805. case PAL_SAL_EP_TYPE:
  806. PalSalEntryPoint = (PPAL_SAL_ENTRY_POINT) NextEntry;
  807. PalProcPhysical = PalSalEntryPoint->PalEntryPoint;
  808. PalProcOffset = PalPhysicalBase - PalProcPhysical;
  809. PalProcVirtual = VIRTUAL_PAL_BASE + PalProcOffset;
  810. ((PPAL_SAL_ENTRY_POINT)NextEntry)++;
  811. break;
  812. case SAL_MEMORY_TYPE:
  813. ((PSAL_MEMORY_DESCRIPTOR)NextEntry)++;
  814. break;
  815. case PLATFORM_FEATURES_TYPE:
  816. ((PPLATFORM_FEATURES)NextEntry)++;
  817. break;
  818. case TRANSLATION_REGISTER_TYPE:
  819. ((PTRANSLATION_REGISTER)NextEntry)++;
  820. break;
  821. case PTC_COHERENCE_TYPE:
  822. ((PPTC_COHERENCE_DOMAIN)NextEntry)++;
  823. break;
  824. case AP_WAKEUP_TYPE:
  825. ((PAP_WAKEUP_DESCRIPTOR)NextEntry)++;
  826. break;
  827. default:
  828. EfiST->ConOut->OutputString(EfiST->ConOut,
  829. L"SST: Invalid SST entry\n");
  830. EfiBS->Exit(EfiImageHandle, 0, 0, 0);
  831. }
  832. }
  833. }
  834. ULONG
  835. GetDevPathSize(
  836. IN EFI_DEVICE_PATH *DevPath
  837. )
  838. {
  839. EFI_DEVICE_PATH *Start;
  840. //
  841. // Search for the end of the device path structure
  842. //
  843. Start = DevPath;
  844. while (DevPath->Type != END_DEVICE_PATH_TYPE) {
  845. DevPath = NextDevicePathNode(DevPath);
  846. }
  847. //
  848. // Compute the size
  849. //
  850. return ((UCHAR) DevPath - (UCHAR) Start);
  851. }
  852. MEMORY_TYPE
  853. EfiToArcType (
  854. UINT32 Type
  855. )
  856. /*++
  857. Routine Description:
  858. Maps an EFI memory type to an Arc memory type. We only care about a few
  859. kinds of memory, so this list is incomplete.
  860. Arguments:
  861. Type - an EFI memory type
  862. Returns:
  863. A MEMORY_TYPE enumerated type.
  864. --*/
  865. {
  866. MEMORY_TYPE typeRet=MemoryFirmwarePermanent;
  867. switch (Type) {
  868. case EfiLoaderCode:
  869. {
  870. typeRet=MemoryLoadedProgram; // This gets claimed later
  871. break;
  872. }
  873. case EfiLoaderData:
  874. case EfiBootServicesCode:
  875. case EfiBootServicesData:
  876. {
  877. typeRet=MemoryFirmwareTemporary;
  878. break;
  879. }
  880. case EfiConventionalMemory:
  881. {
  882. typeRet=MemoryFree;
  883. break;
  884. }
  885. case EfiUnusableMemory:
  886. {
  887. typeRet=MemoryBad;
  888. break;
  889. }
  890. default:
  891. //
  892. // all others are memoryfirmwarepermanent
  893. //
  894. break;
  895. }
  896. return typeRet;
  897. }
  898. VOID
  899. InsertDescriptor (
  900. ULONG BasePage,
  901. ULONG NumberOfPages,
  902. MEMORY_TYPE MemoryType
  903. )
  904. /*++
  905. Routine Description:
  906. This routine inserts a descriptor into the correct place in the
  907. memory descriptor list.
  908. The descriptors come in in EFI_PAGE_SIZE pages and must be
  909. converted to PAGE_SIZE pages. This significantly complicates things,
  910. as we must page align the start of descriptors and hte lengths of the
  911. descriptors.
  912. What we do is the following: we store the descriptors in the MDArray with
  913. EFI_PAGE_SIZE resolution. When we do an insertion, we check if we can
  914. coellesce the current entry with the prior entry (we assume our memory map
  915. is sorted), keeping in mind that we want to ensure our entries are always
  916. modulo PAGE_SIZE.
  917. After we've added all of the entries with this routine, we have a post
  918. processing step that converts all of the (modulo PAGE_SIZE) MDArray entries
  919. into PAGE_SIZE resolution.
  920. Arguments:
  921. BasePage - Base page that the memory starts at.
  922. NumberOfPages - The number of pages starting at memory block to be inserted.
  923. MemoryType - An arc memory type describing the memory.
  924. Return Value:
  925. None. Updates MDArray global memory array.
  926. --*/
  927. {
  928. MEMORY_DESCRIPTOR *CurrentEntry, *PriorEntry;
  929. ULONG NewBasePage, NewNumberOfPages;
  930. BOOLEAN MustCoellesce = FALSE;
  931. BOOLEAN ShrinkPrior;
  932. //
  933. // Search the spot to insert the new descriptor.
  934. //
  935. // We assume that there are no holes in our array.
  936. //
  937. CurrentEntry = (MEMORY_DESCRIPTOR *)&MDArray[NumberDescriptors];
  938. //
  939. // if this is the first entry, just insert it
  940. //
  941. if (NumberDescriptors == 0) {
  942. CurrentEntry->BasePage = BasePage;
  943. CurrentEntry->PageCount = NumberOfPages;
  944. CurrentEntry->MemoryType = MemoryType;
  945. //
  946. // The MDArray is already zeroed out so no need to zero out the next entry.
  947. //
  948. NumberDescriptors++;
  949. #if DBG
  950. wsprintf( DebugBuffer,
  951. L"insert new descriptor #%x of %x, BasePage %x, NumberOfPages %x, Type (%x)\r\n",
  952. NumberDescriptors, MaxDescriptors, BasePage, NumberOfPages, MemoryType);
  953. EfiST->ConOut->OutputString( EfiST->ConOut, DebugBuffer);
  954. #endif
  955. return;
  956. }
  957. PriorEntry = (MEMORY_DESCRIPTOR *)&MDArray[NumberDescriptors-1];
  958. //
  959. // The last entry had better be empty or the descriptor list is
  960. // somehow corrupted.
  961. //
  962. if (CurrentEntry->PageCount != 0) {
  963. EfiST->ConOut->OutputString(EfiST->ConOut,
  964. L"SuMain: Inconsistent Descriptor count in InsertDescriptor!\r\n");
  965. EfiBS->Exit(EfiImageHandle, 0, 0, 0);
  966. }
  967. //
  968. // if the memory type matches the prior entry's memory type, just merge
  969. // the two together
  970. //
  971. if (PriorEntry->MemoryType == MemoryType) {
  972. //
  973. // validate that the array is really sorted correctly
  974. //
  975. if (PriorEntry->BasePage + PriorEntry->PageCount != BasePage) {
  976. #if DBG
  977. wsprintf( DebugBuffer,
  978. L"SuMain: Inconsistent descriptor, PriorEntry->BasePage %x, PriorEntry->PageCount %x, BasePage = %x, type = %x -- insert new descriptor\r\n",
  979. PriorEntry->BasePage,
  980. PriorEntry->PageCount,
  981. BasePage, MemoryType);
  982. EfiST->ConOut->OutputString(EfiST->ConOut,DebugBuffer);
  983. #endif
  984. CurrentEntry->BasePage = BasePage;
  985. CurrentEntry->PageCount = NumberOfPages;
  986. CurrentEntry->MemoryType = MemoryType;
  987. NumberDescriptors++;
  988. #if DBG
  989. wsprintf( DebugBuffer,
  990. L"insert new descriptor #%x of %x, BasePage %x, NumberOfPages %x, Type (%x)\r\n",
  991. NumberDescriptors, MaxDescriptors, BasePage, NumberOfPages, MemoryType);
  992. EfiST->ConOut->OutputString( EfiST->ConOut, DebugBuffer);
  993. #endif
  994. return;
  995. } else {
  996. PriorEntry->PageCount += NumberOfPages;
  997. #if DBG
  998. wsprintf( DebugBuffer,
  999. L"merge descriptor #%x of %x, BasePage %x, NumberOfPages %x --> %x, Type (%x)\r\n",
  1000. NumberDescriptors,
  1001. MaxDescriptors,
  1002. PriorEntry->BasePage,
  1003. PriorEntry->PageCount - NumberOfPages,
  1004. PriorEntry->PageCount,
  1005. MemoryType);
  1006. EfiST->ConOut->OutputString( EfiST->ConOut, DebugBuffer);
  1007. #endif
  1008. return;
  1009. }
  1010. }
  1011. //
  1012. // check if the current starting address is module PAGE_SIZE. If it is,
  1013. // then we know that we must try to coellesce it with the prior entry.
  1014. //
  1015. //
  1016. NewBasePage = BasePage;
  1017. NewNumberOfPages = NumberOfPages;
  1018. if (BasePage % (1 << (PAGE_SHIFT - EFI_PAGE_SHIFT)) != 0) {
  1019. #if DBG
  1020. wsprintf( DebugBuffer,
  1021. L"must coellesce because base page %x isn't module PAGE_SIZE (%x mod %x = %x).\r\n",
  1022. BasePage,
  1023. (PAGE_SHIFT - EFI_PAGE_SHIFT),
  1024. (1 << (PAGE_SHIFT - EFI_PAGE_SHIFT)),
  1025. BasePage % (1 << (PAGE_SHIFT - EFI_PAGE_SHIFT)) );
  1026. EfiST->ConOut->OutputString( EfiST->ConOut, DebugBuffer);
  1027. #endif
  1028. MustCoellesce = TRUE;
  1029. }
  1030. if (PriorEntry->PageCount % (1 << (PAGE_SHIFT - EFI_PAGE_SHIFT)) != 0 ) {
  1031. #if DBG
  1032. wsprintf(
  1033. DebugBuffer,
  1034. L"must coellesce because prior page count %x isn't module PAGE_SIZE (%x mod %x = %x).\r\n",
  1035. PriorEntry->PageCount,
  1036. (PAGE_SHIFT - EFI_PAGE_SHIFT),
  1037. (1 << (PAGE_SHIFT - EFI_PAGE_SHIFT)),
  1038. PriorEntry->PageCount % (1 << (PAGE_SHIFT - EFI_PAGE_SHIFT)) );
  1039. EfiST->ConOut->OutputString( EfiST->ConOut, DebugBuffer);
  1040. #endif
  1041. MustCoellesce = TRUE;
  1042. }
  1043. if (MustCoellesce) {
  1044. if (PriorEntry->BasePage + PriorEntry->PageCount != BasePage) {
  1045. #if DBG
  1046. wsprintf( DebugBuffer,
  1047. L"SuMain: Inconsistent descriptor, PriorEntry->BasePage %x, PriorEntry->PageCount %x, BasePage = %x, type = %x -- insert new descriptor\r\n",
  1048. PriorEntry->BasePage,
  1049. PriorEntry->PageCount,
  1050. BasePage, MemoryType);
  1051. EfiST->ConOut->OutputString( EfiST->ConOut, DebugBuffer);
  1052. #endif
  1053. MustCoellesce = FALSE;
  1054. }
  1055. }
  1056. if (MustCoellesce) {
  1057. switch( MemoryType ) {
  1058. case MemoryFirmwarePermanent:
  1059. //
  1060. // if the current type is permanent, we must steal from the prior entry
  1061. //
  1062. ShrinkPrior = TRUE;
  1063. break;
  1064. case MemoryLoadedProgram:
  1065. if (PriorEntry->MemoryType == MemoryFirmwarePermanent) {
  1066. ShrinkPrior = FALSE;
  1067. } else {
  1068. ShrinkPrior = TRUE;
  1069. }
  1070. break;
  1071. case MemoryFirmwareTemporary:
  1072. if (PriorEntry->MemoryType == MemoryFirmwarePermanent ||
  1073. PriorEntry->MemoryType == MemoryLoadedProgram) {
  1074. ShrinkPrior = FALSE;
  1075. } else {
  1076. ShrinkPrior = TRUE;
  1077. }
  1078. break;
  1079. case MemoryFree:
  1080. ShrinkPrior = FALSE;
  1081. break;
  1082. case MemoryBad:
  1083. ShrinkPrior = TRUE;
  1084. break;
  1085. default:
  1086. EfiST->ConOut->OutputString(EfiST->ConOut,
  1087. L"SuMain: bad memory type in InsertDescriptor\r\n");
  1088. EfiBS->Exit(EfiImageHandle, 0, 0, 0);
  1089. }
  1090. if (ShrinkPrior) {
  1091. //
  1092. // If the prior entry is small enough, we just convert the whole
  1093. // thing to the new type.
  1094. //
  1095. if (PriorEntry->PageCount <= (PAGE_SHIFT - EFI_PAGE_SHIFT)) {
  1096. PriorEntry->PageCount += NumberOfPages;
  1097. PriorEntry->MemoryType = MemoryType;
  1098. #if DBG
  1099. wsprintf( DebugBuffer,
  1100. L"adjust prior descriptor #%x of %x, BasePage %x, NumberOfPages %x, Type (%x)\r\n",
  1101. NumberDescriptors,
  1102. MaxDescriptors,
  1103. PriorEntry->BasePage,
  1104. PriorEntry->PageCount ,
  1105. PriorEntry->MemoryType);
  1106. EfiST->ConOut->OutputString( EfiST->ConOut, DebugBuffer);
  1107. #endif
  1108. return;
  1109. } else {
  1110. //
  1111. // we just steal part of the prior entry.
  1112. //
  1113. PriorEntry->PageCount -= (PAGE_SHIFT - EFI_PAGE_SHIFT);
  1114. NewNumberOfPages += (PAGE_SHIFT - EFI_PAGE_SHIFT);
  1115. NewBasePage -= (PAGE_SHIFT - EFI_PAGE_SHIFT);
  1116. #if DBG
  1117. wsprintf( DebugBuffer,
  1118. L"shrink earlier descriptor #%x of %x, BasePage %x, NumberOfPages %x, Type (%x)\r\n",
  1119. NumberDescriptors,
  1120. MaxDescriptors,
  1121. PriorEntry->BasePage,
  1122. PriorEntry->PageCount,
  1123. PriorEntry->MemoryType);
  1124. EfiST->ConOut->OutputString( EfiST->ConOut, DebugBuffer);
  1125. #endif
  1126. }
  1127. } else {
  1128. //
  1129. // If the current entry is small enough, we just convert the whole
  1130. // thing to the prior type.
  1131. //
  1132. if (NumberOfPages <= (PAGE_SHIFT - EFI_PAGE_SHIFT)) {
  1133. PriorEntry->PageCount += NumberOfPages;
  1134. #if DBG
  1135. wsprintf( DebugBuffer,
  1136. L"adjust prior descriptor #%x of %x, BasePage %x, NumberOfPages %x, Type (%x)\r\n",
  1137. NumberDescriptors,
  1138. MaxDescriptors,
  1139. PriorEntry->BasePage,
  1140. PriorEntry->PageCount ,
  1141. PriorEntry->MemoryType);
  1142. EfiST->ConOut->OutputString( EfiST->ConOut, DebugBuffer);
  1143. #endif
  1144. return;
  1145. } else {
  1146. //
  1147. // we just steal part of the new entry, adding it to the last
  1148. // entry
  1149. //
  1150. PriorEntry->PageCount += (PAGE_SHIFT - EFI_PAGE_SHIFT);
  1151. NewNumberOfPages -= (PAGE_SHIFT - EFI_PAGE_SHIFT);
  1152. NewBasePage += (PAGE_SHIFT - EFI_PAGE_SHIFT);
  1153. #if DBG
  1154. wsprintf( DebugBuffer,
  1155. L"grow earlier descriptor #%x of %x, BasePage %x, NumberOfPages %x, Type (%x)\r\n",
  1156. NumberDescriptors,
  1157. MaxDescriptors,
  1158. PriorEntry->BasePage,
  1159. PriorEntry->PageCount,
  1160. PriorEntry->MemoryType);
  1161. EfiST->ConOut->OutputString( EfiST->ConOut, DebugBuffer);
  1162. #endif
  1163. }
  1164. }
  1165. }
  1166. //
  1167. // we have now adjusted the prior entry, just insert whatever remains
  1168. //
  1169. CurrentEntry->BasePage = NewBasePage;
  1170. CurrentEntry->PageCount = NewNumberOfPages;
  1171. CurrentEntry->MemoryType = MemoryType;
  1172. NumberDescriptors++;
  1173. #if DBG
  1174. wsprintf( DebugBuffer,
  1175. L"insert new descriptor #%x of %x, BasePage %x, NumberOfPages %x, Type (%x)\r\n",
  1176. NumberDescriptors,
  1177. MaxDescriptors,
  1178. CurrentEntry->BasePage,
  1179. CurrentEntry->PageCount,
  1180. CurrentEntry->MemoryType);
  1181. EfiST->ConOut->OutputString( EfiST->ConOut, DebugBuffer);
  1182. #endif
  1183. return;
  1184. }
  1185. #if 0
  1186. #define DBG_OUT(_X) \
  1187. (EfiST->ConOut->OutputString(EfiST->ConOut, (_X))); \
  1188. while (!BlGetKey());
  1189. void DbgOut(PWSTR Str) {
  1190. if (Str)
  1191. DBG_OUT(Str)
  1192. }
  1193. #endif
  1194. #ifdef FORCE_CD_BOOT
  1195. void EfiDbg(PWCHAR szStr) {
  1196. DBG_TRACE(szStr);
  1197. }
  1198. #endif // for FORCE_CD_BOOT
  1199. VOID
  1200. AdjustMemoryDescriptorSizes(
  1201. VOID
  1202. )
  1203. /*++
  1204. Routine Description:
  1205. If the EFI_PAGE_SIZE doesn't match PAGE_SIZE, this routine will
  1206. adjust the page sizes to be in PAGE_SIZE resolution.
  1207. We assume that the MDArray is already in modulo PAGE_SIZE chunks
  1208. Arguments:
  1209. None.
  1210. Returns:
  1211. None. Adjusts MDArray global variable.
  1212. --*/
  1213. {
  1214. ULONG i;
  1215. MEMORY_DESCRIPTOR *CurrentEntry;
  1216. ULONGLONG Scratch;
  1217. for (i = 0; i < NumberDescriptors; i++ ) {
  1218. CurrentEntry = (MEMORY_DESCRIPTOR *)&MDArray[i];
  1219. #if 1
  1220. Scratch = (ULONGLONG)CurrentEntry->BasePage << EFI_PAGE_SHIFT;
  1221. Scratch = Scratch >> PAGE_SHIFT;
  1222. CurrentEntry->BasePage = (ULONG)Scratch;
  1223. Scratch = (ULONGLONG)CurrentEntry->PageCount << EFI_PAGE_SHIFT;
  1224. Scratch = Scratch >> PAGE_SHIFT;
  1225. CurrentEntry->PageCount = (ULONG)Scratch;
  1226. if (CurrentEntry->PageCount == 0) {
  1227. wsprintf( DebugBuffer,
  1228. L"SuMain: Invalid descriptor size smaller than PAGE_SIZE, BasePage %x, type = %x\r\n",
  1229. CurrentEntry->BasePage,
  1230. CurrentEntry->MemoryType);
  1231. EfiST->ConOut->OutputString( EfiST->ConOut, DebugBuffer);
  1232. }
  1233. #else
  1234. CurrentEntry->BasePage = (ULONG)(ULONGLONG)(((ULONGLONG)(CurrentEntry->BasePage << EFI_PAGE_SHIFT)) >> PAGE_SHIFT);
  1235. CurrentEntry->PageCount = (ULONG)((ULONGLONG)(CurrentEntry->PageCount << EFI_PAGE_SHIFT) >> PAGE_SHIFT);
  1236. #endif
  1237. }
  1238. }