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

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