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

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