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.

4104 lines
114 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. biosdrv.c
  5. Abstract:
  6. Provides the ARC emulation routines for I/O to a device supported by
  7. real-mode INT 13h BIOS calls.
  8. Author:
  9. John Vert (jvert) 7-Aug-1991
  10. Revision History:
  11. Allen Kay (akay) 19-May-1999
  12. --*/
  13. #include "arccodes.h"
  14. #include "stdlib.h"
  15. #include "string.h"
  16. #if defined(_IA64_)
  17. #include "bootia64.h"
  18. #endif
  19. #if defined(_X86_)
  20. #include "bootx86.h"
  21. #endif
  22. #include "bootefi.h"
  23. #include "biosdrv.h"
  24. #include "efi.h"
  25. #include "efip.h"
  26. #include "flop.h"
  27. //
  28. // Externals
  29. //
  30. extern VOID FlipToVirtual();
  31. extern VOID FlipToPhysical();
  32. extern ULONGLONG CompareGuid();
  33. extern BOOT_CONTEXT BootContext;
  34. extern EFI_HANDLE EfiImageHandle;
  35. extern EFI_SYSTEM_TABLE *EfiST;
  36. extern EFI_BOOT_SERVICES *EfiBS;
  37. extern EFI_RUNTIME_SERVICES *EfiRS;
  38. extern EFI_GUID EfiDevicePathProtocol;
  39. extern EFI_GUID EfiBlockIoProtocol;
  40. extern EFI_GUID EfiDiskIoProtocol;
  41. extern EFI_GUID EfiLoadedImageProtocol;
  42. extern EFI_GUID EfiFilesystemProtocol;
  43. extern
  44. ULONG GetDevPathSize(
  45. IN EFI_DEVICE_PATH *DevPath
  46. );
  47. #if 0
  48. #define DBGOUT(x) BlPrint x
  49. #define DBGPAUSE while(!GET_KEY());
  50. #else
  51. #define DBGOUT(x)
  52. #define DBGPAUSE
  53. #endif
  54. //
  55. // defines for doing console I/O
  56. //
  57. #define CSI 0x95
  58. #define SGR_INVERSE 7
  59. #define SGR_NORMAL 0
  60. //
  61. // define for FloppyOpenMode
  62. //
  63. #define FloppyOpenMode 0xCDEFABCD
  64. //
  65. // static data for console I/O
  66. //
  67. BOOLEAN ControlSequence=FALSE;
  68. BOOLEAN EscapeSequence=FALSE;
  69. BOOLEAN FontSelection=FALSE;
  70. BOOLEAN HighIntensity=FALSE;
  71. BOOLEAN Blink=FALSE;
  72. ULONG PCount=0;
  73. #define CONTROL_SEQUENCE_MAX_PARAMETER 10
  74. ULONG Parameter[CONTROL_SEQUENCE_MAX_PARAMETER];
  75. #define KEY_INPUT_BUFFER_SIZE 16
  76. UCHAR KeyBuffer[KEY_INPUT_BUFFER_SIZE];
  77. ULONG KeyBufferEnd=0;
  78. ULONG KeyBufferStart=0;
  79. //
  80. // array for translating between ANSI colors and the VGA standard
  81. //
  82. UCHAR TranslateColor[] = {0,4,2,6,1,5,3,7};
  83. ARC_STATUS
  84. BiosDiskClose(
  85. IN ULONG FileId
  86. );
  87. VOID
  88. BiosConsoleFillBuffer(
  89. IN ULONG Key
  90. );
  91. #define DEVICE_NOT_FOUND 0xFEEBEE
  92. #ifdef FORCE_CD_BOOT
  93. EFI_HANDLE
  94. GetCdTest(
  95. VOID
  96. );
  97. #endif
  98. ULONG
  99. FindAtapiDevice(
  100. ULONGLONG *pDevicePaths,
  101. ULONG nDevicePaths,
  102. ULONG PrimarySecondary,
  103. ULONG SlaveMaster,
  104. ULONG Lun
  105. );
  106. ULONG
  107. FindScsiDevice(
  108. ULONGLONG *pDevicePaths,
  109. ULONG nDevicePaths,
  110. ULONG Pun,
  111. ULONG Lun
  112. );
  113. //
  114. // Buffer for temporary storage of data read from the disk that needs
  115. // to end up in a location above the 1MB boundary.
  116. //
  117. // NOTE: it is very important that this buffer not cross a 64k boundary.
  118. //
  119. PUCHAR LocalBuffer=NULL;
  120. //
  121. // There are two sorts of things we can open in this module, disk partitions,
  122. // and raw disk devices. The following device entry tables are
  123. // used for these things.
  124. //
  125. BL_DEVICE_ENTRY_TABLE BiosPartitionEntryTable =
  126. {
  127. (PARC_CLOSE_ROUTINE)BiosPartitionClose,
  128. (PARC_MOUNT_ROUTINE)BlArcNotYetImplemented,
  129. (PARC_OPEN_ROUTINE)BiosPartitionOpen,
  130. (PARC_READ_ROUTINE)BiosPartitionRead,
  131. (PARC_READ_STATUS_ROUTINE)BlArcNotYetImplemented,
  132. (PARC_SEEK_ROUTINE)BiosPartitionSeek,
  133. (PARC_WRITE_ROUTINE)BiosPartitionWrite,
  134. (PARC_GET_FILE_INFO_ROUTINE)BiosPartitionGetFileInfo,
  135. (PARC_SET_FILE_INFO_ROUTINE)BlArcNotYetImplemented,
  136. (PRENAME_ROUTINE)BlArcNotYetImplemented,
  137. (PARC_GET_DIRECTORY_ENTRY_ROUTINE)BlArcNotYetImplemented,
  138. (PBOOTFS_INFO)BlArcNotYetImplemented
  139. };
  140. BL_DEVICE_ENTRY_TABLE BiosDiskEntryTable =
  141. {
  142. (PARC_CLOSE_ROUTINE)BiosDiskClose,
  143. (PARC_MOUNT_ROUTINE)BlArcNotYetImplemented,
  144. (PARC_OPEN_ROUTINE)BiosDiskOpen,
  145. (PARC_READ_ROUTINE)BiosDiskRead,
  146. (PARC_READ_STATUS_ROUTINE)BlArcNotYetImplemented,
  147. (PARC_SEEK_ROUTINE)BiosPartitionSeek,
  148. (PARC_WRITE_ROUTINE)BiosDiskWrite,
  149. (PARC_GET_FILE_INFO_ROUTINE)BiosDiskGetFileInfo,
  150. (PARC_SET_FILE_INFO_ROUTINE)BlArcNotYetImplemented,
  151. (PRENAME_ROUTINE)BlArcNotYetImplemented,
  152. (PARC_GET_DIRECTORY_ENTRY_ROUTINE)BlArcNotYetImplemented,
  153. (PBOOTFS_INFO)BlArcNotYetImplemented
  154. };
  155. BL_DEVICE_ENTRY_TABLE BiosEDDSEntryTable =
  156. {
  157. (PARC_CLOSE_ROUTINE)BiosDiskClose,
  158. (PARC_MOUNT_ROUTINE)BlArcNotYetImplemented,
  159. (PARC_OPEN_ROUTINE)BiosDiskOpen,
  160. (PARC_READ_ROUTINE)BiosElToritoDiskRead,
  161. (PARC_READ_STATUS_ROUTINE)BlArcNotYetImplemented,
  162. (PARC_SEEK_ROUTINE)BiosPartitionSeek,
  163. (PARC_WRITE_ROUTINE)BlArcNotYetImplemented,
  164. (PARC_GET_FILE_INFO_ROUTINE)BiosDiskGetFileInfo,
  165. (PARC_SET_FILE_INFO_ROUTINE)BlArcNotYetImplemented,
  166. (PRENAME_ROUTINE)BlArcNotYetImplemented,
  167. (PARC_GET_DIRECTORY_ENTRY_ROUTINE)BlArcNotYetImplemented,
  168. (PBOOTFS_INFO)BlArcNotYetImplemented
  169. };
  170. ARC_STATUS
  171. BiosDiskClose(
  172. IN ULONG FileId
  173. )
  174. /*++
  175. Routine Description:
  176. Closes the specified device
  177. Arguments:
  178. FileId - Supplies file id of the device to be closed
  179. Return Value:
  180. ESUCCESS - Device closed successfully
  181. !ESUCCESS - Device was not closed.
  182. --*/
  183. {
  184. if (BlFileTable[FileId].Flags.Open == 0) {
  185. BlPrint(TEXT("ERROR - Unopened fileid %lx closed\r\n"),FileId);
  186. }
  187. BlFileTable[FileId].Flags.Open = 0;
  188. return(ESUCCESS);
  189. }
  190. ARC_STATUS
  191. BiosPartitionClose(
  192. IN ULONG FileId
  193. )
  194. /*++
  195. Routine Description:
  196. Closes the specified device
  197. Arguments:
  198. FileId - Supplies file id of the device to be closed
  199. Return Value:
  200. ESUCCESS - Device closed successfully
  201. !ESUCCESS - Device was not closed.
  202. --*/
  203. {
  204. if (BlFileTable[FileId].Flags.Open == 0) {
  205. BlPrint(TEXT("ERROR - Unopened fileid %lx closed\r\n"),FileId);
  206. }
  207. BlFileTable[FileId].Flags.Open = 0;
  208. return(BiosDiskClose((ULONG)BlFileTable[FileId].u.PartitionContext.DiskId));
  209. }
  210. #define STR_PREFIX
  211. #define DBG_PRINT(x)
  212. ARC_STATUS
  213. BiosPartitionOpen(
  214. IN PCHAR OpenPath,
  215. IN OPEN_MODE OpenMode,
  216. OUT PULONG FileId
  217. )
  218. /*++
  219. Routine Description:
  220. Opens the disk partition specified by OpenPath. This routine will open
  221. floppy drives 0 and 1, and any partition on hard drive 0 or 1.
  222. Arguments:
  223. OpenPath - Supplies a pointer to the name of the partition. If OpenPath
  224. is "A:" or "B:" the corresponding floppy drive will be opened.
  225. If it is "C:" or above, this routine will find the corresponding
  226. partition on hard drive 0 or 1 and open it.
  227. OpenMode - Supplies the mode to open the file.
  228. 0 - Read Only
  229. 1 - Write Only
  230. 2 - Read/Write
  231. FileId - Returns the file descriptor for use with the Close, Read, Write,
  232. and Seek routines
  233. Return Value:
  234. ESUCCESS - File successfully opened.
  235. --*/
  236. {
  237. ARC_STATUS Status;
  238. ULONG DiskFileId;
  239. UCHAR PartitionNumber;
  240. ULONG Controller;
  241. ULONG Key;
  242. BOOLEAN IsEisa = FALSE;
  243. //
  244. // BIOS devices are always "multi(0)" (except for EISA flakiness
  245. // where we treat "eisa(0)..." like "multi(0)..." in floppy cases.
  246. //
  247. if(FwGetPathMnemonicKey(OpenPath,"multi",&Key)) {
  248. if(FwGetPathMnemonicKey(OpenPath,"eisa", &Key)) {
  249. return(EBADF);
  250. } else {
  251. IsEisa = TRUE;
  252. }
  253. }
  254. if (Key!=0) {
  255. return(EBADF);
  256. }
  257. //
  258. // If we're opening a floppy drive, there are no partitions
  259. // so we can just return the physical device.
  260. //
  261. if((_stricmp(OpenPath,"multi(0)disk(0)fdisk(0)partition(0)") == 0) ||
  262. (_stricmp(OpenPath,"eisa(0)disk(0)fdisk(0)partition(0)" ) == 0))
  263. {
  264. return(BiosDiskOpen( 0, FloppyOpenMode, FileId));
  265. }
  266. if((_stricmp(OpenPath,"multi(0)disk(0)fdisk(1)partition(0)") == 0) ||
  267. (_stricmp(OpenPath,"eisa(0)disk(0)fdisk(1)partition(0)" ) == 0))
  268. {
  269. return(BiosDiskOpen( 1, FloppyOpenMode, FileId));
  270. }
  271. if((_stricmp(OpenPath,"multi(0)disk(0)fdisk(0)") == 0) ||
  272. (_stricmp(OpenPath,"eisa(0)disk(0)fdisk(0)" ) == 0))
  273. {
  274. return(BiosDiskOpen( 0, FloppyOpenMode, FileId));
  275. }
  276. if((_stricmp(OpenPath,"multi(0)disk(0)fdisk(1)") == 0) ||
  277. (_stricmp(OpenPath,"eisa(0)disk(0)fdisk(1)" ) == 0))
  278. {
  279. return(BiosDiskOpen( 1, FloppyOpenMode, FileId));
  280. }
  281. //
  282. // We can't handle eisa(0) cases for hard disks.
  283. //
  284. if(IsEisa) {
  285. return(EBADF);
  286. }
  287. //
  288. // We can only deal with disk controller 0
  289. //
  290. if (FwGetPathMnemonicKey(OpenPath,"disk",&Controller)) {
  291. return(EBADF);
  292. }
  293. if ( Controller!=0 ) {
  294. return(EBADF);
  295. }
  296. if (!FwGetPathMnemonicKey(OpenPath,"cdrom",&Key)) {
  297. //
  298. // Now we have a CD-ROM disk number, so we open that for raw access.
  299. // Use a special bit to indicate CD-ROM, because otherwise
  300. // the BiosDiskOpen routine thinks a third or greater disk is
  301. // a CD-ROM.
  302. //
  303. return(BiosDiskOpen( Key | 0x80000000, 0, FileId ) );
  304. }
  305. if (FwGetPathMnemonicKey(OpenPath,"rdisk",&Key)) {
  306. return(EBADF);
  307. }
  308. //
  309. // Now we have a disk number, so we open that for raw access.
  310. // We need to add 0x80 to translate it to a BIOS number.
  311. //
  312. Status = BiosDiskOpen( Key,
  313. 0,
  314. &DiskFileId );
  315. if (Status != ESUCCESS) {
  316. DBG_PRINT(STR_PREFIX"BiosDiskOpen Failed\r\n");
  317. return(Status);
  318. }
  319. //
  320. // Find the partition number to open
  321. //
  322. if (FwGetPathMnemonicKey(OpenPath,"partition",&Key)) {
  323. BiosPartitionClose(DiskFileId);
  324. return(EBADF);
  325. }
  326. //
  327. // If the partition number was 0, then we are opening the device
  328. // for raw access, so we are already done.
  329. //
  330. if (Key == 0) {
  331. *FileId = DiskFileId;
  332. return(ESUCCESS);
  333. }
  334. //
  335. // Before we open the partition, we need to find an available
  336. // file descriptor.
  337. //
  338. *FileId=2;
  339. while (BlFileTable[*FileId].Flags.Open != 0) {
  340. *FileId += 1;
  341. if (*FileId == BL_FILE_TABLE_SIZE) {
  342. return(ENOENT);
  343. }
  344. }
  345. //
  346. // We found an entry we can use, so mark it as open.
  347. //
  348. BlFileTable[*FileId].Flags.Open = 1;
  349. BlFileTable[*FileId].DeviceEntryTable=&BiosPartitionEntryTable;
  350. //
  351. // Convert to zero-based partition number
  352. //
  353. PartitionNumber = (UCHAR)(Key - 1);
  354. DBG_PRINT(STR_PREFIX"Trying HardDiskPartitionOpen(...)\r\n");
  355. //
  356. // Try to open the MBR partition
  357. //
  358. Status = HardDiskPartitionOpen( *FileId,
  359. DiskFileId,
  360. PartitionNumber);
  361. #ifdef EFI_PARTITION_SUPPORT
  362. if (Status != ESUCCESS) {
  363. //
  364. // Try to open the GPT partition
  365. //
  366. DBG_PRINT(STR_PREFIX"Trying BlOpenGPTDiskPartition(...)\r\n");
  367. Status = BlOpenGPTDiskPartition(*FileId,
  368. DiskFileId,
  369. PartitionNumber);
  370. }
  371. #endif
  372. return Status;
  373. }
  374. ARC_STATUS
  375. BiosPartitionRead (
  376. IN ULONG FileId,
  377. OUT PVOID Buffer,
  378. IN ULONG Length,
  379. OUT PULONG Count
  380. )
  381. /*++
  382. Routine Description:
  383. Reads from the specified file
  384. NOTE John Vert (jvert) 18-Jun-1991
  385. This only supports block sector reads. Thus, everything
  386. is assumed to start on a sector boundary, and every offset
  387. is considered an offset from the logical beginning of the disk
  388. partition.
  389. Arguments:
  390. FileId - Supplies the file to read from
  391. Buffer - Supplies buffer to hold the data that is read
  392. Length - Supplies maximum number of bytes to read
  393. Count - Returns actual bytes read.
  394. Return Value:
  395. ESUCCESS - Read completed successfully
  396. !ESUCCESS - Read failed.
  397. --*/
  398. {
  399. ARC_STATUS Status;
  400. LARGE_INTEGER PhysicalOffset;
  401. ULONG DiskId;
  402. PhysicalOffset.QuadPart = BlFileTable[FileId].Position.QuadPart +
  403. (ULONGLONG)SECTOR_SIZE * BlFileTable[FileId].u.PartitionContext.StartingSector;
  404. DiskId = BlFileTable[FileId].u.PartitionContext.DiskId;
  405. Status = (BlFileTable[DiskId].DeviceEntryTable->Seek)(DiskId,
  406. &PhysicalOffset,
  407. SeekAbsolute );
  408. if (Status != ESUCCESS) {
  409. return(Status);
  410. }
  411. Status = (BlFileTable[DiskId].DeviceEntryTable->Read)(DiskId,
  412. Buffer,
  413. Length,
  414. Count );
  415. BlFileTable[FileId].Position.QuadPart += *Count;
  416. return(Status);
  417. }
  418. ARC_STATUS
  419. BiosPartitionSeek (
  420. IN ULONG FileId,
  421. IN PLARGE_INTEGER Offset,
  422. IN SEEK_MODE SeekMode
  423. )
  424. /*++
  425. Routine Description:
  426. Changes the current offset of the file specified by FileId
  427. Arguments:
  428. FileId - specifies the file on which the current offset is to
  429. be changed.
  430. Offset - New offset into file.
  431. SeekMode - Either SeekAbsolute or SeekRelative
  432. SeekEndRelative is not supported
  433. Return Value:
  434. ESUCCESS - Operation completed succesfully
  435. EBADF - Operation did not complete successfully.
  436. --*/
  437. {
  438. switch (SeekMode) {
  439. case SeekAbsolute:
  440. BlFileTable[FileId].Position = *Offset;
  441. break;
  442. case SeekRelative:
  443. BlFileTable[FileId].Position.QuadPart += Offset->QuadPart;
  444. break;
  445. default:
  446. BlPrint(TEXT("SeekMode %lx not supported\r\n"),SeekMode);
  447. return(EACCES);
  448. }
  449. return(ESUCCESS);
  450. }
  451. ARC_STATUS
  452. BiosPartitionWrite(
  453. IN ULONG FileId,
  454. OUT PVOID Buffer,
  455. IN ULONG Length,
  456. OUT PULONG Count
  457. )
  458. /*++
  459. Routine Description:
  460. Writes to the specified file
  461. NOTE John Vert (jvert) 18-Jun-1991
  462. This only supports block sector reads. Thus, everything
  463. is assumed to start on a sector boundary, and every offset
  464. is considered an offset from the logical beginning of the disk
  465. partition.
  466. Arguments:
  467. FileId - Supplies the file to write to
  468. Buffer - Supplies buffer with data to write
  469. Length - Supplies number of bytes to write
  470. Count - Returns actual bytes written.
  471. Return Value:
  472. ESUCCESS - write completed successfully
  473. !ESUCCESS - write failed.
  474. --*/
  475. {
  476. ARC_STATUS Status;
  477. LARGE_INTEGER PhysicalOffset;
  478. ULONG DiskId;
  479. PhysicalOffset.QuadPart = BlFileTable[FileId].Position.QuadPart +
  480. (ULONGLONG)SECTOR_SIZE * BlFileTable[FileId].u.PartitionContext.StartingSector;
  481. DiskId = BlFileTable[FileId].u.PartitionContext.DiskId;
  482. Status = (BlFileTable[DiskId].DeviceEntryTable->Seek)(DiskId,
  483. &PhysicalOffset,
  484. SeekAbsolute );
  485. if (Status != ESUCCESS) {
  486. return(Status);
  487. }
  488. Status = (BlFileTable[DiskId].DeviceEntryTable->Write)(DiskId,
  489. Buffer,
  490. Length,
  491. Count );
  492. if(Status == ESUCCESS) {
  493. BlFileTable[FileId].Position.QuadPart += *Count;
  494. }
  495. return(Status);
  496. }
  497. ARC_STATUS
  498. BiosConsoleOpen(
  499. IN PCHAR OpenPath,
  500. IN OPEN_MODE OpenMode,
  501. OUT PULONG FileId
  502. )
  503. /*++
  504. Routine Description:
  505. Attempts to open either the console input or output
  506. Arguments:
  507. OpenPath - Supplies a pointer to the name of the device to open. If
  508. this is either CONSOLE_INPUT_NAME or CONSOLE_OUTPUT_NAME,
  509. a file descriptor is allocated and filled in.
  510. OpenMode - Supplies the mode to open the file.
  511. 0 - Read Only (CONSOLE_INPUT_NAME)
  512. 1 - Write Only (CONSOLE_OUTPUT_NAME)
  513. FileId - Returns the file descriptor for use with the Close, Read and
  514. Write routines
  515. Return Value:
  516. ESUCCESS - Console successfully opened.
  517. --*/
  518. {
  519. if (_stricmp(OpenPath, CONSOLE_INPUT_NAME)==0) {
  520. //
  521. // Open the keyboard for input
  522. //
  523. if (OpenMode != ArcOpenReadOnly) {
  524. return(EACCES);
  525. }
  526. *FileId = ARC_CONSOLE_INPUT;
  527. return(ESUCCESS);
  528. }
  529. if (_stricmp(OpenPath, CONSOLE_OUTPUT_NAME)==0) {
  530. //
  531. // Open the display for output
  532. //
  533. if (OpenMode != ArcOpenWriteOnly) {
  534. return(EACCES);
  535. }
  536. *FileId = ARC_CONSOLE_OUTPUT;
  537. return(ESUCCESS);
  538. }
  539. return(ENOENT);
  540. }
  541. ARC_STATUS
  542. BiosConsoleReadStatus(
  543. IN ULONG FileId
  544. )
  545. /*++
  546. Routine Description:
  547. This routine determines if there is a keypress pending
  548. Arguments:
  549. FileId - Supplies the FileId to be read. (should always be 0 for this
  550. function)
  551. Return Value:
  552. ESUCCESS - There is a key pending
  553. EAGAIN - There is not a key pending
  554. --*/
  555. {
  556. ULONG Key;
  557. //
  558. // If we have buffered input...
  559. //
  560. if (KeyBufferEnd != KeyBufferStart) {
  561. return(ESUCCESS);
  562. }
  563. //
  564. // Check for a key
  565. //
  566. Key = GET_KEY();
  567. if (Key != 0) {
  568. //
  569. // We got a key, so we have to stick it back into our buffer
  570. // and return ESUCCESS.
  571. //
  572. BiosConsoleFillBuffer(Key);
  573. return(ESUCCESS);
  574. } else {
  575. //
  576. // no key pending
  577. //
  578. return(EAGAIN);
  579. }
  580. }
  581. ARC_STATUS
  582. BiosConsoleRead(
  583. IN ULONG FileId,
  584. OUT PUCHAR Buffer,
  585. IN ULONG Length,
  586. OUT PULONG Count
  587. )
  588. /*++
  589. Routine Description:
  590. Gets input from the keyboard.
  591. Arguments:
  592. FileId - Supplies the FileId to be read (should always be 0 for this
  593. function)
  594. Buffer - Returns the keyboard input.
  595. Length - Supplies the length of the buffer (in bytes)
  596. Count - Returns the actual number of bytes read
  597. Return Value:
  598. ESUCCESS - Keyboard read completed succesfully.
  599. --*/
  600. {
  601. ULONG Key;
  602. *Count = 0;
  603. while (*Count < Length) {
  604. if (KeyBufferEnd == KeyBufferStart) { // then buffer is presently empty
  605. do {
  606. //
  607. // Poll the keyboard until input is available
  608. //
  609. Key = GET_KEY();
  610. } while ( Key==0 );
  611. BiosConsoleFillBuffer(Key);
  612. }
  613. Buffer[*Count] = KeyBuffer[KeyBufferStart];
  614. KeyBufferStart = (KeyBufferStart+1) % KEY_INPUT_BUFFER_SIZE;
  615. *Count = *Count + 1;
  616. }
  617. return(ESUCCESS);
  618. }
  619. VOID
  620. BiosConsoleFillBuffer(
  621. IN ULONG Key
  622. )
  623. /*++
  624. Routine Description:
  625. Places input from the keyboard into the keyboard buffer, expanding the
  626. special keys as appropriate.
  627. All keys translated here use the ARC translation table, as defined in the
  628. ARC specification, with one exception -- the BACKTAB_KEY, for which the
  629. ARC spec is lacking. I have decided that BACKTAB_KEY is ESC+TAB.
  630. Arguments:
  631. Key - Raw keypress value as returned by GET_KEY().
  632. Return Value:
  633. none.
  634. --*/
  635. {
  636. switch(Key) {
  637. case UP_ARROW:
  638. KeyBuffer[KeyBufferEnd] = ASCI_CSI_IN;
  639. KeyBufferEnd = (KeyBufferEnd+1) % KEY_INPUT_BUFFER_SIZE;
  640. KeyBuffer[KeyBufferEnd] = 'A';
  641. KeyBufferEnd = (KeyBufferEnd+1) % KEY_INPUT_BUFFER_SIZE;
  642. break;
  643. case DOWN_ARROW:
  644. KeyBuffer[KeyBufferEnd] = ASCI_CSI_IN;
  645. KeyBufferEnd = (KeyBufferEnd+1) % KEY_INPUT_BUFFER_SIZE;
  646. KeyBuffer[KeyBufferEnd] = 'B';
  647. KeyBufferEnd = (KeyBufferEnd+1) % KEY_INPUT_BUFFER_SIZE;
  648. break;
  649. case RIGHT_KEY:
  650. KeyBuffer[KeyBufferEnd] = ASCI_CSI_IN;
  651. KeyBufferEnd = (KeyBufferEnd+1) % KEY_INPUT_BUFFER_SIZE;
  652. KeyBuffer[KeyBufferEnd] = 'C';
  653. KeyBufferEnd = (KeyBufferEnd+1) % KEY_INPUT_BUFFER_SIZE;
  654. break;
  655. case LEFT_KEY:
  656. KeyBuffer[KeyBufferEnd] = ASCI_CSI_IN;
  657. KeyBufferEnd = (KeyBufferEnd+1) % KEY_INPUT_BUFFER_SIZE;
  658. KeyBuffer[KeyBufferEnd] = 'D';
  659. KeyBufferEnd = (KeyBufferEnd+1) % KEY_INPUT_BUFFER_SIZE;
  660. break;
  661. case INS_KEY:
  662. KeyBuffer[KeyBufferEnd] = ASCI_CSI_IN;
  663. KeyBufferEnd = (KeyBufferEnd+1) % KEY_INPUT_BUFFER_SIZE;
  664. KeyBuffer[KeyBufferEnd] = '@';
  665. KeyBufferEnd = (KeyBufferEnd+1) % KEY_INPUT_BUFFER_SIZE;
  666. break;
  667. case DEL_KEY:
  668. KeyBuffer[KeyBufferEnd] = ASCI_CSI_IN;
  669. KeyBufferEnd = (KeyBufferEnd+1) % KEY_INPUT_BUFFER_SIZE;
  670. KeyBuffer[KeyBufferEnd] = 'P';
  671. KeyBufferEnd = (KeyBufferEnd+1) % KEY_INPUT_BUFFER_SIZE;
  672. break;
  673. case F1_KEY:
  674. KeyBuffer[KeyBufferEnd] = ASCI_CSI_IN;
  675. KeyBufferEnd = (KeyBufferEnd+1) % KEY_INPUT_BUFFER_SIZE;
  676. KeyBuffer[KeyBufferEnd] = 'O';
  677. KeyBufferEnd = (KeyBufferEnd+1) % KEY_INPUT_BUFFER_SIZE;
  678. KeyBuffer[KeyBufferEnd] = 'P';
  679. KeyBufferEnd = (KeyBufferEnd+1) % KEY_INPUT_BUFFER_SIZE;
  680. break;
  681. case F2_KEY:
  682. KeyBuffer[KeyBufferEnd] = ASCI_CSI_IN;
  683. KeyBufferEnd = (KeyBufferEnd+1) % KEY_INPUT_BUFFER_SIZE;
  684. KeyBuffer[KeyBufferEnd] = 'O';
  685. KeyBufferEnd = (KeyBufferEnd+1) % KEY_INPUT_BUFFER_SIZE;
  686. KeyBuffer[KeyBufferEnd] = 'Q';
  687. KeyBufferEnd = (KeyBufferEnd+1) % KEY_INPUT_BUFFER_SIZE;
  688. break;
  689. case F3_KEY:
  690. KeyBuffer[KeyBufferEnd] = ASCI_CSI_IN;
  691. KeyBufferEnd = (KeyBufferEnd+1) % KEY_INPUT_BUFFER_SIZE;
  692. KeyBuffer[KeyBufferEnd] = 'O';
  693. KeyBufferEnd = (KeyBufferEnd+1) % KEY_INPUT_BUFFER_SIZE;
  694. KeyBuffer[KeyBufferEnd] = 'w';
  695. KeyBufferEnd = (KeyBufferEnd+1) % KEY_INPUT_BUFFER_SIZE;
  696. break;
  697. case F5_KEY:
  698. KeyBuffer[KeyBufferEnd] = ASCI_CSI_IN;
  699. KeyBufferEnd = (KeyBufferEnd+1) % KEY_INPUT_BUFFER_SIZE;
  700. KeyBuffer[KeyBufferEnd] = 'O';
  701. KeyBufferEnd = (KeyBufferEnd+1) % KEY_INPUT_BUFFER_SIZE;
  702. KeyBuffer[KeyBufferEnd] = 't';
  703. KeyBufferEnd = (KeyBufferEnd+1) % KEY_INPUT_BUFFER_SIZE;
  704. break;
  705. case F6_KEY:
  706. KeyBuffer[KeyBufferEnd] = ASCI_CSI_IN;
  707. KeyBufferEnd = (KeyBufferEnd+1) % KEY_INPUT_BUFFER_SIZE;
  708. KeyBuffer[KeyBufferEnd] = 'O';
  709. KeyBufferEnd = (KeyBufferEnd+1) % KEY_INPUT_BUFFER_SIZE;
  710. KeyBuffer[KeyBufferEnd] = 'u';
  711. KeyBufferEnd = (KeyBufferEnd+1) % KEY_INPUT_BUFFER_SIZE;
  712. break;
  713. case F8_KEY:
  714. KeyBuffer[KeyBufferEnd] = ASCI_CSI_IN;
  715. KeyBufferEnd = (KeyBufferEnd+1) % KEY_INPUT_BUFFER_SIZE;
  716. KeyBuffer[KeyBufferEnd] = 'O';
  717. KeyBufferEnd = (KeyBufferEnd+1) % KEY_INPUT_BUFFER_SIZE;
  718. KeyBuffer[KeyBufferEnd] = 'r';
  719. KeyBufferEnd = (KeyBufferEnd+1) % KEY_INPUT_BUFFER_SIZE;
  720. break;
  721. case F10_KEY:
  722. KeyBuffer[KeyBufferEnd] = ASCI_CSI_IN;
  723. KeyBufferEnd = (KeyBufferEnd+1) % KEY_INPUT_BUFFER_SIZE;
  724. KeyBuffer[KeyBufferEnd] = 'O';
  725. KeyBufferEnd = (KeyBufferEnd+1) % KEY_INPUT_BUFFER_SIZE;
  726. KeyBuffer[KeyBufferEnd] = 'M';
  727. KeyBufferEnd = (KeyBufferEnd+1) % KEY_INPUT_BUFFER_SIZE;
  728. break;
  729. case HOME_KEY:
  730. KeyBuffer[KeyBufferEnd] = ASCI_CSI_IN;
  731. KeyBufferEnd = (KeyBufferEnd+1) % KEY_INPUT_BUFFER_SIZE;
  732. KeyBuffer[KeyBufferEnd] = 'H';
  733. KeyBufferEnd = (KeyBufferEnd+1) % KEY_INPUT_BUFFER_SIZE;
  734. break;
  735. case END_KEY:
  736. KeyBuffer[KeyBufferEnd] = ASCI_CSI_IN;
  737. KeyBufferEnd = (KeyBufferEnd+1) % KEY_INPUT_BUFFER_SIZE;
  738. KeyBuffer[KeyBufferEnd] = 'K';
  739. KeyBufferEnd = (KeyBufferEnd+1) % KEY_INPUT_BUFFER_SIZE;
  740. break;
  741. case ESCAPE_KEY:
  742. KeyBuffer[KeyBufferEnd] = ASCI_CSI_IN;
  743. KeyBufferEnd = (KeyBufferEnd+1) % KEY_INPUT_BUFFER_SIZE;
  744. break;
  745. case BACKTAB_KEY:
  746. KeyBuffer[KeyBufferEnd] = ASCI_CSI_IN;
  747. KeyBufferEnd = (KeyBufferEnd+1) % KEY_INPUT_BUFFER_SIZE;
  748. KeyBuffer[KeyBufferEnd] = (UCHAR)(TAB_KEY & 0xFF);
  749. KeyBufferEnd = (KeyBufferEnd+1) % KEY_INPUT_BUFFER_SIZE;
  750. break;
  751. default:
  752. //
  753. // The ASCII code is the low byte of Key
  754. //
  755. KeyBuffer[KeyBufferEnd] = (UCHAR)(Key & 0xff);
  756. KeyBufferEnd = (KeyBufferEnd+1) % KEY_INPUT_BUFFER_SIZE;
  757. }
  758. }
  759. ARC_STATUS
  760. BiosConsoleWrite(
  761. IN ULONG FileId,
  762. OUT PWCHAR Buffer,
  763. IN ULONG Length,
  764. OUT PULONG Count
  765. )
  766. /*++
  767. Routine Description:
  768. Outputs to the console. (In this case, the VGA display)
  769. Arguments:
  770. FileId - Supplies the FileId to be written (should always be 1 for this
  771. function)
  772. Buffer - Supplies characters to be output
  773. Length - Supplies the length of the buffer (in bytes)
  774. Count - Returns the actual number of bytes written
  775. Return Value:
  776. ESUCCESS - Console write completed succesfully.
  777. --*/
  778. {
  779. ARC_STATUS Status;
  780. PWCHAR String;
  781. ULONG Index;
  782. WCHAR a;
  783. PWCHAR p;
  784. ULONG y;
  785. //
  786. // Process each character in turn.
  787. //
  788. Status = ESUCCESS;
  789. String = Buffer;
  790. for ( *Count = 0 ;
  791. *Count < Length ;
  792. String++,*Count = *Count+sizeof(WCHAR) ) {
  793. //
  794. // If we're in the middle of a control sequence, continue scanning,
  795. // otherwise process character.
  796. //
  797. if (ControlSequence) {
  798. //
  799. // If the character is a digit, update parameter value.
  800. //
  801. if ((*String >= L'0') && (*String <= L'9')) {
  802. Parameter[PCount] = Parameter[PCount] * 10 + *String - L'0';
  803. continue;
  804. }
  805. //
  806. // If we are in the middle of a font selection sequence, this
  807. // character must be a 'D', otherwise reset control sequence.
  808. //
  809. if (FontSelection) {
  810. //if (*String == 'D') {
  811. //
  812. // //
  813. // // Other fonts not implemented yet.
  814. // //
  815. //
  816. //} else {
  817. //}
  818. ControlSequence = FALSE;
  819. FontSelection = FALSE;
  820. continue;
  821. }
  822. switch (*String) {
  823. //
  824. // If a semicolon, move to the next parameter.
  825. //
  826. case L';':
  827. PCount++;
  828. if (PCount > CONTROL_SEQUENCE_MAX_PARAMETER) {
  829. PCount = CONTROL_SEQUENCE_MAX_PARAMETER;
  830. }
  831. Parameter[PCount] = 0;
  832. break;
  833. //
  834. // If a 'J', erase part or all of the screen.
  835. //
  836. case L'J':
  837. switch (Parameter[0]) {
  838. case 0:
  839. //
  840. // Erase to end of the screen
  841. //
  842. BlEfiClearToEndOfDisplay();
  843. //TextClearToEndOfDisplay();
  844. break;
  845. case 1:
  846. //
  847. // Erase from the beginning of the screen
  848. //
  849. break;
  850. default:
  851. //
  852. // Erase entire screen
  853. //
  854. //TextClearDisplay();
  855. BlEfiClearDisplay();
  856. break;
  857. }
  858. ControlSequence = FALSE;
  859. break;
  860. //
  861. // If a 'K', erase part or all of the line.
  862. //
  863. case L'K':
  864. switch (Parameter[0]) {
  865. //
  866. // Erase to end of the line.
  867. //
  868. case 0:
  869. //TextClearToEndOfLine();
  870. BlEfiClearToEndOfDisplay();
  871. break;
  872. //
  873. // Erase from the beginning of the line.
  874. //
  875. case 1:
  876. //TextClearFromStartOfLine();
  877. BlEfiClearToEndOfLine();
  878. break;
  879. //
  880. // Erase entire line.
  881. //
  882. default :
  883. BlEfiGetCursorPosition( NULL, &y );
  884. BlEfiPositionCursor( 0, y );
  885. BlEfiClearToEndOfLine();
  886. //TextClearFromStartOfLine();
  887. //TextClearToEndOfLine();
  888. break;
  889. }
  890. ControlSequence = FALSE;
  891. break;
  892. //
  893. // If a 'H', move cursor to position.
  894. //
  895. case 'H':
  896. //TextSetCursorPosition(Parameter[1]-1, Parameter[0]-1);
  897. BlEfiPositionCursor( Parameter[1]-1, Parameter[0]-1 );
  898. ControlSequence = FALSE;
  899. break;
  900. //
  901. // If a ' ', could be a FNT selection command.
  902. //
  903. case L' ':
  904. FontSelection = TRUE;
  905. break;
  906. case L'm':
  907. //
  908. // Select action based on each parameter.
  909. //
  910. // Blink and HighIntensity are by default disabled
  911. // each time a new SGR is specified, unless they are
  912. // explicitly specified again, in which case these
  913. // will be set to TRUE at that time.
  914. //
  915. HighIntensity = FALSE;
  916. Blink = FALSE;
  917. for ( Index = 0 ; Index <= PCount ; Index++ ) {
  918. switch (Parameter[Index]) {
  919. //
  920. // Attributes off.
  921. //
  922. case 0:
  923. // bugbug blink???
  924. BlEfiSetAttribute( ATT_FG_WHITE );
  925. //TextSetCurrentAttribute(7);
  926. //
  927. HighIntensity = FALSE;
  928. Blink = FALSE;
  929. break;
  930. //
  931. // High Intensity.
  932. //
  933. case 1:
  934. BlEfiSetAttribute( ATT_FG_INTENSE );
  935. //TextSetCurrentAttribute(0xf);
  936. HighIntensity = TRUE;
  937. break;
  938. //
  939. // Underscored.
  940. //
  941. case 4:
  942. break;
  943. //
  944. // Blink.
  945. //
  946. case 5:
  947. //bugbug no blink in EFI
  948. //TextSetCurrentAttribute(0x87);
  949. Blink = TRUE;
  950. break;
  951. //
  952. // Reverse Video.
  953. //
  954. case 7:
  955. BlEfiSetInverseMode( TRUE );
  956. //TextSetCurrentAttribute(0x70);
  957. HighIntensity = FALSE;
  958. Blink = FALSE;
  959. break;
  960. //
  961. // Font selection, not implemented yet.
  962. //
  963. case 10:
  964. case 11:
  965. case 12:
  966. case 13:
  967. case 14:
  968. case 15:
  969. case 16:
  970. case 17:
  971. case 18:
  972. case 19:
  973. break;
  974. //
  975. // Foreground Color
  976. //
  977. case 30:
  978. case 31:
  979. case 32:
  980. case 33:
  981. case 34:
  982. case 35:
  983. case 36:
  984. case 37:
  985. //bugbug EFI
  986. #if 0
  987. a = TextGetCurrentAttribute();
  988. a &= 0x70;
  989. a |= TranslateColor[Parameter[Index]-30];
  990. if (HighIntensity) {
  991. a |= 0x08;
  992. }
  993. if (Blink) {
  994. a |= 0x80;
  995. }
  996. TextSetCurrentAttribute(a);
  997. break;
  998. //
  999. // Background Color
  1000. //
  1001. case 40:
  1002. case 41:
  1003. case 42:
  1004. case 43:
  1005. case 44:
  1006. case 45:
  1007. case 46:
  1008. case 47:
  1009. a = TextGetCurrentAttribute();
  1010. a &= 0x8f;
  1011. a |= TranslateColor[Parameter[Index]-40] << 4;
  1012. TextSetCurrentAttribute(a);
  1013. break;
  1014. #endif
  1015. default:
  1016. break;
  1017. }
  1018. }
  1019. default:
  1020. ControlSequence = FALSE;
  1021. break;
  1022. }
  1023. //
  1024. // This is not a control sequence, check for escape sequence.
  1025. //
  1026. } else {
  1027. //
  1028. // If escape sequence, check for control sequence, otherwise
  1029. // process single character.
  1030. //
  1031. if (EscapeSequence) {
  1032. //
  1033. // Check for '[', means control sequence, any other following
  1034. // character is ignored.
  1035. //
  1036. if (*String == '[') {
  1037. ControlSequence = TRUE;
  1038. //
  1039. // Initialize first parameter.
  1040. //
  1041. PCount = 0;
  1042. Parameter[0] = 0;
  1043. }
  1044. EscapeSequence = FALSE;
  1045. //
  1046. // This is not a control or escape sequence, process single character.
  1047. //
  1048. } else {
  1049. switch (*String) {
  1050. //
  1051. // Check for escape sequence.
  1052. //
  1053. case ASCI_ESC:
  1054. EscapeSequence = TRUE;
  1055. break;
  1056. default:
  1057. TextCharOut(String);
  1058. break;
  1059. }
  1060. }
  1061. }
  1062. }
  1063. return Status;
  1064. }
  1065. ARC_STATUS
  1066. BiosDiskOpen(
  1067. IN ULONG DriveId,
  1068. IN OPEN_MODE OpenMode,
  1069. OUT PULONG FileId
  1070. )
  1071. /*++
  1072. Routine Description:
  1073. Opens a BIOS-accessible disk for raw sector access.
  1074. Arguments:
  1075. DriveId - Supplies the BIOS DriveId of the drive to open
  1076. 0 - Floppy 0
  1077. 1 - Floppy 1
  1078. 0x80 - Hard Drive 0
  1079. 0x81 - Hard Drive 1
  1080. 0x82 - Hard Drive 2
  1081. etc
  1082. High bit set and ID > 0x81 means the device is expected to be
  1083. a CD-ROM drive.
  1084. OpenMode - Supplies the mode of the open
  1085. FileId - Supplies a pointer to a variable that specifies the file
  1086. table entry that is filled in if the open is successful.
  1087. Return Value:
  1088. ESUCCESS is returned if the open operation is successful. Otherwise,
  1089. an unsuccessful status is returned that describes the reason for failure.
  1090. --*/
  1091. {
  1092. EFI_HANDLE DeviceHandle;
  1093. PDRIVE_CONTEXT Context;
  1094. BOOLEAN IsCd;
  1095. DBGOUT((TEXT("BiosDiskOpen: enter, id = 0x%x\r\n"),DriveId));
  1096. //
  1097. // Check special drive number encoding for CD-ROM case
  1098. //
  1099. if(DriveId >= 0x80000000) {
  1100. IsCd = TRUE;
  1101. DriveId &= 0x7fffffff;
  1102. } else {
  1103. IsCd = FALSE;
  1104. }
  1105. if( OpenMode == FloppyOpenMode ) {
  1106. //
  1107. // Must be floppy.
  1108. //
  1109. DeviceHandle = GetFloppyDrive( DriveId );
  1110. if (DeviceHandle == (EFI_HANDLE) DEVICE_NOT_FOUND) {
  1111. return EBADF;
  1112. }
  1113. } else {
  1114. if( IsCd ) {
  1115. //
  1116. // For cd, we get the device we booted from.
  1117. //
  1118. #ifndef FORCE_CD_BOOT
  1119. DeviceHandle = GetCd();
  1120. if (DeviceHandle == (EFI_HANDLE) DEVICE_NOT_FOUND) {
  1121. return EBADF;
  1122. }
  1123. #else
  1124. DeviceHandle = GetCdTest();
  1125. if (DeviceHandle == (EFI_HANDLE)0)
  1126. return EBADF;
  1127. #endif // for FORCE_CD_BOOT
  1128. } else {
  1129. //
  1130. // For harddrive, we get the harddrive associated
  1131. // with the passed-in rdisk (DriveId) value.
  1132. //
  1133. DeviceHandle = GetHardDrive( DriveId );
  1134. if (DeviceHandle == (EFI_HANDLE) DEVICE_NOT_FOUND) {
  1135. DBGOUT((TEXT("GetHardDrive returns DEVICE_NOT_FOUND %x\r\n"),DriveId));
  1136. return EBADF;
  1137. }
  1138. }
  1139. }
  1140. //
  1141. // Find an available FileId descriptor to open the device with
  1142. //
  1143. *FileId=2;
  1144. while (BlFileTable[*FileId].Flags.Open != 0) {
  1145. *FileId += 1;
  1146. if(*FileId == BL_FILE_TABLE_SIZE) {
  1147. DBGOUT((TEXT("BiosDiskOpen: no file table entry available\r\n")));
  1148. DBGPAUSE
  1149. return(ENOENT);
  1150. }
  1151. }
  1152. //
  1153. // We found an entry we can use, so mark it as open.
  1154. //
  1155. BlFileTable[*FileId].Flags.Open = 1;
  1156. BlFileTable[*FileId].DeviceEntryTable = IsCd
  1157. ? &BiosEDDSEntryTable
  1158. : &BiosDiskEntryTable;
  1159. Context = &(BlFileTable[*FileId].u.DriveContext);
  1160. Context->DeviceHandle = (ULONGLONG) DeviceHandle;
  1161. Context->xInt13 = TRUE;
  1162. DBGOUT((TEXT("BiosDiskOpen: exit success\r\n")));
  1163. return(ESUCCESS);
  1164. }
  1165. ARC_STATUS
  1166. BiospWritePartialSector(
  1167. IN UCHAR Int13Unit,
  1168. IN ULONGLONG Sector,
  1169. IN PUCHAR Buffer,
  1170. IN BOOLEAN IsHead,
  1171. IN ULONG Bytes,
  1172. IN UCHAR SectorsPerTrack,
  1173. IN USHORT Heads,
  1174. IN USHORT Cylinders,
  1175. IN BOOLEAN AllowXInt13,
  1176. IN ULONGLONG DeviceHandle
  1177. )
  1178. {
  1179. ARC_STATUS Status;
  1180. //
  1181. // Read sector into the write buffer
  1182. //
  1183. Status = ReadExtendedPhysicalSectors(
  1184. DeviceHandle,
  1185. Sector,
  1186. 1,
  1187. LocalBuffer
  1188. );
  1189. if(Status != ESUCCESS) {
  1190. return(Status);
  1191. }
  1192. //
  1193. // Transfer the appropriate bytes from the user buffer to the write buffer
  1194. //
  1195. RtlMoveMemory(
  1196. IsHead ? (LocalBuffer + Bytes) : LocalBuffer,
  1197. Buffer,
  1198. IsHead ? (SECTOR_SIZE - Bytes) : Bytes
  1199. );
  1200. //
  1201. // Write the sector out
  1202. //
  1203. Status = WriteExtendedPhysicalSectors(
  1204. DeviceHandle,
  1205. Sector,
  1206. 1,
  1207. LocalBuffer
  1208. );
  1209. return(Status);
  1210. }
  1211. ARC_STATUS
  1212. BiosDiskWrite(
  1213. IN ULONG FileId,
  1214. OUT PVOID Buffer,
  1215. IN ULONG Length,
  1216. OUT PULONG Count
  1217. )
  1218. /*++
  1219. Routine Description:
  1220. Writes sectors directly to an open physical disk.
  1221. Arguments:
  1222. FileId - Supplies the file to write to
  1223. Buffer - Supplies buffer with data to write
  1224. Length - Supplies number of bytes to write
  1225. Count - Returns actual bytes written
  1226. Return Value:
  1227. ESUCCESS - write completed successfully
  1228. !ESUCCESS - write failed
  1229. --*/
  1230. {
  1231. ULONGLONG HeadSector,TailSector,CurrentSector;
  1232. ULONGLONG DeviceHandle;
  1233. UCHAR Int13Unit;
  1234. ULONG HeadOffset,TailByteCount;
  1235. UCHAR SectorsPerTrack;
  1236. USHORT Heads,Cylinders;
  1237. BOOLEAN AllowXInt13;
  1238. ARC_STATUS Status;
  1239. ULONG BytesLeftToTransfer;
  1240. UCHAR SectorsToTransfer;
  1241. BOOLEAN Under1MegLine;
  1242. PVOID TransferBuffer;
  1243. PUCHAR UserBuffer;
  1244. ULONG PhysicalSectors;
  1245. BytesLeftToTransfer = Length;
  1246. PhysicalSectors = SECTOR_SIZE;
  1247. if(!LocalBuffer) {
  1248. LocalBuffer = BlAllocateHeap(SCRATCH_BUFFER_SIZE);
  1249. if(!LocalBuffer) {
  1250. Status = ENOMEM;
  1251. goto BiosDiskWriteDone;
  1252. }
  1253. }
  1254. HeadSector = BlFileTable[FileId].Position.QuadPart / PhysicalSectors;
  1255. HeadOffset = (ULONG)(BlFileTable[FileId].Position.QuadPart % PhysicalSectors);
  1256. TailSector = (BlFileTable[FileId].Position.QuadPart + Length) / PhysicalSectors;
  1257. TailByteCount = (ULONG)((BlFileTable[FileId].Position.QuadPart + Length) % PhysicalSectors);
  1258. Int13Unit = BlFileTable[FileId].u.DriveContext.Drive;
  1259. DeviceHandle = BlFileTable[FileId].u.DriveContext.DeviceHandle;
  1260. SectorsPerTrack = BlFileTable[FileId].u.DriveContext.Sectors;
  1261. Heads = BlFileTable[FileId].u.DriveContext.Heads;
  1262. Cylinders = BlFileTable[FileId].u.DriveContext.Cylinders;
  1263. AllowXInt13 = BlFileTable[FileId].u.DriveContext.xInt13;
  1264. UserBuffer = Buffer;
  1265. //
  1266. // Special case of transfer occuring entirely within one sector
  1267. //
  1268. CurrentSector = HeadSector;
  1269. if(HeadOffset && TailByteCount && (HeadSector == TailSector)) {
  1270. Status = ReadExtendedPhysicalSectors(
  1271. DeviceHandle,
  1272. HeadSector,
  1273. 1,
  1274. LocalBuffer
  1275. );
  1276. if(Status != ESUCCESS) {
  1277. goto BiosDiskWriteDone;
  1278. }
  1279. RtlMoveMemory(LocalBuffer+HeadOffset,Buffer,Length);
  1280. Status = WriteExtendedPhysicalSectors(
  1281. DeviceHandle,
  1282. CurrentSector,
  1283. 1,
  1284. LocalBuffer
  1285. );
  1286. if(Status != ESUCCESS) {
  1287. goto BiosDiskWriteDone;
  1288. }
  1289. BytesLeftToTransfer = 0;
  1290. goto BiosDiskWriteDone;
  1291. }
  1292. if(HeadOffset) {
  1293. Status = BiospWritePartialSector(
  1294. Int13Unit,
  1295. HeadSector,
  1296. Buffer,
  1297. TRUE,
  1298. HeadOffset,
  1299. SectorsPerTrack,
  1300. Heads,
  1301. Cylinders,
  1302. AllowXInt13,
  1303. DeviceHandle
  1304. );
  1305. if(Status != ESUCCESS) {
  1306. return(Status);
  1307. }
  1308. BytesLeftToTransfer -= PhysicalSectors - HeadOffset;
  1309. UserBuffer += PhysicalSectors - HeadOffset;
  1310. CurrentSector += 1;
  1311. }
  1312. if(TailByteCount) {
  1313. Status = BiospWritePartialSector(
  1314. Int13Unit,
  1315. TailSector,
  1316. (PUCHAR)Buffer + Length - TailByteCount,
  1317. FALSE,
  1318. TailByteCount,
  1319. SectorsPerTrack,
  1320. Heads,
  1321. Cylinders,
  1322. AllowXInt13,
  1323. DeviceHandle
  1324. );
  1325. if(Status != ESUCCESS) {
  1326. return(Status);
  1327. }
  1328. BytesLeftToTransfer -= TailByteCount;
  1329. }
  1330. //
  1331. // The following calculation is not inside the transfer loop because
  1332. // it is unlikely that a caller's buffer will *cross* the 1 meg line
  1333. // due to the PC memory map.
  1334. //
  1335. if((ULONG_PTR) UserBuffer + BytesLeftToTransfer <= 0x100000) {
  1336. Under1MegLine = TRUE;
  1337. } else {
  1338. Under1MegLine = FALSE;
  1339. }
  1340. //
  1341. // Now handle the middle part. This is some number of whole sectors.
  1342. //
  1343. while(BytesLeftToTransfer) {
  1344. //
  1345. // The number of sectors to transfer is the minimum of:
  1346. // - the number of sectors left in the current track
  1347. // - BytesLeftToTransfer / SECTOR_SIZE
  1348. //
  1349. // Because sectors per track is 1-63 we know this will fit in a UCHAR
  1350. //
  1351. if (AllowXInt13) {
  1352. //
  1353. // Ignore cylinders & heads & track information for XINT13 cases
  1354. //
  1355. SectorsToTransfer = (UCHAR)(BytesLeftToTransfer / PhysicalSectors);
  1356. } else {
  1357. SectorsToTransfer = (UCHAR)min(
  1358. SectorsPerTrack - (CurrentSector % SectorsPerTrack),
  1359. BytesLeftToTransfer / PhysicalSectors
  1360. );
  1361. }
  1362. //
  1363. // Now we'll figure out where to transfer the data from. If the
  1364. // caller's buffer is under the 1 meg line, we can transfer the
  1365. // data directly from the caller's buffer. Otherwise we'll copy the
  1366. // user's buffer to our local buffer and transfer from there.
  1367. // In the latter case we can only transfer in chunks of
  1368. // SCRATCH_BUFFER_SIZE because that's the size of the local buffer.
  1369. //
  1370. // Also make sure the transfer won't cross a 64k boundary.
  1371. //
  1372. if(Under1MegLine) {
  1373. //
  1374. // Check if the transfer would cross a 64k boundary. If so,
  1375. // use the local buffer. Otherwise use the user's buffer.
  1376. //
  1377. if(((ULONG_PTR)UserBuffer & 0xffffffffffff0000) !=
  1378. (((ULONG_PTR)UserBuffer + (SectorsToTransfer * PhysicalSectors) - 1) & 0xffffffffffff0000))
  1379. {
  1380. TransferBuffer = LocalBuffer;
  1381. SectorsToTransfer = min(SectorsToTransfer, SCRATCH_BUFFER_SIZE / (USHORT)PhysicalSectors);
  1382. } else {
  1383. TransferBuffer = UserBuffer;
  1384. }
  1385. } else {
  1386. TransferBuffer = LocalBuffer;
  1387. SectorsToTransfer = min(SectorsToTransfer, SCRATCH_BUFFER_SIZE / (USHORT)PhysicalSectors);
  1388. }
  1389. if(TransferBuffer == LocalBuffer) {
  1390. RtlMoveMemory(LocalBuffer,UserBuffer,SectorsToTransfer*PhysicalSectors);
  1391. }
  1392. Status = WriteExtendedPhysicalSectors(
  1393. DeviceHandle,
  1394. CurrentSector,
  1395. SectorsToTransfer,
  1396. TransferBuffer
  1397. );
  1398. if(Status != ESUCCESS) {
  1399. //
  1400. // Tail part isn't contiguous with middle part
  1401. //
  1402. BytesLeftToTransfer += TailByteCount;
  1403. return(Status);
  1404. }
  1405. CurrentSector += SectorsToTransfer;
  1406. BytesLeftToTransfer -= SectorsToTransfer * PhysicalSectors;
  1407. UserBuffer += SectorsToTransfer * PhysicalSectors;
  1408. }
  1409. Status = ESUCCESS;
  1410. BiosDiskWriteDone:
  1411. *Count = Length - BytesLeftToTransfer;
  1412. BlFileTable[FileId].Position.QuadPart += *Count;
  1413. return(Status);
  1414. }
  1415. ARC_STATUS
  1416. pBiosDiskReadWorker(
  1417. IN ULONG FileId,
  1418. OUT PVOID Buffer,
  1419. IN ULONG Length,
  1420. OUT PULONG Count,
  1421. IN USHORT SectorSize,
  1422. IN BOOLEAN xInt13
  1423. )
  1424. /*++
  1425. Routine Description:
  1426. Reads sectors directly from an open physical disk.
  1427. Arguments:
  1428. FileId - Supplies the file to read from
  1429. Buffer - Supplies buffer to hold the data that is read
  1430. Length - Supplies maximum number of bytes to read
  1431. Count - Returns actual bytes read
  1432. Return Value:
  1433. ESUCCESS - Read completed successfully
  1434. !ESUCCESS - Read failed
  1435. --*/
  1436. {
  1437. ULONGLONG HeadSector,TailSector,CurrentSector;
  1438. ULONG HeadOffset,TailByteCount;
  1439. ULONG BytesLeftToTransfer;
  1440. USHORT Heads,Cylinders;
  1441. UCHAR SectorsPerTrack;
  1442. UCHAR Int13Unit;
  1443. ULONGLONG DeviceHandle;
  1444. ARC_STATUS Status;
  1445. PUCHAR UserBuffer;
  1446. UCHAR SectorsToTransfer;
  1447. BOOLEAN Under1MegLine;
  1448. PVOID TransferBuffer;
  1449. BOOLEAN AllowXInt13;
  1450. DBGOUT((TEXT("BiosDiskRead: enter; length=0x%lx, sector size=%u, xint13=%u\r\n"),Length,SectorSize,xInt13));
  1451. BytesLeftToTransfer = Length;
  1452. if(!LocalBuffer) {
  1453. LocalBuffer = BlAllocateHeap(SCRATCH_BUFFER_SIZE);
  1454. if(!LocalBuffer) {
  1455. Status = ENOMEM;
  1456. DBGOUT((TEXT("BiosDiskRead: out of memory\r\n")));
  1457. goto BiosDiskReadDone;
  1458. }
  1459. }
  1460. SectorsPerTrack = BlFileTable[FileId].u.DriveContext.Sectors;
  1461. Heads = BlFileTable[FileId].u.DriveContext.Heads;
  1462. Cylinders = BlFileTable[FileId].u.DriveContext.Cylinders;
  1463. AllowXInt13 = BlFileTable[FileId].u.DriveContext.xInt13;
  1464. Int13Unit = BlFileTable[FileId].u.DriveContext.Drive;
  1465. DeviceHandle = BlFileTable[FileId].u.DriveContext.DeviceHandle;
  1466. HeadSector = BlFileTable[FileId].Position.QuadPart / SectorSize;
  1467. HeadOffset = (ULONG)(BlFileTable[FileId].Position.QuadPart % SectorSize);
  1468. TailSector = (BlFileTable[FileId].Position.QuadPart + Length) / SectorSize;
  1469. TailByteCount = (ULONG)((BlFileTable[FileId].Position.QuadPart + Length) % SectorSize);
  1470. UserBuffer = Buffer;
  1471. DBGOUT((
  1472. TEXT("BiosDiskRead: unit 0x%x CHS=%lu %lu %lu\r\n"),
  1473. Int13Unit,
  1474. Cylinders,
  1475. Heads,
  1476. SectorsPerTrack
  1477. ));
  1478. DBGOUT((
  1479. TEXT("BiosDiskRead: head=0x%lx%lx tail=0x%lx%lx\r\n"),
  1480. (ULONG)(HeadSector >> 32),
  1481. (ULONG)HeadSector,
  1482. (ULONG)(TailSector >> 32),
  1483. (ULONG)TailSector
  1484. ));
  1485. CurrentSector = HeadSector;
  1486. if(HeadOffset && TailByteCount && (HeadSector == TailSector)) {
  1487. //
  1488. // Read contained entirely within one sector, and does not start or
  1489. // end on the sector boundary.
  1490. //
  1491. DBGOUT((TEXT("BiosDiskRead: read entirely within one sector\r\n")));
  1492. Status = ReadExtendedPhysicalSectors(
  1493. DeviceHandle,
  1494. HeadSector,
  1495. 1,
  1496. LocalBuffer
  1497. );
  1498. if(Status != ESUCCESS) {
  1499. DBGOUT((TEXT("BiosDiskRead: read failed with %u\r\n"),Status));
  1500. goto BiosDiskReadDone;
  1501. }
  1502. RtlMoveMemory(Buffer,LocalBuffer + HeadOffset,Length);
  1503. BytesLeftToTransfer = 0;
  1504. goto BiosDiskReadDone;
  1505. }
  1506. if(HeadOffset) {
  1507. //
  1508. // The leading part of the read is not aligned on a sector boundary.
  1509. // Fetch the partial sector and transfer it into the caller's buffer.
  1510. //
  1511. DBGOUT((TEXT("BiosDiskRead: reading partial head sector\r\n")));
  1512. Status = ReadExtendedPhysicalSectors(
  1513. DeviceHandle,
  1514. HeadSector,
  1515. 1,
  1516. LocalBuffer
  1517. );
  1518. if(Status != ESUCCESS) {
  1519. DBGOUT((TEXT("BiosDiskRead: read failed with %u\r\n"),Status));
  1520. goto BiosDiskReadDone;
  1521. }
  1522. RtlMoveMemory(Buffer,LocalBuffer + HeadOffset,SectorSize - HeadOffset);
  1523. BytesLeftToTransfer -= SectorSize - HeadOffset;
  1524. UserBuffer += SectorSize - HeadOffset;
  1525. CurrentSector = HeadSector + 1;
  1526. }
  1527. if(TailByteCount) {
  1528. //
  1529. // The trailing part of the read is not a full sector.
  1530. // Fetch the partial sector and transfer it into the caller's buffer.
  1531. //
  1532. DBGOUT((TEXT("BiosDiskRead: reading partial tail sector\r\n")));
  1533. Status = ReadExtendedPhysicalSectors(
  1534. DeviceHandle,
  1535. TailSector,
  1536. 1,
  1537. LocalBuffer,
  1538. );
  1539. if(Status != ESUCCESS) {
  1540. DBGOUT((TEXT("BiosDiskRead: read failed with %u\r\n"),Status));
  1541. goto BiosDiskReadDone;
  1542. }
  1543. RtlMoveMemory( ((PUCHAR)Buffer+Length-TailByteCount), LocalBuffer, TailByteCount );
  1544. BytesLeftToTransfer -= TailByteCount;
  1545. }
  1546. //
  1547. // The following calculation is not inside the transfer loop because
  1548. // it is unlikely that a caller's buffer will *cross* the 1 meg line
  1549. // due to the PC memory map.
  1550. //
  1551. if((ULONG_PTR) UserBuffer + BytesLeftToTransfer <= 0x100000) {
  1552. Under1MegLine = TRUE;
  1553. } else {
  1554. Under1MegLine = FALSE;
  1555. }
  1556. //
  1557. // Now BytesLeftToTransfer is an integral multiple of sector size.
  1558. //
  1559. while(BytesLeftToTransfer) {
  1560. //
  1561. // The number of sectors to transfer is the minimum of:
  1562. // - the number of sectors left in the current track
  1563. // - BytesLeftToTransfer / SectorSize
  1564. //
  1565. //
  1566. if(xInt13) {
  1567. //
  1568. // Arbitrary maximum sector count of 128. For a CD-ROM this is
  1569. // 256K, which considering that the xfer buffer all has to be
  1570. // under 1MB anyway, is pretty unlikely.
  1571. //
  1572. if((BytesLeftToTransfer / SectorSize) > 128) {
  1573. SectorsToTransfer = 128;
  1574. } else {
  1575. SectorsToTransfer = (UCHAR)(BytesLeftToTransfer / SectorSize);
  1576. }
  1577. } else {
  1578. //
  1579. // Because sectors per track is 1-63 we know this will fit in a UCHAR.
  1580. //
  1581. SectorsToTransfer = (UCHAR)min(
  1582. SectorsPerTrack - (CurrentSector % SectorsPerTrack),
  1583. BytesLeftToTransfer / SectorSize
  1584. );
  1585. }
  1586. if ((ULONG)(SectorSize * SectorsToTransfer) > Length) {
  1587. TransferBuffer = LocalBuffer;
  1588. } else {
  1589. TransferBuffer = UserBuffer;
  1590. }
  1591. DBGOUT((
  1592. TEXT("BiosDiskRead: reading 0x%x sectors @ 0x%lx%lx; buf=0x%lx\r\n"),
  1593. SectorsToTransfer,
  1594. (ULONG)(CurrentSector >> 32),
  1595. (ULONG)CurrentSector,
  1596. TransferBuffer
  1597. ));
  1598. Status = ReadExtendedPhysicalSectors(
  1599. DeviceHandle,
  1600. CurrentSector,
  1601. SectorsToTransfer,
  1602. TransferBuffer
  1603. );
  1604. if(Status != ESUCCESS) {
  1605. //
  1606. // Trail part isn't contiguous
  1607. //
  1608. DBGOUT((TEXT("BiosDiskRead: read failed with %u\r\n"),Status));
  1609. BytesLeftToTransfer += TailByteCount;
  1610. goto BiosDiskReadDone;
  1611. }
  1612. if(TransferBuffer == LocalBuffer) {
  1613. RtlMoveMemory(UserBuffer,LocalBuffer,SectorsToTransfer * SectorSize);
  1614. }
  1615. UserBuffer += SectorsToTransfer * SectorSize;
  1616. CurrentSector += SectorsToTransfer;
  1617. BytesLeftToTransfer -= SectorsToTransfer*SectorSize;
  1618. }
  1619. Status = ESUCCESS;
  1620. DBGOUT((TEXT("BiosDiskRead: exit success\r\n")));
  1621. BiosDiskReadDone:
  1622. DBGPAUSE
  1623. *Count = Length - BytesLeftToTransfer;
  1624. BlFileTable[FileId].Position.QuadPart += *Count;
  1625. return(Status);
  1626. }
  1627. ARC_STATUS
  1628. BiosDiskRead(
  1629. IN ULONG FileId,
  1630. OUT PVOID Buffer,
  1631. IN ULONG Length,
  1632. OUT PULONG Count
  1633. )
  1634. {
  1635. USHORT PhysicalSectors;
  1636. PhysicalSectors = SECTOR_SIZE;
  1637. return(pBiosDiskReadWorker(FileId,Buffer,Length,Count,PhysicalSectors,TRUE));
  1638. }
  1639. ARC_STATUS
  1640. BiosElToritoDiskRead(
  1641. IN ULONG FileId,
  1642. OUT PVOID Buffer,
  1643. IN ULONG Length,
  1644. OUT PULONG Count
  1645. )
  1646. {
  1647. return(pBiosDiskReadWorker(FileId,Buffer,Length,Count,2048,TRUE));
  1648. }
  1649. ARC_STATUS
  1650. BiosPartitionGetFileInfo(
  1651. IN ULONG FileId,
  1652. OUT PFILE_INFORMATION Finfo
  1653. )
  1654. {
  1655. //
  1656. // THIS ROUTINE DOES NOT WORK FOR PARTITION 0.
  1657. //
  1658. PPARTITION_CONTEXT Context;
  1659. RtlZeroMemory(Finfo, sizeof(FILE_INFORMATION));
  1660. Context = &BlFileTable[FileId].u.PartitionContext;
  1661. Finfo->StartingAddress.QuadPart = Context->StartingSector;
  1662. Finfo->StartingAddress.QuadPart = Finfo->StartingAddress.QuadPart << (CCHAR)Context->SectorShift;
  1663. Finfo->EndingAddress.QuadPart = Finfo->StartingAddress.QuadPart + Context->PartitionLength.QuadPart;
  1664. Finfo->Type = DiskPeripheral;
  1665. return ESUCCESS;
  1666. }
  1667. ARC_STATUS
  1668. BiosDiskGetFileInfo(
  1669. IN ULONG FileId,
  1670. OUT PFILE_INFORMATION FileInfo
  1671. )
  1672. /*++
  1673. Routine Description:
  1674. Gets the information about the disk.
  1675. Arguments:
  1676. FileId - The file id to the disk for which information is needed
  1677. FileInfo - Place holder for returning information about the disk
  1678. Return Value:
  1679. ESUCCESS if successful, otherwise appropriate ARC error code.
  1680. --*/
  1681. {
  1682. ARC_STATUS Status = EINVAL;
  1683. if (FileInfo) {
  1684. EFI_STATUS EfiStatus;
  1685. EFI_BLOCK_IO *EfiBlockIo = NULL;
  1686. PDRIVE_CONTEXT Context;
  1687. Context = &BlFileTable[FileId].u.DriveContext;
  1688. Status = EIO;
  1689. FlipToPhysical();
  1690. //
  1691. // Get hold for the block IO protocol handle
  1692. //
  1693. EfiStatus = EfiBS->HandleProtocol((EFI_HANDLE)Context->DeviceHandle,
  1694. &EfiBlockIoProtocol,
  1695. &EfiBlockIo);
  1696. FlipToVirtual();
  1697. if (!EFI_ERROR(EfiStatus) && EfiBlockIo && EfiBlockIo->Media) {
  1698. LONGLONG DiskSize = (EfiBlockIo->Media->BlockSize *
  1699. EfiBlockIo->Media->LastBlock);
  1700. if (DiskSize) {
  1701. RtlZeroMemory(FileInfo, sizeof(FILE_INFORMATION));
  1702. FileInfo->StartingAddress.QuadPart = 0;
  1703. FileInfo->EndingAddress.QuadPart = DiskSize;
  1704. FileInfo->CurrentPosition = BlFileTable[FileId].Position;
  1705. //
  1706. // NOTE : Anything less than 3MB is floppy drive
  1707. //
  1708. if ((DiskSize < 0x300000) && (EfiBlockIo->Media->RemovableMedia)) {
  1709. FileInfo->Type = FloppyDiskPeripheral;
  1710. } else {
  1711. FileInfo->Type = DiskPeripheral;
  1712. }
  1713. Status = ESUCCESS;
  1714. }
  1715. }
  1716. }
  1717. return Status;
  1718. }
  1719. EFI_HANDLE
  1720. GetCd(
  1721. )
  1722. {
  1723. ULONG i;
  1724. ULONGLONG DevicePathSize, SmallestPathSize;
  1725. ULONG HandleCount;
  1726. EFI_HANDLE *BlockIoHandles;
  1727. EFI_HANDLE DeviceHandle = NULL;
  1728. EFI_DEVICE_PATH *DevicePath, *TestPath;
  1729. EFI_DEVICE_PATH_ALIGNED TestPathAligned;
  1730. ATAPI_DEVICE_PATH *AtapiDevicePath;
  1731. SCSI_DEVICE_PATH *ScsiDevicePath;
  1732. UNKNOWN_DEVICE_VENDOR_DEVICE_PATH *UnknownDevicePath;
  1733. EFI_STATUS Status;
  1734. PBOOT_DEVICE_ATAPI BootDeviceAtapi;
  1735. PBOOT_DEVICE_SCSI BootDeviceScsi;
  1736. PBOOT_DEVICE_FLOPPY BootDeviceFloppy;
  1737. PBOOT_DEVICE_UNKNOWN BootDeviceUnknown;
  1738. EFI_HANDLE ReturnDeviceHandle = (EFI_HANDLE) DEVICE_NOT_FOUND;
  1739. ARC_STATUS ArcStatus;
  1740. //
  1741. // get all handles that support the block I/O protocol.
  1742. //
  1743. ArcStatus = BlGetEfiProtocolHandles(
  1744. &EfiBlockIoProtocol,
  1745. &BlockIoHandles,
  1746. &HandleCount);
  1747. if (ArcStatus != ESUCCESS) {
  1748. return(ReturnDeviceHandle);
  1749. }
  1750. FlipToPhysical();
  1751. SmallestPathSize = 0;
  1752. for (i = 0; i < HandleCount; i++) {
  1753. Status = EfiBS->HandleProtocol (
  1754. BlockIoHandles[i],
  1755. &EfiDevicePathProtocol,
  1756. &DevicePath
  1757. );
  1758. if (EFI_ERROR(Status)) {
  1759. EfiST->ConOut->OutputString(EfiST->ConOut,
  1760. L"GetCd: HandleProtocol failed\r\n");
  1761. goto exit;
  1762. }
  1763. DevicePathSize = GetDevPathSize(DevicePath);
  1764. EfiAlignDp(&TestPathAligned,
  1765. DevicePath,
  1766. DevicePathNodeLength(DevicePath));
  1767. TestPath = (EFI_DEVICE_PATH *) &TestPathAligned;
  1768. //
  1769. // In the cd case, just return the device we booted from.
  1770. //
  1771. while (TestPath->Type != END_DEVICE_PATH_TYPE) {
  1772. if (TestPath->Type == MESSAGING_DEVICE_PATH) {
  1773. if (TestPath->SubType == MSG_ATAPI_DP &&
  1774. BootContext.BusType == BootBusAtapi) {
  1775. //
  1776. // For ATAPI, match PrimarySecondary and SlaveMaster
  1777. // fields with the device we booted from.
  1778. //
  1779. AtapiDevicePath = (ATAPI_DEVICE_PATH *) TestPath;
  1780. BootDeviceAtapi = (PBOOT_DEVICE_ATAPI) &(BootContext.BootDevice);
  1781. if ( (AtapiDevicePath->PrimarySecondary == BootDeviceAtapi->PrimarySecondary) &&
  1782. (AtapiDevicePath->SlaveMaster == BootDeviceAtapi->SlaveMaster) &&
  1783. (AtapiDevicePath->Lun == BootDeviceAtapi->Lun) &&
  1784. ((SmallestPathSize == 0) || (DevicePathSize < SmallestPathSize)) ) {
  1785. //
  1786. // Remember the BlockIo Handle
  1787. //
  1788. ReturnDeviceHandle = BlockIoHandles[i];
  1789. //
  1790. // Update the SmallestPathSize
  1791. //
  1792. SmallestPathSize = DevicePathSize;
  1793. break;
  1794. }
  1795. } else if (TestPath->SubType == MSG_SCSI_DP &&
  1796. BootContext.BusType == BootBusScsi) {
  1797. //
  1798. // For SCSI, match PUN and LUN fields with the
  1799. // device we booted from.
  1800. //
  1801. ScsiDevicePath = (SCSI_DEVICE_PATH *) TestPath;
  1802. BootDeviceScsi = (PBOOT_DEVICE_SCSI) &(BootContext.BootDevice);
  1803. if ((ScsiDevicePath->Pun == BootDeviceScsi->Pun) &&
  1804. (ScsiDevicePath->Lun == BootDeviceScsi->Lun) &&
  1805. ((SmallestPathSize == 0) || (DevicePathSize < SmallestPathSize)) ) {
  1806. //
  1807. // Remember the BlockIo Handle
  1808. //
  1809. ReturnDeviceHandle = BlockIoHandles[i];
  1810. //
  1811. // Update the SmallestPathSize
  1812. //
  1813. SmallestPathSize = DevicePathSize;
  1814. break;
  1815. }
  1816. }
  1817. } else if (TestPath->Type == HARDWARE_DEVICE_PATH) {
  1818. if (TestPath->SubType == HW_VENDOR_DP &&
  1819. BootContext.BusType == BootBusVendor) {
  1820. UnknownDevicePath = (UNKNOWN_DEVICE_VENDOR_DEVICE_PATH *) TestPath;
  1821. BootDeviceUnknown = (PBOOT_DEVICE_UNKNOWN) &(BootContext.BootDevice);
  1822. if ( (CompareGuid( &(UnknownDevicePath->DevicePath.Guid),
  1823. &(BootDeviceUnknown->Guid)) == 0) &&
  1824. (UnknownDevicePath->LegacyDriveLetter ==
  1825. BootDeviceUnknown->LegacyDriveLetter) &&
  1826. ((SmallestPathSize == 0) || (DevicePathSize < SmallestPathSize)) ) {
  1827. //
  1828. // Remember the BlockIo Handle
  1829. //
  1830. ReturnDeviceHandle = BlockIoHandles[i];
  1831. //
  1832. // Update the SmallestPathSize
  1833. //
  1834. SmallestPathSize = DevicePathSize;
  1835. break;
  1836. }
  1837. }
  1838. }
  1839. DevicePath = NextDevicePathNode(DevicePath);
  1840. EfiAlignDp(&TestPathAligned,
  1841. DevicePath,
  1842. DevicePathNodeLength(DevicePath));
  1843. TestPath = (EFI_DEVICE_PATH *) &TestPathAligned;
  1844. }
  1845. }
  1846. #ifdef FORCE_CD_BOOT
  1847. if (ReturnDeviceHandle == (EFI_HANDLE)DEVICE_NOT_FOUND) {
  1848. EfiST->ConOut->OutputString(EfiST->ConOut,
  1849. L"GetCD: LocateHandle failed\r\n");
  1850. ReturnDeviceHandle = 0;
  1851. }
  1852. #endif // for FORCE_CD_BOOT
  1853. //
  1854. // Change back to virtual mode.
  1855. //
  1856. exit:
  1857. FlipToVirtual();
  1858. BlFreeDescriptor( (ULONG)((ULONGLONG)BlockIoHandles >> PAGE_SHIFT) );
  1859. return ReturnDeviceHandle;
  1860. }
  1861. ULONG
  1862. BlGetDriveId(
  1863. ULONG DriveType,
  1864. PBOOT_DEVICE Device
  1865. )
  1866. {
  1867. ULONG i;
  1868. EFI_STATUS Status = EFI_INVALID_PARAMETER;
  1869. ULONG nCachedDevicePaths = 0;
  1870. ULONGLONG *CachedDevicePaths;
  1871. EFI_BLOCK_IO * BlkIo;
  1872. ULONG HandleCount;
  1873. EFI_HANDLE *BlockIoHandles;
  1874. EFI_DEVICE_PATH *TestPath;
  1875. EFI_DEVICE_PATH_ALIGNED TestPathAligned;
  1876. ULONG *BlockIoHandlesBitmap;
  1877. ULONG nFoundDevice = DEVICE_NOT_FOUND;
  1878. ULONG nDriveCount = 0;
  1879. EFI_DEVICE_PATH *CurrentDevicePath;
  1880. BOOLEAN DuplicateFound;
  1881. ULONG DriveId;
  1882. ULONG MemoryPage;
  1883. ARC_STATUS ArcStatus;
  1884. //
  1885. // get all handles that support the block I/O protocol.
  1886. //
  1887. ArcStatus = BlGetEfiProtocolHandles(
  1888. &EfiBlockIoProtocol,
  1889. &BlockIoHandles,
  1890. &HandleCount);
  1891. if (ArcStatus != ESUCCESS) {
  1892. EfiST->ConOut->OutputString(EfiST->ConOut,
  1893. L"BlGetDriveId: BlGetEfiProtocolHandles failed\r\n");
  1894. EfiBS->Exit(EfiImageHandle, Status, 0, 0);
  1895. }
  1896. //
  1897. // now that we know how many handles there are, we can allocate space for
  1898. // the CachedDevicePaths and BlockIoHandlesBitmap
  1899. //
  1900. ArcStatus = BlAllocateAlignedDescriptor(
  1901. LoaderFirmwareTemporary,
  1902. 0,
  1903. (ULONG)((HandleCount*sizeof(ULONGLONG)) >> PAGE_SIZE),
  1904. 0,
  1905. &MemoryPage);
  1906. if (ArcStatus != ESUCCESS) {
  1907. EfiST->ConOut->OutputString(EfiST->ConOut,
  1908. L"BlGetDriveId: BlAllocateAlignedDescriptor failed\r\n");
  1909. EfiBS->Exit(EfiImageHandle, Status, 0, 0);
  1910. }
  1911. CachedDevicePaths = (ULONGLONG *)(ULONGLONG)((ULONGLONG)MemoryPage << PAGE_SHIFT);
  1912. ArcStatus = BlAllocateAlignedDescriptor(
  1913. LoaderFirmwareTemporary,
  1914. 0,
  1915. (ULONG)((HandleCount*sizeof(ULONG)) >> PAGE_SIZE),
  1916. 0,
  1917. &MemoryPage);
  1918. if (ArcStatus != ESUCCESS) {
  1919. EfiST->ConOut->OutputString(EfiST->ConOut,
  1920. L"BlGetDriveId: BlAllocateAlignedDescriptor failed\r\n");
  1921. EfiBS->Exit(EfiImageHandle, Status, 0, 0);
  1922. }
  1923. BlockIoHandlesBitmap = (ULONG *)(ULONGLONG)((ULONGLONG)MemoryPage << PAGE_SHIFT);
  1924. //
  1925. // Change to physical mode so that we can make EFI calls
  1926. //
  1927. FlipToPhysical();
  1928. RtlZeroMemory(CachedDevicePaths, HandleCount*sizeof(ULONGLONG));
  1929. for (i=0;i<HandleCount; i++) {
  1930. BlockIoHandlesBitmap[i] = DEVICE_NOT_FOUND;
  1931. }
  1932. //
  1933. // Cache all of the EFI Device Paths
  1934. //
  1935. for (i = 0; i < HandleCount; i++) {
  1936. Status = EfiBS->HandleProtocol (
  1937. BlockIoHandles[i],
  1938. &EfiDevicePathProtocol,
  1939. &( (EFI_DEVICE_PATH *) CachedDevicePaths[i] )
  1940. );
  1941. }
  1942. // Save the number of cached Device Paths
  1943. nCachedDevicePaths = i;
  1944. ASSERT(nCachedDevicePaths = HandleCount);
  1945. //
  1946. // Find all of the harddrives
  1947. //
  1948. for( i=0; i<nCachedDevicePaths; i++ ) {
  1949. //
  1950. // Get next device path.
  1951. //
  1952. CurrentDevicePath = (EFI_DEVICE_PATH *) CachedDevicePaths[i];
  1953. EfiAlignDp(
  1954. &TestPathAligned,
  1955. CurrentDevicePath,
  1956. DevicePathNodeLength( CurrentDevicePath )
  1957. );
  1958. TestPath = (EFI_DEVICE_PATH *) &TestPathAligned;
  1959. while( ( TestPath->Type != END_DEVICE_PATH_TYPE ) ) {
  1960. //
  1961. // Look for Media HardDrive node
  1962. //
  1963. if(((EFI_DEVICE_PATH *) NextDevicePathNode( CurrentDevicePath ))->Type == END_DEVICE_PATH_TYPE) {
  1964. //
  1965. // Since we found a harddrive, find the
  1966. // raw device associated with it.
  1967. //
  1968. nFoundDevice = DEVICE_NOT_FOUND;
  1969. if( ( TestPath->Type == MESSAGING_DEVICE_PATH ) &&
  1970. ( TestPath->SubType == MSG_ATAPI_DP ) ) {
  1971. Status = EfiBS->HandleProtocol(
  1972. BlockIoHandles[i],
  1973. &EfiBlockIoProtocol,
  1974. &(( EFI_BLOCK_IO * ) BlkIo) );
  1975. if(!BlkIo->Media->RemovableMedia) {
  1976. //
  1977. // Find the ATAPI raw device
  1978. //
  1979. nFoundDevice = FindAtapiDevice(
  1980. CachedDevicePaths,
  1981. nCachedDevicePaths,
  1982. ((ATAPI_DEVICE_PATH *) TestPath)->PrimarySecondary,
  1983. ((ATAPI_DEVICE_PATH *) TestPath)->SlaveMaster,
  1984. ((ATAPI_DEVICE_PATH *) TestPath)->Lun
  1985. );
  1986. }
  1987. } else if( ( TestPath->Type == MESSAGING_DEVICE_PATH ) &&
  1988. ( TestPath->SubType == MSG_SCSI_DP ) ) {
  1989. Status = EfiBS->HandleProtocol(
  1990. BlockIoHandles[i],
  1991. &EfiBlockIoProtocol,
  1992. &(( EFI_BLOCK_IO * ) BlkIo) );
  1993. if(!BlkIo->Media->RemovableMedia) {
  1994. //
  1995. // Find SCSI raw device
  1996. //
  1997. nFoundDevice = FindScsiDevice(
  1998. CachedDevicePaths,
  1999. nCachedDevicePaths,
  2000. ((SCSI_DEVICE_PATH *) TestPath)->Pun,
  2001. ((SCSI_DEVICE_PATH *) TestPath)->Lun
  2002. );
  2003. }
  2004. } else if( ( TestPath->Type == HARDWARE_DEVICE_PATH ) &&
  2005. ( TestPath->SubType == HW_VENDOR_DP ) ) {
  2006. //
  2007. // Find the Hardware Vendor raw device by ensuring it is not a
  2008. // removable media
  2009. //
  2010. Status = EfiBS->HandleProtocol( BlockIoHandles[i], &EfiBlockIoProtocol, &(( EFI_BLOCK_IO * ) BlkIo) );
  2011. if(BlkIo->Media->RemovableMedia)
  2012. nFoundDevice = DEVICE_NOT_FOUND;
  2013. else
  2014. nFoundDevice = 1;
  2015. }
  2016. if( nFoundDevice != DEVICE_NOT_FOUND ) {
  2017. // Found a raw device
  2018. BlockIoHandlesBitmap[ i ] = i;
  2019. switch (DriveType) {
  2020. case BL_DISKTYPE_ATAPI:
  2021. if( ( TestPath->Type == MESSAGING_DEVICE_PATH ) &&
  2022. ( TestPath->SubType == MSG_ATAPI_DP ) &&
  2023. ( ((ATAPI_DEVICE_PATH *) TestPath)->PrimarySecondary ==
  2024. ((PBOOT_DEVICE_ATAPI)Device)->PrimarySecondary) &&
  2025. ( ((ATAPI_DEVICE_PATH *) TestPath)->SlaveMaster ==
  2026. ((PBOOT_DEVICE_ATAPI)Device)->SlaveMaster) &&
  2027. ( ((ATAPI_DEVICE_PATH *) TestPath)->Lun ==
  2028. ((PBOOT_DEVICE_ATAPI)Device)->Lun) ) {
  2029. DriveId = nFoundDevice;
  2030. //DriveId = i;
  2031. }
  2032. break;
  2033. case BL_DISKTYPE_SCSI:
  2034. if( ( TestPath->Type == MESSAGING_DEVICE_PATH ) &&
  2035. ( TestPath->SubType == MSG_SCSI_DP ) &&
  2036. ( ((SCSI_DEVICE_PATH *) TestPath)->Pun ==
  2037. ((PBOOT_DEVICE_SCSI)Device)->Pun) &&
  2038. ( ((SCSI_DEVICE_PATH *) TestPath)->Lun ==
  2039. ((PBOOT_DEVICE_SCSI)Device)->Lun) ) {
  2040. DriveId = nFoundDevice;
  2041. //DriveId = i;
  2042. }
  2043. break;
  2044. case BL_DISKTYPE_UNKNOWN:
  2045. if( ( TestPath->Type == HARDWARE_DEVICE_PATH ) &&
  2046. ( TestPath->SubType == HW_VENDOR_DP ) ) {
  2047. DriveId = nFoundDevice;
  2048. //DriveId = i;
  2049. }
  2050. break;
  2051. default:
  2052. break;
  2053. }
  2054. }
  2055. } // if END_DEVICE_PATH_TYPE
  2056. //
  2057. // Get next device path node.
  2058. //
  2059. CurrentDevicePath = NextDevicePathNode( CurrentDevicePath );
  2060. EfiAlignDp(
  2061. &TestPathAligned,
  2062. CurrentDevicePath,
  2063. DevicePathNodeLength( CurrentDevicePath )
  2064. );
  2065. TestPath = (EFI_DEVICE_PATH *) &TestPathAligned;
  2066. }
  2067. }
  2068. //
  2069. // Change back to virtual mode.
  2070. //
  2071. FlipToVirtual();
  2072. BlFreeDescriptor( (ULONG)((ULONGLONG)BlockIoHandles >> PAGE_SHIFT) );
  2073. BlFreeDescriptor( (ULONG)((ULONGLONG)BlockIoHandlesBitmap >> PAGE_SHIFT) );
  2074. BlFreeDescriptor( (ULONG)((ULONGLONG)CachedDevicePaths >> PAGE_SHIFT) );
  2075. return nDriveCount;
  2076. //return nFoundDevice;
  2077. //return DriveId;
  2078. }
  2079. EFI_HANDLE
  2080. GetHardDrive(
  2081. ULONG DriveId
  2082. )
  2083. {
  2084. ULONG i;
  2085. EFI_STATUS Status = EFI_INVALID_PARAMETER;
  2086. ULONG nCachedDevicePaths = 0;
  2087. ULONGLONG *CachedDevicePaths;
  2088. EFI_BLOCK_IO * BlkIo;
  2089. ULONG HandleCount;
  2090. EFI_HANDLE *BlockIoHandles;
  2091. EFI_DEVICE_PATH *TestPath;
  2092. EFI_DEVICE_PATH_ALIGNED TestPathAligned;
  2093. ULONG *BlockIoHandlesBitmap;
  2094. ULONG nFoundDevice = DEVICE_NOT_FOUND;
  2095. ULONG nDriveCount = 0;
  2096. EFI_DEVICE_PATH *CurrentDevicePath;
  2097. BOOLEAN DuplicateFound;
  2098. EFI_HANDLE ReturnDeviceHandle = (EFI_HANDLE) DEVICE_NOT_FOUND;
  2099. ULONG MemoryPage;
  2100. ARC_STATUS ArcStatus;
  2101. //
  2102. // get all handles that support the block I/O protocol.
  2103. //
  2104. ArcStatus = BlGetEfiProtocolHandles(
  2105. &EfiBlockIoProtocol,
  2106. &BlockIoHandles,
  2107. &HandleCount);
  2108. if (ArcStatus != ESUCCESS) {
  2109. EfiST->ConOut->OutputString(EfiST->ConOut,
  2110. L"BlGetDriveId: BlGetEfiProtocolHandles failed\r\n");
  2111. EfiBS->Exit(EfiImageHandle, Status, 0, 0);
  2112. }
  2113. //
  2114. // now that we know how many handles there are, we can allocate space for
  2115. // the CachedDevicePaths and BlockIoHandlesBitmap
  2116. //
  2117. ArcStatus = BlAllocateAlignedDescriptor(
  2118. LoaderFirmwareTemporary,
  2119. 0,
  2120. (ULONG)((HandleCount*sizeof(ULONGLONG)) >> PAGE_SIZE),
  2121. 0,
  2122. &MemoryPage);
  2123. if (ArcStatus != ESUCCESS) {
  2124. EfiST->ConOut->OutputString(EfiST->ConOut,
  2125. L"BlGetDriveId: BlAllocateAlignedDescriptor failed\r\n");
  2126. EfiBS->Exit(EfiImageHandle, Status, 0, 0);
  2127. }
  2128. CachedDevicePaths = (ULONGLONG *)(ULONGLONG)((ULONGLONG)MemoryPage << PAGE_SHIFT);
  2129. ArcStatus = BlAllocateAlignedDescriptor(
  2130. LoaderFirmwareTemporary,
  2131. 0,
  2132. (ULONG)((HandleCount*sizeof(ULONG)) >> PAGE_SIZE),
  2133. 0,
  2134. &MemoryPage);
  2135. if (ArcStatus != ESUCCESS) {
  2136. EfiST->ConOut->OutputString(EfiST->ConOut,
  2137. L"BlGetDriveId: BlAllocateAlignedDescriptor failed\r\n");
  2138. EfiBS->Exit(EfiImageHandle, Status, 0, 0);
  2139. }
  2140. BlockIoHandlesBitmap = (ULONG *)(ULONGLONG)((ULONGLONG)MemoryPage << PAGE_SHIFT);
  2141. //
  2142. // Change to physical mode so that we can make EFI calls
  2143. //
  2144. FlipToPhysical();
  2145. RtlZeroMemory(CachedDevicePaths, HandleCount*sizeof(ULONGLONG));
  2146. for (i=0;i<HandleCount; i++) {
  2147. BlockIoHandlesBitmap[i] = DEVICE_NOT_FOUND;
  2148. }
  2149. //
  2150. // Cache all of the EFI Device Paths
  2151. //
  2152. for (i = 0; i < HandleCount; i++) {
  2153. Status = EfiBS->HandleProtocol (
  2154. BlockIoHandles[i],
  2155. &EfiDevicePathProtocol,
  2156. &( (EFI_DEVICE_PATH *) CachedDevicePaths[i] )
  2157. );
  2158. }
  2159. // Save the number of cached Device Paths
  2160. nCachedDevicePaths = i;
  2161. //
  2162. // Find all of the harddrives
  2163. //
  2164. for( i=0; i<nCachedDevicePaths; i++ ) {
  2165. //
  2166. // Get next device path.
  2167. //
  2168. CurrentDevicePath = (EFI_DEVICE_PATH *) CachedDevicePaths[i];
  2169. EfiAlignDp(
  2170. &TestPathAligned,
  2171. CurrentDevicePath,
  2172. DevicePathNodeLength( CurrentDevicePath )
  2173. );
  2174. TestPath = (EFI_DEVICE_PATH *) &TestPathAligned;
  2175. while( ( TestPath->Type != END_DEVICE_PATH_TYPE ) ) {
  2176. //
  2177. // Look for Media HardDrive node
  2178. //
  2179. if(((EFI_DEVICE_PATH *) NextDevicePathNode( CurrentDevicePath ))->Type == END_DEVICE_PATH_TYPE) {
  2180. //
  2181. // Since we found a harddrive, find the
  2182. // raw device associated with it.
  2183. //
  2184. nFoundDevice = DEVICE_NOT_FOUND;
  2185. if( ( TestPath->Type == MESSAGING_DEVICE_PATH ) &&
  2186. ( TestPath->SubType == MSG_ATAPI_DP ) ) {
  2187. Status = EfiBS->HandleProtocol(
  2188. BlockIoHandles[i],
  2189. &EfiBlockIoProtocol,
  2190. &(( EFI_BLOCK_IO * ) BlkIo) );
  2191. if(!BlkIo->Media->RemovableMedia) {
  2192. //
  2193. // Find the ATAPI raw device
  2194. //
  2195. nFoundDevice = FindAtapiDevice(
  2196. CachedDevicePaths,
  2197. nCachedDevicePaths,
  2198. ((ATAPI_DEVICE_PATH *) TestPath)->PrimarySecondary,
  2199. ((ATAPI_DEVICE_PATH *) TestPath)->SlaveMaster,
  2200. ((ATAPI_DEVICE_PATH *) TestPath)->Lun
  2201. );
  2202. }
  2203. } else if( ( TestPath->Type == MESSAGING_DEVICE_PATH ) &&
  2204. ( TestPath->SubType == MSG_SCSI_DP ) ) {
  2205. Status = EfiBS->HandleProtocol(
  2206. BlockIoHandles[i],
  2207. &EfiBlockIoProtocol,
  2208. &(( EFI_BLOCK_IO * ) BlkIo) );
  2209. if(!BlkIo->Media->RemovableMedia) {
  2210. //
  2211. // Find SCSI raw device
  2212. //
  2213. nFoundDevice = FindScsiDevice(
  2214. CachedDevicePaths,
  2215. nCachedDevicePaths,
  2216. ((SCSI_DEVICE_PATH *) TestPath)->Pun,
  2217. ((SCSI_DEVICE_PATH *) TestPath)->Lun
  2218. );
  2219. }
  2220. } else if( ( TestPath->Type == HARDWARE_DEVICE_PATH ) &&
  2221. ( TestPath->SubType == HW_VENDOR_DP ) ) {
  2222. //
  2223. // Find the Hardware Vendor raw device by ensuring it is not a
  2224. // removable media
  2225. //
  2226. Status = EfiBS->HandleProtocol( BlockIoHandles[i], &EfiBlockIoProtocol, &(( EFI_BLOCK_IO * ) BlkIo) );
  2227. if(BlkIo->Media->RemovableMedia) {
  2228. nFoundDevice = DEVICE_NOT_FOUND;
  2229. }
  2230. else {
  2231. nFoundDevice = 1;
  2232. }
  2233. }
  2234. if( nFoundDevice != DEVICE_NOT_FOUND ) {
  2235. // Found a raw device
  2236. BlockIoHandlesBitmap[ i ] = i;
  2237. }
  2238. } // if END_DEVICE_PATH_TYPE
  2239. //
  2240. // Get next device path node.
  2241. //
  2242. CurrentDevicePath = NextDevicePathNode( CurrentDevicePath );
  2243. EfiAlignDp(
  2244. &TestPathAligned,
  2245. CurrentDevicePath,
  2246. DevicePathNodeLength( CurrentDevicePath )
  2247. );
  2248. TestPath = (EFI_DEVICE_PATH *) &TestPathAligned;
  2249. }
  2250. }
  2251. //
  2252. // Count the bitmap and when we find
  2253. // the DriveId, return the BlockIoHandle
  2254. //
  2255. for( i=0; i<nCachedDevicePaths; i++ ) {
  2256. if( BlockIoHandlesBitmap[i] != DEVICE_NOT_FOUND ) {
  2257. if( nDriveCount++ == DriveId ) {
  2258. ReturnDeviceHandle = BlockIoHandles[BlockIoHandlesBitmap[i]];
  2259. }
  2260. }
  2261. }
  2262. //
  2263. // Change back to virtual mode.
  2264. //
  2265. FlipToVirtual();
  2266. BlFreeDescriptor( (ULONG)((ULONGLONG)BlockIoHandles >> PAGE_SHIFT) );
  2267. BlFreeDescriptor( (ULONG)((ULONGLONG)BlockIoHandlesBitmap >> PAGE_SHIFT) );
  2268. BlFreeDescriptor( (ULONG)((ULONGLONG)CachedDevicePaths >> PAGE_SHIFT) );
  2269. return ReturnDeviceHandle;
  2270. }
  2271. ULONG
  2272. FindAtapiDevice(
  2273. ULONGLONG *pDevicePaths,
  2274. ULONG nDevicePaths,
  2275. ULONG PrimarySecondary,
  2276. ULONG SlaveMaster,
  2277. ULONG Lun
  2278. )
  2279. {
  2280. ULONG i = 0, nFoundDevice = 0;
  2281. EFI_DEVICE_PATH *TestPath;
  2282. EFI_DEVICE_PATH_ALIGNED TestPathAligned;
  2283. EFI_DEVICE_PATH *CurrentDevicePath;
  2284. //
  2285. // Find the Atapi raw device whose PrimarySecondary,
  2286. // SlaveMaster and Lun are a match.
  2287. //
  2288. for( i=0; i<nDevicePaths; i++ ) {
  2289. //
  2290. // Get next device path.
  2291. //
  2292. CurrentDevicePath = (EFI_DEVICE_PATH *) pDevicePaths[i];
  2293. EfiAlignDp(
  2294. &TestPathAligned,
  2295. CurrentDevicePath,
  2296. DevicePathNodeLength( CurrentDevicePath )
  2297. );
  2298. TestPath = (EFI_DEVICE_PATH *) &TestPathAligned;
  2299. while( (TestPath->Type != END_DEVICE_PATH_TYPE) ) {
  2300. if( ( TestPath->Type == MESSAGING_DEVICE_PATH ) &&
  2301. ( TestPath->SubType == MSG_ATAPI_DP ) ) {
  2302. if( ( ((ATAPI_DEVICE_PATH *)TestPath)->PrimarySecondary == PrimarySecondary ) &&
  2303. ( ((ATAPI_DEVICE_PATH *)TestPath)->SlaveMaster == SlaveMaster ) &&
  2304. ( ((ATAPI_DEVICE_PATH *)TestPath)->Lun == Lun )) {
  2305. nFoundDevice = i;
  2306. return nFoundDevice;
  2307. }
  2308. }
  2309. //
  2310. // Get next device path node.
  2311. //
  2312. CurrentDevicePath = NextDevicePathNode( CurrentDevicePath );
  2313. EfiAlignDp(
  2314. &TestPathAligned,
  2315. CurrentDevicePath,
  2316. DevicePathNodeLength( CurrentDevicePath )
  2317. );
  2318. TestPath = (EFI_DEVICE_PATH *) &TestPathAligned;
  2319. }
  2320. }
  2321. #if DBG
  2322. BlPrint( TEXT("FindAtapiDevice returning DEVICE_NOT_FOUND\r\n"));
  2323. if (BdDebuggerEnabled == TRUE) {
  2324. DbgBreakPoint();
  2325. }
  2326. #endif
  2327. return DEVICE_NOT_FOUND;
  2328. }
  2329. ULONG
  2330. FindScsiDevice(
  2331. ULONGLONG *pDevicePaths,
  2332. ULONG nDevicePaths,
  2333. ULONG Pun,
  2334. ULONG Lun
  2335. )
  2336. {
  2337. ULONG i = 0, nFoundDevice = 0;
  2338. EFI_DEVICE_PATH *TestPath;
  2339. EFI_DEVICE_PATH_ALIGNED TestPathAligned;
  2340. EFI_DEVICE_PATH *CurrentDevicePath;
  2341. //
  2342. // Find the Atapi raw device whose PrimarySecondary,
  2343. // SlaveMaster and Lun are a match.
  2344. //
  2345. for( i=0; i<nDevicePaths; i++ ) {
  2346. //
  2347. // Get next device path.
  2348. //
  2349. CurrentDevicePath = (EFI_DEVICE_PATH *) pDevicePaths[i];
  2350. EfiAlignDp(
  2351. &TestPathAligned,
  2352. CurrentDevicePath,
  2353. DevicePathNodeLength( CurrentDevicePath )
  2354. );
  2355. TestPath = (EFI_DEVICE_PATH *) &TestPathAligned;
  2356. while( (TestPath->Type != END_DEVICE_PATH_TYPE) ) {
  2357. if( ( TestPath->Type == MESSAGING_DEVICE_PATH ) &&
  2358. ( TestPath->SubType == MSG_SCSI_DP ) ) {
  2359. if( ( ((SCSI_DEVICE_PATH *)TestPath)->Pun == Pun ) &&
  2360. ( ((SCSI_DEVICE_PATH *)TestPath)->Lun == Lun )) {
  2361. nFoundDevice = i;
  2362. return nFoundDevice;
  2363. }
  2364. }
  2365. //
  2366. // Get next device path node.
  2367. //
  2368. CurrentDevicePath = NextDevicePathNode( CurrentDevicePath );
  2369. EfiAlignDp(
  2370. &TestPathAligned,
  2371. CurrentDevicePath,
  2372. DevicePathNodeLength( CurrentDevicePath )
  2373. );
  2374. TestPath = (EFI_DEVICE_PATH *) &TestPathAligned;
  2375. }
  2376. }
  2377. #if DBG
  2378. BlPrint( TEXT("FindScsiDevice returning DEVICE_NOT_FOUND\r\n"));
  2379. if (BdDebuggerEnabled == TRUE) {
  2380. DbgBreakPoint();
  2381. }
  2382. #endif
  2383. return DEVICE_NOT_FOUND;
  2384. }
  2385. ULONG
  2386. GetDriveCount(
  2387. )
  2388. {
  2389. ULONG i;
  2390. EFI_STATUS Status = EFI_INVALID_PARAMETER;
  2391. ULONG nCachedDevicePaths = 0;
  2392. ULONGLONG *CachedDevicePaths;
  2393. EFI_BLOCK_IO * BlkIo;
  2394. ULONG HandleCount;
  2395. EFI_HANDLE *BlockIoHandles;
  2396. EFI_DEVICE_PATH *TestPath;
  2397. EFI_DEVICE_PATH_ALIGNED TestPathAligned;
  2398. ULONG *BlockIoHandlesBitmap;
  2399. ULONG nFoundDevice = 0;
  2400. ULONG nDriveCount = 0;
  2401. EFI_DEVICE_PATH *CurrentDevicePath;
  2402. BOOLEAN DuplicateFound;
  2403. EFI_HANDLE ReturnDeviceHandle = (EFI_HANDLE) DEVICE_NOT_FOUND;
  2404. ULONG MemoryPage;
  2405. ARC_STATUS ArcStatus;
  2406. //
  2407. // get all handles that support the block I/O protocol.
  2408. //
  2409. ArcStatus = BlGetEfiProtocolHandles(
  2410. &EfiBlockIoProtocol,
  2411. &BlockIoHandles,
  2412. &HandleCount);
  2413. if (ArcStatus != ESUCCESS) {
  2414. EfiST->ConOut->OutputString(EfiST->ConOut,
  2415. L"BlGetDriveId: BlGetEfiProtocolHandles failed\r\n");
  2416. EfiBS->Exit(EfiImageHandle, Status, 0, 0);
  2417. }
  2418. //
  2419. // now that we know how many handles there are, we can allocate space for
  2420. // the CachedDevicePaths and BlockIoHandlesBitmap
  2421. //
  2422. ArcStatus = BlAllocateAlignedDescriptor(
  2423. LoaderFirmwareTemporary,
  2424. 0,
  2425. (ULONG)((HandleCount*sizeof(ULONGLONG)) >> PAGE_SIZE),
  2426. 0,
  2427. &MemoryPage);
  2428. if (ArcStatus != ESUCCESS) {
  2429. EfiST->ConOut->OutputString(EfiST->ConOut,
  2430. L"BlGetDriveId: BlAllocateAlignedDescriptor failed\r\n");
  2431. EfiBS->Exit(EfiImageHandle, Status, 0, 0);
  2432. }
  2433. CachedDevicePaths = (ULONGLONG *)(ULONGLONG)((ULONGLONG)MemoryPage << PAGE_SHIFT);
  2434. ArcStatus = BlAllocateAlignedDescriptor(
  2435. LoaderFirmwareTemporary,
  2436. 0,
  2437. (ULONG)((HandleCount*sizeof(ULONG)) >> PAGE_SIZE),
  2438. 0,
  2439. &MemoryPage);
  2440. if (ArcStatus != ESUCCESS) {
  2441. EfiST->ConOut->OutputString(EfiST->ConOut,
  2442. L"BlGetDriveId: BlAllocateAlignedDescriptor failed\r\n");
  2443. EfiBS->Exit(EfiImageHandle, Status, 0, 0);
  2444. }
  2445. BlockIoHandlesBitmap = (ULONG *)(ULONGLONG)((ULONGLONG)MemoryPage << PAGE_SHIFT);
  2446. //
  2447. // Change to physical mode so that we can make EFI calls
  2448. //
  2449. FlipToPhysical();
  2450. RtlZeroMemory(CachedDevicePaths, HandleCount*sizeof(ULONGLONG));
  2451. for (i=0;i<HandleCount; i++) {
  2452. BlockIoHandlesBitmap[i] = DEVICE_NOT_FOUND;
  2453. }
  2454. //
  2455. // Cache all of the EFI Device Paths
  2456. //
  2457. for (i = 0; i < HandleCount; i++) {
  2458. Status = EfiBS->HandleProtocol (
  2459. BlockIoHandles[i],
  2460. &EfiDevicePathProtocol,
  2461. &( (EFI_DEVICE_PATH *) CachedDevicePaths[i] )
  2462. );
  2463. }
  2464. // Save the number of cached Device Paths
  2465. nCachedDevicePaths = i;
  2466. //
  2467. // Find all of the harddrives
  2468. //
  2469. for( i=0; i<nCachedDevicePaths; i++ ) {
  2470. //
  2471. // Get next device path.
  2472. //
  2473. CurrentDevicePath = (EFI_DEVICE_PATH *) CachedDevicePaths[i];
  2474. EfiAlignDp(
  2475. &TestPathAligned,
  2476. CurrentDevicePath,
  2477. DevicePathNodeLength( CurrentDevicePath )
  2478. );
  2479. TestPath = (EFI_DEVICE_PATH *) &TestPathAligned;
  2480. while( ( TestPath->Type != END_DEVICE_PATH_TYPE ) ) {
  2481. //
  2482. // Look for Media HardDrive node
  2483. //
  2484. if(((EFI_DEVICE_PATH *) NextDevicePathNode( CurrentDevicePath ))->Type == END_DEVICE_PATH_TYPE) {
  2485. //
  2486. // Since we found a harddrive, find the
  2487. // raw device associated with it.
  2488. //
  2489. nFoundDevice = DEVICE_NOT_FOUND;
  2490. if( ( TestPath->Type == MESSAGING_DEVICE_PATH ) &&
  2491. ( TestPath->SubType == MSG_ATAPI_DP ) ) {
  2492. Status = EfiBS->HandleProtocol(
  2493. BlockIoHandles[i],
  2494. &EfiBlockIoProtocol,
  2495. &(( EFI_BLOCK_IO * ) BlkIo) );
  2496. if(!BlkIo->Media->RemovableMedia) {
  2497. //
  2498. // Find the ATAPI raw device
  2499. //
  2500. nFoundDevice = FindAtapiDevice(
  2501. CachedDevicePaths,
  2502. nCachedDevicePaths,
  2503. ((ATAPI_DEVICE_PATH *) TestPath)->PrimarySecondary,
  2504. ((ATAPI_DEVICE_PATH *) TestPath)->SlaveMaster,
  2505. ((ATAPI_DEVICE_PATH *) TestPath)->Lun
  2506. );
  2507. }
  2508. } else if( ( TestPath->Type == MESSAGING_DEVICE_PATH ) &&
  2509. ( TestPath->SubType == MSG_SCSI_DP ) ) {
  2510. Status = EfiBS->HandleProtocol(
  2511. BlockIoHandles[i],
  2512. &EfiBlockIoProtocol,
  2513. &(( EFI_BLOCK_IO * ) BlkIo) );
  2514. if(!BlkIo->Media->RemovableMedia) {
  2515. //
  2516. // Find SCSI raw device
  2517. //
  2518. nFoundDevice = FindScsiDevice(
  2519. CachedDevicePaths,
  2520. nCachedDevicePaths,
  2521. ((SCSI_DEVICE_PATH *) TestPath)->Pun,
  2522. ((SCSI_DEVICE_PATH *) TestPath)->Lun
  2523. );
  2524. }
  2525. } else if( ( TestPath->Type == HARDWARE_DEVICE_PATH ) &&
  2526. ( TestPath->SubType == HW_VENDOR_DP ) ) {
  2527. //
  2528. // Find the Hardware Vendor raw device by ensuring it is not a
  2529. // removable media
  2530. //
  2531. Status = EfiBS->HandleProtocol( BlockIoHandles[i], &EfiBlockIoProtocol, &(( EFI_BLOCK_IO * ) BlkIo) );
  2532. if(BlkIo->Media->RemovableMedia)
  2533. ;
  2534. else
  2535. nFoundDevice = 1;
  2536. }
  2537. if( nFoundDevice != DEVICE_NOT_FOUND ) {
  2538. // Found a raw device
  2539. BlockIoHandlesBitmap[ i ] = nFoundDevice;
  2540. }
  2541. } // if END_DEVICE_PATH_TYPE
  2542. //
  2543. // Get next device path node.
  2544. //
  2545. CurrentDevicePath = NextDevicePathNode( CurrentDevicePath );
  2546. EfiAlignDp(
  2547. &TestPathAligned,
  2548. CurrentDevicePath,
  2549. DevicePathNodeLength( CurrentDevicePath )
  2550. );
  2551. TestPath = (EFI_DEVICE_PATH *) &TestPathAligned;
  2552. } // while
  2553. } // for
  2554. //
  2555. // Count the bitmap and when we find
  2556. // the DriveId, return the BlockIoHandle
  2557. //
  2558. for( i=0; i<nCachedDevicePaths; i++ ) {
  2559. if( BlockIoHandlesBitmap[i] != DEVICE_NOT_FOUND ) {
  2560. nDriveCount++;
  2561. }
  2562. }
  2563. //
  2564. // Change back to virtual mode.
  2565. //
  2566. FlipToVirtual();
  2567. BlFreeDescriptor( (ULONG)((ULONGLONG)BlockIoHandles >> PAGE_SHIFT) );
  2568. BlFreeDescriptor( (ULONG)((ULONGLONG)BlockIoHandlesBitmap >> PAGE_SHIFT) );
  2569. BlFreeDescriptor( (ULONG)((ULONGLONG)CachedDevicePaths >> PAGE_SHIFT) );
  2570. return nDriveCount;
  2571. }
  2572. BOOLEAN
  2573. IsVirtualFloppyDevice(
  2574. EFI_HANDLE DeviceHandle
  2575. )
  2576. /*++
  2577. Routine Description:
  2578. Finds out if the given device is a virtual floppy (i.e. RAM Disk).
  2579. NOTE : Currently we assume that if a device supports
  2580. Block, Disk, File System & LoadedImage protocols then it should
  2581. be virtual floppy. Also assumes that FlipToPhysical(...) has be
  2582. already been called.
  2583. Arguments:
  2584. DeviceHandle - Handle to the device which needs to be tested.
  2585. Return Value:
  2586. TRUE if the device is virtual floppy otherwise FALSE
  2587. --*/
  2588. {
  2589. BOOLEAN Result = FALSE;
  2590. if (DeviceHandle != (EFI_HANDLE)DEVICE_NOT_FOUND) {
  2591. EFI_STATUS EfiStatus;
  2592. EFI_BLOCK_IO *EfiBlock = NULL;
  2593. EFI_DISK_IO *EfiDisk = NULL;
  2594. EFI_LOADED_IMAGE *EfiImage = NULL;
  2595. EFI_FILE_IO_INTERFACE *EfiFs = NULL;
  2596. //
  2597. // Get hold of the loaded image protocol handle
  2598. //
  2599. EfiStatus = EfiBS->HandleProtocol(DeviceHandle,
  2600. &EfiLoadedImageProtocol,
  2601. &EfiImage);
  2602. if (!EFI_ERROR(EfiStatus) && EfiImage) {
  2603. //
  2604. // Get hold of the FS protocol handle
  2605. //
  2606. EfiStatus = EfiBS->HandleProtocol(DeviceHandle,
  2607. &EfiFilesystemProtocol,
  2608. &EfiFs);
  2609. if (!EFI_ERROR(EfiStatus) && EfiFs) {
  2610. //
  2611. // Get hold of the disk protocol
  2612. //
  2613. EfiStatus = EfiBS->HandleProtocol(DeviceHandle,
  2614. &EfiDiskIoProtocol,
  2615. &EfiDisk);
  2616. if (!EFI_ERROR(EfiStatus) && EfiDisk) {
  2617. //
  2618. // Get hold of the block protocol
  2619. //
  2620. EfiStatus = EfiBS->HandleProtocol(DeviceHandle,
  2621. &EfiBlockIoProtocol,
  2622. &EfiBlock);
  2623. if (!EFI_ERROR(EfiStatus) && EfiBlock) {
  2624. Result = TRUE;
  2625. }
  2626. }
  2627. }
  2628. }
  2629. }
  2630. return Result;
  2631. }
  2632. EFI_HANDLE
  2633. GetFloppyDrive(
  2634. ULONG DriveId
  2635. )
  2636. {
  2637. ULONG i;
  2638. EFI_STATUS Status = EFI_INVALID_PARAMETER;
  2639. ULONG nCachedDevicePaths = 0;
  2640. ULONGLONG *CachedDevicePaths;
  2641. ULONG HandleCount;
  2642. EFI_HANDLE *BlockIoHandles;
  2643. EFI_DEVICE_PATH *TestPath;
  2644. EFI_DEVICE_PATH_ALIGNED TestPathAligned;
  2645. ULONG *BlockIoHandlesBitmap;
  2646. ULONG nFoundDevice = 0;
  2647. ULONG nDriveCount = 0;
  2648. EFI_DEVICE_PATH *CurrentDevicePath;
  2649. BOOLEAN DuplicateFound;
  2650. EFI_HANDLE ReturnDeviceHandle = (EFI_HANDLE) DEVICE_NOT_FOUND;
  2651. ULONG MemoryPage;
  2652. ARC_STATUS ArcStatus;
  2653. //
  2654. // get all handles that support the block I/O protocol.
  2655. //
  2656. ArcStatus = BlGetEfiProtocolHandles(
  2657. &EfiBlockIoProtocol,
  2658. &BlockIoHandles,
  2659. &HandleCount);
  2660. if (ArcStatus != ESUCCESS) {
  2661. EfiST->ConOut->OutputString(EfiST->ConOut,
  2662. L"BlGetDriveId: BlGetEfiProtocolHandles failed\r\n");
  2663. EfiBS->Exit(EfiImageHandle, Status, 0, 0);
  2664. }
  2665. //
  2666. // now that we know how many handles there are, we can allocate space for
  2667. // the CachedDevicePaths and BlockIoHandlesBitmap
  2668. //
  2669. ArcStatus = BlAllocateAlignedDescriptor(
  2670. LoaderFirmwareTemporary,
  2671. 0,
  2672. (ULONG)((HandleCount*sizeof(ULONGLONG)) >> PAGE_SIZE),
  2673. 0,
  2674. &MemoryPage);
  2675. if (ArcStatus != ESUCCESS) {
  2676. EfiST->ConOut->OutputString(EfiST->ConOut,
  2677. L"BlGetDriveId: BlAllocateAlignedDescriptor failed\r\n");
  2678. EfiBS->Exit(EfiImageHandle, Status, 0, 0);
  2679. }
  2680. CachedDevicePaths = (ULONGLONG *)(ULONGLONG)((ULONGLONG)MemoryPage << PAGE_SHIFT);
  2681. ArcStatus = BlAllocateAlignedDescriptor(
  2682. LoaderFirmwareTemporary,
  2683. 0,
  2684. (ULONG)((HandleCount*sizeof(ULONG)) >> PAGE_SIZE),
  2685. 0,
  2686. &MemoryPage);
  2687. if (ArcStatus != ESUCCESS) {
  2688. EfiST->ConOut->OutputString(EfiST->ConOut,
  2689. L"BlGetDriveId: BlAllocateAlignedDescriptor failed\r\n");
  2690. EfiBS->Exit(EfiImageHandle, Status, 0, 0);
  2691. }
  2692. BlockIoHandlesBitmap = (ULONG *)(ULONGLONG)((ULONGLONG)MemoryPage << PAGE_SHIFT);
  2693. //
  2694. // Change to physical mode so that we can make EFI calls
  2695. //
  2696. FlipToPhysical();
  2697. RtlZeroMemory(CachedDevicePaths, HandleCount*sizeof(ULONGLONG));
  2698. for (i=0;i<HandleCount; i++) {
  2699. BlockIoHandlesBitmap[i] = DEVICE_NOT_FOUND;
  2700. }
  2701. //
  2702. // Cache all of the EFI Device Paths
  2703. //
  2704. for (i = 0; i < HandleCount; i++) {
  2705. Status = EfiBS->HandleProtocol (
  2706. BlockIoHandles[i],
  2707. &EfiDevicePathProtocol,
  2708. &( (EFI_DEVICE_PATH *) CachedDevicePaths[i] )
  2709. );
  2710. }
  2711. // Save the number of cached Device Paths
  2712. nCachedDevicePaths = i;
  2713. //
  2714. // Find the floppy.
  2715. //
  2716. for( i=0; i<nCachedDevicePaths; i++ ) {
  2717. //
  2718. // Get next device path.
  2719. //
  2720. CurrentDevicePath = (EFI_DEVICE_PATH *) CachedDevicePaths[i];
  2721. EfiAlignDp(
  2722. &TestPathAligned,
  2723. CurrentDevicePath,
  2724. DevicePathNodeLength( CurrentDevicePath )
  2725. );
  2726. TestPath = (EFI_DEVICE_PATH *) &TestPathAligned;
  2727. while( ( TestPath->Type != END_DEVICE_PATH_TYPE ) ) {
  2728. if (!DriveId) {
  2729. if( ( TestPath->Type == HARDWARE_DEVICE_PATH ) &&
  2730. ( TestPath->SubType == HW_VENDOR_DP ) ) {
  2731. //
  2732. // Find the Hardware Vendor raw device
  2733. //
  2734. if(!(((UNKNOWN_DEVICE_VENDOR_DEVICE_PATH *) TestPath)->LegacyDriveLetter & 0x80) &&
  2735. !(((UNKNOWN_DEVICE_VENDOR_DEVICE_PATH *) TestPath)->LegacyDriveLetter == 0xFF)
  2736. ) {
  2737. ReturnDeviceHandle = BlockIoHandles[i];
  2738. // Bail-out.
  2739. i = nCachedDevicePaths;
  2740. break;
  2741. }
  2742. } else if (TestPath->Type == MESSAGING_DEVICE_PATH &&
  2743. TestPath->SubType == MSG_ATAPI_DP) {
  2744. //
  2745. // For ATAPI "floppy drive", we're really looking for a
  2746. // removable block IO device with a 512 byte block size, as
  2747. // this signature matches the ls120 style floppy drives and
  2748. // keeps us from accidentally finding cdrom drives.
  2749. //
  2750. // our search algorithm short-circuits when we find the
  2751. // first suitable device
  2752. //
  2753. EFI_DEVICE_PATH *TmpTestPath, *AtapiTestPath;
  2754. EFI_DEVICE_PATH_ALIGNED AtapiTestPathAligned;
  2755. EFI_BLOCK_IO * BlkIo;
  2756. BOOLEAN DefinitelyACDROM = FALSE;
  2757. Status = EfiBS->HandleProtocol(
  2758. BlockIoHandles[i],
  2759. &EfiBlockIoProtocol,
  2760. &(( EFI_BLOCK_IO * ) BlkIo) );
  2761. #if 0
  2762. if (EFI_ERROR(Status)) {
  2763. DBGOUT((L"getting BlkIo interface failed, ec=%x\r\n",Status));
  2764. } else {
  2765. DBGOUT((L"Block size = %x, removable media = %s\r\n",
  2766. BlkIo->Media->BlockSize,
  2767. BlkIo->Media->RemovableMedia ? L"TRUE" : L"FALSE" ));
  2768. }
  2769. #endif
  2770. TmpTestPath = (EFI_DEVICE_PATH *) CachedDevicePaths[i];
  2771. EfiAlignDp(
  2772. &AtapiTestPathAligned,
  2773. TmpTestPath,
  2774. DevicePathNodeLength( TmpTestPath )
  2775. );
  2776. AtapiTestPath = (EFI_DEVICE_PATH *) &TestPathAligned;
  2777. //
  2778. // test the device
  2779. // removable media? 512 byte block size?
  2780. //
  2781. if (!EFI_ERROR(Status) && (BlkIo->Media->RemovableMedia)
  2782. && BlkIo->Media->BlockSize == 512) {
  2783. //
  2784. // let's be doubly sure and make sure there
  2785. // isn't a cdrom device path attached to this
  2786. // device path
  2787. //
  2788. while (AtapiTestPath->Type != END_DEVICE_PATH_TYPE ) {
  2789. if (AtapiTestPath->Type == MEDIA_DEVICE_PATH &&
  2790. AtapiTestPath->SubType == MEDIA_CDROM_DP) {
  2791. DefinitelyACDROM = TRUE;
  2792. }
  2793. //
  2794. // Get next device path node.
  2795. //
  2796. TmpTestPath = NextDevicePathNode( TmpTestPath );
  2797. EfiAlignDp(
  2798. &AtapiTestPathAligned,
  2799. TmpTestPath,
  2800. DevicePathNodeLength( TmpTestPath )
  2801. );
  2802. AtapiTestPath = (EFI_DEVICE_PATH *) &AtapiTestPathAligned;
  2803. }
  2804. if (DefinitelyACDROM == FALSE) {
  2805. //
  2806. // found the first floppy drive.
  2807. // Remember the BlockIo Handle
  2808. //
  2809. ReturnDeviceHandle = BlockIoHandles[i];
  2810. break;
  2811. }
  2812. }
  2813. }
  2814. } else {
  2815. //
  2816. // Find the logical vendor device
  2817. //
  2818. if( ( TestPath->Type == MESSAGING_DEVICE_PATH ) &&
  2819. ( TestPath->SubType == MSG_VENDOR_DP ) ) {
  2820. if (IsVirtualFloppyDevice(BlockIoHandles[i])) {
  2821. DriveId--;
  2822. //
  2823. // Is this the device we were looking for?
  2824. //
  2825. if (!DriveId) {
  2826. ReturnDeviceHandle = BlockIoHandles[i];
  2827. i = nCachedDevicePaths; // for outer loop
  2828. break; // found the virtual floppy device we were looking for
  2829. }
  2830. }
  2831. }
  2832. }
  2833. //
  2834. // Get next device path node.
  2835. //
  2836. CurrentDevicePath = NextDevicePathNode( CurrentDevicePath );
  2837. EfiAlignDp(
  2838. &TestPathAligned,
  2839. CurrentDevicePath,
  2840. DevicePathNodeLength( CurrentDevicePath )
  2841. );
  2842. TestPath = (EFI_DEVICE_PATH *) &TestPathAligned;
  2843. }
  2844. }
  2845. //
  2846. // Change back to virtual mode.
  2847. //
  2848. FlipToVirtual();
  2849. BlFreeDescriptor( (ULONG)((ULONGLONG)BlockIoHandles >> PAGE_SHIFT) );
  2850. BlFreeDescriptor( (ULONG)((ULONGLONG)BlockIoHandlesBitmap >> PAGE_SHIFT) );
  2851. BlFreeDescriptor( (ULONG)((ULONGLONG)CachedDevicePaths >> PAGE_SHIFT) );
  2852. return ReturnDeviceHandle;
  2853. }
  2854. #ifdef FORCE_CD_BOOT
  2855. EFI_DEVICE_PATH *
  2856. DevicePathFromHandle (
  2857. IN EFI_HANDLE Handle
  2858. )
  2859. {
  2860. EFI_STATUS Status;
  2861. EFI_DEVICE_PATH *DevicePath;
  2862. EFI_GUID DevicePathProtocol;
  2863. Status = EfiBS->HandleProtocol (Handle, &DevicePathProtocol, (VOID*)&DevicePath);
  2864. if (EFI_ERROR(Status)) {
  2865. DevicePath = NULL;
  2866. }
  2867. return DevicePath;
  2868. }
  2869. ARC_STATUS
  2870. IsUDFSFileSystem(
  2871. IN EFI_HANDLE Handle
  2872. )
  2873. /*++
  2874. Routine Description:
  2875. Mounts the UDFS Volume on the device and updates the
  2876. file system state (global data structures)
  2877. Arguments:
  2878. Volume - UDF Volume pointer
  2879. DeviceId - Device on which the Volume may be residing
  2880. Return Value:
  2881. ESUCCESS if successful otherwise EBADF (if no UDF volume was found)
  2882. --*/
  2883. {
  2884. ARC_STATUS Status = EBADF;
  2885. UCHAR UBlock[UDF_BLOCK_SIZE+256] = {0};
  2886. PUCHAR Block = ALIGN_BUFFER(UBlock);
  2887. ULONG BlockIdx = 256;
  2888. ULONG LastBlock = 0;
  2889. EFI_STATUS EfiStatus;
  2890. EFI_BLOCK_IO *BlkDev;
  2891. EfiStatus = EfiBS->HandleProtocol(
  2892. Handle,
  2893. &EfiBlockIoProtocol,
  2894. &BlkDev);
  2895. if ((EfiStatus == EFI_SUCCESS) && (BlkDev) && (BlkDev->Media) &&
  2896. (BlkDev->Media->RemovableMedia == TRUE)) {
  2897. // get hold of Anchor Volume Descriptor
  2898. EfiStatus = BlkDev->ReadBlocks(
  2899. BlkDev,
  2900. BlkDev->Media->MediaId,
  2901. BlockIdx,
  2902. UDF_BLOCK_SIZE,
  2903. Block);
  2904. if (EfiStatus == EFI_SUCCESS) {
  2905. if (*(PUSHORT)Block == 0x2) {
  2906. // get partition descriptor
  2907. PNSR_PART Part;
  2908. PWCHAR TagID;
  2909. ULONG BlockIdx = *(PULONG)(Block + 20);
  2910. do {
  2911. EfiStatus = BlkDev->ReadBlocks(
  2912. BlkDev,
  2913. BlkDev->Media->MediaId,
  2914. BlockIdx++,
  2915. UDF_BLOCK_SIZE,
  2916. Block);
  2917. TagID = (PWCHAR)Block;
  2918. }
  2919. while ((EfiStatus == ESUCCESS) && (*TagID) &&
  2920. (*TagID != 0x8) && (*TagID != 0x5));
  2921. if ((EfiStatus == ESUCCESS) && (*TagID == 0x5)) {
  2922. Status = ESUCCESS;
  2923. }
  2924. }
  2925. }
  2926. }
  2927. return Status;
  2928. }
  2929. ARC_STATUS
  2930. IsCDFSFileSystem(
  2931. IN EFI_HANDLE Handle
  2932. )
  2933. /*++
  2934. Routine Description:
  2935. Mounts the CDFS Volume on the device and updates the
  2936. file system state (global data structures)
  2937. Arguments:
  2938. Return Value:
  2939. ESUCCESS if successful otherwise EBADF (if no CDFS volume was found)
  2940. --*/
  2941. {
  2942. EFI_DEVICE_PATH *Dp;
  2943. ARC_STATUS Status = EBADF;
  2944. Dp=DevicePathFromHandle(Handle);
  2945. if (Dp) {
  2946. while (!IsDevicePathEnd (Dp) && (Status == EBADF)) {
  2947. if ((Dp->Type == MEDIA_DEVICE_PATH) &&
  2948. (Dp->SubType == MEDIA_CDROM_DP) ) {
  2949. Status = ESUCCESS;
  2950. }
  2951. Dp=NextDevicePathNode(Dp);
  2952. }
  2953. }
  2954. return Status;
  2955. }
  2956. EFI_HANDLE
  2957. GetCdTest(
  2958. VOID
  2959. )
  2960. {
  2961. ULONG i;
  2962. ULONGLONG DevicePathSize, SmallestPathSize;
  2963. ULONG HandleCount;
  2964. EFI_HANDLE *BlockIoHandles;
  2965. EFI_HANDLE DeviceHandle = NULL;
  2966. EFI_DEVICE_PATH *DevicePath, *TestPath,*Dp;
  2967. EFI_DEVICE_PATH_ALIGNED TestPathAligned;
  2968. ATAPI_DEVICE_PATH *AtapiDevicePath;
  2969. SCSI_DEVICE_PATH *ScsiDevicePath;
  2970. UNKNOWN_DEVICE_VENDOR_DEVICE_PATH *UnknownDevicePath;
  2971. EFI_STATUS Status;
  2972. PBOOT_DEVICE_ATAPI BootDeviceAtapi;
  2973. PBOOT_DEVICE_SCSI BootDeviceScsi;
  2974. PBOOT_DEVICE_FLOPPY BootDeviceFloppy;
  2975. // PBOOT_DEVICE_TCPIPv4 BootDeviceTcpipV4;
  2976. // PBOOT_DEVICE_TCPIPv6 BootDeviceTcpipV6;
  2977. PBOOT_DEVICE_UNKNOWN BootDeviceUnknown;
  2978. EFI_HANDLE ReturnDeviceHandle = (EFI_HANDLE) 0;
  2979. ARC_STATUS ArcStatus;
  2980. //
  2981. // get all handles that support the block I/O protocol.
  2982. //
  2983. ArcStatus = BlGetEfiProtocolHandles(
  2984. &EfiBlockIoProtocol,
  2985. &BlockIoHandles,
  2986. &HandleCount);
  2987. if (ArcStatus != ESUCCESS) {
  2988. EfiST->ConOut->OutputString(EfiST->ConOut,
  2989. L"GetCdTest: BlGetEfiProtocolHandles failed\r\n");
  2990. return(ReturnDeviceHandle);
  2991. }
  2992. //
  2993. // change to physical mode so that we can make EFI calls
  2994. //
  2995. FlipToPhysical();
  2996. SmallestPathSize = 0;
  2997. for (i = 0,; i < HandleCount; i++) {
  2998. if (IsUDFSFileSystem(BlockIoHandles[i]) == ESUCCESS) {
  2999. ReturnDeviceHandle = BlockIoHandles[i];
  3000. break;
  3001. }
  3002. }
  3003. if (ReturnDeviceHandle == (EFI_HANDLE) 0) {
  3004. for (i = 0; i < HandleCount; i++) {
  3005. if (IsCDFSFileSystem (BlockIoHandles[i]) == ESUCCESS) {
  3006. ReturnDeviceHandle = BlockIoHandles[i];
  3007. break;
  3008. }
  3009. }
  3010. }
  3011. //
  3012. // Change back to virtual mode.
  3013. //
  3014. FlipToVirtual();
  3015. BlFreeDescriptor( (ULONG)((ULONGLONG)BlockIoHandles >> PAGE_SHIFT) );
  3016. return ReturnDeviceHandle;
  3017. }
  3018. #endif // for FORCE_CD_BOOT
  3019. //
  3020. // Turn off the timer so we don't reboot waiting for the user to press a key
  3021. //
  3022. void
  3023. DisableEFIWatchDog (
  3024. VOID
  3025. )
  3026. {
  3027. EfiBS->SetWatchdogTimer (0,0,0,NULL);
  3028. }
  3029. BOOLEAN
  3030. BlDiskGPTDiskReadCallback(
  3031. ULONGLONG StartingLBA,
  3032. ULONG BytesToRead,
  3033. PVOID pContext,
  3034. UNALIGNED PVOID OutputBuffer
  3035. )
  3036. /*++
  3037. Routine Description:
  3038. This routine is a callback for reading data for a routine that
  3039. validates the GPT partition table.
  3040. NOTE: This routine changes the seek position on disk, and you must seek
  3041. back to your original seek position if you plan on reading from the
  3042. disk after making this call.
  3043. Arguments:
  3044. StartingLBA - starting logical block address to read from.
  3045. BytesToRead - Indicates how many bytes are to be read.
  3046. pContext - context pointer for hte function (in this case, a pointer to the disk id.)
  3047. OutputBuffer - a buffer that receives the data. It's assumed that it is at least
  3048. BytesToRead big enough.
  3049. Return Value:
  3050. TRUE - success, data has been read
  3051. FALSE - failed, data has not been read.
  3052. --*/
  3053. {
  3054. ARC_STATUS Status;
  3055. LARGE_INTEGER SeekPosition;
  3056. PUSHORT DataPointer;
  3057. ULONG DiskId;
  3058. ULONG ReadCount = 0;
  3059. DiskId = *((PULONG)pContext);
  3060. //
  3061. // read from the appropriate LBA on the disk
  3062. //
  3063. SeekPosition.QuadPart = StartingLBA * SECTOR_SIZE;
  3064. Status = BlSeek(DiskId,
  3065. &SeekPosition,
  3066. SeekAbsolute );
  3067. if (Status != ESUCCESS) {
  3068. return FALSE;
  3069. }
  3070. DataPointer = OutputBuffer;
  3071. Status = BlRead(
  3072. DiskId,
  3073. DataPointer,
  3074. BytesToRead,
  3075. &ReadCount);
  3076. if ((Status == ESUCCESS) && (ReadCount == BytesToRead)) {
  3077. return(TRUE);
  3078. }
  3079. return(FALSE);
  3080. }
  3081. ARC_STATUS
  3082. BlGetGPTDiskPartitionEntry(
  3083. IN ULONG DiskNumber,
  3084. IN UCHAR PartitionNumber,
  3085. OUT EFI_PARTITION_ENTRY UNALIGNED **PartitionEntry
  3086. )
  3087. {
  3088. ARC_STATUS Status;
  3089. ULONG DiskId;
  3090. LARGE_INTEGER SeekPosition;
  3091. UCHAR DataBuffer[SECTOR_SIZE * 2];
  3092. ULONG ReadCount;
  3093. UCHAR NullGuid[16] = {0};
  3094. UNALIGNED EFI_PARTITION_TABLE *EfiHdr;
  3095. UNALIGNED EFI_PARTITION_ENTRY *PartEntry = NULL;
  3096. if (PartitionNumber >= 128) {
  3097. return EINVAL;
  3098. }
  3099. //
  3100. // Open the disk for raw access.
  3101. //
  3102. Status = BiosDiskOpen( DiskNumber,
  3103. 0,
  3104. &DiskId );
  3105. if (Status != ESUCCESS) {
  3106. DBGOUT((TEXT("BiosDiskOpen (%x) fails, %x\r\n"), DiskNumber, Status));
  3107. return EINVAL;
  3108. }
  3109. BlFileTable[DiskId].Flags.Read = 1;
  3110. //
  3111. // Read the second LBA on the disk.
  3112. //
  3113. SeekPosition.QuadPart = 1 * SECTOR_SIZE;
  3114. Status = BlSeek( DiskId, &SeekPosition, SeekAbsolute );
  3115. if (Status != ESUCCESS) {
  3116. DBGOUT((TEXT("BlSeek fails, %x\r\n"), Status));
  3117. goto done;
  3118. }
  3119. Status = BlRead( DiskId, DataBuffer, SECTOR_SIZE, &ReadCount );
  3120. if (Status != ESUCCESS) {
  3121. DBGOUT((TEXT("BlRead fails, %x\r\n"), Status));
  3122. goto done;
  3123. }
  3124. if (ReadCount != SECTOR_SIZE) {
  3125. Status = EIO;
  3126. DBGOUT((TEXT("BlRead (wrong amt)\r\n")));
  3127. goto done;
  3128. }
  3129. EfiHdr = (UNALIGNED EFI_PARTITION_TABLE *)DataBuffer;
  3130. //
  3131. // Verify EFI partition table.
  3132. //
  3133. if (!BlIsValidGUIDPartitionTable(
  3134. (UNALIGNED EFI_PARTITION_TABLE *)EfiHdr,
  3135. 1,
  3136. &DiskId,
  3137. BlDiskGPTDiskReadCallback)) {
  3138. DBGOUT((TEXT("BlIsValidGUIDPartitionTable fails, %x\r\n"), Status));
  3139. Status = EBADF;
  3140. goto done;
  3141. }
  3142. //
  3143. // Locate and read the partition entry that was requested.
  3144. //
  3145. SeekPosition.QuadPart = EfiHdr->PartitionEntryLBA * SECTOR_SIZE;
  3146. DBG_PRINT(STR_PREFIX"Seeking GPT Partition Entries\r\n");
  3147. Status = BlSeek( DiskId, &SeekPosition, SeekAbsolute );
  3148. if (Status != ESUCCESS) {
  3149. goto done;
  3150. }
  3151. Status = BlRead( DiskId, EfiPartitionBuffer, sizeof(EfiPartitionBuffer), &ReadCount );
  3152. if (Status != ESUCCESS) {
  3153. goto done;
  3154. }
  3155. if (ReadCount != sizeof(EfiPartitionBuffer)) {
  3156. Status = EIO;
  3157. goto done;
  3158. }
  3159. PartEntry = BlLocateGPTPartition( PartitionNumber - 1, 128, NULL );
  3160. if ( PartEntry != NULL ) {
  3161. if ( (memcmp(PartEntry->Type, NullGuid, 16) != 0) &&
  3162. (memcmp(PartEntry->Id, NullGuid, 16) != 0) &&
  3163. (PartEntry->StartingLBA != 0) &&
  3164. (PartEntry->EndingLBA != 0) ) {
  3165. Status = ESUCCESS;
  3166. goto done;
  3167. }
  3168. }
  3169. Status = EBADF;
  3170. done:
  3171. *PartitionEntry = PartEntry;
  3172. BiosDiskClose(DiskId);
  3173. if (Status != ESUCCESS) {
  3174. Status = ENOENT;
  3175. }
  3176. return Status;
  3177. }
  3178. ARC_STATUS
  3179. XferExtendedPhysicalDiskSectors(
  3180. IN ULONGLONG DeviceHandle,
  3181. IN ULONGLONG StartSector,
  3182. IN USHORT SectorCount,
  3183. PUCHAR Buffer,
  3184. IN BOOLEAN Write
  3185. )
  3186. /*++
  3187. Routine Description:
  3188. Read or write disk sectors via extended int13.
  3189. It is assumed that the caller has ensured that the transfer buffer is
  3190. under the 1MB line, that the sector run does not cross a 64K boundary,
  3191. etc.
  3192. This routine does not check whether extended int13 is actually available
  3193. for the drive.
  3194. Arguments:
  3195. Int13UnitNumber - supplies the int13 drive number for the drive
  3196. to be read from/written to.
  3197. StartSector - supplies the absolute physical sector number. This is 0-based
  3198. relative to all sectors on the drive.
  3199. SectorCount - supplies the number of sectors to read/write.
  3200. Buffer - receives data read from the disk or supplies data to be written.
  3201. Write - supplies a flag indicating whether this is a write operation.
  3202. If FALSE, then it's a read. Otherwise it's a write.
  3203. Return Value:
  3204. ARC status code indicating outcome.
  3205. --*/
  3206. {
  3207. ARC_STATUS s;
  3208. ULONG l,h;
  3209. UCHAR Operation;
  3210. if(!SectorCount) {
  3211. return(ESUCCESS);
  3212. }
  3213. l = (ULONG)StartSector;
  3214. h = (ULONG)(StartSector >> 32);
  3215. Operation = (UCHAR)(Write ? 0x43 : 0x42);
  3216. //
  3217. // We don't reset since this routine is only used on hard drives and
  3218. // CD-ROMs, and we don't totally understand the effect of a disk reset
  3219. // on ElTorito.
  3220. //
  3221. s = GET_EDDS_SECTOR(DeviceHandle,l,h,SectorCount,Buffer,Operation);
  3222. return(s);
  3223. }