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

4300 lines
136 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. oemdisk.c
  5. Abstract:
  6. Provides routines for handling OEM disks for video, SCSI miniport, and HAL.
  7. Currently used only on ARC machines.
  8. Author:
  9. John Vert (jvert) 4-Dec-1993
  10. Revision History:
  11. John Vert (jvert) 4-Dec-1993
  12. created
  13. Mandar Gokhale (mandarg) 12-July-2002
  14. 1. Added functionality to load multiple drivers from an OEM source device
  15. using single txtsetup.oem file. (Adding DriverLoadList key to the [Defaults]
  16. section.
  17. 2. Re-factoring of SlLoadOemScsiDriversFromOemSources(..).
  18. --*/
  19. #include <setupbat.h>
  20. #include "setupldr.h"
  21. #include "stdio.h"
  22. #include <ctype.h>
  23. #ifdef i386
  24. #include <bldrx86.h>
  25. #endif
  26. #if DBG
  27. #define DIAGOUT(x) SlPrint x
  28. #else
  29. #define DIAGOUT(x)
  30. #endif
  31. #if defined(EFI)
  32. #include "bootefi.h"
  33. #endif
  34. BOOLEAN PromptOemHal=FALSE;
  35. BOOLEAN PromptOemScsi=FALSE;
  36. BOOLEAN PromptOemVideo=FALSE;
  37. PVOID PreInstallOemInfHandle = NULL;
  38. //
  39. // Floppy disks which need to be treated as
  40. // as virtual floppies
  41. //
  42. const static ULONG VirtualFloppyStart = 1;
  43. const static ULONG MinimumFloppiesToScan = 2;
  44. #ifdef ARCI386
  45. BOOLEAN PromptOemKeyboard=FALSE;
  46. #endif
  47. PCHAR FloppyDiskPath;
  48. ULONG FloppyNumber=0;
  49. ULONG IsSuperFloppy=0;
  50. extern PCHAR BootPath;
  51. extern PCHAR BootDevice;
  52. extern ULONG BootDeviceId;
  53. extern PVOID InfFile;
  54. typedef struct _MENU_ITEM_DATA {
  55. PVOID InfFile;
  56. PCHAR SectionName;
  57. ULONG Index;
  58. PTCHAR Description;
  59. PCHAR Identifier;
  60. } MENU_ITEM_DATA, *PMENU_ITEM_DATA;
  61. typedef enum _OEMFILETYPE {
  62. OEMSCSI,
  63. OEMHAL,
  64. OEMOTHER
  65. } OEMFILETYPE, *POEMFILETYPE;
  66. //
  67. // Define how many lines of SCSI adapters we can list.
  68. //
  69. #define MAX_SCSI_MINIPORT_COUNT 4
  70. //
  71. // private function prototypes
  72. //
  73. ULONG
  74. SlpAddSectionToMenu(
  75. IN PVOID InfHandle,
  76. IN PCHAR SectionName,
  77. IN PSL_MENU Menu
  78. );
  79. BOOLEAN
  80. SlpOemDiskette(
  81. IN POEM_SOURCE_DEVICE OemSourceDevice,
  82. IN PCHAR ComponentName,
  83. IN OEMFILETYPE ComponentType,
  84. IN TYPE_OF_MEMORY MemoryType,
  85. IN ULONG MenuHeaderId,
  86. OUT PDETECTED_DEVICE DetectedDevice,
  87. OUT PVOID * ImageBase,
  88. OUT OPTIONAL PCHAR * ImageName,
  89. OUT OPTIONAL PTCHAR * DriverDescription,
  90. IN BOOLEAN AllowUserSelection,
  91. IN PTCHAR PreInstallComponentDescription,
  92. OUT PPNP_HARDWARE_ID* HardwareIdDatabase,
  93. IN PCHAR DriverDir,
  94. IN BOOLEAN InsertDevice,
  95. IN OPTIONAL PCSTR DriverIdString
  96. );
  97. BOOLEAN
  98. SlpSelectHardware(
  99. IN POEM_SOURCE_DEVICE SourceDevice,
  100. IN PCHAR ComponentName,
  101. IN OEMFILETYPE ComponentType,
  102. IN TYPE_OF_MEMORY MemoryType,
  103. IN ULONG MenuHeaderId,
  104. IN ULONG OemMenuHeaderId,
  105. OUT PDETECTED_DEVICE DetectedDevice,
  106. OUT PVOID * ImageBase,
  107. OUT OPTIONAL PCHAR * ImageName,
  108. OUT OPTIONAL PTCHAR * DriverDescription,
  109. IN BOOLEAN AllowUserSelection,
  110. IN PTCHAR PreInstallComponentDescription,
  111. IN BOOLEAN PreInstallOemComponent,
  112. OUT PPNP_HARDWARE_ID* HardwareIdDatabase
  113. );
  114. BOOLEAN
  115. SlpOemInfSelection(
  116. IN POEM_SOURCE_DEVICE OemSourceDevice,
  117. IN PVOID OemInfHandle,
  118. IN PCHAR ComponentName,
  119. IN PCHAR SelectedId,
  120. IN PTCHAR ItemDescription,
  121. OUT PDETECTED_DEVICE Device,
  122. OUT PPNP_HARDWARE_ID* HardwareIdDatabase,
  123. IN PCHAR DriverDir
  124. );
  125. VOID
  126. SlpInitDetectedDevice(
  127. IN PDETECTED_DEVICE Device,
  128. IN PCHAR IdString,
  129. IN PTCHAR Description,
  130. IN BOOLEAN ThirdPartyOptionSelected
  131. );
  132. PDETECTED_DEVICE_REGISTRY
  133. SlpInterpretOemRegistryData(
  134. IN PVOID InfHandle,
  135. IN PCHAR SectionName,
  136. IN ULONG Line,
  137. IN HwRegistryType ValueType
  138. );
  139. BOOLEAN
  140. FoundFloppyDiskCallback(
  141. IN PCONFIGURATION_COMPONENT_DATA Component
  142. );
  143. BOOLEAN
  144. SuperFloppyCallback(
  145. IN PCONFIGURATION_COMPONENT_DATA Component
  146. );
  147. int
  148. SlpFindStringInTable(
  149. IN PCHAR String,
  150. IN PCHAR *StringTable
  151. );
  152. //
  153. // FileTypeNames -- keep in sync with HwFileType enum!
  154. //
  155. PCHAR FileTypeNames[HwFileMax] = { "driver", "port" , "class", "inf",
  156. "dll" , "detect", "hal", "catalog"
  157. };
  158. //
  159. // RegistryTypeNames -- keep in sync with HwRegistryType enum!
  160. //
  161. PCHAR RegistryTypeNames[HwRegistryMax] = { "REG_DWORD", "REG_BINARY", "REG_SZ",
  162. "REG_EXPAND_SZ", "REG_MULTI_SZ"
  163. };
  164. ULONG RegistryTypeMap[HwRegistryMax] = { REG_DWORD, REG_BINARY, REG_SZ,
  165. REG_EXPAND_SZ, REG_MULTI_SZ
  166. };
  167. //
  168. // global scratch buffer for work
  169. //
  170. UCHAR ScratchBuffer[256];
  171. VOID
  172. SlPromptOemScsi(
  173. IN POEM_SOURCE_DEVICE ScsiSourceDevice,
  174. IN BOOLEAN AllowUserSelection,
  175. OUT POEMSCSIINFO *pOemScsiInfo
  176. )
  177. /*++
  178. Routine Description:
  179. Provides the user interface and logic for allowing the user to manually select
  180. SCSI adapters from the main INF file or the INF file on an OEM driver disk.
  181. Arguments:
  182. ScsiSourceDevice - The OEM_SOURCE_DEVICE from which the the drivers need to
  183. be loaded.
  184. AllowUserSelection - Whether user can interact while selecting the driver
  185. from txtsetup.oem driver list.
  186. pOemScsiInfo - Returns a linked list containing info about any third-party scsi
  187. drivers selected.
  188. Return Value:
  189. none.
  190. --*/
  191. {
  192. PVOID OemScsiBase;
  193. PTCHAR MessageString, ScsiDescription, MnemonicText;
  194. PCHAR OemScsiName;
  195. BOOLEAN Success, bFirstTime = TRUE, bRepaint;
  196. ULONG x, y1, y2, ScsiDriverCount, NumToSkip;
  197. ULONG c;
  198. TCHAR Mnemonic;
  199. POEMSCSIINFO NewOemScsi, CurOemScsi;
  200. PDETECTED_DEVICE ScsiDevice;
  201. ULONG OemScsiDriverCount = 0;
  202. PPREINSTALL_DRIVER_INFO CurrentDriver;
  203. CurrentDriver = PreinstallDriverList;
  204. *pOemScsiInfo = CurOemScsi = NULL;
  205. MnemonicText = BlFindMessage(SL_SCSI_SELECT_MNEMONIC);
  206. Mnemonic = (TCHAR)_totupper(MnemonicText[0]);
  207. bRepaint = TRUE;
  208. Success = FALSE;
  209. while(1) {
  210. #ifdef EFI
  211. //
  212. // disable efi watchdog
  213. //
  214. DisableEFIWatchDog();
  215. #endif
  216. if( AllowUserSelection ) {
  217. if(bRepaint) {
  218. SlClearClientArea();
  219. if(bFirstTime) {
  220. MessageString = BlFindMessage(SL_SCSI_SELECT_MESSAGE_1);
  221. } else if(Success) {
  222. MessageString = BlFindMessage(SL_SCSI_SELECT_MESSAGE_3);
  223. } else {
  224. MessageString = BlFindMessage(SL_SCSI_SELECT_ERROR);
  225. }
  226. x = 1;
  227. y1 = 4;
  228. SlGenericMessageBox(0, NULL, MessageString, &x, &y1, &y2, FALSE);
  229. y1 = y2 + 1;
  230. x = 4;
  231. //
  232. // Count all currently 'detected' SCSI devices.
  233. //
  234. for(ScsiDriverCount = 0, OemScsiDriverCount = 0, ScsiDevice = BlLoaderBlock->SetupLoaderBlock->ScsiDevices;
  235. ScsiDevice;
  236. ScsiDevice = ScsiDevice->Next) {
  237. ScsiDriverCount++;
  238. if( ScsiDevice->ThirdPartyOptionSelected ) {
  239. OemScsiDriverCount++;
  240. }
  241. }
  242. //
  243. // Display each loaded OEM miniport driver description.
  244. //
  245. if(OemScsiDriverCount) {
  246. if(OemScsiDriverCount > MAX_SCSI_MINIPORT_COUNT) {
  247. NumToSkip = ScsiDriverCount - (OemScsiDriverCount - MAX_SCSI_MINIPORT_COUNT);
  248. //
  249. // Display ellipses to indicate that top entries have scrolled out of view
  250. //
  251. SlGenericMessageBox(0,
  252. NULL,
  253. TEXT("..."),
  254. &x,
  255. &y1,
  256. &y2,
  257. FALSE
  258. );
  259. y1 = y2 + 1;
  260. } else {
  261. NumToSkip = ScsiDriverCount - OemScsiDriverCount;
  262. y1++;
  263. }
  264. ScsiDevice = BlLoaderBlock->SetupLoaderBlock->ScsiDevices;
  265. while(NumToSkip && ScsiDevice) {
  266. ScsiDevice = ScsiDevice->Next;
  267. NumToSkip--;
  268. }
  269. while(ScsiDevice) {
  270. SlGenericMessageBox(0,
  271. NULL,
  272. ScsiDevice->Description,
  273. &x,
  274. &y1,
  275. &y2,
  276. FALSE
  277. );
  278. y1 = y2 + 1;
  279. ScsiDevice = ScsiDevice->Next;
  280. }
  281. } else {
  282. y1++;
  283. SlGenericMessageBox(0,
  284. NULL,
  285. BlFindMessage(SL_TEXT_ANGLED_NONE),
  286. &x,
  287. &y1,
  288. &y2,
  289. FALSE
  290. );
  291. y1 = y2 + 1;
  292. }
  293. x = 1;
  294. y1++;
  295. SlGenericMessageBox(0,
  296. NULL,
  297. BlFindMessage(SL_SCSI_SELECT_MESSAGE_2),
  298. &x,
  299. &y1,
  300. &y2,
  301. FALSE
  302. );
  303. SlWriteStatusText(BlFindMessage(SL_SCSI_SELECT_PROMPT));
  304. bRepaint = FALSE;
  305. }
  306. c = SlGetChar();
  307. } else {
  308. c = ( CurrentDriver != NULL )? Mnemonic : ASCI_CR;
  309. }
  310. #ifdef EFI
  311. //
  312. // reset efi watchdog
  313. //
  314. SetEFIWatchDog(EFI_WATCHDOG_TIMEOUT);
  315. #endif
  316. switch (c) {
  317. case SL_KEY_F3:
  318. SlConfirmExit();
  319. bRepaint = TRUE;
  320. break;
  321. case ASCI_CR:
  322. return;
  323. default:
  324. if(toupper(c) == Mnemonic) {
  325. bFirstTime = FALSE;
  326. bRepaint = TRUE;
  327. Success = SlpSelectHardware(ScsiSourceDevice,
  328. "SCSI",
  329. OEMSCSI,
  330. LoaderBootDriver,
  331. SL_PROMPT_SCSI,
  332. SL_PROMPT_OEM_SCSI,
  333. NULL,
  334. &OemScsiBase,
  335. &OemScsiName,
  336. &ScsiDescription,
  337. AllowUserSelection,
  338. (AllowUserSelection)? NULL : CurrentDriver->DriverDescription,
  339. (BOOLEAN)((AllowUserSelection)? FALSE : CurrentDriver->OemDriver),
  340. &BlLoaderBlock->SetupLoaderBlock->HardwareIdDatabase);
  341. if(!AllowUserSelection) {
  342. CurrentDriver = CurrentDriver->Next;
  343. }
  344. if(Success) {
  345. //
  346. // Check to see if the driver loaded was an OEM SCSI driver. If so,
  347. // then add an OemScsiInfo entry onto the end of our list.
  348. //
  349. if(OemScsiBase) {
  350. NewOemScsi = BlAllocateHeap(sizeof(OEMSCSIINFO));
  351. if(!NewOemScsi) {
  352. SlNoMemoryError();
  353. }
  354. if(CurOemScsi) {
  355. CurOemScsi->Next = NewOemScsi;
  356. } else {
  357. *pOemScsiInfo = NewOemScsi;
  358. }
  359. CurOemScsi = NewOemScsi;
  360. NewOemScsi->ScsiBase = OemScsiBase;
  361. NewOemScsi->ScsiName = OemScsiName;
  362. NewOemScsi->Next = NULL;
  363. }
  364. }
  365. }
  366. }
  367. }
  368. }
  369. BOOLEAN
  370. SlLoadOemScsiDriversUnattended(
  371. IN POEM_SOURCE_DEVICE OemSourceDevice,
  372. IN PVOID InfHandle,
  373. IN PCHAR ParamsSectionName,
  374. IN PCHAR RootDirKeyName,
  375. IN PCHAR BootDriversKeyName,
  376. IN POEMSCSIINFO* ScsiInfo,
  377. OUT PPNP_HARDWARE_ID* HardwareIdDatabase
  378. )
  379. /*++
  380. Routine Description:
  381. Loads the boot drivers (SCSI miniport only) specified in inf file
  382. in an unattended fashion
  383. Arguments:
  384. OemSourceDevice - The OEM_SOURCE_DEVICE which contains the scsi
  385. mass storage drivers that need to be loaded.
  386. InfHandle - Handle to inf file (e.g. winnt.sif)
  387. ParamsSectionName - The section name which contains the boot driver
  388. keys and values.
  389. RootDirKeyName - The key name whose value points to the root directory
  390. under which all the different directories are present
  391. BootDriversKeyName - The key name which consits of multiple values of
  392. one level subdirectory name which are present under
  393. the specified root directory.
  394. ScsiInfo - Returns a linked list containing info about any third-party scsi
  395. drivers loaded.
  396. HardwareIdDatabase - Hardware Ids of the device which the loaded driver supports
  397. Return Value:
  398. TRUE, if successful otherwise FALSE
  399. --*/
  400. {
  401. BOOLEAN LoadResult = FALSE;
  402. if (InfHandle) {
  403. POEMSCSIINFO CurrOemScsi = NULL;
  404. ULONG Index = 0;
  405. PCHAR DriverDir = SlGetSectionKeyIndex(InfHandle,
  406. ParamsSectionName,
  407. BootDriversKeyName,
  408. Index);
  409. PCHAR DriverRoot = SlGetSectionKeyIndex(InfHandle,
  410. ParamsSectionName,
  411. RootDirKeyName,
  412. 0);
  413. ULONG RootLength = DriverRoot ? (ULONG)strlen(DriverRoot) : 0;
  414. //
  415. // DriverRoot and DriverDir need to have valid values
  416. // in specified ParamsSectionName
  417. //
  418. LoadResult = (DriverDir && DriverRoot) ? TRUE : FALSE;
  419. while (DriverDir && LoadResult) {
  420. CHAR FullDriverDir[256];
  421. DETECTED_DEVICE DetectedDevice = {0};
  422. PVOID ImageBase = NULL;
  423. PCHAR ImageName = NULL;
  424. PTCHAR DriverDescription = NULL;
  425. //
  426. // Create the full path of the driver directory relative
  427. // to the boot directory
  428. //
  429. if (RootLength) {
  430. strcpy(FullDriverDir, DriverRoot);
  431. strcat(FullDriverDir, "\\");
  432. } else {
  433. FullDriverDir[0] = 0;
  434. }
  435. strcat(FullDriverDir, DriverDir);
  436. //
  437. // Load the driver and related files, in an unattended manner
  438. //
  439. LoadResult = SlpOemDiskette(OemSourceDevice,
  440. "SCSI",
  441. OEMSCSI,
  442. LoaderBootDriver,
  443. 0,
  444. &DetectedDevice,
  445. &ImageBase,
  446. &ImageName,
  447. &DriverDescription,
  448. FALSE,
  449. NULL,
  450. HardwareIdDatabase,
  451. FullDriverDir,
  452. TRUE,
  453. NULL);
  454. if (LoadResult) {
  455. //
  456. // If the load was successful, then create and add the information
  457. // ScsiInfo
  458. //
  459. if (ImageBase && ScsiInfo) {
  460. POEMSCSIINFO NewScsi = (POEMSCSIINFO)BlAllocateHeap(sizeof(OEMSCSIINFO));
  461. if (!NewScsi) {
  462. SlNoMemoryError();
  463. return FALSE;
  464. }
  465. RtlZeroMemory(NewScsi, sizeof(OEMSCSIINFO));
  466. NewScsi->ScsiBase = ImageBase;
  467. NewScsi->ScsiName = ImageName;
  468. if (CurrOemScsi) {
  469. CurrOemScsi->Next = NewScsi;
  470. } else {
  471. *ScsiInfo = NewScsi;
  472. }
  473. CurrOemScsi = NewScsi;
  474. }
  475. //
  476. // Get the next driver directory to process
  477. //
  478. Index++;
  479. DriverDir = SlGetSectionKeyIndex(InfHandle,
  480. ParamsSectionName,
  481. BootDriversKeyName,
  482. Index);
  483. }
  484. }
  485. }
  486. return LoadResult;
  487. }
  488. VOID
  489. SlPromptOemHal(
  490. IN POEM_SOURCE_DEVICE HalSourceDevice,
  491. IN BOOLEAN AllowUserSelection,
  492. OUT PVOID *HalBase,
  493. OUT PCHAR *HalName
  494. )
  495. /*++
  496. Routine Description:
  497. Provides the user interface and logic for allowing the user to manually select
  498. a HAL from the main INF file or the INF file on an OEM driver disk.
  499. Arguments:
  500. HalSourceDevice - The OEM_SOURCE_DEVICE which contains the HAL that needs
  501. to be loaded.
  502. AllowUserSelection - Indicates whether user can interact while selecting the
  503. OEM hal from the list specified in txtsetup.oem.
  504. HalBase - Returns the address where the HAL was loaded into memory.
  505. HalName - Returns the name of the HAL that was loaded.
  506. Return Value:
  507. ESUCCESS - HAL successfully loaded.
  508. --*/
  509. {
  510. BOOLEAN Success;
  511. do {
  512. Success = SlpSelectHardware(HalSourceDevice,
  513. "Computer",
  514. OEMHAL,
  515. LoaderHalCode,
  516. SL_PROMPT_HAL,
  517. SL_PROMPT_OEM_HAL,
  518. &BlLoaderBlock->SetupLoaderBlock->ComputerDevice,
  519. HalBase,
  520. HalName,
  521. NULL,
  522. AllowUserSelection,
  523. ComputerType,
  524. OemHal,
  525. &BlLoaderBlock->SetupLoaderBlock->HardwareIdDatabase);
  526. } while ( !Success );
  527. }
  528. VOID
  529. SlPromptOemVideo(
  530. IN POEM_SOURCE_DEVICE VideoSourceDevice,
  531. IN BOOLEAN AllowUserSelection,
  532. OUT PVOID *VideoBase,
  533. OUT PCHAR *VideoName
  534. )
  535. /*++
  536. Routine Description:
  537. Provides the user interface and logic for allowing the user to manually select
  538. a video adapter from the main INF file or the INF file on an OEM driver disk.
  539. Arguments:
  540. VideoSourceDevice - The OEM_SOURCE_DEVICE which contains the video driver that
  541. needs to be loaded.
  542. AllowUserSelection - Indicates whether user can interact while selecting the
  543. driver from the list specified in txtsetup.oem.
  544. VideoBase - Returns the address where the video driver was loaded
  545. VideoName - Returns a pointer to the name of the video driver
  546. Return Value:
  547. None.
  548. --*/
  549. {
  550. BOOLEAN Success;
  551. do {
  552. Success = SlpSelectHardware(VideoSourceDevice,
  553. "display",
  554. OEMOTHER,
  555. LoaderBootDriver,
  556. SL_PROMPT_VIDEO,
  557. SL_PROMPT_OEM_VIDEO,
  558. &BlLoaderBlock->SetupLoaderBlock->VideoDevice,
  559. VideoBase,
  560. VideoName,
  561. NULL,
  562. AllowUserSelection,
  563. NULL,
  564. FALSE,
  565. &BlLoaderBlock->SetupLoaderBlock->HardwareIdDatabase);
  566. } while ( !Success );
  567. }
  568. BOOLEAN
  569. SlpSelectHardware(
  570. IN POEM_SOURCE_DEVICE SourceDevice,
  571. IN PCHAR ComponentName,
  572. IN OEMFILETYPE ComponentType,
  573. IN TYPE_OF_MEMORY MemoryType,
  574. IN ULONG MenuHeaderId,
  575. IN ULONG OemMenuHeaderId,
  576. OUT OPTIONAL PDETECTED_DEVICE DetectedDevice,
  577. OUT PVOID *ImageBase,
  578. OUT OPTIONAL PCHAR *ImageName,
  579. OUT OPTIONAL PTCHAR *DriverDescription,
  580. IN BOOLEAN AllowUserSelection,
  581. IN PTCHAR PreInstallComponentDescription,
  582. IN BOOLEAN PreInstallOemComponent,
  583. OUT PPNP_HARDWARE_ID* HardwareIdDatabase
  584. )
  585. /*++
  586. Routine Description:
  587. Present the user with a menu of options for the selected device class.
  588. This menu will consist of options listed in the main inf plus a single
  589. oem option if one is currently selected, plus additional items in the
  590. system partition inf for the component if specified (ARC machines).
  591. When the user makes a selection, forget any previous OEM option (except
  592. for SCSI). If the user selects an option supplied by us, set up the
  593. SELECTED_DEVICE structure and return. Otherwise prompt for a manufacturer-
  594. supplied diskette.
  595. Arguments:
  596. SourceDevice - The device which contains the driver/hal that needs to
  597. be loaded.
  598. ComponentName - Supplies the name of the component to be presented.
  599. ComponentType - Supplies the type of the component (HAL, SCSI, or Other)
  600. MemoryType - Supplies the type of memory used to load the image.
  601. MenuHeaderId - Supplies the ID of the menu header to be displayed
  602. OemMenuHeaderId - Supplies the ID of the menu header to be displayed
  603. when an OEM selection is to be made.
  604. DetectedDevice - returns the DeviceId of the selected device. If an
  605. OEM diskette is required, the necessary OEM structures will
  606. be allocated and filled in. (This field is ignored for SCSI
  607. components.)
  608. ImageBase - Returns the base of the image that was loaded.
  609. ImageName - Returns the filename of the image.
  610. DriverDescription - If specified, returns the description of the loaded
  611. device.
  612. AllowUserSelection - Indicates whether or not user is allowed to select
  613. a driver. This flag is typically set to FALSE when
  614. pre-installing components defined in unattend.txt.
  615. PreInstallComponentDescription - In the pre-install mode, points to the string
  616. that identifies the component to pre-install.
  617. It is NULL if AllowUserSelction is TRUE.
  618. PreInstallOemComponent - In the pre-install mode, this flag indicates
  619. whether or not the component to pre-install is
  620. an OEM or RETAIL component.
  621. Return Value:
  622. TRUE - Success
  623. FALSE - The user has escaped out of the dialog
  624. --*/
  625. {
  626. PSL_MENU Menu = NULL;
  627. ULONG Selection;
  628. ULONG OtherSelection = 0;
  629. PTCHAR OtherSelectionName = (PTCHAR)ScratchBuffer; // use global buffer to save stack
  630. PTCHAR p;
  631. ULONG c;
  632. PCHAR AdapterName;
  633. CHAR Buffer[80];
  634. PCHAR FileName;
  635. PTCHAR FileDescription;
  636. ARC_STATUS Status;
  637. BOOLEAN b;
  638. ULONG Ordinal;
  639. SCSI_INSERT_STATUS sis;
  640. if( AllowUserSelection ) {
  641. if(ComponentType != OEMSCSI) {
  642. Menu = SlCreateMenu();
  643. if (Menu==NULL) {
  644. SlNoMemoryError();
  645. return(FALSE);
  646. }
  647. //
  648. // Build a list of options containing the drivers we ship and the
  649. // currently selected OEM option (if any).
  650. //
  651. c = SlpAddSectionToMenu(InfFile,
  652. ComponentName,
  653. Menu);
  654. //
  655. // Add selection for "other"
  656. //
  657. _tcsncpy(OtherSelectionName,
  658. BlFindMessage(SL_TEXT_OTHER_DRIVER),
  659. sizeof(ScratchBuffer)/sizeof(TCHAR) - 1
  660. );
  661. OtherSelectionName[sizeof(ScratchBuffer)/sizeof(TCHAR) - 1] = TEXT('\0');
  662. //
  663. // Use text up to the first CR or LF.
  664. //
  665. for(p = OtherSelectionName; *p; p++) {
  666. if((*p == TEXT('\n')) || (*p == TEXT('\r'))) {
  667. *p = TEXT('\0');
  668. break;
  669. }
  670. }
  671. OtherSelection = SlAddMenuItem(Menu,
  672. OtherSelectionName,
  673. (PVOID)-1,
  674. 0);
  675. //
  676. // Default is "other"
  677. //
  678. Selection = OtherSelection;
  679. } else {
  680. //
  681. // For SCSI devices we don't display any list of drivers for the user to choose.
  682. // We just prompt for the OEM disk, this is because we always load all SCSI drivers
  683. // in the NT product, due to pnp requirements.
  684. //
  685. //
  686. // Default is "other"
  687. //
  688. Selection = OtherSelection;
  689. }
  690. } else {
  691. //
  692. // This is a pre-install. Find out if the component to pre-install
  693. // is RETAIL or OEM.
  694. //
  695. OtherSelection = SlCountLinesInSection( InfFile,
  696. ComponentName );
  697. if( PreInstallOemComponent ) {
  698. //
  699. // Pre-installing an OEM component
  700. //
  701. Selection = OtherSelection;
  702. } else {
  703. //
  704. // Pre-installing a RETAIL component
  705. //
  706. PCHAR q;
  707. q = SlPreInstallGetComponentName( InfFile,
  708. ComponentName,
  709. PreInstallComponentDescription );
  710. if (q==NULL) {
  711. //
  712. // we have enumerated the entire section without finding a
  713. // match, return failure.
  714. //
  715. SlFatalError(SL_BAD_UNATTENDED_SCRIPT_FILE,
  716. PreInstallComponentDescription,
  717. SlCopyStringAT(ComponentName),
  718. TEXT("txtsetup.sif"));
  719. goto SelectionAbort;
  720. }
  721. Selection = SlGetSectionKeyOrdinal( InfFile,
  722. ComponentName,
  723. q );
  724. }
  725. }
  726. //
  727. // Allow the user to interact with the menu
  728. //
  729. while (1) {
  730. if( AllowUserSelection ) {
  731. SlClearClientArea();
  732. p = BlFindMessage(SL_SELECT_DRIVER_PROMPT);
  733. if (p) {
  734. SlWriteStatusText(p);
  735. }
  736. if(ComponentType != OEMSCSI) {
  737. c = SlDisplayMenu(MenuHeaderId,
  738. Menu,
  739. &Selection);
  740. } else {
  741. //
  742. // For SCSI devices, we don't display any list of driver for the user to chose
  743. //
  744. c = ASCI_CR;
  745. }
  746. } else {
  747. c = ASCI_CR;
  748. }
  749. switch (c) {
  750. case SL_KEY_F3:
  751. SlConfirmExit();
  752. break;
  753. case ASCI_ESC:
  754. goto SelectionAbort;
  755. case ASCI_CR:
  756. if (Selection == OtherSelection) {
  757. //
  758. // User selected "other" Prompt for OEM diskette
  759. //
  760. b = SlpOemDiskette(SourceDevice,
  761. ComponentName,
  762. ComponentType,
  763. MemoryType,
  764. OemMenuHeaderId,
  765. DetectedDevice,
  766. ImageBase,
  767. ImageName,
  768. DriverDescription,
  769. AllowUserSelection,
  770. PreInstallComponentDescription,
  771. HardwareIdDatabase,
  772. NULL,
  773. TRUE,
  774. NULL);
  775. SlClearClientArea();
  776. SlWriteStatusText(TEXT(""));
  777. return(b);
  778. } else {
  779. //
  780. // User selected a built-in. Go ahead and load
  781. // it here.
  782. //
  783. if(ComponentType == OEMHAL) {
  784. //
  785. // We are looking for a HAL. If we're doing a remote
  786. // boot, look in the [Hal] section. Otherwise, look in
  787. // the [Hal.Load] section. (Local setup has a separate
  788. // section to minimize the number of HAL binaries that
  789. // need to be on the boot floppies.)
  790. //
  791. strcpy(Buffer, BlBootingFromNet ? "Hal" : "Hal.Load");
  792. } else {
  793. sprintf(Buffer, "%s.Load", ComponentName );
  794. }
  795. AdapterName = SlGetKeyName(InfFile,
  796. ComponentName,
  797. Selection
  798. );
  799. if(AdapterName==NULL) {
  800. SlFatalError(SL_BAD_INF_FILE, TEXT("txtsetup.sif"), ENODEV);
  801. goto SelectionAbort;
  802. }
  803. FileName = SlGetIniValue(InfFile,
  804. Buffer,
  805. AdapterName,
  806. NULL);
  807. if((FileName==NULL) && (ComponentType == OEMHAL)) {
  808. FileName = SlGetIniValue(InfFile,
  809. "Hal",
  810. AdapterName,
  811. NULL);
  812. FileDescription = SlCopyString(BlFindMessage(SL_HAL_NAME));
  813. } else {
  814. #ifdef UNICODE
  815. FileDescription = SlGetIniValueW(
  816. #else
  817. FileDescription = SlGetIniValue(
  818. #endif
  819. InfFile,
  820. ComponentName,
  821. AdapterName,
  822. NULL);
  823. }
  824. if(FileName==NULL) {
  825. SlFatalError(SL_BAD_INF_FILE, TEXT("txtsetup.sif"), EBADF);
  826. goto SelectionAbort;
  827. }
  828. if(ARGUMENT_PRESENT(ImageName)) {
  829. *ImageName = FileName;
  830. }
  831. if(ARGUMENT_PRESENT(DriverDescription)) {
  832. *DriverDescription = FileDescription;
  833. }
  834. //
  835. // If we're doing OEM SCSI, then get a properly-inserted
  836. // DETECTED_DEVICE structure
  837. //
  838. if(ComponentType == OEMSCSI) {
  839. //
  840. // Find this adapter's ordinal within the Scsi.Load section of txtsetup.sif
  841. //
  842. Ordinal = SlGetSectionKeyOrdinal(InfFile, Buffer, AdapterName);
  843. if(Ordinal == SL_OEM_DEVICE_ORDINAL) {
  844. SlFatalError(SL_BAD_INF_FILE, TEXT("txtsetup.sif"), EINVAL);
  845. goto SelectionAbort;
  846. }
  847. //
  848. // Create a new detected device entry.
  849. //
  850. if((sis = SlInsertScsiDevice(Ordinal, &DetectedDevice)) == ScsiInsertError) {
  851. SlFriendlyError(ENOMEM, "SCSI detection", __LINE__, __FILE__);
  852. goto SelectionAbort;
  853. }
  854. if(sis == ScsiInsertExisting) {
  855. #if DBG
  856. //
  857. // Sanity check to make sure we're talking about the same driver
  858. //
  859. if(_stricmp(DetectedDevice->BaseDllName, FileName)) {
  860. SlError(400);
  861. goto SelectionAbort;
  862. }
  863. #endif
  864. }
  865. }
  866. DetectedDevice->IdString = AdapterName;
  867. DetectedDevice->Description = FileDescription;
  868. DetectedDevice->ThirdPartyOptionSelected = FALSE;
  869. DetectedDevice->FileTypeBits = 0;
  870. DetectedDevice->Files = NULL;
  871. DetectedDevice->BaseDllName = FileName;
  872. //
  873. // We only want to load the image if we're not doing SCSI.
  874. //
  875. if(ComponentType != OEMSCSI) {
  876. sprintf(Buffer, "%s%s", BootPath, FileName);
  877. SlGetDisk(FileName);
  878. #ifdef i386
  879. retryhal:
  880. #endif
  881. BlOutputLoadMessage(BootDevice, FileName, FileDescription);
  882. Status = BlLoadImage(BootDeviceId,
  883. MemoryType,
  884. Buffer,
  885. TARGET_IMAGE,
  886. ImageBase
  887. );
  888. #ifdef i386
  889. //
  890. // If the HAL didn't fit in the preferred range, reset the range to
  891. // all of memory and try again.
  892. //
  893. if ((Status == ENOMEM) &&
  894. ((BlUsableBase != 0) ||
  895. (BlUsableLimit != _16MB))) {
  896. BlUsableBase = 0;
  897. BlUsableLimit = _16MB;
  898. goto retryhal;
  899. }
  900. #endif
  901. } else {
  902. *ImageBase = NULL;
  903. Status = ESUCCESS;
  904. }
  905. }
  906. if (Status != ESUCCESS) {
  907. SlMessageBox(SL_FILE_LOAD_FAILED,Buffer,Status);
  908. goto SelectionAbort;
  909. }
  910. SlClearClientArea();
  911. SlWriteStatusText(TEXT(""));
  912. return(TRUE);
  913. default:
  914. break;
  915. }
  916. }
  917. SelectionAbort:
  918. SlClearClientArea();
  919. SlWriteStatusText(TEXT(""));
  920. return FALSE;
  921. }
  922. ARC_STATUS
  923. SlGetDriverTimeStampFromFile(
  924. IN ULONG DeviceId,
  925. IN PCHAR DriverPath,
  926. OUT PULONG TimeDateStamp
  927. )
  928. /*++
  929. Routine Description:
  930. Gets the driver's link time stamp from the the image
  931. header.
  932. Arguments:
  933. DeviceId : Device on which the driver file resides (e.g. floppy)
  934. DriverPath : Full qualified path of the driver file
  935. TimeDateStamp : Place holder to return the image header time stamp
  936. Return Value:
  937. ESUCCESS if successful, otherwise appropriate error code.
  938. --*/
  939. {
  940. ARC_STATUS Status = EINVAL;
  941. if (DriverPath && TimeDateStamp) {
  942. UCHAR UBuffer[SECTOR_SIZE * 2 + 256] = {0};
  943. UCHAR *Buffer = ALIGN_BUFFER(UBuffer);
  944. ULONG FileId = 0;
  945. //
  946. // open the file
  947. //
  948. Status = BlOpen(DeviceId, DriverPath, ArcOpenReadOnly, &FileId);
  949. if (Status == ESUCCESS) {
  950. ULONG BytesToRead = SECTOR_SIZE * 2;
  951. ULONG BytesRead = 0;
  952. //
  953. // read the first two sectors of the file
  954. //
  955. Status = BlRead(FileId, Buffer, BytesToRead, &BytesRead);
  956. if ((Status == ESUCCESS) && (BytesToRead == BytesRead)) {
  957. PIMAGE_NT_HEADERS ImgHdr = RtlImageNtHeader(Buffer);
  958. Status = EINVAL;
  959. if (ImgHdr) {
  960. *TimeDateStamp = ImgHdr->FileHeader.TimeDateStamp;
  961. Status = ESUCCESS;
  962. }
  963. }
  964. BlClose(FileId);
  965. }
  966. }
  967. return Status;
  968. }
  969. BOOLEAN
  970. SlRemoveInboxDriver(
  971. IN PCHAR DriverToRemove
  972. )
  973. /*++
  974. Routine Description:
  975. Removes the given driver name from list of the
  976. SCSI miniport devices that need to be loaded as default
  977. boot driver.
  978. Arguments:
  979. DriverToRemove : Driver base name, that needs to be removed
  980. Return Value:
  981. TRUE, if the driver was found and removed otherwise FALSE
  982. --*/
  983. {
  984. BOOLEAN Result = FALSE;
  985. if (DriverToRemove) {
  986. PDETECTED_DEVICE NodePtr = BlLoaderBlock->SetupLoaderBlock->ScsiDevices;
  987. PDETECTED_DEVICE PrevNode = NULL;
  988. while (NodePtr) {
  989. if (NodePtr->BaseDllName && !_stricmp(NodePtr->BaseDllName, DriverToRemove))
  990. break;
  991. PrevNode = NodePtr;
  992. NodePtr = NodePtr->Next;
  993. }
  994. if (NodePtr) {
  995. if (PrevNode) {
  996. PrevNode->Next = NodePtr->Next;
  997. Result = TRUE;
  998. } else {
  999. if (NodePtr == BlLoaderBlock->SetupLoaderBlock->ScsiDevices) {
  1000. BlLoaderBlock->SetupLoaderBlock->ScsiDevices = NULL;
  1001. Result = TRUE;
  1002. }
  1003. }
  1004. }
  1005. }
  1006. return Result;
  1007. }
  1008. ARC_STATUS
  1009. SlConstructDriverPath(
  1010. IN PDETECTED_DEVICE Device,
  1011. IN PCHAR DefaultPath,
  1012. OUT PCHAR FullPath
  1013. )
  1014. /*++
  1015. Routine Description:
  1016. Constructs a fully qualified driver path given the device node.
  1017. Arguments:
  1018. Device : The device for which the path needs to be created.
  1019. Defaultpath : Directory path to use, if device does not has file list.
  1020. FullPath : Placeholder to return the constructed path
  1021. Return Value:
  1022. ESUCCESS if path is constructed, otherwise a proper error code.
  1023. --*/
  1024. {
  1025. ARC_STATUS Status = EINVAL;
  1026. if (Device && FullPath) {
  1027. PDETECTED_DEVICE_FILE Node = Device->Files;
  1028. //
  1029. // locate the driver file
  1030. //
  1031. while (Node) {
  1032. HwFileType FileType = Node->FileType;
  1033. if((FileType == HwFilePort) || (FileType == HwFileClass) ||
  1034. (FileType == HwFileDriver) || (FileType == HwFileHal)) {
  1035. break;
  1036. }
  1037. Node = Node->Next;
  1038. }
  1039. if (Node && Node->Filename) {
  1040. *FullPath = '\0';
  1041. if (Node->Directory)
  1042. strcat(FullPath, Node->Directory);
  1043. //
  1044. // append separator only if directory-name does not have
  1045. // trailing separator or the the filename does
  1046. // not have a leading separator
  1047. //
  1048. if ((Node->Filename[0] != '\\') && (*FullPath) &&
  1049. (FullPath[strlen(FullPath) - 1] != '\\')) {
  1050. strcat(FullPath, "\\");
  1051. }
  1052. strcat(FullPath, Node->Filename);
  1053. Status = ESUCCESS;
  1054. } else {
  1055. if (DefaultPath && Device->BaseDllName) {
  1056. //
  1057. // default path has a valid trailing separator
  1058. //
  1059. strcpy(FullPath, DefaultPath);
  1060. strcat(FullPath, Device->BaseDllName);
  1061. Status = ESUCCESS;
  1062. }
  1063. }
  1064. if (Status != ESUCCESS)
  1065. *FullPath = '\0';
  1066. }
  1067. return Status;
  1068. }
  1069. VERSION_COMP_RESULT
  1070. SlCompareDriverVersion(
  1071. IN ULONG InboxDeviceId,
  1072. IN PDETECTED_DEVICE InboxDriver,
  1073. IN ULONG OemDeviceId,
  1074. IN PDETECTED_DEVICE OemDriver
  1075. )
  1076. /*++
  1077. Routine Description:
  1078. Compares the version of an inbox driver and oem driver
  1079. based on the link date-time stamp present in the image
  1080. header.
  1081. Arguments:
  1082. InboxDeviceId : Boot device ID
  1083. InboxDriver : Device containing inbox driver details
  1084. OemDeviceId : Oem device ID (either floppy or boot device)
  1085. OemDriver : Device containing OEM driver details
  1086. Return Value:
  1087. VersionErr if not able to get version information for the
  1088. drivers, otherwise one of the following appropriately :
  1089. VersionSame, VersionOemNew, VersionInboxNew
  1090. --*/
  1091. {
  1092. VERSION_COMP_RESULT Result = VersionError;
  1093. if (InboxDriver && OemDriver) {
  1094. CHAR FullPath[256];
  1095. ULONG InboxDateTime = 0, OemDateTime = 0;
  1096. ARC_STATUS Status;
  1097. Status = SlConstructDriverPath(InboxDriver, BootPath, FullPath);
  1098. if (Status == ESUCCESS) {
  1099. Status = SlGetDriverTimeStampFromFile(InboxDeviceId,
  1100. FullPath, &InboxDateTime);
  1101. if (Status == ESUCCESS) {
  1102. Status = SlConstructDriverPath(OemDriver, NULL, FullPath);
  1103. if (Status == ESUCCESS) {
  1104. Status = SlGetDriverTimeStampFromFile(OemDeviceId,
  1105. FullPath, &OemDateTime);
  1106. }
  1107. }
  1108. }
  1109. if ((Status == ESUCCESS) && InboxDateTime && OemDateTime) {
  1110. if (InboxDateTime != OemDateTime) {
  1111. Result = (InboxDateTime > OemDateTime) ?
  1112. VersionInboxNew : VersionOemNew;
  1113. } else {
  1114. Result = VersionSame;
  1115. }
  1116. }
  1117. }
  1118. return Result;
  1119. }
  1120. BOOLEAN
  1121. SlConfirmInboxDriverReplacement(
  1122. IN PTCHAR DriverName,
  1123. IN PTCHAR AdditionalInfo
  1124. )
  1125. /*++
  1126. Routine Description:
  1127. Puts up a dialog box on the screen giving information about
  1128. the same inbox driver and oem driver being loaded, asking
  1129. for user selection i.e. either OEM or INBOX driver.
  1130. Arguments:
  1131. DriverName : Driver name which is same for inbox and OEM
  1132. AdditionalInfo : Which driver is newer i.e. either OEM or
  1133. Inbox or nothing if could not determine which driver is
  1134. newer.
  1135. Return Value:
  1136. TRUE if the user selected to replace default driver with OEM
  1137. driver, otherwise return FALSE indicating that user wants
  1138. to use inbox driver.
  1139. --*/
  1140. {
  1141. ULONG KeyPressed = 0;
  1142. PTCHAR MnemonicText = BlFindMessage(SL_SCSI_SELECT_MNEMONIC);
  1143. ULONG Mnemonic = MnemonicText ? toupper(MnemonicText[0]) : 'S';
  1144. if (AdditionalInfo) {
  1145. ULONG Len = (ULONG)_tcslen(AdditionalInfo);
  1146. if ((Len >= 2) && (AdditionalInfo[Len-2] == TEXT('\r')) &&
  1147. (AdditionalInfo[Len-1] == TEXT('\n'))) {
  1148. AdditionalInfo[Len-2] = TEXT('\0');
  1149. }
  1150. }
  1151. if (DriverName) {
  1152. SlClearClientArea();
  1153. SlDisplayMessageBox(SL_OEM_DRIVERINFO, AdditionalInfo, DriverName);
  1154. SlWriteStatusText(BlFindMessage(SL_CONFIRM_OEMDRIVER));
  1155. #ifdef EFI
  1156. //
  1157. // disable watchdog timer when waiting for user response
  1158. //
  1159. DisableEFIWatchDog();
  1160. #endif
  1161. do {
  1162. KeyPressed = SlGetChar();
  1163. KeyPressed = toupper(KeyPressed);
  1164. }
  1165. while ((KeyPressed != ASCI_CR) && (KeyPressed != Mnemonic));
  1166. #ifdef EFI
  1167. //
  1168. // reset efi watchdog
  1169. //
  1170. SetEFIWatchDog(EFI_WATCHDOG_TIMEOUT);
  1171. #endif
  1172. SlClearClientArea();
  1173. SlWriteStatusText(TEXT(""));
  1174. }
  1175. return (KeyPressed == Mnemonic) ? TRUE : FALSE;
  1176. }
  1177. PDETECTED_DEVICE
  1178. SlCheckForInboxDriver(
  1179. IN PCHAR DriverToCheck
  1180. )
  1181. /*++
  1182. Routine Description:
  1183. Searches the inbox SCSI miniport list to see if a driver
  1184. of the given name exists.
  1185. Arguments:
  1186. DriverToCheck : Base driver name to look for, in the list
  1187. Return Value:
  1188. Pointer to device node containing driver information, if the
  1189. given driver name is found, otherwise NULL
  1190. --*/
  1191. {
  1192. PDETECTED_DEVICE NodePtr = NULL;
  1193. if (DriverToCheck) {
  1194. NodePtr = BlLoaderBlock->SetupLoaderBlock->ScsiDevices;
  1195. while (NodePtr) {
  1196. if (NodePtr->BaseDllName && !_stricmp(NodePtr->BaseDllName, DriverToCheck)) {
  1197. break;
  1198. }
  1199. NodePtr = NodePtr->Next;
  1200. }
  1201. }
  1202. return NodePtr;
  1203. }
  1204. BOOLEAN
  1205. SlpOemDiskette(
  1206. IN POEM_SOURCE_DEVICE OemSourceDevice,
  1207. IN PCHAR ComponentName,
  1208. IN OEMFILETYPE ComponentType,
  1209. IN TYPE_OF_MEMORY MemoryType,
  1210. IN ULONG MenuHeaderId,
  1211. OUT OPTIONAL PDETECTED_DEVICE DetectedDevice,
  1212. OUT PVOID *ImageBase,
  1213. OUT OPTIONAL PCHAR *ImageName,
  1214. OUT OPTIONAL PTCHAR *DriverDescription,
  1215. IN BOOLEAN AllowUserSelection,
  1216. IN PTCHAR PreInstallComponentDescription,
  1217. OUT PPNP_HARDWARE_ID* HardwareIdDatabase,
  1218. IN PCHAR DriverDir,
  1219. IN BOOLEAN InsertDevice,
  1220. IN OPTIONAL PCSTR DriverIdString
  1221. )
  1222. /*++
  1223. Routine Description:
  1224. Prompt for an oem driver diskette and read the oem text inf file
  1225. from it. Present the choices for the device class to the user and
  1226. allow him to select one.
  1227. Remember information about the selection the user has made.
  1228. Arguments:
  1229. OemSourceDevice - The device which contains the driver/hal that
  1230. needs to be loaded.
  1231. ComponentName - Supplies name of component to look for.
  1232. ComponentType - Supplies the type of the component (HAL, SCSI, or Other)
  1233. MemoryType - Supplies the type of memory used to load the image.
  1234. MenuHeaderId - Supplies ID of menu header to be displayed
  1235. DetectedDevice - Returns information about the device seleceted
  1236. ImageBase - Returns image base of loaded image
  1237. ImageName - Returns filename of loaded image
  1238. DriverDescription - If specified, returns description of loaded driver
  1239. AllowUserSelection - Indicates whether or not user is allowed to select
  1240. a driver. This flag is typically set to FALSE when
  1241. pre-installing components defined in unattend.txt.
  1242. PreInstallComponentDescription - In the pre-install mode, points to the string
  1243. that identifies the component to pre-install.
  1244. It is NULL if AllowUserSelction is TRUE.
  1245. HardwareIdDatabase - The hardware IDs what were loaded for the particular
  1246. driver.
  1247. DriverDir - The driver directory which has the dynamic update driver. The
  1248. path is relative to the boot directory. This value indicates
  1249. that the driver to be loaded is dyamic update boot driver.
  1250. InsertDevice - Indicates whether to insert the device into the detected
  1251. device list or not. Currently only valid for SCSI mass storage device
  1252. drivers.
  1253. DriverIdString - Driver Id of a particular driver to be loaded.
  1254. It is used to load a driver specified in
  1255. the txtsetup.oem file using the DriverLoadList key
  1256. in the [Defaults] section.
  1257. Return Value:
  1258. TRUE if the user made a choice, FALSE if the user cancelled/error occurred.
  1259. --*/
  1260. {
  1261. static CHAR LoadDeviceName[128];
  1262. ULONG LoadDeviceId = SL_OEM_DEVICE_ORDINAL;
  1263. PVOID OemInfHandle = NULL;
  1264. ULONG Error;
  1265. ARC_STATUS Status;
  1266. ULONG Count;
  1267. ULONG DefaultSelection = 0;
  1268. PTCHAR DefaultSelText = NULL;
  1269. PCHAR p;
  1270. PSL_MENU Menu = NULL;
  1271. ULONG c;
  1272. PMENU_ITEM_DATA Data;
  1273. PDETECTED_DEVICE_FILE FileStruct;
  1274. BOOLEAN bDriverLoaded;
  1275. HwFileType filetype;
  1276. static CHAR FullDriverPath[256];
  1277. static CHAR FilePath[256];
  1278. PCHAR OemComponentId = NULL;
  1279. PTCHAR OemComponentDescription;
  1280. DETECTED_DEVICE TempDevice;
  1281. static TCHAR ScratchBuffer[256] = {0};
  1282. PDETECTED_DEVICE InboxDevice;
  1283. BOOLEAN DynamicUpdate = FALSE;
  1284. BOOLEAN Preinstallation = FALSE;
  1285. BOOLEAN DeviceOpened = FALSE;
  1286. BOOLEAN DriverLoadList = FALSE;
  1287. //
  1288. // If source device is specified, then probe it and
  1289. // extract some required state information
  1290. //
  1291. if (OemSourceDevice) {
  1292. if (SL_OEM_SOURCE_DEVICE_TYPE(OemSourceDevice,
  1293. SL_OEM_SOURCE_DEVICE_TYPE_DYN_UPDATE)) {
  1294. DynamicUpdate = TRUE;
  1295. }
  1296. if (SL_OEM_SOURCE_DEVICE_TYPE(OemSourceDevice,
  1297. SL_OEM_SOURCE_DEVICE_TYPE_PREINSTALL)) {
  1298. Preinstallation = TRUE;
  1299. }
  1300. //
  1301. // Is the inf already opened ?
  1302. //
  1303. if (!DynamicUpdate && OemSourceDevice->InfHandle &&
  1304. !SL_OEM_SOURCE_DEVICE_STATE(OemSourceDevice,
  1305. SL_OEM_SOURCE_DEVICE_PROCESSED)) {
  1306. OemInfHandle = OemSourceDevice->InfHandle;
  1307. }
  1308. LoadDeviceId = OemSourceDevice->DeviceId;
  1309. DriverLoadList = ((DriverIdString) && (DriverIdString[0] != 0)) ? TRUE : FALSE;
  1310. }
  1311. if (AllowUserSelection) {
  1312. SlClearClientArea();
  1313. }
  1314. if (AllowUserSelection) {
  1315. //
  1316. // Only try to detect floppy 0 if no source device
  1317. // specified
  1318. //
  1319. if (OemSourceDevice) {
  1320. strcpy(LoadDeviceName, OemSourceDevice->ArcDeviceName);
  1321. LoadDeviceId = OemSourceDevice->DeviceId;
  1322. } else {
  1323. //
  1324. // Compute the name of the A: drive
  1325. //
  1326. if (!SlpFindFloppy(0, LoadDeviceName)) {
  1327. ULONG UserInput;
  1328. //
  1329. // No floppy drive available, bail out.
  1330. //
  1331. SlClearClientArea();
  1332. SlDisplayMessageBox(SL_NO_FLOPPY_DRIVE);
  1333. #ifdef EFI
  1334. //
  1335. // disable efi watchdog timer
  1336. //
  1337. DisableEFIWatchDog();
  1338. #endif
  1339. do {
  1340. UserInput = SlGetChar();
  1341. }
  1342. while ((UserInput != ASCI_ESC) && (UserInput != SL_KEY_F3));
  1343. #ifdef EFI
  1344. //
  1345. // reset efi watchdog timer
  1346. //
  1347. SetEFIWatchDog(EFI_WATCHDOG_TIMEOUT);
  1348. #endif
  1349. if (UserInput == SL_KEY_F3) {
  1350. ArcRestart();
  1351. }
  1352. SlClearClientArea();
  1353. return FALSE;
  1354. }
  1355. }
  1356. //
  1357. // Open the device if its not already done
  1358. //
  1359. if (LoadDeviceId == SL_OEM_DEVICE_ORDINAL) {
  1360. //
  1361. // Prompt for the disk.
  1362. //
  1363. while(1) {
  1364. if (!SlPromptForDisk(BlFindMessage(SL_OEM_DISK_PROMPT), TRUE)) {
  1365. return(FALSE);
  1366. }
  1367. Status = ArcOpen(LoadDeviceName, ArcOpenReadOnly, &LoadDeviceId);
  1368. if(Status == ESUCCESS) {
  1369. DeviceOpened = TRUE;
  1370. break;
  1371. }
  1372. }
  1373. }
  1374. }
  1375. //
  1376. // Load the OEM INF file
  1377. //
  1378. if( AllowUserSelection ) {
  1379. *FilePath = *FullDriverPath = '\0';
  1380. } else {
  1381. if (DynamicUpdate || Preinstallation) {
  1382. strcpy(FilePath, BootPath);
  1383. } else {
  1384. *FilePath = '\0';
  1385. }
  1386. if (DynamicUpdate && DriverDir) {
  1387. //
  1388. // In case of dynamic update boot drivers
  1389. // the path to txtsetup.oem needs to be fully
  1390. // qualified from the boot directory
  1391. //
  1392. strcat(FilePath, DriverDir);
  1393. }
  1394. if (PreInstall) {
  1395. #if defined(_X86_)
  1396. if ( BlBootingFromNet ) {
  1397. #endif
  1398. //
  1399. // On RISC platforms and on x86 remote boot clients,
  1400. // remove the platform specific directory from the path.
  1401. //
  1402. p = (FilePath + strlen(FilePath) - 1);
  1403. if( *p == '\\' ) {
  1404. *p = '\0';
  1405. }
  1406. p = strrchr(FilePath, '\\');
  1407. *(p+1) = '\0';
  1408. #if defined(_X86_)
  1409. }
  1410. #endif
  1411. //
  1412. // Note that on x86 the path to txtsetup.oem is going to be:
  1413. // $win_nt$.~bt\$OEM$
  1414. // while on non-x86 platforms, the path is going to be:
  1415. // $win_nt$.~ls\$OEM$\TEXTMODE
  1416. // but on remote boot clients, the path is going to be:
  1417. // \device\lanmanredirector\server\reminst\setup\language\images\build\$OEM$\TEXTMODE
  1418. //
  1419. strcat(
  1420. FilePath,
  1421. #if defined(_X86_)
  1422. BlBootingFromNet ? WINNT_OEM_TEXTMODE_DIR_A : WINNT_OEM_DIR_A
  1423. #else
  1424. WINNT_OEM_TEXTMODE_DIR_A
  1425. #endif
  1426. );
  1427. }
  1428. //
  1429. // Save the path to the directory that contains txtsetup.oem.
  1430. // It will be used later on, when we load the driver.
  1431. //
  1432. strcpy(FullDriverPath, FilePath);
  1433. strcat(FilePath, "\\");
  1434. }
  1435. //
  1436. // Now form the path to txtsetup.oem
  1437. //
  1438. strcat(FilePath, "txtsetup.oem");
  1439. //
  1440. // Note : Reload the txtsetup.oem again in dynamic update boot driver case
  1441. // since for each driver the txtsetup.oem is different in its own
  1442. // downloaded directory
  1443. //
  1444. if (!OemInfHandle) {
  1445. if (DriverDir || AllowUserSelection || (PreInstallOemInfHandle == NULL)) {
  1446. Status = SlInitIniFile(NULL,
  1447. LoadDeviceId,
  1448. FilePath,
  1449. &OemInfHandle,
  1450. NULL,
  1451. NULL,
  1452. &Error);
  1453. if (Status != ESUCCESS) {
  1454. SlFriendlyError(Status, "txtsetup.oem", __LINE__, __FILE__);
  1455. goto OemLoadFailed;
  1456. }
  1457. if( !AllowUserSelection ) {
  1458. PreInstallOemInfHandle = OemInfHandle;
  1459. }
  1460. } else {
  1461. OemInfHandle = PreInstallOemInfHandle;
  1462. }
  1463. }
  1464. Count = SlCountLinesInSection(OemInfHandle, ComponentName);
  1465. if(Count == BL_INF_FILE_ERROR) {
  1466. SlMessageBox(SL_WARNING_SIF_NO_COMPONENT);
  1467. goto OemLoadFailed;
  1468. }
  1469. //
  1470. // Get the text of the default choice
  1471. //
  1472. if (!PreInstallComponentDescription) {
  1473. if (DriverLoadList){
  1474. p = (PCHAR) DriverIdString;
  1475. }else{
  1476. p = SlGetSectionKeyIndex(OemInfHandle, "Defaults",ComponentName, 0);
  1477. }
  1478. if(p && (p[0] != 0)){
  1479. #ifdef UNICODE
  1480. DefaultSelText = SlGetSectionKeyIndexW(
  1481. #else
  1482. DefaultSelText = SlGetSectionKeyIndex(
  1483. #endif
  1484. OemInfHandle,
  1485. ComponentName,
  1486. p,
  1487. 0);
  1488. //
  1489. // Save away the component id
  1490. //
  1491. OemComponentId = p;
  1492. } else {
  1493. DefaultSelText = NULL;
  1494. }
  1495. } else {
  1496. DefaultSelText = PreInstallComponentDescription;
  1497. }
  1498. //
  1499. // In case of dynamic update drivers, if the defaults is not set then
  1500. // use the first entry in the section as the default !!!
  1501. //
  1502. if (DynamicUpdate && !AllowUserSelection && !DefaultSelText) {
  1503. OemComponentId = SlGetKeyName(
  1504. OemInfHandle,
  1505. ComponentName,
  1506. 0);
  1507. }
  1508. if( AllowUserSelection ) {
  1509. //
  1510. // Build menu
  1511. //
  1512. Menu = SlCreateMenu();
  1513. if (Menu==NULL) {
  1514. SlNoMemoryError();
  1515. }
  1516. SlpAddSectionToMenu(OemInfHandle,ComponentName,Menu);
  1517. //
  1518. // Find the index of the default choice
  1519. //
  1520. if(!DefaultSelText ||
  1521. !SlGetMenuItemIndex(Menu,DefaultSelText,&DefaultSelection)) {
  1522. DefaultSelection=0;
  1523. }
  1524. }
  1525. //
  1526. // Allow the user to interact with the menu
  1527. //
  1528. while (1) {
  1529. if( AllowUserSelection ) {
  1530. SlClearClientArea();
  1531. SlWriteStatusText(BlFindMessage(SL_SELECT_DRIVER_PROMPT));
  1532. c = SlDisplayMenu(MenuHeaderId,
  1533. Menu,
  1534. &DefaultSelection);
  1535. } else {
  1536. c = ASCI_CR;
  1537. }
  1538. switch (c) {
  1539. case SL_KEY_F3:
  1540. SlConfirmExit();
  1541. break;
  1542. case ASCI_ESC:
  1543. return(FALSE);
  1544. break;
  1545. case ASCI_CR:
  1546. //
  1547. // User selected an option, fill in the detected
  1548. // device structure with the information from the
  1549. // INF file.
  1550. //
  1551. if (!DetectedDevice) {
  1552. RtlZeroMemory(&TempDevice, sizeof(DETECTED_DEVICE));
  1553. DetectedDevice = &TempDevice;
  1554. }
  1555. //
  1556. // We create a new device using SlInsertScsiDevice(...) only if we load
  1557. // the requested SCSI miniport successfully
  1558. //
  1559. if (ComponentType == OEMSCSI) {
  1560. DetectedDevice->Ordinal= SL_OEM_DEVICE_ORDINAL;
  1561. }
  1562. if( AllowUserSelection ) {
  1563. Data = SlGetMenuItem(Menu, DefaultSelection);
  1564. OemComponentId = Data->Identifier;
  1565. OemComponentDescription = Data->Description;
  1566. } else {
  1567. if (PreInstallComponentDescription) {
  1568. OemComponentId = SlPreInstallGetComponentName( OemInfHandle,
  1569. ComponentName,
  1570. PreInstallComponentDescription );
  1571. if( OemComponentId == NULL ) {
  1572. SlFatalError(SL_BAD_UNATTENDED_SCRIPT_FILE,
  1573. PreInstallComponentDescription,
  1574. SlCopyStringAT(ComponentName),
  1575. "txtsetup.oem");
  1576. }
  1577. OemComponentDescription = PreInstallComponentDescription;
  1578. } else {
  1579. #ifdef UNICODE
  1580. OemComponentDescription = SlGetSectionKeyIndexW(
  1581. OemInfHandle,
  1582. ComponentName,
  1583. OemComponentId,
  1584. 0);
  1585. #else
  1586. OemComponentDescription = SlGetSectionKeyIndex(
  1587. OemInfHandle,
  1588. ComponentName,
  1589. OemComponentId,
  1590. 0);
  1591. #endif
  1592. }
  1593. }
  1594. if(SlpOemInfSelection(OemSourceDevice,
  1595. OemInfHandle,
  1596. ComponentName,
  1597. OemComponentId,
  1598. OemComponentDescription,
  1599. DetectedDevice,
  1600. HardwareIdDatabase,
  1601. FullDriverPath)) {
  1602. //
  1603. // Go load the driver. The correct disk must
  1604. // already be in the drive, since we just read
  1605. // the INF file off it.
  1606. //
  1607. // We step down the linked list, and load the first driver we find.
  1608. //
  1609. for(FileStruct = DetectedDevice->Files, bDriverLoaded = FALSE;
  1610. (FileStruct && !bDriverLoaded);
  1611. FileStruct = FileStruct->Next) {
  1612. filetype = FileStruct->FileType;
  1613. if((filetype == HwFilePort) || (filetype == HwFileClass) ||
  1614. (filetype == HwFileDriver) || (filetype == HwFileHal)) {
  1615. ULONG DirLength;
  1616. BlOutputLoadMessage(
  1617. LoadDeviceName,
  1618. FileStruct->Filename,
  1619. OemComponentDescription // Data->Description
  1620. );
  1621. //
  1622. // Reconstruct the FullDriverPath
  1623. //
  1624. strcpy(FullDriverPath, FileStruct->Directory);
  1625. DirLength = (ULONG)strlen(FullDriverPath);
  1626. if (DirLength && (FullDriverPath[DirLength - 1] != '\\')) {
  1627. strcat(FullDriverPath, "\\");
  1628. }
  1629. strcat(FullDriverPath, FileStruct->Filename);
  1630. if (ComponentType == OEMSCSI) {
  1631. PTCHAR FmtStr = 0;
  1632. //
  1633. // Verify that we don't have an in-box driver
  1634. //
  1635. InboxDevice = SlCheckForInboxDriver(FileStruct->Filename);
  1636. if (InboxDevice) {
  1637. VERSION_COMP_RESULT VerResult;
  1638. PTCHAR AdditionalInfo;
  1639. PTCHAR DriverName = OemComponentDescription;
  1640. #ifdef UNICODE
  1641. WCHAR FileNameW[100];
  1642. #endif
  1643. if(DriverName == NULL) {
  1644. #ifdef UNICODE
  1645. UNICODE_STRING uString;
  1646. ANSI_STRING aString;
  1647. RtlInitAnsiString(&aString, FileStruct->Filename);
  1648. uString.Buffer = FileNameW;
  1649. uString.MaximumLength = sizeof(FileNameW);
  1650. RtlAnsiStringToUnicodeString(&uString, &aString, FALSE);
  1651. //
  1652. // the converted string is NULL-terminated
  1653. //
  1654. DriverName = FileNameW;
  1655. #else
  1656. DriverName = FileStruct->Filename;
  1657. #endif
  1658. }
  1659. //
  1660. // Compare the drivers version's using link time stamp
  1661. //
  1662. VerResult = SlCompareDriverVersion(
  1663. BootDeviceId,
  1664. InboxDevice,
  1665. LoadDeviceId,
  1666. DetectedDevice
  1667. );
  1668. //
  1669. // Show additional message to the user about the driver
  1670. // version mismatch
  1671. //
  1672. switch (VerResult) {
  1673. case VersionOemNew:
  1674. AdditionalInfo = BlFindMessage(SL_OEMDRIVER_NEW);
  1675. break;
  1676. case VersionInboxNew:
  1677. AdditionalInfo = BlFindMessage(SL_INBOXDRIVER_NEW);
  1678. break;
  1679. default:
  1680. AdditionalInfo = TEXT("");
  1681. break;
  1682. }
  1683. //
  1684. // Show the message and get confirmation from user
  1685. // only in attended case. In case of dynamic update
  1686. // boot drivers just use the inbox driver itself
  1687. //
  1688. if (AllowUserSelection &&
  1689. SlConfirmInboxDriverReplacement(DriverName,
  1690. AdditionalInfo)) {
  1691. //
  1692. // Remove the driver node from inbox SCSI miniport
  1693. // list
  1694. //
  1695. SlRemoveInboxDriver(FileStruct->Filename);
  1696. } else {
  1697. //
  1698. // User selected to use inbox driver
  1699. //
  1700. if (AllowUserSelection) {
  1701. if (DeviceOpened) {
  1702. ArcClose(LoadDeviceId);
  1703. }
  1704. return FALSE;
  1705. }
  1706. if (DynamicUpdate) {
  1707. //
  1708. // NOTE: Use the inbox driver instead
  1709. // of dynamic update driver
  1710. //
  1711. return TRUE;
  1712. }
  1713. //
  1714. // If user already loaded another third party
  1715. // driver then honor that
  1716. //
  1717. if (InboxDevice->ThirdPartyOptionSelected) {
  1718. return FALSE;
  1719. }
  1720. //
  1721. // NOTE : For other autoload features we
  1722. // use the OEM driver, instead of inbox
  1723. // driver to make auto load feature
  1724. // meaningful.
  1725. }
  1726. }
  1727. //
  1728. // Inform the user that the driver is being loaded
  1729. //
  1730. FmtStr = BlFindMessage(SL_FILE_LOAD_MESSAGE);
  1731. if (FmtStr && !WinPEBoot) {
  1732. PTSTR pFileName;
  1733. #ifdef UNICODE
  1734. WCHAR FileNameW[64];
  1735. ANSI_STRING aString;
  1736. UNICODE_STRING uString;
  1737. RtlInitString( &aString, FileStruct->Filename );
  1738. uString.Buffer = FileNameW;
  1739. uString.MaximumLength = sizeof(FileNameW);
  1740. RtlAnsiStringToUnicodeString( &uString, &aString, FALSE );
  1741. pFileName = FileNameW;
  1742. #else
  1743. pFileName = FileStruct->Filename;
  1744. #endif
  1745. _stprintf(ScratchBuffer, FmtStr, pFileName);
  1746. SlWriteStatusText(ScratchBuffer);
  1747. }
  1748. }
  1749. Status = BlLoadImage(LoadDeviceId,
  1750. MemoryType,
  1751. FullDriverPath,
  1752. TARGET_IMAGE,
  1753. ImageBase);
  1754. if (Status == ESUCCESS) {
  1755. DetectedDevice->BaseDllName = FileStruct->Filename;
  1756. if(ARGUMENT_PRESENT(ImageName)) {
  1757. *ImageName = FileStruct->Filename;
  1758. }
  1759. if(ARGUMENT_PRESENT(DriverDescription)) {
  1760. *DriverDescription = OemComponentDescription; // Data->Description;
  1761. }
  1762. bDriverLoaded = TRUE;
  1763. } else {
  1764. if( !PreInstall ) {
  1765. SlFriendlyError(
  1766. Status,
  1767. FullDriverPath,
  1768. __LINE__,
  1769. __FILE__
  1770. );
  1771. //
  1772. // If one of the drivers causes an error, then we abort
  1773. //
  1774. if (DeviceOpened) {
  1775. ArcClose(LoadDeviceId);
  1776. }
  1777. return FALSE;
  1778. } else {
  1779. SlFatalError(SL_FILE_LOAD_FAILED, SlCopyStringAT(FullDriverPath), Status);
  1780. }
  1781. }
  1782. }
  1783. }
  1784. if (DeviceOpened) {
  1785. ArcClose(LoadDeviceId);
  1786. }
  1787. if(bDriverLoaded) {
  1788. if ((ComponentType == OEMSCSI) && InsertDevice) {
  1789. PDETECTED_DEVICE NewScsiDevice = NULL;
  1790. //
  1791. // Insert the device in SCSI miniport list
  1792. //
  1793. if(SlInsertScsiDevice(SL_OEM_DEVICE_ORDINAL, &NewScsiDevice) == ScsiInsertError) {
  1794. SlNoMemoryError();
  1795. }
  1796. //
  1797. // update the node information we just created
  1798. //
  1799. *NewScsiDevice = *DetectedDevice;
  1800. }
  1801. return TRUE;
  1802. } else {
  1803. //
  1804. // We didn't find any drivers, so inform the user.
  1805. //
  1806. SlMessageBox(SL_WARNING_SIF_NO_DRIVERS);
  1807. break;
  1808. }
  1809. } else {
  1810. SlFriendlyError(
  1811. 0,
  1812. "",
  1813. __LINE__,
  1814. __FILE__
  1815. );
  1816. //
  1817. // Treat the invalid txtsetup.oem files cases as
  1818. // user cancellation
  1819. //
  1820. goto OemLoadFailed;
  1821. }
  1822. break;
  1823. }
  1824. }
  1825. OemLoadFailed:
  1826. if (DeviceOpened){
  1827. ArcClose(LoadDeviceId);
  1828. }
  1829. return(FALSE);
  1830. }
  1831. ULONG
  1832. SlpAddSectionToMenu(
  1833. IN PVOID InfHandle,
  1834. IN PCHAR SectionName,
  1835. IN PSL_MENU Menu
  1836. )
  1837. /*++
  1838. Routine Description:
  1839. Adds the entries in an INF section to the given menu
  1840. Arguments:
  1841. InfHandle - Supplies a handle to the INF file
  1842. SectionName - Supplies the name of the section.
  1843. Menu - Supplies the menu to add the items in the section to.
  1844. Return Value:
  1845. Number of items added to the menu.
  1846. --*/
  1847. {
  1848. ULONG i;
  1849. ULONG LineCount;
  1850. PTCHAR Description;
  1851. PMENU_ITEM_DATA Data;
  1852. if (InfHandle==NULL) {
  1853. //
  1854. // nothing to add
  1855. //
  1856. return(0);
  1857. }
  1858. LineCount = SlCountLinesInSection(InfHandle,SectionName);
  1859. if(LineCount == BL_INF_FILE_ERROR) {
  1860. LineCount = 0;
  1861. }
  1862. for (i=0;i<LineCount;i++) {
  1863. Data = BlAllocateHeap(sizeof(MENU_ITEM_DATA));
  1864. if (Data==NULL) {
  1865. SlError(0);
  1866. return(0);
  1867. }
  1868. Data->InfFile = InfHandle;
  1869. Data->SectionName = SectionName;
  1870. Data->Index = i;
  1871. #ifdef UNICODE
  1872. Description = SlGetSectionLineIndexW(
  1873. #else
  1874. Description = SlGetSectionLineIndex(
  1875. #endif
  1876. InfHandle,
  1877. SectionName,
  1878. i,
  1879. 0);
  1880. if (Description==NULL) {
  1881. Description=TEXT("BOGUS!");
  1882. }
  1883. Data->Description = Description;
  1884. Data->Identifier = SlGetKeyName(InfHandle,SectionName,i);
  1885. SlAddMenuItem(Menu,
  1886. Description,
  1887. Data,
  1888. 0);
  1889. }
  1890. return(LineCount);
  1891. }
  1892. BOOLEAN
  1893. SlpFindFloppy(
  1894. IN ULONG Number,
  1895. OUT PCHAR ArcName
  1896. )
  1897. /*++
  1898. Routine Description:
  1899. Determines the ARC name for a particular floppy drive.
  1900. Arguments:
  1901. Number - Supplies the floppy drive number
  1902. ArcName - Returns the ARC name of the given floppy drive.
  1903. Return Value:
  1904. TRUE - Drive was found.
  1905. FALSE - Drive was not found.
  1906. --*/
  1907. {
  1908. FloppyDiskPath = ArcName;
  1909. FloppyDiskPath[0] = '\0';
  1910. BlSearchConfigTree(BlLoaderBlock->ConfigurationRoot,
  1911. PeripheralClass,
  1912. FloppyDiskPeripheral,
  1913. Number,
  1914. FoundFloppyDiskCallback);
  1915. if (ArcName[0]=='\0') {
  1916. return(FALSE);
  1917. } else {
  1918. return(TRUE);
  1919. }
  1920. }
  1921. BOOLEAN
  1922. FoundFloppyDiskCallback(
  1923. IN PCONFIGURATION_COMPONENT_DATA Component
  1924. )
  1925. /*++
  1926. Routine Description:
  1927. Callback routine called by SlpFindFloppy to find a given floppy
  1928. drive in the ARC tree.
  1929. Check to see whether the parent is disk controller 0.
  1930. Arguments:
  1931. Component - Supplies the component.
  1932. Return Value:
  1933. TRUE if search is to continue.
  1934. FALSE if search is to stop.
  1935. --*/
  1936. {
  1937. PCONFIGURATION_COMPONENT_DATA ParentComponent;
  1938. //
  1939. // A floppy disk peripheral was found. If the parent was disk(0),
  1940. // we've got a floppy disk drive.
  1941. //
  1942. ParentComponent = Component->Parent;
  1943. if( ParentComponent &&
  1944. (ParentComponent->ComponentEntry.Type == DiskController))
  1945. {
  1946. //
  1947. // Store the ARC pathname of the floppy
  1948. //
  1949. BlGetPathnameFromComponent(Component,FloppyDiskPath);
  1950. return(FALSE);
  1951. }
  1952. return(TRUE); // keep searching
  1953. }
  1954. BOOLEAN
  1955. SlpIsOnlySuperFloppy(
  1956. void
  1957. )
  1958. /*++
  1959. Routine Description:
  1960. Determines if we only have ATAPI super floppies
  1961. Arguments:
  1962. Return Value:
  1963. TRUE - only super floppies
  1964. FALSE - > 0 regular floppies
  1965. --*/
  1966. {
  1967. BlSearchConfigTree(BlLoaderBlock->ConfigurationRoot,
  1968. PeripheralClass,
  1969. FloppyDiskPeripheral,
  1970. 0,
  1971. SuperFloppyCallback);
  1972. return(IsSuperFloppy == FloppyNumber) ? TRUE : FALSE;
  1973. }
  1974. BOOLEAN
  1975. SuperFloppyCallback(
  1976. IN PCONFIGURATION_COMPONENT_DATA Component
  1977. )
  1978. /*++
  1979. Routine Description:
  1980. Callback routine called by SlpIsOnlySuper to find if we only have ATAPI floppy
  1981. drives in the ARC tree.
  1982. Check to see whether the parent is disk controller 0.
  1983. Arguments:
  1984. Component - Supplies the component.
  1985. Return Value:
  1986. TRUE if search is to continue.
  1987. FALSE if search is to stop.
  1988. --*/
  1989. {
  1990. PCM_FLOPPY_DEVICE_DATA FloppyData;
  1991. PCM_PARTIAL_RESOURCE_LIST DescriptorList;
  1992. if(Component->ComponentEntry.Type==FloppyDiskPeripheral) {
  1993. //
  1994. // A floppy disk peripheral was found.
  1995. //
  1996. FloppyNumber++;
  1997. //
  1998. // Crack the CM descriptors. This is a reversal of the storage from
  1999. // ..\detect\i386\diskc.c. The data is in the 2nd, not the 1st descriptor
  2000. //
  2001. DescriptorList = (PCM_PARTIAL_RESOURCE_LIST)Component->ConfigurationData;
  2002. FloppyData = (PCM_FLOPPY_DEVICE_DATA)(DescriptorList +1);
  2003. if (FloppyData->MaxDensity & 0x80000000) {
  2004. //
  2005. // Is it a special removeable ATAPI device?
  2006. //
  2007. IsSuperFloppy++;
  2008. }
  2009. }
  2010. return(TRUE); // keep searching
  2011. }
  2012. BOOLEAN
  2013. SlpReplicatePnpHardwareIds(
  2014. IN PPNP_HARDWARE_ID ExistingIds,
  2015. OUT PPNP_HARDWARE_ID *NewIds
  2016. )
  2017. /*++
  2018. Routine Description:
  2019. Replicates the input PNP_HARDWARE_ID list.
  2020. Arguments:
  2021. ExistingIds - The input PNP_HARDWARE_ID list
  2022. NewIds - Placeholder for the the new replicated hardware
  2023. ID linked list.
  2024. Return Value:
  2025. TRUE if successful, otherwise FALSE.
  2026. --*/
  2027. {
  2028. BOOLEAN Result = FALSE;
  2029. if (ExistingIds && NewIds) {
  2030. PPNP_HARDWARE_ID SrcNode = ExistingIds;
  2031. PPNP_HARDWARE_ID HeadNode = NULL;
  2032. PPNP_HARDWARE_ID PrevNode = NULL;
  2033. PPNP_HARDWARE_ID CurrNode = NULL;
  2034. do {
  2035. CurrNode = BlAllocateHeap(sizeof(PNP_HARDWARE_ID));
  2036. if (CurrNode) {
  2037. *CurrNode = *SrcNode;
  2038. CurrNode->Next = NULL;
  2039. if (!HeadNode) {
  2040. HeadNode = CurrNode;
  2041. }
  2042. if (PrevNode) {
  2043. PrevNode->Next = CurrNode;
  2044. }
  2045. PrevNode = CurrNode;
  2046. SrcNode = SrcNode->Next;
  2047. }
  2048. }
  2049. while (SrcNode && CurrNode);
  2050. if (CurrNode) {
  2051. Result = TRUE;
  2052. *NewIds = HeadNode;
  2053. }
  2054. }
  2055. return Result;
  2056. }
  2057. BOOLEAN
  2058. SlpOemInfSelection(
  2059. IN POEM_SOURCE_DEVICE OemSourceDevice,
  2060. IN PVOID OemInfHandle,
  2061. IN PCHAR ComponentName,
  2062. IN PCHAR SelectedId,
  2063. IN PTCHAR ItemDescription,
  2064. OUT PDETECTED_DEVICE Device,
  2065. OUT PPNP_HARDWARE_ID* HardwareIdDatabase,
  2066. IN PCHAR DriverDir
  2067. )
  2068. {
  2069. PCHAR FilesSectionName,ConfigSectionName,HardwareIdsSectionName;
  2070. ULONG Line,Count,Line2,Count2;
  2071. BOOLEAN rc = FALSE;
  2072. PDETECTED_DEVICE_FILE FileList = NULL, FileListTail = NULL;
  2073. PDETECTED_DEVICE_REGISTRY RegList = NULL, RegListTail = NULL;
  2074. PPNP_HARDWARE_ID IdList = NULL, IdListTail;
  2075. PPNP_HARDWARE_ID PrivateIdList = NULL;
  2076. ULONG FileTypeBits = 0;
  2077. //
  2078. // Validate the parameters
  2079. //
  2080. if (!ComponentName || !SelectedId) {
  2081. return FALSE;
  2082. }
  2083. //
  2084. // Iterate through the files section, remembering info about the
  2085. // files to be copied in support of the selection.
  2086. //
  2087. FilesSectionName = BlAllocateHeap(sizeof("Files.") + // includes 1 for the \0
  2088. (ULONG)strlen(ComponentName) +
  2089. sizeof(CHAR) + // 1 for the "."
  2090. (ULONG)strlen(SelectedId)
  2091. );
  2092. if (!FilesSectionName) {
  2093. return FALSE; // out of memory
  2094. }
  2095. strcpy(FilesSectionName,"Files.");
  2096. strcat(FilesSectionName,ComponentName);
  2097. strcat(FilesSectionName,".");
  2098. strcat(FilesSectionName,SelectedId);
  2099. Count = SlCountLinesInSection(OemInfHandle,FilesSectionName);
  2100. if(Count == BL_INF_FILE_ERROR) {
  2101. SlMessageBox(SL_BAD_INF_SECTION,FilesSectionName);
  2102. goto sod0;
  2103. }
  2104. for(Line=0; Line<Count; Line++) {
  2105. PCHAR Disk,Filename,Filetype,Tagfile,Directory,ConfigName;
  2106. PTCHAR Description;
  2107. HwFileType filetype;
  2108. PDETECTED_DEVICE_FILE FileStruct;
  2109. //
  2110. // Get the disk specification, filename, and filetype from the line.
  2111. //
  2112. Disk = SlGetSectionLineIndex(OemInfHandle,FilesSectionName,Line,OINDEX_DISKSPEC);
  2113. Filename = SlGetSectionLineIndex(OemInfHandle,FilesSectionName,Line,OINDEX_FILENAME);
  2114. Filetype = SlGetKeyName(OemInfHandle,FilesSectionName,Line);
  2115. if(!Disk || !Filename || !Filetype) {
  2116. #ifdef UNICODE
  2117. DIAGOUT((
  2118. TEXT("SlpOemDiskette: Disk=%S, Filename=%S, Filetype=%S"),
  2119. Disk ? Disk : "(null)",
  2120. Filename ? Filename : "(null)",
  2121. Filetype ? Filetype : "(null)"));
  2122. #else
  2123. DIAGOUT((
  2124. TEXT("SlpOemDiskette: Disk=%s, Filename=%s, Filetype=%s"),
  2125. Disk ? Disk : "(null)",
  2126. Filename ? Filename : "(null)",
  2127. Filetype ? Filetype : "(null)"));
  2128. #endif
  2129. SlError(Line);
  2130. // SppOemInfError(ErrorMsg,&SptOemInfErr2,Line+1,FilesSectionName);
  2131. goto sod0;
  2132. }
  2133. //
  2134. // Parse the filetype.
  2135. //
  2136. filetype = SlpFindStringInTable(Filetype,FileTypeNames);
  2137. if(filetype == HwFileMax) {
  2138. // SppOemInfError(ErrorMsg,&SptOemInfErr4,Line+1,FilesSectionName);
  2139. goto sod0;
  2140. }
  2141. //
  2142. // Fetch the name of the section containing configuration information.
  2143. // Required if file is of type port, class, or driver.
  2144. //
  2145. if((filetype == HwFilePort) || (filetype == HwFileClass) || (filetype == HwFileDriver)) {
  2146. ConfigName = SlGetSectionLineIndex(OemInfHandle,FilesSectionName,Line,OINDEX_CONFIGNAME);
  2147. if(ConfigName == NULL) {
  2148. // SppOemInfError(ErrorMsg,&SptOemInfErr8,Line+1,FilesSectionName);
  2149. goto sod0;
  2150. }
  2151. } else {
  2152. ConfigName = NULL;
  2153. }
  2154. //
  2155. // Using the disk specification, look up the tagfile, description,
  2156. // and directory for the disk.
  2157. //
  2158. Tagfile = SlGetSectionKeyIndex(OemInfHandle,"Disks",Disk,OINDEX_TAGFILE);
  2159. #ifdef UNICODE
  2160. Description = SlGetSectionKeyIndexW(
  2161. #else
  2162. Description = SlGetSectionKeyIndex(
  2163. #endif
  2164. OemInfHandle,
  2165. "Disks",
  2166. Disk,
  2167. OINDEX_DISKDESCR);
  2168. Directory = SlGetSectionKeyIndex(OemInfHandle,"Disks",Disk,OINDEX_DIRECTORY);
  2169. if((Directory == NULL) || !strcmp(Directory,"\\")) {
  2170. Directory = SlCopyStringA("");
  2171. }
  2172. if(!Tagfile || !Description) {
  2173. DIAGOUT((
  2174. TEXT("SppOemDiskette: Tagfile=%s, Description=%s"),
  2175. Tagfile ? Tagfile : "(null)",
  2176. Description ? Description : TEXT("(null)")));
  2177. // SppOemInfError(ErrorMsg,&SptOemInfErr5,Line+1,FilesSectionName);
  2178. goto sod0;
  2179. }
  2180. FileStruct = BlAllocateHeap(sizeof(DETECTED_DEVICE_FILE));
  2181. memset(FileStruct, 0, sizeof(DETECTED_DEVICE_FILE));
  2182. //
  2183. // Use the fully qualified path, for dynamic update drivers
  2184. // if any
  2185. //
  2186. if (DriverDir && DriverDir[0]) {
  2187. PCHAR FullDir = BlAllocateHeap(256);
  2188. if (FullDir) {
  2189. *FullDir = '\0';
  2190. //
  2191. // Do we need a starting '\' ?
  2192. //
  2193. if (DriverDir[0] != '\\') {
  2194. strcat(FullDir, "\\");
  2195. }
  2196. strcat(FullDir, DriverDir);
  2197. //
  2198. // Do we need to append another '\' between
  2199. // the paths ?
  2200. //
  2201. if ((FullDir[strlen(FullDir) - 1] != '\\') &&
  2202. (*Directory != '\\')) {
  2203. strcat(FullDir, "\\");
  2204. }
  2205. strcat(FullDir, Directory);
  2206. //
  2207. // Do we need a terminating '\'?
  2208. //
  2209. if (FullDir[strlen(FullDir) - 1] != '\\') {
  2210. strcat(FullDir, "\\");
  2211. }
  2212. Directory = FullDir;
  2213. } else {
  2214. return FALSE; // ran out of memory
  2215. }
  2216. }
  2217. FileStruct->Directory = Directory;
  2218. FileStruct->Filename = Filename;
  2219. FileStruct->DiskDescription = Description;
  2220. FileStruct->DiskTagfile = Tagfile;
  2221. FileStruct->FileType = filetype;
  2222. //
  2223. // Insert at tail of list so we preserve the order in the Files section
  2224. //
  2225. if(FileList) {
  2226. ASSERT(FileListTail != NULL);
  2227. FileListTail->Next = FileStruct;
  2228. FileListTail = FileStruct;
  2229. } else {
  2230. FileList = FileListTail = FileStruct;
  2231. }
  2232. FileStruct->Next = NULL;
  2233. if(ConfigName) {
  2234. FileStruct->ConfigName = ConfigName;
  2235. } else {
  2236. FileStruct->ConfigName = NULL;
  2237. }
  2238. FileStruct->RegistryValueList = NULL;
  2239. if((filetype == HwFilePort) || (filetype == HwFileDriver)) {
  2240. SET_FILETYPE_PRESENT(FileTypeBits,HwFilePort);
  2241. SET_FILETYPE_PRESENT(FileTypeBits,HwFileDriver);
  2242. } else {
  2243. SET_FILETYPE_PRESENT(FileTypeBits,filetype);
  2244. }
  2245. //
  2246. // If this is a dynamic update driver, then mark the
  2247. // the device file type bits to indicate this. Textmode
  2248. // setup needs this to construct a valid source path.
  2249. //
  2250. if (OemSourceDevice &&
  2251. SL_OEM_SOURCE_DEVICE_TYPE(OemSourceDevice, SL_OEM_SOURCE_DEVICE_TYPE_DYN_UPDATE)){
  2252. SET_FILETYPE_PRESENT(FileTypeBits, HwFileDynUpdt);
  2253. }
  2254. //
  2255. // Now go look in the [Config.<ConfigName>] section for registry
  2256. // information that is to be set for this driver file.
  2257. //
  2258. if(ConfigName) {
  2259. ConfigSectionName = BlAllocateHeap((ULONG)strlen(ConfigName) + sizeof("Config.")); // sizeof counts the \0
  2260. strcpy(ConfigSectionName,"Config.");
  2261. strcat(ConfigSectionName,ConfigName);
  2262. Count2 = SlCountLinesInSection(OemInfHandle,ConfigSectionName);
  2263. if(Count2 == BL_INF_FILE_ERROR) {
  2264. Count2 = 0;
  2265. }
  2266. for(Line2=0; Line2<Count2; Line2++) {
  2267. PCHAR KeyName,ValueName,ValueType;
  2268. PDETECTED_DEVICE_REGISTRY Reg;
  2269. HwRegistryType valuetype;
  2270. //
  2271. // Fetch KeyName, ValueName, and ValueType from the line.
  2272. //
  2273. KeyName = SlGetSectionLineIndex(OemInfHandle,ConfigSectionName,Line2,OINDEX_KEYNAME);
  2274. ValueName = SlGetSectionLineIndex(OemInfHandle,ConfigSectionName,Line2,OINDEX_VALUENAME);
  2275. ValueType = SlGetSectionLineIndex(OemInfHandle,ConfigSectionName,Line2,OINDEX_VALUETYPE);
  2276. if(!KeyName || !ValueName || !ValueType) {
  2277. DIAGOUT((
  2278. TEXT("SlpOemDiskette: KeyName=%s, ValueName=%s, ValueType=%s"),
  2279. KeyName ? KeyName : "(null)",
  2280. ValueName ? ValueName : "(null)",
  2281. ValueType ? ValueType : "(null)"));
  2282. // SppOemInfError(ErrorMsg,&SptOemInfErr2,Line2+1,ConfigSectionName);
  2283. goto sod0;
  2284. }
  2285. //
  2286. // Parse the value type and associated values.
  2287. //
  2288. valuetype = SlpFindStringInTable(ValueType,RegistryTypeNames);
  2289. if(valuetype == HwRegistryMax) {
  2290. // SppOemInfError(ErrorMsg,&SptOemInfErr6,Line2+1,ConfigSectionName);
  2291. goto sod0;
  2292. }
  2293. Reg = SlpInterpretOemRegistryData(OemInfHandle,ConfigSectionName,Line2,valuetype);
  2294. if(Reg) {
  2295. Reg->KeyName = KeyName;
  2296. Reg->ValueName = ValueName;
  2297. //
  2298. // Insert at tail of list so as to preserve the order given in the config section
  2299. //
  2300. if(RegList) {
  2301. ASSERT(RegListTail != NULL);
  2302. RegListTail->Next = Reg;
  2303. RegListTail = Reg;
  2304. } else {
  2305. RegList = RegListTail = Reg;
  2306. }
  2307. Reg->Next = NULL;
  2308. } else {
  2309. // SppOemInfError(ErrorMsg,&SptOemInfErr7,Line2+1,ConfigSectionName);
  2310. goto sod0;
  2311. }
  2312. }
  2313. FileStruct->RegistryValueList = RegList;
  2314. RegList = NULL;
  2315. }
  2316. //
  2317. // Save away the arc device name also
  2318. //
  2319. if (OemSourceDevice && OemSourceDevice->ArcDeviceName) {
  2320. FileStruct->ArcDeviceName = SlCopyStringA(OemSourceDevice->ArcDeviceName);
  2321. } else {
  2322. FileStruct->ArcDeviceName = NULL;
  2323. }
  2324. }
  2325. //
  2326. // Get the hardware ids if such a section exist
  2327. //
  2328. HardwareIdsSectionName = BlAllocateHeap(sizeof("HardwareIds.") + // includes the \0
  2329. (ULONG)strlen(ComponentName) +
  2330. sizeof(CHAR) + // "."
  2331. (ULONG)strlen(SelectedId)
  2332. );
  2333. strcpy(HardwareIdsSectionName,"HardwareIds.");
  2334. strcat(HardwareIdsSectionName,ComponentName);
  2335. strcat(HardwareIdsSectionName,".");
  2336. strcat(HardwareIdsSectionName,SelectedId);
  2337. Count = SlCountLinesInSection(OemInfHandle,HardwareIdsSectionName);
  2338. if(Count == BL_INF_FILE_ERROR) {
  2339. //
  2340. // If the section doesn't exist, the assume it is empty
  2341. //
  2342. Count = 0;
  2343. }
  2344. IdList = IdListTail = NULL;
  2345. for(Line=0; Line<Count; Line++) {
  2346. PCHAR Id;
  2347. PCHAR DriverName;
  2348. PCHAR ClassGuid;
  2349. PPNP_HARDWARE_ID TempIdElement;
  2350. Id = SlGetSectionLineIndex(OemInfHandle,HardwareIdsSectionName,Line,OINDEX_HW_ID);
  2351. DriverName = SlGetSectionLineIndex(OemInfHandle,HardwareIdsSectionName,Line,OINDEX_DRIVER_NAME);
  2352. ClassGuid = SlGetSectionLineIndex(OemInfHandle,HardwareIdsSectionName,Line,OINDEX_CLASS_GUID);
  2353. if( !Id || !DriverName ) {
  2354. SlMessageBox(SL_BAD_INF_SECTION,HardwareIdsSectionName);
  2355. goto sod0;
  2356. }
  2357. TempIdElement = BlAllocateHeap(sizeof(PNP_HARDWARE_ID));
  2358. if(IdListTail == NULL) {
  2359. IdListTail = TempIdElement;
  2360. }
  2361. TempIdElement->Id = Id;
  2362. TempIdElement->DriverName = DriverName;
  2363. TempIdElement->ClassGuid = ClassGuid;
  2364. TempIdElement->Next = IdList;
  2365. IdList = TempIdElement;
  2366. }
  2367. if( IdList != NULL ) {
  2368. //
  2369. // Replicate the PNP hardware Id list
  2370. //
  2371. if (!SlpReplicatePnpHardwareIds(IdList, &PrivateIdList)) {
  2372. goto sod0; // ran out of memory
  2373. }
  2374. IdListTail->Next = *HardwareIdDatabase;
  2375. *HardwareIdDatabase = IdList;
  2376. }
  2377. //
  2378. // Everything is OK so we can place the information we have gathered
  2379. // into the main structure for the device class.
  2380. //
  2381. SlpInitDetectedDevice( Device,
  2382. SelectedId,
  2383. ItemDescription,
  2384. TRUE
  2385. );
  2386. Device->Files = FileList;
  2387. Device->FileTypeBits = FileTypeBits;
  2388. Device->HardwareIds = PrivateIdList;
  2389. rc = TRUE;
  2390. //
  2391. // Clean up and exit.
  2392. //
  2393. sod0:
  2394. return(rc);
  2395. }
  2396. int
  2397. SlpFindStringInTable(
  2398. IN PCHAR String,
  2399. IN PCHAR *StringTable
  2400. )
  2401. /*++
  2402. Routine Description:
  2403. Locate a string in an array of strings, returning its index. The search
  2404. is not case sensitive.
  2405. Arguments:
  2406. String - string to locate in the string table.
  2407. StringTable - array of strings to search in. The final element of the
  2408. array must be NULL so we can tell where the table ends.
  2409. Return Value:
  2410. Index into the table, or some positive index outside the range of valid
  2411. indices for the table if the string is not found.
  2412. --*/
  2413. {
  2414. int i;
  2415. for(i=0; StringTable[i]; i++) {
  2416. if(_stricmp(StringTable[i],String) == 0) {
  2417. return(i);
  2418. }
  2419. }
  2420. return(i);
  2421. }
  2422. VOID
  2423. SlpInitDetectedDevice(
  2424. IN PDETECTED_DEVICE Device,
  2425. IN PCHAR IdString,
  2426. IN PTCHAR Description,
  2427. IN BOOLEAN ThirdPartyOptionSelected
  2428. )
  2429. {
  2430. Device->IdString = IdString;
  2431. Device->Description = Description;
  2432. Device->ThirdPartyOptionSelected = ThirdPartyOptionSelected;
  2433. Device->FileTypeBits = 0;
  2434. Device->Files = NULL;
  2435. }
  2436. PDETECTED_DEVICE_REGISTRY
  2437. SlpInterpretOemRegistryData(
  2438. IN PVOID InfHandle,
  2439. IN PCHAR SectionName,
  2440. IN ULONG Line,
  2441. IN HwRegistryType ValueType
  2442. )
  2443. {
  2444. PDETECTED_DEVICE_REGISTRY Reg;
  2445. PCHAR Value;
  2446. unsigned i,len;
  2447. ULONG Dword;
  2448. ULONG BufferSize;
  2449. PVOID Buffer = NULL;
  2450. PUCHAR BufferUchar;
  2451. //
  2452. // Perform appropriate action based on the type
  2453. //
  2454. switch(ValueType) {
  2455. case HwRegistryDword:
  2456. // case REG_DWORD_LITTLE_ENDIAN:
  2457. // case REG_DWORD_BIG_ENDIAN:
  2458. Value = SlGetSectionLineIndex(InfHandle,SectionName,Line,OINDEX_FIRSTVALUE);
  2459. if(Value == NULL) {
  2460. goto x1;
  2461. }
  2462. //
  2463. // Make sure it's really a hex number
  2464. //
  2465. len = (ULONG)strlen(Value);
  2466. if(len > 8) {
  2467. goto x1;
  2468. }
  2469. for(i=0; i<len; i++) {
  2470. if(!isxdigit(Value[i])) {
  2471. goto x1;
  2472. }
  2473. }
  2474. //
  2475. // convert it from ascii to a hex number
  2476. //
  2477. if (!sscanf(Value,"%lx",&Dword)) {
  2478. Dword = 0;
  2479. }
  2480. #if 0
  2481. //
  2482. // If big endian, perform appropriate conversion
  2483. //
  2484. if(VaueType == REG_DWORD_BIG_ENDIAN) {
  2485. Dword = ((Dword << 24) & 0xff000000)
  2486. | ((Dword << 8) & 0x00ff0000)
  2487. | ((Dword >> 8) & 0x0000ff00)
  2488. | ((Dword >> 24) & 0x000000ff);
  2489. }
  2490. #endif
  2491. //
  2492. // Allocate a 4-byte buffer and store the dword in it
  2493. //
  2494. Buffer = BlAllocateHeap(BufferSize = sizeof(ULONG));
  2495. if (Buffer == NULL) {
  2496. goto x1;
  2497. }
  2498. *(PULONG)Buffer = Dword;
  2499. break;
  2500. case HwRegistrySz:
  2501. case HwRegistryExpandSz:
  2502. Value = SlGetSectionLineIndex(InfHandle,SectionName,Line,OINDEX_FIRSTVALUE);
  2503. if(Value == NULL) {
  2504. goto x1;
  2505. }
  2506. //
  2507. // Allocate a buffer of appropriate size for the string
  2508. //
  2509. Buffer = BlAllocateHeap(BufferSize = (ULONG)strlen(Value)+1);
  2510. if (Buffer == NULL) {
  2511. goto x1;
  2512. }
  2513. strcpy(Buffer, Value);
  2514. break;
  2515. case HwRegistryBinary:
  2516. Value = SlGetSectionLineIndex(InfHandle,SectionName,Line,OINDEX_FIRSTVALUE);
  2517. if(Value == NULL) {
  2518. goto x1;
  2519. }
  2520. //
  2521. // Figure out how many byte values are specified
  2522. //
  2523. len = (unsigned)strlen(Value);
  2524. if(len & 1) {
  2525. goto x1; // odd # of characters
  2526. }
  2527. //
  2528. // Allocate a buffer to hold the byte values
  2529. //
  2530. Buffer = BlAllocateHeap(BufferSize = len / 2);
  2531. BufferUchar = Buffer;
  2532. //
  2533. // For each digit pair, convert to a hex number and store in the
  2534. // buffer
  2535. //
  2536. for(i=0; i<len; i+=2) {
  2537. UCHAR byte;
  2538. unsigned j;
  2539. //
  2540. // Convert the current digit pair to hex
  2541. //
  2542. for(byte=0,j=i; j<i+2; j++) {
  2543. byte <<= 4;
  2544. if(isdigit(Value[j])) {
  2545. byte |= (UCHAR)Value[j] - (UCHAR)'0';
  2546. } else if((Value[j] >= 'a') && (Value[j] <= 'f')) {
  2547. byte |= (UCHAR)Value[j] - (UCHAR)'a' + (UCHAR)10;
  2548. } else if((Value[j] >= 'A') && (Value[j] <= 'F')) {
  2549. byte |= (UCHAR)Value[j] - (UCHAR)'A' + (UCHAR)10;
  2550. } else {
  2551. goto x1;
  2552. }
  2553. }
  2554. BufferUchar[i/2] = byte;
  2555. }
  2556. break;
  2557. case HwRegistryMultiSz:
  2558. //
  2559. // Calculate size of the buffer needed to hold all specified strings
  2560. //
  2561. BufferSize = 1;
  2562. i = 0;
  2563. Value = SlGetSectionLineIndex(InfHandle,SectionName,Line,OINDEX_FIRSTVALUE+i++);
  2564. while (Value) {
  2565. BufferSize += (ULONG)strlen(Value)+1;
  2566. Value = SlGetSectionLineIndex(InfHandle,SectionName,Line,OINDEX_FIRSTVALUE+i++);
  2567. }
  2568. //
  2569. // Allocate a buffer of appropriate size
  2570. //
  2571. Buffer = BlAllocateHeap(BufferSize);
  2572. BufferUchar = Buffer;
  2573. //
  2574. // Store each string in the buffer, converting to wide char format
  2575. // in the process
  2576. //
  2577. i = 0;
  2578. Value = SlGetSectionLineIndex(InfHandle,SectionName,Line,OINDEX_FIRSTVALUE+i++);
  2579. while(Value) {
  2580. strcpy((PCHAR)BufferUchar,Value);
  2581. BufferUchar += strlen(Value) + 1;
  2582. Value = SlGetSectionLineIndex(InfHandle,SectionName,Line,OINDEX_FIRSTVALUE+i++);
  2583. }
  2584. //
  2585. // Place final terminating nul in the buffer
  2586. //
  2587. *BufferUchar = 0;
  2588. break;
  2589. default:
  2590. x1:
  2591. //
  2592. // Error - bad type specified or maybe we detected bad data values
  2593. // and jumped here
  2594. //
  2595. return(NULL);
  2596. }
  2597. Reg = BlAllocateHeap(sizeof(DETECTED_DEVICE_REGISTRY));
  2598. Reg->ValueType = RegistryTypeMap[ValueType];
  2599. Reg->Buffer = Buffer;
  2600. Reg->BufferSize = BufferSize;
  2601. return(Reg);
  2602. }
  2603. PCHAR
  2604. SlPreInstallGetComponentName(
  2605. IN PVOID Inf,
  2606. IN PCHAR SectionName,
  2607. IN PTCHAR TargetName
  2608. )
  2609. /*++
  2610. Routine Description:
  2611. Determines the canonical short name for a component to be loaded for
  2612. this machine.
  2613. Arguments:
  2614. Inf - Handle to an inf file (retail or OEM).
  2615. SectionName - Supplies the name of the section (eg. [Computer])
  2616. TargetName - Supplies the ARC string to be matched (eg. "Digital DECpc AXP 150")
  2617. Return Value:
  2618. NULL - No match was found.
  2619. PCHAR - Pointer to the canonical shortname of the component.
  2620. --*/
  2621. {
  2622. ULONG i;
  2623. PTCHAR SearchName;
  2624. //
  2625. // If this is not an OEM component, then enumerate the entries in the
  2626. // section in txtsetup.sif
  2627. //
  2628. for (i=0;;i++) {
  2629. #ifdef UNICODE
  2630. SearchName = SlGetSectionLineIndexW(
  2631. #else
  2632. SearchName = SlGetSectionLineIndex(
  2633. #endif
  2634. Inf,
  2635. SectionName,
  2636. i,
  2637. 0 );
  2638. if (SearchName==NULL) {
  2639. //
  2640. // we have enumerated the entire section without finding a
  2641. // match, return failure.
  2642. //
  2643. return(NULL);
  2644. }
  2645. if (_tcsicmp(TargetName, SearchName) == 0) {
  2646. //
  2647. // we have a match
  2648. //
  2649. break;
  2650. }
  2651. }
  2652. //
  2653. // i is the index into the section of the short machine name
  2654. //
  2655. return(SlGetKeyName(Inf,
  2656. SectionName,
  2657. i));
  2658. }
  2659. ARC_STATUS
  2660. SlLoadWinPESection(
  2661. IN POEM_SOURCE_DEVICE OemSourceDevice,
  2662. IN PVOID OemInfHandle,
  2663. IN PCSTR OemSectionName,
  2664. IN PVOID InboxInfHandle,
  2665. IN PCSTR InboxSectionName,
  2666. IN BOOLEAN IsScsiSection,
  2667. IN POEMSCSIINFO* ScsiInfo, OPTIONAL
  2668. OUT PPNP_HARDWARE_ID* HardwareIdDatabase OPTIONAL
  2669. )
  2670. /*++
  2671. Routine Description:
  2672. Loads the oem drivers from the specified section in the
  2673. given OEM file name
  2674. Arguments:
  2675. OemSourceDevice : The device that has the drivers that need to
  2676. be loaded for WinPE.
  2677. OemInfHandle : Handle to the oem inf file
  2678. OemSectionName : The section name that needs to be loaded.
  2679. InboxInfHandle : The original setup inf handle (txtsetup.sif)
  2680. InboxSectionName : The section name, whose drivers are to be loaded
  2681. IsScsiSection : Indicates whether the driver being loaded is SCSI
  2682. miniport or not.
  2683. ScsiInfo - Returns a linked list containing info about any third-party scsi
  2684. drivers loaded.
  2685. HardwareIdDatabase - Hardware Ids of the device which the loaded driver supports
  2686. Return Value:
  2687. Appropriate ARC_STATUS
  2688. --*/
  2689. {
  2690. ARC_STATUS Status = EINVAL;
  2691. if (OemSourceDevice && OemInfHandle && OemSectionName && InboxInfHandle && InboxSectionName) {
  2692. CHAR Buffer[128];
  2693. ULONG EntryCount;
  2694. BOOLEAN Append = TRUE;
  2695. PCHAR SectionName = Buffer;
  2696. ULONG InsertIndex = 0;
  2697. Status = ESUCCESS;
  2698. strcpy(SectionName, OemSectionName);
  2699. strcat(SectionName, WINPE_REPLACE_SUFFIX_A);
  2700. //
  2701. // check if there is a .replace section
  2702. //
  2703. EntryCount = SlCountLinesInSection(OemInfHandle,
  2704. SectionName);
  2705. if (EntryCount && (EntryCount != BL_INF_FILE_ERROR)) {
  2706. Append = FALSE;
  2707. } else {
  2708. //
  2709. // check if there is a .append section
  2710. //
  2711. strcpy(SectionName, OemSectionName);
  2712. strcat(SectionName, WINPE_APPEND_SUFFIX_A);
  2713. EntryCount = SlCountLinesInSection(OemInfHandle,
  2714. SectionName);
  2715. }
  2716. //
  2717. // if append was requested then load the inbox
  2718. // drivers first
  2719. //
  2720. if (Append) {
  2721. Status = SlLoadSection(InboxInfHandle,
  2722. InboxSectionName,
  2723. IsScsiSection,
  2724. TRUE,
  2725. &InsertIndex);
  2726. }
  2727. //
  2728. // load the non-pnp oem drivers if any
  2729. //
  2730. if ((Status == ESUCCESS) && EntryCount && (EntryCount != BL_INF_FILE_ERROR)) {
  2731. Status = SlLoadSection(OemInfHandle,
  2732. SectionName,
  2733. IsScsiSection,
  2734. FALSE,
  2735. &InsertIndex);
  2736. }
  2737. //
  2738. // load the pnp oem drivers
  2739. //
  2740. if (IsScsiSection && ScsiInfo && HardwareIdDatabase) {
  2741. EntryCount = SlCountLinesInSection(OemInfHandle,
  2742. WINPE_OEMDRIVER_PARAMS_A);
  2743. //
  2744. // Try to load the driver only if present
  2745. //
  2746. if (EntryCount && (EntryCount != BL_INF_FILE_ERROR)) {
  2747. BOOLEAN Result;
  2748. ULONG OldDeviceType = OemSourceDevice->DeviceType;
  2749. //
  2750. // We mark the device type as dynupdate device type
  2751. // so that the fully qualified driver root directory is
  2752. // used while loading MSDs
  2753. //
  2754. SL_OEM_SET_SOURCE_DEVICE_TYPE(OemSourceDevice,
  2755. (SL_OEM_SOURCE_DEVICE_TYPE_LOCAL |
  2756. SL_OEM_SOURCE_DEVICE_TYPE_FIXED |
  2757. SL_OEM_SOURCE_DEVICE_TYPE_DYN_UPDATE));
  2758. Result = SlLoadOemScsiDriversUnattended(OemSourceDevice,
  2759. OemInfHandle,
  2760. WINPE_OEMDRIVER_PARAMS_A,
  2761. WINPE_OEMDRIVER_ROOTDIR_A,
  2762. WINPE_OEMDRIVER_DIRS_A,
  2763. ScsiInfo,
  2764. HardwareIdDatabase);
  2765. //
  2766. // Restore the old device type
  2767. //
  2768. SL_OEM_SET_SOURCE_DEVICE_TYPE(OemSourceDevice,
  2769. OldDeviceType);
  2770. if (!Result) {
  2771. Status = EINVAL;
  2772. }
  2773. }
  2774. }
  2775. }
  2776. return Status;
  2777. }
  2778. ARC_STATUS
  2779. SlInitOemSourceDevices(
  2780. OUT POEM_SOURCE_DEVICE *OemSourceDevices,
  2781. OUT POEM_SOURCE_DEVICE *DefaultSourceDevice
  2782. )
  2783. /*++
  2784. Routine Description:
  2785. This routine scans the devices to figure out which
  2786. are the OEM source devices and creates a list of
  2787. such devices.
  2788. Arguments:
  2789. OemSourceDevices - Place holder for receiving the
  2790. linked list of OEM source devices.
  2791. DefaultSourceDevice - Place holder for the OEM source
  2792. device which will be used as the default device
  2793. while trying to load OEM drivers / HAL -- generally
  2794. floppy(0).
  2795. Return Value:
  2796. Returns the appropriate ARC_STATUS error code.
  2797. --*/
  2798. {
  2799. ARC_STATUS Status = EINVAL;
  2800. if (OemSourceDevices && DefaultSourceDevice) {
  2801. ULONG Index = 0;
  2802. CHAR ArcDeviceName[128];
  2803. POEM_SOURCE_DEVICE OemDevices = NULL;
  2804. ArcDeviceName[0] = '\0';
  2805. Status = ESUCCESS;
  2806. //
  2807. // We may not find any devices
  2808. //
  2809. *OemSourceDevices = *DefaultSourceDevice = NULL;
  2810. //
  2811. // Iterate through all the floppy drives and make them
  2812. // oem source devices
  2813. //
  2814. while (ESUCCESS == Status) {
  2815. POEM_SOURCE_DEVICE NewDevice;
  2816. //
  2817. // Scan for atleast minimum number for floppies
  2818. //
  2819. if (!SlpFindFloppy(Index, ArcDeviceName)) {
  2820. if ((Index + 1) < MinimumFloppiesToScan) {
  2821. Index++;
  2822. continue;
  2823. } else {
  2824. break;
  2825. }
  2826. }
  2827. NewDevice = BlAllocateHeap(sizeof(OEM_SOURCE_DEVICE));
  2828. if (!NewDevice) {
  2829. Status = ENOMEM;
  2830. } else {
  2831. ARC_STATUS OpenStatus;
  2832. ULONG DeviceId;
  2833. ULONG DeviceType = (SL_OEM_SOURCE_DEVICE_TYPE_LOCAL |
  2834. SL_OEM_SOURCE_DEVICE_TYPE_REMOVABLE);
  2835. memset(NewDevice, 0, sizeof(OEM_SOURCE_DEVICE));
  2836. strcpy(NewDevice->ArcDeviceName, ArcDeviceName);
  2837. //
  2838. // Assume we are not going to use device id
  2839. //
  2840. NewDevice->DeviceId = SL_OEM_DEVICE_ORDINAL;
  2841. //
  2842. // Treat all the floppy drives which are greater than 0
  2843. // as virtual floppy drives
  2844. //
  2845. if (Index >= VirtualFloppyStart) {
  2846. DeviceType |= SL_OEM_SOURCE_DEVICE_TYPE_VIRTUAL;
  2847. }
  2848. //
  2849. // Currently we only use local removable media for
  2850. // OEM drivers
  2851. //
  2852. SL_OEM_SET_SOURCE_DEVICE_TYPE(NewDevice, DeviceType);
  2853. SL_OEM_SET_SOURCE_DEVICE_STATE(NewDevice,
  2854. SL_OEM_SOURCE_DEVICE_NOT_PROCESSED);
  2855. OpenStatus = ArcOpen(ArcDeviceName,
  2856. ArcOpenReadOnly,
  2857. &DeviceId);
  2858. if (ESUCCESS == OpenStatus) {
  2859. CHAR InfPath[128];
  2860. ULONG FileId;
  2861. ULONG MediaType = SL_OEM_SOURCE_MEDIA_PRESENT;
  2862. strcpy(InfPath, "\\");
  2863. strcat(InfPath, TXTSETUP_OEM_FILENAME);
  2864. //
  2865. // Verify if the file is present
  2866. //
  2867. OpenStatus = BlOpen(DeviceId,
  2868. InfPath,
  2869. ArcOpenReadOnly,
  2870. &FileId);
  2871. if (ESUCCESS == OpenStatus) {
  2872. PVOID InfHandle = NULL;
  2873. ULONG ErrorLine = 0;
  2874. //
  2875. // We don't need file handle any more
  2876. //
  2877. BlClose(FileId);
  2878. //
  2879. // Open and parse the txtsetup.oem file
  2880. //
  2881. OpenStatus = SlInitIniFile(NULL,
  2882. DeviceId,
  2883. InfPath,
  2884. &InfHandle,
  2885. NULL,
  2886. 0,
  2887. &ErrorLine);
  2888. if (ESUCCESS == OpenStatus) {
  2889. PCHAR StrValue;
  2890. MediaType |= SL_OEM_SOURCE_MEDIA_HAS_DRIVERS;
  2891. NewDevice->InfHandle = InfHandle;
  2892. NewDevice->DeviceId = DeviceId;
  2893. StrValue = SlGetSectionKeyIndex(InfHandle,
  2894. TXTSETUP_OEM_DEFAULTS,
  2895. TXTSETUP_OEM_DEFAULTS_COMPUTER,
  2896. 0);
  2897. if (StrValue) {
  2898. MediaType |= (SL_OEM_SOURCE_MEDIA_HAS_DEFAULT |
  2899. SL_OEM_SOURCE_MEDIA_HAS_HAL);
  2900. }
  2901. StrValue = SlGetSectionKeyIndex(InfHandle,
  2902. TXTSETUP_OEM_DEFAULTS,
  2903. TXTSETUP_OEM_DEFAULTS_SCSI,
  2904. 0);
  2905. if (StrValue) {
  2906. MediaType |= (SL_OEM_SOURCE_MEDIA_HAS_DEFAULT |
  2907. SL_OEM_SOURCE_MEDIA_HAS_MSD);
  2908. }
  2909. } else {
  2910. //
  2911. // Inform the user about the error & abort ?
  2912. //
  2913. MediaType |= SL_OEM_SOURCE_MEDIA_NO_DRIVERS;
  2914. }
  2915. //
  2916. // close the device if not needed
  2917. //
  2918. if (NewDevice->DeviceId != DeviceId) {
  2919. ArcClose(DeviceId);
  2920. }
  2921. //
  2922. // Mark the device state as scanned
  2923. //
  2924. SL_OEM_SET_SOURCE_DEVICE_STATE(NewDevice,
  2925. SL_OEM_SOURCE_DEVICE_SCANNED);
  2926. }
  2927. SL_OEM_SET_SOURCE_MEDIA_TYPE(NewDevice,
  2928. MediaType);
  2929. } else {
  2930. SL_OEM_SET_SOURCE_MEDIA_TYPE(NewDevice,
  2931. SL_OEM_SOURCE_MEDIA_ABSENT);
  2932. }
  2933. //
  2934. // insert the new device at the head of the linked list
  2935. //
  2936. if (!OemDevices) {
  2937. OemDevices = NewDevice;
  2938. } else {
  2939. NewDevice->Next = OemDevices;
  2940. OemDevices = NewDevice;
  2941. }
  2942. //
  2943. // Currently floppy0 is the default OEM source device
  2944. //
  2945. if (Index == 0) {
  2946. *DefaultSourceDevice = NewDevice;
  2947. }
  2948. //
  2949. // Process next floppy drive
  2950. //
  2951. Index++;
  2952. ArcDeviceName[0] = '\0';
  2953. }
  2954. }
  2955. if (ESUCCESS == Status) {
  2956. *OemSourceDevices = OemDevices;
  2957. }
  2958. }
  2959. return Status;
  2960. }
  2961. BOOLEAN
  2962. SlProcessDriversToLoad(
  2963. IN POEM_SOURCE_DEVICE OemSourceDevice,
  2964. OUT PPNP_HARDWARE_ID * HardwareIdDatabaseList,
  2965. OUT POEMSCSIINFO* OemScsiInfo,
  2966. IN BOOLEAN LoadMultipleDrivers
  2967. )
  2968. /*++
  2969. Routine Description:
  2970. This routine scans the oem source device and loads all the drivers
  2971. as specified by the DriverLoadList key in the [Defaults] section of
  2972. the txtsetup.oem file.
  2973. It is of the format
  2974. [Defaults]
  2975. DriverLoadList = driverid1, driverid2
  2976. Arguments:
  2977. OemSourceDevice - The OEM source device we want to process.
  2978. HardwareIdDatabase - The hardware IDs what were loaded for the particular
  2979. driver.
  2980. OemScsiInfo - Placeholder for receiving the list OEMSCSIINFO
  2981. list, which has the driver base and driver name for each
  2982. driver loaded.
  2983. LoadMultipleDrivers - Flag which indicates whether we are processing the
  2984. DriverLoadList or a single entry in the [Default] section.
  2985. Return Value:
  2986. Returns the appropriate BOOLEAN status code.
  2987. TRUE(Success)/FALSE(Failure)
  2988. --*/
  2989. {
  2990. BOOLEAN LoadResult = FALSE;
  2991. BOOLEAN DriverLoaded = FALSE;
  2992. if (OemSourceDevice &&
  2993. HardwareIdDatabaseList &&
  2994. OemScsiInfo &&
  2995. OemSourceDevice->InfHandle){
  2996. ULONG DriverIdIndex = 0;
  2997. PCHAR DriverId = NULL;
  2998. POEMSCSIINFO CurrOemScsi = NULL;
  2999. POEMSCSIINFO OemScsiLocalList = NULL;
  3000. //
  3001. // If we are processing DriverLoadList from [defaults] section only then
  3002. // process it otherwise we want to process the [defaults] section normally.
  3003. //
  3004. if (LoadMultipleDrivers){
  3005. DriverId = SlGetSectionKeyIndex(OemSourceDevice->InfHandle,
  3006. TXTSETUP_OEM_DEFAULTS,
  3007. TXTSETUP_OEM_DEFAULTS_DRIVERLOADLIST,
  3008. DriverIdIndex);
  3009. //
  3010. // In case no entry was specified in the DriverLoadList fall back
  3011. // on the default entry.
  3012. //
  3013. if (!DriverId || (DriverId[0] == 0)){
  3014. LoadMultipleDrivers = FALSE;
  3015. }
  3016. }
  3017. //
  3018. // Process all the Driver Id's specified or process for a single entry in case
  3019. // we are processing the [Defaults] section.
  3020. //
  3021. while((DriverId && (DriverId)[0])||
  3022. (!LoadMultipleDrivers)){
  3023. DETECTED_DEVICE DetectedDevice = {0};
  3024. PTCHAR DriverDescription = NULL;
  3025. PPNP_HARDWARE_ID HardwareIdDatabase = NULL;
  3026. PVOID ImageBase = NULL;
  3027. PCHAR ImageName = NULL;
  3028. //
  3029. // Load the driver and related files, in an unattended manner
  3030. //
  3031. LoadResult = SlpOemDiskette(OemSourceDevice,
  3032. "SCSI",
  3033. OEMSCSI,
  3034. LoaderBootDriver,
  3035. 0,
  3036. &DetectedDevice,
  3037. &ImageBase,
  3038. &ImageName,
  3039. &DriverDescription,
  3040. FALSE,
  3041. NULL,
  3042. &HardwareIdDatabase,
  3043. NULL,
  3044. TRUE,
  3045. DriverId); // if present indicates the DriverId to override
  3046. if (LoadResult) {
  3047. //
  3048. // If the load was successful, then create and add the information
  3049. // ScsiInfo
  3050. //
  3051. POEMSCSIINFO NewScsi = (POEMSCSIINFO)BlAllocateHeap(sizeof(OEMSCSIINFO));
  3052. if (!NewScsi) {
  3053. SlNoMemoryError();
  3054. LoadResult = FALSE;
  3055. break;
  3056. }
  3057. RtlZeroMemory(NewScsi, sizeof(OEMSCSIINFO));
  3058. NewScsi->ScsiBase = ImageBase;
  3059. NewScsi->ScsiName = ImageName;
  3060. if (CurrOemScsi) {
  3061. CurrOemScsi->Next = NewScsi;
  3062. } else {
  3063. OemScsiLocalList = NewScsi;
  3064. }
  3065. CurrOemScsi = NewScsi;
  3066. if (HardwareIdDatabase){
  3067. PPNP_HARDWARE_ID TempHwIdPtr = HardwareIdDatabase;
  3068. while (HardwareIdDatabase->Next) {
  3069. HardwareIdDatabase = HardwareIdDatabase->Next;
  3070. }
  3071. HardwareIdDatabase->Next = *HardwareIdDatabaseList;
  3072. *HardwareIdDatabaseList = TempHwIdPtr;
  3073. }
  3074. //
  3075. // At least one driver got loaded successfully.
  3076. //
  3077. DriverLoaded = TRUE;
  3078. }
  3079. //
  3080. // If we are not processing the DriverLoadList then we need
  3081. // to break from the loop as we process just one entry.
  3082. // Else
  3083. // Get the next driver entry to be processed.
  3084. //
  3085. if (!LoadMultipleDrivers){
  3086. break;
  3087. } else {
  3088. //
  3089. // Get the next driver Id to process.
  3090. //
  3091. DriverIdIndex++;
  3092. DriverId = SlGetSectionKeyIndex(OemSourceDevice->InfHandle,
  3093. TXTSETUP_OEM_DEFAULTS,
  3094. TXTSETUP_OEM_DEFAULTS_DRIVERLOADLIST,
  3095. DriverIdIndex);
  3096. }
  3097. }
  3098. if (DriverLoaded && OemScsiLocalList){
  3099. *OemScsiInfo = OemScsiLocalList;
  3100. }
  3101. }
  3102. return DriverLoaded;
  3103. }
  3104. BOOLEAN
  3105. SlIsDriverLoadListPresent(
  3106. IN PVOID InfHandle
  3107. )
  3108. /*++
  3109. Routine Description:
  3110. This routine checks if the [Defaults] section of
  3111. the txtsetup.oem file has a DriverLoadList key with atleast one valid value.
  3112. [Defaults]
  3113. DriverLoadList = driverid1, driverid2
  3114. Arguments:
  3115. InfHandle - Handle to the txtsetup.oem file.
  3116. Return Value:
  3117. Appropriate BOOLEAN status.
  3118. TRUE/FALSE.
  3119. --*/
  3120. {
  3121. PCHAR StrValue = NULL;
  3122. if (InfHandle){
  3123. StrValue = SlGetSectionKeyIndex(InfHandle,
  3124. TXTSETUP_OEM_DEFAULTS,
  3125. TXTSETUP_OEM_DEFAULTS_DRIVERLOADLIST,
  3126. 0);
  3127. }
  3128. return((StrValue && (StrValue[0] != 0)) ? TRUE : FALSE);
  3129. }
  3130. ARC_STATUS
  3131. SlLoadOemScsiDriversFromOemSources(
  3132. IN POEM_SOURCE_DEVICE OemSourceDevices,
  3133. IN OUT PPNP_HARDWARE_ID *HardwareIds,
  3134. OUT POEMSCSIINFO *OemScsiInfo
  3135. )
  3136. /*++
  3137. Routine Description:
  3138. Goes through each of the OEM source device and loads the
  3139. default drivers, if any.
  3140. Arguments:
  3141. OemSourceDevices - List of OEM source devices.
  3142. HardwareIds - List of all the hardware IDs of the devices which
  3143. are controlled by the drivers which were loaded.
  3144. OemScsiInfo - Placeholder for receiving the list OEMSCSIINFO
  3145. list, which has the driver base and driver name for each
  3146. driver loaded.
  3147. Return Value:
  3148. Returns the appropriate ARC_STATUS error code.
  3149. --*/
  3150. {
  3151. ARC_STATUS Status = EINVAL;
  3152. if (OemSourceDevices && OemScsiInfo) {
  3153. POEM_SOURCE_DEVICE CurrDevice = OemSourceDevices;
  3154. POEMSCSIINFO DeviceOemScsiInfo = NULL;
  3155. POEMSCSIINFO LastOemScsiNode = NULL;
  3156. Status = ESUCCESS;
  3157. while (CurrDevice) {
  3158. //
  3159. // Only process those devices which are not processed yet
  3160. // and which are not dynamic update source devices and
  3161. // not marked to be skipped.
  3162. //
  3163. if (!SL_OEM_SOURCE_DEVICE_STATE(CurrDevice,
  3164. SL_OEM_SOURCE_DEVICE_PROCESSED) &&
  3165. !SL_OEM_SOURCE_DEVICE_TYPE(CurrDevice,
  3166. SL_OEM_SOURCE_DEVICE_TYPE_DYN_UPDATE) &&
  3167. !SL_OEM_SOURCE_DEVICE_STATE(CurrDevice,
  3168. SL_OEM_SOURCE_DEVICE_SKIPPED)
  3169. ) {
  3170. //
  3171. // Does the device has MSD with default entry ?
  3172. //
  3173. if (SL_OEM_SOURCE_MEDIA_TYPE(CurrDevice,
  3174. SL_OEM_SOURCE_MEDIA_HAS_DRIVERS) &&
  3175. SL_OEM_SOURCE_MEDIA_TYPE(CurrDevice,
  3176. SL_OEM_SOURCE_MEDIA_HAS_DEFAULT) &&
  3177. SL_OEM_SOURCE_MEDIA_TYPE(CurrDevice,
  3178. SL_OEM_SOURCE_MEDIA_HAS_MSD)) {
  3179. BOOLEAN Result = FALSE;
  3180. POEMSCSIINFO OemScsiInfoLocal = NULL;
  3181. //
  3182. // Load drivers specified in the DriverLoadList key.
  3183. // We make no distinction between virual oem source devices and floppies
  3184. // hence we make no distinction between loading drivers from them.
  3185. //
  3186. Result = SlProcessDriversToLoad(CurrDevice,
  3187. HardwareIds,
  3188. &OemScsiInfoLocal,
  3189. SlIsDriverLoadListPresent(CurrDevice->InfHandle));
  3190. //
  3191. // If we are successful in loading even a single driver from
  3192. // the DriverLoadList ( in case we intended to load the driver list)
  3193. // or
  3194. // the driver specified by the default section in the default behavior case
  3195. // mark the device as processed.
  3196. //
  3197. if(Result){
  3198. //
  3199. // Add the oem source device list to the global list.
  3200. //
  3201. if (OemScsiInfoLocal){
  3202. //
  3203. // Initialize head if necessary
  3204. //
  3205. if (!DeviceOemScsiInfo) {
  3206. DeviceOemScsiInfo = OemScsiInfoLocal;
  3207. }
  3208. //
  3209. // Merge the current linked list with the
  3210. // full OEM source device linked list
  3211. //
  3212. if (LastOemScsiNode) {
  3213. LastOemScsiNode->Next = OemScsiInfoLocal;
  3214. } else {
  3215. LastOemScsiNode = OemScsiInfoLocal;
  3216. }
  3217. //
  3218. // NOTE : We need to maintain the linked list
  3219. // in the order the drivers were loaded so
  3220. // search for the last node in the current list
  3221. // and keep last node pointer around for the
  3222. // merge for next iteration.
  3223. //
  3224. while (LastOemScsiNode->Next) {
  3225. LastOemScsiNode = LastOemScsiNode->Next;
  3226. }
  3227. }
  3228. //
  3229. // Mark the oem source device state, as processed
  3230. //
  3231. SL_OEM_SET_SOURCE_DEVICE_STATE(CurrDevice,
  3232. SL_OEM_SOURCE_DEVICE_PROCESSED);
  3233. } else {
  3234. //
  3235. // Make the oem source device state as skipped so that
  3236. // we don't create virtual oem source device for it
  3237. //
  3238. SL_OEM_SET_SOURCE_DEVICE_STATE(CurrDevice,
  3239. SL_OEM_SOURCE_DEVICE_SKIPPED);
  3240. }
  3241. }
  3242. }
  3243. CurrDevice = CurrDevice->Next;
  3244. }
  3245. //
  3246. // Initialize the return argument irrespective of
  3247. // status code since we might have loaded some drivers
  3248. // and would like to use it anyway
  3249. //
  3250. *OemScsiInfo = DeviceOemScsiInfo;
  3251. }
  3252. return Status;
  3253. }
  3254. ARC_STATUS
  3255. SlInitVirtualOemSourceDevices(
  3256. IN PSETUP_LOADER_BLOCK SetupLoaderBlock,
  3257. IN POEM_SOURCE_DEVICE OemSourceDevices
  3258. )
  3259. /*++
  3260. Routine Description:
  3261. Goes through each of the OEM source devices and creates
  3262. another linked list of virtual OEM source devices.
  3263. This list is put in the loader block for setupdd.sys
  3264. to inform the RAM disk driver to create virtual devices
  3265. under NT to read drivers of this device.
  3266. NOTE : Currently we allocate memory for the whole virtual
  3267. device and replicate its contents into the allocated memory.
  3268. We do this because we don't want OEMs to write separate
  3269. NT driver to read from the virtual device under NT.
  3270. We also limit the size of each virtual device to be 3MB
  3271. at the max.
  3272. Arguments:
  3273. SetupLoaderBlock - Setup loader block
  3274. OemSourceDevices - The list of OEM source devices identified
  3275. by the setupldr.
  3276. Return Value:
  3277. Returns the appropriate ARC_STATUS error code.
  3278. --*/
  3279. {
  3280. ARC_STATUS Status = EINVAL;
  3281. if (SetupLoaderBlock && OemSourceDevices) {
  3282. PDETECTED_OEM_SOURCE_DEVICE OemVirtualDevices = NULL;
  3283. PDETECTED_OEM_SOURCE_DEVICE NewVirtualDevice = NULL;
  3284. POEM_SOURCE_DEVICE CurrentDevice = OemSourceDevices;
  3285. Status = ESUCCESS;
  3286. while (CurrentDevice) {
  3287. //
  3288. // Process only those devices which are virtual
  3289. // and have drivers in them and which were not skipped
  3290. //
  3291. if (SL_OEM_SOURCE_DEVICE_TYPE(CurrentDevice,
  3292. SL_OEM_SOURCE_DEVICE_TYPE_VIRTUAL) &&
  3293. SL_OEM_SOURCE_MEDIA_TYPE(CurrentDevice,
  3294. SL_OEM_SOURCE_MEDIA_HAS_DRIVERS) &&
  3295. !SL_OEM_SOURCE_DEVICE_STATE(CurrentDevice,
  3296. SL_OEM_SOURCE_DEVICE_SKIPPED)) {
  3297. ULONGLONG ImageSize = 0;
  3298. PVOID ImageBase = NULL;
  3299. ULONG DeviceId = SL_OEM_DEVICE_ORDINAL;
  3300. FILE_INFORMATION FileInfo = {0};
  3301. LARGE_INTEGER Start = {0};
  3302. //
  3303. // Open the device, only if needed
  3304. //
  3305. if (CurrentDevice->DeviceId == SL_OEM_DEVICE_ORDINAL) {
  3306. Status = ArcOpen(CurrentDevice->ArcDeviceName,
  3307. ArcOpenReadOnly,
  3308. &DeviceId);
  3309. } else {
  3310. DeviceId = CurrentDevice->DeviceId;
  3311. }
  3312. if (Status != ESUCCESS) {
  3313. break;
  3314. }
  3315. //
  3316. // Rewind the device
  3317. //
  3318. Status = ArcSeek(DeviceId, &Start, SeekAbsolute);
  3319. if (Status != ESUCCESS) {
  3320. break;
  3321. }
  3322. //
  3323. // Get the device size
  3324. //
  3325. Status = ArcGetFileInformation(DeviceId,
  3326. &FileInfo);
  3327. if (Status != ESUCCESS) {
  3328. break;
  3329. }
  3330. //
  3331. // Allocate the memory for the disk image
  3332. //
  3333. ImageSize = FileInfo.EndingAddress.QuadPart;
  3334. //
  3335. // NOTE : At the max we only allow 3MB per
  3336. // virtual device (should be only one device
  3337. // in most of the cases)
  3338. //
  3339. if (ImageSize > 0x300000) {
  3340. Status = E2BIG;
  3341. } else {
  3342. #ifdef _X86_
  3343. ULONG HeapPage = 0;
  3344. //
  3345. // NOTE : Allocate "LoaderFirmwarePermanent" memory
  3346. // so that memory manager while initializing doesn't
  3347. // reclaim this memory. This also helps us to avoid
  3348. // double copy -- i.e. this is the only location
  3349. // where we read the device contents into memory and
  3350. // this memory is valid through out the textmode setup.
  3351. //
  3352. // If we didn't allocate loader firmware permanent memory
  3353. // then setupdd.sys would have to allocate paged pool memory
  3354. // and replicate the contents from the loader block during
  3355. // initialization.
  3356. //
  3357. Status = BlAllocateDescriptor(
  3358. LoaderFirmwarePermanent,
  3359. 0,
  3360. (ULONG)(ROUND_TO_PAGES(ImageSize) >> PAGE_SHIFT),
  3361. (PULONG)&HeapPage);
  3362. if (Status == ESUCCESS) {
  3363. ImageBase = (PVOID)(KSEG0_BASE | (HeapPage << PAGE_SHIFT));
  3364. }
  3365. #else
  3366. //
  3367. // NOTE : 05/13/2001 LoaderFirmwarePermanent doesn't seem to work on non
  3368. // x86 platforsm (particularly IA64). Till this issue is resolved
  3369. // we have to allocate memory from regular heap and we have to
  3370. // replicate the memory in setupdd!SpInitialize0(..)
  3371. //
  3372. ImageBase = BlAllocateHeap((ULONG)ImageSize);
  3373. if (!ImageBase) {
  3374. Status = ENOMEM;
  3375. }
  3376. #endif
  3377. if (Status != ESUCCESS) {
  3378. break;
  3379. }
  3380. if (ImageBase) {
  3381. ULONG BytesRead = 0;
  3382. RtlZeroMemory(ImageBase, (ULONG)ImageSize);
  3383. //
  3384. // Read the whole device image in a single call
  3385. //
  3386. Status = ArcRead(DeviceId,
  3387. ImageBase,
  3388. (ULONG)ImageSize,
  3389. &BytesRead);
  3390. //
  3391. // NOTE : The approximate device size may
  3392. // be bigger than the media size. So if we
  3393. // read atleast some bytes then we assume
  3394. // we are fine.
  3395. //
  3396. if ((BytesRead > 0) && (Status != ESUCCESS)) {
  3397. Status = ESUCCESS;
  3398. }
  3399. } else {
  3400. Status = ENOMEM;
  3401. }
  3402. }
  3403. if (Status != ESUCCESS) {
  3404. break;
  3405. }
  3406. //
  3407. // Create a new virtual device node and put it in the
  3408. // list of virtual devices
  3409. //
  3410. NewVirtualDevice = BlAllocateHeap(sizeof(DETECTED_OEM_SOURCE_DEVICE));
  3411. RtlZeroMemory(NewVirtualDevice, sizeof(DETECTED_OEM_SOURCE_DEVICE));
  3412. if (NewVirtualDevice == NULL) {
  3413. Status = ENOMEM;
  3414. break;
  3415. }
  3416. NewVirtualDevice->ArcDeviceName = SlCopyStringA(CurrentDevice->ArcDeviceName);
  3417. NewVirtualDevice->ImageBase = ImageBase;
  3418. NewVirtualDevice->ImageSize = ImageSize;
  3419. DbgPrint("SETUPLDR: Virtual Device => %s (base:%p, size:%d)\n",
  3420. NewVirtualDevice->ArcDeviceName,
  3421. ImageBase,
  3422. (ULONG)ImageSize);
  3423. //
  3424. // Add the new device at the head of the linked list
  3425. //
  3426. if (!OemVirtualDevices) {
  3427. OemVirtualDevices = NewVirtualDevice;
  3428. } else {
  3429. NewVirtualDevice->Next = OemVirtualDevices;
  3430. OemVirtualDevices = NewVirtualDevice;
  3431. }
  3432. }
  3433. //
  3434. // go on to next OEM source device
  3435. //
  3436. CurrentDevice = CurrentDevice->Next;
  3437. }
  3438. if (Status == ESUCCESS) {
  3439. SetupLoaderBlock->OemSourceDevices = OemVirtualDevices;
  3440. }
  3441. }
  3442. return Status;
  3443. }