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.

6709 lines
194 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. setup.c
  5. Abstract:
  6. This module contains the code that implements the NT setup loader
  7. Author:
  8. John Vert (jvert) 6-Oct-1993
  9. Environment:
  10. ARC Environment
  11. Revision History:
  12. --*/
  13. #include <setupbat.h>
  14. #include "setupldr.h"
  15. #include "stdio.h"
  16. #include "string.h"
  17. #include "stdlib.h"
  18. #include <dockinfo.h>
  19. #include <netboot.h>
  20. #include <ramdisk.h>
  21. #include "acpitabl.h"
  22. #ifdef i386
  23. #include <bldrx86.h>
  24. #endif
  25. #if defined(_IA64_)
  26. #include "bldria64.h"
  27. #endif
  28. #if defined(EFI)
  29. #include "bootefi.h"
  30. #endif
  31. #if defined(_IA64_)
  32. UCHAR OsLoaderName[] = "setupldr.efi";
  33. #else
  34. UCHAR OsLoaderName[] = "setupldr.exe";
  35. #endif
  36. #if defined(_WIN64) && defined(_M_IA64)
  37. #pragma section(".base", long, read, write)
  38. __declspec(allocate(".base"))
  39. extern
  40. PVOID __ImageBase;
  41. #else
  42. extern
  43. PVOID __ImageBase;
  44. #endif
  45. #define BlDiagLoadMessage(x,y,z)
  46. #define DRIVER_DATABASE_FILENAME L"drvmain.sdb"
  47. #define KERNEL_UP_IMAGE_FILENAME "ntoskrnl.exe"
  48. #define KERNEL_MP_IMAGE_FILENAME "ntkrnlmp.exe"
  49. CHAR KernelImage[13];
  50. BOOLEAN UseCommandConsole = FALSE;
  51. BOOLEAN g_RollbackEnabled = FALSE;
  52. BOOLEAN TryASRViaNetwork = FALSE;
  53. CHAR KdFileName[8+1+3+1]="KDCOM.DLL";
  54. BOOLEAN UseAlternateKdDll = FALSE;
  55. #define KD_ALT_DLL_PREFIX_CHARS 2
  56. #define KD_ALT_DLL_REPLACE_CHARS 6
  57. #define DBG_OUT(x)
  58. /*
  59. //
  60. // For debugging purposes
  61. // Example:
  62. //
  63. // DBG_OUT("Testing")
  64. //
  65. #define DBG_OUT(x) { \
  66. if (x) { \
  67. BlPositionCursor(5, 10); \
  68. BlPrint(" "); \
  69. BlPositionCursor(5, 10); \
  70. BlPrint(x); \
  71. while (!SlGetChar()); \
  72. } \
  73. }
  74. //
  75. // For debugging purposes
  76. // Example:
  77. //
  78. // DebugOutput("Calling SlDetectScsi(). Line = %d. %s\n",__LINE__,"")
  79. //
  80. //
  81. #define DebugOutput(X,Y,Z) { \
  82. if (ARC_CONSOLE_OUTPUT) { \
  83. CHAR _b[128]; \
  84. ULONG _c; \
  85. sprintf(&_b[0], X, Y, Z); \
  86. ArcWrite(ARC_CONSOLE_OUTPUT, &_b[0], strlen(&_b[0]), &_c); \
  87. SlGetChar(); \
  88. } \
  89. }
  90. */
  91. //
  92. // Define external static data.
  93. //
  94. ULONG BlConsoleOutDeviceId = ARC_CONSOLE_OUTPUT;
  95. ULONG BlConsoleInDeviceId = ARC_CONSOLE_INPUT;
  96. //
  97. // Global string constants.
  98. //
  99. PCHAR FilesSectionName = "SourceDisksFiles";
  100. PCHAR MediaSectionName = "SourceDisksNames";
  101. #if defined(_AXP64_)
  102. PCHAR PlatformExtension = ".axp64";
  103. #elif defined(_ALPHA_)
  104. PCHAR PlatformExtension = ".alpha";
  105. #elif defined(_IA64_)
  106. PCHAR PlatformExtension = ".ia64";
  107. #elif defined(_X86_)
  108. PCHAR PlatformExtension = ".x86";
  109. #endif
  110. //
  111. // Global data
  112. //
  113. ULONG BlDcacheFillSize = 32;
  114. ULONG BlVirtualBias = 0;
  115. //
  116. // Global setupldr control values
  117. //
  118. MEDIA_TYPE BootMedia;
  119. MEDIA_TYPE InstallMedia;
  120. PCHAR BootDevice;
  121. ULONG BootDeviceId;
  122. BOOLEAN BootDeviceIdValid = FALSE;
  123. PCHAR BootPath;
  124. ULONG BootDriveNumber;
  125. ULONG InstallDriveNumber;
  126. PCHAR HalName;
  127. PCHAR HalDescription;
  128. PCHAR AnsiCpName;
  129. PCHAR OemHalFontName;
  130. UNICODE_STRING AnsiCodepage;
  131. UNICODE_STRING OemCodepage;
  132. UNICODE_STRING UnicodeCaseTable;
  133. UNICODE_STRING OemHalFont;
  134. #ifdef _WANT_MACHINE_IDENTIFICATION
  135. UNICODE_STRING BiosInfo;
  136. #endif
  137. BOOLEAN LoadScsiMiniports;
  138. BOOLEAN LoadDiskClass;
  139. BOOLEAN LoadCdfs;
  140. BOOLEAN FixedBootMedia = FALSE;
  141. BOOLEAN FloppyBoot = FALSE;
  142. PVOID InfFile;
  143. PVOID WinntSifHandle;
  144. PVOID MigrateInfHandle;
  145. ULONG BootFontImageLength = 0;
  146. PVOID UnsupDriversInfHandle;
  147. BOOLEAN IgnoreMissingFiles;
  148. BOOLEAN BlUsePae;
  149. BOOLEAN UseRegularBackground = TRUE;
  150. BOOLEAN IsUpgrade = FALSE;
  151. //
  152. // OEM related variables
  153. //
  154. POEM_SOURCE_DEVICE OemSourceDevices = NULL;
  155. POEM_SOURCE_DEVICE DefaultOemSourceDevice = NULL;
  156. POEM_SOURCE_DEVICE AutoLoadOemHalDevice = NULL;
  157. BOOLEAN AutoLoadOemScsi = FALSE;
  158. //
  159. // Pre-install stuff
  160. //
  161. PCHAR OemTag = "OEM";
  162. PTCHAR _TOemTag = TEXT("OEM");
  163. BOOLEAN PreInstall = FALSE;
  164. PTCHAR ComputerType = NULL;
  165. BOOLEAN OemHal = FALSE;
  166. PPREINSTALL_DRIVER_INFO PreinstallDriverList = NULL;
  167. POEM_SOURCE_DEVICE PreInstallOemSourceDevice = NULL;
  168. PCHAR PreInstallSourcePath = NULL;
  169. //
  170. // Dynamic update variables
  171. //
  172. static BOOLEAN DynamicUpdate = FALSE;
  173. static PCSTR DynamicUpdateRootDir = NULL;
  174. static POEM_SOURCE_DEVICE DynamicUpdateSourceDevice = NULL;
  175. //
  176. // WinPE (aka MiniNT) global variables
  177. //
  178. BOOLEAN WinPEBoot = FALSE;
  179. BOOLEAN WinPEAutoBoot = FALSE;
  180. PCTSTR StartupMsg = NULL;
  181. //
  182. // Is used by HALACPI.DLL
  183. //
  184. BOOLEAN DisableACPI = FALSE;
  185. BOOLEAN isOSCHOICE = FALSE;
  186. //
  187. // Primarily used by floppy boot support to key track
  188. // of the last disk read
  189. //
  190. PCHAR LastDiskTag = NULL;
  191. #if defined(ELTORITO)
  192. extern BOOLEAN ElToritoCDBoot;
  193. #endif
  194. //
  195. // Define transfer entry of loaded image.
  196. //
  197. typedef
  198. VOID
  199. (*PTRANSFER_ROUTINE) (
  200. PLOADER_PARAMETER_BLOCK LoaderBlock
  201. );
  202. #if defined(_IA64_)
  203. VOID
  204. BuildArcTree();
  205. #endif
  206. //
  207. // Local function prototypes
  208. //
  209. VOID
  210. SlGetSetupValuesBeforePrompt(
  211. IN PSETUP_LOADER_BLOCK SetupBlock
  212. );
  213. VOID
  214. SlGetSetupValuesAfterPrompt(
  215. IN PSETUP_LOADER_BLOCK SetupBlock
  216. );
  217. ARC_STATUS
  218. SlLoadDriver(
  219. IN PTCHAR DriverDescription,
  220. IN PCHAR DriverName,
  221. IN ULONG DriverFlags,
  222. IN BOOLEAN InsertIntoDriverList,
  223. IN BOOLEAN MigratedDriver
  224. );
  225. ARC_STATUS
  226. SlLoadOemDriver(
  227. IN PCHAR ExportDriver OPTIONAL,
  228. IN PCHAR DriverName,
  229. IN PVOID BaseAddress,
  230. IN PTCHAR LoadMessage
  231. );
  232. PBOOT_DRIVER_LIST_ENTRY
  233. SlpCreateDriverEntry(
  234. IN PCHAR DriverName
  235. );
  236. ARC_STATUS
  237. SlDetectMigratedScsiDrivers(
  238. IN PVOID Inf
  239. );
  240. ARC_STATUS
  241. SlGetMigratedHardwareIds(
  242. IN PSETUP_LOADER_BLOCK SetupBlock,
  243. IN PVOID Inf
  244. );
  245. BOOLEAN
  246. SlpIsDiskVacant(
  247. IN PARC_DISK_SIGNATURE DiskSignature
  248. );
  249. ARC_STATUS
  250. SlpStampFTSignature(
  251. IN PARC_DISK_SIGNATURE DiskSignature,
  252. IN BOOLEAN GenerateNewSignature
  253. );
  254. VOID
  255. SlpMarkDisks(
  256. IN BOOLEAN Reboot
  257. );
  258. VOID
  259. SlCheckOemKeypress(
  260. IN ULONG WaitTime
  261. );
  262. VOID
  263. SlCheckASRKeypress(
  264. VOID
  265. );
  266. ARC_STATUS
  267. SlLoadPnpDriversSection(
  268. IN PVOID Inf,
  269. IN PCHAR SectionName,
  270. IN OUT PDETECTED_DEVICE* DetectedDeviceList OPTIONAL
  271. );
  272. BOOLEAN
  273. SlIsUpgrade(
  274. IN PVOID SifHandle
  275. );
  276. BOOLEAN
  277. SlIsCdBootUpgrade(
  278. IN PCHAR InstallDirectory,
  279. IN PCHAR SetupFileName,
  280. IN ULONG MaxDisksToScan,
  281. IN ULONG MaxPartitionsPerDisk,
  282. OUT PCHAR SetupDevice
  283. );
  284. BOOLEAN
  285. SlRemoveOsLoadOption(
  286. IN PSTR LoadOptions,
  287. IN PCSTR OptionToRemove
  288. );
  289. ARC_STATUS
  290. SlLoadBootFontFile(
  291. IN PSETUP_LOADER_BLOCK SetupLoaderBlock,
  292. IN ULONG DiskId,
  293. IN ULONG BootFontImageLength
  294. );
  295. //
  296. // Dynamic update function prototypes
  297. //
  298. BOOLEAN
  299. SlpIsDynamicUpdate(
  300. IN PVOID InfHandle,
  301. OUT PCSTR *DynamicUpdateRootDir
  302. );
  303. ARC_STATUS
  304. SlInit(
  305. IN ULONG Argc,
  306. IN CHAR * FIRMWARE_PTR * FIRMWARE_PTR Argv,
  307. IN CHAR * FIRMWARE_PTR * FIRMWARE_PTR Envp
  308. )
  309. /*++
  310. Routine Description:
  311. The main startup routine for the NT Setup Loader. This is the entrypoint
  312. called by the ARC firmware.
  313. If successful, this routine will never return, it will start NT directly.
  314. Arguments:
  315. Argc - Supplies the number of arguments that were provided on the
  316. command that invoked this program.
  317. Argv - Supplies a pointer to a vector of pointers to null terminated
  318. argument strings.
  319. Envp - Supplies a pointer to a vector of pointers to null terminated
  320. environment variables.
  321. Return Value:
  322. ARC_STATUS if unsuccessful.
  323. --*/
  324. {
  325. //
  326. // if we use too much stack space the heap and stack can overlap and we can run into corruption problems
  327. // without any "stack overflow" exceptions; making large strings static helps prevent this
  328. //
  329. PCONFIGURATION_COMPONENT_DATA DataCache;
  330. ARC_STATUS Status;
  331. ULONG LinesPerBlock;
  332. ULONG CacheLineSize;
  333. static CHAR SetupDevice[128];
  334. static CHAR SetupDirectory[128];
  335. static CHAR BadFileName[128];
  336. static CHAR CanonicalName[128];
  337. static CHAR HalDirectoryPath[256];
  338. static CHAR KernelDirectoryPath[256];
  339. PCHAR NetSetupServerShare;
  340. PCHAR NetSetupPath;
  341. PCHAR p;
  342. ULONG ErrorLine=0;
  343. ULONG DontCare;
  344. PVOID SystemBase;
  345. PVOID HalBase;
  346. PVOID LoaderBase;
  347. PVOID ScsiBase;
  348. PVOID VideoBase;
  349. PCHAR FileName;
  350. PVOID KdDllBase;
  351. static CHAR KdDllName[256];
  352. ULONG i;
  353. PKLDR_DATA_TABLE_ENTRY SystemDataTableEntry;
  354. PKLDR_DATA_TABLE_ENTRY HalDataTableEntry;
  355. PKLDR_DATA_TABLE_ENTRY KdDataTableEntry;
  356. PTRANSFER_ROUTINE SystemEntry;
  357. PIMAGE_NT_HEADERS NtHeaders;
  358. PBOOT_DRIVER_LIST_ENTRY DriverEntry;
  359. PSETUP_LOADER_BLOCK SetupBlock;
  360. PDETECTED_DEVICE ScsiDevice;
  361. PCHAR VideoFileName;
  362. PTCHAR VideoDescription;
  363. PCHAR OemScsiName;
  364. POEMSCSIINFO OemScsiInfo = NULL;
  365. PCHAR OemVideoName;
  366. PVOID OemInfHandle = NULL;
  367. BOOLEAN LoadedAVideoDriver = FALSE;
  368. static CHAR NetbootCardDriverName[24];
  369. static CHAR NetbootUser[64];
  370. static CHAR NetbootDomain[64];
  371. static CHAR NetbootPassword[64];
  372. static CHAR NetbootAdministratorPassword[OSC_ADMIN_PASSWORD_LEN];
  373. static CHAR NetbootSifFile[128];
  374. DOCKING_STATION_INFO dockInfo = { 0, 0, 0, FW_DOCKINFO_DOCK_STATE_UNKNOWN };
  375. PCONFIGURATION_COMPONENT_DATA dockInfoData;
  376. extern ULONG BlProgressBarShowTimeOut;
  377. ULONG OemKeypressTimeout = 5; //secs
  378. #if defined(REMOTE_BOOT)
  379. BOOLEAN RemoteBootEnableIpsec = FALSE;
  380. #endif // defined(REMOTE_BOOT)
  381. #if defined(_X86_) || defined(_IA64_)
  382. BOOLEAN Win9xUnsupHdc = FALSE;
  383. #endif
  384. static FULL_PATH_SET PathSet;
  385. UNICODE_STRING DrvMainSdb;
  386. #if DBG
  387. ULONG StartTime = 0;
  388. #endif
  389. //
  390. // Disable progress bar, by default.
  391. //
  392. BlProgressBarShowTimeOut = -1;
  393. //
  394. // Initialize the boot debugger for platforms that directly load the
  395. // OS Loader.
  396. //
  397. // N.B. This must occur after the console input and output have been
  398. // initialized so debug messages can be printed on the console
  399. // output device.
  400. //
  401. #if defined(_ALPHA_) || defined(ARCI386) || defined(_IA64_)
  402. LoaderBase = &__ImageBase;
  403. //
  404. // Initialize traps and the boot debugger.
  405. //
  406. #if defined(ENABLE_LOADER_DEBUG)
  407. #if defined(_ALPHA_)
  408. BdInitializeTraps();
  409. #endif
  410. BdInitDebugger(OsLoaderName, LoaderBase, ENABLE_LOADER_DEBUG);
  411. #else
  412. BdInitDebugger(OsLoaderName, 0, NULL);
  413. #endif
  414. #endif
  415. #if 0 && !defined(_IA64_)
  416. //
  417. // AJR bugbug -- do we really need to do this twice? we already call in SuMain()
  418. //
  419. // ChuckL -- Turned this code off because it screws up remote boot, which
  420. // does some allocations before we get here.
  421. //
  422. //
  423. // Initialize the memory descriptor list, the OS loader heap, and the
  424. // OS loader parameter block.
  425. //
  426. Status = BlMemoryInitialize();
  427. if (Status != ESUCCESS) {
  428. BlDiagLoadMessage(LOAD_HW_MEM_CLASS,
  429. DIAG_BL_MEMORY_INIT,
  430. LOAD_HW_MEM_ACT);
  431. goto LoadFailed;
  432. }
  433. #endif
  434. #if defined(_IA64_)
  435. //
  436. // Build required portion of ARC tree since we are not doing NTDETECT
  437. // anymore.
  438. //
  439. BuildArcTree();
  440. #endif
  441. SetupBlock = BlAllocateHeap(sizeof(SETUP_LOADER_BLOCK));
  442. if (SetupBlock==NULL) {
  443. SlNoMemoryError();
  444. goto LoadFailed;
  445. }
  446. BlLoaderBlock->SetupLoaderBlock = SetupBlock;
  447. SetupBlock->ScsiDevices = NULL;
  448. SetupBlock->BootBusExtenders = NULL;
  449. SetupBlock->BusExtenders = NULL;
  450. SetupBlock->InputDevicesSupport = NULL;
  451. SetupBlock->Flags |= SETUPBLK_FLAGS_IS_TEXTMODE;
  452. SetupBlock->ScalarValues.SetupFromCdRom = FALSE;
  453. SetupBlock->ScalarValues.SetupOperation = SetupOperationSetup;
  454. SetupBlock->ScalarValues.LoadedScsi = 0;
  455. SetupBlock->ScalarValues.LoadedCdRomDrivers = 0;
  456. SetupBlock->ScalarValues.LoadedDiskDrivers = 0;
  457. SetupBlock->ScalarValues.LoadedFloppyDrivers = 0;
  458. SetupBlock->ScalarValues.LoadedFileSystems = 0;
  459. //
  460. // Initialize the NT configuration tree.
  461. //
  462. BlLoaderBlock->ConfigurationRoot = NULL;
  463. Status = BlConfigurationInitialize(NULL, NULL);
  464. if (Status != ESUCCESS) {
  465. BlDiagLoadMessage(LOAD_HW_FW_CFG_CLASS,
  466. DIAG_BL_CONFIG_INIT,
  467. LOAD_HW_FW_CFG_ACT);
  468. goto LoadFailed;
  469. }
  470. //
  471. // Compute the data cache fill size. This value is used to align
  472. // I/O buffers in case the host system does not support coherent
  473. // caches.
  474. //
  475. // If a combined secondary cache is present, then use the fill size
  476. // for that cache. Otherwise, if a secondary data cache is present,
  477. // then use the fill size for that cache. Otherwise, if a primary
  478. // data cache is present, then use the fill size for that cache.
  479. // Otherwise, use the default fill size.
  480. //
  481. DataCache = KeFindConfigurationEntry(BlLoaderBlock->ConfigurationRoot,
  482. CacheClass,
  483. SecondaryCache,
  484. NULL);
  485. if (DataCache == NULL) {
  486. DataCache = KeFindConfigurationEntry(BlLoaderBlock->ConfigurationRoot,
  487. CacheClass,
  488. SecondaryDcache,
  489. NULL);
  490. if (DataCache == NULL) {
  491. DataCache = KeFindConfigurationEntry(BlLoaderBlock->ConfigurationRoot,
  492. CacheClass,
  493. PrimaryDcache,
  494. NULL);
  495. }
  496. }
  497. if (DataCache != NULL) {
  498. LinesPerBlock = DataCache->ComponentEntry.Key >> 24;
  499. CacheLineSize = 1 << ((DataCache->ComponentEntry.Key >> 16) & 0xff);
  500. BlDcacheFillSize = LinesPerBlock * CacheLineSize;
  501. }
  502. //
  503. // Initialize the OS loader I/O system.
  504. //
  505. Status = BlIoInitialize();
  506. if (Status != ESUCCESS) {
  507. BlDiagLoadMessage(LOAD_HW_DISK_CLASS,
  508. DIAG_BL_IO_INIT,
  509. LOAD_HW_DISK_ACT);
  510. goto LoadFailed;
  511. }
  512. #if DBG
  513. StartTime = ArcGetRelativeTime();
  514. #endif
  515. SlPositionCursor(5,3);
  516. #if !defined(_IA64_)
  517. //
  518. // Initialize the message resources
  519. //
  520. Status = BlInitResources(Argv[0]);
  521. if (Status != ESUCCESS) {
  522. // if this fails, then we can't print out any messages,
  523. // so we just exit.
  524. return(Status);
  525. }
  526. #endif
  527. //
  528. // If there is an ImageType parameter, this is a command console or rollback.
  529. //
  530. p = BlGetArgumentValue(Argc, Argv, "ImageType");
  531. if (p) {
  532. if (!strcmp (p, "cmdcons")) {
  533. UseCommandConsole = TRUE;
  534. } else if (!strcmp (p, "rollback")) {
  535. g_RollbackEnabled = TRUE;
  536. }
  537. }
  538. #ifdef FORCE_CD_BOOT
  539. g_RollbackEnabled = FALSE;
  540. #endif
  541. //
  542. // See if we're redirecting.
  543. //
  544. if( LoaderRedirectionInformation.PortAddress ) {
  545. //
  546. // Yes, we are redirecting right now. Use these settings.
  547. //
  548. BlLoaderBlock->Extension->HeadlessLoaderBlock = BlAllocateHeap(sizeof(HEADLESS_LOADER_BLOCK));
  549. RtlCopyMemory( BlLoaderBlock->Extension->HeadlessLoaderBlock,
  550. &LoaderRedirectionInformation,
  551. sizeof(HEADLESS_LOADER_BLOCK) );
  552. } else {
  553. BlLoaderBlock->Extension->HeadlessLoaderBlock = NULL;
  554. }
  555. //
  556. // Initialize the display and announce ourselves
  557. //
  558. SlInitDisplay();
  559. #if defined(_X86_) && !defined(ALLOW_386)
  560. //
  561. // Disallow installation on a 386 or any processor which
  562. // does not support CPUID and CMPXCHG8B instructions.
  563. //
  564. {
  565. extern BOOLEAN BlIs386(VOID);
  566. extern ULONG BlGetFeatureBits(VOID);
  567. if(BlIs386()) {
  568. SlFatalError(SL_TEXT_REQUIRES_486);
  569. }
  570. //
  571. // CMPXCHG8B is required on Whistler and above. This
  572. // implies a requirement for CPUID which is used to
  573. // determine the presence of CMPXCHG8B.
  574. //
  575. if ((BlGetFeatureBits() & 0x100) == 0) {
  576. SlFatalError(SL_TEXT_REQUIRED_FEATURES_MISSING);
  577. }
  578. }
  579. #endif
  580. #ifdef _IA64_
  581. //
  582. // Is this automated WinPE boot?
  583. //
  584. p = BlGetArgumentValue(Argc, Argv, "systempartition");
  585. if (p && SlIsWinPEAutoBoot(p)) {
  586. WinPEAutoBoot = TRUE;
  587. //
  588. // get the WinPE device & directory
  589. //
  590. if (ESUCCESS != SlGetWinPEStartupParams(SetupDevice, SetupDirectory)) {
  591. SlFriendlyError(
  592. Status,
  593. "SETUPLDR:Cannot find WinPE installation",
  594. __LINE__,
  595. __FILE__
  596. );
  597. goto LoadFailed;
  598. }
  599. }
  600. #endif
  601. if (!WinPEAutoBoot) {
  602. //
  603. // If this is a winnt setup, then we want to behave as if
  604. // we were started from the location specified by the
  605. // OSLOADPARTITION and OSLOADFILENAME nv-ram variables.
  606. //
  607. p = BlGetArgumentValue(Argc,Argv,"osloadoptions");
  608. if(p && !_stricmp(p,"winnt32")) {
  609. p = BlGetArgumentValue(Argc,Argv,"osloadpartition");
  610. if(!p) {
  611. SlError(100);
  612. goto LoadFailed;
  613. }
  614. Status = BlGenerateDeviceNames(p,SetupDevice,NULL);
  615. if (Status != ESUCCESS) {
  616. SlError(110);
  617. goto LoadFailed;
  618. }
  619. p = BlGetArgumentValue(Argc,Argv,"osloadfilename");
  620. if(!p || !(*p)) {
  621. SlError(120);
  622. goto LoadFailed;
  623. }
  624. strcpy(SetupDirectory,p);
  625. //
  626. // Make sure directory is terminated with a \.
  627. //
  628. if(SetupDirectory[strlen(SetupDirectory)-1] != '\\') {
  629. strcat(SetupDirectory,"\\");
  630. }
  631. } else {
  632. //
  633. // extract device name from our startup path
  634. //
  635. p=strrchr(Argv[0],')');
  636. if (p==NULL) {
  637. SlError(0);
  638. goto LoadFailed;
  639. }
  640. strncpy(SetupDevice, Argv[0], (int)(p-Argv[0]+1));
  641. SetupDevice[p-Argv[0]+1] = '\0';
  642. Status = BlGenerateDeviceNames(SetupDevice,CanonicalName,NULL);
  643. if (Status != ESUCCESS) {
  644. SlFriendlyError(
  645. Status,
  646. SetupDevice,
  647. __LINE__,
  648. __FILE__
  649. );
  650. goto LoadFailed;
  651. }
  652. strcpy(SetupDevice,CanonicalName);
  653. //
  654. // If this is a remote boot, load winnt.sif. If we were passed
  655. // a path through the soft reboot use that, if not then look
  656. // in the same place that the loader was loaded from. Once we
  657. // have read winnt.sif we get the SetupSourceDevice path.
  658. //
  659. if (BlBootingFromNet) {
  660. NetGetRebootParameters(
  661. NULL,
  662. NULL,
  663. NetbootSifFile,
  664. NetbootUser,
  665. NetbootDomain,
  666. NetbootPassword,
  667. NetbootAdministratorPassword,
  668. TRUE);
  669. if (NetbootSifFile[0] != '\0') {
  670. strcpy(BadFileName, NetbootSifFile);
  671. } else {
  672. strcpy(BadFileName,NetBootPath);
  673. strcat(BadFileName,WINNT_SIF_FILE_A);
  674. }
  675. if (NetbootAdministratorPassword[0] != '\0') {
  676. //
  677. // It's possible that the string contained in NetbootAdministratorPassword
  678. // may not be terminated. Just block copy the entire 64-bytes into the loader
  679. // block, then we'll treat the data carefully in setupdd.sys when we read it
  680. // back out.
  681. //
  682. RtlMoveMemory(BlLoaderBlock->SetupLoaderBlock->NetBootAdministratorPassword,
  683. NetbootAdministratorPassword,
  684. OSC_ADMIN_PASSWORD_LEN );
  685. }
  686. BlLoaderBlock->SetupLoaderBlock->WinntSifFile = NULL;
  687. BlLoaderBlock->SetupLoaderBlock->WinntSifFileLength = 0;
  688. Status = SlInitIniFile(SetupDevice,
  689. 0,
  690. BadFileName,
  691. &WinntSifHandle,
  692. &BlLoaderBlock->SetupLoaderBlock->WinntSifFile,
  693. &BlLoaderBlock->SetupLoaderBlock->WinntSifFileLength,
  694. &DontCare);
  695. if(Status != ESUCCESS) {
  696. if (NetbootSifFile[0] != '\0') {
  697. SlFatalError(
  698. SL_BAD_INF_FILE,
  699. SlCopyStringAT(NetbootSifFile),
  700. Status);
  701. } else {
  702. SlFatalError(
  703. SL_BAD_INF_FILE,
  704. WINNT_SIF_FILE,
  705. Status);
  706. }
  707. goto LoadFailed;
  708. }
  709. //
  710. // Get the SetupSourceDevice parameter from winnt.sif.
  711. //
  712. // SetupSourceDevice is of the form "\Device\LanmanRedirector\server\share\setup\nt5".
  713. //
  714. NetSetupServerShare = SlGetSectionKeyIndex(WinntSifHandle,
  715. "SetupData",
  716. "SetupSourceDevice",
  717. 0);
  718. #if DBG
  719. if ((strlen(NetSetupServerShare) + 1) > sizeof(SetupBlock->NetBootIMirrorFilePath)) {
  720. DbgPrint("The UNC name is too long!\n");
  721. goto LoadFailed;
  722. }
  723. #endif
  724. strcpy(SetupBlock->NetBootIMirrorFilePath, NetSetupServerShare);
  725. if(NetSetupServerShare != NULL) {
  726. // must start with '\'
  727. if (*NetSetupServerShare != '\\') {
  728. NetSetupServerShare = NULL;
  729. } else {
  730. // skip to '\' after Device
  731. NetSetupServerShare = strchr(NetSetupServerShare+1,'\\');
  732. if (NetSetupServerShare != NULL) {
  733. // skip to '\' after LanmanRedirector (before server)
  734. NetSetupServerShare = strchr(NetSetupServerShare+1,'\\');
  735. if (NetSetupServerShare != NULL) {
  736. // skip to '\' after server
  737. NetSetupPath = strchr(NetSetupServerShare+1,'\\');
  738. if (NetSetupPath != NULL) {
  739. // skip to '\' after share (path part)
  740. NetSetupPath = strchr(NetSetupPath+1,'\\');
  741. }
  742. }
  743. }
  744. }
  745. }
  746. if ((NetSetupServerShare == NULL) || (NetSetupPath == NULL)) {
  747. SlFatalError(SL_INF_ENTRY_MISSING,TEXT("SetupSourceDevice"),TEXT("SetupData"));
  748. goto LoadFailed;
  749. }
  750. *NetSetupPath = 0; // terminate server\share part
  751. NetSetupPath++; // remainder is path part
  752. //
  753. // If the TargetNtPartition parameter exists in winnt.sif, then
  754. // the target is remote, and this is a remote boot setup. Otherwise,
  755. // this is a remote installation setup.
  756. //
  757. if (SlGetSectionKeyIndex(WinntSifHandle,
  758. "SetupData",
  759. "TargetNtPartition",
  760. 0) == NULL) {
  761. PUCHAR pTmp, pTmp2;
  762. pTmp = SlGetSectionKeyIndex(WinntSifHandle,
  763. "OSChooser",
  764. "ImageType",
  765. 0);
  766. if (pTmp != NULL) {
  767. pTmp2 = pTmp;
  768. while (*pTmp != '\0') {
  769. *pTmp = (UCHAR)toupper(*pTmp);
  770. pTmp++;
  771. }
  772. if (!strcmp(pTmp2, "SYSPREP")) {
  773. pTmp = SlGetSectionKeyIndex(WinntSifHandle,
  774. "SetupData",
  775. "SysPrepDevice",
  776. 0);
  777. if (pTmp != NULL) {
  778. strcpy(SetupBlock->NetBootIMirrorFilePath, pTmp);
  779. } else {
  780. memset(SetupBlock->NetBootIMirrorFilePath,
  781. 0x0,
  782. sizeof(SetupBlock->NetBootIMirrorFilePath)
  783. );
  784. }
  785. SetupBlock->Flags |= SETUPBLK_FLAGS_SYSPREP_INSTALL;
  786. } else {
  787. SetupBlock->Flags |= SETUPBLK_FLAGS_REMOTE_INSTALL;
  788. }
  789. } else {
  790. SetupBlock->Flags |= SETUPBLK_FLAGS_REMOTE_INSTALL;
  791. }
  792. }
  793. }
  794. //
  795. // extract directory from our startup path.
  796. //
  797. if (BlBootingFromNet) {
  798. strcpy(SetupDirectory, "\\");
  799. strcat(SetupDirectory, NetSetupPath);
  800. } else if (UseCommandConsole) {
  801. strcpy(SetupDirectory,"\\cmdcons");
  802. } else if(*(p+1) != '\\') {
  803. //
  804. // directory must begin at root
  805. //
  806. strcpy(SetupDirectory, "\\");
  807. } else {
  808. *SetupDirectory = '\0';
  809. }
  810. strcat(SetupDirectory, p+1);
  811. p=strrchr(SetupDirectory, '\\');
  812. *(p+1) = '\0';
  813. }
  814. }
  815. #if defined(ELTORITO)
  816. if (ElToritoCDBoot && !WinPEAutoBoot) {
  817. //
  818. // Use the i386 directory for setup files when we boot from an El Torito CD
  819. //
  820. PCHAR SetupDirectoryOnDisk = "\\$WIN_NT$.~BT";
  821. CHAR SetupBootDevice[128] = {0};
  822. ULONG MaxDisksToScan = 1; // on x86 only the first disk
  823. ULONG MaxPartitionsToScan = 4; // on x86 check only primary partitions
  824. BOOLEAN CheckUpgrades = TRUE;
  825. #if defined(_IA64_)
  826. strcat(SetupDirectory, "ia64\\");
  827. /*
  828. //
  829. // Values for IA64 installation, currently not used
  830. //
  831. SetupDirectoryOnDisk = "\\$WIN_NT$.~LS\\ia64";
  832. MaxDisksToScan = 4; // NOTE : arbitrary limit
  833. MaxPartitionsToScan = 4; // NOTE : arbitrary limit
  834. */
  835. CheckUpgrades = FALSE; // NOTE : Currently disabled on IA64
  836. #else
  837. strcat(SetupDirectory, "i386\\");
  838. #endif
  839. //
  840. // If WinPE boot then disable check for CD boot upgrade
  841. // NOTE: We check for the presence of system32\\drivers directory
  842. // rather than relying on /minint flag in txtsetup.sif since we
  843. // have not yet loaded txtsetup.sif file
  844. //
  845. if (CheckUpgrades) {
  846. CHAR DriversDir[128];
  847. ARC_STATUS DirStatus;
  848. ULONG DeviceId, DirId;
  849. strcat(DriversDir, SetupDirectory);
  850. strcat(DriversDir, "system32\\drivers");
  851. DirStatus = ArcOpen(SetupDevice, ArcOpenReadOnly, &DeviceId);
  852. if (ESUCCESS == DirStatus) {
  853. DirStatus = BlOpen(DeviceId, DriversDir, ArcOpenDirectory, &DirId);
  854. if (ESUCCESS == DirStatus) {
  855. CheckUpgrades = FALSE; // looks like a WinPE boot
  856. BlClose(DirId);
  857. }
  858. ArcClose(DeviceId);
  859. }
  860. }
  861. //
  862. // Figure out if user was already trying to upgrade
  863. // using winnt32.exe. If user confirms he is
  864. // wants to continue upgrading then switch to
  865. // harddisk
  866. //
  867. if (CheckUpgrades &&
  868. SlIsCdBootUpgrade(SetupDirectoryOnDisk,
  869. WINNT_SIF_FILE_A,
  870. MaxDisksToScan,
  871. MaxPartitionsToScan,
  872. SetupBootDevice)) {
  873. strcpy(SetupDevice, SetupBootDevice);
  874. strcpy(SetupDirectory, SetupDirectoryOnDisk);
  875. strcat(SetupDirectory, "\\");
  876. ElToritoCDBoot = FALSE;
  877. }
  878. }
  879. #endif
  880. //
  881. // Turn on ability to load compressed files.
  882. //
  883. DecompEnableDecompression(TRUE);
  884. ///////////////////////////////////////////////////////////////////
  885. //
  886. // On x86, the files loaded from now on are on boot floppy #1
  887. // HALs may be on floppy #1 or floppy #2
  888. //
  889. ///////////////////////////////////////////////////////////////////
  890. strcpy(KernelDirectoryPath, SetupDirectory);
  891. strcat(KernelDirectoryPath, "txtsetup.sif");
  892. BlLoaderBlock->SetupLoaderBlock->IniFile = NULL;
  893. Status = SlInitIniFile(SetupDevice,
  894. 0,
  895. KernelDirectoryPath,
  896. &InfFile,
  897. &BlLoaderBlock->SetupLoaderBlock->IniFile,
  898. &BlLoaderBlock->SetupLoaderBlock->IniFileLength,
  899. &ErrorLine);
  900. if (Status != ESUCCESS) {
  901. //
  902. // See if we can get the txtsetup.sif out of the WinPE boot
  903. // directory.
  904. //
  905. if( (strcmp( SetupDirectory, "\\") == 0) &&
  906. (!ElToritoCDBoot) &&
  907. (!BlBootingFromNet) ) {
  908. //
  909. // We're not booting off CD and we're not booting off the
  910. // net and we're about to fail because we didn't find \txtsetup.sif
  911. // Try in the MiniNT directory...
  912. //
  913. Status = SlInitIniFile(SetupDevice,
  914. 0,
  915. "\\minint\\txtsetup.sif",
  916. &InfFile,
  917. &BlLoaderBlock->SetupLoaderBlock->IniFile,
  918. &BlLoaderBlock->SetupLoaderBlock->IniFileLength,
  919. &ErrorLine);
  920. }
  921. if( Status != ESUCCESS ) {
  922. SlFatalError(SL_BAD_INF_FILE,
  923. TEXT("txtsetup.sif"),
  924. Status);
  925. goto LoadFailed;
  926. }
  927. }
  928. SlGetSetupValuesBeforePrompt(SetupBlock);
  929. //
  930. // Find out if we are starting the MiniNT boot or rollback
  931. // (mutually exclusive options)
  932. //
  933. if (BlLoaderBlock->LoadOptions) {
  934. CHAR Option[256];
  935. PCHAR NextOption = strchr(BlLoaderBlock->LoadOptions, '/');
  936. PCHAR OptionEnd = NULL;
  937. while (NextOption) {
  938. OptionEnd = strchr(NextOption, ' ');
  939. if (OptionEnd) {
  940. strncpy(Option, NextOption, OptionEnd - NextOption);
  941. Option[OptionEnd - NextOption] = 0;
  942. } else {
  943. strcpy(Option, NextOption);
  944. }
  945. if (!_stricmp(Option, "/minint")) {
  946. WinPEBoot = TRUE;
  947. break;
  948. }
  949. NextOption++;
  950. NextOption = strchr(NextOption, '/');
  951. }
  952. }
  953. //
  954. // Fix up the setup directory path to include system32 also
  955. // if this is a MiniNT boot
  956. //
  957. if (WinPEBoot) {
  958. strcat(SetupDirectory, "system32\\");
  959. //
  960. // find out if a different load message has been specified
  961. //
  962. #ifdef UNICODE
  963. StartupMsg = SlGetIniValueW(InfFile,
  964. #else
  965. StartupMsg = (PCTSTR)SlGetIniValue(InfFile,
  966. #endif
  967. "setupdata",
  968. "loaderprompt",
  969. NULL);
  970. //
  971. // Reduce the OEM key press time out
  972. //
  973. OemKeypressTimeout = 2; // secs
  974. }
  975. //
  976. // Now we know everything we should load, compute the ARC name to load
  977. // from and start loading things.
  978. //
  979. if (BootDevice==NULL) {
  980. //
  981. // No device was explicitly specified, so use whatever device
  982. // setupldr was started from.
  983. //
  984. BootDevice = SlCopyStringA(SetupDevice);
  985. }
  986. Status = ArcOpen(BootDevice, ArcOpenReadOnly, &BootDeviceId);
  987. if (Status != ESUCCESS) {
  988. SlFatalError(SL_IO_ERROR,SlCopyStringAT(BootDevice));
  989. goto LoadFailed;
  990. } else {
  991. BootDeviceIdValid = TRUE;
  992. }
  993. #ifdef _X86_
  994. //
  995. // Load the bootfont.bin into memory
  996. //
  997. SlLoadBootFontFile(BlLoaderBlock->SetupLoaderBlock,
  998. BootDeviceId,
  999. BootFontImageLength);
  1000. #endif // _X86_
  1001. _strlwr(BootDevice);
  1002. FixedBootMedia = (strstr(BootDevice,")rdisk(") != NULL);
  1003. FloppyBoot = (strstr(BootDevice, ")fdisk(") != NULL);
  1004. //
  1005. // If we are booting from fixed media, we better load disk class drivers.
  1006. //
  1007. if(FixedBootMedia) {
  1008. LoadDiskClass = TRUE;
  1009. }
  1010. if(!BlGetPathMnemonicKey(BootDevice,"disk",&DontCare)
  1011. && !BlGetPathMnemonicKey(BootDevice,"fdisk",&BootDriveNumber))
  1012. {
  1013. //
  1014. // boot was from floppy, canonicalize the ARC name.
  1015. //
  1016. BlLoaderBlock->ArcBootDeviceName = BlAllocateHeap(80);
  1017. sprintf(BlLoaderBlock->ArcBootDeviceName, "multi(0)disk(0)fdisk(%d)",BootDriveNumber);
  1018. } else {
  1019. BlLoaderBlock->ArcBootDeviceName = BootDevice;
  1020. }
  1021. if (BootPath==NULL) {
  1022. //
  1023. // No explicit boot path given, default to the directory setupldr was started
  1024. // from.
  1025. //
  1026. #if defined(_X86_)
  1027. //
  1028. // Increadibly nauseating hack:
  1029. //
  1030. // If we are booting from hard drive on x86, we will assume this is
  1031. // the 'floppyless' winnt/winnt32 scenario, in which case the actual
  1032. // boot path is \$win_nt$.~bt.
  1033. //
  1034. // This lets us avoid having winnt and winnt32 attempt to modify
  1035. // the BootPath value in the [SetupData] section of txtsetup.sif.
  1036. //
  1037. if( (FixedBootMedia) || (WinPEBoot && FloppyBoot) ) {
  1038. CHAR SetupPath[256];
  1039. if( WinPEBoot ) {
  1040. strcpy(SetupPath, "\\minint\\system32\\");
  1041. } else if( UseCommandConsole ) {
  1042. strcpy(SetupPath, "\\CMDCONS\\");
  1043. } else {
  1044. strcpy(SetupPath, "\\$WIN_NT$.~BT\\");
  1045. }
  1046. BootPath = SlCopyStringA(SetupPath);
  1047. } else
  1048. #endif
  1049. BootPath = SlCopyStringA(SetupDirectory);
  1050. }
  1051. //
  1052. // Load the WinPE inf, if present.
  1053. //
  1054. if (WinPEBoot) {
  1055. CHAR FullPath[128];
  1056. strcpy(FullPath, BootPath);
  1057. strcat(FullPath, WINPE_OEM_FILENAME_A);
  1058. Status = SlInitIniFile(NULL,
  1059. BootDeviceId,
  1060. FullPath,
  1061. &OemInfHandle,
  1062. NULL,
  1063. 0,
  1064. &ErrorLine);
  1065. if (Status != ESUCCESS) {
  1066. OemInfHandle = NULL;
  1067. Status = ESUCCESS;
  1068. }
  1069. }
  1070. #ifdef _WANT_MACHINE_IDENTIFICATION
  1071. BlLoaderBlock->Extension->InfFileImage = NULL;
  1072. BlLoaderBlock->Extension->InfFileSize = 0;
  1073. if (BiosInfo.Buffer) {
  1074. if (Status == ESUCCESS) {
  1075. Status = BlLoadBiosinfoInf( BootDeviceId,
  1076. BlFindMessage(SL_BIOSINFO_NAME),
  1077. BootPath,
  1078. &BiosInfo,
  1079. &BlLoaderBlock->Extension->InfFileImage,
  1080. &BlLoaderBlock->Extension->InfFileSize,
  1081. BadFileName);
  1082. }
  1083. if (Status != ESUCCESS) {
  1084. SlFatalError(SL_FILE_LOAD_FAILED, SlCopyStringAT(BadFileName), Status);
  1085. goto LoadFailed;
  1086. }
  1087. }
  1088. #endif
  1089. //
  1090. // Let the kernel deal with failure to load this driver database.
  1091. //
  1092. BlLoaderBlock->Extension->DrvDBImage = NULL;
  1093. BlLoaderBlock->Extension->DrvDBSize = 0;
  1094. DrvMainSdb.Buffer = DRIVER_DATABASE_FILENAME;
  1095. DrvMainSdb.Length = DrvMainSdb.MaximumLength = sizeof(DRIVER_DATABASE_FILENAME) - sizeof(UNICODE_NULL);
  1096. BlLoadDrvDB( BootDeviceId,
  1097. NULL, // BlFindMessage(SL_DRVMAINSDB_NAME),
  1098. BootPath,
  1099. &DrvMainSdb,
  1100. &BlLoaderBlock->Extension->DrvDBImage,
  1101. &BlLoaderBlock->Extension->DrvDBSize,
  1102. BadFileName);
  1103. //
  1104. // Attempt to load winnt.sif from the path where we are
  1105. // loading setup files. Borrow the BadFileName buffer
  1106. // for temporary use.
  1107. //
  1108. if (!BlBootingFromNet) {
  1109. CHAR FloppyName[80];
  1110. ULONG FloppyId;
  1111. BOOLEAN FloppyUsed = FALSE;
  1112. if (SlpFindFloppy(0,FloppyName)) {
  1113. Status = ArcOpen(FloppyName,ArcOpenReadOnly,&FloppyId);
  1114. if (Status == ESUCCESS) {
  1115. strcpy(BadFileName,"\\");
  1116. strcat(BadFileName,WINNT_SIF_FILE_A);
  1117. BlLoaderBlock->SetupLoaderBlock->WinntSifFile = NULL;
  1118. BlLoaderBlock->SetupLoaderBlock->WinntSifFileLength = 0;
  1119. Status = SlInitIniFile(
  1120. NULL,
  1121. FloppyId,
  1122. BadFileName,
  1123. &WinntSifHandle,
  1124. &BlLoaderBlock->SetupLoaderBlock->WinntSifFile,
  1125. &BlLoaderBlock->SetupLoaderBlock->WinntSifFileLength,
  1126. &DontCare
  1127. );
  1128. if (Status == ESUCCESS) {
  1129. FloppyUsed = TRUE;
  1130. }
  1131. ArcClose(FloppyId);
  1132. }
  1133. }
  1134. if (!FloppyUsed) {
  1135. strcpy(BadFileName,BootPath);
  1136. strcat(BadFileName,WINNT_SIF_FILE_A);
  1137. BlLoaderBlock->SetupLoaderBlock->WinntSifFile = NULL;
  1138. BlLoaderBlock->SetupLoaderBlock->WinntSifFileLength = 0;
  1139. Status = SlInitIniFile(
  1140. NULL,
  1141. BootDeviceId,
  1142. BadFileName,
  1143. &WinntSifHandle,
  1144. &BlLoaderBlock->SetupLoaderBlock->WinntSifFile,
  1145. &BlLoaderBlock->SetupLoaderBlock->WinntSifFileLength,
  1146. &DontCare
  1147. );
  1148. }
  1149. }
  1150. IsUpgrade = SlIsUpgrade(WinntSifHandle);
  1151. UseRegularBackground = (UseCommandConsole || IsUpgrade || WinPEBoot);
  1152. //
  1153. // If the BIOS told us to redirect, we'd be doing it right now. However,
  1154. // the user may have told us some specific settings. If that's the case,
  1155. // override anything we're doing now with the settings from the user.
  1156. //
  1157. if( WinntSifHandle ) {
  1158. UCHAR UnattendTerminalPortNumber = 0;
  1159. PUCHAR UnattendTerminalPortAddress = NULL;
  1160. ULONG UnattendBaudRate = (ULONG)BD_9600;
  1161. p = SlGetSectionKeyIndex(WinntSifHandle, WINNT_DATA_A, WINNT_U_HEADLESS_REDIRECT_A, 0);
  1162. if (p != NULL) {
  1163. BlLoaderBlock->Extension->HeadlessLoaderBlock = BlAllocateHeap(sizeof(HEADLESS_LOADER_BLOCK));
  1164. if (BlLoaderBlock->Extension->HeadlessLoaderBlock == NULL) {
  1165. SlNoMemoryError();
  1166. goto LoadFailed;
  1167. }
  1168. RtlZeroMemory( BlLoaderBlock->Extension->HeadlessLoaderBlock, sizeof(HEADLESS_LOADER_BLOCK) );
  1169. if (!_strnicmp(p, "com", 3)) {
  1170. UnattendTerminalPortNumber = (UCHAR)atoi( (PCHAR)(p+3) );
  1171. switch( UnattendTerminalPortNumber ) {
  1172. case 4:
  1173. UnattendTerminalPortAddress = (PUCHAR)COM4_PORT;
  1174. break;
  1175. case 3:
  1176. UnattendTerminalPortAddress = (PUCHAR)COM3_PORT;
  1177. break;
  1178. case 2:
  1179. UnattendTerminalPortAddress = (PUCHAR)COM2_PORT;
  1180. break;
  1181. default:
  1182. UnattendTerminalPortAddress = (PUCHAR)COM1_PORT;
  1183. break;
  1184. }
  1185. //
  1186. // See if they want to give us a baudrate.
  1187. //
  1188. p = SlGetSectionKeyIndex( WinntSifHandle, WINNT_DATA_A, WINNT_U_HEADLESS_REDIRECTBAUDRATE_A, 0 );
  1189. if( p ) {
  1190. UnattendBaudRate = (ULONG)atoi( (PCHAR)(p) );
  1191. }
  1192. //
  1193. // Make sure the baudrate is something we recognize.
  1194. //
  1195. if( (UnattendBaudRate != BD_115200) &&
  1196. (UnattendBaudRate != BD_57600) &&
  1197. (UnattendBaudRate != BD_19200) ) {
  1198. UnattendBaudRate = (ULONG)BD_9600;
  1199. }
  1200. //
  1201. // Time to fill up the loader block with all the information we
  1202. // just retrieved from the unattend file.
  1203. //
  1204. BlLoaderBlock->Extension->HeadlessLoaderBlock->PortNumber = UnattendTerminalPortNumber;
  1205. BlLoaderBlock->Extension->HeadlessLoaderBlock->BaudRate = UnattendBaudRate;
  1206. BlLoaderBlock->Extension->HeadlessLoaderBlock->Parity = 0;
  1207. BlLoaderBlock->Extension->HeadlessLoaderBlock->StopBits = 1;
  1208. BlLoaderBlock->Extension->HeadlessLoaderBlock->UsedBiosSettings = FALSE;
  1209. BlLoaderBlock->Extension->HeadlessLoaderBlock->PortAddress = UnattendTerminalPortAddress;
  1210. RtlZeroMemory( &LoaderRedirectionInformation, sizeof(HEADLESS_LOADER_BLOCK) );
  1211. RtlCopyMemory( &LoaderRedirectionInformation,
  1212. BlLoaderBlock->Extension->HeadlessLoaderBlock,
  1213. sizeof(HEADLESS_LOADER_BLOCK) );
  1214. BlInitializeHeadlessPort();
  1215. SlClearDisplay();
  1216. } else if( !_stricmp(p, "usebiossettings" ) ) {
  1217. //
  1218. // Now we get to dig up all the information from the
  1219. // ACPI table.
  1220. //
  1221. if( BlRetrieveBIOSRedirectionInformation() ) {
  1222. RtlCopyMemory( BlLoaderBlock->Extension->HeadlessLoaderBlock,
  1223. &LoaderRedirectionInformation,
  1224. sizeof(HEADLESS_LOADER_BLOCK) );
  1225. //
  1226. // No need to call off to BlInitializeHeadlessPort here because
  1227. // if there are any BIOS settings, we would have already picked
  1228. // them up by now and would already be redirecting.
  1229. //
  1230. } else {
  1231. //
  1232. // We can't retrieve the information we need.
  1233. //
  1234. BlLoaderBlock->Extension->HeadlessLoaderBlock = NULL;
  1235. }
  1236. } else if( !_stricmp(p, "noncomport" ) ) {
  1237. //
  1238. // It's something other than serial. Go load a file off the floppy
  1239. // and get the driver from there.
  1240. //
  1241. //
  1242. // Currently not implemented.
  1243. //
  1244. BlLoaderBlock->Extension->HeadlessLoaderBlock = NULL;
  1245. } else {
  1246. //
  1247. // We got something we didn't recognize.
  1248. //
  1249. BlLoaderBlock->Extension->HeadlessLoaderBlock = NULL;
  1250. }
  1251. }
  1252. }
  1253. if (UseRegularBackground) {
  1254. extern BOOLEAN BlOutputDots;
  1255. extern int BlMaxFilesToLoad;
  1256. SlSetCurrentAttribute(DEFATT);
  1257. SlSetStatusAttribute(DEFATT);
  1258. SlClearDisplay();
  1259. SlPositionCursor(0,0);
  1260. if (UseCommandConsole) {
  1261. SlPrint(BlFindMessage(SL_CMDCONS_MSG));
  1262. }
  1263. BlOutputDots = TRUE;
  1264. //
  1265. // To reset BlShowProgress bar correctly
  1266. //
  1267. BlProgressBarShowTimeOut = 0;
  1268. //
  1269. // Note : We can compute the real number of drivers to be loaded
  1270. // from various INF sections and manually counting all the
  1271. // different SlLoadDriver(...) calls. But the code/effort required
  1272. // to do this is not worth the feature, since we just want to
  1273. // replace the old "..." with progress bar to make the recovery
  1274. // console starting look similar to windows starting. So we make
  1275. // an assumption here about the maximum files to be loaded.
  1276. //
  1277. BlMaxFilesToLoad = 80;
  1278. BlSetProgBarCharacteristics(SL_CMDCONS_PROGBAR_FRONT,
  1279. SL_CMDCONS_PROGBAR_BACK);
  1280. if (WinPEBoot) {
  1281. StartupMsg ? BlOutputStartupMsgStr(StartupMsg) :
  1282. BlOutputStartupMsg(SL_SETUP_STARTING_WINPE);
  1283. } else if (UseCommandConsole) {
  1284. BlOutputStartupMsg(SL_CMDCONS_STARTING);
  1285. } else if (g_RollbackEnabled) {
  1286. BlOutputStartupMsg(SL_ROLLBACK_STARTING);
  1287. } else if (IsUpgrade) {
  1288. BlOutputStartupMsg(SL_SETUP_STARTING);
  1289. }
  1290. } else {
  1291. extern ULONG BlProgressBarShowTimeOut;
  1292. BlProgressBarShowTimeOut = -1;
  1293. SlSetCurrentAttribute(DEFATT);
  1294. SlSetStatusAttribute(DEFSTATTR);
  1295. SlClearDisplay();
  1296. SlWriteHeaderText(SL_WELCOME_HEADER);
  1297. SlClearClientArea();
  1298. }
  1299. //
  1300. // remove the /noguiboot option so what we show the logo
  1301. // and switch the video adapter into graphics mode
  1302. // early on during initialization
  1303. //
  1304. if (IsUpgrade) {
  1305. PSTR LoadOptions = SlCopyStringA(BlLoaderBlock->LoadOptions);
  1306. if (SlRemoveOsLoadOption(LoadOptions, "/noguiboot")) {
  1307. BlLoaderBlock->LoadOptions = LoadOptions;
  1308. }
  1309. }
  1310. //
  1311. // Figure out all the OEM drivers source devices
  1312. //
  1313. RamdiskInitialize(BlLoaderBlock->LoadOptions, FALSE);
  1314. SlInitOemSourceDevices(&OemSourceDevices, &DefaultOemSourceDevice);
  1315. //
  1316. // If we found at least one valid OEM source device with proper
  1317. // txtsetup.oem and no default driver then bump up the timeout to
  1318. // 20 secs
  1319. //
  1320. if (OemSourceDevices) {
  1321. POEM_SOURCE_DEVICE CurrDevice = OemSourceDevices;
  1322. while(CurrDevice) {
  1323. if (SL_OEM_SOURCE_MEDIA_TYPE(CurrDevice,
  1324. SL_OEM_SOURCE_MEDIA_HAS_DRIVERS) &&
  1325. !SL_OEM_SOURCE_MEDIA_TYPE(CurrDevice,
  1326. SL_OEM_SOURCE_MEDIA_HAS_DEFAULT)) {
  1327. OemKeypressTimeout = 20;
  1328. break;
  1329. }
  1330. CurrDevice = CurrDevice->Next;
  1331. }
  1332. }
  1333. //
  1334. // We need to check to see if the user pressed any keys to force OEM HAL,
  1335. // OEM SCSI, or both. Do this before getting the settings in the sif file,
  1336. // so that we won't try to detect the machine if OEM HAL is needed.
  1337. //
  1338. SlCheckOemKeypress(OemKeypressTimeout);
  1339. #if defined(_X86_) || defined(_IA64_)
  1340. //
  1341. // We need to check to see if the user pressed any keys to force loading,
  1342. // an ASR pnp repair disk. Only do this if the user didn't select
  1343. // anything in the SlCheckOemKeypress function.
  1344. //
  1345. if(!UseCommandConsole && !WinPEBoot && !IsUpgrade && !BlBootingFromNet) {
  1346. PCHAR pTmp;
  1347. pTmp = SlGetSectionKeyIndex(InfFile,
  1348. "SetupData",
  1349. "DisableAsr",
  1350. 0);
  1351. if ((pTmp == NULL) || (atoi(pTmp) == 0)) {
  1352. SlCheckASRKeypress();
  1353. }
  1354. }
  1355. if (BlBootingFromNet && TryASRViaNetwork) {
  1356. PVOID ASRPNPSifHandle = NULL;
  1357. ULONG c;
  1358. PCHAR FileNameFromSif;
  1359. FileNameFromSif = SlGetIniValue(
  1360. WinntSifHandle,
  1361. "OSChooser",
  1362. "ASRFile",
  1363. "generic.sif" );
  1364. Status = SlInitIniFile( SetupDevice,
  1365. 0,
  1366. FileNameFromSif,
  1367. &ASRPNPSifHandle,
  1368. &BlLoaderBlock->SetupLoaderBlock->ASRPnPSifFile,
  1369. &BlLoaderBlock->SetupLoaderBlock->ASRPnPSifFileLength,
  1370. &c );
  1371. if(Status != ESUCCESS) {
  1372. SlFatalError(SL_BAD_INF_FILE,SlCopyStringAT(FileNameFromSif),Status);
  1373. goto LoadFailed;
  1374. }
  1375. }
  1376. #endif
  1377. SlGetSetupValuesAfterPrompt(SetupBlock);
  1378. //
  1379. // Are there any dyamic update boot drivers which we need
  1380. // to process
  1381. //
  1382. DynamicUpdate = SlpIsDynamicUpdate(WinntSifHandle, &DynamicUpdateRootDir);
  1383. //
  1384. // Add the dynamic update source device as OEM source device since it could
  1385. // have F6
  1386. //
  1387. if (DynamicUpdate) {
  1388. DynamicUpdateSourceDevice = BlAllocateHeap(sizeof(OEM_SOURCE_DEVICE));
  1389. if (DynamicUpdateSourceDevice) {
  1390. memset(DynamicUpdateSourceDevice, 0, sizeof(OEM_SOURCE_DEVICE));
  1391. strcpy(DynamicUpdateSourceDevice->ArcDeviceName,
  1392. BootDevice);
  1393. DynamicUpdateSourceDevice->DriverDir = DynamicUpdateRootDir;
  1394. SL_OEM_SET_SOURCE_DEVICE_TYPE(DynamicUpdateSourceDevice,
  1395. (SL_OEM_SOURCE_DEVICE_TYPE_LOCAL |
  1396. SL_OEM_SOURCE_DEVICE_TYPE_FIXED |
  1397. SL_OEM_SOURCE_DEVICE_TYPE_DYN_UPDATE));
  1398. SL_OEM_SET_SOURCE_MEDIA_TYPE(DynamicUpdateSourceDevice,
  1399. (SL_OEM_SOURCE_MEDIA_PRESENT |
  1400. SL_OEM_SOURCE_MEDIA_HAS_DRIVERS |
  1401. SL_OEM_SOURCE_MEDIA_HAS_MSD |
  1402. SL_OEM_SOURCE_MEDIA_HAS_DEFAULT));
  1403. SL_OEM_SET_SOURCE_DEVICE_STATE(DynamicUpdateSourceDevice,
  1404. SL_OEM_SOURCE_DEVICE_NOT_PROCESSED);
  1405. DynamicUpdateSourceDevice->DeviceId = BootDeviceId;
  1406. //
  1407. // Insert it at the head of the linked list
  1408. //
  1409. DynamicUpdateSourceDevice->Next = OemSourceDevices;
  1410. OemSourceDevices = DynamicUpdateSourceDevice;
  1411. }
  1412. }
  1413. if (BlBootingFromNet || (Status == ESUCCESS)) {
  1414. //
  1415. // Find out if this is a pre-install, by looking at OemPreinstall key
  1416. // in [unattended] section of winnt.sif
  1417. //
  1418. p = SlGetSectionKeyIndex(WinntSifHandle,WINNT_UNATTENDED_A,WINNT_U_OEMPREINSTALL_A,0);
  1419. if(p && !_stricmp(p,"yes")) {
  1420. PreInstall = TRUE;
  1421. }
  1422. //
  1423. // If this is a pre-install, find out which hal to load, by looking
  1424. // at ComputerType key in [unattended] section of winnt.sif.
  1425. //
  1426. if( PreInstall && !DynamicUpdate) {
  1427. #ifdef UNICODE
  1428. ComputerType = (PTCHAR)SlGetSectionKeyIndexW(
  1429. #else
  1430. ComputerType = (PTCHAR)SlGetSectionKeyIndex(
  1431. #endif
  1432. WinntSifHandle,
  1433. WINNT_UNATTENDED_A,
  1434. WINNT_U_COMPUTERTYPE_A,
  1435. 0);
  1436. if(ComputerType) {
  1437. //
  1438. // If the hal to load is an OEM one, then set OemHal to TRUE
  1439. //
  1440. p = SlGetSectionKeyIndex(WinntSifHandle,WINNT_UNATTENDED_A,WINNT_U_COMPUTERTYPE_A,1);
  1441. if(p && !_stricmp(p, OemTag)) {
  1442. OemHal = TRUE;
  1443. } else {
  1444. OemHal = FALSE;
  1445. }
  1446. //
  1447. // In the pre-install mode, don't let the user specify
  1448. // an OEM hal, if one was specified in unattend.txt
  1449. //
  1450. PromptOemHal = FALSE;
  1451. }
  1452. //
  1453. // Find out which SCSI drivers to load, by looking at
  1454. // [MassStorageDrivers] in winnt.sif
  1455. //
  1456. if( SpSearchINFSection( WinntSifHandle, WINNT_OEMSCSIDRIVERS_A ) ) {
  1457. ULONG i;
  1458. PPREINSTALL_DRIVER_INFO TempDriverInfo;
  1459. PTSTR pOem;
  1460. #ifdef UNICODE
  1461. CHAR DriverDescriptionA[100];
  1462. UNICODE_STRING uString;
  1463. ANSI_STRING aString;
  1464. #endif
  1465. PreinstallDriverList = NULL;
  1466. for( i = 0;
  1467. #ifdef UNICODE
  1468. ((pOem = SlGetKeyNameW(
  1469. #else
  1470. ((pOem = SlGetKeyName(
  1471. #endif
  1472. WinntSifHandle,
  1473. WINNT_OEMSCSIDRIVERS_A,
  1474. i )) != NULL);
  1475. i++ ) {
  1476. TempDriverInfo = BlAllocateHeap(sizeof(PREINSTALL_DRIVER_INFO));
  1477. if (TempDriverInfo==NULL) {
  1478. SlNoMemoryError();
  1479. goto LoadFailed;
  1480. }
  1481. TempDriverInfo->DriverDescription = pOem;
  1482. #ifdef UNICODE
  1483. RtlInitUnicodeString( &uString, TempDriverInfo->DriverDescription);
  1484. aString.Buffer = DriverDescriptionA;
  1485. aString.MaximumLength = sizeof(DriverDescriptionA);
  1486. RtlUnicodeStringToAnsiString( &aString, &uString, FALSE );
  1487. pOem = SlGetIniValueW(
  1488. WinntSifHandle,
  1489. WINNT_OEMSCSIDRIVERS_A,
  1490. DriverDescriptionA,
  1491. NULL );
  1492. #else
  1493. pOem = SlGetIniValue(
  1494. WinntSifHandle,
  1495. WINNT_OEMSCSIDRIVERS_A,
  1496. TempDriverInfo->DriverDescription,
  1497. NULL );
  1498. #endif
  1499. TempDriverInfo->OemDriver = (pOem && !_tcsicmp(pOem, _TOemTag))? TRUE : FALSE;
  1500. TempDriverInfo->Next = PreinstallDriverList;
  1501. PreinstallDriverList = TempDriverInfo;
  1502. }
  1503. if( PreinstallDriverList != NULL ) {
  1504. //
  1505. // In the pre-install mode, don't let the user specify
  1506. // an OEM scsi, if at least one was specified in unattend.txt
  1507. //
  1508. PromptOemScsi = FALSE;
  1509. }
  1510. }
  1511. }
  1512. p = SlGetSectionKeyIndex(WinntSifHandle,WINNT_SETUPPARAMS_A,WINNT_S_SKIPMISSING_A,0);
  1513. if(p && (*p != '0')) {
  1514. IgnoreMissingFiles = TRUE;
  1515. }
  1516. #if defined(_X86_) || defined(_IA64_)
  1517. //
  1518. // Find out if this is a Win9x upgrade
  1519. //
  1520. Win9xUnsupHdc = FALSE;
  1521. p = SlGetSectionKeyIndex(WinntSifHandle,WINNT_DATA_A,WINNT_D_WIN95UPGRADE_A,0);
  1522. if(p && !_stricmp(p, WINNT_A_YES_A)) {
  1523. //
  1524. // If it is an Win9x upgrade, find out if winnt32 found an unsupported
  1525. // hard disk controller.
  1526. //
  1527. p = SlGetSectionKeyIndex(WinntSifHandle,WINNT_DATA_A,WINNT_D_WIN95UNSUPHDC_A,0);
  1528. if(p && (*p != '0')) {
  1529. Win9xUnsupHdc = TRUE;
  1530. }
  1531. }
  1532. #endif
  1533. //
  1534. // At this point, we know that we wre able to read winnt.sif.
  1535. // So attempt to read migrate.inf. Borrow the BadFileName buffer
  1536. // for temporary use.
  1537. //
  1538. strcpy(BadFileName,BootPath);
  1539. strcat(BadFileName,WINNT_MIGRATE_INF_FILE_A);
  1540. if( SlInitIniFile(NULL,
  1541. BootDeviceId,
  1542. BadFileName,
  1543. &MigrateInfHandle,
  1544. &BlLoaderBlock->SetupLoaderBlock->MigrateInfFile,
  1545. &BlLoaderBlock->SetupLoaderBlock->MigrateInfFileLength,
  1546. &DontCare) != ESUCCESS ) {
  1547. MigrateInfHandle = NULL;
  1548. BlLoaderBlock->SetupLoaderBlock->MigrateInfFile = NULL;
  1549. BlLoaderBlock->SetupLoaderBlock->MigrateInfFileLength = 0;
  1550. }
  1551. //
  1552. // Attempt also to read unsupdrv.inf. Borrow the BadFileName buffer
  1553. // for temporary use.
  1554. //
  1555. strcpy(BadFileName,BootPath);
  1556. strcat(BadFileName,WINNT_UNSUPDRV_INF_FILE_A);
  1557. if( SlInitIniFile(NULL,
  1558. BootDeviceId,
  1559. BadFileName,
  1560. &UnsupDriversInfHandle,
  1561. &BlLoaderBlock->SetupLoaderBlock->UnsupDriversInfFile,
  1562. &BlLoaderBlock->SetupLoaderBlock->UnsupDriversInfFileLength,
  1563. &DontCare) != ESUCCESS ) {
  1564. UnsupDriversInfHandle = NULL;
  1565. BlLoaderBlock->SetupLoaderBlock->UnsupDriversInfFile = NULL;
  1566. BlLoaderBlock->SetupLoaderBlock->UnsupDriversInfFileLength = 0;
  1567. }
  1568. SlGetMigratedHardwareIds(SetupBlock, UnsupDriversInfHandle);
  1569. } else {
  1570. WinntSifHandle = NULL;
  1571. //
  1572. // If winnt.sif doesn't exist, then we don't bother to read migrate.inf and unsupdrv.inf,
  1573. // since we are booting from the retail boot floppies or the CD, and in this
  1574. // case there is no migrate.inf or unsupdrv.inf.
  1575. //
  1576. MigrateInfHandle = NULL;
  1577. BlLoaderBlock->SetupLoaderBlock->MigrateInfFile = NULL;
  1578. BlLoaderBlock->SetupLoaderBlock->MigrateInfFileLength = 0;
  1579. UnsupDriversInfHandle = NULL;
  1580. BlLoaderBlock->SetupLoaderBlock->UnsupDriversInfFile = NULL;
  1581. BlLoaderBlock->SetupLoaderBlock->UnsupDriversInfFileLength = 0;
  1582. }
  1583. //
  1584. // Store the boot path in the loader block.
  1585. //
  1586. if (UseCommandConsole) {
  1587. SetupBlock->Flags |= SETUPBLK_FLAGS_CONSOLE;
  1588. }
  1589. if (g_RollbackEnabled) {
  1590. SetupBlock->Flags |= SETUPBLK_FLAGS_ROLLBACK;
  1591. }
  1592. if ( !BlBootingFromNet ) {
  1593. BlLoaderBlock->NtBootPathName = BootPath;
  1594. } else {
  1595. ANSI_STRING aString;
  1596. UNICODE_STRING uString;
  1597. ULONG length;
  1598. ARC_STATUS ArcStatus;
  1599. ULONG FileId;
  1600. #if defined(REMOTE_BOOT)
  1601. PCHAR TempEnableIpsec;
  1602. #endif // defined(REMOTE_BOOT)
  1603. SetupBlock->Flags |= SETUPBLK_FLAGS_IS_REMOTE_BOOT;
  1604. BlLoaderBlock->NtBootPathName =
  1605. BlAllocateHeap( strlen(NetSetupServerShare) + strlen(BootPath) + 1 );
  1606. if ( BlLoaderBlock->NtBootPathName == NULL ) {
  1607. SlNoMemoryError();
  1608. goto LoadFailed;
  1609. }
  1610. strcpy( BlLoaderBlock->NtBootPathName, NetSetupServerShare );
  1611. strcat( BlLoaderBlock->NtBootPathName, BootPath );
  1612. //
  1613. // NetSetupServerShare is of the form \server\IMirror. NetBootPath
  1614. // is of the form Clients\machine\ (note trailing \). We need to
  1615. // insert a \ between the two and add BootDrive to yield
  1616. // \server\IMirror\Clients\machine\BootDrive.
  1617. //
  1618. length = strlen(NetSetupServerShare) + 1 + strlen(NetBootPath) + strlen("BootDrive") + 1;
  1619. SetupBlock->MachineDirectoryPath = BlAllocateHeap( length );
  1620. if ( SetupBlock->MachineDirectoryPath == NULL ) {
  1621. SlNoMemoryError();
  1622. goto LoadFailed;
  1623. }
  1624. strcpy( SetupBlock->MachineDirectoryPath, NetSetupServerShare );
  1625. SetupBlock->MachineDirectoryPath[strlen(NetSetupServerShare)] = '\\';
  1626. SetupBlock->MachineDirectoryPath[strlen(NetSetupServerShare) + 1] = 0;
  1627. strcat(SetupBlock->MachineDirectoryPath, NetBootPath);
  1628. strcat(SetupBlock->MachineDirectoryPath, "BootDrive");
  1629. //
  1630. // Save the path to the SIF file so it can be deleted later.
  1631. //
  1632. if (((SetupBlock->Flags & (SETUPBLK_FLAGS_REMOTE_INSTALL|SETUPBLK_FLAGS_SYSPREP_INSTALL)) != 0) &&
  1633. (NetbootSifFile[0] != '\0')) {
  1634. length = strlen(NetSetupServerShare) + 1 + strlen(NetbootSifFile) + 1;
  1635. SetupBlock->NetBootSifPath = BlAllocateHeap( length );
  1636. if ( SetupBlock->NetBootSifPath == NULL ) {
  1637. SlNoMemoryError();
  1638. goto LoadFailed;
  1639. }
  1640. strcpy( SetupBlock->NetBootSifPath, NetSetupServerShare );
  1641. SetupBlock->NetBootSifPath[strlen(NetSetupServerShare)] = '\\';
  1642. SetupBlock->NetBootSifPath[strlen(NetSetupServerShare) + 1] = 0;
  1643. strcat(SetupBlock->NetBootSifPath, NetbootSifFile);
  1644. }
  1645. //
  1646. // NetSetupServerShare was read from winnt.sif and we replaced
  1647. // the '\' at the end with a NULL -- put this back for when
  1648. // winnt.sif is re-parsed by the kernel (the only modification
  1649. // that the kernel parser can really accept is replacing a
  1650. // final " with a NULL, which SlInitIniFile does).
  1651. //
  1652. NetSetupServerShare[strlen(NetSetupServerShare)] = '\\';
  1653. //
  1654. // Get the computer name from winnt.sif.
  1655. //
  1656. p = SlGetSectionKeyIndex(WinntSifHandle,WINNT_USERDATA_A,WINNT_US_COMPNAME_A,0);
  1657. if(!p || (*p == 0)) {
  1658. SlFatalError(SL_INF_ENTRY_MISSING,WINNT_US_COMPNAME,WINNT_USERDATA);
  1659. goto LoadFailed;
  1660. }
  1661. RtlInitString( &aString, p );
  1662. uString.Buffer = SetupBlock->ComputerName;
  1663. uString.MaximumLength = 64 * sizeof(WCHAR);
  1664. RtlAnsiStringToUnicodeString( &uString, &aString, FALSE );
  1665. //
  1666. // Save these from the global variables.
  1667. //
  1668. SetupBlock->IpAddress = NetLocalIpAddress;
  1669. SetupBlock->SubnetMask = NetLocalSubnetMask;
  1670. SetupBlock->DefaultRouter = NetGatewayIpAddress;
  1671. SetupBlock->ServerIpAddress = NetServerIpAddress;
  1672. //
  1673. // Get information about the net card and do an exchange with the
  1674. // server to get information we need to load it properly.
  1675. //
  1676. SetupBlock->NetbootCardInfo = BlAllocateHeap(sizeof(NET_CARD_INFO));
  1677. if ( SetupBlock->NetbootCardInfo == NULL ) {
  1678. SlNoMemoryError();
  1679. goto LoadFailed;
  1680. }
  1681. SetupBlock->NetbootCardInfoLength = sizeof(NET_CARD_INFO);
  1682. Status = NetQueryCardInfo(
  1683. (PNET_CARD_INFO)SetupBlock->NetbootCardInfo
  1684. );
  1685. if (Status != STATUS_SUCCESS) {
  1686. SlFatalError(SL_NETBOOT_CARD_ERROR);
  1687. goto LoadFailed;
  1688. }
  1689. //
  1690. // This call may allocate SetupBlock->NetbootCardRegistry
  1691. //
  1692. Status = NetQueryDriverInfo(
  1693. (PNET_CARD_INFO)SetupBlock->NetbootCardInfo,
  1694. NetSetupServerShare,
  1695. NULL,
  1696. SetupBlock->NetbootCardHardwareId,
  1697. sizeof(SetupBlock->NetbootCardHardwareId),
  1698. SetupBlock->NetbootCardDriverName,
  1699. NetbootCardDriverName,
  1700. sizeof(SetupBlock->NetbootCardDriverName),
  1701. SetupBlock->NetbootCardServiceName,
  1702. sizeof(SetupBlock->NetbootCardServiceName),
  1703. &SetupBlock->NetbootCardRegistry,
  1704. &SetupBlock->NetbootCardRegistryLength);
  1705. if (Status == STATUS_INSUFFICIENT_RESOURCES) {
  1706. SlNoMemoryError();
  1707. goto LoadFailed;
  1708. } else if (Status != STATUS_SUCCESS) {
  1709. SlFatalError(SL_NETBOOT_SERVER_ERROR);
  1710. goto LoadFailed;
  1711. }
  1712. #if 0
  1713. DbgPrint("HardwareID is <%ws>, DriverName is <%ws>, Service <%ws>\n",
  1714. SetupBlock->NetbootCardHardwareId,
  1715. SetupBlock->NetbootCardDriverName,
  1716. SetupBlock->NetbootCardServiceName);
  1717. DbgPrint("NetbootCardRegistry at %lx, length %d\n",
  1718. SetupBlock->NetbootCardRegistry,
  1719. SetupBlock->NetbootCardRegistryLength);
  1720. DbgBreakPoint();
  1721. #endif
  1722. #if defined(REMOTE_BOOT)
  1723. //
  1724. // See if we should enable remote boot security (IPSEC).
  1725. //
  1726. TempEnableIpsec = SlGetSectionKeyIndex(WinntSifHandle,
  1727. "RemoteBoot",
  1728. "EnableIpSecurity",
  1729. 0);
  1730. if ((TempEnableIpsec != NULL) &&
  1731. ((TempEnableIpsec[0] == 'Y') ||
  1732. (TempEnableIpsec[0] == 'y'))) {
  1733. RemoteBootEnableIpsec = TRUE;
  1734. }
  1735. if ((SetupBlock->Flags & (SETUPBLK_FLAGS_REMOTE_INSTALL |
  1736. SETUPBLK_FLAGS_SYSPREP_INSTALL)) == 0) {
  1737. //
  1738. // Read the secret off the disk, if there is one, and store it
  1739. // in the loader block.
  1740. //
  1741. ArcStatus = BlOpenRawDisk(&FileId);
  1742. if (ArcStatus == ESUCCESS) {
  1743. SetupBlock->NetBootSecret = BlAllocateHeap(sizeof(RI_SECRET));
  1744. if (SetupBlock->NetBootSecret == NULL) {
  1745. SlNoMemoryError();
  1746. BlCloseRawDisk(FileId);
  1747. goto LoadFailed;
  1748. }
  1749. ArcStatus = BlReadSecret(FileId, (PRI_SECRET)(SetupBlock->NetBootSecret));
  1750. if (ArcStatus != ESUCCESS) {
  1751. SlNoMemoryError();
  1752. BlCloseRawDisk(FileId);
  1753. goto LoadFailed;
  1754. }
  1755. ArcStatus = BlCloseRawDisk(FileId);
  1756. //
  1757. // By now we have TFTPed some files so this will be TRUE if it
  1758. // is ever going to be.
  1759. //
  1760. SetupBlock->NetBootUsePassword2 = NetBootTftpUsedPassword2;
  1761. }
  1762. } else
  1763. #endif // defined(REMOTE_BOOT)
  1764. {
  1765. //
  1766. // Construct a secret to pass to the redirector, based on what
  1767. // was passed to use across the reboot. For the moment only
  1768. // user/domain/password matters.
  1769. //
  1770. WCHAR UnicodePassword[64];
  1771. UNICODE_STRING TmpNtPassword;
  1772. CHAR LmOwfPassword[LM_OWF_PASSWORD_SIZE];
  1773. CHAR NtOwfPassword[NT_OWF_PASSWORD_SIZE];
  1774. CHAR GarbageSid[RI_SECRET_SID_SIZE];
  1775. ULONG i;
  1776. SetupBlock->NetBootSecret = BlAllocateHeap(sizeof(RI_SECRET));
  1777. if (SetupBlock->NetBootSecret == NULL) {
  1778. SlNoMemoryError();
  1779. goto LoadFailed;
  1780. }
  1781. //
  1782. // Do a quick conversion of the password to Unicode.
  1783. //
  1784. TmpNtPassword.Length = strlen(NetbootPassword) * sizeof(WCHAR);
  1785. TmpNtPassword.MaximumLength = sizeof(UnicodePassword);
  1786. TmpNtPassword.Buffer = UnicodePassword;
  1787. for (i = 0; i < sizeof(NetbootPassword); i++) {
  1788. UnicodePassword[i] = (WCHAR)(NetbootPassword[i]);
  1789. }
  1790. BlOwfPassword(NetbootPassword, &TmpNtPassword, LmOwfPassword, NtOwfPassword);
  1791. BlInitializeSecret(
  1792. NetbootDomain,
  1793. NetbootUser,
  1794. LmOwfPassword,
  1795. NtOwfPassword,
  1796. #if defined(REMOTE_BOOT)
  1797. NULL, // no password2
  1798. NULL, // no password2
  1799. #endif // defined(REMOTE_BOOT)
  1800. GarbageSid,
  1801. SetupBlock->NetBootSecret);
  1802. }
  1803. }
  1804. //
  1805. // Initialize the debugging system.
  1806. //
  1807. BlLogInitialize(BootDeviceId);
  1808. //
  1809. // Do PPC-specific initialization.
  1810. //
  1811. #if defined(_PPC_)
  1812. Status = BlPpcInitialize();
  1813. if (Status != ESUCCESS) {
  1814. goto LoadFailed;
  1815. }
  1816. #endif // defined(_PPC_)
  1817. //
  1818. // Check for an alternate Kernel Debugger DLL, i.e.,
  1819. // /debugport=1394 (kd1394.dll), /debugport=usb (kdusb.dll), etc...
  1820. //
  1821. if (BlLoaderBlock->LoadOptions != NULL) {
  1822. FileName = strstr(BlLoaderBlock->LoadOptions, "DEBUGPORT=");
  1823. if (FileName == NULL) {
  1824. FileName = strstr(BlLoaderBlock->LoadOptions, "debugport=");
  1825. }
  1826. }
  1827. if (FileName != NULL) {
  1828. _strupr(FileName);
  1829. if (strstr(FileName, "COM") == NULL) {
  1830. UseAlternateKdDll = TRUE;
  1831. FileName += strlen("DEBUGPORT=");
  1832. for (i = 0; i < KD_ALT_DLL_REPLACE_CHARS; i++) {
  1833. if (FileName[i] == ' ') {
  1834. break;
  1835. }
  1836. KdFileName[KD_ALT_DLL_PREFIX_CHARS + i] = FileName[i];
  1837. }
  1838. KdFileName[KD_ALT_DLL_PREFIX_CHARS + i] = '\0';
  1839. strcat(KdFileName, ".DLL");
  1840. }
  1841. }
  1842. //
  1843. // If this is a preinstall case then add another
  1844. // OEM source device
  1845. //
  1846. if (PreInstall || WinPEBoot) {
  1847. PreInstallOemSourceDevice = BlAllocateHeap(sizeof(OEM_SOURCE_DEVICE));
  1848. PreInstallSourcePath = BlAllocateHeap(256);
  1849. if (PreInstallOemSourceDevice && PreInstallSourcePath) {
  1850. strcpy(PreInstallOemSourceDevice->ArcDeviceName,
  1851. BootDevice);
  1852. strcpy(PreInstallSourcePath, BootPath);
  1853. strcat(PreInstallSourcePath, WINNT_OEM_DIR_A);
  1854. PreInstallOemSourceDevice->DriverDir = PreInstallSourcePath;
  1855. SL_OEM_SET_SOURCE_DEVICE_TYPE(PreInstallOemSourceDevice,
  1856. (SL_OEM_SOURCE_DEVICE_TYPE_LOCAL |
  1857. SL_OEM_SOURCE_DEVICE_TYPE_FIXED |
  1858. SL_OEM_SOURCE_DEVICE_TYPE_PREINSTALL));
  1859. //
  1860. // Mark the device as containing preinstall drivers only if they
  1861. // specified any F6 mass storage drivers
  1862. //
  1863. if (!WinPEBoot && PreinstallDriverList) {
  1864. SL_OEM_SET_SOURCE_MEDIA_TYPE(PreInstallOemSourceDevice,
  1865. (SL_OEM_SOURCE_MEDIA_PRESENT |
  1866. SL_OEM_SOURCE_MEDIA_HAS_DRIVERS |
  1867. SL_OEM_SOURCE_MEDIA_HAS_MSD |
  1868. SL_OEM_SOURCE_MEDIA_HAS_DEFAULT));
  1869. }
  1870. SL_OEM_SET_SOURCE_DEVICE_STATE(PreInstallOemSourceDevice,
  1871. SL_OEM_SOURCE_DEVICE_NOT_PROCESSED);
  1872. PreInstallOemSourceDevice->DeviceId = BootDeviceId;
  1873. //
  1874. // Insert it at the head of the linked list
  1875. //
  1876. PreInstallOemSourceDevice->Next = OemSourceDevices;
  1877. OemSourceDevices = PreInstallOemSourceDevice;
  1878. } else {
  1879. SlNoMemoryError();
  1880. goto LoadFailed;
  1881. }
  1882. }
  1883. if (!BlBootingFromNet) {
  1884. //
  1885. // Figure out if there are any OEM hal/drivers which need to
  1886. // be autoloaded.
  1887. // NOTE: We skip the dynamic update OEM source device since it's
  1888. // drivers will be autoloaded later.
  1889. //
  1890. POEM_SOURCE_DEVICE CurrDevice = OemSourceDevices;
  1891. while (CurrDevice && !(AutoLoadOemHalDevice && AutoLoadOemScsi)) {
  1892. if ((SL_OEM_SOURCE_MEDIA_TYPE(CurrDevice,
  1893. SL_OEM_SOURCE_MEDIA_HAS_DRIVERS) &&
  1894. SL_OEM_SOURCE_MEDIA_TYPE(CurrDevice,
  1895. SL_OEM_SOURCE_MEDIA_HAS_DEFAULT)) &&
  1896. !SL_OEM_SOURCE_DEVICE_TYPE(CurrDevice,
  1897. SL_OEM_SOURCE_DEVICE_TYPE_DYN_UPDATE)) {
  1898. if (!AutoLoadOemHalDevice &&
  1899. SL_OEM_SOURCE_MEDIA_TYPE(CurrDevice, SL_OEM_SOURCE_MEDIA_HAS_HAL)) {
  1900. AutoLoadOemHalDevice = CurrDevice;
  1901. }
  1902. if (!AutoLoadOemScsi &&
  1903. SL_OEM_SOURCE_MEDIA_TYPE(CurrDevice, SL_OEM_SOURCE_MEDIA_HAS_MSD)) {
  1904. AutoLoadOemScsi = TRUE;
  1905. }
  1906. }
  1907. CurrDevice = CurrDevice->Next;
  1908. }
  1909. //
  1910. // Set allocatable range to the kernel-specific range
  1911. //
  1912. BlUsableBase = BL_KERNEL_RANGE_LOW;
  1913. BlUsableLimit = BL_KERNEL_RANGE_HIGH;
  1914. //
  1915. // Load the kernel.
  1916. //
  1917. SlGetDisk(KERNEL_MP_IMAGE_FILENAME);
  1918. strcpy(KernelDirectoryPath, BootPath);
  1919. strcat(KernelDirectoryPath,KERNEL_MP_IMAGE_FILENAME);
  1920. strcpy(KernelImage,KERNEL_MP_IMAGE_FILENAME);
  1921. #ifdef i386
  1922. retrykernel:
  1923. #endif
  1924. BlOutputLoadMessage(BootDevice, KernelDirectoryPath, BlFindMessage(SL_KERNEL_NAME));
  1925. Status = BlLoadImage(BootDeviceId,
  1926. LoaderSystemCode,
  1927. KernelDirectoryPath,
  1928. TARGET_IMAGE,
  1929. &SystemBase);
  1930. #ifdef i386
  1931. //
  1932. // If the kernel didn't fit in the preferred range, reset the range to
  1933. // all of memory and try again.
  1934. //
  1935. if ((Status == ENOMEM) &&
  1936. ((BlUsableBase != 0) ||
  1937. (BlUsableLimit != _16MB))) {
  1938. BlUsableBase = 0;
  1939. BlUsableLimit = _16MB;
  1940. goto retrykernel;
  1941. }
  1942. #endif
  1943. if (Status != ESUCCESS) {
  1944. SlFatalError(SL_FILE_LOAD_FAILED,SlCopyStringAT(KernelDirectoryPath),Status);
  1945. goto LoadFailed;
  1946. }
  1947. BlUpdateBootStatus();
  1948. //
  1949. // Load the HAL.
  1950. //
  1951. strcpy(HalDirectoryPath, BootPath);
  1952. if (PromptOemHal || (PreInstall && (ComputerType != NULL))) {
  1953. if(PreInstall && OemHal) {
  1954. //
  1955. // This is a pre-install and an OEM hal was specified
  1956. //
  1957. strcat( HalDirectoryPath,
  1958. #if defined(_X86_) || defined(_IA64_)
  1959. WINNT_OEM_DIR_A
  1960. #else
  1961. WINNT_OEM_TEXTMODE_DIR_A
  1962. #endif
  1963. );
  1964. strcat( HalDirectoryPath, "\\" );
  1965. }
  1966. SlPromptOemHal((PreInstall ? PreInstallOemSourceDevice : DefaultOemSourceDevice),
  1967. (!PreInstall || (ComputerType == NULL)),
  1968. &HalBase,
  1969. &HalName);
  1970. strcat(HalDirectoryPath,HalName);
  1971. //
  1972. // Reset the last disk tag for floopy boot
  1973. //
  1974. if (FloppyBoot) {
  1975. LastDiskTag = NULL;
  1976. }
  1977. } else {
  1978. //
  1979. // Note that on x86, the HAL may be on floppy #1 or floppy #2
  1980. //
  1981. strcat(HalDirectoryPath,HalName);
  1982. SlGetDisk(HalName);
  1983. BlOutputLoadMessage(BootDevice, HalDirectoryPath, BlFindMessage(SL_HAL_NAME));
  1984. #ifdef i386
  1985. retryhal:
  1986. #endif
  1987. Status = BlLoadImage(BootDeviceId,
  1988. LoaderHalCode,
  1989. HalDirectoryPath,
  1990. TARGET_IMAGE,
  1991. &HalBase);
  1992. #ifdef i386
  1993. //
  1994. // If the HAL didn't fit in the preferred range, reset the range to
  1995. // all of memory and try again.
  1996. //
  1997. if ((Status == ENOMEM) &&
  1998. ((BlUsableBase != 0) ||
  1999. (BlUsableLimit != _16MB))) {
  2000. BlUsableBase = 0;
  2001. BlUsableLimit = _16MB;
  2002. goto retryhal;
  2003. }
  2004. #endif
  2005. if (Status != ESUCCESS) {
  2006. SlFatalError(SL_FILE_LOAD_FAILED,SlCopyStringAT(HalDirectoryPath),Status);
  2007. goto LoadFailed;
  2008. }
  2009. BlUpdateBootStatus();
  2010. }
  2011. //
  2012. // Set allocatable range to the driver-specific range
  2013. //
  2014. BlUsableBase = BL_DRIVER_RANGE_LOW;
  2015. BlUsableLimit = BL_DRIVER_RANGE_HIGH;
  2016. } else {
  2017. PCHAR id;
  2018. ULONG idLength;
  2019. //
  2020. // This is a remote boot setup. Load the HAL first, so that we
  2021. // can determine whether to load the UP or MP kernel.
  2022. //
  2023. // Note that we cannot load the HAL first on local boots
  2024. // because that would break floppy boot, where the kernel
  2025. // is on floppy #1 and the HALs are on floppy #2.
  2026. //
  2027. //
  2028. // Set allocatable range to the kernel-specific range
  2029. //
  2030. // Don't do this for RIS right now. (matth 4/18/2001)
  2031. //
  2032. // BlUsableBase = BL_KERNEL_RANGE_LOW;
  2033. // BlUsableLimit = BL_KERNEL_RANGE_HIGH;
  2034. strcpy(HalDirectoryPath, BootPath);
  2035. if (PromptOemHal || (PreInstall && (ComputerType != NULL))) {
  2036. if(PreInstall && OemHal) {
  2037. //
  2038. // This is a pre-install and an OEM hal was specified
  2039. //
  2040. strcat( HalDirectoryPath,
  2041. #if defined(_X86_) || defined(_IA64_)
  2042. WINNT_OEM_DIR_A
  2043. #else
  2044. WINNT_OEM_TEXTMODE_DIR_A
  2045. #endif
  2046. );
  2047. strcat( HalDirectoryPath, "\\" );
  2048. }
  2049. SlPromptOemHal((PreInstall ? PreInstallOemSourceDevice : DefaultOemSourceDevice),
  2050. (!PreInstall || (ComputerType == NULL)),
  2051. &HalBase,
  2052. &HalName);
  2053. strcat(HalDirectoryPath,HalName);
  2054. //
  2055. // Reset the last disk tag for floopy boot
  2056. //
  2057. if (FloppyBoot) {
  2058. LastDiskTag = NULL;
  2059. }
  2060. } else {
  2061. strcat(HalDirectoryPath,HalName);
  2062. BlOutputLoadMessage(BootDevice, HalDirectoryPath, BlFindMessage(SL_HAL_NAME));
  2063. Status = BlLoadImage(BootDeviceId,
  2064. LoaderHalCode,
  2065. HalDirectoryPath,
  2066. TARGET_IMAGE,
  2067. &HalBase);
  2068. if (Status != ESUCCESS) {
  2069. SlFatalError(SL_FILE_LOAD_FAILED,SlCopyStringAT(HalDirectoryPath),Status);
  2070. goto LoadFailed;
  2071. }
  2072. BlUpdateBootStatus();
  2073. }
  2074. //
  2075. // Load the kernel, loading ntoskrnl.exe or ntkrnlmp.exe based on
  2076. // whether the HAL is UP or MP. This is important for remote boot
  2077. // because the networking code's spin lock usage pattern requires
  2078. // the kernel and HAL to be matched.
  2079. //
  2080. // If the computer ID string ends in "_mp", load the MP kernel.
  2081. // Otherwise, load the UP kernel. The code is modeled after similar
  2082. // code in setup\textmode\kernel\sphw.c\SpInstallingMp().
  2083. //
  2084. id = SetupBlock->ComputerDevice.IdString;
  2085. idLength = strlen(id);
  2086. //
  2087. // load ntkrnlmp always in MiniNT network boot
  2088. //
  2089. #if defined(EFI)
  2090. strcpy( KernelImage, KERNEL_MP_IMAGE_FILENAME );
  2091. #else
  2092. if (WinPEBoot || ((idLength >= 3) && (_stricmp(id+idLength-3,"_mp") == 0))) {
  2093. strcpy(KernelImage,KERNEL_MP_IMAGE_FILENAME);
  2094. } else {
  2095. strcpy(KernelImage,KERNEL_UP_IMAGE_FILENAME);
  2096. }
  2097. #endif
  2098. #if defined(REMOTE_BOOT)
  2099. #if DBG
  2100. if ((strlen(id) + 1) > sizeof(SetupBlock->NetBootHalName)) {
  2101. DbgPrint("The HAL name is too long!\n");
  2102. goto LoadFailed;
  2103. }
  2104. #endif
  2105. strcpy(SetupBlock->NetBootHalName, id);
  2106. #endif // defined(REMOTE_BOOT)
  2107. SlGetDisk(KernelImage);
  2108. strcpy(KernelDirectoryPath, BootPath);
  2109. strcat(KernelDirectoryPath,KernelImage);
  2110. BlOutputLoadMessage(BootDevice, KernelDirectoryPath, BlFindMessage(SL_KERNEL_NAME));
  2111. Status = BlLoadImage(BootDeviceId,
  2112. LoaderSystemCode,
  2113. KernelDirectoryPath,
  2114. TARGET_IMAGE,
  2115. &SystemBase);
  2116. if (Status != ESUCCESS) {
  2117. SlFatalError(SL_FILE_LOAD_FAILED,SlCopyStringAT(KernelDirectoryPath),Status);
  2118. goto LoadFailed;
  2119. }
  2120. BlUpdateBootStatus();
  2121. //
  2122. // Set allocatable range to the driver-specific range
  2123. //
  2124. BlUsableBase = BL_DRIVER_RANGE_LOW;
  2125. BlUsableLimit = BL_DRIVER_RANGE_HIGH;
  2126. }
  2127. //
  2128. // Load Kernel Debugger DLL
  2129. //
  2130. strcpy(KdDllName, BootPath);
  2131. strcat(KdDllName, KdFileName);
  2132. SlGetDisk(KdFileName);
  2133. BlOutputLoadMessage(BootDevice, KdDllName, BlFindMessage(SL_KDDLL_NAME));
  2134. Status = BlLoadImage(BootDeviceId,
  2135. LoaderHalCode,
  2136. KdDllName,
  2137. TARGET_IMAGE,
  2138. &KdDllBase);
  2139. if ((Status != ESUCCESS) && (UseAlternateKdDll == TRUE)) {
  2140. UseAlternateKdDll = FALSE;
  2141. strcpy(KdDllName, BootPath);
  2142. strcpy(KdFileName, "KDCOM.DLL");
  2143. strcat(KdDllName, KdFileName);
  2144. Status = BlLoadImage(BootDeviceId,
  2145. LoaderHalCode,
  2146. KdDllName,
  2147. TARGET_IMAGE,
  2148. &KdDllBase);
  2149. }
  2150. if (Status != ESUCCESS) {
  2151. SlFatalError(SL_FILE_LOAD_FAILED, SlCopyStringAT(KdDllName), Status);
  2152. goto LoadFailed;
  2153. }
  2154. //
  2155. // Generate a loader data entry for the system image.
  2156. //
  2157. Status = BlAllocateDataTableEntry("ntoskrnl.exe",
  2158. KernelDirectoryPath,
  2159. SystemBase,
  2160. &SystemDataTableEntry);
  2161. if (Status != ESUCCESS) {
  2162. SlFatalError(SL_FILE_LOAD_FAILED,SlCopyStringAT(KernelDirectoryPath),Status);
  2163. goto LoadFailed;
  2164. }
  2165. //
  2166. // Generate a loader data entry for the HAL DLL.
  2167. //
  2168. Status = BlAllocateDataTableEntry("hal.dll",
  2169. HalDirectoryPath,
  2170. HalBase,
  2171. &HalDataTableEntry);
  2172. if (Status != ESUCCESS) {
  2173. SlFatalError(SL_FILE_LOAD_FAILED,SlCopyStringAT(HalDirectoryPath),Status);
  2174. goto LoadFailed;
  2175. }
  2176. //
  2177. // Generate a loader data entry for the Kernel Debugger DLL.
  2178. //
  2179. Status = BlAllocateDataTableEntry("kdcom.dll",
  2180. KdDllName,
  2181. KdDllBase,
  2182. &KdDataTableEntry);
  2183. if (Status != ESUCCESS) {
  2184. SlFatalError(SL_FILE_LOAD_FAILED, SlCopyStringAT(KdDllName), Status);
  2185. goto LoadFailed;
  2186. }
  2187. #if defined(_ALPHA_)
  2188. {
  2189. CHAR PalFileName[32];
  2190. CHAR FloppyName[80];
  2191. PTCHAR DiskDescription;
  2192. ULONG FloppyId;
  2193. PDETECTED_DEVICE OemPal;
  2194. PDETECTED_DEVICE_FILE OemPalFile;
  2195. //
  2196. // Get the name of the pal file we are suppose to load.
  2197. //
  2198. Status = BlGeneratePalName(PalFileName);
  2199. //
  2200. // If we get an error from BlGenereatePalName, something is
  2201. // really wrong with the firmware or the ARC tree. Abort and
  2202. // bail out.
  2203. //
  2204. if (Status != ESUCCESS) {
  2205. SlFatalError(SL_FILE_LOAD_FAILED,SlCopyStringAT(PalFileName),Status);
  2206. goto LoadFailed;
  2207. }
  2208. //
  2209. // Try loading the pal file from the boot device.
  2210. //
  2211. //
  2212. // NOTE John Vert (jvert) 4-Feb-1994
  2213. // Below call assumes all the PALs are on
  2214. // the same floppy. We really should check the SIF
  2215. // file and go immediately to the diskette prompt
  2216. // if it's not in the SIF file, otherwise get
  2217. // the appropriate disk.
  2218. //
  2219. SetupBlock->OemPal = NULL;
  2220. #if defined(_AXP64_)
  2221. SlGetDisk("a121165.p64");
  2222. #else
  2223. SlGetDisk("A321064.PAL");
  2224. #endif
  2225. Status = BlLoadPal(BootDeviceId,
  2226. LoaderSystemCode,
  2227. BootPath,
  2228. TARGET_IMAGE,
  2229. &BlLoaderBlock->u.Alpha.PalBaseAddress,
  2230. BlFindMessage(SL_PAL_NAME));
  2231. //
  2232. // If we have failed, prompt the user for a floppy that contains
  2233. // the pal code and load it from floppy. We keep looping until
  2234. // either we get the right disk, or we get an error other than
  2235. // 'file not found'.
  2236. //
  2237. if(Status == ENOENT) {
  2238. DiskDescription = BlFindMessage(SL_OEM_DISK_PROMPT);
  2239. }
  2240. while (Status == ENOENT) {
  2241. SlClearClientArea();
  2242. //
  2243. // Compute the name of the A: drive.
  2244. //
  2245. if (!SlpFindFloppy(0,FloppyName)) {
  2246. //
  2247. // No floppy drive available, bail out.
  2248. //
  2249. SlFatalError(SL_FILE_LOAD_FAILED,SlCopyStringAT(PalFileName),Status);
  2250. goto LoadFailed;
  2251. }
  2252. //
  2253. // Prompt for the disk.
  2254. //
  2255. SlPromptForDisk(DiskDescription, FALSE);
  2256. //
  2257. // Open the floppy.
  2258. //
  2259. Status = ArcOpen(FloppyName, ArcOpenReadOnly, &FloppyId);
  2260. if (Status != ESUCCESS) {
  2261. //
  2262. // We want to give the user another chance if they didn't
  2263. // have a floppy inserted.
  2264. //
  2265. if(Status != ENOENT) {
  2266. Status = (Status == EIO) ? ENOENT : Status;
  2267. }
  2268. continue;
  2269. }
  2270. //
  2271. // Load the pal file from the root of the floppy.
  2272. //
  2273. Status = BlLoadPal(FloppyId,
  2274. LoaderSystemCode,
  2275. "\\",
  2276. TARGET_IMAGE,
  2277. &BlLoaderBlock->u.Alpha.PalBaseAddress,
  2278. BlFindMessage(SL_PAL_NAME));
  2279. ArcClose(FloppyId);
  2280. //
  2281. // if we found the PAL, then record DETECTED_DEVICE info
  2282. //
  2283. if(Status == ESUCCESS) {
  2284. OemPal = BlAllocateHeap(sizeof(DETECTED_DEVICE));
  2285. if(!OemPal) {
  2286. SlNoMemoryError();
  2287. }
  2288. SetupBlock->OemPal = OemPal;
  2289. OemPal->Next = NULL;
  2290. OemPal->IdString = NULL;
  2291. OemPal->Description = NULL;
  2292. OemPal->ThirdPartyOptionSelected = TRUE;
  2293. OemPal->FileTypeBits = 0;
  2294. OemPal->MigratedDriver = FALSE;
  2295. OemPalFile = BlAllocateHeap(sizeof(DETECTED_DEVICE_FILE));
  2296. if(!OemPalFile) {
  2297. SlNoMemoryError();
  2298. }
  2299. OemPal->Files = OemPalFile;
  2300. OemPalFile->Next = NULL;
  2301. OemPalFile->Filename = SlCopyStringA(PalFileName);
  2302. OemPalFile->FileType = HwFileMax;
  2303. OemPalFile->ConfigName = NULL;
  2304. OemPalFile->RegistryValueList = NULL;
  2305. OemPalFile->DiskDescription = SlCopyString(DiskDescription);
  2306. OemPalFile->DiskTagfile = NULL;
  2307. OemPalFile->Directory = SlCopyStringA("");
  2308. }
  2309. }
  2310. if(Status != ESUCCESS) {
  2311. SlFriendlyError(
  2312. Status,
  2313. PalFileName,
  2314. __LINE__,
  2315. __FILE__
  2316. );
  2317. goto LoadFailed;
  2318. }
  2319. }
  2320. #endif // ifdef _ALPHA_
  2321. PathSet.PathCount = 1;
  2322. PathSet.AliasName = "\\SystemRoot";
  2323. PathSet.PathOffset[0] = '\0';
  2324. PathSet.Source[0].DeviceId = BootDeviceId;
  2325. PathSet.Source[0].DeviceName = BootDevice;
  2326. PathSet.Source[0].DirectoryPath = BootPath;
  2327. Status = BlScanImportDescriptorTable(&PathSet,
  2328. SystemDataTableEntry,
  2329. LoaderSystemCode
  2330. );
  2331. if (Status != ESUCCESS) {
  2332. SlFatalError(SL_FILE_LOAD_FAILED,SlCopyStringAT(KernelImage),Status);
  2333. }
  2334. //
  2335. // Scan the import table for the HAL DLL and load all referenced DLLs.
  2336. //
  2337. Status = BlScanImportDescriptorTable(&PathSet,
  2338. HalDataTableEntry,
  2339. LoaderHalCode);
  2340. if (Status != ESUCCESS) {
  2341. SlFatalError(SL_FILE_LOAD_FAILED,SlCopyStringAT("hal.dll"),Status);
  2342. goto LoadFailed;
  2343. }
  2344. //
  2345. // Scan the import table for the Kernel Debugger DLL and load all
  2346. // referenced DLLs.
  2347. //
  2348. Status = BlScanImportDescriptorTable(&PathSet,
  2349. KdDataTableEntry,
  2350. LoaderSystemCode);
  2351. if (Status != ESUCCESS) {
  2352. SlFatalError(SL_FILE_LOAD_FAILED, SlCopyStringAT(KdFileName), Status);
  2353. goto LoadFailed;
  2354. }
  2355. //
  2356. // Relocate the system entry point and set system specific information.
  2357. //
  2358. NtHeaders = RtlImageNtHeader(SystemBase);
  2359. SystemEntry = (PTRANSFER_ROUTINE)((ULONG_PTR)SystemBase +
  2360. NtHeaders->OptionalHeader.AddressOfEntryPoint);
  2361. #if defined(_MIPS_)
  2362. BlLoaderBlock->u.Mips.GpBase = (ULONG)SystemBase +
  2363. NtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_GLOBALPTR].VirtualAddress;
  2364. #endif
  2365. #if defined(_ALPHA_) || defined(_AXP64_)
  2366. BlLoaderBlock->u.Alpha.GpBase = (ULONG_PTR)SystemBase +
  2367. NtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_GLOBALPTR].VirtualAddress;
  2368. #endif
  2369. #if defined(_IA64_)
  2370. BlLoaderBlock->u.Ia64.KernelVirtualBase = (ULONG_PTR)SystemBase;
  2371. BlLoaderBlock->u.Ia64.KernelPhysicalBase = (ULONG_PTR)SystemBase & 0x7fffffff;
  2372. #endif
  2373. ///////////////////////////////////////////////////////////////////
  2374. //
  2375. // On x86, the files loaded from now on are on boot floppy #2
  2376. //
  2377. ///////////////////////////////////////////////////////////////////
  2378. //
  2379. // Load registry's SYSTEM hive
  2380. //
  2381. SlGetDisk("SETUPREG.HIV");
  2382. Status = BlLoadSystemHive(BootDeviceId,
  2383. NULL, // BlFindMessage(SL_HIVE_NAME), UNREFERENCED_PARAMETER
  2384. BootPath,
  2385. "SETUPREG.HIV");
  2386. if (Status != ESUCCESS) {
  2387. SlFatalError(SL_FILE_LOAD_FAILED,SlCopyStringAT("SETUPREG.HIV"),Status);
  2388. goto LoadFailed;
  2389. }
  2390. //
  2391. // Pull the Docking information from the hardware tree.
  2392. //
  2393. dockInfoData = KeFindConfigurationEntry(BlLoaderBlock->ConfigurationRoot,
  2394. PeripheralClass,
  2395. DockingInformation,
  2396. NULL);
  2397. if (NULL == dockInfoData) {
  2398. BlLoaderBlock->Extension->Profile.Status = HW_PROFILE_STATUS_SUCCESS;
  2399. BlLoaderBlock->Extension->Profile.DockingState = HW_PROFILE_DOCKSTATE_UNKNOWN;
  2400. BlLoaderBlock->Extension->Profile.Capabilities = 0;
  2401. BlLoaderBlock->Extension->Profile.DockID = 0;
  2402. BlLoaderBlock->Extension->Profile.SerialNumber = 0;
  2403. } else if (sizeof (dockInfo) <=
  2404. dockInfoData->ComponentEntry.ConfigurationDataLength) {
  2405. RtlCopyMemory (
  2406. &dockInfo,
  2407. (PUCHAR) (dockInfoData->ConfigurationData) + sizeof(CM_PARTIAL_RESOURCE_LIST),
  2408. sizeof (dockInfo));
  2409. BlLoaderBlock->Extension->Profile.Status = HW_PROFILE_STATUS_FAILURE;
  2410. switch (dockInfo.ReturnCode) {
  2411. case FW_DOCKINFO_SUCCESS:
  2412. BlLoaderBlock->Extension->Profile.Status = HW_PROFILE_STATUS_SUCCESS;
  2413. BlLoaderBlock->Extension->Profile.DockingState = HW_PROFILE_DOCKSTATE_DOCKED;
  2414. BlLoaderBlock->Extension->Profile.Capabilities = dockInfo.Capabilities;
  2415. BlLoaderBlock->Extension->Profile.DockID = dockInfo.DockID;
  2416. BlLoaderBlock->Extension->Profile.SerialNumber = dockInfo.SerialNumber;
  2417. break;
  2418. case FW_DOCKINFO_SYSTEM_NOT_DOCKED:
  2419. BlLoaderBlock->Extension->Profile.Status = HW_PROFILE_STATUS_SUCCESS;
  2420. BlLoaderBlock->Extension->Profile.DockingState = HW_PROFILE_DOCKSTATE_UNDOCKED;
  2421. BlLoaderBlock->Extension->Profile.Capabilities = dockInfo.Capabilities;
  2422. BlLoaderBlock->Extension->Profile.DockID = dockInfo.DockID;
  2423. BlLoaderBlock->Extension->Profile.SerialNumber = dockInfo.SerialNumber;
  2424. break;
  2425. case FW_DOCKINFO_DOCK_STATE_UNKNOWN:
  2426. BlLoaderBlock->Extension->Profile.Status = HW_PROFILE_STATUS_SUCCESS;
  2427. BlLoaderBlock->Extension->Profile.DockingState = HW_PROFILE_DOCKSTATE_UNKNOWN;
  2428. BlLoaderBlock->Extension->Profile.Capabilities = dockInfo.Capabilities;
  2429. BlLoaderBlock->Extension->Profile.DockID = dockInfo.DockID;
  2430. BlLoaderBlock->Extension->Profile.SerialNumber = dockInfo.SerialNumber;
  2431. break;
  2432. case FW_DOCKINFO_FUNCTION_NOT_SUPPORTED:
  2433. case FW_DOCKINFO_BIOS_NOT_CALLED:
  2434. BlLoaderBlock->Extension->Profile.Status = HW_PROFILE_STATUS_SUCCESS;
  2435. default:
  2436. BlLoaderBlock->Extension->Profile.DockingState = HW_PROFILE_DOCKSTATE_UNSUPPORTED;
  2437. BlLoaderBlock->Extension->Profile.Capabilities = dockInfo.Capabilities;
  2438. BlLoaderBlock->Extension->Profile.DockID = dockInfo.DockID;
  2439. BlLoaderBlock->Extension->Profile.SerialNumber = dockInfo.SerialNumber;
  2440. break;
  2441. }
  2442. } else {
  2443. BlLoaderBlock->Extension->Profile.Status = HW_PROFILE_STATUS_SUCCESS;
  2444. BlLoaderBlock->Extension->Profile.Capabilities = 0;
  2445. BlLoaderBlock->Extension->Profile.DockID = 0;
  2446. BlLoaderBlock->Extension->Profile.SerialNumber = 0;
  2447. }
  2448. if (BlLoaderBlock->Extension->Profile.Status == HW_PROFILE_STATUS_SUCCESS) {
  2449. //
  2450. // We don't match profiles in textmode setup so just pretend that we did.
  2451. //
  2452. BlLoaderBlock->Extension->Profile.Status = HW_PROFILE_STATUS_TRUE_MATCH;
  2453. }
  2454. //
  2455. // Allocate structure for NLS data.
  2456. //
  2457. BlLoaderBlock->NlsData = BlAllocateHeap(sizeof(NLS_DATA_BLOCK));
  2458. if (BlLoaderBlock->NlsData == NULL) {
  2459. Status = ENOMEM;
  2460. SlNoMemoryError();
  2461. goto LoadFailed;
  2462. }
  2463. //
  2464. // Load the OEM font
  2465. //
  2466. SlGetDisk(OemHalFontName);
  2467. Status = BlLoadOemHalFont(BootDeviceId,
  2468. NULL, // BlFindMessage(SL_OEM_FONT_NAME), UNREFERENCED_PARAMETER
  2469. BootPath,
  2470. &OemHalFont,
  2471. BadFileName);
  2472. if(Status != ESUCCESS) {
  2473. SlFatalError(SL_FILE_LOAD_FAILED, SlCopyStringAT(BadFileName), Status);
  2474. goto LoadFailed;
  2475. }
  2476. //
  2477. // Load the NLS data.
  2478. //
  2479. // For now, we ensure that the disk containing the ansi
  2480. // codepage file is in the drive and hope that the rest of the
  2481. // nls files (oem codepage, unicode table) are on the same disk.
  2482. //
  2483. SlGetDisk(AnsiCpName);
  2484. Status = BlLoadNLSData(BootDeviceId,
  2485. NULL, // BlFindMessage(SL_NLS_NAME), UNREFERENCED_PARAMETER
  2486. BootPath,
  2487. &AnsiCodepage,
  2488. &OemCodepage,
  2489. &UnicodeCaseTable,
  2490. BadFileName);
  2491. if(Status != ESUCCESS) {
  2492. SlFatalError(SL_FILE_LOAD_FAILED, SlCopyStringAT(BadFileName), Status);
  2493. goto LoadFailed;
  2494. }
  2495. //
  2496. // Load the system drivers we will need here
  2497. //
  2498. InitializeListHead(&BlLoaderBlock->BootDriverListHead);
  2499. //
  2500. // Load setupdd.sys next. Setupdd.sys needs to be loaded before any other
  2501. // driver, because it will need to prep the rest of the system.
  2502. //
  2503. Status = SlLoadDriver(BlFindMessage(SL_SETUP_NAME),
  2504. "setupdd.sys",
  2505. 0,
  2506. TRUE,
  2507. FALSE
  2508. );
  2509. if (Status != ESUCCESS) {
  2510. SlFatalError(SL_FILE_LOAD_FAILED,SlCopyStringAT("setupdd.sys"),Status);
  2511. goto LoadFailed;
  2512. }
  2513. //
  2514. // Fill in its registry key -- setupdd fills these in for all the other
  2515. // drivers (unless we do it here), but we have to do it here for setupdd
  2516. // itself.
  2517. //
  2518. DriverEntry = (PBOOT_DRIVER_LIST_ENTRY)(BlLoaderBlock->BootDriverListHead.Flink);
  2519. DriverEntry->RegistryPath.Buffer = BlAllocateHeap(256);
  2520. if (DriverEntry->RegistryPath.Buffer == NULL) {
  2521. SlNoMemoryError();
  2522. goto LoadFailed;
  2523. }
  2524. DriverEntry->RegistryPath.Length = 0;
  2525. DriverEntry->RegistryPath.MaximumLength = 256;
  2526. RtlAppendUnicodeToString(&DriverEntry->RegistryPath,
  2527. L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\setupdd");
  2528. #if 0
  2529. #ifdef i386
  2530. //
  2531. // Note that if pciide.sys, intelide.sys and pciidex.sys are on the same
  2532. // boot floppy (x86 only), then we don't need to load pciidex.sys.
  2533. // The driver will be automatically loaded when pciide.sys or intelide.sys
  2534. // (both listed on [BusExtenders.Load] is loaded.
  2535. //
  2536. Status = SlLoadDriver(BlFindMessage(SL_PCI_IDE_EXTENSIONS_NAME),
  2537. "PCIIDEX.SYS",
  2538. 0,
  2539. FALSE,
  2540. FALSE
  2541. );
  2542. #endif
  2543. #endif
  2544. //
  2545. // Load boot bus extenders.
  2546. // It has to be done before scsiport.sys
  2547. //
  2548. Status = SlLoadPnpDriversSection( InfFile,
  2549. "BootBusExtenders",
  2550. &(SetupBlock->BootBusExtenders) );
  2551. if (Status!=ESUCCESS) {
  2552. goto LoadFailed;
  2553. }
  2554. //
  2555. // Load bus extenders.
  2556. // It has to be done before scsiport.sys
  2557. //
  2558. Status = SlLoadPnpDriversSection( InfFile,
  2559. "BusExtenders",
  2560. &(SetupBlock->BusExtenders) );
  2561. if (Status!=ESUCCESS) {
  2562. goto LoadFailed;
  2563. }
  2564. //
  2565. // Load input device related drivers.
  2566. //
  2567. Status = SlLoadPnpDriversSection( InfFile,
  2568. "InputDevicesSupport",
  2569. &(SetupBlock->InputDevicesSupport) );
  2570. if (Status!=ESUCCESS) {
  2571. goto LoadFailed;
  2572. }
  2573. //
  2574. // Detect video
  2575. //
  2576. SlDetectVideo(SetupBlock);
  2577. //
  2578. // On x86, the video type is always set to VGA in i386\x86dtect.c.
  2579. // On non-x86, the video type is either recognized, in which case
  2580. // we don't unconditionally need vga.sys (the Display.Load section
  2581. // tells us what to load), or it's not recognized,
  2582. // in which case we will prompt the user for an oem disk.
  2583. // If there is no display controller node at all, then PromptOemDisk
  2584. // will be false and there will be no video device. In this case
  2585. // we load vga.sys.
  2586. //
  2587. if (SetupBlock->VideoDevice.IdString != NULL) {
  2588. VideoFileName = SlGetSectionKeyIndex(InfFile,
  2589. "Display.Load",
  2590. SetupBlock->VideoDevice.IdString,
  2591. SIF_FILENAME_INDEX);
  2592. if (VideoFileName != NULL) {
  2593. #ifdef ARCI386
  2594. VideoDescription = SlGetIniValue(InfFile,
  2595. "Display",
  2596. SetupBlock->VideoDevice.IdString,
  2597. BlFindMessage(SL_VIDEO_NAME));
  2598. #else
  2599. //
  2600. // With the new video detection mechanism, the description
  2601. // for the video driver is likely to be something like
  2602. // "Windows NT Compatible" which looks funny when displayed
  2603. // in the status bar.
  2604. //
  2605. VideoDescription = BlFindMessage(SL_VIDEO_NAME);
  2606. #endif
  2607. if (!WinPEBoot) {
  2608. Status = SlLoadDriver(VideoDescription,
  2609. VideoFileName,
  2610. 0,
  2611. TRUE,
  2612. FALSE
  2613. );
  2614. }
  2615. if (Status == ESUCCESS) {
  2616. SetupBlock->VideoDevice.BaseDllName = SlCopyStringA(VideoFileName);
  2617. } else {
  2618. SlFriendlyError(
  2619. Status,
  2620. VideoFileName,
  2621. __LINE__,
  2622. __FILE__
  2623. );
  2624. goto LoadFailed;
  2625. }
  2626. LoadedAVideoDriver = TRUE;
  2627. }
  2628. } else if (PromptOemVideo) {
  2629. SlPromptOemVideo(DefaultOemSourceDevice,
  2630. TRUE,
  2631. &VideoBase,
  2632. &OemVideoName);
  2633. Status = SlLoadOemDriver(
  2634. "VIDEOPRT.SYS",
  2635. OemVideoName,
  2636. VideoBase,
  2637. BlFindMessage(SL_VIDEO_NAME)
  2638. );
  2639. if(Status==ESUCCESS) {
  2640. LoadedAVideoDriver = TRUE;
  2641. SetupBlock->VideoDevice.BaseDllName = SlCopyStringA(OemVideoName);
  2642. }
  2643. //
  2644. // Reset the last disk tag for floopy boot
  2645. //
  2646. if (FloppyBoot) {
  2647. LastDiskTag = NULL;
  2648. }
  2649. }
  2650. if(!LoadedAVideoDriver) {
  2651. Status = SlLoadDriver(BlFindMessage(SL_VIDEO_NAME),
  2652. VGA_DRIVER_FILENAME,
  2653. 0,
  2654. TRUE,
  2655. FALSE
  2656. );
  2657. if(Status == ESUCCESS) {
  2658. SetupBlock->VideoDevice.BaseDllName = SlCopyStringA(VGA_DRIVER_FILENAME);
  2659. } else {
  2660. SlFriendlyError(
  2661. Status,
  2662. VGA_DRIVER_FILENAME,
  2663. __LINE__,
  2664. __FILE__
  2665. );
  2666. goto LoadFailed;
  2667. }
  2668. }
  2669. if(SetupBlock->VideoDevice.IdString == NULL) {
  2670. SetupBlock->VideoDevice.IdString = SlCopyStringA(VIDEO_DEVICE_NAME);
  2671. }
  2672. //
  2673. // Load keyboard drivers.
  2674. //
  2675. Status = SlLoadPnpDriversSection( InfFile,
  2676. "Keyboard",
  2677. &(SetupBlock->KeyboardDevices) );
  2678. if (Status!=ESUCCESS) {
  2679. goto LoadFailed;
  2680. }
  2681. Status = SlLoadDriver(BlFindMessage(SL_KBD_NAME),
  2682. "kbdclass.sys",
  2683. 0,
  2684. TRUE,
  2685. FALSE
  2686. );
  2687. if(Status != ESUCCESS) {
  2688. SlFriendlyError(
  2689. Status,
  2690. "kbdclass.sys",
  2691. __LINE__,
  2692. __FILE__
  2693. );
  2694. goto LoadFailed;
  2695. }
  2696. //
  2697. // We would need mouse support also in minint environment
  2698. //
  2699. if (WinPEBoot) {
  2700. Status = SlLoadSection(InfFile,
  2701. "MouseDrivers",
  2702. FALSE,
  2703. TRUE,
  2704. NULL);
  2705. if(Status != ESUCCESS) {
  2706. SlFriendlyError(
  2707. Status,
  2708. "MouseDrivers",
  2709. __LINE__,
  2710. __FILE__
  2711. );
  2712. goto LoadFailed;
  2713. }
  2714. }
  2715. ///////////////////////////////////////////////////////////////////
  2716. //
  2717. // On x86, the files loaded from now on are on boot floppy #3
  2718. //
  2719. ///////////////////////////////////////////////////////////////////
  2720. //
  2721. // Load scsiport.sys next, so it'll always be around for any scsi miniports we may load
  2722. //
  2723. Status = SlLoadDriver(BlFindMessage(SL_SCSIPORT_NAME),
  2724. "SCSIPORT.SYS",
  2725. 0,
  2726. FALSE,
  2727. FALSE
  2728. );
  2729. //
  2730. // Detect scsi
  2731. //
  2732. // (If the user wants to select their own SCSI devices, we won't
  2733. // do any detection)
  2734. //
  2735. if(!PromptOemScsi && (PreinstallDriverList == NULL) ) {
  2736. SlDetectScsi(SetupBlock);
  2737. #if defined(_X86_) || defined(_IA64_)
  2738. if( Win9xUnsupHdc ) {
  2739. //
  2740. // If this is a Win9x upgrade and winnt32 detected an unsupported
  2741. // SCSI controller, then the user needs to be prompted for an OEM SCSI driver
  2742. //
  2743. PromptOemScsi = TRUE;
  2744. }
  2745. #endif
  2746. }
  2747. #if defined(ELTORITO) && !defined(ARCI386)
  2748. //
  2749. // If this is an El Torito CD-ROM install, then we want to load all SCSI miniports
  2750. // and disk class drivers.
  2751. // BUT we do not want to load all the disk class drivers for an ARC
  2752. // machine which knows what drivers it wants to install from its tree
  2753. //
  2754. if(ElToritoCDBoot) {
  2755. LoadScsiMiniports = TRUE;
  2756. }
  2757. #endif
  2758. //
  2759. // If the LoadScsi flag is set, enumerate all the known SCSI miniports and load each
  2760. // one.
  2761. //
  2762. if(LoadScsiMiniports) {
  2763. if (WinPEBoot && OemInfHandle) {
  2764. Status = SlLoadWinPESection(PreInstallOemSourceDevice,
  2765. OemInfHandle,
  2766. WINNT_OEMSCSIDRIVERS_A,
  2767. InfFile,
  2768. "Scsi",
  2769. TRUE,
  2770. &OemScsiInfo,
  2771. &BlLoaderBlock->SetupLoaderBlock->HardwareIdDatabase);
  2772. } else {
  2773. Status = SlLoadSection(InfFile,"Scsi",TRUE, TRUE, NULL);
  2774. }
  2775. if (Status!=ESUCCESS) {
  2776. goto LoadFailed;
  2777. }
  2778. SetupBlock->ScalarValues.LoadedScsi = 1;
  2779. }
  2780. //
  2781. // Pick the the dynamic update boot drivers, if any
  2782. //
  2783. if (DynamicUpdate) {
  2784. SlLoadOemScsiDriversUnattended(DynamicUpdateSourceDevice,
  2785. WinntSifHandle,
  2786. WINNT_SETUPPARAMS_A,
  2787. WINNT_SP_DYNUPDTBOOTDRIVERROOT_A,
  2788. WINNT_SP_DYNUPDTBOOTDRIVERS_A,
  2789. &OemScsiInfo,
  2790. &BlLoaderBlock->SetupLoaderBlock->HardwareIdDatabase);
  2791. }
  2792. //
  2793. // Allow the user to pick an OEM SCSI driver here
  2794. //
  2795. if (PromptOemScsi || (PreinstallDriverList != NULL)) {
  2796. POEMSCSIINFO DynUpdtScsiInfo = OemScsiInfo;
  2797. SlPromptOemScsi(((PreinstallDriverList == NULL) ?
  2798. DefaultOemSourceDevice : PreInstallOemSourceDevice),
  2799. (!PreInstall || (PreinstallDriverList == NULL)),
  2800. &OemScsiInfo);
  2801. //
  2802. // Mark the default OEM source device as processed,
  2803. // if the user manually pressed F6
  2804. //
  2805. if (PromptOemScsi && DefaultOemSourceDevice) {
  2806. SL_OEM_SET_SOURCE_DEVICE_STATE(DefaultOemSourceDevice,
  2807. SL_OEM_SOURCE_DEVICE_PROCESSED);
  2808. }
  2809. //
  2810. // Reset the last disk tag for floopy boot
  2811. //
  2812. if (FloppyBoot) {
  2813. LastDiskTag = NULL;
  2814. }
  2815. //
  2816. // Merge the dynamic update SCSI driver list with oem SCSI
  2817. // driver list
  2818. //
  2819. if (DynUpdtScsiInfo) {
  2820. if (OemScsiInfo) {
  2821. POEMSCSIINFO CurrNode = DynUpdtScsiInfo;
  2822. while (CurrNode && CurrNode->Next) {
  2823. CurrNode = CurrNode->Next;
  2824. }
  2825. if (CurrNode) {
  2826. CurrNode->Next = OemScsiInfo;
  2827. OemScsiInfo = DynUpdtScsiInfo;
  2828. }
  2829. } else {
  2830. OemScsiInfo = DynUpdtScsiInfo;
  2831. }
  2832. }
  2833. // Cleanup here needed for all installation - ARCI386
  2834. if (UseRegularBackground) {
  2835. SlClearDisplay();
  2836. if (WinPEBoot) {
  2837. StartupMsg ? BlOutputStartupMsgStr(StartupMsg) :
  2838. BlOutputStartupMsg(SL_SETUP_STARTING_WINPE);
  2839. } else {
  2840. if (UseCommandConsole) {
  2841. BlOutputStartupMsg(SL_CMDCONS_STARTING);
  2842. } else if (g_RollbackEnabled) {
  2843. BlOutputStartupMsg(SL_ROLLBACK_STARTING);
  2844. } else {
  2845. BlOutputStartupMsg(SL_SETUP_STARTING);
  2846. }
  2847. }
  2848. BlRedrawProgressBar();
  2849. } else {
  2850. SlClearClientArea();
  2851. SlWriteStatusText(TEXT(""));
  2852. }
  2853. }
  2854. //
  2855. // If we found any valid txtsetup.oem with valid default MSD
  2856. // in any OEM source device which is not yet processed, then
  2857. // go and autoload the drivers from these devices.
  2858. //
  2859. if (OemSourceDevices && AutoLoadOemScsi) {
  2860. POEMSCSIINFO DeviceOemScsiInfo = NULL;
  2861. POEMSCSIINFO LastOemScsiNode = NULL;
  2862. SlLoadOemScsiDriversFromOemSources(OemSourceDevices,
  2863. &BlLoaderBlock->SetupLoaderBlock->HardwareIdDatabase,
  2864. &DeviceOemScsiInfo);
  2865. //
  2866. // Merge the full OEM source device list with the
  2867. // global OEM scsi information
  2868. //
  2869. if (DeviceOemScsiInfo) {
  2870. if (OemScsiInfo) {
  2871. LastOemScsiNode = OemScsiInfo;
  2872. while (LastOemScsiNode->Next) {
  2873. LastOemScsiNode = LastOemScsiNode->Next;
  2874. }
  2875. LastOemScsiNode->Next = DeviceOemScsiInfo;
  2876. } else {
  2877. OemScsiInfo = DeviceOemScsiInfo;
  2878. }
  2879. }
  2880. }
  2881. //
  2882. // Load all the disk images for the virtual devices
  2883. // into memory
  2884. //
  2885. if (OemSourceDevices) {
  2886. Status = SlInitVirtualOemSourceDevices(BlLoaderBlock->SetupLoaderBlock,
  2887. OemSourceDevices);
  2888. if (Status != ESUCCESS) {
  2889. SlFatalError(SL_OEM_FILE_LOAD_FAILED);
  2890. goto LoadFailed;
  2891. }
  2892. }
  2893. //
  2894. // Add unsupported SCSI drivers, if any, to the list
  2895. //
  2896. if( UnsupDriversInfHandle != NULL ) {
  2897. Status = SlDetectMigratedScsiDrivers( UnsupDriversInfHandle );
  2898. if (Status!=ESUCCESS) {
  2899. goto LoadFailed;
  2900. }
  2901. }
  2902. //
  2903. // Walk the list of detected SCSI miniports and load each one.
  2904. //
  2905. ScsiDevice = SetupBlock->ScsiDevices;
  2906. while (ScsiDevice != NULL) {
  2907. if(ScsiDevice->ThirdPartyOptionSelected) {
  2908. if(!OemScsiInfo) {
  2909. SlError(500);
  2910. goto LoadFailed;
  2911. }
  2912. Status = SlLoadOemDriver(
  2913. NULL,
  2914. OemScsiInfo->ScsiName,
  2915. OemScsiInfo->ScsiBase,
  2916. BlFindMessage(SL_SCSIPORT_NAME)
  2917. );
  2918. OemScsiInfo = OemScsiInfo->Next;
  2919. } else if(ScsiDevice->MigratedDriver) {
  2920. Status = SlLoadDriver(ScsiDevice->Description,
  2921. ScsiDevice->BaseDllName,
  2922. 0,
  2923. TRUE,
  2924. TRUE
  2925. );
  2926. if( Status != ESUCCESS ) {
  2927. // DebugOutput("Status = %d %s \n",Status,"");
  2928. }
  2929. } else {
  2930. Status = SlLoadDriver(ScsiDevice->Description,
  2931. ScsiDevice->BaseDllName,
  2932. 0,
  2933. TRUE,
  2934. FALSE
  2935. );
  2936. }
  2937. if((Status == ESUCCESS)
  2938. || ((Status == ENOENT) && IgnoreMissingFiles && !ScsiDevice->ThirdPartyOptionSelected)) {
  2939. SetupBlock->ScalarValues.LoadedScsi = 1;
  2940. } else {
  2941. SlFriendlyError(
  2942. Status,
  2943. ScsiDevice->BaseDllName,
  2944. __LINE__,
  2945. __FILE__
  2946. );
  2947. goto LoadFailed;
  2948. }
  2949. ScsiDevice = ScsiDevice->Next;
  2950. }
  2951. //
  2952. // If the LoadDiskClass flag is set, enumerate all the monolithic disk class drivers
  2953. // and load each one. Note that we also do this if we've "detected" any scsi drivers,
  2954. // so that we preserve the drive order.
  2955. //
  2956. if((LoadDiskClass) || (SetupBlock->ScalarValues.LoadedScsi == 1)) {
  2957. Status = SlLoadSection(InfFile, "DiskDrivers", FALSE, TRUE, NULL);
  2958. if (Status == ESUCCESS) {
  2959. SetupBlock->ScalarValues.LoadedDiskDrivers = 1;
  2960. } else {
  2961. goto LoadFailed;
  2962. }
  2963. }
  2964. #if !defined(_IA64_)
  2965. //
  2966. // There is currently no floppy support on IA64 systems.
  2967. //
  2968. //
  2969. // Load the floppy driver (flpydisk.sys)
  2970. //
  2971. #if !defined (ARCI386) && defined(_X86_)
  2972. Status=ESUCCESS;
  2973. //
  2974. // If there are only SFLOPPY devices (such as the LS-120 ATAPI super floppy)
  2975. // DON'T load flpydisk.sys on them. It will collide with SFLOPPY.SYS
  2976. //
  2977. if (!SlpIsOnlySuperFloppy()) {
  2978. #endif
  2979. Status = SlLoadDriver(BlFindMessage(SL_FLOPPY_NAME),
  2980. "flpydisk.sys",
  2981. 0,
  2982. TRUE,
  2983. FALSE
  2984. );
  2985. #if !defined (ARCI386) && defined(_X86_)
  2986. }
  2987. #endif
  2988. if (Status == ESUCCESS) {
  2989. SetupBlock->ScalarValues.LoadedFloppyDrivers = 1;
  2990. }
  2991. #endif
  2992. #ifdef i386
  2993. else {
  2994. SlFriendlyError(
  2995. Status,
  2996. "flpydisk.sys",
  2997. __LINE__,
  2998. __FILE__
  2999. );
  3000. goto LoadFailed;
  3001. }
  3002. #endif
  3003. if(SetupBlock->ScalarValues.LoadedScsi == 1) {
  3004. //
  3005. // Enumerate the entries in the scsi class section and load each one.
  3006. //
  3007. Status = SlLoadSection(InfFile, "ScsiClass",FALSE, TRUE, NULL);
  3008. if (Status != ESUCCESS) {
  3009. goto LoadFailed;
  3010. }
  3011. }
  3012. if((LoadDiskClass) || (SetupBlock->ScalarValues.LoadedScsi == 1)) {
  3013. Status = SlLoadSection(InfFile, "FileSystems", FALSE, TRUE, NULL);
  3014. if (Status == ESUCCESS) {
  3015. SetupBlock->ScalarValues.LoadedFileSystems = 1;
  3016. } else {
  3017. goto LoadFailed;
  3018. }
  3019. } else {
  3020. //
  3021. // Load FAT
  3022. //
  3023. Status = SlLoadDriver(BlFindMessage(SL_FAT_NAME),
  3024. "fastfat.sys",
  3025. 0,
  3026. TRUE,
  3027. FALSE
  3028. );
  3029. #ifdef i386
  3030. if(Status != ESUCCESS) {
  3031. SlFriendlyError(
  3032. Status,
  3033. "fastfat.sys",
  3034. __LINE__,
  3035. __FILE__
  3036. );
  3037. goto LoadFailed;
  3038. }
  3039. #endif
  3040. }
  3041. //
  3042. // Load CDFS if setupldr was started from a cdrom, or if ForceLoadCdfs is set.
  3043. //
  3044. if (LoadCdfs || (!BlGetPathMnemonicKey(SetupDevice,
  3045. "cdrom",
  3046. &BootDriveNumber))) {
  3047. Status = SlLoadSection(InfFile, "CdRomDrivers",FALSE, TRUE, NULL);
  3048. if (Status == ESUCCESS) {
  3049. SetupBlock->ScalarValues.LoadedCdRomDrivers = 1;
  3050. } else {
  3051. goto LoadFailed;
  3052. }
  3053. }
  3054. if (BlBootingFromNet || WinPEBoot) {
  3055. //
  3056. // Load the network stack.
  3057. //
  3058. Status = SlLoadDriver(BlFindMessage(SL_KSECDD_NAME),
  3059. "ksecdd.sys",
  3060. 0,
  3061. TRUE,
  3062. FALSE
  3063. );
  3064. if(Status != ESUCCESS) {
  3065. SlFriendlyError(
  3066. Status,
  3067. "ksecdd.sys",
  3068. __LINE__,
  3069. __FILE__
  3070. );
  3071. goto LoadFailed;
  3072. }
  3073. Status = SlLoadDriver(BlFindMessage(SL_NDIS_NAME),
  3074. "ndis.sys",
  3075. 0,
  3076. TRUE,
  3077. FALSE
  3078. );
  3079. if(Status != ESUCCESS) {
  3080. SlFriendlyError(
  3081. Status,
  3082. "ndis.sys",
  3083. __LINE__,
  3084. __FILE__
  3085. );
  3086. goto LoadFailed;
  3087. }
  3088. if (BlBootingFromNet) {
  3089. Status = SlLoadDriver(BlFindMessage(SL_IPSEC_NAME),
  3090. "ipsec.sys",
  3091. 0,
  3092. TRUE,
  3093. FALSE
  3094. );
  3095. if(Status != ESUCCESS) {
  3096. SlFriendlyError(
  3097. Status,
  3098. "ipsec.sys",
  3099. __LINE__,
  3100. __FILE__
  3101. );
  3102. goto LoadFailed;
  3103. }
  3104. Status = SlLoadDriver(BlFindMessage(SL_TCPIP_NAME),
  3105. "tcpip.sys",
  3106. 0,
  3107. TRUE,
  3108. FALSE
  3109. );
  3110. if(Status != ESUCCESS) {
  3111. SlFriendlyError(
  3112. Status,
  3113. "tcpip.sys",
  3114. __LINE__,
  3115. __FILE__
  3116. );
  3117. goto LoadFailed;
  3118. }
  3119. Status = SlLoadDriver(BlFindMessage(SL_NETBT_NAME),
  3120. "netbt.sys",
  3121. 0,
  3122. TRUE,
  3123. FALSE
  3124. );
  3125. if(Status != ESUCCESS) {
  3126. SlFriendlyError(
  3127. Status,
  3128. "netbt.sys",
  3129. __LINE__,
  3130. __FILE__
  3131. );
  3132. goto LoadFailed;
  3133. }
  3134. Status = SlLoadDriver(BlFindMessage(SL_NETADAPTER_NAME),
  3135. NetbootCardDriverName,
  3136. 0,
  3137. TRUE,
  3138. FALSE
  3139. );
  3140. if(Status != ESUCCESS) {
  3141. SlFriendlyError(
  3142. Status,
  3143. NetbootCardDriverName,
  3144. __LINE__,
  3145. __FILE__
  3146. );
  3147. goto LoadFailed;
  3148. }
  3149. //
  3150. // Fill in the registry key for the netboot card because its service name
  3151. // may be different from the driver name.
  3152. //
  3153. DriverEntry = (PBOOT_DRIVER_LIST_ENTRY)(BlLoaderBlock->BootDriverListHead.Blink); // SlLoadDriver inserts at the tail
  3154. DriverEntry->RegistryPath.Buffer = BlAllocateHeap(256);
  3155. if (DriverEntry->RegistryPath.Buffer == NULL) {
  3156. SlNoMemoryError();
  3157. goto LoadFailed;
  3158. }
  3159. DriverEntry->RegistryPath.Length = 0;
  3160. DriverEntry->RegistryPath.MaximumLength = 256;
  3161. RtlAppendUnicodeToString(&DriverEntry->RegistryPath,
  3162. L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
  3163. RtlAppendUnicodeToString(&DriverEntry->RegistryPath,
  3164. SetupBlock->NetbootCardServiceName);
  3165. Status = SlLoadDriver(BlFindMessage(SL_RDBSS_NAME),
  3166. "rdbss.sys",
  3167. 0,
  3168. TRUE,
  3169. FALSE
  3170. );
  3171. if(Status != ESUCCESS) {
  3172. SlFriendlyError(
  3173. Status,
  3174. "rdbss.sys",
  3175. __LINE__,
  3176. __FILE__
  3177. );
  3178. goto LoadFailed;
  3179. }
  3180. }
  3181. Status = SlLoadDriver(BlFindMessage(SL_MUP_NAME),
  3182. "mup.sys",
  3183. 0,
  3184. TRUE,
  3185. FALSE
  3186. );
  3187. if(Status != ESUCCESS) {
  3188. SlFriendlyError(
  3189. Status,
  3190. "mup.sys",
  3191. __LINE__,
  3192. __FILE__
  3193. );
  3194. goto LoadFailed;
  3195. }
  3196. if (BlBootingFromNet) {
  3197. Status = SlLoadDriver(BlFindMessage(SL_MRXSMB_NAME),
  3198. "mrxsmb.sys",
  3199. 0,
  3200. TRUE,
  3201. FALSE
  3202. );
  3203. if(Status != ESUCCESS) {
  3204. SlFriendlyError(
  3205. Status,
  3206. "mrxsmb.sys",
  3207. __LINE__,
  3208. __FILE__
  3209. );
  3210. goto LoadFailed;
  3211. }
  3212. }
  3213. }
  3214. if (!UseRegularBackground) {
  3215. SlWriteStatusText (BlFindMessage (SL_KERNEL_TRANSITION));
  3216. }
  3217. //
  3218. // Finally, make sure the appropriate disk containing NTDLL.DLL is in
  3219. // the drive.
  3220. //
  3221. SlGetDisk("ntdll.dll");
  3222. //
  3223. // Fill in the SETUPLDR block with relevant information
  3224. //
  3225. SetupBlock->ArcSetupDeviceName = BlLoaderBlock->ArcBootDeviceName;
  3226. SetupBlock->ScalarValues.SetupFromCdRom = FALSE;
  3227. SetupBlock->ScalarValues.SetupOperation = SetupOperationSetup;
  3228. //
  3229. // Get the NTFT drive signatures to allow the kernel to create the
  3230. // correct ARC name <=> NT name mappings.
  3231. //
  3232. //
  3233. // X86Only : Go enumerate all the disks and record their ability to
  3234. // support xint13.
  3235. //
  3236. BlGetArcDiskInformation(TRUE);
  3237. //
  3238. // ntdetect has already run. Although it's awful to have
  3239. // 2 disks that look just alike, stamping a signature on one
  3240. // after ntdetect has run will also break us. Rather err on
  3241. // the side of caution and not write to the disks.
  3242. //
  3243. // This is much safer on x86 because we've ensured that the
  3244. // boot disk has a signature before we get here. On Alpha,
  3245. // we can't do that. So it's ugly, but call this guy for
  3246. // BIOS-based x86 machines.
  3247. //
  3248. // don't reboot after stamping signatures
  3249. // the first time
  3250. //
  3251. SlpMarkDisks(FALSE);
  3252. //
  3253. // If setup was started from a CD-ROM, generate an entry in the ARC disk
  3254. // information list describing the cd-rom.
  3255. //
  3256. if (!BlGetPathMnemonicKey(SetupDevice,
  3257. "cdrom",
  3258. &BootDriveNumber)) {
  3259. BlReadSignature(SetupDevice,TRUE);
  3260. }
  3261. //
  3262. // Close the ARC device.
  3263. //
  3264. ArcClose(BootDeviceId);
  3265. #if 0
  3266. {
  3267. ULONG EndTime = ArcGetRelativeTime();
  3268. char szTemp[256];
  3269. extern ULONG BlFilesOpened;
  3270. BlPositionCursor(1, 10);
  3271. sprintf(szTemp, "BootTime : %d secs, FilesOpened : %d\r\n",
  3272. EndTime - StartTime, BlFilesOpened );
  3273. BlPrint(szTemp);
  3274. }
  3275. #endif
  3276. if (UseRegularBackground) {
  3277. BlOutputStartupMsg(SL_PLEASE_WAIT);
  3278. BlUpdateProgressBar(100);
  3279. }
  3280. //
  3281. // Remove system32 from the boot path if we added it
  3282. //
  3283. if (WinPEBoot) {
  3284. PCHAR Sys32 = BlLoaderBlock->NtBootPathName +
  3285. strlen(BlLoaderBlock->NtBootPathName) -
  3286. strlen("system32\\");
  3287. if (Sys32 && !_stricmp(Sys32, "system32\\")) {
  3288. *Sys32 = 0;
  3289. }
  3290. }
  3291. //
  3292. // Close down the remote boot network file system.
  3293. //
  3294. // NOTE: If BlBootingFromNet, don't do anything after this point
  3295. // that would cause access to the boot ROM.
  3296. //
  3297. if ( BlBootingFromNet ) {
  3298. NetTerminate();
  3299. }
  3300. //
  3301. //
  3302. // Execute the architecture specific setup code.
  3303. //
  3304. // NOTE: If BlBootingFromNet, don't do anything after this point
  3305. // that would cause access to the boot ROM.
  3306. //
  3307. Status = BlSetupForNt(BlLoaderBlock);
  3308. if (Status != ESUCCESS) {
  3309. SlFriendlyError(
  3310. Status,
  3311. "\"Windows NT Executive\"",
  3312. __LINE__,
  3313. __FILE__
  3314. );
  3315. goto LoadFailed;
  3316. }
  3317. //
  3318. // Turn off the debugging system.
  3319. //
  3320. BlLogTerminate();
  3321. //
  3322. // Inform boot debugger that the boot phase is complete.
  3323. //
  3324. #if defined(ENABLE_LOADER_DEBUG) || DBG
  3325. #if (defined(_X86_) || defined(_ALPHA_)) && !defined(ARCI386)
  3326. if (BdDebuggerEnabled == TRUE) {
  3327. DbgUnLoadImageSymbols(NULL, (PVOID)-1, 0);
  3328. }
  3329. #endif
  3330. #endif
  3331. //
  3332. // Transfer control to loaded image.
  3333. //
  3334. (SystemEntry)(BlLoaderBlock);
  3335. Status = EBADF;
  3336. SlFriendlyError(
  3337. Status,
  3338. "\"Windows NT Executive\"",
  3339. __LINE__,
  3340. __FILE__
  3341. );
  3342. LoadFailed:
  3343. SlWriteStatusText(BlFindMessage(SL_TOTAL_SETUP_DEATH));
  3344. SlFlushConsoleBuffer();
  3345. SlGetChar();
  3346. ArcRestart();
  3347. return(Status);
  3348. }
  3349. VOID
  3350. SlpTruncateMemory(
  3351. IN ULONG MaxMemory
  3352. )
  3353. /*++
  3354. Routine Description:
  3355. Eliminates all the memory descriptors above a given boundary
  3356. Arguments:
  3357. MaxMemory - Supplies the maximum memory boundary in megabytes
  3358. Return Value:
  3359. None.
  3360. --*/
  3361. {
  3362. PLIST_ENTRY NextEntry;
  3363. PMEMORY_ALLOCATION_DESCRIPTOR MemoryDescriptor;
  3364. ULONG MaxPage = MaxMemory * 256; // Convert Mb to pages
  3365. if (MaxMemory == 0) {
  3366. return;
  3367. }
  3368. NextEntry = BlLoaderBlock->MemoryDescriptorListHead.Flink;
  3369. while ( NextEntry != &BlLoaderBlock->MemoryDescriptorListHead ) {
  3370. MemoryDescriptor = CONTAINING_RECORD(NextEntry,
  3371. MEMORY_ALLOCATION_DESCRIPTOR,
  3372. ListEntry);
  3373. NextEntry = NextEntry->Flink;
  3374. if ( (MemoryDescriptor->MemoryType != LoaderFree) &&
  3375. (MemoryDescriptor->MemoryType != LoaderFirmwareTemporary) ) {
  3376. continue;
  3377. }
  3378. if (MemoryDescriptor->BasePage >= MaxPage) {
  3379. //
  3380. // This memory descriptor lies entirely above the boundary,
  3381. // eliminate it.
  3382. //
  3383. BlRemoveDescriptor(MemoryDescriptor);
  3384. } else if (MemoryDescriptor->BasePage + MemoryDescriptor->PageCount > MaxPage) {
  3385. //
  3386. // This memory descriptor crosses the boundary, truncate it.
  3387. //
  3388. MemoryDescriptor->PageCount = MaxPage - MemoryDescriptor->BasePage;
  3389. }
  3390. }
  3391. }
  3392. VOID
  3393. SlGetSetupValuesBeforePrompt(
  3394. IN PSETUP_LOADER_BLOCK SetupBlock
  3395. )
  3396. /*++
  3397. Routine Description:
  3398. Reads the setup control values out of the given .INI file.
  3399. Also supplies reasonable defaults for values that don't exist.
  3400. Arguments:
  3401. SetupBlock - Supplies a pointer to the Setup loader block
  3402. Return Value:
  3403. None. Global variables are initialized to reflect the
  3404. contents of the INI file
  3405. --*/
  3406. {
  3407. PCHAR NlsName;
  3408. ANSI_STRING NlsString;
  3409. PCHAR Options="1";
  3410. ULONG MaxMemory;
  3411. if (BlBootingFromNet) {
  3412. BlLoaderBlock->LoadOptions = SlGetIniValue(WinntSifHandle,
  3413. "setupdata",
  3414. "osloadoptions",
  3415. NULL);
  3416. } else {
  3417. BlLoaderBlock->LoadOptions = NULL;
  3418. }
  3419. if (BlLoaderBlock->LoadOptions == NULL) {
  3420. BlLoaderBlock->LoadOptions = SlGetIniValue(InfFile,
  3421. "setupdata",
  3422. "osloadoptions",
  3423. NULL);
  3424. }
  3425. AnsiCpName = SlGetIniValue(InfFile,
  3426. "nls",
  3427. "AnsiCodepage",
  3428. "c_1252.nls");
  3429. NlsString.Buffer = AnsiCpName;
  3430. NlsString.Length = (USHORT) strlen(AnsiCpName);
  3431. AnsiCodepage.MaximumLength = strlen(AnsiCpName)*sizeof(WCHAR)+sizeof(UNICODE_NULL);
  3432. AnsiCodepage.Buffer = BlAllocateHeap(AnsiCodepage.MaximumLength);
  3433. if (AnsiCodepage.Buffer == NULL) {
  3434. SlNoMemoryError();
  3435. }
  3436. RtlAnsiStringToUnicodeString(&AnsiCodepage, &NlsString, FALSE);
  3437. NlsName = SlGetIniValue(InfFile,
  3438. "nls",
  3439. "OemCodepage",
  3440. "c_437.nls");
  3441. NlsString.Buffer = NlsName;
  3442. NlsString.Length = (USHORT) strlen(NlsName);
  3443. OemCodepage.MaximumLength = strlen(NlsName)*sizeof(WCHAR)+sizeof(UNICODE_NULL);
  3444. OemCodepage.Buffer = BlAllocateHeap(OemCodepage.MaximumLength);
  3445. if (OemCodepage.Buffer == NULL) {
  3446. SlNoMemoryError();
  3447. }
  3448. RtlAnsiStringToUnicodeString(&OemCodepage, &NlsString, FALSE);
  3449. NlsName = SlGetIniValue(InfFile,
  3450. "nls",
  3451. "UnicodeCasetable",
  3452. "l_intl.nls");
  3453. NlsString.Buffer = NlsName;
  3454. NlsString.Length = (USHORT) strlen(NlsName);
  3455. UnicodeCaseTable.MaximumLength = strlen(NlsName)*sizeof(WCHAR)+sizeof(UNICODE_NULL);
  3456. UnicodeCaseTable.Buffer = BlAllocateHeap(UnicodeCaseTable.MaximumLength);
  3457. if (UnicodeCaseTable.Buffer == NULL) {
  3458. SlNoMemoryError();
  3459. }
  3460. RtlAnsiStringToUnicodeString(&UnicodeCaseTable, &NlsString, FALSE);
  3461. OemHalFontName = SlGetIniValue(InfFile,
  3462. "nls",
  3463. "OemHalFont",
  3464. "vgaoem.fon");
  3465. NlsString.Buffer = OemHalFontName;
  3466. NlsString.Length = (USHORT) strlen(OemHalFontName);
  3467. OemHalFont.MaximumLength = strlen(OemHalFontName)*sizeof(WCHAR)+sizeof(UNICODE_NULL);
  3468. OemHalFont.Buffer = BlAllocateHeap(OemHalFont.MaximumLength);
  3469. if (OemHalFont.Buffer == NULL) {
  3470. SlNoMemoryError();
  3471. }
  3472. RtlAnsiStringToUnicodeString(&OemHalFont, &NlsString, FALSE);
  3473. #ifdef _WANT_MACHINE_IDENTIFICATION
  3474. BiosInfo.Buffer = NULL;
  3475. NlsString.Buffer = SlGetIniValue(InfFile,
  3476. "BiosInfo",
  3477. "InfName",
  3478. NULL);
  3479. if (NlsString.Buffer) {
  3480. NlsString.Length = (USHORT) strlen(NlsString.Buffer);
  3481. BiosInfo.MaximumLength = NlsString.Length*sizeof(WCHAR)+sizeof(UNICODE_NULL);
  3482. BiosInfo.Buffer = BlAllocateHeap(BiosInfo.MaximumLength);
  3483. RtlAnsiStringToUnicodeString(&BiosInfo, &NlsString, FALSE);
  3484. }
  3485. #endif
  3486. //
  3487. // Loading all the miniport will exhaust all free mem <16Mb - ArcSetup dies.
  3488. //
  3489. #ifndef ARCI386
  3490. LoadScsiMiniports = (atoi(SlGetIniValue(InfFile,
  3491. "SetupData",
  3492. "ForceScsi",
  3493. "0")) == 1);
  3494. #endif
  3495. LoadDiskClass = (atoi(SlGetIniValue(InfFile,
  3496. "setupdata",
  3497. "ForceDiskClass",
  3498. "0")) == 1);
  3499. LoadCdfs = (atoi(SlGetIniValue(InfFile,
  3500. "setupdata",
  3501. "ForceCdRom",
  3502. "0")) == 1);
  3503. BootPath = SlGetIniValue(InfFile,
  3504. "setupdata",
  3505. "BootPath",
  3506. NULL);
  3507. BootDevice = SlGetIniValue(InfFile,
  3508. "setupdata",
  3509. "BootDevice",
  3510. NULL);
  3511. //
  3512. // Build a linked list with all the P&P hardware ids.
  3513. // listed on [HardwareIdsDatabase]. This list will be used
  3514. // during the initialization phase of setupdd.sys
  3515. //
  3516. SetupBlock->HardwareIdDatabase = NULL;
  3517. if( SpSearchINFSection( InfFile, "HardwareIdsDatabase" ) ) {
  3518. ULONG i;
  3519. PPNP_HARDWARE_ID TempHardwareId;
  3520. PCHAR p;
  3521. for( i = 0;
  3522. ((p = SlGetKeyName( InfFile, "HardwareIdsDatabase", i )) != NULL);
  3523. i++ ) {
  3524. TempHardwareId = BlAllocateHeap(sizeof(PNP_HARDWARE_ID));
  3525. if (TempHardwareId==NULL) {
  3526. SlNoMemoryError();
  3527. }
  3528. TempHardwareId->Id = p;
  3529. p = SlGetSectionKeyIndex( InfFile,
  3530. "HardwareIdsDatabase",
  3531. TempHardwareId->Id,
  3532. 0 );
  3533. TempHardwareId->DriverName = p;
  3534. p = SlGetSectionKeyIndex( InfFile,
  3535. "HardwareIdsDatabase",
  3536. TempHardwareId->Id,
  3537. 1 );
  3538. TempHardwareId->ClassGuid = p;
  3539. TempHardwareId->Next = SetupBlock->HardwareIdDatabase;
  3540. SetupBlock->HardwareIdDatabase = TempHardwareId;
  3541. }
  3542. }
  3543. if (BlLoaderBlock->LoadOptions) {
  3544. _strupr(BlLoaderBlock->LoadOptions);
  3545. if ( Options = strstr(BlLoaderBlock->LoadOptions,"/MAXMEM") ) {
  3546. MaxMemory = atoi(Options+8);
  3547. SlpTruncateMemory( MaxMemory );
  3548. }
  3549. }
  3550. }
  3551. VOID
  3552. SlGetSetupValuesAfterPrompt(
  3553. IN PSETUP_LOADER_BLOCK SetupBlock
  3554. )
  3555. /*++
  3556. Routine Description:
  3557. Reads the setup control values out of the given .INI file. Also supplies
  3558. reasonable defaults for values that don't exist.
  3559. Note : This is called after the user is prompted for F5,
  3560. F6 & F7 behavior.
  3561. Arguments:
  3562. SetupBlock - Supplies a pointer to the Setup loader block
  3563. Return Value:
  3564. None. Global variables are initialized to reflect the contents
  3565. of the INI file
  3566. --*/
  3567. {
  3568. PCHAR MachineName = NULL;
  3569. //
  3570. // Determine which HAL to load. If the appropriate HAL cannot be
  3571. // determined, or if we are to prompt for an OEM HAL, then set the
  3572. // 'PromptOemHal' flag (may have already been set by the user's
  3573. // keypress).
  3574. //
  3575. if(!PromptOemHal) {
  3576. PromptOemHal = (atoi(SlGetIniValue(InfFile,
  3577. "setupdata",
  3578. "ForceOemHal",
  3579. "0")) == 1);
  3580. }
  3581. if(!PromptOemHal) {
  3582. MachineName = SlDetectHal();
  3583. }
  3584. SetupBlock->ComputerDevice.Files = 0;
  3585. SetupBlock->ComputerDevice.Next = NULL;
  3586. SetupBlock->ComputerDevice.Description = NULL;
  3587. SetupBlock->ComputerDevice.ThirdPartyOptionSelected = FALSE;
  3588. SetupBlock->ComputerDevice.FileTypeBits = 0;
  3589. SetupBlock->ComputerDevice.Files = 0;
  3590. SetupBlock->ComputerDevice.BaseDllName = SlCopyStringA("");
  3591. if(MachineName!=NULL) {
  3592. SetupBlock->ComputerDevice.IdString = SlCopyStringA(MachineName);
  3593. //
  3594. // Map the machine name to a HAL name. If we're doing a remote boot,
  3595. // look in the [Hal] section. Otherwise, look in the [Hal.Load]
  3596. // section. (Local setup has a separate section to minimize the
  3597. // number of HAL binaries that need to be on the boot floppies.)
  3598. //
  3599. HalName = SlGetIniValue(InfFile,
  3600. BlBootingFromNet ? "Hal" : "Hal.Load",
  3601. MachineName,
  3602. NULL);
  3603. HalDescription = SlGetIniValue(InfFile,
  3604. "Computer",
  3605. MachineName,
  3606. NULL);
  3607. }
  3608. if(!(MachineName && HalName && HalDescription)) {
  3609. PromptOemHal = TRUE;
  3610. }
  3611. //
  3612. // If we haven't already been instructed to prompt for an OEM SCSI disk (by
  3613. // the user's keypress), then get this value from the inf file.
  3614. //
  3615. if(!PromptOemScsi) {
  3616. PromptOemScsi = (atoi(SlGetIniValue(InfFile,
  3617. "setupdata",
  3618. "ForceOemScsi",
  3619. "0")) == 1);
  3620. }
  3621. }
  3622. VOID
  3623. BlOutputLoadMessage (
  3624. IN PCHAR DeviceName,
  3625. IN PCHAR FileName,
  3626. IN PTCHAR FileDescription OPTIONAL
  3627. )
  3628. /*++
  3629. Routine Description:
  3630. This routine outputs a loading message on the status line
  3631. Arguments:
  3632. DeviceName - Supplies a pointer to a zero terminated device name.
  3633. FileName - Supplies a pointer to a zero terminated file name.
  3634. FileDescription - Friendly name of the file in question.
  3635. Return Value:
  3636. None.
  3637. --*/
  3638. {
  3639. static int dots = 0;
  3640. TCHAR OutputBuffer[256];
  3641. PTCHAR FormatString;
  3642. #ifdef UNICODE
  3643. WCHAR OutputBufferUnicode[256];
  3644. UNICODE_STRING us;
  3645. ANSI_STRING as;
  3646. #endif
  3647. PTCHAR p;
  3648. UNREFERENCED_PARAMETER( DeviceName );
  3649. //
  3650. // Construct and output loading file message.
  3651. //
  3652. if (!UseRegularBackground) {
  3653. FormatString = BlFindMessage(SL_FILE_LOAD_MESSAGE);
  3654. if (FileDescription) {
  3655. _stprintf(OutputBuffer,FormatString,FileDescription);
  3656. SlWriteStatusText(OutputBuffer);
  3657. }
  3658. }
  3659. return;
  3660. }
  3661. ARC_STATUS
  3662. SlLoadDriver(
  3663. IN PTCHAR DriverDescription,
  3664. IN PCHAR DriverName,
  3665. IN ULONG DriverFlags,
  3666. IN BOOLEAN InsertIntoDriverList,
  3667. IN BOOLEAN MigratedDriver
  3668. )
  3669. /*++
  3670. Routine Description:
  3671. Attempts to load a driver from the device identified by the global
  3672. variable BootDeviceId.
  3673. Arguments:
  3674. DriverDescription - Supplies a friendly description of the driver being
  3675. loaded.
  3676. DriverName - Supplies the name of the driver.
  3677. DriverFlags - Flags to set in the LDR_DATA_TABLE_ENTRY.
  3678. InsertIntoDriverList - Flag specifying whether this 'driver' should be
  3679. placed into the BootDriveListHead list (eg, scsiport.sys
  3680. is not a true driver, and should not be placed in this list)
  3681. MigratedDriver - Flag specifying whther this driver was migrated from an NT system.
  3682. Return Value:
  3683. ESUCCESS - Driver successfully loaded
  3684. --*/
  3685. {
  3686. PBOOT_DRIVER_LIST_ENTRY DriverEntry;
  3687. NTSTATUS Status;
  3688. PKLDR_DATA_TABLE_ENTRY DataTableEntry;
  3689. FULL_PATH_SET PathSet;
  3690. if(BlCheckForLoadedDll(DriverName,&DataTableEntry)) {
  3691. return(ESUCCESS);
  3692. }
  3693. DriverEntry = SlpCreateDriverEntry(DriverName);
  3694. if(DriverEntry == NULL) {
  3695. SlNoMemoryError();
  3696. return(ENOMEM);
  3697. }
  3698. if( !WinPEBoot && !MigratedDriver ) {
  3699. SlGetDisk(DriverName);
  3700. }
  3701. PathSet.PathCount = 1;
  3702. PathSet.AliasName = "\\SystemRoot";
  3703. PathSet.PathOffset[0] = '\0';
  3704. PathSet.Source[0].DeviceId = BootDeviceId;
  3705. PathSet.Source[0].DeviceName = BootDevice;
  3706. if (WinPEBoot) {
  3707. static PCHAR Path = NULL;
  3708. if (!Path) {
  3709. CHAR Buffer[256];
  3710. strcpy(Buffer, BootPath);
  3711. strcat(Buffer, "drivers\\");
  3712. Path = SlCopyStringA(Buffer);
  3713. }
  3714. PathSet.Source[0].DirectoryPath = Path;
  3715. } else {
  3716. PathSet.Source[0].DirectoryPath = BootPath;
  3717. }
  3718. Status = BlLoadDeviceDriver(
  3719. &PathSet,
  3720. DriverName,
  3721. DriverDescription,
  3722. DriverFlags,
  3723. &DriverEntry->LdrEntry
  3724. );
  3725. if((Status == ESUCCESS) && InsertIntoDriverList) {
  3726. InsertTailList(&BlLoaderBlock->BootDriverListHead,&DriverEntry->Link);
  3727. }
  3728. return(Status);
  3729. }
  3730. ARC_STATUS
  3731. SlLoadOemDriver(
  3732. IN PCHAR ExportDriver OPTIONAL,
  3733. IN PCHAR DriverName,
  3734. IN PVOID BaseAddress,
  3735. IN PTCHAR LoadMessage
  3736. )
  3737. {
  3738. PBOOT_DRIVER_LIST_ENTRY DriverEntry;
  3739. ARC_STATUS Status;
  3740. PKLDR_DATA_TABLE_ENTRY DataTableEntry;
  3741. FULL_PATH_SET PathSet;
  3742. UNREFERENCED_PARAMETER(LoadMessage);
  3743. if(BlCheckForLoadedDll(DriverName,&DataTableEntry)) {
  3744. return(ESUCCESS);
  3745. }
  3746. if(ExportDriver) {
  3747. SlGetDisk(ExportDriver);
  3748. }
  3749. DriverEntry = SlpCreateDriverEntry(DriverName);
  3750. if (DriverEntry==NULL) {
  3751. return(ENOMEM);
  3752. }
  3753. Status = BlAllocateDataTableEntry(
  3754. DriverName,
  3755. DriverName,
  3756. BaseAddress,
  3757. &DriverEntry->LdrEntry
  3758. );
  3759. if (Status == ESUCCESS) {
  3760. PathSet.PathCount = 1;
  3761. PathSet.AliasName = "\\SystemRoot";
  3762. PathSet.PathOffset[0] = '\0';
  3763. PathSet.Source[0].DeviceId = BootDeviceId;
  3764. PathSet.Source[0].DeviceName = BootDevice;
  3765. PathSet.Source[0].DirectoryPath = BootPath;
  3766. Status = BlScanImportDescriptorTable(
  3767. &PathSet,
  3768. DriverEntry->LdrEntry,
  3769. LoaderBootDriver
  3770. );
  3771. if(Status == ESUCCESS) {
  3772. InsertTailList(&BlLoaderBlock->BootDriverListHead,&DriverEntry->Link);
  3773. }
  3774. }
  3775. return(Status);
  3776. }
  3777. PBOOT_DRIVER_LIST_ENTRY
  3778. SlpCreateDriverEntry(
  3779. IN PCHAR DriverName
  3780. )
  3781. /*++
  3782. Routine Description:
  3783. Allocates and initializes a boot driver list entry structure.
  3784. Arguments:
  3785. DriverName - Supplies the name of the driver.
  3786. Return Value:
  3787. Pointer to the initialized structure.
  3788. --*/
  3789. {
  3790. PBOOT_DRIVER_LIST_ENTRY DriverEntry;
  3791. ANSI_STRING String;
  3792. DriverEntry = BlAllocateHeap(sizeof(BOOT_DRIVER_LIST_ENTRY));
  3793. if (DriverEntry==NULL) {
  3794. SlNoMemoryError();
  3795. return(NULL);
  3796. }
  3797. DriverEntry->FilePath.MaximumLength = strlen(DriverName)*sizeof(WCHAR)+sizeof(WCHAR);
  3798. DriverEntry->FilePath.Buffer = BlAllocateHeap(DriverEntry->FilePath.MaximumLength);
  3799. if (DriverEntry->FilePath.Buffer==NULL) {
  3800. SlNoMemoryError();
  3801. return(NULL);
  3802. }
  3803. String.Length = (USHORT) strlen(DriverName);
  3804. String.Buffer = DriverName;
  3805. RtlAnsiStringToUnicodeString(&DriverEntry->FilePath, &String, FALSE);
  3806. return(DriverEntry);
  3807. }
  3808. BOOLEAN
  3809. SlGetDisk(
  3810. IN PCHAR Filename
  3811. )
  3812. /*++
  3813. Routine Description:
  3814. Given a filename, this routine ensures that the correct disk is
  3815. in the drive identified by the global variables BootDevice and
  3816. BootDeviceId. The user may be prompted to change disks.
  3817. Arguments:
  3818. Filename - Supplies the name of the file to be loaded.
  3819. Return Value:
  3820. TRUE - Disk was successfully loaded.
  3821. FALSE - User has cancelled out of Setup.
  3822. --*/
  3823. {
  3824. PCHAR DiskNumber;
  3825. PTCHAR DiskName;
  3826. PCHAR DiskTag;
  3827. ULONG FileId;
  3828. CHAR PlatformSpecificSection[128];
  3829. PCHAR DiskTagSection = NULL;
  3830. //
  3831. // If the media is fixed, the user can't change disks.
  3832. // Just return TRUE indicating that the disk is in the drive.
  3833. //
  3834. if(FixedBootMedia || BlBootingFromNet) {
  3835. return(TRUE);
  3836. }
  3837. //
  3838. // Look up filename to get the disk number. Look in the platform-specific
  3839. // directory first.
  3840. //
  3841. strcpy(PlatformSpecificSection,FilesSectionName);
  3842. strcat(PlatformSpecificSection,PlatformExtension);
  3843. #if defined(ELTORITO)
  3844. if (ElToritoCDBoot) {
  3845. // for Cd boot we use the setup media path instead of a boot-media-specific path
  3846. DiskNumber = SlGetSectionKeyIndex(InfFile,PlatformSpecificSection,Filename,0);
  3847. } else {
  3848. #endif
  3849. DiskNumber = SlGetSectionKeyIndex(InfFile,PlatformSpecificSection,Filename,6);
  3850. #if defined(ELTORITO)
  3851. }
  3852. #endif
  3853. if(DiskNumber == NULL) {
  3854. #if defined(ELTORITO)
  3855. if (ElToritoCDBoot) {
  3856. // for Cd boot we use the setup media path instead of a boot-media-specific path
  3857. DiskNumber = SlGetSectionKeyIndex(InfFile,FilesSectionName,Filename,0);
  3858. } else {
  3859. #endif
  3860. DiskNumber = SlGetSectionKeyIndex(InfFile,FilesSectionName,Filename,6);
  3861. #if defined(ELTORITO)
  3862. }
  3863. #endif
  3864. }
  3865. if((DiskNumber==NULL) || !(*DiskNumber)) {
  3866. SlFatalError(SL_INF_ENTRY_MISSING,SlCopyStringAT(Filename),FilesSectionName);
  3867. return(FALSE);
  3868. }
  3869. //
  3870. // Look up disk number to get the diskname and tag.
  3871. // Look in platform-specific directory first.
  3872. //
  3873. strcpy(PlatformSpecificSection,MediaSectionName);
  3874. strcat(PlatformSpecificSection,PlatformExtension);
  3875. #ifdef UNICODE
  3876. if(DiskName = (PTCHAR)SlGetSectionKeyIndexW(
  3877. #else
  3878. if(DiskName = (PTCHAR)SlGetSectionKeyIndex(
  3879. #endif
  3880. InfFile,
  3881. PlatformSpecificSection,
  3882. DiskNumber,
  3883. 0)) {
  3884. DiskTag = SlGetSectionKeyIndex(InfFile,PlatformSpecificSection,DiskNumber,1);
  3885. DiskTagSection = PlatformSpecificSection;
  3886. } else {
  3887. #ifdef UNICODE
  3888. if(DiskName = (PTCHAR)SlGetSectionKeyIndexW(
  3889. #else
  3890. if(DiskName = (PTCHAR)SlGetSectionKeyIndex(
  3891. #endif
  3892. InfFile,
  3893. MediaSectionName,
  3894. DiskNumber,
  3895. 0)) {
  3896. DiskTag = SlGetSectionKeyIndex(InfFile,MediaSectionName,DiskNumber,1);
  3897. DiskTagSection = MediaSectionName;
  3898. } else {
  3899. SlFatalError(SL_INF_ENTRY_MISSING,SlCopyStringAT(DiskNumber),SlCopyStringAT(MediaSectionName));
  3900. return(FALSE);
  3901. }
  3902. }
  3903. if (!DiskTag) {
  3904. SlFatalError(SL_INF_ENTRY_MISSING,SlCopyStringAT(DiskNumber), SlCopyStringAT(DiskTagSection));
  3905. return FALSE;
  3906. }
  3907. //
  3908. // If this disk is known to be in the drive, don't look again
  3909. //
  3910. if ((LastDiskTag != NULL) && (!strcmp(DiskTag, LastDiskTag))) {
  3911. return(TRUE);
  3912. }
  3913. LastDiskTag = NULL;
  3914. while(1) {
  3915. //
  3916. // Open a new device id onto the disk.
  3917. //
  3918. if(BootDeviceIdValid) {
  3919. ArcClose(BootDeviceId);
  3920. BootDeviceIdValid = FALSE;
  3921. }
  3922. if(ArcOpen(BootDevice,ArcOpenReadOnly,&BootDeviceId) == ESUCCESS) {
  3923. BootDeviceIdValid = TRUE;
  3924. //
  3925. // Check for existence of the disk tag.
  3926. //
  3927. if(BlOpen(BootDeviceId,DiskTag,ArcOpenReadOnly,&FileId) == ESUCCESS) {
  3928. //
  3929. // Disk is in the drive. Return success.
  3930. // Leave BootDeviceId open onto the device.
  3931. //
  3932. BlClose(FileId);
  3933. LastDiskTag = DiskTag;
  3934. return(TRUE);
  3935. } else {
  3936. //
  3937. // Prompt for the user to change disks.
  3938. //
  3939. ArcClose(BootDeviceId);
  3940. BootDeviceIdValid = FALSE;
  3941. SlPromptForDisk(DiskName, FALSE);
  3942. }
  3943. } else {
  3944. //
  3945. // Can't open device. Prompt for the disk.
  3946. //
  3947. SlPromptForDisk(DiskName, FALSE);
  3948. }
  3949. }
  3950. }
  3951. PTCHAR
  3952. SlCopyString(
  3953. IN PTCHAR String
  3954. )
  3955. /*++
  3956. Routine Description:
  3957. Copies a tchar string into the loader heap so it can be passed to the
  3958. kernel.
  3959. Arguments:
  3960. String - Supplies the string to be copied.
  3961. Return Value:
  3962. PTCHAR - pointer into the loader heap where the string was copied to.
  3963. --*/
  3964. {
  3965. PTCHAR Buffer;
  3966. if (String==NULL) {
  3967. SlNoMemoryError();
  3968. }
  3969. Buffer = BlAllocateHeap((_tcslen(String)+1)*sizeof(TCHAR));
  3970. if (Buffer==NULL) {
  3971. SlNoMemoryError();
  3972. } else {
  3973. _tcscpy(Buffer, String);
  3974. }
  3975. return(Buffer);
  3976. }
  3977. PCHAR
  3978. SlCopyStringA(
  3979. IN PCSTR String
  3980. )
  3981. /*++
  3982. Routine Description:
  3983. Copies an ANSI string into the loader heap so it can be passed to the
  3984. kernel.
  3985. Arguments:
  3986. String - Supplies the string to be copied.
  3987. Return Value:
  3988. PCHAR - pointer into the loader heap where the string was copied to.
  3989. --*/
  3990. {
  3991. PCHAR Buffer;
  3992. if (String==NULL) {
  3993. SlNoMemoryError();
  3994. }
  3995. Buffer = BlAllocateHeap(strlen(String)+1);
  3996. if (Buffer==NULL) {
  3997. SlNoMemoryError();
  3998. } else {
  3999. strcpy(Buffer, String);
  4000. }
  4001. return(Buffer);
  4002. }
  4003. ARC_STATUS
  4004. SlLoadSection(
  4005. IN PVOID Inf,
  4006. IN PCSTR SectionName,
  4007. IN BOOLEAN IsScsiSection,
  4008. IN BOOLEAN AppendLoadSuffix,
  4009. IN OUT PULONG StartingInsertIndex OPTIONAL
  4010. )
  4011. /*++
  4012. Routine Description:
  4013. Enumerates all the drivers in a section and loads them.
  4014. Arguments:
  4015. Inf - Supplies a handle to the INF file.
  4016. SectionName - Supplies the name of the section.
  4017. IsScsiSection - Flag specifying whether this is the Scsi.Load section.
  4018. If so, we create the DETECTED_DEVICE linked list, but
  4019. don't actually load the drivers.
  4020. AppendLoadSuffix - Indicates whether to append the ".load" suffix to the
  4021. section name or not.
  4022. StartingInsertIndex - The position index in the linked list at which
  4023. the device needs to be inserted. The output value
  4024. contains the next available index.
  4025. Return Value:
  4026. ESUCCESS if all drivers were loaded successfully/no errors encountered
  4027. --*/
  4028. {
  4029. ULONG i;
  4030. CHAR LoadSectionName[100];
  4031. PCHAR DriverFilename;
  4032. PCHAR DriverId;
  4033. PTCHAR DriverDescription;
  4034. PCHAR NoLoadSpec;
  4035. PCHAR p;
  4036. ARC_STATUS Status;
  4037. PDETECTED_DEVICE ScsiDevice;
  4038. SCSI_INSERT_STATUS sis;
  4039. ULONG InsertIndex;
  4040. strcpy(LoadSectionName, SectionName);
  4041. if (AppendLoadSuffix) {
  4042. strcat(LoadSectionName, ".Load");
  4043. }
  4044. //
  4045. // Use the specified insert index, if its valid
  4046. //
  4047. if (StartingInsertIndex && ((*StartingInsertIndex) != (-1))) {
  4048. InsertIndex = *StartingInsertIndex;
  4049. } else {
  4050. InsertIndex = 0;
  4051. }
  4052. i=0;
  4053. do {
  4054. DriverFilename = SlGetSectionLineIndex(Inf,LoadSectionName,i,SIF_FILENAME_INDEX);
  4055. NoLoadSpec = SlGetSectionLineIndex(Inf,LoadSectionName,i,2);
  4056. if(DriverFilename && ((NoLoadSpec == NULL) || _stricmp(NoLoadSpec,"noload"))) {
  4057. if(!IsScsiSection) {
  4058. //
  4059. // We only want to load the drivers if they aren't scsi miniports
  4060. //
  4061. DriverId = SlGetKeyName(Inf,LoadSectionName,i);
  4062. #ifdef UNICODE
  4063. DriverDescription = SlGetIniValueW(
  4064. Inf,
  4065. (PSTR)SectionName,
  4066. DriverId,
  4067. SlCopyStringAW(DriverId));
  4068. #else
  4069. DriverDescription = SlGetIniValue(
  4070. Inf,
  4071. (PSTR)SectionName,
  4072. DriverId,
  4073. DriverId);
  4074. #endif
  4075. Status = SlLoadDriver(DriverDescription,
  4076. DriverFilename,
  4077. 0,
  4078. TRUE,
  4079. FALSE
  4080. );
  4081. if((Status == ENOENT) && IgnoreMissingFiles) {
  4082. Status = ESUCCESS;
  4083. }
  4084. } else {
  4085. Status = ESUCCESS;
  4086. }
  4087. if (Status == ESUCCESS) {
  4088. if(IsScsiSection) {
  4089. //
  4090. // Create a new detected device entry.
  4091. //
  4092. if((sis = SlInsertScsiDevice(InsertIndex, &ScsiDevice)) == ScsiInsertError) {
  4093. return(ENOMEM);
  4094. }
  4095. if(sis == ScsiInsertExisting) {
  4096. #if DBG
  4097. //
  4098. // Sanity check to make sure we're talking about the same driver
  4099. //
  4100. if(_stricmp(ScsiDevice->BaseDllName, DriverFilename)) {
  4101. SlError(400);
  4102. return EINVAL;
  4103. }
  4104. #endif
  4105. } else {
  4106. InsertIndex++;
  4107. p = SlGetKeyName(Inf,LoadSectionName,i);
  4108. //
  4109. // Find the driver description
  4110. //
  4111. if(p) {
  4112. #ifdef UNICODE
  4113. DriverDescription = SlGetIniValueW(
  4114. Inf,
  4115. (PSTR)SectionName,
  4116. p,
  4117. SlCopyStringAW(p));
  4118. #else
  4119. DriverDescription = SlGetIniValue(
  4120. Inf,
  4121. (PSTR)SectionName,
  4122. p,
  4123. p);
  4124. #endif
  4125. } else {
  4126. DriverDescription = SlCopyString(BlFindMessage(SL_TEXT_SCSI_UNNAMED));
  4127. }
  4128. ScsiDevice->IdString = p ? p : SlCopyStringA("");
  4129. ScsiDevice->Description = DriverDescription;
  4130. ScsiDevice->ThirdPartyOptionSelected = FALSE;
  4131. ScsiDevice->MigratedDriver = FALSE;
  4132. ScsiDevice->FileTypeBits = 0;
  4133. ScsiDevice->Files = NULL;
  4134. ScsiDevice->BaseDllName = DriverFilename;
  4135. }
  4136. }
  4137. } else {
  4138. SlFriendlyError(
  4139. Status,
  4140. DriverFilename,
  4141. __LINE__,
  4142. __FILE__
  4143. );
  4144. return(Status);
  4145. }
  4146. }
  4147. i++;
  4148. } while ( DriverFilename != NULL );
  4149. if (StartingInsertIndex) {
  4150. *StartingInsertIndex = InsertIndex;
  4151. }
  4152. return(ESUCCESS);
  4153. }
  4154. VOID
  4155. SlpMarkDisks(
  4156. IN BOOLEAN Reboot
  4157. )
  4158. /*++
  4159. Routine Description:
  4160. This routine ensures that there is not more than one disk with the
  4161. same checksum, a signature of zero, and a valid partition table.
  4162. If it finds a disk with a signature of zero, it searches the rest
  4163. of the list for any other disks with a zero signature and the same
  4164. checksum. If it finds one, it stamps a unique signature on the
  4165. first disk.
  4166. We also use a heuristic to determine if the disk is 'vacant', and if
  4167. so, we stamp a unique signature on it (unless it's the first one we
  4168. found).
  4169. Arguments:
  4170. Reboot - Indicates whether to reboot after stamping signatures
  4171. Return Value:
  4172. None.
  4173. --*/
  4174. {
  4175. PARC_DISK_INFORMATION DiskInfo;
  4176. PLIST_ENTRY Entry;
  4177. PLIST_ENTRY CheckEntry;
  4178. PARC_DISK_SIGNATURE DiskSignature;
  4179. PARC_DISK_SIGNATURE CheckDiskSignature;
  4180. ARC_STATUS Status = ESUCCESS;
  4181. BOOLEAN VacantDiskFound = FALSE;
  4182. BOOLEAN SignatureStamped = FALSE;
  4183. ULONG DiskCount = 0;
  4184. ULONG DisksStamped = 0;
  4185. DiskInfo = BlLoaderBlock->ArcDiskInformation;
  4186. Entry = DiskInfo->DiskSignatures.Flink;
  4187. while (Entry != &DiskInfo->DiskSignatures) {
  4188. DiskSignature = CONTAINING_RECORD(Entry,ARC_DISK_SIGNATURE,ListEntry);
  4189. //
  4190. // Make sure there are no other disks with this same
  4191. // signature.
  4192. //
  4193. CheckEntry = Entry->Flink;
  4194. while( CheckEntry != &DiskInfo->DiskSignatures ) {
  4195. CheckDiskSignature = CONTAINING_RECORD(CheckEntry,ARC_DISK_SIGNATURE,ListEntry);
  4196. if( (CheckDiskSignature->Signature == DiskSignature->Signature) ) {
  4197. //
  4198. // We found another disk with the same disk signature.
  4199. // Stamp a new signature on the disk.
  4200. //
  4201. Status = SlpStampFTSignature(CheckDiskSignature, TRUE);
  4202. SignatureStamped = TRUE;
  4203. DisksStamped++;
  4204. if (Status != ESUCCESS) {
  4205. SlError(Status);
  4206. }
  4207. }
  4208. CheckEntry = CheckEntry->Flink;
  4209. }
  4210. //
  4211. // Now look for disk with no signature.
  4212. //
  4213. if (DiskSignature->ValidPartitionTable) {
  4214. if (DiskSignature->Signature == 0) {
  4215. Status = SlpStampFTSignature(DiskSignature, TRUE);
  4216. SignatureStamped = TRUE;
  4217. DisksStamped++;
  4218. if (Status != ESUCCESS) {
  4219. SlError(Status);
  4220. }
  4221. }
  4222. } else {
  4223. //
  4224. // See if the disk is vacant.
  4225. //
  4226. if (SlpIsDiskVacant(DiskSignature)) {
  4227. //
  4228. // If disk has the signature then use it otherwise
  4229. // stamp a new signature
  4230. //
  4231. Status = SlpStampFTSignature(DiskSignature,
  4232. (DiskSignature->Signature == 0));
  4233. SignatureStamped = TRUE;
  4234. DisksStamped++;
  4235. if (Status != ESUCCESS) {
  4236. SlError(Status);
  4237. }
  4238. }
  4239. }
  4240. DiskCount++;
  4241. Entry = Entry->Flink;
  4242. }
  4243. //
  4244. // We've just changed the signatures on a disk. It might be
  4245. // okay to continue with the boot, but may not. Lets not reboot
  4246. // as textmode setup will bugcheck if the signatures
  4247. // are not stamped correctly.
  4248. //
  4249. if( SignatureStamped) {
  4250. if (Reboot) {
  4251. SlFatalError(SIGNATURE_CHANGED);
  4252. } else {
  4253. //
  4254. // Don't bother rescanning the disks if there is only
  4255. // one disk or we just stamped only one disk
  4256. //
  4257. if ((DiskCount > 1) && (DisksStamped > 1)) {
  4258. Status = BlGetArcDiskInformation(TRUE);
  4259. if (Status != ESUCCESS) {
  4260. SlFatalError(SIGNATURE_CHANGED);
  4261. }else {
  4262. //
  4263. // Reboot if first time signature
  4264. // stamping failed to update the disks
  4265. // correctly
  4266. //
  4267. SlpMarkDisks(TRUE);
  4268. }
  4269. }
  4270. }
  4271. }
  4272. }
  4273. BOOLEAN
  4274. SlpIsDiskVacant(
  4275. IN PARC_DISK_SIGNATURE DiskSignature
  4276. )
  4277. /*++
  4278. Routine Description:
  4279. This routine attempts to determine if a disk is 'vacant' by
  4280. checking to see if the first half of its MBR has all bytes set
  4281. to the same value.
  4282. Arguments:
  4283. DiskSignature - Supplies a pointer to the existing disk
  4284. signature structure.
  4285. Return Value:
  4286. TRUE - The disk is vacant.
  4287. FALSE - The disk is not vacant (ie, we can't determine if it
  4288. is vacant using our heuristic)
  4289. --*/
  4290. {
  4291. UCHAR Partition[100];
  4292. ULONG DiskId;
  4293. ARC_STATUS Status;
  4294. UCHAR SectorBuffer[512+256];
  4295. PUCHAR Sector;
  4296. LARGE_INTEGER SeekValue;
  4297. ULONG Count, i;
  4298. BOOLEAN IsVacant;
  4299. //
  4300. // Open partition0.
  4301. //
  4302. strcpy(Partition, DiskSignature->ArcName);
  4303. strcat(Partition, "partition(0)");
  4304. Status = ArcOpen(Partition, ArcOpenReadOnly, &DiskId);
  4305. if (Status != ESUCCESS) {
  4306. return(FALSE);
  4307. }
  4308. //
  4309. // Read in the first sector
  4310. //
  4311. Sector = ALIGN_BUFFER(SectorBuffer);
  4312. SeekValue.QuadPart = 0;
  4313. Status = ArcSeek(DiskId, &SeekValue, SeekAbsolute);
  4314. if (Status == ESUCCESS) {
  4315. Status = ArcRead(DiskId, Sector, 512, &Count);
  4316. }
  4317. if (Status != ESUCCESS) {
  4318. ArcClose(DiskId);
  4319. return(FALSE);
  4320. }
  4321. //
  4322. // See if 1st 256 bytes are identical
  4323. //
  4324. for(i = 1, IsVacant = TRUE; i<256; i++) {
  4325. if(Sector[i] - *Sector) {
  4326. IsVacant = FALSE;
  4327. break;
  4328. }
  4329. }
  4330. ArcClose(DiskId);
  4331. return(IsVacant);
  4332. }
  4333. ARC_STATUS
  4334. SlpStampFTSignature(
  4335. IN PARC_DISK_SIGNATURE DiskSignature,
  4336. IN BOOLEAN GenerateNewSignature
  4337. )
  4338. /*++
  4339. Routine Description:
  4340. This routine stamps a given drive with a unique signature.
  4341. It traverses the list of disk signatures to ensure that it
  4342. stamps a signature that is not already present in the
  4343. disk list. Then it writes the new disk signature to the
  4344. disk and recomputes the checksum.
  4345. Arguments:
  4346. DiskSignature - Supplies a pointer to the existing disk
  4347. signature structure.
  4348. GenerateNewSignature - Indicates whether to generate a new
  4349. signature or use the one in DiskSignature. When TRUE
  4350. this will also disable the check of duplicate signatures.
  4351. This argument is ignored when the DiskSignature->Signature
  4352. field is 0, since 0 is not a valid signature
  4353. Return Value:
  4354. None.
  4355. --*/
  4356. {
  4357. ULONG NewSignature;
  4358. PLIST_ENTRY ListEntry;
  4359. UCHAR SectorBuffer[SECTOR_SIZE * 2];
  4360. PUCHAR Sector;
  4361. LARGE_INTEGER SeekValue;
  4362. UCHAR Partition[100];
  4363. PARC_DISK_SIGNATURE Signature;
  4364. ULONG DiskId;
  4365. ARC_STATUS Status;
  4366. ULONG i;
  4367. ULONG Sum;
  4368. ULONG Count;
  4369. if (GenerateNewSignature || (DiskSignature->Signature == 0)) {
  4370. //
  4371. // Get a reasonably unique seed to start with.
  4372. //
  4373. NewSignature = ArcGetRelativeTime();
  4374. NewSignature = (NewSignature & 0xFFFF) << 16;
  4375. NewSignature += ArcGetRelativeTime();
  4376. //
  4377. // Scan through the list to make sure it's unique.
  4378. //
  4379. ReScan:
  4380. ListEntry = BlLoaderBlock->ArcDiskInformation->DiskSignatures.Flink;
  4381. while (ListEntry != &BlLoaderBlock->ArcDiskInformation->DiskSignatures) {
  4382. Signature = CONTAINING_RECORD(ListEntry,ARC_DISK_SIGNATURE,ListEntry);
  4383. if (Signature->Signature == NewSignature) {
  4384. //
  4385. // Found a duplicate, pick a new number and
  4386. // try again.
  4387. //
  4388. if (++NewSignature == 0) {
  4389. //
  4390. // zero signatures are what we're trying to avoid
  4391. // (like this will ever happen)
  4392. //
  4393. NewSignature = 1;
  4394. }
  4395. goto ReScan;
  4396. }
  4397. ListEntry = ListEntry->Flink;
  4398. }
  4399. } else {
  4400. NewSignature = DiskSignature->Signature;
  4401. }
  4402. //
  4403. // Now we have a valid new signature to put on the disk.
  4404. // Read the sector off disk, put the new signature in,
  4405. // write the sector back, and recompute the checksum.
  4406. //
  4407. strcpy(Partition,DiskSignature->ArcName);
  4408. strcat(Partition,"partition(0)");
  4409. Status = ArcOpen(Partition, ArcOpenReadWrite, &DiskId);
  4410. if (Status != ESUCCESS) {
  4411. return(Status);
  4412. }
  4413. //
  4414. // Read in the first sector
  4415. //
  4416. Sector = ALIGN_BUFFER_WITH_SIZE(SectorBuffer, SECTOR_SIZE);
  4417. SeekValue.QuadPart = 0;
  4418. Status = ArcSeek(DiskId, &SeekValue, SeekAbsolute);
  4419. if (Status == ESUCCESS) {
  4420. Status = ArcRead(DiskId,Sector,512,&Count);
  4421. }
  4422. if (Status != ESUCCESS) {
  4423. ArcClose(DiskId);
  4424. return(Status);
  4425. }
  4426. //
  4427. // If partition table is not valid then initialize it with BOOT_RECORD_SIGNATURE and
  4428. // fill partition entries with zeros
  4429. //
  4430. if (((USHORT UNALIGNED *)Sector)[BOOT_SIGNATURE_OFFSET] != BOOT_RECORD_SIGNATURE) {
  4431. memset(Sector + (PARTITION_TABLE_OFFSET * 2),
  4432. 0,
  4433. SECTOR_SIZE - (PARTITION_TABLE_OFFSET * 2));
  4434. ((USHORT UNALIGNED *)Sector)[BOOT_SIGNATURE_OFFSET] = BOOT_RECORD_SIGNATURE;
  4435. }
  4436. ((ULONG UNALIGNED *)Sector)[PARTITION_TABLE_OFFSET/2-1] = NewSignature;
  4437. Status = ArcSeek(DiskId, &SeekValue, SeekAbsolute);
  4438. if (Status == ESUCCESS) {
  4439. Status = ArcWrite(DiskId,Sector,512,&Count);
  4440. }
  4441. ArcClose(DiskId);
  4442. if (Status != ESUCCESS) {
  4443. return(Status);
  4444. }
  4445. //
  4446. // We have successfully written back out the new signature,
  4447. // recompute the checksum.
  4448. //
  4449. DiskSignature->Signature = NewSignature;
  4450. DiskSignature->ValidPartitionTable = TRUE;
  4451. Sum = 0;
  4452. for (i=0;i<128;i++) {
  4453. Sum += ((PULONG)Sector)[i];
  4454. }
  4455. DiskSignature->CheckSum = 0-Sum;
  4456. return(ESUCCESS);
  4457. }
  4458. VOID
  4459. SlCheckOemKeypress(
  4460. IN ULONG WaitTime
  4461. )
  4462. {
  4463. ULONG StartTime;
  4464. ULONG EndTime;
  4465. ULONG c;
  4466. PTCHAR StatusText;
  4467. //
  4468. // For no particular reason some machines occasionally leave F7s
  4469. // in their keyboard buffer. Drain them out here.
  4470. //
  4471. while (ArcGetReadStatus(ARC_CONSOLE_INPUT) == ESUCCESS) {
  4472. c = SlGetChar();
  4473. switch (c) {
  4474. case SL_KEY_F5: // Force OEM HAL prompt
  4475. PromptOemHal = TRUE;
  4476. break;
  4477. case SL_KEY_F6: // Force OEM SCSI prompt
  4478. PromptOemScsi = TRUE;
  4479. break;
  4480. }
  4481. }
  4482. //
  4483. // HACK alert: The oem hal and SCSI stuff doesn't make sense in an RIS
  4484. // environment. Instead, the administrator should put the oem drivers
  4485. // on the RIS server. So we don't display the OEM drivers prompt, instead
  4486. // we hide it with some bogus "please wait" text. We do this instead of
  4487. // just skipping the check altogether so that the user will still have a
  4488. // chance to press F7 to disable ACPI.
  4489. //
  4490. StatusText = BlFindMessage(
  4491. BlBootingFromNet
  4492. ? SL_PLEASE_WAIT
  4493. : SL_MSG_PRESS_F5_OR_F6);
  4494. if( StatusText != NULL ) {
  4495. SlWriteStatusText(StatusText);
  4496. }
  4497. StartTime = ArcGetRelativeTime();
  4498. if (WinPEBoot) {
  4499. EndTime = StartTime + WaitTime;
  4500. } else {
  4501. EndTime = StartTime + WaitTime;
  4502. }
  4503. do {
  4504. if(ArcGetReadStatus(ARC_CONSOLE_INPUT) == ESUCCESS) {
  4505. //
  4506. // There is a key pending, so see what it is.
  4507. //
  4508. c = SlGetChar();
  4509. switch(c) {
  4510. case SL_KEY_F5: // Force OEM HAL prompt
  4511. PromptOemHal = TRUE;
  4512. break;
  4513. case SL_KEY_F6: // Force OEM SCSI prompt
  4514. PromptOemScsi = TRUE;
  4515. break;
  4516. case SL_KEY_F7:
  4517. DisableACPI = TRUE; // Force ACPI disabled
  4518. break;
  4519. case SL_KEY_F10:
  4520. UseCommandConsole = TRUE; // User wants to use cmdcons
  4521. break;
  4522. }
  4523. }
  4524. } while (EndTime > ArcGetRelativeTime());
  4525. //
  4526. // see comment above -- we reset these values back to FALSE in the RIS
  4527. // scenario because they don't make sense
  4528. //
  4529. if (BlBootingFromNet) {
  4530. PromptOemHal = FALSE;
  4531. PromptOemScsi = FALSE;
  4532. } else {
  4533. SlWriteStatusText(TEXT(""));
  4534. }
  4535. }
  4536. VOID
  4537. SlCheckASRKeypress(
  4538. VOID
  4539. )
  4540. /*++
  4541. Routine Description:
  4542. See if the user is doing an ASR. If so, see if he's got a floppy
  4543. with asrpnp.sif on it. We'll ask him to press F5 for this.
  4544. Arguments:
  4545. None.
  4546. Return Value:
  4547. None.
  4548. --*/
  4549. {
  4550. ARC_STATUS Status;
  4551. #define ASR_FILE "asrpnp.sif"
  4552. ULONG StartTime;
  4553. ULONG EndTime;
  4554. ULONG c;
  4555. PTCHAR StatusText;
  4556. CHAR FloppyName[80];
  4557. ULONG FloppyId;
  4558. CHAR FileName[128];
  4559. PVOID ASRPNPSifHandle = NULL;
  4560. BOOLEAN PromptASR = FALSE;
  4561. BOOLEAN Done = FALSE;
  4562. BOOLEAN FirstTry = TRUE;
  4563. #if defined(EFI)
  4564. //
  4565. // Turn off the EFI Watchdog
  4566. //
  4567. DisableEFIWatchDog();
  4568. #endif
  4569. do {
  4570. SlClearClientArea();
  4571. //
  4572. // Drain the keyboard buffer.
  4573. //
  4574. while (ArcGetReadStatus(ARC_CONSOLE_INPUT) == ESUCCESS) {
  4575. c = SlGetChar();
  4576. }
  4577. if (FirstTry) {
  4578. StatusText = BlFindMessage(SL_MSG_PRESS_ASR);
  4579. FirstTry = FALSE;
  4580. }
  4581. else {
  4582. StatusText = BlFindMessage(SL_MSG_PREPARING_ASR);
  4583. }
  4584. if( StatusText != NULL ) {
  4585. SlWriteStatusText(StatusText);
  4586. }
  4587. StartTime = ArcGetRelativeTime();
  4588. EndTime = StartTime + 5;
  4589. do {
  4590. if(ArcGetReadStatus(ARC_CONSOLE_INPUT) == ESUCCESS) {
  4591. //
  4592. // There is a key pending, so see what it is.
  4593. //
  4594. c = SlGetChar();
  4595. switch(c) {
  4596. case SL_KEY_F2: // Force ASR prompt
  4597. PromptASR = TRUE;
  4598. Done = TRUE;
  4599. break;
  4600. case ASCI_ESC:
  4601. PromptASR = FALSE;
  4602. Done = TRUE;
  4603. break;
  4604. }
  4605. }
  4606. } while( !Done && (EndTime > ArcGetRelativeTime()) );
  4607. SlWriteStatusText(TEXT(""));
  4608. if( PromptASR ) {
  4609. Done = FALSE;
  4610. StatusText = BlFindMessage(SL_MSG_ENTERING_ASR);
  4611. if( StatusText != NULL ) {
  4612. SlWriteStatusText(StatusText);
  4613. }
  4614. //
  4615. // Build the filename we're looking for.
  4616. //
  4617. strcpy( FileName, "\\" );
  4618. strcat( FileName, ASR_FILE );
  4619. //
  4620. // Initialize pointers in loader block.
  4621. //
  4622. BlLoaderBlock->SetupLoaderBlock->ASRPnPSifFile = NULL;
  4623. BlLoaderBlock->SetupLoaderBlock->ASRPnPSifFileLength = 0;
  4624. Status = ESUCCESS;
  4625. //
  4626. // Build the path to the floppy.
  4627. //
  4628. if (SlpFindFloppy(0,FloppyName)) {
  4629. Status = ArcOpen(FloppyName,ArcOpenReadOnly,&FloppyId);
  4630. //
  4631. // We found the floppy and opened him. See if he's
  4632. // got our file.
  4633. //
  4634. if( Status == ESUCCESS ) {
  4635. ASRPNPSifHandle = NULL;
  4636. Status = SlInitIniFile( NULL,
  4637. FloppyId,
  4638. FileName,
  4639. &ASRPNPSifHandle,
  4640. &BlLoaderBlock->SetupLoaderBlock->ASRPnPSifFile,
  4641. &BlLoaderBlock->SetupLoaderBlock->ASRPnPSifFileLength,
  4642. &c );
  4643. ArcClose(FloppyId);
  4644. }
  4645. }
  4646. //
  4647. // See if we successfully loaded the file off the
  4648. // floppy.
  4649. //
  4650. SlWriteStatusText(TEXT(""));
  4651. if( (Status != ESUCCESS) ||
  4652. (BlLoaderBlock->SetupLoaderBlock->ASRPnPSifFile == NULL) ) {
  4653. //
  4654. // Missed. Inform the user and we'll try again.
  4655. //
  4656. SlMessageBox(SL_MSG_WARNING_ASR);
  4657. } else if (BlLoaderBlock->SetupLoaderBlock->ASRPnPSifFileLength == 0) {
  4658. //
  4659. // Invalid ASR file: inform user and we'll try again
  4660. //
  4661. StatusText = BlFindMessage(SL_MSG_INVALID_ASRPNP_FILE);
  4662. //
  4663. // First display the ASR insert floppy message
  4664. //
  4665. SlDisplayMessageBox(SL_MSG_WARNING_ASR);
  4666. //
  4667. // Populate status area with the error
  4668. //
  4669. if( StatusText != NULL ) {
  4670. SlWriteStatusText(StatusText);
  4671. }
  4672. //
  4673. // Now wait for user to hit a key
  4674. //
  4675. SlFlushConsoleBuffer();
  4676. SlGetChar();
  4677. //
  4678. // Clear status just in case ...
  4679. //
  4680. if( StatusText != NULL ) {
  4681. SlWriteStatusText(TEXT(""));
  4682. }
  4683. } else {
  4684. Done = TRUE;
  4685. }
  4686. }
  4687. } while( PromptASR && !Done );
  4688. }
  4689. SCSI_INSERT_STATUS
  4690. SlInsertScsiDevice(
  4691. IN ULONG Ordinal,
  4692. OUT PDETECTED_DEVICE *pScsiDevice
  4693. )
  4694. /*++
  4695. Routine Description:
  4696. This routine
  4697. Arguments:
  4698. Ordinal - Supplies the 0-based ordinal of the Scsi device
  4699. to insert (based on order listed in [Scsi.Load]
  4700. section of txtsetup.sif). If the Scsi device is a third party
  4701. driver, then Ordinal is -1.
  4702. pScsiDevice - Receives a pointer to the inserted DETECTED_DEVICE structure,
  4703. the existing structure, or NULL.
  4704. Return Value:
  4705. ScsiInsertError - Not enough memory to allocate a new DETECTED_DEVICE.
  4706. ScsiInsertNewEntry - A new entry was inserted into the DETECTED_DEVICE list.
  4707. ScsiInsertExisting - An existing entry was found that matched the specified
  4708. ordinal, so we returned this entry.
  4709. --*/
  4710. {
  4711. PDETECTED_DEVICE prev, cur;
  4712. if(Ordinal == (ULONG)-1) {
  4713. //
  4714. // This is a third-party driver, so find the end of the linked list
  4715. // (we want to preserve the order in which the user specifies the drivers).
  4716. //
  4717. for(prev=BlLoaderBlock->SetupLoaderBlock->ScsiDevices, cur = NULL;
  4718. prev && prev->Next;
  4719. prev=prev->Next);
  4720. } else {
  4721. //
  4722. // Find the insertion point in the linked list for this driver,
  4723. // based on its ordinal. (Note that we will insert all supported drivers
  4724. // before any third-party ones, since (ULONG)-1 = maximum unsigned long value)
  4725. //
  4726. for(prev = NULL, cur = BlLoaderBlock->SetupLoaderBlock->ScsiDevices;
  4727. cur && (Ordinal > cur->Ordinal);
  4728. prev = cur, cur = cur->Next);
  4729. }
  4730. if(cur && (cur->Ordinal == Ordinal)) {
  4731. //
  4732. // We found an existing entry for this driver
  4733. //
  4734. *pScsiDevice = cur;
  4735. return ScsiInsertExisting;
  4736. }
  4737. if(!(*pScsiDevice = BlAllocateHeap(sizeof(DETECTED_DEVICE)))) {
  4738. return ScsiInsertError;
  4739. }
  4740. (*pScsiDevice)->Next = cur;
  4741. if(prev) {
  4742. prev->Next = *pScsiDevice;
  4743. } else {
  4744. BlLoaderBlock->SetupLoaderBlock->ScsiDevices = *pScsiDevice;
  4745. }
  4746. (*pScsiDevice)->Ordinal = Ordinal;
  4747. return ScsiInsertNewEntry;
  4748. }
  4749. ARC_STATUS
  4750. SlLoadPnpDriversSection(
  4751. IN PVOID Inf,
  4752. IN PCHAR SectionName,
  4753. IN OUT PDETECTED_DEVICE* DetectedDeviceList OPTIONAL
  4754. )
  4755. /*++
  4756. Routine Description:
  4757. Enumerates all pnp drivers listed in [<section name>.Load], loads them, and puts
  4758. a list with all the the drivers loaded, in the setup loader block.
  4759. Arguments:
  4760. Inf - Supplies a handle to the INF file.
  4761. SectionName - Name of the section in the inf file that contains the list of
  4762. drivers to be loaded.
  4763. DetectedDeviceList - Address of the variable in Setup loader block that will contain
  4764. the list of drivers loaded. If this argument is NULL, then the list of
  4765. loaded devices will not be created.
  4766. Return Value:
  4767. ESUCCESS if all drivers were loaded successfully/no errors encountered
  4768. --*/
  4769. {
  4770. ULONG i;
  4771. CHAR LoadSectionName[100];
  4772. PCHAR DriverFilename;
  4773. PCHAR DriverId;
  4774. PTCHAR DriverDescription;
  4775. PCHAR NoLoadSpec;
  4776. PCHAR p;
  4777. ARC_STATUS Status;
  4778. PDETECTED_DEVICE TempDevice;
  4779. sprintf(LoadSectionName, "%s.Load",SectionName);
  4780. i=0;
  4781. do {
  4782. DriverFilename = SlGetSectionLineIndex(Inf,LoadSectionName,i,SIF_FILENAME_INDEX);
  4783. NoLoadSpec = SlGetSectionLineIndex(Inf,LoadSectionName,i,2);
  4784. if(DriverFilename && ((NoLoadSpec == NULL) || _stricmp(NoLoadSpec,"noload"))) {
  4785. DriverId = SlGetKeyName(Inf,LoadSectionName,i);
  4786. #ifdef UNICODE
  4787. DriverDescription = SlGetIniValueW(
  4788. Inf,
  4789. SectionName,
  4790. DriverId,
  4791. SlCopyStringAW(DriverId));
  4792. #else
  4793. DriverDescription = SlGetIniValue(
  4794. Inf,
  4795. SectionName,
  4796. DriverId,
  4797. DriverId);
  4798. #endif
  4799. Status = SlLoadDriver(DriverDescription,
  4800. DriverFilename,
  4801. 0,
  4802. TRUE,
  4803. FALSE
  4804. );
  4805. // if((Status == ENOENT) && IgnoreMissingFiles) {
  4806. // Status = ESUCCESS;
  4807. // }
  4808. if (Status == ESUCCESS) {
  4809. if( DetectedDeviceList != NULL ) {
  4810. //
  4811. // if the enumerator loaded, then record DETECTED_DEVICE info
  4812. //
  4813. TempDevice = BlAllocateHeap(sizeof(DETECTED_DEVICE));
  4814. if(!TempDevice) {
  4815. SlNoMemoryError();
  4816. return ENOMEM;
  4817. }
  4818. TempDevice->IdString = SlCopyStringA(DriverId);
  4819. TempDevice->Description = DriverDescription;
  4820. TempDevice->ThirdPartyOptionSelected = FALSE;
  4821. TempDevice->MigratedDriver = FALSE;
  4822. TempDevice->FileTypeBits = 0;
  4823. TempDevice->BaseDllName = SlCopyStringA(DriverFilename);
  4824. TempDevice->Next = *DetectedDeviceList;
  4825. *DetectedDeviceList = TempDevice;
  4826. }
  4827. } else {
  4828. SlFriendlyError(
  4829. Status,
  4830. DriverFilename,
  4831. __LINE__,
  4832. __FILE__
  4833. );
  4834. return(Status);
  4835. }
  4836. }
  4837. i++;
  4838. } while ( DriverFilename != NULL );
  4839. return(ESUCCESS);
  4840. }
  4841. ARC_STATUS
  4842. SlDetectMigratedScsiDrivers(
  4843. IN PVOID Inf
  4844. )
  4845. /*++
  4846. Routine Description:
  4847. Create an entry in the ScsiDevice list for each migrated SCSI driver.
  4848. Arguments:
  4849. Inf - Supplies a handle to the INF file.
  4850. Return Value:
  4851. ESUCCESS if all drivers were added to the ScsiDevice list.
  4852. --*/
  4853. {
  4854. ULONG i;
  4855. CHAR LoadSectionName[100];
  4856. PCHAR DriverFilename;
  4857. PCHAR DriverId;
  4858. PTCHAR DriverDescription;
  4859. ARC_STATUS Status;
  4860. PDETECTED_DEVICE ScsiDevice;
  4861. SCSI_INSERT_STATUS sis;
  4862. i=0;
  4863. do {
  4864. DriverId = SlGetSectionLineIndex(Inf,"Devices",i,0);
  4865. if( DriverId ) {
  4866. sprintf(LoadSectionName, "Files.%s", DriverId);
  4867. DriverFilename = SlGetSectionLineIndex(Inf,LoadSectionName,0,0);
  4868. if(DriverFilename) {
  4869. //
  4870. // Remove inbox drivers with the same name as a winnt32-migrated OEM driver (if any)
  4871. //
  4872. SlRemoveInboxDriver (DriverFilename);
  4873. //
  4874. // Create a new detected device entry.
  4875. //
  4876. if((sis = SlInsertScsiDevice(-1, &ScsiDevice)) == ScsiInsertError) {
  4877. return(ENOMEM);
  4878. }
  4879. if(sis == ScsiInsertExisting) {
  4880. #if DBG
  4881. //
  4882. // Sanity check to make sure we're talking about the same driver
  4883. //
  4884. if(_stricmp(ScsiDevice->BaseDllName, DriverFilename)) {
  4885. SlError(400);
  4886. return EINVAL;
  4887. }
  4888. #endif
  4889. } else {
  4890. DriverDescription = SlCopyString(BlFindMessage(SL_TEXT_SCSI_UNNAMED));
  4891. ScsiDevice->IdString = DriverId;
  4892. ScsiDevice->Description = DriverDescription;
  4893. ScsiDevice->ThirdPartyOptionSelected = FALSE;
  4894. ScsiDevice->MigratedDriver = TRUE;
  4895. ScsiDevice->FileTypeBits = 0;
  4896. ScsiDevice->Files = NULL;
  4897. ScsiDevice->BaseDllName = DriverFilename;
  4898. }
  4899. }
  4900. }
  4901. i++;
  4902. } while ( DriverId != NULL );
  4903. return(ESUCCESS);
  4904. }
  4905. ARC_STATUS
  4906. SlGetMigratedHardwareIds(
  4907. IN PSETUP_LOADER_BLOCK SetupBlock,
  4908. IN PVOID Inf
  4909. )
  4910. /*++
  4911. Routine Description:
  4912. Add the hardware ids for the migrated scsi drivers, to the hardware id list.
  4913. Arguments:
  4914. SetupBlock - Supplies a pointer to the Setup loader block
  4915. Return Value:
  4916. ESUCCESS if all hardware ids were added to the hardware id list
  4917. --*/
  4918. {
  4919. PCHAR DriverId;
  4920. ULONG i, j;
  4921. PPNP_HARDWARE_ID TempHardwareId;
  4922. PCHAR p;
  4923. for( j = 0;
  4924. (DriverId = SlGetSectionLineIndex(Inf,"Devices",j,0)) != NULL;
  4925. j++ ) {
  4926. CHAR SectionName[100];
  4927. sprintf(SectionName, "HardwareIds.%s", DriverId);
  4928. for( i = 0;
  4929. ((p = SlGetKeyName( Inf, SectionName, i )) != NULL);
  4930. i++ ) {
  4931. TempHardwareId = BlAllocateHeap(sizeof(PNP_HARDWARE_ID));
  4932. if (TempHardwareId==NULL) {
  4933. SlNoMemoryError();
  4934. return ENOMEM;
  4935. }
  4936. TempHardwareId->Id = p;
  4937. p = SlGetSectionKeyIndex( Inf,
  4938. SectionName,
  4939. TempHardwareId->Id,
  4940. 0 );
  4941. TempHardwareId->DriverName = p;
  4942. p = SlGetSectionKeyIndex( Inf,
  4943. SectionName,
  4944. TempHardwareId->Id,
  4945. 1 );
  4946. TempHardwareId->ClassGuid = p;
  4947. TempHardwareId->Next = SetupBlock->HardwareIdDatabase;
  4948. SetupBlock->HardwareIdDatabase = TempHardwareId;
  4949. }
  4950. }
  4951. return( ESUCCESS );
  4952. }
  4953. BOOLEAN
  4954. SlIsCdBootUpgrade(
  4955. IN PCHAR InstallDirectory,
  4956. IN PCHAR SetupFileName,
  4957. IN ULONG MaxDisksToScan,
  4958. IN ULONG MaxPartitionsPerDisk,
  4959. OUT PCHAR NewSetupDevice
  4960. )
  4961. /*++
  4962. Routine Description:
  4963. Finds out by looking into the hard disk if the specified
  4964. directory exists and if the the user was indeed
  4965. trying to uprgade
  4966. Arguments:
  4967. InstallDirectory - Directory used on the hard disk
  4968. for installation
  4969. SetupFileName - Inf file name which has the key which
  4970. indicates if upgrade was in progress or
  4971. not
  4972. MaxDisksToScan - Maximum number of disks to scan
  4973. MaxPartitionsPerDisk - Maximum partitions per disk to look into
  4974. for the install directory.
  4975. NewSetupDevice - Place holder for arc name for the device
  4976. if user wants to switch to harddisk boot.
  4977. Return Value:
  4978. TRUE if upgrade was in progress and user selected to continue on
  4979. otherwise FALSE.
  4980. --*/
  4981. {
  4982. BOOLEAN Result = FALSE;
  4983. CHAR DeviceName[128];
  4984. ARC_STATUS Status;
  4985. ULONG CurrentPartition;
  4986. ULONG CurrentDisk;
  4987. //
  4988. // Go through each disk
  4989. //
  4990. for (CurrentDisk = 0;
  4991. (!Result && (CurrentDisk < MaxDisksToScan));
  4992. CurrentDisk++) {
  4993. Status = ESUCCESS;
  4994. //
  4995. // Go through each valid partition
  4996. // for the current disk
  4997. //
  4998. for (CurrentPartition = 1;
  4999. (!Result && (Status == ESUCCESS));
  5000. CurrentPartition++) {
  5001. ULONG DiskId;
  5002. sprintf(DeviceName,
  5003. "multi(0)disk(0)rdisk(%d)partition(%d)",
  5004. CurrentDisk,
  5005. CurrentPartition);
  5006. Status = ArcOpen(DeviceName, ArcOpenReadOnly, &DiskId);
  5007. if (Status == ESUCCESS) {
  5008. CHAR FullName[128];
  5009. PVOID SifHandle = NULL;
  5010. ULONG ErrorLine = 0;
  5011. ARC_STATUS FileStatus;
  5012. strcpy(FullName, InstallDirectory);
  5013. strcat(FullName, "\\");
  5014. strcat(FullName, SetupFileName);
  5015. FileStatus = SlInitIniFile(NULL,
  5016. DiskId,
  5017. FullName,
  5018. &SifHandle,
  5019. NULL,
  5020. NULL,
  5021. &ErrorLine);
  5022. if ((FileStatus == ESUCCESS) && SifHandle) {
  5023. Result = SlIsUpgrade(SifHandle);
  5024. }
  5025. ArcClose(DiskId);
  5026. } else {
  5027. //
  5028. // Ignore the error till the maximum number of
  5029. // partitions are searched for
  5030. //
  5031. if (CurrentPartition < MaxPartitionsPerDisk) {
  5032. Status = ESUCCESS;
  5033. }
  5034. }
  5035. }
  5036. }
  5037. if (Result) {
  5038. ULONG UserInput;
  5039. BOOLEAN OldStatus = SlGetStatusBarStatus();
  5040. //
  5041. // Reset the result based on user input
  5042. //
  5043. Result = FALSE;
  5044. SlEnableStatusBar(FALSE);
  5045. SlClearClientArea();
  5046. SlDisplayMessageBox(SL_UPGRADE_IN_PROGRESS);
  5047. do {
  5048. SlFlushConsoleBuffer();
  5049. UserInput = SlGetChar();
  5050. }
  5051. while ((UserInput != ASCI_CR) &&
  5052. (UserInput != SL_KEY_F3) &&
  5053. (UserInput != SL_KEY_F10));
  5054. SlClearClientArea();
  5055. if (UserInput == SL_KEY_F3) {
  5056. ArcRestart();
  5057. } else if (UserInput == ASCI_CR) {
  5058. Result = TRUE;
  5059. strcpy(NewSetupDevice, DeviceName);
  5060. }
  5061. SlEnableStatusBar(OldStatus);
  5062. }
  5063. return Result;
  5064. }
  5065. BOOLEAN
  5066. SlIsUpgrade(
  5067. IN PVOID SifHandle
  5068. )
  5069. /*++
  5070. Routine Description:
  5071. Finds out by looking into the SIF file if upgrade is
  5072. in progress or not
  5073. Arguments:
  5074. InfHandle - Handle to winnt.sif file
  5075. Return Value:
  5076. TRUE if upgrade is in progress otherwise FALSE
  5077. --*/
  5078. {
  5079. BOOLEAN Result = FALSE;
  5080. if (SifHandle) {
  5081. PCHAR NtUpgrade = SlGetSectionKeyIndex(SifHandle,
  5082. WINNT_DATA_A,
  5083. WINNT_D_NTUPGRADE_A,
  5084. 0);
  5085. if (NtUpgrade) {
  5086. Result = (_stricmp(NtUpgrade, WINNT_A_YES_A) == 0);
  5087. }
  5088. if (!Result) {
  5089. PCHAR Win9xUpgrade = SlGetSectionKeyIndex(SifHandle,
  5090. WINNT_DATA_A,
  5091. WINNT_D_WIN95UPGRADE_A,
  5092. 0);
  5093. if (Win9xUpgrade) {
  5094. Result = (_stricmp(Win9xUpgrade, WINNT_A_YES_A) == 0);
  5095. }
  5096. }
  5097. }
  5098. return Result;
  5099. }
  5100. BOOLEAN
  5101. SlpIsDynamicUpdate(
  5102. IN PVOID InfHandle,
  5103. OUT PCSTR *DynamicUpdateRootDir
  5104. )
  5105. /*++
  5106. Routine Description:
  5107. Finds out whether there are any dynamic update boot drivers
  5108. to process or not.
  5109. Arguments:
  5110. InfHandle - Handle to winnt.sif file
  5111. DynamicUpdateRootDir - Receives the root directory under which all
  5112. the dynamic update boot driver packages are present.
  5113. Return Value:
  5114. TRUE, if there are dynamic update boot drivers otherwise
  5115. FALSE
  5116. --*/
  5117. {
  5118. BOOLEAN Result = FALSE;
  5119. if (InfHandle) {
  5120. PCHAR DynUpdateKey = SlGetSectionKeyIndex(InfHandle,
  5121. WINNT_SETUPPARAMS_A,
  5122. WINNT_SP_DYNUPDTBOOTDRIVERPRESENT_A,
  5123. 0);
  5124. PCHAR DynUpdateRoot = SlGetSectionKeyIndex(InfHandle,
  5125. WINNT_SETUPPARAMS_A,
  5126. WINNT_SP_DYNUPDTBOOTDRIVERROOT_A,
  5127. 0);
  5128. //
  5129. // DynamicUpdateBootDriverPresent and DynamicUpateBootDriverRoot
  5130. // should have valid values
  5131. //
  5132. Result = (DynUpdateKey && DynUpdateRoot &&
  5133. !_stricmp(DynUpdateKey, "yes"));
  5134. if (Result && DynamicUpdateRootDir) {
  5135. *DynamicUpdateRootDir = SlCopyStringA(DynUpdateRoot);
  5136. }
  5137. }
  5138. return Result;
  5139. }
  5140. UCHAR
  5141. SlGetDefaultAttr(
  5142. VOID
  5143. )
  5144. {
  5145. return (UCHAR)((UseRegularBackground) ? (ATT_FG_WHITE | ATT_BG_BLACK) : (ATT_FG_WHITE | ATT_BG_BLUE));
  5146. }
  5147. UCHAR
  5148. SlGetDefaultInvAttr(
  5149. VOID
  5150. )
  5151. {
  5152. return (UCHAR)((UseRegularBackground) ? (ATT_FG_BLACK | ATT_BG_WHITE) : (ATT_FG_BLUE | ATT_BG_WHITE));
  5153. }
  5154. BOOLEAN
  5155. SlRemoveOsLoadOption(
  5156. IN OUT PSTR LoadOptions,
  5157. IN PCSTR OptionToRemove
  5158. )
  5159. /*++
  5160. Routine Description:
  5161. Removes the first occurance of the requested option from
  5162. the load options.
  5163. Arguments:
  5164. LoadOptions - Pointer to the OS load options.
  5165. OptionToRemove - The option that needs to be removed from the
  5166. given OS load options. NOTE : This needs to start with "/"
  5167. character.
  5168. Return Value:
  5169. TRUE, if the requested option was removed otherwise FALSE.
  5170. --*/
  5171. {
  5172. BOOLEAN Result = FALSE;
  5173. //
  5174. // verify arguments
  5175. //
  5176. if (LoadOptions && OptionToRemove && (OptionToRemove[0] == '/')) {
  5177. CHAR Option[256];
  5178. PSTR CurrentOption = strchr(LoadOptions, '/');
  5179. while (CurrentOption && (*CurrentOption)) {
  5180. //
  5181. // get hold of the next load
  5182. //
  5183. PSTR EndPtr = strchr(CurrentOption + 1, '/');
  5184. ULONG TokenLength;
  5185. if (!EndPtr) {
  5186. EndPtr = CurrentOption + strlen(CurrentOption);
  5187. }
  5188. //
  5189. // replicate the token into local buffer
  5190. //
  5191. TokenLength = (ULONG)(ULONG_PTR)(EndPtr - CurrentOption);
  5192. strncpy(Option, CurrentOption, TokenLength);
  5193. Option[TokenLength] = '\0';
  5194. //
  5195. // remove trailing whitespaces from the token
  5196. //
  5197. TokenLength--;
  5198. while (TokenLength && (Option[TokenLength] == ' ')) {
  5199. Option[TokenLength] = '\0';
  5200. TokenLength--;
  5201. }
  5202. //
  5203. // Is this the token we are looking for ?
  5204. //
  5205. if (_stricmp(Option, OptionToRemove) == 0) {
  5206. //
  5207. // remove the token from orginal string
  5208. //
  5209. strcpy(CurrentOption, EndPtr);
  5210. Result = TRUE;
  5211. break;
  5212. }
  5213. CurrentOption = EndPtr;
  5214. }
  5215. }
  5216. return Result;
  5217. }
  5218. #ifdef _IA64_
  5219. BOOLEAN
  5220. SlIsWinPEAutoBoot(
  5221. IN PSTR LoaderDeviceName
  5222. )
  5223. /*++
  5224. Routine Description:
  5225. Determines if this is an automated WinPE boot.
  5226. NOTE : Automated WinPE boot is determined by the presence
  5227. of the $WINPE$.$$$ file at the same location where
  5228. setupldr.efi was started from.
  5229. Arguments:
  5230. LoaderDeviceName : Arcname of the device where setupldr
  5231. was started from.
  5232. Return Value:
  5233. TRUE if this is WinPE auto boot, otherwise FALSE.
  5234. --*/
  5235. {
  5236. BOOLEAN Result = FALSE;
  5237. if (LoaderDeviceName) {
  5238. ULONG DiskId;
  5239. ARC_STATUS Status;
  5240. //
  5241. // open the partition
  5242. //
  5243. Status = ArcOpen(LoaderDeviceName, ArcOpenReadOnly, &DiskId);
  5244. //
  5245. // try ATAPI device name in case SCSI device name fails
  5246. //
  5247. if (ESUCCESS != Status) {
  5248. CHAR Buffer[128];
  5249. strcpy(Buffer, LoaderDeviceName);
  5250. _strlwr(Buffer);
  5251. if (NULL != strstr(Buffer, "scsi")) {
  5252. CHAR AtapiDeviceName[128];
  5253. PCSTR AdapterStart;
  5254. PSTR AdapterEnd;
  5255. AdapterStart = strstr(Buffer, "scsi(");
  5256. if (AdapterStart) {
  5257. AdapterStart += strlen("scsi(");
  5258. AdapterEnd = strchr(AdapterStart, ')');
  5259. if (AdapterEnd) {
  5260. *AdapterEnd = '\0';
  5261. sprintf(AtapiDeviceName,
  5262. "multi(%s)%s",
  5263. AdapterStart,
  5264. AdapterEnd + 1);
  5265. Status = ArcOpen(AtapiDeviceName,
  5266. ArcOpenReadOnly,
  5267. &DiskId);
  5268. }
  5269. }
  5270. }
  5271. }
  5272. if (Status == ESUCCESS) {
  5273. CHAR FileName[128];
  5274. ARC_STATUS FileStatus;
  5275. ULONG FileId;
  5276. //
  5277. // check for the existence of \$WINPE$.$$$
  5278. //
  5279. strcpy(FileName, "\\");
  5280. strcat(FileName, WINPE_AUTOBOOT_FILENAME);
  5281. FileStatus = BlOpen(DiskId, FileName, ArcOpenReadOnly, &FileId);
  5282. if (FileStatus == ESUCCESS) {
  5283. BlClose(FileId);
  5284. Result = TRUE;
  5285. }
  5286. ArcClose(DiskId);
  5287. }
  5288. }
  5289. return Result;
  5290. }
  5291. ARC_STATUS
  5292. SlGetWinPEStartupParams(
  5293. IN OUT PSTR StartupDeviceName,
  5294. IN OUT PSTR StartupDirectory
  5295. )
  5296. /*++
  5297. Routine Description:
  5298. Searches for the WinPE installation on the available
  5299. partitions on the first 4 disks.
  5300. Arguments:
  5301. StartupDeviceName - place holder for receiving device name
  5302. where WinPE installation was found.
  5303. StartupDirectory - place holder for receiving WinPE installation
  5304. directory.
  5305. Return Value:
  5306. Appropriate ARC_STATUS error code.
  5307. --*/
  5308. {
  5309. ARC_STATUS Status = EINVAL;
  5310. //
  5311. // validate arguments
  5312. //
  5313. if (StartupDeviceName && StartupDirectory) {
  5314. BOOLEAN Found = FALSE;
  5315. CHAR DeviceName[128];
  5316. ULONG CurrentPartition;
  5317. ULONG CurrentDisk;
  5318. //
  5319. // Go through each disk (at the max 4)
  5320. //
  5321. for (CurrentDisk = 0;
  5322. (!Found && (CurrentDisk < 4));
  5323. CurrentDisk++) {
  5324. //
  5325. // Go through each valid partition
  5326. // for the current disk
  5327. //
  5328. for (CurrentPartition = 1, Status = ESUCCESS;
  5329. (!Found && (Status == ESUCCESS));
  5330. CurrentPartition++) {
  5331. ULONG DiskId;
  5332. sprintf(DeviceName,
  5333. "multi(0)disk(0)rdisk(%d)partition(%d)",
  5334. CurrentDisk,
  5335. CurrentPartition);
  5336. //
  5337. // open the disk
  5338. //
  5339. Status = ArcOpen(DeviceName, ArcOpenReadOnly, &DiskId);
  5340. if (Status == ESUCCESS) {
  5341. CHAR FullName[128];
  5342. ARC_STATUS FileStatus;
  5343. ULONG DirId;
  5344. //
  5345. // check for the existence of \\winpe\\ia64\\system32 directory
  5346. //
  5347. strcpy(FullName, "\\WINPE\\ia64\\system32");
  5348. FileStatus = BlOpen(DiskId, FullName, ArcOpenDirectory, &DirId);
  5349. if (FileStatus == ESUCCESS) {
  5350. BlClose(DirId);
  5351. Found = TRUE;
  5352. }
  5353. ArcClose(DiskId);
  5354. }
  5355. }
  5356. }
  5357. //
  5358. // update return arguments
  5359. //
  5360. if (Found && (ESUCCESS == Status)) {
  5361. strcpy(StartupDeviceName, DeviceName);
  5362. strcpy(StartupDirectory, "\\WINPE\\ia64\\");
  5363. }
  5364. if (!Found) {
  5365. Status = EBADF;
  5366. }
  5367. }
  5368. return Status;
  5369. }
  5370. #endif // _IA64_
  5371. #ifdef _X86_
  5372. ARC_STATUS
  5373. SlLoadBootFontFile(
  5374. IN PSETUP_LOADER_BLOCK SetupLoaderBlock,
  5375. IN ULONG DiskId,
  5376. IN ULONG BootFontImageLength
  5377. )
  5378. /*++
  5379. Routine Description:
  5380. Loads the bootfont.bin into memory and initializes
  5381. relevant fields in setup loader block.
  5382. Arguments:
  5383. SetupLoaderBlock - pointer to setup loader block.
  5384. DiskId - Disk ID where bootfont.bin resides on the root
  5385. BootFontImageLength - The length of the bootfont.bin file.
  5386. Return Value:
  5387. Appropriate ARC_STATUS error code.
  5388. --*/
  5389. {
  5390. ARC_STATUS Status = EINVAL;
  5391. //
  5392. // verify arguments
  5393. //
  5394. if (SetupLoaderBlock && BootFontImageLength) {
  5395. ULONG FileId;
  5396. PVOID Image = NULL;
  5397. //
  5398. // open the bootfont.bin file
  5399. //
  5400. if (BlBootingFromNet
  5401. #if defined(REMOTE_BOOT)
  5402. && NetworkBootRom
  5403. #endif // defined(REMOTE_BOOT)
  5404. ) {
  5405. CHAR Buffer[129];
  5406. strcpy(Buffer, NetBootPath);
  5407. strcat(Buffer, "BOOTFONT.BIN");
  5408. Status = BlOpen(DiskId,
  5409. Buffer,
  5410. ArcOpenReadOnly,
  5411. &FileId);
  5412. } else {
  5413. Status = BlOpen(DiskId,
  5414. "\\BOOTFONT.BIN",
  5415. ArcOpenReadOnly,
  5416. &FileId);
  5417. }
  5418. //
  5419. // allocate memory and read the contents of the file
  5420. // into memory
  5421. //
  5422. if (ESUCCESS == Status) {
  5423. Image = BlAllocateHeap(BootFontImageLength);
  5424. if (Image) {
  5425. ULONG BytesRead = 0;
  5426. Status = BlRead(FileId, Image, BootFontImageLength, &BytesRead);
  5427. if ((ESUCCESS == Status) && (BytesRead != BootFontImageLength)) {
  5428. Status = EIO;
  5429. }
  5430. } else {
  5431. Status = ENOMEM;
  5432. }
  5433. BlClose(FileId);
  5434. }
  5435. if (Image && (ESUCCESS == Status)) {
  5436. SetupLoaderBlock->BootFontFile = Image;
  5437. SetupLoaderBlock->BootFontFileLength = BootFontImageLength;
  5438. }
  5439. }
  5440. return Status;
  5441. }
  5442. #endif