loader.c 55 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251
  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. loader.c
  9. Abstract:
  10. This module loads the kernel into memory, performs the initialization steps
  11. necessary to start the kernel, and then transfers execution to it.
  12. Author:
  13. Evan Green 29-Jul-2012
  14. Environment:
  15. Boot
  16. --*/
  17. //
  18. // ------------------------------------------------------------------- Includes
  19. //
  20. #include <minoca/kernel/kernel.h>
  21. #include <minoca/fw/smbios.h>
  22. #include <minoca/lib/fat/fat.h>
  23. #include "firmware.h"
  24. #include "bootlib.h"
  25. #include "dbgport.h"
  26. #include <minoca/lib/basevid.h>
  27. #include "paging.h"
  28. #include "loader.h"
  29. //
  30. // ---------------------------------------------------------------- Definitions
  31. //
  32. #define LOADER_BINARY_NAME_MAX_SIZE 16
  33. #define LOADER_MODULE_BUFFER_SIZE \
  34. (sizeof(DEBUG_MODULE) + sizeof(LOADER_BINARY_NAME_MAX_SIZE))
  35. #define LOADER_NAME "Minoca Boot Loader"
  36. //
  37. // ----------------------------------------------- Internal Function Prototypes
  38. //
  39. KSTATUS
  40. BopMapAcpiTables (
  41. PMEMORY_DESCRIPTOR_LIST MemoryMap,
  42. PBOOT_VOLUME BootDevice,
  43. FILE_ID ConfigurationDirectory,
  44. PFIRMWARE_TABLE_DIRECTORY *FirmwareTables
  45. );
  46. VOID
  47. BopAcpiMemoryIteratorRoutine (
  48. PMEMORY_DESCRIPTOR_LIST DescriptorList,
  49. PMEMORY_DESCRIPTOR Descriptor,
  50. PVOID Context
  51. );
  52. KSTATUS
  53. BopLoadDrivers (
  54. PLOADER_BUFFER BootDriverFile
  55. );
  56. KSTATUS
  57. BopMapNeededHardwareRegions (
  58. PKERNEL_INITIALIZATION_BLOCK Parameters
  59. );
  60. KSTATUS
  61. BopReadBootConfiguration (
  62. PBOOT_INITIALIZATION_BLOCK Parameters,
  63. PBOOT_CONFIGURATION_CONTEXT *NewContext,
  64. PBOOT_ENTRY *BootEntry
  65. );
  66. KSTATUS
  67. BopGetConfigurationDirectory (
  68. PBOOT_VOLUME BootDevice,
  69. PFILE_ID DirectoryFileId
  70. );
  71. VOID
  72. BopSetBootTime (
  73. PKERNEL_INITIALIZATION_BLOCK Parameters
  74. );
  75. KSTATUS
  76. BopAddSystemMemoryResource (
  77. PKERNEL_INITIALIZATION_BLOCK Parameters,
  78. UINTN Size,
  79. SYSTEM_MEMORY_RESOURCE_TYPE Type,
  80. ULONG MapFlags
  81. );
  82. KSTATUS
  83. BopAddMmInitMemory (
  84. PKERNEL_INITIALIZATION_BLOCK Parameters
  85. );
  86. VOID
  87. BopMmInitMemoryMapIterationRoutine (
  88. PMEMORY_DESCRIPTOR_LIST DescriptorList,
  89. PMEMORY_DESCRIPTOR Descriptor,
  90. PVOID Context
  91. );
  92. KSTATUS
  93. BopAllocateKernelBuffer (
  94. UINTN Size,
  95. ULONG MapFlags,
  96. PPHYSICAL_ADDRESS PhysicalAddress,
  97. PLOADER_BUFFER BufferOut
  98. );
  99. //
  100. // ------------------------------------------------------ Data Type Definitions
  101. //
  102. /*++
  103. Structure Description:
  104. This structure defines the iteration context when mapping regions of the
  105. memory map marked for ACPI tables.
  106. Members:
  107. RsdtTableEntry - Stores the array of table pointers in the RSDT.
  108. RsdtTableCount - Stores the number of entries in the RSDT table.
  109. TableEntry - Stores the array of pointers to kernel addresses of ACPI
  110. tables.
  111. BootTableEntry - Stores the array of pointers to boot addresses of ACPI
  112. tables.
  113. TableDirectory - Stores a pointer to the firmware table directory.
  114. DsdtTable - Stores a pointer to the DSDT table.
  115. --*/
  116. typedef struct _LOADER_ACPI_MEMORY_ITERATOR {
  117. PULONG RsdtTableEntry;
  118. UINTN RsdtTableCount;
  119. PVOID *TableEntry;
  120. PVOID *BootTableEntry;
  121. PFIRMWARE_TABLE_DIRECTORY TableDirectory;
  122. PVOID DsdtTable;
  123. KSTATUS Status;
  124. } LOADER_ACPI_MEMORY_ITERATOR, *PLOADER_ACPI_MEMORY_ITERATOR;
  125. //
  126. // -------------------------------------------------------------------- Globals
  127. //
  128. //
  129. // Set this to TRUE to force-enable debugging the boot loader.
  130. //
  131. BOOL BoForceDebug = FALSE;
  132. DEBUG_MODULE BoLoaderModule;
  133. extern MEMORY_DESCRIPTOR_LIST BoVirtualMap;
  134. //
  135. // Store a pointer to the firmware tables.
  136. //
  137. PFIRMWARE_TABLE_DIRECTORY BoFirmwareTables;
  138. LIST_ENTRY BoLoadedImageList;
  139. //
  140. // Carve off memory to store the loader module, including its string.
  141. //
  142. UCHAR BoLoaderModuleBuffer[LOADER_MODULE_BUFFER_SIZE];
  143. //
  144. // Piggyback off of the image support's system directory file ID.
  145. //
  146. extern FILE_ID BoSystemDirectoryId;
  147. //
  148. // ------------------------------------------------------------------ Functions
  149. //
  150. __USED
  151. INT
  152. BoMain (
  153. PBOOT_INITIALIZATION_BLOCK Parameters
  154. )
  155. /*++
  156. Routine Description:
  157. This routine is the entry point for the boot loader program.
  158. Arguments:
  159. Parameters - Supplies a pointer to the application initialization
  160. parameters.
  161. Return Value:
  162. On success, this function does not return.
  163. On failure, this function returns the step number on which it failed. This
  164. provides an indication as to where in the boot process it failed.
  165. --*/
  166. {
  167. UINTN AlignedLoaderSize;
  168. PVOID AlignedLoaderStart;
  169. PBOOT_CONFIGURATION_CONTEXT BootConfiguration;
  170. PBOOT_VOLUME BootDevice;
  171. LOADER_BUFFER BootDriversFile;
  172. PBOOT_ENTRY BootEntry;
  173. FILE_ID ConfigurationDirectory;
  174. PDEBUG_DEVICE_DESCRIPTION DebugDevice;
  175. PLOADED_IMAGE KernelImage;
  176. PDEBUG_MODULE KernelModule;
  177. PKERNEL_INITIALIZATION_BLOCK KernelParameters;
  178. PCSTR KernelPath;
  179. PHYSICAL_ADDRESS KernelStackPhysical;
  180. PDEBUG_MODULE LoaderModule;
  181. ULONG LoaderModuleNameLength;
  182. ULONG LoaderStep;
  183. ULONG LoadFlags;
  184. PHYSICAL_ADDRESS PageDirectoryPhysical;
  185. UINTN PageOffset;
  186. UINTN PageSize;
  187. UINTN RoundedStackMaximum;
  188. UINTN RoundedStackMinimum;
  189. UINTN StackBottom;
  190. PVOID StackEnd;
  191. BOOL StackOutsideImage;
  192. KSTATUS Status;
  193. BootConfiguration = NULL;
  194. BootDevice = NULL;
  195. BootEntry = NULL;
  196. DebugDevice = NULL;
  197. PageSize = MmPageSize();
  198. StackOutsideImage = FALSE;
  199. //
  200. // Perform very early firmware initialization before the processor
  201. // initialization clobbers any processor state.
  202. //
  203. LoaderStep = 0;
  204. Status = FwInitialize(0, Parameters);
  205. if (!KSUCCESS(Status)) {
  206. goto MainEnd;
  207. }
  208. //
  209. // Perform very basic processor initialization, preparing it to take
  210. // exceptions and use the serial port.
  211. //
  212. BoInitializeProcessor();
  213. LoaderStep += 1;
  214. BoHlBootInitialize(&DebugDevice, BoGetAcpiTable);
  215. if (BoFirmwareDebugDevice != NULL) {
  216. DebugDevice = BoFirmwareDebugDevice;
  217. }
  218. LoaderStep += 1;
  219. LoaderModule = (PDEBUG_MODULE)BoLoaderModuleBuffer;
  220. //
  221. // Initialize the debugging subsystem.
  222. //
  223. RtlZeroMemory(&BoLoaderModuleBuffer, sizeof(BoLoaderModuleBuffer));
  224. LoaderModuleNameLength =
  225. RtlStringLength((PVOID)(UINTN)(Parameters->ApplicationName)) + 1;
  226. if (LoaderModuleNameLength > LOADER_BINARY_NAME_MAX_SIZE) {
  227. LoaderModuleNameLength = LOADER_BINARY_NAME_MAX_SIZE;
  228. }
  229. LoaderModule->StructureSize = sizeof(DEBUG_MODULE) +
  230. LoaderModuleNameLength -
  231. (ANYSIZE_ARRAY * sizeof(CHAR));
  232. RtlStringCopy(LoaderModule->BinaryName,
  233. (PVOID)(UINTN)(Parameters->ApplicationName),
  234. LoaderModuleNameLength);
  235. LoaderModule->LowestAddress =
  236. (PVOID)(UINTN)(Parameters->ApplicationLowestAddress);
  237. LoaderModule->Size = Parameters->ApplicationSize;
  238. BoProductName = LOADER_NAME;
  239. if ((BoForceDebug != FALSE) ||
  240. (Parameters->BootEntryFlags & BOOT_ENTRY_FLAG_BOOT_DEBUG) != 0) {
  241. Status = KdInitialize(DebugDevice, LoaderModule);
  242. if (!KSUCCESS(Status)) {
  243. goto MainEnd;
  244. }
  245. }
  246. //
  247. // Initialize the firmware layer.
  248. //
  249. LoaderStep += 1;
  250. Status = FwInitialize(1, Parameters);
  251. if (!KSUCCESS(Status)) {
  252. goto MainEnd;
  253. }
  254. LoaderStep += 1;
  255. //
  256. // Initialize paging structures.
  257. //
  258. Status = BoInitializePagingStructures(&PageDirectoryPhysical);
  259. if (!KSUCCESS(Status)) {
  260. goto MainEnd;
  261. }
  262. LoaderStep += 1;
  263. Status = BoArchMapNeededHardwareRegions();
  264. if (!KSUCCESS(Status)) {
  265. goto MainEnd;
  266. }
  267. LoaderStep += 1;
  268. Status = BoFwMapKnownRegions(0, NULL);
  269. if (!KSUCCESS(Status)) {
  270. goto MainEnd;
  271. }
  272. LoaderStep += 1;
  273. //
  274. // Identity map the loader and its stack into kernel address space.
  275. //
  276. AlignedLoaderStart = (PVOID)(UINTN)ALIGN_RANGE_DOWN(
  277. Parameters->ApplicationLowestAddress,
  278. PageSize);
  279. PageOffset = Parameters->ApplicationLowestAddress -
  280. (UINTN)AlignedLoaderStart;
  281. AlignedLoaderSize = ALIGN_RANGE_UP(Parameters->ApplicationSize + PageOffset,
  282. PageSize);
  283. Status = BoMapPhysicalAddress(&AlignedLoaderStart,
  284. (PHYSICAL_ADDRESS)(UINTN)AlignedLoaderStart,
  285. AlignedLoaderSize,
  286. MAP_FLAG_EXECUTE,
  287. MemoryTypeLoaderTemporary);
  288. if (!KSUCCESS(Status)) {
  289. goto MainEnd;
  290. }
  291. LoaderStep += 1;
  292. //
  293. // Parse the boot configuration file.
  294. //
  295. if (Parameters->BootConfigurationFileSize != 0) {
  296. Status = BopReadBootConfiguration(Parameters,
  297. &BootConfiguration,
  298. &BootEntry);
  299. if (!KSUCCESS(Status)) {
  300. goto MainEnd;
  301. }
  302. }
  303. LoaderStep += 1;
  304. //
  305. // Determine if the stack is inside the loader image itself (like in a big
  306. // global).
  307. //
  308. StackBottom = Parameters->StackTop - Parameters->StackSize;
  309. StackOutsideImage = TRUE;
  310. if ((StackBottom >= Parameters->ApplicationLowestAddress) &&
  311. (Parameters->StackTop <
  312. Parameters->ApplicationLowestAddress + Parameters->ApplicationSize)) {
  313. StackOutsideImage = FALSE;
  314. }
  315. if (StackOutsideImage != FALSE) {
  316. RoundedStackMinimum = ALIGN_RANGE_DOWN(StackBottom, PageSize);
  317. RoundedStackMaximum = ALIGN_RANGE_UP(Parameters->StackTop, PageSize);
  318. Status = BoMapPhysicalAddress((PVOID)&RoundedStackMinimum,
  319. RoundedStackMinimum,
  320. RoundedStackMaximum - RoundedStackMinimum,
  321. 0,
  322. MemoryTypeLoaderTemporary);
  323. if (!KSUCCESS(Status)) {
  324. goto MainEnd;
  325. }
  326. }
  327. //
  328. // Create and initialize the kernel initializaton block.
  329. //
  330. LoaderStep += 1;
  331. KernelParameters = BoAllocateMemory(sizeof(KERNEL_INITIALIZATION_BLOCK));
  332. if (KernelParameters == NULL) {
  333. Status = STATUS_NO_MEMORY;
  334. goto MainEnd;
  335. }
  336. //
  337. // Initialize the parameter block.
  338. //
  339. RtlZeroMemory(KernelParameters, sizeof(KERNEL_INITIALIZATION_BLOCK));
  340. INITIALIZE_LIST_HEAD(&(KernelParameters->SystemResourceListHead));
  341. KernelParameters->Version = KERNEL_INITIALIZATION_BLOCK_VERSION;
  342. KernelParameters->Size = sizeof(KERNEL_INITIALIZATION_BLOCK);
  343. KernelParameters->MemoryMap = &BoMemoryMap;
  344. KernelParameters->VirtualMap = &BoVirtualMap;
  345. KernelParameters->BootEntry = BootEntry;
  346. //
  347. // Map the initial page table staging area. It doesn't matter where this
  348. // gets mapped to, the only important thing here is that a page table get
  349. // allocated and initialized, and that page table get mapped itself.
  350. //
  351. LoaderStep += 1;
  352. Status = BoCreatePageTableStage(PageDirectoryPhysical,
  353. &(KernelParameters->PageTableStage));
  354. if (!KSUCCESS(Status)) {
  355. goto MainEnd;
  356. }
  357. //
  358. // Mount the boot device.
  359. //
  360. LoaderStep += 1;
  361. Status = BoOpenBootVolume(Parameters->DriveNumber,
  362. Parameters->PartitionOffset,
  363. BootEntry,
  364. &BootDevice);
  365. if (!KSUCCESS(Status)) {
  366. goto MainEnd;
  367. }
  368. //
  369. // Initialize support to load images.
  370. //
  371. LoaderStep += 1;
  372. Status = BoInitializeImageSupport(BootDevice, BootEntry);
  373. if (!KSUCCESS(Status)) {
  374. goto MainEnd;
  375. }
  376. //
  377. // Open up the configuration directory, which is currently the root
  378. // directory.
  379. //
  380. LoaderStep += 1;
  381. Status = BopGetConfigurationDirectory(BootDevice, &ConfigurationDirectory);
  382. if (!KSUCCESS(Status)) {
  383. goto MainEnd;
  384. }
  385. //
  386. // Load the kernel.
  387. //
  388. LoaderStep += 1;
  389. KernelPath = DEFAULT_KERNEL_BINARY_PATH;
  390. if (BootEntry != NULL) {
  391. KernelPath = BootEntry->KernelPath;
  392. }
  393. LoadFlags = IMAGE_LOAD_FLAG_IGNORE_INTERPRETER |
  394. IMAGE_LOAD_FLAG_PRIMARY_EXECUTABLE |
  395. IMAGE_LOAD_FLAG_NO_STATIC_CONSTRUCTORS |
  396. IMAGE_LOAD_FLAG_BIND_NOW;
  397. Status = ImLoad(&BoLoadedImageList,
  398. KernelPath,
  399. NULL,
  400. NULL,
  401. NULL,
  402. LoadFlags,
  403. &KernelImage,
  404. NULL);
  405. if (!KSUCCESS(Status)) {
  406. goto MainEnd;
  407. }
  408. LoaderStep += 1;
  409. KernelModule = KernelImage->DebuggerModule;
  410. if (KernelModule == NULL) {
  411. goto MainEnd;
  412. }
  413. KernelParameters->KernelModule = KernelModule;
  414. //
  415. // Allocate and map a stack for the kernel.
  416. //
  417. LoaderStep += 1;
  418. ASSERT((DEFAULT_KERNEL_STACK_SIZE & (PageSize - 1)) == 0);
  419. Status = FwAllocatePages(&KernelStackPhysical,
  420. DEFAULT_KERNEL_STACK_SIZE,
  421. PageSize,
  422. MemoryTypeLoaderPermanent);
  423. if (!KSUCCESS(Status)) {
  424. goto MainEnd;
  425. }
  426. LoaderStep += 1;
  427. KernelParameters->KernelStack.Buffer = (PVOID)-1;
  428. KernelParameters->KernelStack.Size = DEFAULT_KERNEL_STACK_SIZE;
  429. Status = BoMapPhysicalAddress(&(KernelParameters->KernelStack.Buffer),
  430. KernelStackPhysical,
  431. KernelParameters->KernelStack.Size,
  432. MAP_FLAG_GLOBAL,
  433. MemoryTypeLoaderPermanent);
  434. if (!KSUCCESS(Status)) {
  435. goto MainEnd;
  436. }
  437. //
  438. // Map the page directory and self-map the page tables.
  439. //
  440. KernelParameters->PageDirectory = (PVOID)-1;
  441. Status = BoMapPagingStructures(PageDirectoryPhysical,
  442. &(KernelParameters->PageDirectory),
  443. &(KernelParameters->PageTables));
  444. if (!KSUCCESS(Status)) {
  445. goto MainEnd;
  446. }
  447. //
  448. // Map ACPI Tables.
  449. //
  450. LoaderStep += 1;
  451. Status = BopMapAcpiTables(&BoMemoryMap,
  452. BootDevice,
  453. ConfigurationDirectory,
  454. &(KernelParameters->FirmwareTables));
  455. if (!KSUCCESS(Status)) {
  456. goto MainEnd;
  457. }
  458. //
  459. // Load the boot driver list, device to driver database, and boot device
  460. // map into memory.
  461. //
  462. LoaderStep += 1;
  463. Status = BoLoadFile(BootDevice,
  464. &ConfigurationDirectory,
  465. BOOT_DRIVER_FILE,
  466. &(BootDriversFile.Buffer),
  467. &(BootDriversFile.Size),
  468. NULL);
  469. if (!KSUCCESS(Status)) {
  470. goto MainEnd;
  471. }
  472. LoaderStep += 1;
  473. Status = BoLoadFile(BootDevice,
  474. &ConfigurationDirectory,
  475. DEVICE_TO_DRIVER_FILE,
  476. &(KernelParameters->DeviceToDriverFile.Buffer),
  477. &(KernelParameters->DeviceToDriverFile.Size),
  478. NULL);
  479. if (!KSUCCESS(Status)) {
  480. goto MainEnd;
  481. }
  482. LoaderStep += 1;
  483. Status = BoLoadFile(BootDevice,
  484. &ConfigurationDirectory,
  485. DEVICE_MAP_FILE,
  486. &(KernelParameters->DeviceMapFile.Buffer),
  487. &(KernelParameters->DeviceMapFile.Size),
  488. NULL);
  489. if (!KSUCCESS(Status)) {
  490. goto MainEnd;
  491. }
  492. //
  493. // Load all boot drivers.
  494. //
  495. LoaderStep += 1;
  496. Status = BopLoadDrivers(&BootDriversFile);
  497. if (!KSUCCESS(Status)) {
  498. goto MainEnd;
  499. }
  500. //
  501. // Dismount the boot volume.
  502. //
  503. LoaderStep += 1;
  504. Status = BoCloseVolume(BootDevice);
  505. BootDevice = NULL;
  506. if (!KSUCCESS(Status)) {
  507. goto MainEnd;
  508. }
  509. //
  510. // Map any hardware regions.
  511. //
  512. LoaderStep += 1;
  513. Status = BopMapNeededHardwareRegions(KernelParameters);
  514. if (!KSUCCESS(Status)) {
  515. goto MainEnd;
  516. }
  517. //
  518. // Attempt to measure the cycle counter frequency so the kernel has an
  519. // early stall source.
  520. //
  521. BoArchMeasureCycleCounter(KernelParameters);
  522. //
  523. // Set up any resources needed for the kernel debug transport.
  524. //
  525. LoaderStep += 1;
  526. BoSetUpKernelDebugTransport(KernelParameters);
  527. //
  528. // Corral the loaded image information and stick in the parameter block.
  529. //
  530. LoaderStep += 1;
  531. MOVE_LIST(&BoLoadedImageList, &(KernelParameters->ImageList));
  532. INITIALIZE_LIST_HEAD(&BoLoadedImageList);
  533. KernelParameters->LoaderModule = LoaderModule;
  534. //
  535. // Allocate some memory for the kernel memory manager to bootstrap with.
  536. //
  537. Status = BopAddMmInitMemory(KernelParameters);
  538. if (!KSUCCESS(Status)) {
  539. goto MainEnd;
  540. }
  541. LoaderStep += 1;
  542. //
  543. // Get the boot time as close as possible to the actual kernel launch time
  544. // while still in boot services.
  545. //
  546. BopSetBootTime(KernelParameters);
  547. //
  548. // Exit boot services. If the firmware is providing the debug device, then
  549. // shut down the debugger before exiting boot services.
  550. //
  551. LoaderStep += 1;
  552. if (DebugDevice == BoFirmwareDebugDevice) {
  553. KdDisconnect();
  554. }
  555. LoaderStep += 1;
  556. Status = BoFwPrepareForKernelLaunch(KernelParameters);
  557. if (!KSUCCESS(Status)) {
  558. goto MainEnd;
  559. }
  560. //
  561. // Prevent excessive SMI activity during early kernel init by disabling
  562. // legacy interrupts.
  563. //
  564. LoaderStep += 1;
  565. BopDisableLegacyInterrupts();
  566. //
  567. // Turn on paging.
  568. //
  569. LoaderStep += 1;
  570. BoEnablePaging();
  571. LoaderStep += 1;
  572. MmMdPrintMdl(&BoMemoryMap);
  573. RtlDebugPrint("Virtual Memory Map\n");
  574. MmMdPrintMdl(&BoVirtualMap);
  575. //
  576. // Stop the debugger.
  577. //
  578. LoaderStep += 1;
  579. if (DebugDevice != BoFirmwareDebugDevice) {
  580. KdDisconnect();
  581. }
  582. LoaderStep += 1;
  583. //
  584. // Transfer execution to the kernel. This should not return.
  585. //
  586. StackEnd = KernelParameters->KernelStack.Buffer +
  587. KernelParameters->KernelStack.Size;
  588. BoTransferToKernelAsm(KernelParameters, KernelModule->EntryPoint, StackEnd);
  589. LoaderStep += 1;
  590. Status = STATUS_SUCCESS;
  591. MainEnd:
  592. RtlDebugPrint("Loader Failed: Step 0x%x, Status %d\n", LoaderStep, Status);
  593. FwPrintString(0, 0, "Loader Failed: ");
  594. FwPrintHexInteger(15, 0, Status);
  595. FwPrintString(0, 1, "Step: ");
  596. FwPrintInteger(6, 1, LoaderStep);
  597. FwDestroy();
  598. return LoaderStep;
  599. }
  600. KSTATUS
  601. BoLoadAndMapFile (
  602. PBOOT_VOLUME Volume,
  603. PFILE_ID Directory,
  604. PSTR FileName,
  605. PVOID *FilePhysical,
  606. PVOID *FileVirtual,
  607. PUINTN FileSize,
  608. MEMORY_TYPE VirtualType
  609. )
  610. /*++
  611. Routine Description:
  612. This routine loads a file into memory and maps it into the kernel's
  613. virtual address space.
  614. Arguments:
  615. Volume - Supplies a pointer to the mounted volume to read the file from.
  616. Directory - Supplies an optional pointer to the ID of the directory to
  617. start path traversal from. If NULL, the root of the volume will be used.
  618. FileName - Supplies the name of the file to load.
  619. FilePhysical - Supplies a pointer where the file buffer's physical address
  620. will be returned. This routine will allocate the buffer to hold the
  621. file. If this parameter and the virtual parameter are NULL, the status
  622. code will reflect whether or not the file could be opened, but the file
  623. contents will not be loaded.
  624. FileVirtual - Supplies a pointer where the file buffer's virtual address
  625. will be returned. If this parameter and the physical parameter are
  626. NULL, the status code will reflect whether or not the file could be
  627. opened, but the file contents will not be loaded.
  628. FileSize - Supplies a pointer where the size of the file in bytes will be
  629. returned.
  630. VirtualType - Supplies the memory type to use for the virtual allocation.
  631. The physical allocation type will be loader permanent.
  632. Return Value:
  633. Status code.
  634. --*/
  635. {
  636. UINTN AlignedSize;
  637. PVOID FinalPages;
  638. ULONG PageSize;
  639. PHYSICAL_ADDRESS PhysicalAddress;
  640. PVOID PhysicalBuffer;
  641. UINTN Size;
  642. KSTATUS Status;
  643. PVOID VirtualBuffer;
  644. FinalPages = NULL;
  645. PageSize = MmPageSize();
  646. PhysicalBuffer = NULL;
  647. Size = 0;
  648. VirtualBuffer = NULL;
  649. Status = BoLoadFile(Volume,
  650. Directory,
  651. FileName,
  652. &PhysicalBuffer,
  653. &Size,
  654. NULL);
  655. if (!KSUCCESS(Status)) {
  656. goto LoadAndMapFileEnd;
  657. }
  658. //
  659. // If no PA and no VA is requested, go to the end.
  660. //
  661. if (FileVirtual == NULL) {
  662. goto LoadAndMapFileEnd;
  663. }
  664. //
  665. // Allocate loader permanent pages.
  666. //
  667. AlignedSize = ALIGN_RANGE_UP(Size, PageSize);
  668. Status = FwAllocatePages(&PhysicalAddress,
  669. AlignedSize,
  670. PageSize,
  671. MemoryTypeLoaderPermanent);
  672. if (!KSUCCESS(Status)) {
  673. goto LoadAndMapFileEnd;
  674. }
  675. ASSERT((UINTN)PhysicalAddress == PhysicalAddress);
  676. FinalPages = (PVOID)(UINTN)PhysicalAddress;
  677. RtlCopyMemory(FinalPages, PhysicalBuffer, Size);
  678. //
  679. // Map the address.
  680. //
  681. VirtualBuffer = (PVOID)-1;
  682. Status = BoMapPhysicalAddress(&VirtualBuffer,
  683. (PHYSICAL_ADDRESS)(UINTN)FinalPages,
  684. AlignedSize,
  685. MAP_FLAG_GLOBAL,
  686. VirtualType);
  687. if (!KSUCCESS(Status)) {
  688. goto LoadAndMapFileEnd;
  689. }
  690. ASSERT(VirtualBuffer >= KERNEL_VA_START);
  691. Status = STATUS_SUCCESS;
  692. LoadAndMapFileEnd:
  693. if (PhysicalBuffer != NULL) {
  694. BoFreeMemory(PhysicalBuffer);
  695. }
  696. if (FileSize != NULL) {
  697. *FileSize = Size;
  698. }
  699. if (FilePhysical != NULL) {
  700. *FilePhysical = FinalPages;
  701. }
  702. if (FileVirtual != NULL) {
  703. *FileVirtual = VirtualBuffer;
  704. }
  705. return Status;
  706. }
  707. PVOID
  708. BoGetAcpiTable (
  709. ULONG Signature,
  710. PVOID PreviousTable
  711. )
  712. /*++
  713. Routine Description:
  714. This routine attempts to find an ACPI description table with the given
  715. signature. This routine does not validate the checksum of the table.
  716. Arguments:
  717. Signature - Supplies the signature of the desired table.
  718. PreviousTable - Supplies an optional pointer to the table to start the
  719. search from.
  720. Return Value:
  721. Returns a pointer to the beginning of the header to the table if the table
  722. was found, or NULL if the table could not be located.
  723. --*/
  724. {
  725. PDESCRIPTION_HEADER Table;
  726. PVOID *TableEntry;
  727. LONG TableIndex;
  728. //
  729. // Return NULL if someone is asking for firmware tables before they're
  730. // set up.
  731. //
  732. if (BoFirmwareTables == NULL) {
  733. return NULL;
  734. }
  735. //
  736. // Search the list of pointers, but do it backwards. This runs on the
  737. // assumption that if there are two tables in the firmware, the later one
  738. // is the better one. It also allows the test tables to override existing
  739. // firmware tables.
  740. //
  741. TableEntry = (PVOID *)(BoFirmwareTables + 1);
  742. for (TableIndex = BoFirmwareTables->TableCount - 1;
  743. TableIndex >= 0;
  744. TableIndex -= 1) {
  745. Table = (PDESCRIPTION_HEADER)(TableEntry[TableIndex]);
  746. //
  747. // If the caller searched with a previous table, skip anything up to
  748. // and including that table.
  749. //
  750. if (PreviousTable != NULL) {
  751. if (Table == PreviousTable) {
  752. PreviousTable = NULL;
  753. }
  754. continue;
  755. }
  756. if (Table->Signature == Signature) {
  757. return Table;
  758. }
  759. }
  760. return NULL;
  761. }
  762. KSTATUS
  763. BoAddFirmwareTable (
  764. PKERNEL_INITIALIZATION_BLOCK KernelParameters,
  765. PVOID Table
  766. )
  767. /*++
  768. Routine Description:
  769. This routine adds a firmware configuration table to the loader's list of
  770. tables.
  771. Arguments:
  772. KernelParameters - Supplies a pointer to the kernel initialization
  773. parameters.
  774. Table - Supplies a pointer to the table to add.
  775. Return Value:
  776. STATUS_SUCCESS on success.
  777. STATUS_INSUFFICIENT_RESOURCES on allocation failure.
  778. STATUS_TOO_EARLY if firmware tables are not yet available.
  779. --*/
  780. {
  781. UINTN AllocationSize;
  782. PVOID NewAllocation;
  783. ULONG NewCount;
  784. PVOID *Tables;
  785. if (BoFirmwareTables == NULL) {
  786. return STATUS_TOO_EARLY;
  787. }
  788. //
  789. // Reallocate the loader's array.
  790. //
  791. NewCount = BoFirmwareTables->TableCount + 1;
  792. AllocationSize = sizeof(FIRMWARE_TABLE_DIRECTORY) +
  793. (NewCount * sizeof(PVOID));
  794. NewAllocation = BoAllocateMemory(AllocationSize);
  795. if (NewAllocation == NULL) {
  796. return STATUS_INSUFFICIENT_RESOURCES;
  797. }
  798. RtlCopyMemory(NewAllocation,
  799. BoFirmwareTables,
  800. AllocationSize - sizeof(PVOID));
  801. BoFreeMemory(BoFirmwareTables);
  802. BoFirmwareTables = NewAllocation;
  803. Tables = (PVOID *)(BoFirmwareTables + 1);
  804. Tables[NewCount - 1] = Table;
  805. BoFirmwareTables->TableCount = NewCount;
  806. //
  807. // Reallocate the kernel's array.
  808. //
  809. ASSERT(KernelParameters->FirmwareTables->TableCount + 1 ==
  810. BoFirmwareTables->TableCount);
  811. NewAllocation = BoAllocateMemory(AllocationSize);
  812. if (NewAllocation == NULL) {
  813. return STATUS_INSUFFICIENT_RESOURCES;
  814. }
  815. RtlCopyMemory(NewAllocation,
  816. KernelParameters->FirmwareTables,
  817. AllocationSize - sizeof(PVOID));
  818. BoFreeMemory(KernelParameters->FirmwareTables);
  819. KernelParameters->FirmwareTables = NewAllocation;
  820. Tables = (PVOID *)(KernelParameters->FirmwareTables + 1);
  821. Tables[NewCount - 1] = Table;
  822. KernelParameters->FirmwareTables->TableCount = NewCount;
  823. return STATUS_SUCCESS;
  824. }
  825. PVOID
  826. BoExpandHeap (
  827. PMEMORY_HEAP Heap,
  828. UINTN Size,
  829. UINTN Tag
  830. )
  831. /*++
  832. Routine Description:
  833. This routine is called when the heap wants to expand and get more space.
  834. Arguments:
  835. Heap - Supplies a pointer to the heap to allocate from.
  836. Size - Supplies the size of the allocation request, in bytes.
  837. Tag - Supplies a 32-bit tag to associate with this allocation for debugging
  838. purposes. These are usually four ASCII characters so as to stand out
  839. when a poor developer is looking at a raw memory dump. It could also be
  840. a return address.
  841. Return Value:
  842. Returns a pointer to the allocation if successful, or NULL if the
  843. allocation failed.
  844. --*/
  845. {
  846. ULONG AllocationSize;
  847. ULONG PageSize;
  848. PHYSICAL_ADDRESS PhysicalAddress;
  849. PVOID PhysicalPointer;
  850. KSTATUS Status;
  851. PVOID VirtualAddress;
  852. PhysicalPointer = NULL;
  853. if (Size == 0) {
  854. return NULL;
  855. }
  856. PageSize = MmPageSize();
  857. //
  858. // Attempt to allocate new pages to satisfy the allocation.
  859. //
  860. AllocationSize = ALIGN_RANGE_UP(Size, PageSize);
  861. Status = FwAllocatePages(&PhysicalAddress,
  862. AllocationSize,
  863. PageSize,
  864. MemoryTypeLoaderTemporary);
  865. if (!KSUCCESS(Status)) {
  866. goto ExpandHeapEnd;
  867. }
  868. //
  869. // Identity map those pages into kernel address space.
  870. //
  871. ASSERT((UINTN)PhysicalAddress == PhysicalAddress);
  872. VirtualAddress = (PVOID)(UINTN)PhysicalAddress;
  873. Status = BoMapPhysicalAddress(&VirtualAddress,
  874. PhysicalAddress,
  875. AllocationSize,
  876. 0,
  877. MemoryTypeLoaderTemporary);
  878. if (!KSUCCESS(Status)) {
  879. goto ExpandHeapEnd;
  880. }
  881. PhysicalPointer = (PVOID)(UINTN)PhysicalAddress;
  882. ExpandHeapEnd:
  883. return PhysicalPointer;
  884. }
  885. //
  886. // --------------------------------------------------------- Internal Functions
  887. //
  888. KSTATUS
  889. BopMapAcpiTables (
  890. PMEMORY_DESCRIPTOR_LIST MemoryMap,
  891. PBOOT_VOLUME BootDevice,
  892. FILE_ID ConfigurationDirectory,
  893. PFIRMWARE_TABLE_DIRECTORY *FirmwareTables
  894. )
  895. /*++
  896. Routine Description:
  897. This routine maps any areas mentioned by the BIOS as ACPI tables into
  898. kernel address space.
  899. Arguments:
  900. MemoryMap - Supplies a pointer to the physical memory map.
  901. BootDevice - Supplies a pointer to the boot device.
  902. ConfigurationDirectory - Supplies the file ID of the configuration
  903. directory.
  904. FirmwareTables - Supplies a pointer to the firwmare table list.
  905. Return Value:
  906. Status code.
  907. --*/
  908. {
  909. LOADER_ACPI_MEMORY_ITERATOR AcpiContext;
  910. ULONG AllocationSize;
  911. PVOID *BootTableEntry;
  912. PDESCRIPTION_HEADER DsdtTable;
  913. PFADT FadtTable;
  914. PDESCRIPTION_HEADER Header;
  915. PVOID NewTable;
  916. PRSDP RsdpTable;
  917. PRSDT RsdtTable;
  918. ULONG RsdtTableCount;
  919. PULONG RsdtTableEntry;
  920. PSMBIOS_ENTRY_POINT SmbiosTable;
  921. KSTATUS Status;
  922. ULONG TableCount;
  923. PFIRMWARE_TABLE_DIRECTORY TableDirectory;
  924. PVOID *TableEntry;
  925. ULONG TableIndex;
  926. ULONG TestTablesExaminedBytes;
  927. PVOID TestTablesPhysical;
  928. UINTN TestTablesSize;
  929. PVOID TestTablesVirtual;
  930. DsdtTable = NULL;
  931. FadtTable = NULL;
  932. RsdtTable = NULL;
  933. RsdtTableCount = 0;
  934. RsdtTableEntry = NULL;
  935. TableCount = 0;
  936. TableDirectory = NULL;
  937. TestTablesPhysical = NULL;
  938. //
  939. // Locate the RSDP.
  940. //
  941. RsdpTable = FwFindRsdp();
  942. if (RsdpTable != NULL) {
  943. //
  944. // Use the RSDP to locate the RSDT, and count the number of tables in
  945. // the RSDT.
  946. //
  947. RsdtTable = (PRSDT)(UINTN)RsdpTable->RsdtAddress;
  948. RsdtTableCount = (RsdtTable->Header.Length -
  949. sizeof(DESCRIPTION_HEADER)) / sizeof(ULONG);
  950. if (RsdtTableCount == 0) {
  951. Status = STATUS_INVALID_DIRECTORY;
  952. goto MapAcpiTablesEnd;
  953. }
  954. RsdtTableEntry = (PULONG)&(RsdtTable->Entries);
  955. //
  956. // Add one slot for the DSDT, whose pointer is buried in the FADT table.
  957. //
  958. TableCount = RsdtTableCount + 1;
  959. //
  960. // Attempt to find the FADT and use that to locate the DSDT physical
  961. // address.
  962. //
  963. for (TableIndex = 0; TableIndex < RsdtTableCount; TableIndex += 1) {
  964. FadtTable = (PFADT)(UINTN)RsdtTableEntry[TableIndex];
  965. if (FadtTable->Header.Signature == FADT_SIGNATURE) {
  966. DsdtTable = (PDESCRIPTION_HEADER)(UINTN)FadtTable->DsdtAddress;
  967. if ((DsdtTable != NULL) &&
  968. (DsdtTable->Signature == DSDT_SIGNATURE)) {
  969. break;
  970. } else {
  971. DsdtTable = NULL;
  972. }
  973. }
  974. }
  975. }
  976. //
  977. // Attempt to load the test firmware file.
  978. //
  979. Status = BoLoadAndMapFile(BootDevice,
  980. &ConfigurationDirectory,
  981. FIRMWARE_TABLES_FILE,
  982. &TestTablesPhysical,
  983. &TestTablesVirtual,
  984. &TestTablesSize,
  985. MemoryTypeLoaderTemporary);
  986. //
  987. // Failure is expected here. If it actually succeeded, count the number
  988. // of tables in the blob. Tables are expected to be contiguous and
  989. // properly checksummed.
  990. //
  991. if (KSUCCESS(Status)) {
  992. TestTablesExaminedBytes = 0;
  993. Header = (PDESCRIPTION_HEADER)TestTablesPhysical;
  994. while (TestTablesExaminedBytes + sizeof(DESCRIPTION_HEADER) <=
  995. TestTablesSize) {
  996. TableCount += 1;
  997. TestTablesExaminedBytes += Header->Length;
  998. Header = (PDESCRIPTION_HEADER)((PUCHAR)Header + Header->Length);
  999. }
  1000. } else {
  1001. TestTablesPhysical = NULL;
  1002. TestTablesSize = 0;
  1003. }
  1004. //
  1005. // If there are no tables at all, fail.
  1006. //
  1007. if (TableCount == 0) {
  1008. RtlDebugPrint("Error: No firmware tables found!\n");
  1009. Status = STATUS_NOT_SUPPORTED;
  1010. goto MapAcpiTablesEnd;
  1011. }
  1012. //
  1013. // Add one for the SMBIOS table.
  1014. //
  1015. SmbiosTable = FwFindSmbiosTable();
  1016. if (SmbiosTable != NULL) {
  1017. TableCount += 1;
  1018. }
  1019. //
  1020. // Allocate the firmware table directory.
  1021. //
  1022. AllocationSize = sizeof(FIRMWARE_TABLE_DIRECTORY) +
  1023. (TableCount * sizeof(PVOID));
  1024. TableDirectory = BoAllocateMemory(AllocationSize);
  1025. if (TableDirectory == NULL) {
  1026. Status = STATUS_INSUFFICIENT_RESOURCES;
  1027. goto MapAcpiTablesEnd;
  1028. }
  1029. RtlZeroMemory(TableDirectory, AllocationSize);
  1030. //
  1031. // Allocate the loader's version of the same thing.
  1032. //
  1033. BoFirmwareTables = BoAllocateMemory(AllocationSize);
  1034. if (BoFirmwareTables == NULL) {
  1035. Status = STATUS_INSUFFICIENT_RESOURCES;
  1036. goto MapAcpiTablesEnd;
  1037. }
  1038. RtlZeroMemory(BoFirmwareTables, AllocationSize);
  1039. //
  1040. // Map every descriptor in the memory map marked as an ACPI table.
  1041. //
  1042. TableEntry = (PVOID *)(TableDirectory + 1);
  1043. BootTableEntry = (PVOID *)(BoFirmwareTables + 1);
  1044. RtlZeroMemory(&AcpiContext, sizeof(LOADER_ACPI_MEMORY_ITERATOR));
  1045. AcpiContext.RsdtTableEntry = RsdtTableEntry;
  1046. AcpiContext.RsdtTableCount = RsdtTableCount;
  1047. AcpiContext.TableEntry = TableEntry;
  1048. AcpiContext.BootTableEntry = BootTableEntry;
  1049. AcpiContext.TableDirectory = TableDirectory;
  1050. AcpiContext.DsdtTable = DsdtTable;
  1051. AcpiContext.Status = STATUS_SUCCESS;
  1052. MmMdIterate(MemoryMap, BopAcpiMemoryIteratorRoutine, &AcpiContext);
  1053. if (!KSUCCESS(AcpiContext.Status)) {
  1054. goto MapAcpiTablesEnd;
  1055. }
  1056. //
  1057. // If there are test tables, add them to the list.
  1058. //
  1059. if (TestTablesSize != 0) {
  1060. //
  1061. // Loop through the tables in the file.
  1062. //
  1063. TestTablesExaminedBytes = 0;
  1064. Header = (PDESCRIPTION_HEADER)TestTablesPhysical;
  1065. while (TestTablesExaminedBytes + sizeof(DESCRIPTION_HEADER) <=
  1066. TestTablesSize) {
  1067. TableEntry[TableDirectory->TableCount] =
  1068. (PVOID)(TestTablesVirtual + ((UINTN)Header -
  1069. (UINTN)TestTablesPhysical));
  1070. TableDirectory->TableCount += 1;
  1071. TestTablesExaminedBytes += Header->Length;
  1072. BootTableEntry[BoFirmwareTables->TableCount] = Header;
  1073. BoFirmwareTables->TableCount += 1;
  1074. Header = (PDESCRIPTION_HEADER)((PUCHAR)Header + Header->Length);
  1075. }
  1076. }
  1077. //
  1078. // If there's an SMBIOS table, then copy it to a single buffer and tack
  1079. // that on as well.
  1080. //
  1081. if (SmbiosTable != NULL) {
  1082. AllocationSize = sizeof(SMBIOS_ENTRY_POINT) +
  1083. SmbiosTable->StructureTableLength;
  1084. NewTable = BoAllocateMemory(AllocationSize);
  1085. if (NewTable == NULL) {
  1086. Status = STATUS_INSUFFICIENT_RESOURCES;
  1087. goto MapAcpiTablesEnd;
  1088. }
  1089. RtlCopyMemory(NewTable, SmbiosTable, sizeof(SMBIOS_ENTRY_POINT));
  1090. RtlCopyMemory(NewTable + sizeof(SMBIOS_ENTRY_POINT),
  1091. (PVOID)(UINTN)(SmbiosTable->StructureTableAddress),
  1092. SmbiosTable->StructureTableLength);
  1093. TableEntry[TableDirectory->TableCount] = NewTable;
  1094. TableDirectory->TableCount += 1;
  1095. BootTableEntry[BoFirmwareTables->TableCount] = NewTable;
  1096. BoFirmwareTables->TableCount += 1;
  1097. }
  1098. Status = STATUS_SUCCESS;
  1099. MapAcpiTablesEnd:
  1100. if (!KSUCCESS(Status)) {
  1101. if (TableDirectory != NULL) {
  1102. BoFreeMemory(TableDirectory);
  1103. TableDirectory = NULL;
  1104. }
  1105. }
  1106. *FirmwareTables = TableDirectory;
  1107. return Status;
  1108. }
  1109. VOID
  1110. BopAcpiMemoryIteratorRoutine (
  1111. PMEMORY_DESCRIPTOR_LIST DescriptorList,
  1112. PMEMORY_DESCRIPTOR Descriptor,
  1113. PVOID Context
  1114. )
  1115. /*++
  1116. Routine Description:
  1117. This routine is called once for each descriptor in the memory descriptor
  1118. list.
  1119. Arguments:
  1120. DescriptorList - Supplies a pointer to the descriptor list being iterated
  1121. over.
  1122. Descriptor - Supplies a pointer to the current descriptor.
  1123. Context - Supplies an optional opaque pointer of context that was provided
  1124. when the iteration was requested.
  1125. Return Value:
  1126. None.
  1127. --*/
  1128. {
  1129. PLOADER_ACPI_MEMORY_ITERATOR AcpiContext;
  1130. KSTATUS Status;
  1131. PFIRMWARE_TABLE_DIRECTORY TableDirectory;
  1132. UINTN TableIndex;
  1133. PVOID VirtualAddress;
  1134. AcpiContext = Context;
  1135. TableDirectory = AcpiContext->TableDirectory;
  1136. if ((Descriptor->Type == MemoryTypeAcpiTables) ||
  1137. (Descriptor->Type == MemoryTypeAcpiNvStorage) ||
  1138. (Descriptor->Type == MemoryTypeFirmwarePermanent)) {
  1139. VirtualAddress = (PVOID)-1;
  1140. //
  1141. // Loop through each table in the RSDT. If its pointer corresponds
  1142. // to the range just mapped, copy the virtual address equivalent
  1143. // into the next slot of the firmware table.
  1144. //
  1145. for (TableIndex = 0;
  1146. TableIndex < AcpiContext->RsdtTableCount;
  1147. TableIndex += 1) {
  1148. if ((AcpiContext->RsdtTableEntry[TableIndex] >=
  1149. Descriptor->BaseAddress) &&
  1150. (AcpiContext->RsdtTableEntry[TableIndex] <
  1151. Descriptor->BaseAddress + Descriptor->Size)) {
  1152. //
  1153. // If the descriptor has not yet been mapped, map that
  1154. // sucker now.
  1155. //
  1156. if (VirtualAddress == (PVOID)-1) {
  1157. Status = BoMapPhysicalAddress(&VirtualAddress,
  1158. Descriptor->BaseAddress,
  1159. Descriptor->Size,
  1160. MAP_FLAG_READ_ONLY,
  1161. Descriptor->Type);
  1162. if (!KSUCCESS(Status)) {
  1163. AcpiContext->Status = Status;
  1164. return;
  1165. }
  1166. }
  1167. AcpiContext->TableEntry[TableDirectory->TableCount] =
  1168. (PVOID)(VirtualAddress +
  1169. (AcpiContext->RsdtTableEntry[TableIndex] -
  1170. Descriptor->BaseAddress));
  1171. TableDirectory->TableCount += 1;
  1172. AcpiContext->BootTableEntry[BoFirmwareTables->TableCount] =
  1173. (PVOID)(UINTN)(AcpiContext->RsdtTableEntry[TableIndex]);
  1174. BoFirmwareTables->TableCount += 1;
  1175. }
  1176. }
  1177. //
  1178. // Check to see if the DSDT is in this region.
  1179. //
  1180. if ((AcpiContext->DsdtTable != NULL) &&
  1181. ((UINTN)(AcpiContext->DsdtTable) >= Descriptor->BaseAddress) &&
  1182. ((UINTN)(AcpiContext->DsdtTable) <
  1183. Descriptor->BaseAddress + Descriptor->Size)) {
  1184. //
  1185. // Again, map it if it has not been mapped yet.
  1186. //
  1187. if (VirtualAddress == (PVOID)-1) {
  1188. Status = BoMapPhysicalAddress(&VirtualAddress,
  1189. Descriptor->BaseAddress,
  1190. Descriptor->Size,
  1191. MAP_FLAG_READ_ONLY,
  1192. Descriptor->Type);
  1193. if (!KSUCCESS(Status)) {
  1194. AcpiContext->Status = Status;
  1195. return;
  1196. }
  1197. }
  1198. AcpiContext->TableEntry[TableDirectory->TableCount] =
  1199. (PVOID)(VirtualAddress + ((UINTN)(AcpiContext->DsdtTable) -
  1200. Descriptor->BaseAddress));
  1201. TableDirectory->TableCount += 1;
  1202. AcpiContext->BootTableEntry[BoFirmwareTables->TableCount] =
  1203. (PVOID)(UINTN)(AcpiContext->DsdtTable);
  1204. BoFirmwareTables->TableCount += 1;
  1205. AcpiContext->DsdtTable = NULL;
  1206. }
  1207. }
  1208. return;
  1209. }
  1210. KSTATUS
  1211. BopLoadDrivers (
  1212. PLOADER_BUFFER BootDriverFile
  1213. )
  1214. /*++
  1215. Routine Description:
  1216. This routine loads all boot drivers.
  1217. Arguments:
  1218. BootDriverFile - Supplies a pointer to the buffer specifying a
  1219. newline-delimited list of drivers that should be loaded at boot.
  1220. Return Value:
  1221. Status code.
  1222. --*/
  1223. {
  1224. PSTR DriverName;
  1225. ULONG LoadFlags;
  1226. PSTR NewLine;
  1227. KSTATUS Status;
  1228. PSTR StringEnd;
  1229. ULONG StringLength;
  1230. StringEnd = (PSTR)(BootDriverFile->Buffer) + BootDriverFile->Size;
  1231. DriverName = (PSTR)(BootDriverFile->Buffer);
  1232. StringLength = BootDriverFile->Size;
  1233. while (TRUE) {
  1234. //
  1235. // Find the next newline character. Assume that the file itself is
  1236. // NULL terminated.
  1237. //
  1238. NewLine = RtlStringFindCharacter(DriverName, '\n', StringLength);
  1239. if (NewLine != NULL) {
  1240. //
  1241. // If it's just one or two away, this is a blank line. Skip it. If
  1242. // this was the last line, stop.
  1243. //
  1244. if ((UINTN)NewLine - (UINTN)DriverName < 2) {
  1245. if (NewLine + 1 == StringEnd) {
  1246. break;
  1247. }
  1248. StringLength -= (UINTN)((NewLine + 1) - DriverName);
  1249. DriverName = NewLine + 1;
  1250. continue;
  1251. }
  1252. //
  1253. // Terminate the string. Watch out for CRs immediately before this.
  1254. //
  1255. if (*(NewLine - 1) == '\r') {
  1256. *(NewLine - 1) = '\0';
  1257. } else {
  1258. *NewLine = '\0';
  1259. }
  1260. }
  1261. RtlDebugPrint("Driver: %s\n", DriverName);
  1262. //
  1263. // Load the driver.
  1264. //
  1265. LoadFlags = IMAGE_LOAD_FLAG_IGNORE_INTERPRETER |
  1266. IMAGE_LOAD_FLAG_NO_STATIC_CONSTRUCTORS |
  1267. IMAGE_LOAD_FLAG_BIND_NOW |
  1268. IMAGE_LOAD_FLAG_GLOBAL;
  1269. Status = ImLoad(&BoLoadedImageList,
  1270. DriverName,
  1271. NULL,
  1272. NULL,
  1273. NULL,
  1274. LoadFlags,
  1275. NULL,
  1276. NULL);
  1277. if (!KSUCCESS(Status)) {
  1278. goto LoadDriversEnd;
  1279. }
  1280. //
  1281. // If this was the last string, stop now.
  1282. //
  1283. if ((NewLine == NULL) || (NewLine == StringEnd) ||
  1284. (NewLine + 1 == StringEnd)) {
  1285. break;
  1286. }
  1287. //
  1288. // Advance the string to the next driver.
  1289. //
  1290. StringLength -= (ULONG)((NewLine + 1) - DriverName);
  1291. DriverName = NewLine + 1;
  1292. }
  1293. Status = STATUS_SUCCESS;
  1294. LoadDriversEnd:
  1295. if (!KSUCCESS(Status) && DriverName != NULL) {
  1296. RtlDebugPrint("Error: Failed to load driver %s (Status %d).\n",
  1297. DriverName,
  1298. Status);
  1299. FwPrintString(0, 2, "Failed to load driver ");
  1300. FwPrintString(22, 2, DriverName);
  1301. }
  1302. return Status;
  1303. }
  1304. KSTATUS
  1305. BopMapNeededHardwareRegions (
  1306. PKERNEL_INITIALIZATION_BLOCK Parameters
  1307. )
  1308. /*++
  1309. Routine Description:
  1310. This routine maps pieces of hardware needed for very early kernel
  1311. initialization.
  1312. Arguments:
  1313. Parameters - Supplies a pointer to the kernel's initialization parameters.
  1314. Return Value:
  1315. Status code.
  1316. --*/
  1317. {
  1318. PLIST_ENTRY CurrentEntry;
  1319. PLIST_ENTRY ListHead;
  1320. KSTATUS Status;
  1321. PHL_PHYSICAL_ADDRESS_USAGE Usage;
  1322. PVOID VirtualAddress;
  1323. //
  1324. // Loop through each of the mapped hardware module physical address usage
  1325. // structures.
  1326. //
  1327. ListHead = BoHlGetPhysicalMemoryUsageListHead();
  1328. CurrentEntry = ListHead->Next;
  1329. while (CurrentEntry != ListHead) {
  1330. Usage = LIST_VALUE(CurrentEntry, HL_PHYSICAL_ADDRESS_USAGE, ListEntry);
  1331. CurrentEntry = CurrentEntry->Next;
  1332. //
  1333. // Identity map the space to a kernel address.
  1334. //
  1335. VirtualAddress = (PVOID)(UINTN)Usage->PhysicalAddress;
  1336. Status = BoMapPhysicalAddress(&VirtualAddress,
  1337. Usage->PhysicalAddress,
  1338. Usage->Size,
  1339. MAP_FLAG_CACHE_DISABLE,
  1340. MemoryTypeLoaderTemporary);
  1341. if (!KSUCCESS(Status)) {
  1342. goto MapNeededHardwareRegionsEnd;
  1343. }
  1344. ASSERT((UINTN)VirtualAddress == Usage->PhysicalAddress);
  1345. }
  1346. //
  1347. // Create a memory resource for the hardware module to use during very
  1348. // early initialization (including initialization of the debug device).
  1349. //
  1350. Status = BopAddSystemMemoryResource(Parameters,
  1351. HARDWARE_MODULE_INITIAL_ALLOCATION_SIZE,
  1352. SystemMemoryResourceHardwareModule,
  1353. MAP_FLAG_GLOBAL);
  1354. if (!KSUCCESS(Status)) {
  1355. goto MapNeededHardwareRegionsEnd;
  1356. }
  1357. //
  1358. // Also create a device memory resource.
  1359. //
  1360. Status = BopAddSystemMemoryResource(
  1361. Parameters,
  1362. HARDWARE_MODULE_INITIAL_DEVICE_ALLOCATION_SIZE,
  1363. SystemMemoryResourceHardwareModuleDevice,
  1364. MAP_FLAG_GLOBAL);
  1365. if (!KSUCCESS(Status)) {
  1366. goto MapNeededHardwareRegionsEnd;
  1367. }
  1368. //
  1369. // Map any regions needed by firmware.
  1370. //
  1371. Status = BoFwMapKnownRegions(1, Parameters);
  1372. if (!KSUCCESS(Status)) {
  1373. goto MapNeededHardwareRegionsEnd;
  1374. }
  1375. MapNeededHardwareRegionsEnd:
  1376. return Status;
  1377. }
  1378. KSTATUS
  1379. BopReadBootConfiguration (
  1380. PBOOT_INITIALIZATION_BLOCK Parameters,
  1381. PBOOT_CONFIGURATION_CONTEXT *NewContext,
  1382. PBOOT_ENTRY *BootEntry
  1383. )
  1384. /*++
  1385. Routine Description:
  1386. This routine allocates and initializes a boot configuration context with
  1387. the boot configuration from the given file data.
  1388. Arguments:
  1389. Parameters - Supplies a pointer to the application initialization
  1390. information.
  1391. NewContext - Supplies a pointer where a pointer to the boot configuration
  1392. information will be returned. It is the caller's responsibility to
  1393. destroy this context and free the returned pointer on success.
  1394. BootEntry - Supplies a pointer where a pointer to the selected boot entry
  1395. will be returned on success.
  1396. Return Value:
  1397. Status code.
  1398. --*/
  1399. {
  1400. PBOOT_CONFIGURATION_CONTEXT BootConfiguration;
  1401. PBOOT_ENTRY Entry;
  1402. ULONG EntryIndex;
  1403. BOOL Initialized;
  1404. PBOOT_ENTRY SelectedEntry;
  1405. KSTATUS Status;
  1406. Initialized = FALSE;
  1407. SelectedEntry = NULL;
  1408. BootConfiguration = BoAllocateMemory(sizeof(BOOT_CONFIGURATION_CONTEXT));
  1409. if (BootConfiguration == NULL) {
  1410. Status = STATUS_INSUFFICIENT_RESOURCES;
  1411. goto ReadBootConfigurationEnd;
  1412. }
  1413. RtlZeroMemory(BootConfiguration, sizeof(BOOT_CONFIGURATION_CONTEXT));
  1414. BootConfiguration->AllocateFunction = BoAllocateMemory;
  1415. BootConfiguration->FreeFunction = BoFreeMemory;
  1416. BootConfiguration->FileData =
  1417. (PVOID)(UINTN)(Parameters->BootConfigurationFile);
  1418. BootConfiguration->FileDataSize = Parameters->BootConfigurationFileSize;
  1419. Status = BcInitializeContext(BootConfiguration);
  1420. if (!KSUCCESS(Status)) {
  1421. goto ReadBootConfigurationEnd;
  1422. }
  1423. Initialized = TRUE;
  1424. Status = BcReadBootConfigurationFile(BootConfiguration);
  1425. if (!KSUCCESS(Status)) {
  1426. goto ReadBootConfigurationEnd;
  1427. }
  1428. //
  1429. // Find the selected boot entry.
  1430. //
  1431. for (EntryIndex = 0;
  1432. EntryIndex < BootConfiguration->BootEntryCount;
  1433. EntryIndex += 1) {
  1434. Entry = BootConfiguration->BootEntries[EntryIndex];
  1435. if (Entry->Id == Parameters->BootEntryId) {
  1436. SelectedEntry = Entry;
  1437. break;
  1438. }
  1439. }
  1440. if (SelectedEntry == NULL) {
  1441. Status = STATUS_INVALID_CONFIGURATION;
  1442. goto ReadBootConfigurationEnd;
  1443. }
  1444. ReadBootConfigurationEnd:
  1445. if (!KSUCCESS(Status)) {
  1446. if (BootConfiguration != NULL) {
  1447. if (Initialized != FALSE) {
  1448. BcDestroyContext(BootConfiguration);
  1449. }
  1450. BoFreeMemory(BootConfiguration);
  1451. BootConfiguration = NULL;
  1452. }
  1453. }
  1454. *NewContext = BootConfiguration;
  1455. *BootEntry = SelectedEntry;
  1456. return Status;
  1457. }
  1458. KSTATUS
  1459. BopGetConfigurationDirectory (
  1460. PBOOT_VOLUME BootDevice,
  1461. PFILE_ID DirectoryFileId
  1462. )
  1463. /*++
  1464. Routine Description:
  1465. This routine gets the file ID for the boot configuration directory.
  1466. Arguments:
  1467. BootDevice - Supplies a pointer to the boot device volume.
  1468. DirectoryFileId - Supplies a pointer where the file ID of the directory
  1469. will be returned on success.
  1470. Return Value:
  1471. Status code.
  1472. --*/
  1473. {
  1474. FILE_PROPERTIES Properties;
  1475. KSTATUS Status;
  1476. Status = BoLookupPath(BootDevice,
  1477. &BoSystemDirectoryId,
  1478. CONFIGURATION_DIRECTORY_PATH,
  1479. &Properties);
  1480. if (!KSUCCESS(Status)) {
  1481. return Status;
  1482. }
  1483. *DirectoryFileId = Properties.FileId;
  1484. return STATUS_SUCCESS;
  1485. }
  1486. VOID
  1487. BopSetBootTime (
  1488. PKERNEL_INITIALIZATION_BLOCK Parameters
  1489. )
  1490. /*++
  1491. Routine Description:
  1492. This routine attempts to retrieve the current time from the system and
  1493. set it in the kernel initialization block.
  1494. Arguments:
  1495. Parameters - Supplies a pointer to the kernel initialization block.
  1496. Return Value:
  1497. None, as failure here is not fatal.
  1498. --*/
  1499. {
  1500. KSTATUS Status;
  1501. Status = FwGetCurrentTime(&(Parameters->BootTime));
  1502. if (!KSUCCESS(Status)) {
  1503. RtlZeroMemory(&(Parameters->BootTime), sizeof(SYSTEM_TIME));
  1504. return;
  1505. }
  1506. return;
  1507. }
  1508. KSTATUS
  1509. BopAddSystemMemoryResource (
  1510. PKERNEL_INITIALIZATION_BLOCK Parameters,
  1511. UINTN Size,
  1512. SYSTEM_MEMORY_RESOURCE_TYPE Type,
  1513. ULONG MapFlags
  1514. )
  1515. /*++
  1516. Routine Description:
  1517. This routine adds a system memory resource to the list of system resources
  1518. in the kernel initialization block.
  1519. Arguments:
  1520. Parameters - Supplies a pointer to the kernel initialization block.
  1521. Size - Supplies the requested size of the resource.
  1522. Type - Supplies the type of memory resource to create.
  1523. MapFlags - Supplies the flags to map the memory with.
  1524. Return Value:
  1525. STATUS_SUCCESS on success.
  1526. STATUS_INSUFFICIENT_RESOURCES on allocation failure.
  1527. --*/
  1528. {
  1529. LOADER_BUFFER Buffer;
  1530. PSYSTEM_RESOURCE_MEMORY MemoryResource;
  1531. KSTATUS Status;
  1532. MemoryResource = BoAllocateMemory(sizeof(SYSTEM_RESOURCE_MEMORY));
  1533. if (MemoryResource == NULL) {
  1534. Status = STATUS_INSUFFICIENT_RESOURCES;
  1535. goto AddSystemMemoryResourceEnd;
  1536. }
  1537. RtlZeroMemory(MemoryResource, sizeof(SYSTEM_RESOURCE_MEMORY));
  1538. MemoryResource->Header.Type = SystemResourceMemory;
  1539. MemoryResource->MemoryType = Type;
  1540. MemoryResource->Header.Size = HARDWARE_MODULE_INITIAL_ALLOCATION_SIZE;
  1541. Status = BopAllocateKernelBuffer(Size,
  1542. MapFlags,
  1543. &(MemoryResource->Header.PhysicalAddress),
  1544. &Buffer);
  1545. if (!KSUCCESS(Status)) {
  1546. goto AddSystemMemoryResourceEnd;
  1547. }
  1548. MemoryResource->Header.VirtualAddress = Buffer.Buffer;
  1549. INSERT_BEFORE(&(MemoryResource->Header.ListEntry),
  1550. &(Parameters->SystemResourceListHead));
  1551. AddSystemMemoryResourceEnd:
  1552. if (!KSUCCESS(Status)) {
  1553. if (MemoryResource != NULL) {
  1554. BoFreeMemory(MemoryResource);
  1555. }
  1556. }
  1557. return Status;
  1558. }
  1559. KSTATUS
  1560. BopAddMmInitMemory (
  1561. PKERNEL_INITIALIZATION_BLOCK Parameters
  1562. )
  1563. /*++
  1564. Routine Description:
  1565. This routine allocates and maps the memory that the memory manager uses to
  1566. bootstrap itself.
  1567. Arguments:
  1568. Parameters - Supplies a pointer to the kernel initialization block.
  1569. Return Value:
  1570. STATUS_SUCCESS on success.
  1571. STATUS_INSUFFICIENT_RESOURCES on allocation failure.
  1572. --*/
  1573. {
  1574. UINTN AllocationSize;
  1575. UINTN DescriptorCount;
  1576. ULONG FirmwarePermanentCount;
  1577. ULONG PageShift;
  1578. ULONG PageSize;
  1579. PHYSICAL_ADDRESS PhysicalAddress;
  1580. KSTATUS Status;
  1581. //
  1582. // Determine how many descriptors the final virtual memory map is going to
  1583. // need. This value is the current virtual map, plus any runtime services
  1584. // regions in the physical map (that will get virtualized later).
  1585. //
  1586. DescriptorCount = BoVirtualMap.DescriptorCount +
  1587. FREE_SYSTEM_DESCRIPTORS_REQUIRED_FOR_REFILL;
  1588. FirmwarePermanentCount = 0;
  1589. MmMdIterate(&BoMemoryMap,
  1590. BopMmInitMemoryMapIterationRoutine,
  1591. &FirmwarePermanentCount);
  1592. DescriptorCount += FirmwarePermanentCount;
  1593. PageShift = MmPageShift();
  1594. PageSize = MmPageSize();
  1595. //
  1596. // The memory manager needs space for all the virtual descriptors.
  1597. //
  1598. AllocationSize = DescriptorCount * sizeof(MEMORY_DESCRIPTOR);
  1599. //
  1600. // It also needs a word for each physical page, plus an extra page for the
  1601. // physical memory segments.
  1602. // Note: if the loader continues to be 32-bit for a 64-bit kernel, then
  1603. // this ULONG calculation is off.
  1604. //
  1605. AllocationSize += sizeof(UINTN) * (BoMemoryMap.TotalSpace >> PageShift);
  1606. AllocationSize += PageSize;
  1607. AllocationSize = ALIGN_RANGE_UP(AllocationSize, PageSize);
  1608. Status = BopAllocateKernelBuffer(AllocationSize,
  1609. MAP_FLAG_GLOBAL,
  1610. &PhysicalAddress,
  1611. &(Parameters->MmInitMemory));
  1612. if (!KSUCCESS(Status)) {
  1613. return Status;
  1614. }
  1615. Parameters->MmInitMemory.Size = AllocationSize;
  1616. return Status;
  1617. }
  1618. VOID
  1619. BopMmInitMemoryMapIterationRoutine (
  1620. PMEMORY_DESCRIPTOR_LIST DescriptorList,
  1621. PMEMORY_DESCRIPTOR Descriptor,
  1622. PVOID Context
  1623. )
  1624. /*++
  1625. Routine Description:
  1626. This routine is called once for each descriptor in the physical memory map.
  1627. Arguments:
  1628. DescriptorList - Supplies a pointer to the descriptor list being iterated
  1629. over.
  1630. Descriptor - Supplies a pointer to the current descriptor.
  1631. Context - Supplies a context pointer, which in this case just points to a
  1632. count of how many firmware permanent descriptors were seen.
  1633. Return Value:
  1634. None.
  1635. --*/
  1636. {
  1637. PULONG Count;
  1638. Count = Context;
  1639. if (Descriptor->Type == MemoryTypeFirmwarePermanent) {
  1640. *Count += 1;
  1641. }
  1642. return;
  1643. }
  1644. KSTATUS
  1645. BopAllocateKernelBuffer (
  1646. UINTN Size,
  1647. ULONG MapFlags,
  1648. PPHYSICAL_ADDRESS PhysicalAddress,
  1649. PLOADER_BUFFER BufferOut
  1650. )
  1651. /*++
  1652. Routine Description:
  1653. This routine allocates and maps a memory of region for the kernel.
  1654. Arguments:
  1655. Size - Supplies the requested size of the resource.
  1656. MapFlags - Supplies the flags to map the memory with.
  1657. PhysicalAddress - Supplies a pointer where the physical address of the
  1658. allocation will be returned.
  1659. BufferOut - Supplies a pointer where the buffer virtual address and size
  1660. will be returned.
  1661. Return Value:
  1662. STATUS_SUCCESS on success.
  1663. STATUS_INSUFFICIENT_RESOURCES on allocation failure.
  1664. --*/
  1665. {
  1666. KSTATUS Status;
  1667. Status = FwAllocatePages(PhysicalAddress,
  1668. Size,
  1669. 0,
  1670. MemoryTypeLoaderPermanent);
  1671. if (!KSUCCESS(Status)) {
  1672. goto AllocateKernelBufferEnd;
  1673. }
  1674. BufferOut->Buffer = (PVOID)-1;
  1675. Status = BoMapPhysicalAddress(&(BufferOut->Buffer),
  1676. *PhysicalAddress,
  1677. Size,
  1678. MapFlags,
  1679. MemoryTypeLoaderPermanent);
  1680. if (!KSUCCESS(Status)) {
  1681. goto AllocateKernelBufferEnd;
  1682. }
  1683. AllocateKernelBufferEnd:
  1684. return Status;
  1685. }