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

3562 lines
98 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. osloader.c
  5. Abstract:
  6. This module contains the code that implements the NT operating system
  7. loader.
  8. Author:
  9. David N. Cutler (davec) 10-May-1991
  10. Revision History:
  11. --*/
  12. #include "bldr.h"
  13. #include "bldrint.h"
  14. #include "ctype.h"
  15. #include "stdlib.h"
  16. #include "stdio.h"
  17. #include "string.h"
  18. #include "msg.h"
  19. #include "cmp.h"
  20. #include "ramdisk.h"
  21. #include "cpyuchr.h"
  22. #include "fat.h"
  23. #include <netboot.h>
  24. #include <ntverp.h>
  25. #include <ntiodump.h>
  26. #ifdef i386
  27. #include "bldrx86.h"
  28. #endif
  29. #if defined(_IA64_)
  30. #include "bldria64.h"
  31. #endif
  32. #include "blcache.h"
  33. #include "vmode.h"
  34. #include "ximagdef.h"
  35. #define PAGEFILE_SYS ("\\pagefile.sys")
  36. typedef PUCHAR PBYTE;
  37. #if defined(_WIN64) && defined(_M_IA64)
  38. #pragma section(".base", long, read, write)
  39. __declspec(allocate(".base"))
  40. extern
  41. PVOID __ImageBase;
  42. #else
  43. extern
  44. PVOID __ImageBase;
  45. #endif
  46. #if DBG
  47. #define NtBuildNumber (VER_PRODUCTBUILD | 0xC0000000)
  48. #else
  49. #define NtBuildNumber (VER_PRODUCTBUILD | 0xF0000000)
  50. #endif
  51. //
  52. // These are the paths we will search through during a LastKnownGood boot.
  53. // Note that each LastKnownGood path must be of 8.3 form as the FastFat
  54. // boot code currently doesn't support long file names (bletch).
  55. //
  56. // The temporary path exists only between SMSS's start and login. It contains
  57. // everything that was saved as part of the last good boot. The working path
  58. // contains all the backups from this boot, and is the path SetupApi saves
  59. // things to.
  60. //
  61. #define LAST_KNOWN_GOOD_TEMPORARY_PATH "LastGood.Tmp"
  62. #define LAST_KNOWN_GOOD_WORKING_PATH "LastGood"
  63. //
  64. // Long term work-item, make "system64" work on Win64.
  65. //
  66. #define SYSTEM_DIRECTORY_PATH "system32"
  67. #ifdef ARCI386
  68. TCHAR OutputBuffer[256];
  69. char BreakInKey;
  70. ULONG Count;
  71. UCHAR OsLoaderVersion[] = "ARCx86 OS Loader V5.20\r\n";
  72. WCHAR OsLoaderVersionW[] = L"ARCx86 OS Loader V5.20\r\n";
  73. #else
  74. UCHAR OsLoaderVersion[] = "OS Loader V5.20\r\n";
  75. WCHAR OsLoaderVersionW[] = L"OS Loader V5.20\r\n";
  76. #endif
  77. #if defined(_IA64_)
  78. UCHAR OsLoaderName[] = "ia64ldr.efi";
  79. #else
  80. UCHAR OsLoaderName[] = "osloader.exe";
  81. #endif
  82. CHAR KernelFileName[8+1+3+1]="ntoskrnl.exe";
  83. CHAR HalFileName[8+1+3+1]="hal.dll";
  84. CHAR KdFileName[8+1+3+1]="KDCOM.DLL";
  85. BOOLEAN UseAlternateKdDll = FALSE;
  86. #define KD_ALT_DLL_PREFIX_CHARS 2
  87. #define KD_ALT_DLL_REPLACE_CHARS 6
  88. //
  89. // progress bar variables (defined in blload.c)
  90. //
  91. extern int BlNumFilesLoaded;
  92. extern int BlMaxFilesToLoad;
  93. extern BOOLEAN BlOutputDots;
  94. extern BOOLEAN BlShowProgressBar;
  95. extern ULONG BlStartTime;
  96. BOOLEAN isOSCHOICE = FALSE;
  97. #if defined(_X86_)
  98. //
  99. // XIP variables
  100. //
  101. BOOLEAN XIPEnabled;
  102. BOOLEAN XIPBootFlag;
  103. BOOLEAN XIPReadOnlyFlag;
  104. PCHAR XIPLoadPath;
  105. PFN_COUNT XIPPageCount;
  106. PFN_COUNT XIPBasePage;
  107. ARC_STATUS
  108. Blx86CheckForPaeKernel(
  109. IN BOOLEAN UserSpecifiedPae,
  110. IN BOOLEAN UserSpecifiedNoPae,
  111. IN PCHAR UserSpecifiedKernelImage,
  112. IN PCHAR HalImagePath,
  113. IN ULONG LoadDeviceId,
  114. IN ULONG SystemDeviceId,
  115. OUT PULONG HighestSystemPage,
  116. OUT PBOOLEAN UsePaeMode,
  117. IN OUT PCHAR KernelPath
  118. );
  119. ARC_STATUS
  120. BlpCheckVersion(
  121. IN ULONG LoadDeviceId,
  122. IN PCHAR ImagePath
  123. );
  124. #endif
  125. //
  126. // Define transfer entry of loaded image.
  127. //
  128. typedef
  129. VOID
  130. (*PTRANSFER_ROUTINE) (
  131. PLOADER_PARAMETER_BLOCK LoaderBlock
  132. );
  133. PVOID
  134. BlLoadDataFile(
  135. IN ULONG DeviceId,
  136. IN PCHAR LoadDevice,
  137. IN PCHAR SystemPath,
  138. IN PUNICODE_STRING Filename,
  139. IN MEMORY_TYPE MemoryType,
  140. OUT PULONG FileSize
  141. );
  142. ARC_STATUS
  143. BlLoadTriageDump(
  144. IN ULONG DriveId,
  145. OUT PVOID * DumpHeader
  146. );
  147. VOID
  148. putwS(
  149. PUNICODE_STRING String
  150. );
  151. #if defined(_X86_)
  152. BOOLEAN
  153. BlAmd64RemapDram (
  154. IN PCHAR LoaderOptions
  155. );
  156. #endif
  157. #if defined(_IA64_)
  158. VOID
  159. BuildArcTree();
  160. #endif // defined(_IA64_)
  161. //
  162. // Define local static data.
  163. //
  164. PCHAR ArcStatusCodeMessages[] = {
  165. "operation was success",
  166. "E2BIG",
  167. "EACCES",
  168. "EAGAIN",
  169. "EBADF",
  170. "EBUSY",
  171. "EFAULT",
  172. "EINVAL",
  173. "EIO",
  174. "EISDIR",
  175. "EMFILE",
  176. "EMLINK",
  177. "ENAMETOOLONG",
  178. "ENODEV",
  179. "ENOENT",
  180. "ENOEXEC",
  181. "ENOMEM",
  182. "ENOSPC",
  183. "ENOTDIR",
  184. "ENOTTY",
  185. "ENXIO",
  186. "EROFS",
  187. };
  188. //
  189. // Diagnostic load messages
  190. //
  191. VOID
  192. BlFatalError(
  193. IN ULONG ClassMessage,
  194. IN ULONG DetailMessage,
  195. IN ULONG ActionMessage
  196. );
  197. VOID
  198. BlBadFileMessage(
  199. IN PCHAR BadFileName
  200. );
  201. //
  202. // Define external static data.
  203. //
  204. BOOLEAN BlConsoleInitialized = FALSE;
  205. ULONG BlConsoleOutDeviceId = ARC_CONSOLE_OUTPUT;
  206. ULONG BlConsoleInDeviceId = ARC_CONSOLE_INPUT;
  207. ULONG BlDcacheFillSize = 32;
  208. BOOLEAN BlRebootSystem = FALSE;
  209. ULONG BlVirtualBias = 0;
  210. BOOLEAN BlUsePae = FALSE;
  211. //++
  212. //
  213. // PULONG
  214. // IndexByUlong(
  215. // PVOID Pointer,
  216. // ULONG Index
  217. // )
  218. //
  219. // Routine Description:
  220. //
  221. // Return the address Index ULONGs into Pointer. That is,
  222. // Index * sizeof (ULONG) bytes into Pointer.
  223. //
  224. // Arguments:
  225. //
  226. // Pointer - Start of region.
  227. //
  228. // Index - Number of ULONGs to index into.
  229. //
  230. // Return Value:
  231. //
  232. // PULONG representing the pointer described above.
  233. //
  234. //--
  235. #define IndexByUlong(Pointer,Index) (&(((ULONG*) (Pointer)) [Index]))
  236. //++
  237. //
  238. // PBYTE
  239. // IndexByByte(
  240. // PVOID Pointer,
  241. // ULONG Index
  242. // )
  243. //
  244. // Routine Description:
  245. //
  246. // Return the address Index BYTEs into Pointer. That is,
  247. // Index * sizeof (BYTE) bytes into Pointer.
  248. //
  249. // Arguments:
  250. //
  251. // Pointer - Start of region.
  252. //
  253. // Index - Number of BYTEs to index into.
  254. //
  255. // Return Value:
  256. //
  257. // PBYTE representing the pointer described above.
  258. //
  259. //--
  260. #define IndexByByte(Pointer, Index) (&(((UCHAR*) (Pointer)) [Index]))
  261. ARC_STATUS
  262. BlLoadTriageDump(
  263. IN ULONG DriveId,
  264. OUT PVOID * TriageDumpOut
  265. )
  266. /*++
  267. Routine Description:
  268. Load the triage dump, if it exists; return an error value otherwise.
  269. Arguments:
  270. DriveId - The device where we should check for the triage dump.
  271. TriageDumpOut - Where the triage dump pointer is copied to on success.
  272. Return Value:
  273. ESUCCESS - If there was a triage dump and the dump information was
  274. successfully copied into pTriageDump.
  275. ARC_STATUS - Otherwise.
  276. --*/
  277. {
  278. ARC_STATUS Status;
  279. PMEMORY_DUMP MemoryDump = NULL;
  280. ULONG PageFile = BL_INVALID_FILE_ID;
  281. ULONG Count, actualBase;
  282. PBYTE Buffer = NULL, NewBuffer = NULL;
  283. //
  284. // Fill in the TriageDump structure
  285. //
  286. Status = BlOpen (DriveId, PAGEFILE_SYS, ArcOpenReadOnly, &PageFile);
  287. if (Status != ESUCCESS) {
  288. goto _return;
  289. }
  290. //
  291. // Allocate the buffer for the triage dump.
  292. //
  293. Buffer = (PBYTE) BlAllocateHeap (SECTOR_SIZE);
  294. if (!Buffer) {
  295. Status = ENOMEM;
  296. goto _return;
  297. }
  298. //
  299. // Read the first SECTOR_SIZE of the pagefile.
  300. //
  301. Status = BlRead (PageFile, Buffer, SECTOR_SIZE, &Count);
  302. if (Status != ESUCCESS || Count != SECTOR_SIZE) {
  303. Status = EINVAL;
  304. goto _return;
  305. }
  306. MemoryDump = (PMEMORY_DUMP) Buffer;
  307. if (MemoryDump->Header.ValidDump != DUMP_VALID_DUMP ||
  308. MemoryDump->Header.Signature != DUMP_SIGNATURE ||
  309. MemoryDump->Header.DumpType != DUMP_TYPE_TRIAGE) {
  310. //
  311. // Not a valid dump file.
  312. //
  313. Status = EINVAL;
  314. goto _return;
  315. }
  316. Status = BlAllocateDescriptor (LoaderOsloaderHeap,0,BYTES_TO_PAGES(TRIAGE_DUMP_SIZE) ,&actualBase);
  317. if (!actualBase || (Status != STATUS_SUCCESS)) {
  318. Status = ENOMEM;
  319. goto _return;
  320. }
  321. NewBuffer = (PBYTE)(KSEG0_BASE | (actualBase << PAGE_SHIFT));
  322. //
  323. // Read the first TRIAGE_DUMP_SIZE of the pagefile.
  324. //
  325. Status = BlReadAtOffset (PageFile, 0,TRIAGE_DUMP_SIZE,NewBuffer);
  326. if (Status != ESUCCESS) {
  327. Status = EINVAL;
  328. goto _return;
  329. }
  330. MemoryDump = (PMEMORY_DUMP) NewBuffer;
  331. //
  332. // Does the dump have a valid signature.
  333. //
  334. if (MemoryDump->Triage.ValidOffset > (TRIAGE_DUMP_SIZE - sizeof (ULONG)) ||
  335. *(ULONG *)IndexByByte (Buffer, MemoryDump->Triage.ValidOffset) != TRIAGE_DUMP_VALID) {
  336. Status = EINVAL;
  337. goto _return;
  338. }
  339. Status = ESUCCESS;
  340. _return:
  341. if (PageFile != BL_INVALID_FILE_ID) {
  342. BlClose (PageFile);
  343. PageFile = BL_INVALID_FILE_ID;
  344. }
  345. if (Status != ESUCCESS && Buffer) {
  346. Buffer = NULL;
  347. MemoryDump = NULL;
  348. }
  349. *TriageDumpOut = MemoryDump;
  350. return Status;
  351. }
  352. ARC_STATUS
  353. BlInitStdio (
  354. IN ULONG Argc,
  355. IN CHAR * FIRMWARE_PTR * FIRMWARE_PTR Argv
  356. )
  357. {
  358. PCHAR ConsoleOutDevice;
  359. PCHAR ConsoleInDevice;
  360. ULONG Status;
  361. if (BlConsoleInitialized) {
  362. return ESUCCESS;
  363. }
  364. //
  365. // initialize the progress bar
  366. //
  367. // BlShowProgressBar = TRUE;
  368. if( BlIsTerminalConnected() ) {
  369. BlShowProgressBar = TRUE;
  370. DisplayLogoOnBoot = FALSE;
  371. }
  372. //
  373. // Get the name of the console output device and open the device for
  374. // write access.
  375. //
  376. ConsoleOutDevice = BlGetArgumentValue(Argc, Argv, "consoleout");
  377. if ((ConsoleOutDevice == NULL) && !BlIsTerminalConnected()) {
  378. return ENODEV;
  379. }
  380. Status = ArcOpen(ConsoleOutDevice, ArcOpenWriteOnly, &BlConsoleOutDeviceId);
  381. if ((Status != ESUCCESS) && !BlIsTerminalConnected()) {
  382. return Status;
  383. }
  384. //
  385. // Get the name of the console input device and open the device for
  386. // read access.
  387. //
  388. ConsoleInDevice = BlGetArgumentValue(Argc, Argv, "consolein");
  389. if ((ConsoleInDevice == NULL) && !BlIsTerminalConnected()) {
  390. return ENODEV;
  391. }
  392. Status = ArcOpen(ConsoleInDevice, ArcOpenReadOnly, &BlConsoleInDeviceId);
  393. if ((Status != ESUCCESS) && !BlIsTerminalConnected()) {
  394. return Status;
  395. }
  396. BlConsoleInitialized = TRUE;
  397. return ESUCCESS;
  398. }
  399. int
  400. Blatoi(
  401. char *s
  402. )
  403. {
  404. int digval = 0;
  405. int num = 0;
  406. char *n;
  407. num = 0;
  408. for (n=s; *n; n++) {
  409. if (isdigit((int)(unsigned char)*n)) {
  410. digval = *n - '0';
  411. } else if (isxdigit((int)(unsigned char)*n)) {
  412. digval = toupper(*n) - 'A' + 10;
  413. } else {
  414. digval = 0;
  415. }
  416. num = num * 16 + digval;
  417. }
  418. return num;
  419. }
  420. PCHAR
  421. BlTranslateSignatureArcName(
  422. IN PCHAR ArcNameIn
  423. )
  424. /*++
  425. Routine Description:
  426. This function's purpose is to translate a signature based arc
  427. name to a scsi based arc name. The 2 different arc name syntaxes
  428. are as follows:
  429. scsi(28111684)disk(0)rdisk(0)partition(1)
  430. scsi(1)disk(0)rdisk(0)partition(1)
  431. Both of these arc names are really the same disk, the first uses
  432. the disk's signature and the second uses the scsi bus number. This
  433. function translates the signature arc name by interating thru all
  434. of the scsi buses that the loaded scsi miniport supports. If it
  435. finds a signature match then the arc name is changed to use the
  436. correct scsi bus number. This problem occurs because the boot loader
  437. only loads one scsi miniport and therefore only sees the buses
  438. attached to it's devices. If you have a system with multiple
  439. scsi adapters of differing type, like an adaptec and a symbios logic,
  440. then there is a high probability that the boot loader will see the
  441. buses in a different order than the nt executive will and the
  442. system will not boot.
  443. Arguments:
  444. ArcNameIn - Supplies the signature based arc name
  445. Return Value:
  446. Success - Valid pointer to a scsi based arcname.
  447. Failure - NULL pointer
  448. --*/
  449. {
  450. #if defined(_X86_)
  451. extern ULONG ScsiPortCount;
  452. PCHAR s,p;
  453. ULONG sigval;
  454. ULONG Signature;
  455. int found = -1;
  456. ULONG i;
  457. ARC_STATUS Status;
  458. ULONG DriveId;
  459. CHAR Buffer[2048+256];
  460. CHAR ArcName[128];
  461. PUCHAR Sector;
  462. LARGE_INTEGER SeekValue;
  463. ULONG Count;
  464. PCONFIGURATION_COMPONENT target;
  465. PCONFIGURATION_COMPONENT lun;
  466. CHAR devicePath[117];
  467. BOOLEAN gotPath;
  468. USHORT mbrSig;
  469. if (_strnicmp( ArcNameIn, "signature(", 10 ) != 0) {
  470. //
  471. // not a signature based name so leave
  472. //
  473. return NULL;
  474. }
  475. s = strchr( ArcNameIn, '(' );
  476. p = strchr( ArcNameIn, ')' );
  477. if (s == NULL || p == NULL) {
  478. return NULL;
  479. }
  480. *p = 0;
  481. sigval = Blatoi( s+1 );
  482. *p = ')';
  483. if (sigval == 0) {
  484. return NULL;
  485. }
  486. Sector = ALIGN_BUFFER(Buffer);
  487. for (i=0; i < ScsiPortCount; i++) {
  488. target = ScsiGetFirstConfiguredTargetComponent(i);
  489. while (target != NULL) {
  490. lun = ScsiGetFirstConfiguredLunComponent(target);
  491. while (lun != NULL) {
  492. gotPath = ScsiGetDevicePath(i, target, lun, devicePath);
  493. if (gotPath == FALSE) {
  494. break;
  495. }
  496. sprintf(ArcName, "%spartition(0)", devicePath);
  497. Status = ArcOpen( ArcName, ArcOpenReadOnly, &DriveId );
  498. if (Status == ESUCCESS) {
  499. SeekValue.QuadPart = 0;
  500. Status = ArcSeek(DriveId, &SeekValue, SeekAbsolute);
  501. if (Status == ESUCCESS) {
  502. Status = ArcRead( DriveId, Sector, 512, &Count );
  503. if (Status == ESUCCESS && Count == 512) {
  504. mbrSig =
  505. ((PUSHORT)Sector)[BOOT_SIGNATURE_OFFSET];
  506. Signature =
  507. ((PULONG)Sector)[PARTITION_TABLE_OFFSET/2-1];
  508. if (mbrSig == BOOT_RECORD_SIGNATURE &&
  509. Signature == sigval) {
  510. found = i;
  511. ArcClose(DriveId);
  512. goto SigFound;
  513. }
  514. }
  515. }
  516. ArcClose(DriveId);
  517. }
  518. lun = ScsiGetNextConfiguredLunComponent(lun);
  519. }
  520. target = ScsiGetNextConfiguredTargetComponent(target);
  521. }
  522. }
  523. SigFound:
  524. if (found == -1) {
  525. //
  526. // the signature in the arcname is bogus
  527. //
  528. return NULL;
  529. }
  530. //
  531. // if we get here then we have an arc name with a
  532. // good signature in it, so now we can generate
  533. // a good arc name
  534. //
  535. p = strstr(ArcNameIn, "partition(");
  536. if (p == NULL) {
  537. ASSERT(FALSE);
  538. return NULL;
  539. }
  540. if ( sizeof(Buffer) < strlen(devicePath) + strlen(p) + 1 ) {
  541. return NULL;
  542. }
  543. strcpy(Buffer, devicePath);
  544. strcat(Buffer, p);
  545. p = (PCHAR)BlAllocateHeap( strlen(Buffer) + 1 );
  546. if (p) {
  547. strcpy( p, Buffer );
  548. }
  549. return p;
  550. #else
  551. UNREFERENCED_PARAMETER(ArcNameIn);
  552. return NULL;
  553. #endif
  554. }
  555. #if defined(_X86_)
  556. VOID FLUSH_TB();
  557. VOID ENABLE_PSE();
  558. #define _8kb ( 8*1024)
  559. #define _32kb (32*1024)
  560. #define _4mb (4*1024*1024)
  561. #define _4mb_pages (_4mb >> PAGE_SHIFT)
  562. ARC_STATUS
  563. XipLargeRead(
  564. ULONG FileId,
  565. PFN_COUNT BasePage,
  566. PFN_COUNT PageCount
  567. )
  568. /*++
  569. Routine Description:
  570. Initialize the XIP 'ROM' by reading from disk.
  571. Arguments:
  572. FileId - The file used to initialize for XIP.
  573. BasePage - PFN of the first XIP Rom page.
  574. PageCount - Number of XIP Rom pages.
  575. Return Value:
  576. ESUCCESS returned if all goes well.
  577. --*/
  578. {
  579. PHARDWARE_PTE PDE_VA = (PHARDWARE_PTE)PDE_BASE;
  580. ARC_STATUS status = ESUCCESS;
  581. PHARDWARE_PTE pde;
  582. HARDWARE_PTE zproto, proto;
  583. PBYTE baseaddr, curraddr, copybuffer;
  584. ULONG fileoffset;
  585. ULONG count;
  586. ULONG tcount;
  587. ULONG paddingbytes;
  588. int i, n;
  589. copybuffer = NULL;
  590. //
  591. // Look for a zero PDE entry starting at entry 128 (address 512MB).
  592. //
  593. pde = PDE_VA + 128;
  594. baseaddr = (PUCHAR)(128*_4mb);
  595. for (i = 0; i < 32; i++) {
  596. if (*(PULONG)pde == 0) {
  597. break;
  598. }
  599. pde++;
  600. baseaddr += _4mb;
  601. }
  602. if (i == 32) {
  603. return ENOMEM;
  604. }
  605. //
  606. // Have to enable 4MB pages in cr4 in order to use them in the PDE
  607. //
  608. ENABLE_PSE();
  609. //
  610. // Initialize the pte prototypes.
  611. //
  612. *(PULONG)&zproto = 0;
  613. proto = zproto;
  614. proto.Write = 1;
  615. proto.LargePage = 1;
  616. proto.Valid = 1;
  617. //
  618. //Use intermediate 8KB buffer and read in smaller chunks.
  619. //
  620. copybuffer = (PBYTE) BlAllocateHeap (TRIAGE_DUMP_SIZE);
  621. if (!copybuffer) {
  622. return ENOMEM;
  623. }
  624. //
  625. // Map the XIP memory 4MB at a time.
  626. // Read in the file 8KB at a time.
  627. // Don't exceed the PageCount.
  628. //
  629. fileoffset = 0;
  630. do {
  631. //
  632. // Reset the curraddr to the beginning of the buffer.
  633. // Set the PFN in the 4MB pte and flush the TLB
  634. //
  635. curraddr = baseaddr;
  636. proto.PageFrameNumber = BasePage;
  637. *pde = proto;
  638. FLUSH_TB();
  639. //
  640. // Adjust the BasePage and PageCount values for the next iteration
  641. //
  642. BasePage += _4mb_pages;
  643. if (PageCount < _4mb_pages) {
  644. PageCount = 0;
  645. } else {
  646. PageCount -= _4mb_pages;
  647. }
  648. //
  649. // Read in the next 4MB in 8KB chunks.
  650. //
  651. n = _4mb / _8kb;
  652. while (n--) {
  653. status = BlRead(FileId, (PVOID)copybuffer, _8kb, &count);
  654. //
  655. // Just give up on an error.
  656. //
  657. if (status != ESUCCESS) {
  658. goto done;
  659. }
  660. //
  661. // If not the first read (or a short read)
  662. // the copy is simple.
  663. //
  664. if (fileoffset > 0 || count < _8kb) {
  665. RtlCopyMemory( (PVOID)curraddr, (PVOID)copybuffer, count );
  666. curraddr += count;
  667. fileoffset += count;
  668. if (count < _8kb) {
  669. goto done;
  670. }
  671. } else {
  672. //
  673. // Process boot sector. Need to pad out ReservedSectors
  674. // to align clusters on a page boundary.
  675. //
  676. PPACKED_BOOT_SECTOR pboot;
  677. BIOS_PARAMETER_BLOCK bios;
  678. ULONG newReservedSectors;
  679. pboot = (PPACKED_BOOT_SECTOR)copybuffer;
  680. FatUnpackBios(&bios, &pboot->PackedBpb);
  681. if (bios.BytesPerSector != SECTOR_SIZE
  682. || FatBytesPerCluster(&bios) != PAGE_SIZE) {
  683. goto done;
  684. }
  685. //
  686. // Compute how much paddint is required and update the ReservedSectors field.
  687. //
  688. paddingbytes = PAGE_SIZE - (FatFileAreaLbo(&bios) & (PAGE_SIZE-1));
  689. if (paddingbytes < PAGE_SIZE) {
  690. newReservedSectors = (FatReservedBytes(&bios) + paddingbytes) / SECTOR_SIZE;
  691. pboot->PackedBpb.ReservedSectors[0] = (UCHAR) (newReservedSectors & 0xff);
  692. pboot->PackedBpb.ReservedSectors[1] = (UCHAR) (newReservedSectors >> 8);
  693. }
  694. //
  695. // Copy the boot block.
  696. // Add padding.
  697. // Copy the rest of the read buffer.
  698. // Read in a short page to get us back on track.
  699. //
  700. RtlCopyMemory( (PVOID)curraddr, (PVOID)copybuffer, SECTOR_SIZE );
  701. curraddr += SECTOR_SIZE;
  702. RtlZeroMemory( (PVOID)curraddr, paddingbytes );
  703. curraddr += paddingbytes;
  704. RtlCopyMemory( (PVOID)curraddr, (PVOID) (copybuffer + SECTOR_SIZE), count - SECTOR_SIZE );
  705. curraddr += (count - SECTOR_SIZE);
  706. status = BlRead(FileId, (PVOID)copybuffer, count - paddingbytes, &tcount);
  707. if (status != ESUCCESS || tcount != count - paddingbytes) {
  708. goto done;
  709. }
  710. RtlCopyMemory( (PVOID)curraddr, (PVOID)copybuffer, count - paddingbytes );
  711. curraddr += (count - paddingbytes);
  712. fileoffset += (2*count - paddingbytes);;
  713. //
  714. // We decrement n again, since we have eaten up another 8KB of the 4MB mapping.
  715. //
  716. n--;
  717. }
  718. }
  719. } while (PageCount);
  720. done:
  721. //
  722. // Unmap the current 4MB chunk and flush the TB
  723. //
  724. *pde = zproto;
  725. FLUSH_TB();
  726. //
  727. // Free the temporary copy buffer
  728. //
  729. if (copybuffer) {
  730. ;
  731. }
  732. return status;
  733. }
  734. #endif //_X86_
  735. ARC_STATUS
  736. BlOsLoader (
  737. IN ULONG Argc,
  738. IN CHAR * FIRMWARE_PTR * FIRMWARE_PTR Argv,
  739. IN CHAR * FIRMWARE_PTR * FIRMWARE_PTR Envp
  740. )
  741. /*++
  742. Routine Description:
  743. This is the main routine that controls the loading of the NT operating
  744. system on an ARC compliant system. It opens the system partition,
  745. the boot partition, the console input device, and the console output
  746. device. The NT operating system and all its DLLs are loaded and bound
  747. together. Control is then transfered to the loaded system.
  748. Arguments:
  749. Argc - Supplies the number of arguments that were provided on the
  750. command that invoked this program.
  751. Argv - Supplies a pointer to a vector of pointers to null terminated
  752. argument strings.
  753. Envp - Supplies a pointer to a vector of pointers to null terminated
  754. environment variables.
  755. Return Value:
  756. EBADF is returned if the specified OS image cannot be loaded.
  757. --*/
  758. {
  759. ULONG CacheLineSize;
  760. PCONFIGURATION_COMPONENT_DATA DataCache;
  761. CHAR DeviceName[256];
  762. CHAR DevicePrefix[256];
  763. PCHAR DirectoryEnd;
  764. CHAR KdDllName[256];
  765. PCHAR FileName;
  766. ULONG FileSize;
  767. BOOLEAN KdDllLoadFailed;
  768. PKLDR_DATA_TABLE_ENTRY KdDataTableEntry = NULL;
  769. PKLDR_DATA_TABLE_ENTRY HalDataTableEntry;
  770. PCHAR LoadDevice;
  771. ULONG LoadDeviceId;
  772. CHAR LoadDevicePath[256];
  773. CHAR LoadDeviceLKG1Path[256];
  774. CHAR LoadDeviceLKG2Path[256];
  775. FULL_PATH_SET LoadDevicePathSet;
  776. PCHAR SystemDevice;
  777. ULONG SystemDeviceId;
  778. CHAR SystemDevicePath[256];
  779. FULL_PATH_SET SystemDevicePathSet;
  780. CHAR KernelDirectoryPath[256];
  781. FULL_PATH_SET KernelPathSet;
  782. CHAR KernelPathName[256];
  783. CHAR HalPathName[256];
  784. PVOID HalBase;
  785. PVOID KdDllBase;
  786. #if defined(_ALPHA_) || defined(ARCI386) || defined(_IA64_)
  787. PVOID LoaderBase;
  788. PMEMORY_DESCRIPTOR ProgramDescriptor;
  789. #endif
  790. PVOID SystemBase;
  791. ULONG Index;
  792. ULONG Limit;
  793. ULONG LinesPerBlock;
  794. PCHAR LoadFileName;
  795. PCHAR LoadOptions;
  796. PCHAR OsLoader;
  797. #if defined(_X86_)
  798. PCHAR x86SystemPartition;
  799. PCHAR userSpecifiedKernelName = NULL;
  800. ULONG highestSystemPage;
  801. BOOLEAN userSpecifiedPae;
  802. BOOLEAN userSpecifiedNoPae;
  803. #endif
  804. #if defined(REMOTE_BOOT)
  805. PCHAR SavedOsLoader;
  806. PCHAR SavedLoadFileName;
  807. #endif
  808. ULONG i;
  809. ARC_STATUS Status;
  810. NTSTATUS NtStatus;
  811. PKLDR_DATA_TABLE_ENTRY SystemDataTableEntry;
  812. PTRANSFER_ROUTINE SystemEntry;
  813. PIMAGE_NT_HEADERS NtHeaders;
  814. PWSTR BootFileSystem;
  815. CHAR BadFileName[128];
  816. PBOOTFS_INFO FsInfo;
  817. PCHAR TmpPchar;
  818. BOOLEAN bDiskCacheInitialized = FALSE;
  819. BOOLEAN ServerHive = FALSE;
  820. #if defined(REMOTE_BOOT)
  821. ULONGLONG NetRebootParameter;
  822. CHAR OutputBuffer[256];
  823. #endif // defined(REMOTE_BOOT)
  824. BOOLEAN bLastKnownGood, bLastKnownGoodChosenLate;
  825. #if defined(_X86_)
  826. BOOLEAN safeBoot = FALSE;
  827. #endif
  828. PBOOT_DRIVER_NODE DriverNode = 0;
  829. PBOOT_DRIVER_LIST_ENTRY DriverEntry = 0;
  830. PLIST_ENTRY NextEntry = 0;
  831. PLIST_ENTRY BootDriverListHead = 0;
  832. UNICODE_STRING unicodeString;
  833. CHAR Directory[256];
  834. UNREFERENCED_PARAMETER( Envp );
  835. #ifdef EFI
  836. //
  837. // set the EFI watchdog to 20 minutes.
  838. // by default, it is set to 5 minutes by the efi boot manager
  839. //
  840. SetEFIWatchDog(EFI_WATCHDOG_TIMEOUT);
  841. #elif defined(_X86_)
  842. //
  843. // set the x86 watchdog timer if it exists
  844. //
  845. SetX86WatchDog(X86_WATCHDOG_TIMEOUT);
  846. #endif
  847. // BlShowProgressBar = TRUE;
  848. BlShowProgressBar = FALSE;
  849. BlStartTime = ArcGetRelativeTime();
  850. //
  851. // Initialize the OS loader console input and output.
  852. //
  853. Status = BlInitStdio(Argc, Argv);
  854. if (Status != ESUCCESS) {
  855. return Status;
  856. }
  857. //
  858. // Initialize the boot debugger for platforms that directly load the
  859. // OS Loader.
  860. //
  861. // N.B. This must occur after the console input and output have been
  862. // initialized so debug messages can be printed on the console
  863. // output device.
  864. //
  865. #if defined(_ALPHA_) || defined(ARCI386) || defined(_IA64_)
  866. //
  867. // Locate the memory descriptor for the OS Loader.
  868. //
  869. ProgramDescriptor = NULL;
  870. while ((ProgramDescriptor = ArcGetMemoryDescriptor(ProgramDescriptor)) != NULL) {
  871. if (ProgramDescriptor->MemoryType == MemoryLoadedProgram) {
  872. break;
  873. }
  874. }
  875. //
  876. // If the program memory descriptor was found, then compute the base
  877. // address of the OS Loader for use by the debugger.
  878. //
  879. LoaderBase = &__ImageBase;
  880. //
  881. // Initialize traps and the boot debugger.
  882. //
  883. #if defined(ENABLE_LOADER_DEBUG)
  884. #if defined(_ALPHA_)
  885. BdInitializeTraps();
  886. #endif
  887. DBGTRACE( TEXT("About to BdInitDebugger. Base = %x\r\n"), LoaderBase );
  888. BdInitDebugger((PCHAR)OsLoaderName, LoaderBase, ENABLE_LOADER_DEBUG);
  889. DBGTRACE( TEXT("Back From BdInitDebugger.\r\n") );
  890. #else
  891. BdInitDebugger((PCHAR)OsLoaderName, 0, NULL);
  892. #endif
  893. #endif
  894. #if defined(REMOTE_BOOT)
  895. //
  896. // Get any parameters from a reboot on a Net PC.
  897. //
  898. if (BlBootingFromNet) {
  899. NetGetRebootParameters(&NetRebootParameter, NULL, NULL, NULL, NULL, NULL, TRUE);
  900. }
  901. #endif // defined(REMOTE_BOOT)
  902. #if 0 && !defined(_IA64_)
  903. //
  904. // AJR bugbug -- do we really need to do this twice? we already call in SuMain()
  905. //
  906. // ChuckL -- Turned this code off because it screws up remote boot, which
  907. // does some allocations before we get here.
  908. //
  909. //
  910. // Initialize the memory descriptor list, the OS loader heap, and the
  911. // OS loader parameter block.
  912. //
  913. Status = BlMemoryInitialize();
  914. if (Status != ESUCCESS) {
  915. BlFatalError(LOAD_HW_MEM_CLASS,
  916. DIAG_BL_MEMORY_INIT,
  917. LOAD_HW_MEM_ACT);
  918. goto LoadFailed;
  919. }
  920. #endif
  921. #if defined(_IA64_)
  922. //
  923. // Build required portion of ARC tree since we are not doing NTDETECT
  924. // anymore for IA-64.
  925. //
  926. BuildArcTree();
  927. #endif
  928. #ifdef EFI
  929. //
  930. // Establish SMBIOS information in the loader block
  931. //
  932. SetupSMBiosInLoaderBlock();
  933. #endif
  934. //
  935. // Compute the data cache fill size. This value is used to align
  936. // I/O buffers in case the host system does not support coherent
  937. // caches.
  938. //
  939. // If a combined secondary cache is present, then use the fill size
  940. // for that cache. Otherwise, if a secondary data cache is present,
  941. // then use the fill size for that cache. Otherwise, if a primary
  942. // data cache is present, then use the fill size for that cache.
  943. // Otherwise, use the default fill size.
  944. //
  945. DataCache = KeFindConfigurationEntry(BlLoaderBlock->ConfigurationRoot,
  946. CacheClass,
  947. SecondaryCache,
  948. NULL);
  949. if (DataCache == NULL) {
  950. DataCache = KeFindConfigurationEntry(BlLoaderBlock->ConfigurationRoot,
  951. CacheClass,
  952. SecondaryDcache,
  953. NULL);
  954. if (DataCache == NULL) {
  955. DataCache = KeFindConfigurationEntry(BlLoaderBlock->ConfigurationRoot,
  956. CacheClass,
  957. PrimaryDcache,
  958. NULL);
  959. }
  960. }
  961. if (DataCache != NULL) {
  962. LinesPerBlock = DataCache->ComponentEntry.Key >> 24;
  963. CacheLineSize = 1 << ((DataCache->ComponentEntry.Key >> 16) & 0xff);
  964. BlDcacheFillSize = LinesPerBlock * CacheLineSize;
  965. }
  966. //
  967. // Initialize the OS loader I/O system.
  968. //
  969. Status = BlIoInitialize();
  970. if (Status != ESUCCESS) {
  971. BlFatalError(LOAD_HW_DISK_CLASS,
  972. DIAG_BL_IO_INIT,
  973. LOAD_HW_DISK_ACT);
  974. goto LoadFailed;
  975. }
  976. //
  977. // Initialize the resource section.
  978. //
  979. Status = BlInitResources(Argv[0]);
  980. if (Status != ESUCCESS) {
  981. BlFatalError(LOAD_HW_DISK_CLASS,
  982. DIAG_BL_IO_INIT,
  983. LOAD_HW_DISK_ACT);
  984. goto LoadFailed;
  985. }
  986. //
  987. // Initialize the progress bar
  988. //
  989. BlSetProgBarCharacteristics(HIBER_UI_BAR_ELEMENT, BLDR_UI_BAR_BACKGROUND);
  990. //
  991. // Initialize the NT configuration tree.
  992. //
  993. BlLoaderBlock->ConfigurationRoot = NULL;
  994. Status = BlConfigurationInitialize(NULL, NULL);
  995. if (Status != ESUCCESS) {
  996. BlFatalError(LOAD_HW_FW_CFG_CLASS,
  997. DIAG_BL_CONFIG_INIT,
  998. LOAD_HW_FW_CFG_ACT);
  999. goto LoadFailed;
  1000. }
  1001. //
  1002. // Copy the osloadoptions argument into the LoaderBlock.
  1003. //
  1004. LoadOptions = BlGetArgumentValue(Argc, Argv, "osloadoptions");
  1005. #if defined(_X86_)
  1006. userSpecifiedPae = FALSE;
  1007. userSpecifiedNoPae = FALSE;
  1008. safeBoot = FALSE;
  1009. #endif
  1010. if (LoadOptions != NULL) {
  1011. FileSize = (ULONG)strlen(LoadOptions) + 1;
  1012. FileName = (PCHAR)BlAllocateHeap(FileSize);
  1013. strcpy(FileName, LoadOptions);
  1014. BlLoaderBlock->LoadOptions = FileName;
  1015. //
  1016. // Check for the SOS switch that forces the output of filenames during
  1017. // the boot instead of the progress dots.
  1018. //
  1019. if ((strstr(FileName, "SOS") != NULL) ||
  1020. (strstr(FileName, "sos") != NULL)) {
  1021. BlOutputDots = FALSE;
  1022. }
  1023. #ifdef EFI
  1024. GraphicsMode = FALSE;
  1025. #else
  1026. GraphicsMode = (BOOLEAN)(strstr(FileName, "BOOTLOGO") != NULL); // to display boot logo go to graphics mode
  1027. #endif
  1028. //
  1029. // Check for the 3gb user address space switch which causes the system
  1030. // to load at the alternate base address if it is relocatable.
  1031. //
  1032. #if defined(_X86_)
  1033. if (strstr(FileName, "SAFEBOOT") != NULL) {
  1034. safeBoot = TRUE;
  1035. }
  1036. if ((strstr(FileName, "3GB") != NULL) ||
  1037. (strstr(FileName, "3gb") != NULL)) {
  1038. BlVirtualBias = ALTERNATE_BASE - KSEG0_BASE;
  1039. }
  1040. if ((strstr(FileName, "PAE") != NULL) ||
  1041. (strstr(FileName, "pae") != NULL)) {
  1042. userSpecifiedPae = TRUE;
  1043. }
  1044. if ((strstr(FileName, "NOPAE") != NULL) ||
  1045. (strstr(FileName, "nopae") != NULL)) {
  1046. userSpecifiedNoPae = TRUE;
  1047. }
  1048. if (safeBoot != FALSE) {
  1049. //
  1050. // We're in safeboot mode. Override the user's desire to boot
  1051. // into PAE mode.
  1052. //
  1053. userSpecifiedPae = FALSE;
  1054. }
  1055. #endif
  1056. //
  1057. // Check for an alternate HAL specification.
  1058. //
  1059. FileName = strstr(BlLoaderBlock->LoadOptions, "HAL=");
  1060. if (FileName != NULL) {
  1061. FileName += strlen("HAL=");
  1062. for (i = 0; i < sizeof(HalFileName); i++) {
  1063. if (FileName[i] == ' ') {
  1064. HalFileName[i] = '\0';
  1065. break;
  1066. }
  1067. HalFileName[i] = FileName[i];
  1068. }
  1069. }
  1070. HalFileName[sizeof(HalFileName) - 1] = '\0';
  1071. //
  1072. // Check for an alternate kernel specification.
  1073. //
  1074. FileName = strstr(BlLoaderBlock->LoadOptions, "KERNEL=");
  1075. if (FileName != NULL) {
  1076. FileName += strlen("KERNEL=");
  1077. for (i = 0; i < sizeof(KernelFileName); i++) {
  1078. if (FileName[i] == ' ') {
  1079. KernelFileName[i] = '\0';
  1080. break;
  1081. }
  1082. KernelFileName[i] = FileName[i];
  1083. }
  1084. #if defined(_X86_)
  1085. userSpecifiedKernelName = KernelFileName;
  1086. #endif
  1087. }
  1088. #if defined(_X86_)
  1089. else {
  1090. userSpecifiedKernelName = NULL;
  1091. }
  1092. #endif
  1093. KernelFileName[sizeof(KernelFileName) - 1] = '\0';
  1094. //
  1095. // Check for an alternate Kernel Debugger DLL, i.e.,
  1096. // /debugport=1394 (kd1394.dll), /debugport=usb (kdusb.dll), etc...
  1097. //
  1098. FileName = strstr(BlLoaderBlock->LoadOptions, "DEBUGPORT=");
  1099. if (FileName == NULL) {
  1100. FileName = strstr(BlLoaderBlock->LoadOptions, "debugport=");
  1101. }
  1102. if (FileName != NULL) {
  1103. _strupr(FileName);
  1104. if (strstr(FileName, "COM") == NULL) {
  1105. UseAlternateKdDll = TRUE;
  1106. FileName += strlen("DEBUGPORT=");
  1107. for (i = 0; i < KD_ALT_DLL_REPLACE_CHARS; i++) {
  1108. if (FileName[i] == ' ') {
  1109. break;
  1110. }
  1111. KdFileName[KD_ALT_DLL_PREFIX_CHARS + i] = FileName[i];
  1112. }
  1113. KdFileName[KD_ALT_DLL_PREFIX_CHARS + i] = '\0';
  1114. strcat(KdFileName, ".DLL");
  1115. }
  1116. }
  1117. } else {
  1118. BlLoaderBlock->LoadOptions = NULL;
  1119. }
  1120. #if defined(_X86_)
  1121. if (LoadOptions != NULL) {
  1122. //
  1123. // Process XIP options
  1124. //
  1125. {
  1126. PCHAR XIPBootOption, XIPRomOption, XIPRamOption, XIPSizeOption;
  1127. PCHAR path, sizestr;
  1128. ULONG nmegs = 0;
  1129. PCHAR p, opts;
  1130. ULONG n;
  1131. opts = BlLoaderBlock->LoadOptions;
  1132. (XIPBootOption = strstr(opts, "XIPBOOT")) || (XIPBootOption = strstr(opts, "xipboot"));
  1133. (XIPRomOption = strstr(opts, "XIPROM=")) || (XIPRomOption = strstr(opts, "xiprom="));
  1134. (XIPRamOption = strstr(opts, "XIPRAM=")) || (XIPRamOption = strstr(opts, "xipram="));
  1135. (XIPSizeOption = strstr(opts, "XIPMEGS=")) || (XIPSizeOption = strstr(opts, "xipmegs="));
  1136. XIPEnabled = FALSE;
  1137. if (XIPRomOption || XIPRamOption) {
  1138. if (XIPRomOption && XIPRamOption) {
  1139. ;
  1140. } else {
  1141. sizestr = XIPSizeOption? strchr(XIPSizeOption, '=') : NULL;
  1142. if (sizestr) {
  1143. sizestr++;
  1144. nmegs = 0;
  1145. while ('0' <= *sizestr && *sizestr <= '9') {
  1146. nmegs = 10*nmegs + (*sizestr - '0');
  1147. sizestr++;
  1148. }
  1149. }
  1150. path = strchr(XIPRomOption? XIPRomOption : XIPRamOption, '=');
  1151. if (nmegs && path) {
  1152. path++;
  1153. XIPBootFlag = XIPBootOption? TRUE : FALSE;
  1154. XIPPageCount = (1024*1024*nmegs) >> PAGE_SHIFT;
  1155. //
  1156. // strdup XIPLoadPath
  1157. //
  1158. for (p = path; *p; p++) {
  1159. if (*p == ' ') break;
  1160. if (*p == '/') break;
  1161. if (*p == '\n') break;
  1162. if (*p == '\r') break;
  1163. if (*p == '\t') break;
  1164. }
  1165. n = (p - path);
  1166. if (n > 1) {
  1167. XIPLoadPath = BlAllocateHeap(n+1);
  1168. if (XIPLoadPath) {
  1169. for (i = 0; i < n; i++) {
  1170. XIPLoadPath[i] = path[i];
  1171. }
  1172. XIPLoadPath[i] = '\0';
  1173. XIPEnabled = TRUE;
  1174. }
  1175. }
  1176. }
  1177. }
  1178. }
  1179. }
  1180. }
  1181. //
  1182. // Allocate the XIP pages.
  1183. //
  1184. if (XIPEnabled) {
  1185. ULONG OldBase;
  1186. ULONG OldLimit;
  1187. OldBase = BlUsableBase;
  1188. OldLimit = BlUsableLimit;
  1189. BlUsableBase = BL_XIPROM_RANGE_LOW;
  1190. BlUsableLimit = BL_XIPROM_RANGE_HIGH;
  1191. Status = BlAllocateAlignedDescriptor (LoaderXIPRom, 0, XIPPageCount, _4mb_pages, &XIPBasePage);
  1192. if (Status != ESUCCESS) {
  1193. XIPEnabled = FALSE;
  1194. }
  1195. BlUsableBase = OldBase;
  1196. BlUsableLimit = OldLimit;
  1197. }
  1198. #endif //_X86_
  1199. //
  1200. // Get the name of the OS loader (on i386 it's system32\NTLDR) and get
  1201. // the OS path (on i386 it's <SystemRoot> such as "\winnt").
  1202. //
  1203. OsLoader = BlGetArgumentValue(Argc, Argv, "osloader");
  1204. LoadFileName = BlGetArgumentValue(Argc, Argv, "osloadfilename");
  1205. //
  1206. // Check the load path to make sure it's valid.
  1207. //
  1208. if (LoadFileName == NULL) {
  1209. Status = ENOENT;
  1210. BlFatalError(LOAD_HW_FW_CFG_CLASS,
  1211. DIAG_BL_FW_GET_BOOT_DEVICE,
  1212. LOAD_HW_FW_CFG_ACT);
  1213. goto LoadFailed;
  1214. }
  1215. //
  1216. // Check the loader path to see if it's valid.
  1217. //
  1218. if (OsLoader == NULL) {
  1219. Status = ENOENT;
  1220. BlFatalError(LOAD_HW_FW_CFG_CLASS,
  1221. DIAG_BL_FIND_HAL_IMAGE,
  1222. LOAD_HW_FW_CFG_ACT);
  1223. goto LoadFailed;
  1224. }
  1225. #if defined(REMOTE_BOOT)
  1226. //
  1227. // If we're booting from the net, temporarily remove the server\share
  1228. // from the front of the OsLoader and LoadFileName strings so that TFTP
  1229. // works.
  1230. //
  1231. if (BlBootingFromNet) {
  1232. NetServerShare = OsLoader; // Required for Client Side Cache.
  1233. SavedOsLoader = OsLoader; // save OsLoader pointer
  1234. OsLoader++; // skip leading "\"
  1235. OsLoader = strchr(OsLoader,'\\'); // find server\share separator
  1236. if (OsLoader != NULL) {
  1237. OsLoader++; // skip server\share separator
  1238. OsLoader = strchr(OsLoader,'\\'); // find share\path separator
  1239. }
  1240. if (OsLoader == NULL) { // very bad if no \ found
  1241. OsLoader = SavedOsLoader;
  1242. goto LoadFailed;
  1243. }
  1244. SavedLoadFileName = LoadFileName; // save LoadFileName pointer
  1245. LoadFileName++; // skip leading "\"
  1246. LoadFileName = strchr(LoadFileName,'\\'); // find server\share separator
  1247. if (LoadFileName != NULL) {
  1248. LoadFileName++; // skip server\share separator
  1249. LoadFileName = strchr(LoadFileName,'\\'); // find share\path separator
  1250. }
  1251. if (LoadFileName == NULL) { // very bad if no \ found
  1252. LoadFileName = SavedLoadFileName;
  1253. OsLoader = SavedOsLoader;
  1254. goto LoadFailed;
  1255. }
  1256. }
  1257. #endif // defined(REMOTE_BOOT)
  1258. //
  1259. // Try to make sure disk caching is initialized. Failure in
  1260. // initializing the disk cache should not keep us from booting, so
  1261. // Status is not set.
  1262. //
  1263. if (BlDiskCacheInitialize() == ESUCCESS) {
  1264. bDiskCacheInitialized = TRUE;
  1265. }
  1266. //
  1267. // Get the NTFT drive signatures to allow the kernel to create the
  1268. // correct ARC name <=> NT name mappings.
  1269. //
  1270. BlGetArcDiskInformation(FALSE);
  1271. //
  1272. // Display the Configuration prompt for breakin at this point, but don't
  1273. // check for key downstrokes. This gives the user a little more reaction
  1274. // time.
  1275. //
  1276. BlStartConfigPrompt();
  1277. //
  1278. // Determine if we are going to do a last known good boot.
  1279. //
  1280. // ISSUE-2000/03/29-ADRIAO: LastKnownGood enhancements
  1281. // Note that last known kernel/hal support requires that we know we're
  1282. // going into a lkg boot prior to initializing the loader. On an x86 system
  1283. // with only one boot.ini option we will not present the user the lkg option
  1284. // until *after* we've loaded the kernel, hal, registry, and kd-dlls. If we
  1285. // decide to support last known kernel/hal, we'd probably have to do
  1286. // something similar to what 9x does (ie look for a depressed CTRL key at
  1287. // the earliest point in boot.)
  1288. //
  1289. bLastKnownGood = (BOOLEAN)(LoadOptions && (strstr(LoadOptions, "LASTKNOWNGOOD") != NULL));
  1290. //
  1291. // Put together everything we need to describe the loader device. This is
  1292. // where the OS is loaded from (ie some \winnt installation). The alias
  1293. // for this path is \SystemRoot.
  1294. //
  1295. LoadDevice = BlGetArgumentValue(Argc, Argv, "osloadpartition");
  1296. if (LoadDevice == NULL) {
  1297. Status = ENODEV;
  1298. BlFatalError(LOAD_HW_FW_CFG_CLASS,
  1299. DIAG_BL_FW_GET_BOOT_DEVICE,
  1300. LOAD_HW_FW_CFG_ACT);
  1301. goto LoadFailed;
  1302. }
  1303. //
  1304. // Initialize the Ramdisk if it is specified in LoadOptions
  1305. //
  1306. Status = RamdiskInitialize( LoadOptions, FALSE );
  1307. if (Status != ESUCCESS) {
  1308. // BlFatalError called inside RamdiskInitialize
  1309. goto LoadFailed;
  1310. }
  1311. //
  1312. // Translate it's signature based arc name
  1313. //
  1314. TmpPchar = BlTranslateSignatureArcName( LoadDevice );
  1315. if (TmpPchar) {
  1316. LoadDevice = TmpPchar;
  1317. }
  1318. //
  1319. // Open the load device
  1320. //
  1321. Status = ArcOpen(LoadDevice, ArcOpenReadWrite, &LoadDeviceId);
  1322. if (Status != ESUCCESS) {
  1323. BlFatalError(LOAD_HW_DISK_CLASS,
  1324. DIAG_BL_OPEN_BOOT_DEVICE,
  1325. LOAD_HW_DISK_ACT);
  1326. goto LoadFailed;
  1327. }
  1328. #if defined(_X86_)
  1329. //
  1330. // Check for the special SDIBOOT flag, which tells us to boot from an
  1331. // SDI image in the root of the boot partition.
  1332. //
  1333. if ( BlLoaderBlock->LoadOptions != NULL ) {
  1334. TmpPchar = strstr( BlLoaderBlock->LoadOptions, "SDIBOOT=" );
  1335. if ( TmpPchar != NULL ) {
  1336. TmpPchar = strchr( TmpPchar, '=' ) + 1;
  1337. RamdiskSdiBoot( TmpPchar );
  1338. }
  1339. }
  1340. #endif
  1341. if (GraphicsMode) {
  1342. HW_CURSOR(0x80000000,0x12);
  1343. VgaEnableVideo();
  1344. LoadBootLogoBitmap (LoadDeviceId, LoadFileName);
  1345. if (DisplayLogoOnBoot) {
  1346. PrepareGfxProgressBar();
  1347. BlUpdateBootStatus();
  1348. }
  1349. }
  1350. //
  1351. // Initiate filesystem metadata caching on the load device.
  1352. //
  1353. // NOTE: From here on access the LoadDevice only through the LoadDeviceId.
  1354. // This way, your access will be faster because it is cached. Otherwise if
  1355. // you make writes, you will have cache consistency issues.
  1356. //
  1357. if (bDiskCacheInitialized) {
  1358. BlDiskCacheStartCachingOnDevice(LoadDeviceId);
  1359. }
  1360. //
  1361. // Build the load device path set. We keep multiple paths so that we can
  1362. // fall back to a last known driver set during a last known good boot.
  1363. //
  1364. strcpy(LoadDevicePath, LoadFileName);
  1365. strcat(LoadDevicePath, "\\");
  1366. strcpy(LoadDeviceLKG1Path, LoadDevicePath);
  1367. strcat(LoadDeviceLKG1Path, LAST_KNOWN_GOOD_TEMPORARY_PATH "\\" );
  1368. strcpy(LoadDeviceLKG2Path, LoadDevicePath);
  1369. strcat(LoadDeviceLKG2Path, LAST_KNOWN_GOOD_WORKING_PATH "\\" );
  1370. #if defined(_X86_)
  1371. //
  1372. // Read in the XIP image
  1373. //
  1374. if (XIPEnabled) {
  1375. ULONG FileId;
  1376. //
  1377. // Read in the imagefile
  1378. //
  1379. Status = BlOpen(LoadDeviceId, XIPLoadPath, ArcOpenReadOnly, &FileId);
  1380. if (Status == ESUCCESS) {
  1381. Status = XipLargeRead(FileId, XIPBasePage, XIPPageCount);
  1382. (void) BlClose(FileId);
  1383. }
  1384. if (Status != ESUCCESS) {
  1385. XIPEnabled = FALSE;
  1386. }
  1387. }
  1388. #endif //_X86_
  1389. i = 0;
  1390. if (bLastKnownGood) {
  1391. //
  1392. // Add the last known good paths as if we are in a LastKnownGood boot.
  1393. //
  1394. LoadDevicePathSet.Source[i].DeviceId = LoadDeviceId;
  1395. LoadDevicePathSet.Source[i].DeviceName = LoadDevice;
  1396. LoadDevicePathSet.Source[i].DirectoryPath = LoadDeviceLKG1Path;
  1397. i++;
  1398. LoadDevicePathSet.Source[i].DeviceId = LoadDeviceId;
  1399. LoadDevicePathSet.Source[i].DeviceName = LoadDevice;
  1400. LoadDevicePathSet.Source[i].DirectoryPath = LoadDeviceLKG2Path;
  1401. i++;
  1402. }
  1403. LoadDevicePathSet.Source[i].DeviceId = LoadDeviceId;
  1404. LoadDevicePathSet.Source[i].DeviceName = LoadDevice;
  1405. LoadDevicePathSet.Source[i].DirectoryPath = LoadDevicePath;
  1406. //
  1407. // The load path sources are all relative to \SystemRoot.
  1408. //
  1409. LoadDevicePathSet.AliasName = "\\SystemRoot";
  1410. LoadDevicePathSet.PathOffset[0] = '\0';
  1411. LoadDevicePathSet.PathCount = ++i;
  1412. //
  1413. // While here, form the kernel path set. This is the same as the boot path
  1414. // set except that it's off of system32/64. Note also that we don't add in
  1415. // the LKG path today.
  1416. //
  1417. KernelPathSet.PathCount = 1;
  1418. KernelPathSet.AliasName = "\\SystemRoot";
  1419. strcpy(KernelPathSet.PathOffset, SYSTEM_DIRECTORY_PATH "\\" );
  1420. KernelPathSet.Source[0].DeviceId = LoadDeviceId;
  1421. KernelPathSet.Source[0].DeviceName = LoadDevice;
  1422. KernelPathSet.Source[0].DirectoryPath = LoadDevicePath;
  1423. //
  1424. // While here, form the fully qualified kernel path.
  1425. //
  1426. strcpy(KernelDirectoryPath, LoadFileName);
  1427. strcat(KernelDirectoryPath, "\\" SYSTEM_DIRECTORY_PATH "\\" );
  1428. //
  1429. // Now put together everything we need to describe the system device. This
  1430. // is where we get the hal and pal from. There is no alias for this path
  1431. // (ie no equivalent to \SystemRoot.)
  1432. //
  1433. SystemDevice = BlGetArgumentValue(Argc, Argv, "systempartition");
  1434. if (SystemDevice == NULL) {
  1435. Status = ENODEV;
  1436. BlFatalError(LOAD_HW_FW_CFG_CLASS,
  1437. DIAG_BL_FW_GET_SYSTEM_DEVICE,
  1438. LOAD_HW_FW_CFG_ACT);
  1439. goto LoadFailed;
  1440. }
  1441. //
  1442. // Translate it's signature based arc name
  1443. //
  1444. TmpPchar = BlTranslateSignatureArcName( SystemDevice );
  1445. if (TmpPchar) {
  1446. SystemDevice = TmpPchar;
  1447. }
  1448. //
  1449. // Open the system device. If SystemDevice path and LoadDevice
  1450. // path are the same [as on all x86 I have seen so far], do not
  1451. // open the device under another device id so we can use disk
  1452. // caching. Otherwise there may be a cache consistency issue.
  1453. //
  1454. if (!_stricmp(LoadDevice, SystemDevice)) {
  1455. SystemDeviceId = LoadDeviceId;
  1456. } else {
  1457. Status = ArcOpen(SystemDevice, ArcOpenReadWrite, &SystemDeviceId);
  1458. if (Status != ESUCCESS) {
  1459. BlFatalError(LOAD_HW_FW_CFG_CLASS,
  1460. DIAG_BL_FW_OPEN_SYSTEM_DEVICE,
  1461. LOAD_HW_FW_CFG_ACT);
  1462. goto LoadFailed;
  1463. }
  1464. }
  1465. //
  1466. // Initiate filesystem metadata caching on the system device.
  1467. //
  1468. // NOTE: From here on access the SystemDevice only through the
  1469. // SystemDeviceId. This way, your access will be faster because it is
  1470. // cached. Otherwise if you make writes, you will have cache consistency
  1471. // issues.
  1472. //
  1473. if (bDiskCacheInitialized) {
  1474. if (SystemDeviceId != LoadDeviceId) {
  1475. BlDiskCacheStartCachingOnDevice(SystemDeviceId);
  1476. }
  1477. }
  1478. //
  1479. // Get the path name of the OS loader file and isolate the directory
  1480. // path so it can be used to load the HAL DLL.
  1481. //
  1482. // Note well: We actually don't use this path to load the hal anymore
  1483. // -- we rely on the kernel path to load the hal as they are at the same
  1484. // location
  1485. // -- we do use this path for identifying the system partition, so do not
  1486. // remove code related to systemdevicepath unless you know what you're
  1487. // doing.
  1488. //
  1489. FileName = OsLoader;
  1490. DirectoryEnd = strrchr(FileName, '\\');
  1491. FileName = strchr(FileName, '\\');
  1492. SystemDevicePath[0] = 0;
  1493. if (DirectoryEnd != NULL) {
  1494. Limit = (ULONG)((ULONG_PTR)DirectoryEnd - (ULONG_PTR)FileName + 1);
  1495. for (Index = 0; Index < Limit; Index += 1) {
  1496. SystemDevicePath[Index] = *FileName++;
  1497. }
  1498. SystemDevicePath[Index] = 0;
  1499. }
  1500. //
  1501. // Describe our hal paths.
  1502. //
  1503. // ISSUE-2000/03/29-ADRIAO: LastKnownGood enhancements
  1504. // On x86 we'd like to support LKG for hals way into the future. Ideally
  1505. // we'd get them from \Winnt\LastGood\System32. Unfortunately, we get back
  1506. // \Winnt\System32 from the Arc, making it kinda hard to splice in our
  1507. // LKG path.
  1508. //
  1509. // ISSUE-2000/03/29-ADRIAO: Existant namespace polution
  1510. // We need to come up with an Alias for the Hal path so that it can
  1511. // properly be inserted into the image namespace. Either that or we should
  1512. // consider lying and saying it comes from \SystemRoot. Note that on x86
  1513. // we probably *would* want it to say it was from \SystemRoot in case it
  1514. // brings in its own DLL's!
  1515. //
  1516. SystemDevicePathSet.PathCount = 1;
  1517. SystemDevicePathSet.AliasName = NULL;
  1518. SystemDevicePathSet.PathOffset[0] = '\0';
  1519. SystemDevicePathSet.Source[0].DeviceId = SystemDeviceId;
  1520. SystemDevicePathSet.Source[0].DeviceName = SystemDevice;
  1521. SystemDevicePathSet.Source[0].DirectoryPath = SystemDevicePath;
  1522. //
  1523. // Handle triage dump (if present).
  1524. //
  1525. Status = BlLoadTriageDump (LoadDeviceId,
  1526. &BlLoaderBlock->Extension->TriageDumpBlock);
  1527. if (Status != ESUCCESS) {
  1528. BlLoaderBlock->Extension->TriageDumpBlock = NULL;
  1529. }
  1530. //
  1531. // Handle hibernation image (if present)
  1532. //
  1533. #if defined(i386) || defined(_IA64_)
  1534. Status = BlHiberRestore(LoadDeviceId, NULL);
  1535. if (Status != ESUCCESS) {
  1536. Status = ESUCCESS;
  1537. // proceed with the boot.
  1538. // goto LoadFailed;
  1539. }
  1540. #endif
  1541. //
  1542. // Initialize the logging system. Note that we dump to the system device
  1543. // and not the load device.
  1544. //
  1545. BlLogInitialize(SystemDeviceId);
  1546. #if defined(REMOTE_BOOT)
  1547. //
  1548. // If booting from the net, check for any of the following:
  1549. // - The client-side disk is incorrect for this NetPC.
  1550. // - The client-side cache is stale.
  1551. //
  1552. if (BlBootingFromNet) {
  1553. BlLoaderBlock->SetupLoaderBlock = BlAllocateHeap(sizeof(SETUP_LOADER_BLOCK));
  1554. if (BlLoaderBlock->SetupLoaderBlock == NULL) {
  1555. Status = ENOMEM;
  1556. BlFatalError(LOAD_HW_MEM_CLASS,
  1557. DIAG_BL_MEMORY_INIT,
  1558. LOAD_HW_MEM_ACT);
  1559. goto LoadFailed;
  1560. }
  1561. //
  1562. // ISSUE-1998/07/13-JVert (John Vert)
  1563. // Code below is ifdef'd out because net boot is no longer
  1564. // in the product. BlCheckMachineReplacement ends up calling
  1565. // SlDetectHAL, which now requires access to txtsetup.sif
  1566. // in order to see if an ACPI machine has a known "good" BIOS.
  1567. // Since there is no txtsetup.sif during a normal boot there
  1568. // is no point in getting all the INF processing logic into
  1569. // NTLDR.
  1570. // ISSUE-1998/07/16-ChuckL (Chuck Lenzmeier)
  1571. // This means that if we ever reenable full remote boot, as
  1572. // opposed to just remote install, and we want to be able to
  1573. // do machine replacement, we're going to have to figure out
  1574. // how to make SlDetectHAL work outside of textmode setup.
  1575. //
  1576. strncpy(OutputBuffer, LoadFileName + 1, 256);
  1577. TmpPchar = strchr(OutputBuffer, '\\');
  1578. TmpPchar++;
  1579. TmpPchar = strchr(TmpPchar, '\\');
  1580. TmpPchar++;
  1581. strcpy(TmpPchar, "startrom.com");
  1582. BlCheckMachineReplacement(SystemDevice, SystemDeviceId, NetRebootParameter, OutputBuffer);
  1583. } else
  1584. #endif // defined(REMOTE_BOOT)
  1585. {
  1586. BlLoaderBlock->SetupLoaderBlock = NULL;
  1587. }
  1588. //
  1589. // See if we're redirecting.
  1590. //
  1591. if( LoaderRedirectionInformation.PortAddress ) {
  1592. //
  1593. // Yes, we are redirecting right now. Use these settings.
  1594. //
  1595. BlLoaderBlock->Extension->HeadlessLoaderBlock = BlAllocateHeap(sizeof(HEADLESS_LOADER_BLOCK));
  1596. RtlCopyMemory( BlLoaderBlock->Extension->HeadlessLoaderBlock,
  1597. &LoaderRedirectionInformation,
  1598. sizeof(HEADLESS_LOADER_BLOCK) );
  1599. } else {
  1600. BlLoaderBlock->Extension->HeadlessLoaderBlock = NULL;
  1601. }
  1602. //
  1603. // Generate the full path name for the HAL DLL image and load it into
  1604. // memory.
  1605. //
  1606. strcpy(HalPathName, KernelDirectoryPath);
  1607. strcat(HalPathName, HalFileName);
  1608. //
  1609. // Prepare for building the full path name of the kernel
  1610. //
  1611. strcpy(KernelPathName, KernelDirectoryPath);
  1612. #if defined(_X86_)
  1613. BlAmd64RemapDram( LoadOptions );
  1614. //
  1615. // If Amd64 long mode is detected, the following call will set
  1616. // the global BlAmd64UseLongMode to TRUE, AND will append
  1617. // KernelFileName to KernelPathName.
  1618. //
  1619. Status = BlAmd64CheckForLongMode( LoadDeviceId,
  1620. KernelPathName,
  1621. KernelFileName );
  1622. if (Status != ESUCCESS) {
  1623. Status = ENODEV;
  1624. BlFatalError(LOAD_SW_MIS_FILE_CLASS,
  1625. DIAG_BL_LOAD_SYSTEM_IMAGE,
  1626. LOAD_SW_FILE_REINST_ACT);
  1627. goto LoadFailed;
  1628. }
  1629. if (BlAmd64UseLongMode == FALSE) {
  1630. //
  1631. // On X86, there are two kernel images: one compiled for PAE mode,
  1632. // and one not. Call a routine that decides what to load.
  1633. //
  1634. // Upon successful return, KernelPathName contains the full path of
  1635. // the kernel image.
  1636. //
  1637. Status = Blx86CheckForPaeKernel( userSpecifiedPae,
  1638. userSpecifiedNoPae,
  1639. userSpecifiedKernelName,
  1640. HalPathName,
  1641. LoadDeviceId,
  1642. SystemDeviceId,
  1643. &highestSystemPage,
  1644. &BlUsePae,
  1645. KernelPathName
  1646. );
  1647. if (Status != ESUCCESS) {
  1648. //
  1649. // A valid kernel compatible with this processor could not be
  1650. // located. This is fatal.
  1651. //
  1652. BlFatalError(LOAD_SW_MIS_FILE_CLASS,
  1653. (Status == EBADF)
  1654. ? DIAG_BL_LOAD_HAL_IMAGE
  1655. : DIAG_BL_LOAD_SYSTEM_IMAGE,
  1656. LOAD_SW_FILE_REINST_ACT);
  1657. goto LoadFailed;
  1658. }
  1659. }
  1660. #else
  1661. //
  1662. // Generate the full pathname of ntoskrnl.exe
  1663. //
  1664. // "\winnt\system32\ntoskrnl.exe"
  1665. //
  1666. strcat(KernelPathName, KernelFileName);
  1667. #endif
  1668. //
  1669. // Set allocatable range to the kernel-specific range
  1670. //
  1671. BlUsableBase = BL_KERNEL_RANGE_LOW;
  1672. BlUsableLimit = BL_KERNEL_RANGE_HIGH;
  1673. //
  1674. // Initialize the progress bar
  1675. //
  1676. if( BlIsTerminalConnected() ) {
  1677. BlOutputStartupMsg(BL_MSG_STARTING_WINDOWS);
  1678. BlOutputTrailerMsg(BL_ADVANCED_BOOT_MESSAGE);
  1679. }
  1680. #if defined (_X86_)
  1681. if (BlAmd64UseLongMode == FALSE) {
  1682. BlpCheckVersion(LoadDeviceId,KernelPathName);
  1683. }
  1684. #endif
  1685. //
  1686. // Load the kernel image into memory.
  1687. //
  1688. BlOutputLoadMessage(LoadDevice, KernelPathName, NULL);
  1689. #ifdef i386
  1690. retrykernel:
  1691. #endif
  1692. Status = BlLoadImage(LoadDeviceId,
  1693. LoaderSystemCode,
  1694. KernelPathName,
  1695. TARGET_IMAGE,
  1696. &SystemBase);
  1697. #ifdef i386
  1698. //
  1699. // If the kernel didn't fit in the preferred range, reset the range to
  1700. // all of memory and try again.
  1701. //
  1702. if ((Status == ENOMEM) &&
  1703. ((BlUsableBase != BL_DRIVER_RANGE_LOW) ||
  1704. (BlUsableLimit != BL_DRIVER_RANGE_HIGH))) {
  1705. BlUsableBase = BL_DRIVER_RANGE_LOW;
  1706. BlUsableLimit = BL_DRIVER_RANGE_HIGH;
  1707. goto retrykernel;
  1708. }
  1709. #endif
  1710. if (Status != ESUCCESS) {
  1711. BlFatalError(LOAD_SW_MIS_FILE_CLASS,
  1712. DIAG_BL_LOAD_SYSTEM_IMAGE,
  1713. LOAD_SW_FILE_REINST_ACT);
  1714. goto LoadFailed;
  1715. }
  1716. BlUpdateBootStatus();
  1717. //
  1718. // Whatever filesystem was used to load the kernel image is the
  1719. // one that needs to be loaded along with the boot drivers.
  1720. //
  1721. #if defined(REMOTE_BOOT)
  1722. if (BlBootingFromNet) {
  1723. //
  1724. // For a remote boot, the boot file system is always NTFS.
  1725. //
  1726. BootFileSystem = L"ntfs";
  1727. } else
  1728. #endif // defined(REMOTE_BOOT)
  1729. {
  1730. FsInfo = BlGetFsInfo(LoadDeviceId);
  1731. if (FsInfo != NULL) {
  1732. BootFileSystem = FsInfo->DriverName;
  1733. } else {
  1734. BlFatalError(LOAD_SW_MIS_FILE_CLASS,
  1735. DIAG_BL_LOAD_SYSTEM_IMAGE,
  1736. LOAD_SW_FILE_REINST_ACT);
  1737. goto LoadFailed;
  1738. }
  1739. }
  1740. //
  1741. // Load the HAL DLL image into memory.
  1742. //
  1743. BlOutputLoadMessage(LoadDevice, HalPathName, NULL);
  1744. #ifdef i386
  1745. retryhal:
  1746. #endif
  1747. Status = BlLoadImage(LoadDeviceId,
  1748. LoaderHalCode,
  1749. HalPathName,
  1750. TARGET_IMAGE,
  1751. &HalBase);
  1752. #ifdef i386
  1753. //
  1754. // If the HAL didn't fit in the preferred range, reset the range to
  1755. // all of memory and try again.
  1756. //
  1757. if ((Status == ENOMEM) &&
  1758. ((BlUsableBase != BL_DRIVER_RANGE_LOW) ||
  1759. (BlUsableLimit != BL_DRIVER_RANGE_HIGH))) {
  1760. BlUsableBase = BL_DRIVER_RANGE_LOW;
  1761. BlUsableLimit = BL_DRIVER_RANGE_HIGH;
  1762. goto retryhal;
  1763. }
  1764. #endif
  1765. if (Status != ESUCCESS) {
  1766. BlFatalError(LOAD_SW_MIS_FILE_CLASS,
  1767. DIAG_BL_LOAD_HAL_IMAGE,
  1768. LOAD_SW_FILE_REINST_ACT);
  1769. goto LoadFailed;
  1770. }
  1771. BlUpdateBootStatus();
  1772. //
  1773. // Load the Kernel Debugger DLL image into memory.
  1774. //
  1775. KdDllLoadFailed = FALSE;
  1776. strcpy(&KdDllName[0], KernelDirectoryPath);
  1777. strcat(&KdDllName[0], KdFileName);
  1778. BlOutputLoadMessage(LoadDevice, &KdDllName[0], NULL);
  1779. Status = BlLoadImage(LoadDeviceId,
  1780. LoaderSystemCode,
  1781. &KdDllName[0],
  1782. TARGET_IMAGE,
  1783. &KdDllBase);
  1784. if ((Status != ESUCCESS) && (UseAlternateKdDll == TRUE)) {
  1785. UseAlternateKdDll = FALSE;
  1786. strcpy(&KdDllName[0], KernelDirectoryPath);
  1787. strcat(&KdDllName[0], "kdcom.dll");
  1788. BlOutputLoadMessage(LoadDevice, &KdDllName[0], NULL);
  1789. Status = BlLoadImage(LoadDeviceId,
  1790. LoaderSystemCode,
  1791. &KdDllName[0],
  1792. TARGET_IMAGE,
  1793. &KdDllBase);
  1794. }
  1795. //
  1796. // Don't bugcheck if KDCOM.DLL is not present, we may be trying to dual-
  1797. // boot an older OS. If we really do require KDCOM.DLL, we will fail to
  1798. // scan the import table for the system image, and bugcheck with kernel
  1799. // needed DLLs to load
  1800. //
  1801. if (Status != ESUCCESS) {
  1802. KdDllLoadFailed = TRUE;
  1803. }
  1804. BlUpdateBootStatus();
  1805. //
  1806. // Set allocatable range to the driver-specific range
  1807. //
  1808. BlUsableBase = BL_DRIVER_RANGE_LOW;
  1809. BlUsableLimit = BL_DRIVER_RANGE_HIGH;
  1810. //
  1811. // Generate a loader data entry for the system image.
  1812. //
  1813. Status = BlAllocateDataTableEntry("ntoskrnl.exe",
  1814. KernelPathName,
  1815. SystemBase,
  1816. &SystemDataTableEntry);
  1817. if (Status != ESUCCESS) {
  1818. BlFatalError(LOAD_SW_INT_ERR_CLASS,
  1819. DIAG_BL_LOAD_SYSTEM_IMAGE,
  1820. LOAD_SW_INT_ERR_ACT);
  1821. goto LoadFailed;
  1822. }
  1823. //
  1824. // Generate a loader data entry for the HAL DLL.
  1825. //
  1826. Status = BlAllocateDataTableEntry("hal.dll",
  1827. HalPathName,
  1828. HalBase,
  1829. &HalDataTableEntry);
  1830. if (Status != ESUCCESS) {
  1831. BlFatalError(LOAD_SW_INT_ERR_CLASS,
  1832. DIAG_BL_LOAD_HAL_IMAGE,
  1833. LOAD_SW_INT_ERR_ACT);
  1834. goto LoadFailed;
  1835. }
  1836. //
  1837. // Generate a loader data entry for the Kernel Debugger DLL.
  1838. //
  1839. if (!KdDllLoadFailed) {
  1840. Status = BlAllocateDataTableEntry("kdcom.dll",
  1841. KdDllName,
  1842. KdDllBase,
  1843. &KdDataTableEntry);
  1844. if (Status != ESUCCESS) {
  1845. BlFatalError(LOAD_SW_INT_ERR_CLASS,
  1846. DIAG_BL_LOAD_SYSTEM_DLLS,
  1847. LOAD_SW_INT_ERR_ACT);
  1848. goto LoadFailed;
  1849. }
  1850. }
  1851. //
  1852. // Scan the import table for the system image and load all referenced
  1853. // DLLs.
  1854. //
  1855. Status = BlScanImportDescriptorTable(&KernelPathSet,
  1856. SystemDataTableEntry,
  1857. LoaderSystemCode);
  1858. if (Status != ESUCCESS) {
  1859. BlFatalError(LOAD_SW_INT_ERR_CLASS,
  1860. DIAG_BL_LOAD_SYSTEM_DLLS,
  1861. LOAD_SW_INT_ERR_ACT);
  1862. goto LoadFailed;
  1863. }
  1864. //
  1865. // Scan the import table for the HAL DLL and load all referenced DLLs.
  1866. //
  1867. Status = BlScanImportDescriptorTable(&KernelPathSet,
  1868. HalDataTableEntry,
  1869. LoaderHalCode);
  1870. if (Status != ESUCCESS) {
  1871. BlFatalError(LOAD_SW_INT_ERR_CLASS,
  1872. DIAG_BL_LOAD_HAL_DLLS,
  1873. LOAD_SW_INT_ERR_ACT);
  1874. goto LoadFailed;
  1875. }
  1876. //
  1877. // Scan the import table for the Kernel Debugger DLL and load all
  1878. // referenced DLLs.
  1879. //
  1880. if (!KdDllLoadFailed) {
  1881. Status = BlScanImportDescriptorTable(&KernelPathSet,
  1882. KdDataTableEntry,
  1883. LoaderSystemCode);
  1884. if (Status != ESUCCESS) {
  1885. BlFatalError(LOAD_SW_INT_ERR_CLASS,
  1886. DIAG_BL_LOAD_SYSTEM_DLLS,
  1887. LOAD_SW_INT_ERR_ACT);
  1888. goto LoadFailed;
  1889. }
  1890. }
  1891. //
  1892. // Relocate the system entry point and set system specific information.
  1893. //
  1894. NtHeaders = RtlImageNtHeader(SystemBase);
  1895. SystemEntry = (PTRANSFER_ROUTINE)((ULONG_PTR)SystemBase +
  1896. NtHeaders->OptionalHeader.AddressOfEntryPoint);
  1897. #if defined(_IA64_)
  1898. BlLoaderBlock->u.Ia64.KernelVirtualBase = (ULONG_PTR)SystemBase;
  1899. BlLoaderBlock->u.Ia64.KernelPhysicalBase = (ULONG_PTR)SystemBase & 0x7fffffff;
  1900. #endif
  1901. //
  1902. // Allocate a structure for NLS data which will be loaded and filled
  1903. // by BlLoadAndScanSystemHive.
  1904. //
  1905. BlLoaderBlock->NlsData = BlAllocateHeap(sizeof(NLS_DATA_BLOCK));
  1906. if (BlLoaderBlock->NlsData == NULL) {
  1907. Status = ENOMEM;
  1908. BlFatalError(LOAD_HW_MEM_CLASS,
  1909. DIAG_BL_LOAD_SYSTEM_HIVE,
  1910. LOAD_HW_MEM_ACT);
  1911. goto LoadFailed;
  1912. }
  1913. #if defined(REMOTE_BOOT)
  1914. //
  1915. // If booting from the net, we use the SetupLoaderBlock to pass
  1916. // information. BlLoadAndScanSystemHive fills in the netboot card
  1917. // fields if present in the registry.
  1918. //
  1919. if (BlBootingFromNet) {
  1920. BlLoaderBlock->SetupLoaderBlock->NetbootCardInfo = BlAllocateHeap(sizeof(NET_CARD_INFO));
  1921. if ( BlLoaderBlock->SetupLoaderBlock->NetbootCardInfo == NULL ) {
  1922. Status = ENOMEM;
  1923. BlFatalError(LOAD_HW_MEM_CLASS,
  1924. DIAG_BL_MEMORY_INIT,
  1925. LOAD_HW_MEM_ACT);
  1926. goto LoadFailed;
  1927. }
  1928. BlLoaderBlock->SetupLoaderBlock->NetbootCardInfoLength = sizeof(NET_CARD_INFO);
  1929. }
  1930. #endif // defined(REMOTE_BOOT)
  1931. //
  1932. // Load the SYSTEM hive.
  1933. //
  1934. //
  1935. bLastKnownGoodChosenLate = bLastKnownGood;
  1936. Status = BlLoadAndScanSystemHive(LoadDeviceId,
  1937. LoadDevice,
  1938. LoadFileName,
  1939. BootFileSystem,
  1940. &bLastKnownGoodChosenLate,
  1941. &ServerHive,
  1942. BadFileName);
  1943. if (Status != ESUCCESS) {
  1944. if (BlRebootSystem != FALSE) {
  1945. Status = ESUCCESS;
  1946. } else {
  1947. BlBadFileMessage(BadFileName);
  1948. }
  1949. goto LoadFailed;
  1950. }
  1951. if (bLastKnownGoodChosenLate) {
  1952. //
  1953. // The user may have selected last known good boot after the kernel and
  1954. // friends were loaded. Update the boot path list here as neccessary.
  1955. //
  1956. if (!bLastKnownGood) {
  1957. ASSERT((LoadDevicePathSet.PathCount < MAX_PATH_SOURCES) &&
  1958. (LoadDevicePathSet.PathCount == 1));
  1959. //
  1960. // Move the current boot path to the end of our last good array.
  1961. //
  1962. LoadDevicePathSet.Source[2] = LoadDevicePathSet.Source[0];
  1963. //
  1964. // Add the last known good paths as if we are in a LastKnownGood boot.
  1965. //
  1966. LoadDevicePathSet.Source[0].DeviceId = LoadDeviceId;
  1967. LoadDevicePathSet.Source[0].DeviceName = LoadDevice;
  1968. LoadDevicePathSet.Source[0].DirectoryPath = LoadDeviceLKG1Path;
  1969. LoadDevicePathSet.Source[1].DeviceId = LoadDeviceId;
  1970. LoadDevicePathSet.Source[1].DeviceName = LoadDevice;
  1971. LoadDevicePathSet.Source[1].DirectoryPath = LoadDeviceLKG2Path;
  1972. LoadDevicePathSet.PathCount = 3;
  1973. bLastKnownGood = TRUE;
  1974. }
  1975. } else {
  1976. //
  1977. // The user might have changed his mind and deselected LKG. If so undo
  1978. // the path work here.
  1979. //
  1980. if (bLastKnownGood) {
  1981. ASSERT((LoadDevicePathSet.PathCount < MAX_PATH_SOURCES) &&
  1982. (LoadDevicePathSet.PathCount == 3));
  1983. //
  1984. // Move the current boot path to the end of our last good array.
  1985. //
  1986. LoadDevicePathSet.Source[0] = LoadDevicePathSet.Source[2];
  1987. LoadDevicePathSet.PathCount = 1;
  1988. bLastKnownGood = FALSE;
  1989. }
  1990. }
  1991. //
  1992. // Count the number of drivers we need to load
  1993. //
  1994. BlMaxFilesToLoad = BlNumFilesLoaded;
  1995. BootDriverListHead = &(BlLoaderBlock->BootDriverListHead);
  1996. NextEntry = BootDriverListHead->Flink ;
  1997. while (NextEntry != BootDriverListHead) {
  1998. DriverNode = CONTAINING_RECORD(NextEntry,
  1999. BOOT_DRIVER_NODE,
  2000. ListEntry.Link);
  2001. DriverEntry = &DriverNode->ListEntry;
  2002. NextEntry = DriverEntry->Link.Flink;
  2003. BlMaxFilesToLoad++;
  2004. }
  2005. //
  2006. // Rescale the progress bar
  2007. //
  2008. BlRedrawProgressBar();
  2009. //
  2010. // Insert the headless driver onto the boot driver list if this is supposed to be a
  2011. // headless boot.
  2012. //
  2013. // The SAC is only availabe on server products, so we need to check the
  2014. // product type.
  2015. //
  2016. if ((BlLoaderBlock->Extension->HeadlessLoaderBlock != NULL) && ServerHive) {
  2017. BlAddToBootDriverList(
  2018. &BlLoaderBlock->BootDriverListHead,
  2019. L"sacdrv.sys", // Driver name
  2020. L"sacdrv", // Service
  2021. L"SAC", // Group
  2022. 1, // Tag
  2023. NormalError, // ErrorControl
  2024. TRUE // Insert at head of list
  2025. );
  2026. }
  2027. #if defined(REMOTE_BOOT)
  2028. //
  2029. // If booting from the net, then save the IP address and subnet mask,
  2030. // and determine which net card driver we need to load. This may involve
  2031. // doing an exchange with the server if the registry is not set up
  2032. // correctly.
  2033. //
  2034. if (BlBootingFromNet && NetworkBootRom) {
  2035. NET_CARD_INFO tempNetCardInfo;
  2036. PSETUP_LOADER_BLOCK setupLoaderBlock = BlLoaderBlock->SetupLoaderBlock;
  2037. //
  2038. // Pass DHCP information to OS for use by TCP/IP
  2039. //
  2040. setupLoaderBlock->IpAddress = NetLocalIpAddress;
  2041. setupLoaderBlock->SubnetMask = NetLocalSubnetMask;
  2042. setupLoaderBlock->DefaultRouter = NetGatewayIpAddress;
  2043. setupLoaderBlock->ServerIpAddress = NetServerIpAddress;
  2044. //
  2045. // Get information about the net card from the ROM.
  2046. //
  2047. NtStatus = NetQueryCardInfo(
  2048. &tempNetCardInfo
  2049. );
  2050. if (NtStatus != STATUS_SUCCESS) {
  2051. Status = ENOMEM;
  2052. BlFatalError(LOAD_HW_MEM_CLASS,
  2053. DIAG_BL_MEMORY_INIT,
  2054. LOAD_HW_MEM_ACT);
  2055. goto LoadFailed;
  2056. }
  2057. //
  2058. // If the net card info is the same as the one that BlLoadAndScanSystemHive
  2059. // stored in the setup loader block, and it also read something into
  2060. // the hardware ID and driver name parameters, then we are fine,
  2061. // otherwise we need to do an exchange with the server to get
  2062. // the information.
  2063. //
  2064. // If we don't do an exchange with the server, then NetbootCardRegistry
  2065. // will stay NULL, which will be OK because even if the card has
  2066. // moved to a different slot, the registry params still go in the
  2067. // same place.
  2068. //
  2069. if ((memcmp(
  2070. &tempNetCardInfo,
  2071. setupLoaderBlock->NetbootCardInfo,
  2072. sizeof(NET_CARD_INFO)) != 0) ||
  2073. (setupLoaderBlock->NetbootCardHardwareId[0] == L'\0') ||
  2074. (setupLoaderBlock->NetbootCardDriverName[0] == L'\0') ||
  2075. (setupLoaderBlock->NetbootCardServiceName[0] == L'\0')) {
  2076. //
  2077. // This call may allocate setupLoaderBlock->NetbootCardRegistry
  2078. //
  2079. //
  2080. // If we ever do go back to remote boot land, we'll have
  2081. // to fill the second parameter with the server setup path of the
  2082. // flat NT image. It doesn't look like we conveniently have it
  2083. // here so we might have to store it in the setup loader block
  2084. // so that we can pass it in here. We'll postpone this work
  2085. // until we do the full remote install work. The path should be
  2086. // set to \srv\reminst\setup\english\images\cd1911.
  2087. //
  2088. NtStatus = NetQueryDriverInfo(
  2089. &tempNetCardInfo,
  2090. NULL,
  2091. SavedLoadFileName,
  2092. setupLoaderBlock->NetbootCardHardwareId,
  2093. sizeof(setupLoaderBlock->NetbootCardHardwareId),
  2094. setupLoaderBlock->NetbootCardDriverName,
  2095. NULL, // don't need NetbootCardDriverName in ANSI
  2096. sizeof(setupLoaderBlock->NetbootCardDriverName),
  2097. setupLoaderBlock->NetbootCardServiceName,
  2098. sizeof(setupLoaderBlock->NetbootCardServiceName),
  2099. &setupLoaderBlock->NetbootCardRegistry,
  2100. &setupLoaderBlock->NetbootCardRegistryLength);
  2101. if (NtStatus != STATUS_SUCCESS) {
  2102. Status = ENOMEM;
  2103. BlFatalError(LOAD_HW_MEM_CLASS,
  2104. DIAG_BL_MEMORY_INIT,
  2105. LOAD_HW_MEM_ACT);
  2106. goto LoadFailed;
  2107. }
  2108. //
  2109. // if we detected a new card, then remember to pin it later.
  2110. //
  2111. if (setupLoaderBlock->NetbootCardRegistry != NULL) {
  2112. setupLoaderBlock->Flags |= SETUPBLK_FLAGS_PIN_NET_DRIVER;
  2113. }
  2114. }
  2115. //
  2116. // Add an entry to the BootDriverList for the netboot card,
  2117. // because it will either not have a registry entry or else
  2118. // will have one with Start set to 3.
  2119. //
  2120. // NOTE: This routine does NOT resort the list.
  2121. //
  2122. BlAddToBootDriverList(
  2123. &BlLoaderBlock->BootDriverListHead,
  2124. setupLoaderBlock->NetbootCardDriverName,
  2125. setupLoaderBlock->NetbootCardServiceName,
  2126. L"NDIS", // Group
  2127. 1, // Tag
  2128. NormalError, // ErrorControl
  2129. FALSE // Insert at Tail of list
  2130. );
  2131. RtlMoveMemory(
  2132. setupLoaderBlock->NetbootCardInfo,
  2133. &tempNetCardInfo,
  2134. sizeof(NET_CARD_INFO)
  2135. );
  2136. }
  2137. #endif // defined(REMOTE_BOOT)
  2138. //
  2139. // Load boot drivers
  2140. //
  2141. Status = BlLoadBootDrivers(&LoadDevicePathSet,
  2142. &BlLoaderBlock->BootDriverListHead,
  2143. BadFileName);
  2144. if (Status != ESUCCESS) {
  2145. if (BlRebootSystem != FALSE) {
  2146. Status = ESUCCESS;
  2147. } else {
  2148. BlBadFileMessage(BadFileName);
  2149. }
  2150. goto LoadFailed;
  2151. }
  2152. //
  2153. // Load the blocked driver database.
  2154. //
  2155. RtlInitUnicodeString(&unicodeString, L"drvmain.sdb");
  2156. strcpy(Directory, LoadFileName);
  2157. strcat(Directory, "\\AppPatch\\");
  2158. //
  2159. // Let the kernel deal with failure to load this driver database.
  2160. //
  2161. BlLoaderBlock->Extension->DrvDBImage = NULL;
  2162. BlLoaderBlock->Extension->DrvDBSize = 0;
  2163. BlLoadDrvDB( LoadDeviceId,
  2164. LoadDevice,
  2165. Directory,
  2166. &unicodeString,
  2167. &BlLoaderBlock->Extension->DrvDBImage,
  2168. &BlLoaderBlock->Extension->DrvDBSize,
  2169. BadFileName);
  2170. #if defined(REMOTE_BOOT)
  2171. if (BlBootingFromNet) {
  2172. ARC_STATUS ArcStatus;
  2173. ULONG FileId;
  2174. //
  2175. // Exchange with the server to set up for the future IPSEC conversation
  2176. // we will have. Whether IPSEC is enabled is determined in BlLoadAndScanSystemHives.
  2177. //
  2178. if ((BlLoaderBlock->SetupLoaderBlock->Flags & SETUPBLK_FLAGS_IPSEC_ENABLED) != 0) {
  2179. BlLoaderBlock->SetupLoaderBlock->IpsecInboundSpi = 0x11111111;
  2180. NetPrepareIpsec(
  2181. BlLoaderBlock->SetupLoaderBlock->IpsecInboundSpi,
  2182. &BlLoaderBlock->SetupLoaderBlock->IpsecSessionKey,
  2183. &BlLoaderBlock->SetupLoaderBlock->IpsecOutboundSpi
  2184. );
  2185. }
  2186. //
  2187. // Indicate whether the CSC needs to be repinned or disabled.
  2188. //
  2189. if ( NetBootRepin ) {
  2190. BlLoaderBlock->SetupLoaderBlock->Flags |= SETUPBLK_FLAGS_REPIN;
  2191. }
  2192. if ( !NetBootCSC ) {
  2193. BlLoaderBlock->SetupLoaderBlock->Flags |= SETUPBLK_FLAGS_DISABLE_CSC;
  2194. }
  2195. //
  2196. // Restore the server\share at the front of the OsLoader and
  2197. // LoadFileName strings.
  2198. //
  2199. OsLoader = SavedOsLoader;
  2200. LoadFileName = SavedLoadFileName;
  2201. //
  2202. // Read the secret off the disk, if there is one, and store it
  2203. // in the loader block.
  2204. //
  2205. ArcStatus = BlOpenRawDisk(&FileId);
  2206. if (ArcStatus == ESUCCESS) {
  2207. BlLoaderBlock->SetupLoaderBlock->NetBootSecret = BlAllocateHeap(sizeof(RI_SECRET));
  2208. if (BlLoaderBlock->SetupLoaderBlock->NetBootSecret == NULL) {
  2209. Status = ENOMEM;
  2210. BlFatalError(LOAD_HW_MEM_CLASS,
  2211. DIAG_BL_MEMORY_INIT,
  2212. LOAD_HW_MEM_ACT);
  2213. goto LoadFailed;
  2214. }
  2215. ArcStatus = BlReadSecret(
  2216. FileId,
  2217. (PRI_SECRET)(BlLoaderBlock->SetupLoaderBlock->NetBootSecret));
  2218. if (Status != ESUCCESS) {
  2219. BlFatalError(LOAD_HW_MEM_CLASS,
  2220. DIAG_BL_MEMORY_INIT,
  2221. LOAD_HW_MEM_ACT);
  2222. goto LoadFailed;
  2223. }
  2224. ArcStatus = BlCloseRawDisk(FileId);
  2225. //
  2226. // By now we have TFTPed some files so this will be TRUE if it
  2227. // is ever going to be.
  2228. //
  2229. BlLoaderBlock->SetupLoaderBlock->NetBootUsePassword2 = NetBootTftpUsedPassword2;
  2230. }
  2231. }
  2232. #endif // defined(REMOTE_BOOT)
  2233. //
  2234. // Generate the ARC boot device name and NT path name.
  2235. //
  2236. Status = BlGenerateDeviceNames(LoadDevice, DeviceName, &DevicePrefix[0]);
  2237. if (Status != ESUCCESS) {
  2238. BlFatalError(LOAD_HW_FW_CFG_CLASS,
  2239. DIAG_BL_ARC_BOOT_DEV_NAME,
  2240. LOAD_HW_FW_CFG_ACT);
  2241. goto LoadFailed;
  2242. }
  2243. FileSize = (ULONG)strlen(DeviceName) + 1;
  2244. FileName = (PCHAR)BlAllocateHeap(FileSize);
  2245. strcpy(FileName, DeviceName);
  2246. BlLoaderBlock->ArcBootDeviceName = FileName;
  2247. FileSize = (ULONG)strlen(LoadFileName) + 2;
  2248. FileName = (PCHAR)BlAllocateHeap( FileSize);
  2249. strcpy(FileName, LoadFileName);
  2250. strcat(FileName, "\\");
  2251. BlLoaderBlock->NtBootPathName = FileName;
  2252. //
  2253. // Generate the ARC HAL device name and NT path name.
  2254. //
  2255. // On the x86, the systempartition variable lies, and instead points to
  2256. // the location of the hal. Therefore, the variable, 'X86SystemPartition'
  2257. // is defined for the real system partition.
  2258. //
  2259. #if defined(_X86_)
  2260. x86SystemPartition = BlGetArgumentValue(Argc, Argv, "x86systempartition");
  2261. strcpy(&DeviceName[0], x86SystemPartition);
  2262. #else
  2263. Status = BlGenerateDeviceNames(SystemDevice, &DeviceName[0], &DevicePrefix[0]);
  2264. if (Status != ESUCCESS) {
  2265. BlFatalError(LOAD_HW_FW_CFG_CLASS,
  2266. DIAG_BL_ARC_BOOT_DEV_NAME,
  2267. LOAD_HW_FW_CFG_ACT);
  2268. goto LoadFailed;
  2269. }
  2270. #endif
  2271. FileSize = (ULONG)strlen(DeviceName) + 1;
  2272. FileName = (PCHAR)BlAllocateHeap(FileSize);
  2273. strcpy(FileName, DeviceName);
  2274. BlLoaderBlock->ArcHalDeviceName = FileName;
  2275. //
  2276. // On the x86, this structure is unfortunately named. What we really need
  2277. // here is the osloader path. What we actually have is a path to the HAL.
  2278. // Since this path is always at the root of the partition, hardcode it here.
  2279. //
  2280. #if defined(_X86_)
  2281. FileName = (PCHAR)BlAllocateHeap(2);
  2282. FileName[0] = '\\';
  2283. FileName[1] = '\0';
  2284. #else
  2285. FileSize = (ULONG)strlen(&SystemDevicePath[0]) + 1;
  2286. FileName = (PCHAR)BlAllocateHeap(FileSize);
  2287. strcpy(FileName, &SystemDevicePath[0]);
  2288. #endif
  2289. BlLoaderBlock->NtHalPathName = FileName;
  2290. //
  2291. // Close the open handles & stop caching on closed devices.
  2292. //
  2293. ArcClose(LoadDeviceId);
  2294. if (bDiskCacheInitialized) {
  2295. BlDiskCacheStopCachingOnDevice(LoadDeviceId);
  2296. }
  2297. //
  2298. // Close the system device only if it is different from the
  2299. // LoadDevice.
  2300. //
  2301. if (SystemDeviceId != LoadDeviceId) {
  2302. ArcClose(SystemDeviceId);
  2303. if (bDiskCacheInitialized) {
  2304. BlDiskCacheStopCachingOnDevice(SystemDeviceId);
  2305. }
  2306. }
  2307. //
  2308. // Bump the progress bar all the way to 100% as this is our last chance
  2309. // before we jump into the kernel.
  2310. //
  2311. BlUpdateProgressBar(100);
  2312. if ( BlBootingFromNet ) {
  2313. //
  2314. // If booting from Network, we should save the network information
  2315. // in the network loader block for use by the kernel.
  2316. //
  2317. BlLoaderBlock->Extension->NetworkLoaderBlock = BlAllocateHeap(sizeof(NETWORK_LOADER_BLOCK));
  2318. if (BlLoaderBlock->Extension->NetworkLoaderBlock == NULL) {
  2319. Status = ENOMEM;
  2320. BlFatalError(LOAD_HW_MEM_CLASS,
  2321. DIAG_BL_MEMORY_INIT,
  2322. LOAD_HW_MEM_ACT);
  2323. goto LoadFailed;
  2324. }
  2325. memset( BlLoaderBlock->Extension->NetworkLoaderBlock, 0, sizeof(NETWORK_LOADER_BLOCK) );
  2326. //
  2327. // Pass DHCP information to OS for use by TCP/IP
  2328. //
  2329. NtStatus = NetFillNetworkLoaderBlock(BlLoaderBlock->Extension->NetworkLoaderBlock);
  2330. if (NtStatus != STATUS_SUCCESS) {
  2331. Status = NtStatus;
  2332. BlFatalError(LOAD_HW_MEM_CLASS,
  2333. DIAG_BL_MEMORY_INIT,
  2334. LOAD_HW_MEM_ACT);
  2335. goto LoadFailed;
  2336. }
  2337. //
  2338. // Close down the remote boot network file system.
  2339. //
  2340. // NOTE: If BlBootingFromNet, don't do anything after this point
  2341. // that would cause access to the boot ROM.
  2342. //
  2343. NetTerminate();
  2344. }
  2345. #if defined(_X86_)
  2346. //
  2347. // Write out the boot status flags to disk so we can determine if the
  2348. // OS fails to boot.
  2349. //
  2350. BlWriteBootStatusFlags(LoadDeviceId, (PUCHAR)LoadFileName, FALSE, FALSE);
  2351. #endif
  2352. #if defined(_X86_)
  2353. //
  2354. // Close down the arc emulator's i/o system if we initialized it.
  2355. // This cannot be done after BlSetupForNt becase that routine will
  2356. // unmap the miniport code the arc emulator may need to shutdown.
  2357. //
  2358. AETerminateIo();
  2359. #endif
  2360. //
  2361. // Execute the architecture specific setup code.
  2362. //
  2363. Status = BlSetupForNt(BlLoaderBlock);
  2364. if (Status != ESUCCESS) {
  2365. BlFatalError(LOAD_SW_INT_ERR_CLASS,
  2366. DIAG_BL_SETUP_FOR_NT,
  2367. LOAD_SW_INT_ERR_ACT);
  2368. goto LoadFailed;
  2369. }
  2370. //
  2371. // Transfer control to loaded image.
  2372. //
  2373. BlTransferToKernel(SystemEntry, BlLoaderBlock);
  2374. //
  2375. // Any return from the system is an error.
  2376. //
  2377. Status = EBADF;
  2378. BlFatalError(LOAD_SW_BAD_FILE_CLASS,
  2379. DIAG_BL_KERNEL_INIT_XFER,
  2380. LOAD_SW_FILE_REINST_ACT);
  2381. //
  2382. // The load failed.
  2383. //
  2384. LoadFailed:
  2385. //
  2386. // We do not know if the devices we are caching will be
  2387. // closed/reopened etc beyond this function. To be safe,
  2388. // uninitialize the disk caching.
  2389. //
  2390. if (bDiskCacheInitialized) {
  2391. BlDiskCacheUninitialize();
  2392. }
  2393. return Status;
  2394. }
  2395. VOID
  2396. BlOutputLoadMessage (
  2397. IN PCHAR DeviceName,
  2398. IN PCHAR FileName,
  2399. IN PTCHAR FileDescription OPTIONAL
  2400. )
  2401. /*++
  2402. Routine Description:
  2403. This routine outputs a loading message to the console output device.
  2404. Arguments:
  2405. DeviceName - Supplies a pointer to a zero terminated device name.
  2406. FileName - Supplies a pointer to a zero terminated file name.
  2407. FileDescription - Friendly name of the file in question.
  2408. Return Value:
  2409. None.
  2410. --*/
  2411. {
  2412. ULONG Count;
  2413. CHAR OutputBuffer[256];
  2414. #ifdef UNICODE
  2415. TCHAR OutputBufferUnicode[256];
  2416. ANSI_STRING aString;
  2417. UNICODE_STRING uString;
  2418. #endif
  2419. PTCHAR p;
  2420. UNREFERENCED_PARAMETER(FileDescription);
  2421. if(!DisplayLogoOnBoot) {
  2422. //
  2423. // Proceed only if no logo is displayed.
  2424. ///////////////////////////////////////////////
  2425. //
  2426. // Construct and output loading file message.
  2427. //
  2428. if (!BlOutputDots) {
  2429. strcpy(&OutputBuffer[0], " ");
  2430. if (DeviceName)
  2431. strcat(&OutputBuffer[0], DeviceName);
  2432. if (FileName)
  2433. strcat(&OutputBuffer[0], FileName);
  2434. strcat(&OutputBuffer[0], "\r\n");
  2435. BlLog((LOG_LOGFILE,OutputBuffer));
  2436. #ifdef UNICODE
  2437. p = OutputBufferUnicode;
  2438. uString.Buffer = OutputBufferUnicode;
  2439. uString.MaximumLength = sizeof(OutputBufferUnicode);
  2440. RtlInitAnsiString(&aString, OutputBuffer );
  2441. RtlAnsiStringToUnicodeString( &uString, &aString, FALSE );
  2442. #else
  2443. p = OutputBuffer;
  2444. #endif
  2445. ArcWrite(BlConsoleOutDeviceId,
  2446. p,
  2447. (ULONG)_tcslen(p)*sizeof(TCHAR),
  2448. &Count);
  2449. }
  2450. }
  2451. return;
  2452. }
  2453. ARC_STATUS
  2454. BlLoadAndScanSystemHive(
  2455. IN ULONG DeviceId,
  2456. IN PCHAR DeviceName,
  2457. IN PCHAR DirectoryPath,
  2458. IN PWSTR BootFileSystem,
  2459. IN OUT BOOLEAN *LastKnownGoodBoot,
  2460. OUT BOOLEAN *ServerHive,
  2461. OUT PCHAR BadFileName
  2462. )
  2463. /*++
  2464. Routine Description:
  2465. This function loads the system hive into memory, verifies its
  2466. consistency, scans it for the list of boot drivers, and loads
  2467. the resulting list of drivers.
  2468. If the system hive cannot be loaded or is not a valid hive, it
  2469. is rejected and the system.alt hive is used. If this is invalid,
  2470. the boot must fail.
  2471. Arguments:
  2472. DeviceId - Supplies the file id of the device the system tree is on.
  2473. DeviceName - Supplies the name of the device the system tree is on.
  2474. DirectoryPath - Supplies a pointer to the zero-terminated directory path
  2475. of the root of the NT system32 directory.
  2476. HiveName - Supplies the name of the SYSTEM hive
  2477. LastKnownGoodBoot - On input, LastKnownGood indicates whether LKG has been
  2478. selected. This value is updated to TRUE if the user
  2479. chooses LKG via the profile configuration menu.
  2480. ServerHive - Return TRUE if this is a server hive, else FALSE.
  2481. BadFileName - Returns the file required for booting that was corrupt
  2482. or missing. This will not be filled in if ESUCCESS is returned.
  2483. Return Value:
  2484. ESUCCESS - System hive valid and all necessary boot drivers successfully
  2485. loaded.
  2486. !ESUCCESS - System hive corrupt or critical boot drivers not present.
  2487. LastKnownGoodBoot receives FALSE, BadFileName contains name
  2488. of corrupted/missing file.
  2489. --*/
  2490. {
  2491. ARC_STATUS Status;
  2492. PTCHAR FailReason;
  2493. CHAR Directory[256];
  2494. CHAR FontDirectory[256];
  2495. UNICODE_STRING AnsiCodepage;
  2496. UNICODE_STRING OemCodepage;
  2497. UNICODE_STRING OemHalFont;
  2498. UNICODE_STRING LanguageTable;
  2499. BOOLEAN RestartSetup;
  2500. BOOLEAN LogPresent;
  2501. #ifdef _WANT_MACHINE_IDENTIFICATION
  2502. UNICODE_STRING unicodeString;
  2503. #endif
  2504. if (sizeof(Directory) < strlen(DirectoryPath) + sizeof("\\system32\\config\\")) {
  2505. return ENOMEM;
  2506. }
  2507. strcpy(Directory,DirectoryPath);
  2508. strcat(Directory,"\\system32\\config\\");
  2509. Status = BlLoadAndInitSystemHive(DeviceId,
  2510. DeviceName,
  2511. Directory,
  2512. "system",
  2513. FALSE,
  2514. &RestartSetup,
  2515. &LogPresent);
  2516. if(Status != ESUCCESS) {
  2517. if( !LogPresent ) {
  2518. //
  2519. // Bogus hive, try system.alt only if no log is present.
  2520. //
  2521. Status = BlLoadAndInitSystemHive(DeviceId,
  2522. DeviceName,
  2523. Directory,
  2524. "system.alt",
  2525. TRUE,
  2526. &RestartSetup,
  2527. &LogPresent);
  2528. }
  2529. if(Status != ESUCCESS) {
  2530. strcpy(BadFileName,DirectoryPath);
  2531. strcat(BadFileName,"\\SYSTEM32\\CONFIG\\SYSTEM");
  2532. goto HiveScanFailed;
  2533. }
  2534. }
  2535. if(RestartSetup) {
  2536. //
  2537. // Need to restart setup.
  2538. //
  2539. Status = BlLoadAndInitSystemHive(DeviceId,
  2540. DeviceName,
  2541. Directory,
  2542. "system.sav",
  2543. TRUE,
  2544. &RestartSetup,
  2545. &LogPresent);
  2546. if(Status != ESUCCESS) {
  2547. strcpy(BadFileName,DirectoryPath);
  2548. strcat(BadFileName,"\\SYSTEM32\\CONFIG\\SYSTEM.SAV");
  2549. goto HiveScanFailed;
  2550. }
  2551. }
  2552. //
  2553. // Hive is there, it's valid, go compute the driver list and NLS
  2554. // filenames. Note that if this fails, there is no point in switching
  2555. // to system.alt, since it will always be the same as system.
  2556. //
  2557. FailReason = BlScanRegistry(BootFileSystem,
  2558. LastKnownGoodBoot,
  2559. &BlLoaderBlock->BootDriverListHead,
  2560. &AnsiCodepage,
  2561. &OemCodepage,
  2562. &LanguageTable,
  2563. &OemHalFont,
  2564. #ifdef _WANT_MACHINE_IDENTIFICATION
  2565. &unicodeString,
  2566. #endif
  2567. BlLoaderBlock->SetupLoaderBlock,
  2568. ServerHive);
  2569. if (FailReason != NULL) {
  2570. Status = EBADF;
  2571. strcpy(BadFileName,Directory);
  2572. strcat(BadFileName,"SYSTEM");
  2573. goto HiveScanFailed;
  2574. }
  2575. strcpy(Directory,DirectoryPath);
  2576. strcat(Directory,"\\system32\\");
  2577. //
  2578. // Load NLS data tables.
  2579. //
  2580. Status = BlLoadNLSData(DeviceId,
  2581. DeviceName,
  2582. Directory,
  2583. &AnsiCodepage,
  2584. &OemCodepage,
  2585. &LanguageTable,
  2586. BadFileName);
  2587. if (Status != ESUCCESS) {
  2588. goto HiveScanFailed;
  2589. }
  2590. //
  2591. // Load the OEM font file to be used by the HAL for possible frame
  2592. // buffer displays.
  2593. //
  2594. #ifdef i386
  2595. if (OemHalFont.Buffer == NULL) {
  2596. goto oktoskipfont;
  2597. }
  2598. #endif
  2599. //
  2600. // On newer systems fonts are in the FONTS directory.
  2601. // On older systems fonts are in the SYSTEM directory.
  2602. //
  2603. strcpy(FontDirectory, DirectoryPath);
  2604. strcat(FontDirectory, "\\FONTS\\");
  2605. Status = BlLoadOemHalFont(DeviceId,
  2606. DeviceName,
  2607. FontDirectory,
  2608. &OemHalFont,
  2609. BadFileName);
  2610. if(Status != ESUCCESS) {
  2611. strcpy(FontDirectory, DirectoryPath);
  2612. strcat(FontDirectory, "\\SYSTEM\\");
  2613. Status = BlLoadOemHalFont(DeviceId,
  2614. DeviceName,
  2615. FontDirectory,
  2616. &OemHalFont,
  2617. BadFileName);
  2618. }
  2619. if (Status != ESUCCESS) {
  2620. #ifndef i386
  2621. goto HiveScanFailed;
  2622. #endif
  2623. }
  2624. #ifdef i386
  2625. oktoskipfont:
  2626. #endif
  2627. if (BlLoaderBlock->Extension && BlLoaderBlock->Extension->Size >= sizeof(LOADER_PARAMETER_EXTENSION)) {
  2628. ULONG majorVersion;
  2629. ULONG minorVersion;
  2630. CHAR versionBuffer[64];
  2631. PCHAR major;
  2632. PCHAR minor;
  2633. major = strcpy(versionBuffer, VER_PRODUCTVERSION_STR);
  2634. minor = strchr(major, '.');
  2635. *minor++ = '\0';
  2636. majorVersion = atoi(major);
  2637. minorVersion = atoi(minor);
  2638. if ( BlLoaderBlock->Extension->MajorVersion > majorVersion ||
  2639. (BlLoaderBlock->Extension->MajorVersion == majorVersion &&
  2640. BlLoaderBlock->Extension->MinorVersion >= minorVersion)) {
  2641. #ifdef i386
  2642. #ifdef _WANT_MACHINE_IDENTIFICATION
  2643. if (unicodeString.Length) {
  2644. //
  2645. // For x86 machines, read in the inf into memory for processing
  2646. // by the kernel.
  2647. //
  2648. strcpy(Directory,DirectoryPath);
  2649. strcat(Directory,"\\inf\\");
  2650. //
  2651. // Fail to boot if there is any error in loading this
  2652. // critical inf.
  2653. //
  2654. Status = BlLoadBiosinfoInf( DeviceId,
  2655. DeviceName,
  2656. Directory,
  2657. &unicodeString,
  2658. &BlLoaderBlock->Extension->InfFileImage,
  2659. &BlLoaderBlock->Extension->InfFileSize,
  2660. BadFileName);
  2661. if (Status != ESUCCESS) {
  2662. goto HiveScanFailed;
  2663. }
  2664. }
  2665. #endif
  2666. #endif
  2667. }
  2668. }
  2669. HiveScanFailed:
  2670. if (Status != ESUCCESS) {
  2671. *LastKnownGoodBoot = FALSE;
  2672. }
  2673. return(Status);
  2674. }
  2675. VOID
  2676. BlBadFileMessage(
  2677. IN PCHAR BadFileName
  2678. )
  2679. /*++
  2680. Routine Description:
  2681. This function displays the error message for a missing or incorrect
  2682. critical file.
  2683. Arguments:
  2684. BadFileName - Supplies the name of the file that is missing or
  2685. corrupt.
  2686. Return Value:
  2687. None.
  2688. --*/
  2689. {
  2690. ULONG Count;
  2691. PTCHAR Text;
  2692. PTSTR pBadFileName;
  2693. #ifdef UNICODE
  2694. WCHAR BadFileNameW[128];
  2695. ANSI_STRING aString;
  2696. UNICODE_STRING uString;
  2697. pBadFileName = BadFileNameW;
  2698. uString.Buffer = BadFileNameW;
  2699. uString.MaximumLength = sizeof(BadFileNameW);
  2700. RtlInitAnsiString(&aString, BadFileName);
  2701. RtlAnsiStringToUnicodeString( &uString, &aString, FALSE );
  2702. #else
  2703. pBadFileName = BadFileName;
  2704. #endif
  2705. ArcWrite(BlConsoleOutDeviceId,
  2706. TEXT("\r\n"),
  2707. (ULONG)_tcslen(TEXT("\r\n"))*sizeof(TCHAR),
  2708. &Count);
  2709. //
  2710. // Remove any remains from the last known good message.
  2711. //
  2712. BlClearToEndOfScreen();
  2713. Text = BlFindMessage(LOAD_SW_MIS_FILE_CLASS);
  2714. if (Text != NULL) {
  2715. ArcWrite(BlConsoleOutDeviceId,
  2716. Text,
  2717. (ULONG)_tcslen(Text)*sizeof(TCHAR),
  2718. &Count);
  2719. }
  2720. ArcWrite(BlConsoleOutDeviceId,
  2721. pBadFileName,
  2722. (ULONG)_tcslen(pBadFileName)*sizeof(TCHAR),
  2723. &Count);
  2724. ArcWrite(BlConsoleOutDeviceId,
  2725. TEXT("\r\n\r\n"),
  2726. (ULONG)_tcslen(TEXT("\r\n\r\n"))*sizeof(TCHAR),
  2727. &Count);
  2728. Text = BlFindMessage(LOAD_SW_FILE_REST_ACT);
  2729. if (Text != NULL) {
  2730. ArcWrite(BlConsoleOutDeviceId,
  2731. Text,
  2732. (ULONG)_tcslen(Text)*sizeof(TCHAR),
  2733. &Count);
  2734. }
  2735. }
  2736. VOID
  2737. BlClearToEndOfScreen(
  2738. VOID
  2739. );
  2740. VOID
  2741. BlFatalError(
  2742. IN ULONG ClassMessage,
  2743. IN ULONG DetailMessage,
  2744. IN ULONG ActionMessage
  2745. )
  2746. /*++
  2747. Routine Description:
  2748. This function looks up messages to display at a error condition.
  2749. It attempts to locate the string in the resource section of the
  2750. osloader. If that fails, it prints a numerical error code.
  2751. The only time it should print a numerical error code is if the
  2752. resource section could not be located. This will only happen
  2753. on ARC machines where boot fails before the osloader.exe file
  2754. can be opened.
  2755. Arguments:
  2756. ClassMessage - General message that describes the class of
  2757. problem.
  2758. DetailMessage - Detailed description of what caused problem
  2759. ActionMessage - Message that describes a course of action
  2760. for user to take.
  2761. Return Value:
  2762. none
  2763. --*/
  2764. {
  2765. PTCHAR Text;
  2766. TCHAR Buffer[40];
  2767. ULONG Count;
  2768. ArcWrite(BlConsoleOutDeviceId,
  2769. TEXT("\r\n"),
  2770. (ULONG)_tcslen(TEXT("\r\n"))*sizeof(TCHAR),
  2771. &Count);
  2772. //
  2773. // Remove any remains from the last known good message.
  2774. //
  2775. BlClearToEndOfScreen();
  2776. Text = BlFindMessage(ClassMessage);
  2777. if (Text == NULL) {
  2778. _stprintf(Buffer,TEXT("%08lx\r\n"),ClassMessage);
  2779. Text = Buffer;
  2780. }
  2781. ArcWrite(BlConsoleOutDeviceId,
  2782. Text,
  2783. (ULONG)_tcslen(Text)*sizeof(TCHAR),
  2784. &Count);
  2785. Text = BlFindMessage(DetailMessage);
  2786. if (Text == NULL) {
  2787. _stprintf(Buffer,TEXT("%08lx\r\n"),DetailMessage);
  2788. Text = Buffer;
  2789. }
  2790. ArcWrite(BlConsoleOutDeviceId,
  2791. Text,
  2792. (ULONG)_tcslen(Text)*sizeof(TCHAR),
  2793. &Count);
  2794. Text = BlFindMessage(ActionMessage);
  2795. if (Text == NULL) {
  2796. _stprintf(Buffer,TEXT("%08lx\r\n"),ActionMessage);
  2797. Text = Buffer;
  2798. }
  2799. ArcWrite(BlConsoleOutDeviceId,
  2800. Text,
  2801. (ULONG)_tcslen(Text)*sizeof(TCHAR),
  2802. &Count);
  2803. #if defined(ENABLE_LOADER_DEBUG) || DBG
  2804. #if (defined(_X86_) || defined(_ALPHA_) || defined(_IA64_)) && !defined(ARCI386) // everything but ARCI386
  2805. if(BdDebuggerEnabled) {
  2806. DbgBreakPoint();
  2807. }
  2808. #endif
  2809. #endif
  2810. return;
  2811. }