Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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