Windows NT 4.0 source code leak
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.

2526 lines
67 KiB

4 years ago
  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. #define BlDiagLoadMessage(x,y,z)
  19. #define VGA_DRIVER_FILENAME "vga.sys"
  20. #define KERNEL_IMAGE_FILENAME "ntkrnlmp.exe"
  21. //
  22. // Global string constants.
  23. //
  24. PCHAR FilesSectionName = "SourceDisksFiles";
  25. PCHAR MediaSectionName = "SourceDisksNames";
  26. #if defined(_ALPHA_)
  27. PCHAR PlatformExtension = ".alpha";
  28. #elif defined(_MIPS_)
  29. PCHAR PlatformExtension = ".mips";
  30. #elif defined(_PPC_)
  31. PCHAR PlatformExtension = ".ppc";
  32. #elif defined(_X86_)
  33. PCHAR PlatformExtension = ".x86";
  34. #endif
  35. //
  36. // Global data
  37. //
  38. ULONG BlDcacheFillSize = 32;
  39. //
  40. // Global setupldr control values
  41. //
  42. MEDIA_TYPE BootMedia;
  43. MEDIA_TYPE InstallMedia;
  44. PCHAR BootDevice;
  45. ULONG BootDeviceId;
  46. BOOLEAN BootDeviceIdValid = FALSE;
  47. PCHAR BootPath;
  48. ULONG BootDriveNumber;
  49. ULONG InstallDriveNumber;
  50. PCHAR HalName;
  51. PCHAR HalDescription;
  52. PCHAR AnsiCpName;
  53. PCHAR OemHalFontName;
  54. UNICODE_STRING AnsiCodepage;
  55. UNICODE_STRING OemCodepage;
  56. UNICODE_STRING UnicodeCaseTable;
  57. UNICODE_STRING OemHalFont;
  58. BOOLEAN LoadScsiMiniports;
  59. BOOLEAN LoadDiskClass;
  60. BOOLEAN LoadCdfs;
  61. BOOLEAN FixedBootMedia = FALSE;
  62. PVOID InfFile;
  63. PVOID WinntSifHandle;
  64. BOOLEAN IgnoreMissingFiles;
  65. //
  66. // Pre-install stuff
  67. //
  68. PCHAR OemTag = "OEM";
  69. BOOLEAN PreInstall = FALSE;
  70. PCHAR ComputerType = NULL;
  71. BOOLEAN OemHal = FALSE;
  72. PPREINSTALL_DRIVER_INFO PreinstallDriverList = NULL;
  73. #if defined(ELTORITO)
  74. extern BOOLEAN ElToritoCDBoot;
  75. #endif
  76. //
  77. // Define transfer entry of loaded image.
  78. //
  79. typedef
  80. VOID
  81. (*PTRANSFER_ROUTINE) (
  82. PLOADER_PARAMETER_BLOCK LoaderBlock
  83. );
  84. //
  85. // Local function prototypes
  86. //
  87. VOID
  88. SlGetSetupValues(
  89. IN PSETUP_LOADER_BLOCK SetupBlock
  90. );
  91. ARC_STATUS
  92. SlLoadDriver(
  93. IN PCHAR DeviceName,
  94. IN PCHAR DriverName,
  95. IN ULONG DriverFlags,
  96. IN BOOLEAN InsertIntoDriverList
  97. );
  98. ARC_STATUS
  99. SlLoadOemDriver(
  100. IN PCHAR ExportDriver, OPTIONAL
  101. IN PCHAR DriverName,
  102. IN PVOID BaseAddress,
  103. IN PCHAR LoadMessage
  104. );
  105. PBOOT_DRIVER_LIST_ENTRY
  106. SlpCreateDriverEntry(
  107. IN PCHAR DriverName
  108. );
  109. ARC_STATUS
  110. SlLoadSection(
  111. IN PVOID Inf,
  112. IN PCHAR SectionName,
  113. IN BOOLEAN IsScsiSection
  114. );
  115. BOOLEAN
  116. SlpIsDiskVacant(
  117. IN PARC_DISK_SIGNATURE DiskSignature
  118. );
  119. ARC_STATUS
  120. SlpStampFTSignature(
  121. IN PARC_DISK_SIGNATURE DiskSignature
  122. );
  123. VOID
  124. SlpMarkDisks(
  125. VOID
  126. );
  127. VOID
  128. SlCheckOemKeypress(
  129. VOID
  130. );
  131. ARC_STATUS
  132. SlLoadBusExtender(
  133. IN PVOID Inf
  134. );
  135. ARC_STATUS
  136. SlInit(
  137. IN ULONG Argc,
  138. IN PCHAR Argv[],
  139. IN PCHAR Envp[]
  140. )
  141. /*++
  142. Routine Description:
  143. The main startup routine for the NT Setup Loader. This is the entrypoint
  144. called by the ARC firmware.
  145. If successful, this routine will never return, it will start NT directly.
  146. Arguments:
  147. Argc - Supplies the number of arguments that were provided on the
  148. command that invoked this program.
  149. Argv - Supplies a pointer to a vector of pointers to null terminated
  150. argument strings.
  151. Envp - Supplies a pointer to a vector of pointers to null terminated
  152. environment variables.
  153. Return Value:
  154. ARC_STATUS if unsuccessful.
  155. --*/
  156. {
  157. PCONFIGURATION_COMPONENT_DATA DataCache;
  158. ARC_STATUS Status;
  159. ULONG LinesPerBlock;
  160. ULONG CacheLineSize;
  161. CHAR SetupDevice[128];
  162. CHAR SetupDirectory[128];
  163. CHAR BadFileName[128];
  164. CHAR CanonicalName[128];
  165. CHAR HalDirectoryPath[256];
  166. CHAR KernelDirectoryPath[256];
  167. PCHAR p;
  168. ULONG ErrorLine=0;
  169. ULONG DontCare;
  170. PVOID SystemBase;
  171. PVOID HalBase;
  172. PVOID ScsiBase;
  173. PVOID VideoBase;
  174. PLDR_DATA_TABLE_ENTRY SystemDataTableEntry;
  175. PLDR_DATA_TABLE_ENTRY HalDataTableEntry;
  176. PTRANSFER_ROUTINE SystemEntry;
  177. PIMAGE_NT_HEADERS NtHeaders;
  178. PBOOT_DRIVER_LIST_ENTRY DriverEntry;
  179. PSETUP_LOADER_BLOCK SetupBlock;
  180. PDETECTED_DEVICE ScsiDevice;
  181. PCHAR VideoFileName;
  182. PCHAR VideoDescription;
  183. PCHAR OemScsiName;
  184. POEMSCSIINFO OemScsiInfo;
  185. PCHAR OemVideoName;
  186. BOOLEAN LoadedAVideoDriver = FALSE;
  187. //
  188. // Initialize the memory descriptor list, the OS loader heap, and the
  189. // OS loader parameter block.
  190. //
  191. Status = BlMemoryInitialize();
  192. if (Status != ESUCCESS) {
  193. BlDiagLoadMessage(LOAD_HW_MEM_CLASS,
  194. DIAG_BL_MEMORY_INIT,
  195. LOAD_HW_MEM_ACT);
  196. goto LoadFailed;
  197. }
  198. SetupBlock = BlAllocateHeap(sizeof(SETUP_LOADER_BLOCK));
  199. if (SetupBlock==NULL) {
  200. SlNoMemoryError();
  201. goto LoadFailed;
  202. }
  203. BlLoaderBlock->SetupLoaderBlock = SetupBlock;
  204. SetupBlock->ScsiDevices = NULL;
  205. SetupBlock->ScalarValues.SetupFromCdRom = FALSE;
  206. SetupBlock->ScalarValues.SetupOperation = SetupOperationSetup;
  207. SetupBlock->ScalarValues.LoadedScsi = 0;
  208. SetupBlock->ScalarValues.LoadedCdRomDrivers = 0;
  209. SetupBlock->ScalarValues.LoadedDiskDrivers = 0;
  210. SetupBlock->ScalarValues.LoadedFloppyDrivers = 0;
  211. //
  212. // Initialize the NT configuration tree.
  213. //
  214. BlLoaderBlock->ConfigurationRoot = NULL;
  215. Status = BlConfigurationInitialize(NULL, NULL);
  216. if (Status != ESUCCESS) {
  217. BlDiagLoadMessage(LOAD_HW_FW_CFG_CLASS,
  218. DIAG_BL_CONFIG_INIT,
  219. LOAD_HW_FW_CFG_ACT);
  220. goto LoadFailed;
  221. }
  222. //
  223. // Compute the data cache fill size. This value is used to align
  224. // I/O buffers in case the host system does not support coherent
  225. // caches.
  226. //
  227. // If a combined secondary cache is present, then use the fill size
  228. // for that cache. Otherwise, if a secondary data cache is present,
  229. // then use the fill size for that cache. Otherwise, if a primary
  230. // data cache is present, then use the fill size for that cache.
  231. // Otherwise, use the default fill size.
  232. //
  233. DataCache = KeFindConfigurationEntry(BlLoaderBlock->ConfigurationRoot,
  234. CacheClass,
  235. SecondaryCache,
  236. NULL);
  237. if (DataCache == NULL) {
  238. DataCache = KeFindConfigurationEntry(BlLoaderBlock->ConfigurationRoot,
  239. CacheClass,
  240. SecondaryDcache,
  241. NULL);
  242. if (DataCache == NULL) {
  243. DataCache = KeFindConfigurationEntry(BlLoaderBlock->ConfigurationRoot,
  244. CacheClass,
  245. PrimaryDcache,
  246. NULL);
  247. }
  248. }
  249. if (DataCache != NULL) {
  250. LinesPerBlock = DataCache->ComponentEntry.Key >> 24;
  251. CacheLineSize = 1 << ((DataCache->ComponentEntry.Key >> 16) & 0xff);
  252. BlDcacheFillSize = LinesPerBlock * CacheLineSize;
  253. }
  254. //
  255. // Initialize the OS loader I/O system.
  256. //
  257. Status = BlIoInitialize();
  258. if (Status != ESUCCESS) {
  259. BlDiagLoadMessage(LOAD_HW_DISK_CLASS,
  260. DIAG_BL_IO_INIT,
  261. LOAD_HW_DISK_ACT);
  262. goto LoadFailed;
  263. }
  264. SlPositionCursor(5,3);
  265. //
  266. // Initialize the message resources
  267. //
  268. Status = BlInitResources(Argv[0]);
  269. if (Status != ESUCCESS) {
  270. // if this fails, then we can't print out any messages,
  271. // so we just exit.
  272. return(Status);
  273. }
  274. //
  275. // Initialize the display and announce ourselves
  276. //
  277. SlInitDisplay();
  278. SlWriteHeaderText(SL_WELCOME_HEADER);
  279. SlClearClientArea();
  280. #if defined(_X86_) && !defined(ALLOW_386)
  281. //
  282. // Disallow installation on a 386
  283. //
  284. {
  285. extern BOOLEAN SlIs386(VOID);
  286. if(SlIs386()) {
  287. SlFatalError(SL_TEXT_REQUIRES_486);
  288. }
  289. }
  290. #endif
  291. //
  292. // If this is a winnt setup, then we want to behave as if
  293. // we were started from the location specified by the
  294. // OSLOADPARTITION and OSLOADFILENAME nv-ram variables.
  295. //
  296. p = BlGetArgumentValue(Argc,Argv,"osloadoptions");
  297. if(p && !_stricmp(p,"winnt32")) {
  298. p = BlGetArgumentValue(Argc,Argv,"osloadpartition");
  299. if(!p) {
  300. SlError(100);
  301. goto LoadFailed;
  302. }
  303. Status = BlGenerateDeviceNames(p,SetupDevice,NULL);
  304. if (Status != ESUCCESS) {
  305. SlError(110);
  306. goto LoadFailed;
  307. }
  308. p = BlGetArgumentValue(Argc,Argv,"osloadfilename");
  309. if(!p || !(*p)) {
  310. SlError(120);
  311. goto LoadFailed;
  312. }
  313. strcpy(SetupDirectory,p);
  314. //
  315. // Make sure directory is terminated with a \.
  316. //
  317. if(SetupDirectory[strlen(SetupDirectory)-1] != '\\') {
  318. strcat(SetupDirectory,"\\");
  319. }
  320. } else {
  321. //
  322. // extract device name from our startup path
  323. //
  324. p=strrchr(Argv[0],')');
  325. if (p==NULL) {
  326. SlError(0);
  327. goto LoadFailed;
  328. }
  329. strncpy(SetupDevice, Argv[0],p-Argv[0]+1);
  330. SetupDevice[p-Argv[0]+1] = '\0';
  331. Status = BlGenerateDeviceNames(SetupDevice,CanonicalName,NULL);
  332. if (Status != ESUCCESS) {
  333. SlFriendlyError(
  334. Status,
  335. SetupDevice,
  336. __LINE__,
  337. __FILE__
  338. );
  339. goto LoadFailed;
  340. }
  341. strcpy(SetupDevice,CanonicalName);
  342. //
  343. // extract directory from our startup path.
  344. //
  345. if(*(p+1) != '\\') {
  346. //
  347. // directory must begin at root
  348. //
  349. strcpy(SetupDirectory, "\\");
  350. } else {
  351. *SetupDirectory = '\0';
  352. }
  353. strcat(SetupDirectory, p+1);
  354. p=strrchr(SetupDirectory, '\\');
  355. *(p+1) = '\0';
  356. }
  357. #if defined(ELTORITO)
  358. if (ElToritoCDBoot) {
  359. //
  360. // Use the i386 directory for setup files when we boot from an El Torito CD
  361. //
  362. strcat(SetupDirectory, "i386\\");
  363. }
  364. #endif
  365. //
  366. // We need to check to see if the user pressed any keys to force OEM HAL,
  367. // OEM SCSI, or both. Do this before getting the settings in the sif file,
  368. // so that we won't try to detect the machine if OEM HAL is needed.
  369. //
  370. SlCheckOemKeypress();
  371. strcpy(KernelDirectoryPath, SetupDirectory);
  372. strcat(KernelDirectoryPath, "txtsetup.sif");
  373. BlLoaderBlock->SetupLoaderBlock->IniFile = NULL;
  374. Status = SlInitIniFile(SetupDevice,
  375. 0,
  376. KernelDirectoryPath,
  377. &InfFile,
  378. &ErrorLine);
  379. if (Status != ESUCCESS) {
  380. SlFatalError(SL_BAD_INF_FILE,"txtsetup.sif");
  381. goto LoadFailed;
  382. }
  383. SlGetSetupValues(SetupBlock);
  384. //
  385. // Now we know everything we should load, compute the ARC name to load
  386. // from and start loading things.
  387. //
  388. if (BootDevice==NULL) {
  389. //
  390. // No device was explicitly specified, so use whatever device
  391. // setupldr was started from.
  392. //
  393. BootDevice = SlCopyString(SetupDevice);
  394. }
  395. Status = ArcOpen(BootDevice, ArcOpenReadOnly, &BootDeviceId);
  396. if (Status != ESUCCESS) {
  397. SlFatalError(SL_IO_ERROR,BootDevice);
  398. goto LoadFailed;
  399. } else {
  400. BootDeviceIdValid = TRUE;
  401. }
  402. _strlwr(BootDevice);
  403. FixedBootMedia = (strstr(BootDevice,")rdisk(") != NULL);
  404. //
  405. // If we are booting from fixed media, we better load disk class drivers.
  406. //
  407. if(FixedBootMedia) {
  408. LoadDiskClass = TRUE;
  409. }
  410. if(!BlGetPathMnemonicKey(BootDevice,"disk",&DontCare)
  411. && !BlGetPathMnemonicKey(BootDevice,"fdisk",&BootDriveNumber))
  412. {
  413. //
  414. // boot was from floppy, canonicalize the ARC name.
  415. //
  416. BlLoaderBlock->ArcBootDeviceName = BlAllocateHeap(80);
  417. sprintf(BlLoaderBlock->ArcBootDeviceName, "multi(0)disk(0)fdisk(%d)",BootDriveNumber);
  418. } else {
  419. BlLoaderBlock->ArcBootDeviceName = BootDevice;
  420. }
  421. if (BootPath==NULL) {
  422. //
  423. // No explicit boot path given, default to the directory setupldr was started
  424. // from.
  425. //
  426. #ifdef _X86_
  427. //
  428. // Increadibly nauseating hack:
  429. //
  430. // If we are booting from hard drive on x86, we will assume this is
  431. // the 'floppyless' winnt/winnt32 scenario, in which case the actual
  432. // boot path is \$win_nt$.~bt.
  433. //
  434. // This lets us avoid having winnt and winnt32 attempt to modify
  435. // the BootPath value in the [SetupData] section of txtsetup.sif.
  436. //
  437. if(FixedBootMedia) {
  438. BootPath = SlCopyString("\\$WIN_NT$.~BT\\");
  439. } else
  440. #endif
  441. BootPath = SlCopyString(SetupDirectory);
  442. }
  443. BlLoaderBlock->NtBootPathName = BootPath;
  444. //
  445. // Attempt to load winnt.sif from the path where we are
  446. // loading setup files. Borrow the BadFileName buffer
  447. // for temporary use.
  448. //
  449. strcpy(BadFileName,BootPath);
  450. strcat(BadFileName,WINNT_SIF_FILE);
  451. Status = SlInitIniFile(NULL,BootDeviceId,BadFileName,&WinntSifHandle,&DontCare);
  452. if(Status == ESUCCESS) {
  453. //
  454. // Find out if this is a pre-install, by looking at OemPreinstall key
  455. // in [unattended] section of winnt.sif
  456. //
  457. p = SlGetSectionKeyIndex(WinntSifHandle,WINNT_UNATTENDED,WINNT_U_OEMPREINSTALL,0);
  458. if(p && !_stricmp(p,"yes")) {
  459. PreInstall = TRUE;
  460. }
  461. //
  462. // If this is a pre-install, find out which hal to load, by looking
  463. // at ComputerType key in [unattended] section of winnt.sif.
  464. //
  465. if( PreInstall ) {
  466. ComputerType = SlGetSectionKeyIndex(WinntSifHandle,WINNT_UNATTENDED,WINNT_U_COMPUTERTYPE,0);
  467. if(ComputerType) {
  468. //
  469. // If the hal to load is an OEM one, then set OemHal to TRUE
  470. //
  471. p = SlGetSectionKeyIndex(WinntSifHandle,WINNT_UNATTENDED,WINNT_U_COMPUTERTYPE,1);
  472. if(p && !_stricmp(p, OemTag)) {
  473. OemHal = TRUE;
  474. } else {
  475. OemHal = FALSE;
  476. }
  477. //
  478. // In the pre-install mode, don't let the user specify
  479. // an OEM hal, if one was specified in unattend.txt
  480. //
  481. PromptOemHal = FALSE;
  482. }
  483. //
  484. // Find out which SCSI drivers to load, by looking at
  485. // [MassStorageDrivers] in winnt.sif
  486. //
  487. if( SpSearchINFSection( WinntSifHandle, WINNT_OEMSCSIDRIVERS ) ) {
  488. ULONG i;
  489. PPREINSTALL_DRIVER_INFO TempDriverInfo;
  490. PreinstallDriverList = NULL;
  491. for( i = 0;
  492. ((p = SlGetKeyName( WinntSifHandle, WINNT_OEMSCSIDRIVERS, i )) != NULL);
  493. i++ ) {
  494. TempDriverInfo = BlAllocateHeap(sizeof(PREINSTALL_DRIVER_INFO));
  495. if (TempDriverInfo==NULL) {
  496. SlNoMemoryError();
  497. goto LoadFailed;
  498. }
  499. TempDriverInfo->DriverDescription = p;
  500. p = SlGetIniValue( WinntSifHandle,
  501. WINNT_OEMSCSIDRIVERS,
  502. TempDriverInfo->DriverDescription,
  503. NULL );
  504. TempDriverInfo->OemDriver = (p && !_stricmp(p, OemTag))? TRUE : FALSE;
  505. TempDriverInfo->Next = PreinstallDriverList;
  506. PreinstallDriverList = TempDriverInfo;
  507. }
  508. if( PreinstallDriverList != NULL ) {
  509. //
  510. // In the pre-install mode, don't let the user specify
  511. // an OEM scsi, if at least one was specified in unattend.txt
  512. //
  513. PromptOemScsi = FALSE;
  514. }
  515. }
  516. }
  517. p = SlGetSectionKeyIndex(WinntSifHandle,WINNT_SETUPPARAMS,WINNT_S_SKIPMISSING,0);
  518. if(p && (*p != '0')) {
  519. IgnoreMissingFiles = TRUE;
  520. }
  521. } else {
  522. WinntSifHandle = NULL;
  523. }
  524. //
  525. // Initialize the debugging system.
  526. //
  527. BlLogInitialize(BootDeviceId);
  528. //
  529. // Do PPC-specific initialization.
  530. //
  531. #if defined(_PPC_)
  532. Status = BlPpcInitialize();
  533. if (Status != ESUCCESS) {
  534. goto LoadFailed;
  535. }
  536. #endif // defined(_PPC_)
  537. SlGetDisk(KERNEL_IMAGE_FILENAME);
  538. strcpy(KernelDirectoryPath, BootPath);
  539. strcat(KernelDirectoryPath,KERNEL_IMAGE_FILENAME);
  540. BlOutputLoadMessage(BlFindMessage(SL_KERNEL_NAME), KernelDirectoryPath);
  541. Status = BlLoadImage(BootDeviceId,
  542. LoaderSystemCode,
  543. KernelDirectoryPath,
  544. TARGET_IMAGE,
  545. &SystemBase);
  546. if (Status != ESUCCESS) {
  547. SlFatalError(SL_FILE_LOAD_FAILED,KernelDirectoryPath,Status);
  548. goto LoadFailed;
  549. }
  550. strcpy(HalDirectoryPath, BootPath);
  551. if (PromptOemHal || (PreInstall && (ComputerType != NULL))) {
  552. if(PreInstall && OemHal) {
  553. //
  554. // This is a pre-install and an OEM hal was specified
  555. //
  556. strcat( HalDirectoryPath,
  557. #ifdef _X86_
  558. WINNT_OEM_DIR
  559. #else
  560. WINNT_OEM_TEXTMODE_DIR
  561. #endif
  562. );
  563. strcat( HalDirectoryPath, "\\" );
  564. }
  565. SlPromptOemHal(&HalBase, &HalName);
  566. strcat(HalDirectoryPath,HalName);
  567. } else {
  568. strcat(HalDirectoryPath,HalName);
  569. SlGetDisk(HalName);
  570. BlOutputLoadMessage(BlFindMessage(SL_HAL_NAME), HalDirectoryPath);
  571. Status = BlLoadImage(BootDeviceId,
  572. LoaderHalCode,
  573. HalDirectoryPath,
  574. TARGET_IMAGE,
  575. &HalBase);
  576. if (Status != ESUCCESS) {
  577. SlFatalError(SL_FILE_LOAD_FAILED,HalDirectoryPath,Status);
  578. goto LoadFailed;
  579. }
  580. }
  581. //
  582. // Generate a loader data entry for the system image.
  583. //
  584. Status = BlAllocateDataTableEntry("ntoskrnl.exe",
  585. KernelDirectoryPath,
  586. SystemBase,
  587. &SystemDataTableEntry);
  588. if (Status != ESUCCESS) {
  589. SlFatalError(SL_FILE_LOAD_FAILED,KernelDirectoryPath,Status);
  590. goto LoadFailed;
  591. }
  592. //
  593. // Generate a loader data entry for the HAL DLL.
  594. //
  595. Status = BlAllocateDataTableEntry("hal.dll",
  596. HalDirectoryPath,
  597. HalBase,
  598. &HalDataTableEntry);
  599. if (Status != ESUCCESS) {
  600. SlFatalError(SL_FILE_LOAD_FAILED,HalDirectoryPath,Status);
  601. goto LoadFailed;
  602. }
  603. #if defined(_ALPHA_)
  604. {
  605. CHAR PalFileName[32];
  606. CHAR FloppyName[80];
  607. PCHAR DiskDescription;
  608. ULONG FloppyId;
  609. PDETECTED_DEVICE OemPal;
  610. PDETECTED_DEVICE_FILE OemPalFile;
  611. //
  612. // Get the name of the pal file we are suppose to load.
  613. //
  614. Status = BlGeneratePalName(PalFileName);
  615. //
  616. // If we get an error from BlGenereatePalName, something is
  617. // really wrong with the firmware or the ARC tree. Abort and
  618. // bail out.
  619. //
  620. if (Status != ESUCCESS) {
  621. SlFatalError(SL_FILE_LOAD_FAILED,PalFileName,Status);
  622. goto LoadFailed;
  623. }
  624. //
  625. // Try loading the pal file from the boot device.
  626. //
  627. //
  628. // NOTE John Vert (jvert) 4-Feb-1994
  629. // Below call assumes all the PALs are on
  630. // the same floppy. We really should check the SIF
  631. // file and go immediately to the diskette prompt
  632. // if it's not in the SIF file, otherwise get
  633. // the appropriate disk.
  634. //
  635. SetupBlock->OemPal = NULL;
  636. SlGetDisk("A321064.PAL");
  637. Status = BlLoadPal(BootDeviceId,
  638. LoaderSystemCode,
  639. BootPath,
  640. TARGET_IMAGE,
  641. &BlLoaderBlock->u.Alpha.PalBaseAddress,
  642. BlFindMessage(SL_PAL_NAME));
  643. //
  644. // If we have failed, prompt the user for a floppy that contains
  645. // the pal code and load it from floppy. We keep looping until
  646. // either we get the right disk, or we get an error other than
  647. // 'file not found'.
  648. //
  649. if(Status == ENOENT) {
  650. DiskDescription = BlFindMessage(SL_OEM_DISK_PROMPT);
  651. }
  652. while (Status == ENOENT) {
  653. SlClearClientArea();
  654. //
  655. // Compute the name of the A: drive.
  656. //
  657. if (!SlpFindFloppy(0,FloppyName)) {
  658. //
  659. // No floppy drive available, bail out.
  660. //
  661. SlFatalError(SL_FILE_LOAD_FAILED,PalFileName,Status);
  662. goto LoadFailed;
  663. }
  664. //
  665. // Prompt for the disk.
  666. //
  667. SlPromptForDisk(DiskDescription, FALSE);
  668. //
  669. // Open the floppy.
  670. //
  671. Status = ArcOpen(FloppyName, ArcOpenReadOnly, &FloppyId);
  672. if (Status != ESUCCESS) {
  673. //
  674. // We want to give the user another chance if they didn't
  675. // have a floppy inserted.
  676. //
  677. if(Status != ENOENT) {
  678. Status = (Status == EIO) ? ENOENT : Status;
  679. }
  680. continue;
  681. }
  682. //
  683. // Load the pal file from the root of the floppy.
  684. //
  685. Status = BlLoadPal(FloppyId,
  686. LoaderSystemCode,
  687. "\\",
  688. TARGET_IMAGE,
  689. &BlLoaderBlock->u.Alpha.PalBaseAddress,
  690. BlFindMessage(SL_PAL_NAME));
  691. ArcClose(FloppyId);
  692. //
  693. // if we found the PAL, then record DETECTED_DEVICE info
  694. //
  695. if(Status == ESUCCESS) {
  696. OemPal = BlAllocateHeap(sizeof(DETECTED_DEVICE));
  697. if(!OemPal) {
  698. SlNoMemoryError();
  699. }
  700. SetupBlock->OemPal = OemPal;
  701. OemPal->Next = NULL;
  702. OemPal->IdString = NULL;
  703. OemPal->Description = NULL;
  704. OemPal->ThirdPartyOptionSelected = TRUE;
  705. OemPal->FileTypeBits = 0;
  706. OemPalFile = BlAllocateHeap(sizeof(DETECTED_DEVICE_FILE));
  707. if(!OemPalFile) {
  708. SlNoMemoryError();
  709. }
  710. OemPal->Files = OemPalFile;
  711. OemPalFile->Next = NULL;
  712. OemPalFile->Filename = SlCopyString(PalFileName);
  713. OemPalFile->FileType = HwFileMax;
  714. OemPalFile->ConfigName = NULL;
  715. OemPalFile->RegistryValueList = NULL;
  716. OemPalFile->DiskDescription = SlCopyString(DiskDescription);
  717. OemPalFile->DiskTagfile = NULL;
  718. OemPalFile->Directory = SlCopyString("");
  719. }
  720. }
  721. if(Status != ESUCCESS) {
  722. SlFriendlyError(
  723. Status,
  724. PalFileName,
  725. __LINE__,
  726. __FILE__
  727. );
  728. goto LoadFailed;
  729. }
  730. }
  731. #endif // ifdef _ALPHA_
  732. Status = BlScanImportDescriptorTable(BootDeviceId,
  733. BootDevice,
  734. BootPath,
  735. SystemDataTableEntry);
  736. if (Status != ESUCCESS) {
  737. SlFatalError(SL_FILE_LOAD_FAILED,KERNEL_IMAGE_FILENAME,Status);
  738. }
  739. //
  740. // Scan the import table for the HAL DLL and load all referenced DLLs.
  741. //
  742. Status = BlScanImportDescriptorTable(BootDeviceId,
  743. BootDevice,
  744. BootPath,
  745. HalDataTableEntry);
  746. if (Status != ESUCCESS) {
  747. SlFatalError(SL_FILE_LOAD_FAILED,"hal.dll",Status);
  748. goto LoadFailed;
  749. }
  750. //
  751. // Relocate the system entry point and set system specific information.
  752. //
  753. NtHeaders = RtlImageNtHeader(SystemBase);
  754. SystemEntry = (PTRANSFER_ROUTINE)((ULONG)SystemBase +
  755. NtHeaders->OptionalHeader.AddressOfEntryPoint);
  756. #if defined(_MIPS_)
  757. BlLoaderBlock->u.Mips.GpBase = (ULONG)SystemBase +
  758. NtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_GLOBALPTR].VirtualAddress;
  759. #endif
  760. #if defined(_ALPHA_)
  761. BlLoaderBlock->u.Alpha.GpBase = (ULONG)SystemBase +
  762. NtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_GLOBALPTR].VirtualAddress;
  763. #endif
  764. //
  765. // Load registry's SYSTEM hive
  766. //
  767. SlGetDisk("SETUPREG.HIV");
  768. Status = BlLoadSystemHive(BootDeviceId,
  769. BlFindMessage(SL_HIVE_NAME),
  770. BootPath,
  771. "SETUPREG.HIV");
  772. if (Status != ESUCCESS) {
  773. SlFatalError(SL_FILE_LOAD_FAILED,"SETUPREG.HIV",Status);
  774. goto LoadFailed;
  775. }
  776. //
  777. // Allocate structure for NLS data.
  778. //
  779. BlLoaderBlock->NlsData = BlAllocateHeap(sizeof(NLS_DATA_BLOCK));
  780. if (BlLoaderBlock->NlsData == NULL) {
  781. Status = ENOMEM;
  782. SlNoMemoryError();
  783. goto LoadFailed;
  784. }
  785. //
  786. // Load the OEM font
  787. //
  788. SlGetDisk(OemHalFontName);
  789. Status = BlLoadOemHalFont(BootDeviceId,
  790. BlFindMessage(SL_OEM_FONT_NAME),
  791. BootPath,
  792. &OemHalFont,
  793. BadFileName);
  794. if(Status != ESUCCESS) {
  795. SlFatalError(SL_FILE_LOAD_FAILED, OemHalFontName, Status);
  796. goto LoadFailed;
  797. }
  798. //
  799. // Load the NLS data.
  800. //
  801. // For now, we ensure that the disk containing the ansi
  802. // codepage file is in the drive and hope that the rest of the
  803. // nls files (oem codepage, unicode table) are on the same disk.
  804. //
  805. SlGetDisk(AnsiCpName);
  806. Status = BlLoadNLSData(BootDeviceId,
  807. BlFindMessage(SL_NLS_NAME),
  808. BootPath,
  809. &AnsiCodepage,
  810. &OemCodepage,
  811. &UnicodeCaseTable,
  812. BadFileName);
  813. if(Status != ESUCCESS) {
  814. SlFatalError(SL_FILE_LOAD_FAILED, AnsiCpName, Status);
  815. goto LoadFailed;
  816. }
  817. //
  818. // Load the system drivers we will need here
  819. //
  820. InitializeListHead(&BlLoaderBlock->BootDriverListHead);
  821. //
  822. // Always load setupdd.sys first, it will need to prep the rest of the
  823. // system.
  824. //
  825. Status = SlLoadDriver(BlFindMessage(SL_SETUP_NAME),
  826. "setupdd.sys",
  827. 0,
  828. TRUE
  829. );
  830. if (Status != ESUCCESS) {
  831. SlFatalError(SL_FILE_LOAD_FAILED,"setupdd.sys",Status);
  832. goto LoadFailed;
  833. }
  834. //
  835. // Fill in its registry key.
  836. //
  837. DriverEntry = (PBOOT_DRIVER_LIST_ENTRY)(BlLoaderBlock->BootDriverListHead.Flink);
  838. DriverEntry->RegistryPath.Buffer = BlAllocateHeap(256);
  839. if (DriverEntry->RegistryPath.Buffer == NULL) {
  840. SlNoMemoryError();
  841. goto LoadFailed;
  842. }
  843. DriverEntry->RegistryPath.Length = 0;
  844. DriverEntry->RegistryPath.MaximumLength = 256;
  845. RtlAppendUnicodeToString(&DriverEntry->RegistryPath,
  846. L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\setupdd");
  847. //
  848. // Load the Winnt.SIF file *here*
  849. //
  850. //
  851. // Load bus extenders.
  852. // It has to be done before scsiport.sys
  853. //
  854. Status = SlLoadBusExtender( InfFile );
  855. //
  856. // Load scsiport.sys next, so it'll always be around for any scsi miniports we may load
  857. //
  858. Status = SlLoadDriver(BlFindMessage(SL_SCSIPORT_NAME),
  859. "SCSIPORT.SYS",
  860. 0,
  861. FALSE
  862. );
  863. //
  864. // Detect scsi, video
  865. //
  866. // (If the user wants to select their own SCSI devices, we won't
  867. // do any detection)
  868. //
  869. if(!PromptOemScsi && (PreinstallDriverList == NULL) ) {
  870. SlDetectScsi(SetupBlock);
  871. }
  872. SlDetectVideo(SetupBlock);
  873. #if defined(ELTORITO)
  874. //
  875. // If this is an El Torito CD-ROM install, then we want to load all SCSI miniports
  876. // and disk class drivers.
  877. //
  878. if(ElToritoCDBoot) {
  879. LoadScsiMiniports = TRUE;
  880. }
  881. #endif
  882. //
  883. // If the LoadScsi flag is set, enumerate all the known SCSI miniports and load each
  884. // one.
  885. //
  886. if(LoadScsiMiniports) {
  887. Status = SlLoadSection(InfFile,"Scsi",TRUE);
  888. if (Status!=ESUCCESS) {
  889. goto LoadFailed;
  890. }
  891. SetupBlock->ScalarValues.LoadedScsi = 1;
  892. }
  893. //
  894. // Allow the user to pick an OEM SCSI driver here
  895. //
  896. if (PromptOemScsi || (PreinstallDriverList != NULL) ) {
  897. SlPromptOemScsi(&OemScsiInfo);
  898. }
  899. //
  900. // Walk the list of detected SCSI miniports and load each one.
  901. //
  902. ScsiDevice = SetupBlock->ScsiDevices;
  903. while (ScsiDevice != NULL) {
  904. if(ScsiDevice->ThirdPartyOptionSelected) {
  905. if(!OemScsiInfo) {
  906. SlError(500);
  907. goto LoadFailed;
  908. }
  909. Status = SlLoadOemDriver(
  910. NULL,
  911. OemScsiInfo->ScsiName,
  912. OemScsiInfo->ScsiBase,
  913. BlFindMessage(SL_SCSIPORT_NAME)
  914. );
  915. OemScsiInfo = OemScsiInfo->Next;
  916. } else {
  917. Status = SlLoadDriver(ScsiDevice->Description,
  918. ScsiDevice->BaseDllName,
  919. 0,
  920. TRUE
  921. );
  922. }
  923. if((Status == ESUCCESS)
  924. || ((Status == ENOENT) && IgnoreMissingFiles && !ScsiDevice->ThirdPartyOptionSelected)) {
  925. SetupBlock->ScalarValues.LoadedScsi = 1;
  926. } else {
  927. SlFriendlyError(
  928. Status,
  929. ScsiDevice->BaseDllName,
  930. __LINE__,
  931. __FILE__
  932. );
  933. goto LoadFailed;
  934. }
  935. ScsiDevice = ScsiDevice->Next;
  936. }
  937. //
  938. // If the LoadDiskClass flag is set, enumerate all the monolithic disk class drivers
  939. // and load each one. Note that we also do this if we've "detected" any scsi drivers,
  940. // so that we preserve the drive order.
  941. //
  942. if((LoadDiskClass) || (SetupBlock->ScalarValues.LoadedScsi == 1)) {
  943. Status = SlLoadSection(InfFile, "DiskDrivers", FALSE);
  944. if (Status == ESUCCESS) {
  945. SetupBlock->ScalarValues.LoadedDiskDrivers = 1;
  946. } else {
  947. goto LoadFailed;
  948. }
  949. }
  950. //
  951. // On x86, the video type is always set to VGA in i386\x86dtect.c.
  952. // On non-x86, the video type is either recognized, in which case
  953. // we don't unconditionally need vga.sys (the Display.Load section
  954. // tells us what to load), or it's not recognized,
  955. // in which case we will prompt the user for an oem disk.
  956. // If there is no display controller node at all, then PromptOemDisk
  957. // will be false and there will be no video device. In this case
  958. // we load vga.sys.
  959. //
  960. if (SetupBlock->VideoDevice.IdString != NULL) {
  961. VideoFileName = SlGetSectionKeyIndex(InfFile,
  962. "Display.Load",
  963. SetupBlock->VideoDevice.IdString,
  964. SIF_FILENAME_INDEX);
  965. if (VideoFileName != NULL) {
  966. #if 0
  967. VideoDescription = SlGetIniValue(InfFile,
  968. "Display",
  969. SetupBlock->VideoDevice.IdString,
  970. BlFindMessage(SL_VIDEO_NAME));
  971. #else
  972. //
  973. // With the new video detection mechanism, the description
  974. // for the video driver is likely to be something like
  975. // "Windows NT Compatible" which looks funny when displayed
  976. // in the status bar.
  977. //
  978. VideoDescription = BlFindMessage(SL_VIDEO_NAME);
  979. #endif
  980. Status = SlLoadDriver(VideoDescription,
  981. VideoFileName,
  982. 0,
  983. TRUE
  984. );
  985. if (Status == ESUCCESS) {
  986. SetupBlock->VideoDevice.BaseDllName = SlCopyString(VideoFileName);
  987. } else {
  988. SlFriendlyError(
  989. Status,
  990. VideoFileName,
  991. __LINE__,
  992. __FILE__
  993. );
  994. goto LoadFailed;
  995. }
  996. LoadedAVideoDriver = TRUE;
  997. }
  998. } else if (PromptOemVideo) {
  999. SlPromptOemVideo(&VideoBase, &OemVideoName);
  1000. Status = SlLoadOemDriver(
  1001. "VIDEOPRT.SYS",
  1002. OemVideoName,
  1003. VideoBase,
  1004. BlFindMessage(SL_VIDEO_NAME)
  1005. );
  1006. if(Status==ESUCCESS) {
  1007. LoadedAVideoDriver = TRUE;
  1008. SetupBlock->VideoDevice.BaseDllName = SlCopyString(OemVideoName);
  1009. }
  1010. }
  1011. if(!LoadedAVideoDriver) {
  1012. Status = SlLoadDriver(BlFindMessage(SL_VIDEO_NAME),
  1013. VGA_DRIVER_FILENAME,
  1014. 0,
  1015. TRUE
  1016. );
  1017. if(Status == ESUCCESS) {
  1018. SetupBlock->VideoDevice.BaseDllName = SlCopyString(VGA_DRIVER_FILENAME);
  1019. } else {
  1020. SlFriendlyError(
  1021. Status,
  1022. VGA_DRIVER_FILENAME,
  1023. __LINE__,
  1024. __FILE__
  1025. );
  1026. goto LoadFailed;
  1027. }
  1028. }
  1029. if(SetupBlock->VideoDevice.IdString == NULL) {
  1030. SetupBlock->VideoDevice.IdString = SlCopyString("VGA");
  1031. }
  1032. //
  1033. // Load the floppy driver
  1034. //
  1035. Status = SlLoadDriver(BlFindMessage(SL_FLOPPY_NAME),
  1036. "floppy.sys",
  1037. 0,
  1038. TRUE
  1039. );
  1040. if (Status == ESUCCESS) {
  1041. SetupBlock->ScalarValues.LoadedFloppyDrivers = 1;
  1042. }
  1043. #ifdef i386
  1044. else {
  1045. SlFriendlyError(
  1046. Status,
  1047. "floppy.sys",
  1048. __LINE__,
  1049. __FILE__
  1050. );
  1051. goto LoadFailed;
  1052. }
  1053. #endif
  1054. if(SetupBlock->ScalarValues.LoadedScsi == 1) {
  1055. //
  1056. // Enumerate the entries in the scsi class section and load each one.
  1057. //
  1058. Status = SlLoadSection(InfFile, "ScsiClass",FALSE);
  1059. if (Status != ESUCCESS) {
  1060. goto LoadFailed;
  1061. }
  1062. }
  1063. //
  1064. // Load the keyboard driver
  1065. //
  1066. SetupBlock->KeyboardDevice.Next = NULL;
  1067. SetupBlock->KeyboardDevice.IdString = SlCopyString("Keyboard");
  1068. SetupBlock->KeyboardDevice.ThirdPartyOptionSelected = FALSE;
  1069. SetupBlock->KeyboardDevice.FileTypeBits = 0;
  1070. SetupBlock->KeyboardDevice.BaseDllName = SlCopyString("i8042prt.sys");
  1071. Status = SlLoadDriver(BlFindMessage(SL_KBD_NAME),
  1072. "i8042prt.sys",
  1073. 0,
  1074. TRUE
  1075. );
  1076. if(Status != ESUCCESS) {
  1077. SlFriendlyError(
  1078. Status,
  1079. "i8042prt.sys",
  1080. __LINE__,
  1081. __FILE__
  1082. );
  1083. goto LoadFailed;
  1084. }
  1085. Status = SlLoadDriver(BlFindMessage(SL_KBD_NAME),
  1086. "kbdclass.sys",
  1087. 0,
  1088. TRUE
  1089. );
  1090. if(Status != ESUCCESS) {
  1091. SlFriendlyError(
  1092. Status,
  1093. "kbdclass.sys",
  1094. __LINE__,
  1095. __FILE__
  1096. );
  1097. goto LoadFailed;
  1098. }
  1099. //
  1100. // Load FAT
  1101. //
  1102. Status = SlLoadDriver(BlFindMessage(SL_FAT_NAME),
  1103. "fastfat.sys",
  1104. 0,
  1105. TRUE
  1106. );
  1107. #ifdef i386
  1108. if(Status != ESUCCESS) {
  1109. SlFriendlyError(
  1110. Status,
  1111. "fastfat.sys",
  1112. __LINE__,
  1113. __FILE__
  1114. );
  1115. goto LoadFailed;
  1116. }
  1117. #endif
  1118. //
  1119. // Load CDFS if setupldr was started from a cdrom, or if ForceLoadCdfs is set.
  1120. //
  1121. if (LoadCdfs || (!BlGetPathMnemonicKey(SetupDevice,
  1122. "cdrom",
  1123. &BootDriveNumber))) {
  1124. Status = SlLoadSection(InfFile, "CdRomDrivers",FALSE);
  1125. if (Status == ESUCCESS) {
  1126. SetupBlock->ScalarValues.LoadedCdRomDrivers = 1;
  1127. } else {
  1128. goto LoadFailed;
  1129. }
  1130. }
  1131. //
  1132. // Finally, make sure the appropriate disk containing NTDLL.DLL is in
  1133. // the drive.
  1134. //
  1135. SlGetDisk("ntdll.dll");
  1136. //
  1137. // Fill in the SETUPLDR block with relevant information
  1138. //
  1139. SetupBlock->ArcSetupDeviceName = BlLoaderBlock->ArcBootDeviceName;
  1140. SetupBlock->ScalarValues.SetupFromCdRom = FALSE;
  1141. SetupBlock->ScalarValues.SetupOperation = SetupOperationSetup;
  1142. //
  1143. // Get the NTFT drive signatures to allow the kernel to create the
  1144. // correct ARC name <=> NT name mappings.
  1145. //
  1146. BlGetArcDiskInformation();
  1147. SlpMarkDisks();
  1148. //
  1149. // If setup was started from a CD-ROM, generate an entry in the ARC disk
  1150. // information list describing the cd-rom.
  1151. //
  1152. if (!BlGetPathMnemonicKey(SetupDevice,
  1153. "cdrom",
  1154. &BootDriveNumber)) {
  1155. BlReadSignature(SetupDevice,TRUE);
  1156. }
  1157. //
  1158. //
  1159. // Execute the architecture specific setup code.
  1160. //
  1161. Status = BlSetupForNt(BlLoaderBlock);
  1162. if (Status != ESUCCESS) {
  1163. SlFriendlyError(
  1164. Status,
  1165. "\"Windows NT Executive\"",
  1166. __LINE__,
  1167. __FILE__
  1168. );
  1169. goto LoadFailed;
  1170. }
  1171. //
  1172. // Turn off the debugging system.
  1173. //
  1174. BlLogTerminate();
  1175. //
  1176. // Transfer control to loaded image.
  1177. //
  1178. (SystemEntry)(BlLoaderBlock);
  1179. Status = EBADF;
  1180. SlFriendlyError(
  1181. Status,
  1182. "\"Windows NT Executive\"",
  1183. __LINE__,
  1184. __FILE__
  1185. );
  1186. LoadFailed:
  1187. SlWriteStatusText(BlFindMessage(SL_TOTAL_SETUP_DEATH));
  1188. SlFlushConsoleBuffer();
  1189. SlGetChar();
  1190. ArcRestart();
  1191. return(Status);
  1192. }
  1193. VOID
  1194. SlGetSetupValues(
  1195. IN PSETUP_LOADER_BLOCK SetupBlock
  1196. )
  1197. /*++
  1198. Routine Description:
  1199. Reads the setup control values out of the given .INI file. Also supplies
  1200. reasonable defaults for values that don't exist.
  1201. Arguments:
  1202. SetupBlock - Supplies a pointer to the Setup loader block
  1203. Return Value:
  1204. None. Global variables are initialized to reflect the contents of the INI file
  1205. --*/
  1206. {
  1207. PCHAR MachineName = NULL;
  1208. PCHAR NlsName;
  1209. ANSI_STRING NlsString;
  1210. BlLoaderBlock->LoadOptions = SlGetIniValue(InfFile,
  1211. "setupdata",
  1212. "osloadoptions",
  1213. "");
  1214. //
  1215. // Determine which HAL to load. If the appropriate HAL cannot be
  1216. // determined, or if we are to prompt for an OEM HAL, then set the
  1217. // 'PromptOemHal' flag (may have already been set by the user's
  1218. // keypress).
  1219. //
  1220. if(!PromptOemHal) {
  1221. PromptOemHal = (atoi(SlGetIniValue(InfFile,
  1222. "setupdata",
  1223. "ForceOemHal",
  1224. "0")) == 1);
  1225. }
  1226. if(!PromptOemHal) {
  1227. MachineName = SlDetectHal(SetupBlock);
  1228. }
  1229. SetupBlock->ComputerDevice.Files = 0;
  1230. SetupBlock->ComputerDevice.Next = NULL;
  1231. SetupBlock->ComputerDevice.Description = NULL;
  1232. SetupBlock->ComputerDevice.ThirdPartyOptionSelected = FALSE;
  1233. SetupBlock->ComputerDevice.FileTypeBits = 0;
  1234. SetupBlock->ComputerDevice.Files = 0;
  1235. SetupBlock->ComputerDevice.BaseDllName = SlCopyString("");
  1236. if(MachineName!=NULL) {
  1237. SetupBlock->ComputerDevice.IdString = SlCopyString(MachineName);
  1238. HalName = SlGetIniValue(InfFile,
  1239. "Hal.Load",
  1240. MachineName,
  1241. NULL);
  1242. HalDescription = SlGetIniValue(InfFile,
  1243. "Computer",
  1244. MachineName,
  1245. NULL);
  1246. }
  1247. if(!(MachineName && HalName && HalDescription)) {
  1248. PromptOemHal = TRUE;
  1249. }
  1250. AnsiCpName = SlGetIniValue(InfFile,
  1251. "nls",
  1252. "AnsiCodepage",
  1253. "c_1252.nls");
  1254. NlsString.Buffer = AnsiCpName;
  1255. NlsString.Length = strlen(AnsiCpName);
  1256. AnsiCodepage.MaximumLength = strlen(AnsiCpName)*sizeof(WCHAR)+sizeof(UNICODE_NULL);
  1257. AnsiCodepage.Buffer = BlAllocateHeap(AnsiCodepage.MaximumLength);
  1258. RtlAnsiStringToUnicodeString(&AnsiCodepage, &NlsString, FALSE);
  1259. NlsName = SlGetIniValue(InfFile,
  1260. "nls",
  1261. "OemCodepage",
  1262. "c_437.nls");
  1263. NlsString.Buffer = NlsName;
  1264. NlsString.Length = strlen(NlsName);
  1265. OemCodepage.MaximumLength = strlen(NlsName)*sizeof(WCHAR)+sizeof(UNICODE_NULL);
  1266. OemCodepage.Buffer = BlAllocateHeap(OemCodepage.MaximumLength);
  1267. RtlAnsiStringToUnicodeString(&OemCodepage, &NlsString, FALSE);
  1268. NlsName = SlGetIniValue(InfFile,
  1269. "nls",
  1270. "UnicodeCasetable",
  1271. "l_intl.nls");
  1272. NlsString.Buffer = NlsName;
  1273. NlsString.Length = strlen(NlsName);
  1274. UnicodeCaseTable.MaximumLength = strlen(NlsName)*sizeof(WCHAR)+sizeof(UNICODE_NULL);
  1275. UnicodeCaseTable.Buffer = BlAllocateHeap(UnicodeCaseTable.MaximumLength);
  1276. RtlAnsiStringToUnicodeString(&UnicodeCaseTable, &NlsString, FALSE);
  1277. OemHalFontName = SlGetIniValue(InfFile,
  1278. "nls",
  1279. "OemHalFont",
  1280. "vgaoem.fon");
  1281. NlsString.Buffer = OemHalFontName;
  1282. NlsString.Length = strlen(OemHalFontName);
  1283. OemHalFont.MaximumLength = strlen(OemHalFontName)*sizeof(WCHAR)+sizeof(UNICODE_NULL);
  1284. OemHalFont.Buffer = BlAllocateHeap(OemHalFont.MaximumLength);
  1285. RtlAnsiStringToUnicodeString(&OemHalFont, &NlsString, FALSE);
  1286. LoadScsiMiniports = (atoi(SlGetIniValue(InfFile,
  1287. "SetupData",
  1288. "ForceScsi",
  1289. "0")) == 1);
  1290. LoadDiskClass = (atoi(SlGetIniValue(InfFile,
  1291. "setupdata",
  1292. "ForceDiskClass",
  1293. "0")) == 1);
  1294. LoadCdfs = (atoi(SlGetIniValue(InfFile,
  1295. "setupdata",
  1296. "ForceCdRom",
  1297. "0")) == 1);
  1298. //
  1299. // If we haven't already been instructed to prompt for an OEM SCSI disk (by
  1300. // the user's keypress), then get this value from the inf file.
  1301. //
  1302. if(!PromptOemScsi) {
  1303. PromptOemScsi = (atoi(SlGetIniValue(InfFile,
  1304. "setupdata",
  1305. "ForceOemScsi",
  1306. "0")) == 1);
  1307. }
  1308. BootPath = SlGetIniValue(InfFile,
  1309. "setupdata",
  1310. "BootPath",
  1311. NULL);
  1312. BootDevice = SlGetIniValue(InfFile,
  1313. "setupdata",
  1314. "BootDevice",
  1315. NULL);
  1316. return;
  1317. }
  1318. VOID
  1319. BlOutputLoadMessage (
  1320. IN PCHAR DeviceName,
  1321. IN PCHAR FileName
  1322. )
  1323. /*++
  1324. Routine Description:
  1325. This routine outputs a loading message on the status line
  1326. Arguments:
  1327. DeviceName - Supplies a pointer to a zero terminated device name.
  1328. FileName - Supplies a pointer to a zero terminated file name.
  1329. Return Value:
  1330. None.
  1331. --*/
  1332. {
  1333. CHAR OutputBuffer[256];
  1334. PCHAR FormatString;
  1335. //
  1336. // Construct and output loading file message.
  1337. //
  1338. FormatString = BlFindMessage(SL_FILE_LOAD_MESSAGE);
  1339. sprintf(OutputBuffer,FormatString,DeviceName);
  1340. SlWriteStatusText(OutputBuffer);
  1341. return;
  1342. }
  1343. ARC_STATUS
  1344. SlLoadDriver(
  1345. IN PCHAR DeviceName,
  1346. IN PCHAR DriverName,
  1347. IN ULONG DriverFlags,
  1348. IN BOOLEAN InsertIntoDriverList
  1349. )
  1350. /*++
  1351. Routine Description:
  1352. Attempts to load a driver from the device identified by the global
  1353. variable BootDeviceId.
  1354. Arguments:
  1355. DeviceName - Supplies the name of the device.
  1356. DriverName - Supplies the name of the driver.
  1357. DriverFlags - Flags to set in the LDR_DATA_TABLE_ENTRY.
  1358. InsertIntoDriverList - Flag specifying whether this 'driver' should be
  1359. placed into the BootDriveListHead list (eg, scsiport.sys
  1360. is not a true driver, and should not be placed in this list)
  1361. Return Value:
  1362. ESUCCESS - Driver successfully loaded
  1363. --*/
  1364. {
  1365. PBOOT_DRIVER_LIST_ENTRY DriverEntry;
  1366. NTSTATUS Status;
  1367. CHAR DriverPath[128];
  1368. PLDR_DATA_TABLE_ENTRY DataTableEntry;
  1369. if(BlCheckForLoadedDll(DriverName,&DataTableEntry)) {
  1370. return(ESUCCESS);
  1371. }
  1372. DriverEntry = SlpCreateDriverEntry(DriverName);
  1373. if(DriverEntry == NULL) {
  1374. SlNoMemoryError();
  1375. return(ENOMEM);
  1376. }
  1377. SlGetDisk(DriverName);
  1378. strcpy(DriverPath,BootPath);
  1379. Status = BlLoadDeviceDriver(
  1380. BootDeviceId,
  1381. DeviceName,
  1382. DriverPath,
  1383. DriverName,
  1384. DriverFlags,
  1385. &DriverEntry->LdrEntry
  1386. );
  1387. if((Status == ESUCCESS) && InsertIntoDriverList) {
  1388. InsertTailList(&BlLoaderBlock->BootDriverListHead,&DriverEntry->Link);
  1389. }
  1390. return(Status);
  1391. }
  1392. ARC_STATUS
  1393. SlLoadOemDriver(
  1394. IN PCHAR ExportDriver, OPTIONAL
  1395. IN PCHAR DriverName,
  1396. IN PVOID BaseAddress,
  1397. IN PCHAR LoadMessage
  1398. )
  1399. {
  1400. PBOOT_DRIVER_LIST_ENTRY DriverEntry;
  1401. ARC_STATUS Status;
  1402. PLDR_DATA_TABLE_ENTRY DataTableEntry;
  1403. if(BlCheckForLoadedDll(DriverName,&DataTableEntry)) {
  1404. return(ESUCCESS);
  1405. }
  1406. if(ExportDriver) {
  1407. SlGetDisk(ExportDriver);
  1408. }
  1409. DriverEntry = SlpCreateDriverEntry(DriverName);
  1410. if (DriverEntry==NULL) {
  1411. return(ENOMEM);
  1412. }
  1413. Status = BlAllocateDataTableEntry(
  1414. DriverName,
  1415. DriverName,
  1416. BaseAddress,
  1417. &DriverEntry->LdrEntry
  1418. );
  1419. if (Status == ESUCCESS) {
  1420. Status = BlScanImportDescriptorTable(
  1421. BootDeviceId,
  1422. LoadMessage,
  1423. BootPath,
  1424. DriverEntry->LdrEntry
  1425. );
  1426. if(Status == ESUCCESS) {
  1427. InsertTailList(&BlLoaderBlock->BootDriverListHead,&DriverEntry->Link);
  1428. }
  1429. }
  1430. return(Status);
  1431. }
  1432. PBOOT_DRIVER_LIST_ENTRY
  1433. SlpCreateDriverEntry(
  1434. IN PCHAR DriverName
  1435. )
  1436. /*++
  1437. Routine Description:
  1438. Allocates and initializes a boot driver list entry structure.
  1439. Arguments:
  1440. DriverName - Supplies the name of the driver.
  1441. Return Value:
  1442. Pointer to the initialized structure.
  1443. --*/
  1444. {
  1445. PBOOT_DRIVER_LIST_ENTRY DriverEntry;
  1446. ANSI_STRING String;
  1447. DriverEntry = BlAllocateHeap(sizeof(BOOT_DRIVER_LIST_ENTRY));
  1448. if (DriverEntry==NULL) {
  1449. SlNoMemoryError();
  1450. return(NULL);
  1451. }
  1452. DriverEntry->FilePath.MaximumLength = strlen(DriverName)*sizeof(WCHAR)+1;
  1453. DriverEntry->FilePath.Buffer = BlAllocateHeap(DriverEntry->FilePath.MaximumLength);
  1454. if (DriverEntry->FilePath.Buffer==NULL) {
  1455. SlNoMemoryError();
  1456. return(NULL);
  1457. }
  1458. String.Length = strlen(DriverName);
  1459. String.Buffer = DriverName;
  1460. RtlAnsiStringToUnicodeString(&DriverEntry->FilePath, &String, FALSE);
  1461. return(DriverEntry);
  1462. }
  1463. BOOLEAN
  1464. SlGetDisk(
  1465. IN PCHAR Filename
  1466. )
  1467. /*++
  1468. Routine Description:
  1469. Given a filename, this routine ensures that the correct disk is
  1470. in the drive identified by the global variables BootDevice and
  1471. BootDeviceId. The user may be prompted to change disks.
  1472. Arguments:
  1473. Filename - Supplies the name of the file to be loaded.
  1474. Return Value:
  1475. TRUE - Disk was successfully loaded.
  1476. FALSE - User has cancelled out of Setup.
  1477. --*/
  1478. {
  1479. PCHAR DiskNumber;
  1480. PCHAR DiskName;
  1481. PCHAR DiskTag;
  1482. ULONG FileId;
  1483. CHAR PlatformSpecificSection[128];
  1484. //
  1485. // If the media is fixed, the user can't change disks.
  1486. // Just return TRUE indicating that the disk is in the drive.
  1487. //
  1488. if(FixedBootMedia) {
  1489. return(TRUE);
  1490. }
  1491. //
  1492. // Look up filename to get the disk number. Look in the platform-specific
  1493. // directory first.
  1494. //
  1495. strcpy(PlatformSpecificSection,FilesSectionName);
  1496. strcat(PlatformSpecificSection,PlatformExtension);
  1497. #if defined(ELTORITO)
  1498. if (ElToritoCDBoot) {
  1499. // for Cd boot we use the setup media path instead of a boot-media-specific path
  1500. DiskNumber = SlGetSectionKeyIndex(InfFile,PlatformSpecificSection,Filename,0);
  1501. } else {
  1502. #endif
  1503. DiskNumber = SlGetSectionKeyIndex(InfFile,PlatformSpecificSection,Filename,6);
  1504. #if defined(ELTORITO)
  1505. }
  1506. #endif
  1507. if(DiskNumber == NULL) {
  1508. #if defined(ELTORITO)
  1509. if (ElToritoCDBoot) {
  1510. // for Cd boot we use the setup media path instead of a boot-media-specific path
  1511. DiskNumber = SlGetSectionKeyIndex(InfFile,FilesSectionName,Filename,0);
  1512. } else {
  1513. #endif
  1514. DiskNumber = SlGetSectionKeyIndex(InfFile,FilesSectionName,Filename,6);
  1515. #if defined(ELTORITO)
  1516. }
  1517. #endif
  1518. }
  1519. if((DiskNumber==NULL) || !(*DiskNumber)) {
  1520. SlFatalError(SL_INF_ENTRY_MISSING,Filename,FilesSectionName);
  1521. return(FALSE);
  1522. }
  1523. //
  1524. // Look up disk number to get the diskname and tag.
  1525. // Look in platform-specific directory first.
  1526. //
  1527. strcpy(PlatformSpecificSection,MediaSectionName);
  1528. strcat(PlatformSpecificSection,PlatformExtension);
  1529. if(DiskName = SlGetSectionKeyIndex(InfFile,PlatformSpecificSection,DiskNumber,0)) {
  1530. DiskTag = SlGetSectionKeyIndex(InfFile,PlatformSpecificSection,DiskNumber,1);
  1531. } else {
  1532. if(DiskName = SlGetSectionKeyIndex(InfFile,MediaSectionName,DiskNumber,0)) {
  1533. DiskTag = SlGetSectionKeyIndex(InfFile,MediaSectionName,DiskNumber,1);
  1534. } else {
  1535. SlFatalError(SL_INF_ENTRY_MISSING,DiskNumber,MediaSectionName);
  1536. return(FALSE);
  1537. }
  1538. }
  1539. while(1) {
  1540. //
  1541. // Open a new device id onto the disk.
  1542. //
  1543. if(BootDeviceIdValid) {
  1544. ArcClose(BootDeviceId);
  1545. BootDeviceIdValid = FALSE;
  1546. }
  1547. if(ArcOpen(BootDevice,ArcOpenReadOnly,&BootDeviceId) == ESUCCESS) {
  1548. BootDeviceIdValid = TRUE;
  1549. //
  1550. // Check for existence of the disk tag.
  1551. //
  1552. if(BlOpen(BootDeviceId,DiskTag,ArcOpenReadOnly,&FileId) == ESUCCESS) {
  1553. //
  1554. // Disk is in the drive. Return success.
  1555. // Leave BootDeviceId open onto the device.
  1556. //
  1557. BlClose(FileId);
  1558. return(TRUE);
  1559. } else {
  1560. //
  1561. // Prompt for the user to change disks.
  1562. //
  1563. ArcClose(BootDeviceId);
  1564. BootDeviceIdValid = FALSE;
  1565. SlPromptForDisk(DiskName, FALSE);
  1566. }
  1567. } else {
  1568. //
  1569. // Can't open device. Prompt for the disk.
  1570. //
  1571. SlPromptForDisk(DiskName, FALSE);
  1572. }
  1573. }
  1574. }
  1575. PCHAR
  1576. SlCopyString(
  1577. IN PCHAR String
  1578. )
  1579. /*++
  1580. Routine Description:
  1581. Copies a string into the loader heap so it can be passed to the
  1582. kernel.
  1583. Arguments:
  1584. String - Supplies the string to be copied.
  1585. Return Value:
  1586. PCHAR - pointer into the loader heap where the string was copied to.
  1587. --*/
  1588. {
  1589. PCHAR Buffer;
  1590. if (String==NULL) {
  1591. SlNoMemoryError();
  1592. }
  1593. Buffer = BlAllocateHeap(strlen(String)+1);
  1594. if (Buffer==NULL) {
  1595. SlNoMemoryError();
  1596. } else {
  1597. strcpy(Buffer, String);
  1598. }
  1599. return(Buffer);
  1600. }
  1601. ARC_STATUS
  1602. SlLoadSection(
  1603. IN PVOID Inf,
  1604. IN PCHAR SectionName,
  1605. IN BOOLEAN IsScsiSection
  1606. )
  1607. /*++
  1608. Routine Description:
  1609. Enumerates all the drivers in a section and loads them.
  1610. Arguments:
  1611. Inf - Supplies a handle to the INF file.
  1612. SectionName - Supplies the name of the section.
  1613. IsScsiSection - Flag specifying whether this is the Scsi.Load section.
  1614. If so, we create the DETECTED_DEVICE linked list, but
  1615. don't actually load the drivers.
  1616. Return Value:
  1617. ESUCCESS if all drivers were loaded successfully/no errors encountered
  1618. --*/
  1619. {
  1620. ULONG i;
  1621. CHAR LoadSectionName[100];
  1622. PCHAR DriverFilename;
  1623. PCHAR DriverId;
  1624. PCHAR DriverDescription;
  1625. PCHAR NoLoadSpec;
  1626. PCHAR p;
  1627. ARC_STATUS Status;
  1628. PDETECTED_DEVICE ScsiDevice;
  1629. SCSI_INSERT_STATUS sis;
  1630. sprintf(LoadSectionName, "%s.Load",SectionName);
  1631. i=0;
  1632. do {
  1633. DriverFilename = SlGetSectionLineIndex(Inf,LoadSectionName,i,SIF_FILENAME_INDEX);
  1634. NoLoadSpec = SlGetSectionLineIndex(Inf,LoadSectionName,i,2);
  1635. if(DriverFilename && ((NoLoadSpec == NULL) || _stricmp(NoLoadSpec,"noload"))) {
  1636. if(!IsScsiSection) {
  1637. //
  1638. // We only want to load the drivers if they aren't scsi miniports
  1639. //
  1640. DriverId = SlGetKeyName(Inf,LoadSectionName,i);
  1641. DriverDescription = SlGetIniValue(Inf,SectionName,DriverId,"noname");
  1642. Status = SlLoadDriver(DriverDescription,
  1643. DriverFilename,
  1644. 0,
  1645. TRUE
  1646. );
  1647. if((Status == ENOENT) && IgnoreMissingFiles) {
  1648. Status = ESUCCESS;
  1649. }
  1650. } else {
  1651. Status = ESUCCESS;
  1652. }
  1653. if (Status == ESUCCESS) {
  1654. if(IsScsiSection) {
  1655. //
  1656. // Create a new detected device entry.
  1657. //
  1658. if((sis = SlInsertScsiDevice(i, &ScsiDevice)) == ScsiInsertError) {
  1659. return(ENOMEM);
  1660. }
  1661. if(sis == ScsiInsertExisting) {
  1662. #if DBG
  1663. //
  1664. // Sanity check to make sure we're talking about the same driver
  1665. //
  1666. if(_strcmpi(ScsiDevice->BaseDllName, DriverFilename)) {
  1667. SlError(400);
  1668. return EINVAL;
  1669. }
  1670. #endif
  1671. } else {
  1672. p = SlGetKeyName(Inf,LoadSectionName,i);
  1673. //
  1674. // Find the driver description
  1675. //
  1676. if(p) {
  1677. DriverDescription = SlGetIniValue(Inf,
  1678. SectionName,
  1679. p,
  1680. p);
  1681. } else {
  1682. DriverDescription = SlCopyString(BlFindMessage(SL_TEXT_SCSI_UNNAMED));
  1683. }
  1684. ScsiDevice->IdString = p ? p : SlCopyString("");
  1685. ScsiDevice->Description = DriverDescription;
  1686. ScsiDevice->ThirdPartyOptionSelected = FALSE;
  1687. ScsiDevice->FileTypeBits = 0;
  1688. ScsiDevice->Files = NULL;
  1689. ScsiDevice->BaseDllName = DriverFilename;
  1690. }
  1691. }
  1692. } else {
  1693. SlFriendlyError(
  1694. Status,
  1695. DriverFilename,
  1696. __LINE__,
  1697. __FILE__
  1698. );
  1699. return(Status);
  1700. }
  1701. }
  1702. i++;
  1703. } while ( DriverFilename != NULL );
  1704. return(ESUCCESS);
  1705. }
  1706. VOID
  1707. SlpMarkDisks(
  1708. VOID
  1709. )
  1710. /*++
  1711. Routine Description:
  1712. This routine ensures that there is not more than one disk with the
  1713. same checksum, a signature of zero, and a valid partition table.
  1714. If it finds a disk with a signature of zero, it searches the rest
  1715. of the list for any other disks with a zero signature and the same
  1716. checksum. If it finds one, it stamps a unique signature on the
  1717. first disk.
  1718. We also use a heuristic to determine if the disk is 'vacant', and if
  1719. so, we stamp a unique signature on it (unless it's the first one we
  1720. found).
  1721. Arguments:
  1722. None.
  1723. Return Value:
  1724. None.
  1725. --*/
  1726. {
  1727. PARC_DISK_INFORMATION DiskInfo;
  1728. PLIST_ENTRY Entry;
  1729. PLIST_ENTRY CheckEntry;
  1730. PARC_DISK_SIGNATURE DiskSignature;
  1731. PARC_DISK_SIGNATURE CheckSignature;
  1732. ARC_STATUS Status;
  1733. BOOLEAN VacantDiskFound = FALSE;
  1734. DiskInfo = BlLoaderBlock->ArcDiskInformation;
  1735. Entry = DiskInfo->DiskSignatures.Flink;
  1736. while (Entry != &DiskInfo->DiskSignatures) {
  1737. DiskSignature = CONTAINING_RECORD(Entry,ARC_DISK_SIGNATURE,ListEntry);
  1738. if (DiskSignature->ValidPartitionTable) {
  1739. if (DiskSignature->Signature==0) {
  1740. //
  1741. // Check the rest of the list to see if there is another
  1742. // disk with the same checksum and an signature of zero.
  1743. //
  1744. CheckEntry = Entry->Flink;
  1745. while (CheckEntry != &DiskInfo->DiskSignatures) {
  1746. CheckSignature = CONTAINING_RECORD(CheckEntry,ARC_DISK_SIGNATURE,ListEntry);
  1747. if ((CheckSignature->Signature==0) &&
  1748. (CheckSignature->ValidPartitionTable) &&
  1749. (CheckSignature->CheckSum == DiskSignature->CheckSum)) {
  1750. //
  1751. // We have two disks that are indistinguishable, both do
  1752. // not have signatures. Mark the first one with a signature
  1753. // so that they can be differentiated by textmode setup.
  1754. //
  1755. Status = SlpStampFTSignature(DiskSignature);
  1756. if (Status != ESUCCESS) {
  1757. SlError(Status);
  1758. }
  1759. break;
  1760. } else {
  1761. CheckEntry = CheckEntry->Flink;
  1762. }
  1763. }
  1764. }
  1765. } else {
  1766. //
  1767. // See if the disk is vacant, to find out whether we can mess with it.
  1768. //
  1769. if (SlpIsDiskVacant(DiskSignature)) {
  1770. //
  1771. // stamp all but the first one.
  1772. //
  1773. if (VacantDiskFound) {
  1774. Status = SlpStampFTSignature(DiskSignature);
  1775. if (Status != ESUCCESS) {
  1776. SlError(Status);
  1777. }
  1778. } else {
  1779. VacantDiskFound = TRUE;
  1780. }
  1781. }
  1782. }
  1783. Entry = Entry->Flink;
  1784. }
  1785. }
  1786. BOOLEAN
  1787. SlpIsDiskVacant(
  1788. IN PARC_DISK_SIGNATURE DiskSignature
  1789. )
  1790. /*++
  1791. Routine Description:
  1792. This routine attempts to determine if a disk is 'vacant' by
  1793. checking to see if the first half of its MBR has all bytes set
  1794. to the same value.
  1795. Arguments:
  1796. DiskSignature - Supplies a pointer to the existing disk
  1797. signature structure.
  1798. Return Value:
  1799. TRUE - The disk is vacant.
  1800. FALSE - The disk is not vacant (ie, we can't determine if it
  1801. is vacant using our heuristic)
  1802. --*/
  1803. {
  1804. UCHAR Partition[100];
  1805. ULONG DiskId;
  1806. ARC_STATUS Status;
  1807. UCHAR SectorBuffer[512+256];
  1808. PUCHAR Sector;
  1809. LARGE_INTEGER SeekValue;
  1810. ULONG Count, i;
  1811. BOOLEAN IsVacant;
  1812. //
  1813. // Open partition0.
  1814. //
  1815. strcpy(Partition, DiskSignature->ArcName);
  1816. strcat(Partition, "partition(0)");
  1817. Status = ArcOpen(Partition, ArcOpenReadOnly, &DiskId);
  1818. if (Status != ESUCCESS) {
  1819. return(FALSE);
  1820. }
  1821. //
  1822. // Read in the first sector
  1823. //
  1824. Sector = ALIGN_BUFFER(SectorBuffer);
  1825. SeekValue.QuadPart = 0;
  1826. Status = ArcSeek(DiskId, &SeekValue, SeekAbsolute);
  1827. if (Status == ESUCCESS) {
  1828. Status = ArcRead(DiskId, Sector, 512, &Count);
  1829. }
  1830. if (Status != ESUCCESS) {
  1831. ArcClose(DiskId);
  1832. return(FALSE);
  1833. }
  1834. //
  1835. // See if 1st 256 bytes are identical
  1836. //
  1837. for(i = 1, IsVacant = TRUE; i<256; i++) {
  1838. if(Sector[i] - *Sector) {
  1839. IsVacant = FALSE;
  1840. break;
  1841. }
  1842. }
  1843. ArcClose(DiskId);
  1844. return(IsVacant);
  1845. }
  1846. ARC_STATUS
  1847. SlpStampFTSignature(
  1848. IN PARC_DISK_SIGNATURE DiskSignature
  1849. )
  1850. /*++
  1851. Routine Description:
  1852. This routine stamps a given drive with a unique signature.
  1853. It traverses the list of disk signatures to ensure that it
  1854. stamps a signature that is not already present in the
  1855. disk list. Then it writes the new disk signature to the
  1856. disk and recomputes the checksum.
  1857. Arguments:
  1858. DiskSignature - Supplies a pointer to the existing disk
  1859. signature structure.
  1860. Return Value:
  1861. None.
  1862. --*/
  1863. {
  1864. ULONG NewSignature;
  1865. PLIST_ENTRY ListEntry;
  1866. UCHAR SectorBuffer[512+256];
  1867. PUCHAR Sector;
  1868. LARGE_INTEGER SeekValue;
  1869. UCHAR Partition[100];
  1870. PARC_DISK_SIGNATURE Signature;
  1871. ULONG DiskId;
  1872. ARC_STATUS Status;
  1873. ULONG i;
  1874. ULONG Sum;
  1875. ULONG Count;
  1876. //
  1877. // Get a reasonably unique seed to start with.
  1878. //
  1879. NewSignature = ArcGetRelativeTime();
  1880. //
  1881. // Scan through the list to make sure it's unique.
  1882. //
  1883. ReScan:
  1884. ListEntry = BlLoaderBlock->ArcDiskInformation->DiskSignatures.Flink;
  1885. while (ListEntry != &BlLoaderBlock->ArcDiskInformation->DiskSignatures) {
  1886. Signature = CONTAINING_RECORD(ListEntry,ARC_DISK_SIGNATURE,ListEntry);
  1887. if (Signature->Signature == NewSignature) {
  1888. //
  1889. // Found a duplicate, pick a new number and
  1890. // try again.
  1891. //
  1892. if (++NewSignature == 0) {
  1893. //
  1894. // zero signatures are what we're trying to avoid
  1895. // (like this will ever happen)
  1896. //
  1897. NewSignature = 1;
  1898. }
  1899. goto ReScan;
  1900. }
  1901. ListEntry = ListEntry->Flink;
  1902. }
  1903. //
  1904. // Now we have a valid new signature to put on the disk.
  1905. // Read the sector off disk, put the new signature in,
  1906. // write the sector back, and recompute the checksum.
  1907. //
  1908. strcpy(Partition,DiskSignature->ArcName);
  1909. strcat(Partition,"partition(0)");
  1910. Status = ArcOpen(Partition, ArcOpenReadWrite, &DiskId);
  1911. if (Status != ESUCCESS) {
  1912. return(Status);
  1913. }
  1914. //
  1915. // Read in the first sector
  1916. //
  1917. Sector = ALIGN_BUFFER(SectorBuffer);
  1918. SeekValue.QuadPart = 0;
  1919. Status = ArcSeek(DiskId, &SeekValue, SeekAbsolute);
  1920. if (Status == ESUCCESS) {
  1921. Status = ArcRead(DiskId,Sector,512,&Count);
  1922. }
  1923. if (Status != ESUCCESS) {
  1924. ArcClose(DiskId);
  1925. return(Status);
  1926. }
  1927. ((PULONG)Sector)[PARTITION_TABLE_OFFSET/2-1] = NewSignature;
  1928. Status = ArcSeek(DiskId, &SeekValue, SeekAbsolute);
  1929. if (Status == ESUCCESS) {
  1930. Status = ArcWrite(DiskId,Sector,512,&Count);
  1931. }
  1932. ArcClose(DiskId);
  1933. if (Status != ESUCCESS) {
  1934. return(Status);
  1935. }
  1936. //
  1937. // We have successfully written back out the new signature,
  1938. // recompute the checksum.
  1939. //
  1940. DiskSignature->Signature = NewSignature;
  1941. Sum = 0;
  1942. for (i=0;i<128;i++) {
  1943. Sum += ((PULONG)Sector)[i];
  1944. }
  1945. DiskSignature->CheckSum = 0-Sum;
  1946. return(ESUCCESS);
  1947. }
  1948. VOID
  1949. SlCheckOemKeypress(
  1950. VOID
  1951. )
  1952. {
  1953. ULONG StartTime;
  1954. ULONG EndTime;
  1955. ULONG c;
  1956. StartTime = ArcGetRelativeTime();
  1957. EndTime = StartTime + 3;
  1958. do {
  1959. if(ArcGetReadStatus(ARC_CONSOLE_INPUT) == ESUCCESS) {
  1960. //
  1961. // There is a key pending, so see what it is.
  1962. //
  1963. c = SlGetChar();
  1964. switch(c) {
  1965. case SL_KEY_F5: // Force OEM HAL prompt
  1966. PromptOemHal = TRUE;
  1967. break;
  1968. case SL_KEY_F6: // Force OEM SCSI prompt
  1969. PromptOemScsi = TRUE;
  1970. }
  1971. }
  1972. } while (EndTime > ArcGetRelativeTime());
  1973. }
  1974. SCSI_INSERT_STATUS
  1975. SlInsertScsiDevice(
  1976. IN ULONG Ordinal,
  1977. OUT PDETECTED_DEVICE *pScsiDevice
  1978. )
  1979. /*++
  1980. Routine Description:
  1981. This routine
  1982. Arguments:
  1983. Ordinal - Supplies the 0-based ordinal of the Scsi device
  1984. to insert (based on order listed in [Scsi.Load]
  1985. section of txtsetup.sif). If the Scsi device is a third party
  1986. driver, then Ordinal is -1.
  1987. pScsiDevice - Receives a pointer to the inserted DETECTED_DEVICE structure,
  1988. the existing structure, or NULL.
  1989. Return Value:
  1990. ScsiInsertError - Not enough memory to allocate a new DETECTED_DEVICE.
  1991. ScsiInsertNewEntry - A new entry was inserted into the DETECTED_DEVICE list.
  1992. ScsiInsertExisting - An existing entry was found that matched the specified
  1993. ordinal, so we returned this entry.
  1994. --*/
  1995. {
  1996. PDETECTED_DEVICE prev, cur;
  1997. if(Ordinal == (ULONG)-1) {
  1998. //
  1999. // This is a third-party driver, so find the end of the linked list
  2000. // (we want to preserve the order in which the user specifies the drivers).
  2001. //
  2002. for(prev=BlLoaderBlock->SetupLoaderBlock->ScsiDevices, cur = NULL;
  2003. prev && prev->Next;
  2004. prev=prev->Next);
  2005. } else {
  2006. //
  2007. // Find the insertion point in the linked list for this driver,
  2008. // based on its ordinal. (Note that we will insert all supported drivers
  2009. // before any third-party ones, since (ULONG)-1 = maximum unsigned long value)
  2010. //
  2011. for(prev = NULL, cur = BlLoaderBlock->SetupLoaderBlock->ScsiDevices;
  2012. cur && (Ordinal > cur->Ordinal);
  2013. prev = cur, cur = cur->Next);
  2014. }
  2015. if(cur && (cur->Ordinal == Ordinal)) {
  2016. //
  2017. // We found an existing entry for this driver
  2018. //
  2019. *pScsiDevice = cur;
  2020. return ScsiInsertExisting;
  2021. }
  2022. if(!(*pScsiDevice = BlAllocateHeap(sizeof(DETECTED_DEVICE)))) {
  2023. return ScsiInsertError;
  2024. }
  2025. (*pScsiDevice)->Next = cur;
  2026. if(prev) {
  2027. prev->Next = *pScsiDevice;
  2028. } else {
  2029. BlLoaderBlock->SetupLoaderBlock->ScsiDevices = *pScsiDevice;
  2030. }
  2031. (*pScsiDevice)->Ordinal = Ordinal;
  2032. return ScsiInsertNewEntry;
  2033. }
  2034. ARC_STATUS
  2035. SlLoadBusExtender(
  2036. IN PVOID Inf
  2037. )
  2038. /*++
  2039. Routine Description:
  2040. Loads all known extender drivers.
  2041. Arguments:
  2042. Inf - Supplies a handle to the INF file.
  2043. Return Value:
  2044. ESUCCESS if all drivers were loaded successfully/no errors encountered
  2045. --*/
  2046. {
  2047. return( SlLoadSection(Inf,"Extenders",FALSE) );
  2048. }