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.

int13.c 38KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414
  1. /*
  2. * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
  3. *
  4. * This program is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License as
  6. * published by the Free Software Foundation; either version 2 of the
  7. * License, or any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful, but
  10. * WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. */
  18. FILE_LICENCE ( GPL2_OR_LATER );
  19. #include <stdint.h>
  20. #include <stdlib.h>
  21. #include <limits.h>
  22. #include <byteswap.h>
  23. #include <errno.h>
  24. #include <assert.h>
  25. #include <ipxe/list.h>
  26. #include <ipxe/blockdev.h>
  27. #include <ipxe/io.h>
  28. #include <ipxe/open.h>
  29. #include <ipxe/uri.h>
  30. #include <ipxe/process.h>
  31. #include <ipxe/xfer.h>
  32. #include <ipxe/retry.h>
  33. #include <ipxe/timer.h>
  34. #include <ipxe/acpi.h>
  35. #include <ipxe/sanboot.h>
  36. #include <ipxe/device.h>
  37. #include <ipxe/pci.h>
  38. #include <realmode.h>
  39. #include <bios.h>
  40. #include <biosint.h>
  41. #include <bootsector.h>
  42. #include <int13.h>
  43. /** @file
  44. *
  45. * INT 13 emulation
  46. *
  47. * This module provides a mechanism for exporting block devices via
  48. * the BIOS INT 13 disk interrupt interface.
  49. *
  50. */
  51. /**
  52. * Overall timeout for INT 13 commands (independent of underlying device
  53. *
  54. * Underlying devices should ideally never become totally stuck.
  55. * However, if they do, then the INT 13 mechanism provides no means
  56. * for the caller to cancel the operation, and the machine appears to
  57. * hang. Use an overall timeout for all commands to avoid this
  58. * problem and bounce timeout failures to the caller.
  59. */
  60. #define INT13_COMMAND_TIMEOUT ( 15 * TICKS_PER_SEC )
  61. /** An INT 13 emulated drive */
  62. struct int13_drive {
  63. /** Reference count */
  64. struct refcnt refcnt;
  65. /** List of all registered drives */
  66. struct list_head list;
  67. /** Block device URI */
  68. struct uri *uri;
  69. /** Underlying block device interface */
  70. struct interface block;
  71. /** BIOS in-use drive number (0x80-0xff) */
  72. unsigned int drive;
  73. /** BIOS natural drive number (0x80-0xff)
  74. *
  75. * This is the drive number that would have been assigned by
  76. * 'naturally' appending the drive to the end of the BIOS
  77. * drive list.
  78. *
  79. * If the emulated drive replaces a preexisting drive, this is
  80. * the drive number that the preexisting drive gets remapped
  81. * to.
  82. */
  83. unsigned int natural_drive;
  84. /** Block device capacity */
  85. struct block_device_capacity capacity;
  86. /** Number of cylinders
  87. *
  88. * The cylinder number field in an INT 13 call is ten bits
  89. * wide, giving a maximum of 1024 cylinders. Conventionally,
  90. * when the 7.8GB limit of a CHS address is exceeded, it is
  91. * the number of cylinders that is increased beyond the
  92. * addressable limit.
  93. */
  94. unsigned int cylinders;
  95. /** Number of heads
  96. *
  97. * The head number field in an INT 13 call is eight bits wide,
  98. * giving a maximum of 256 heads. However, apparently all
  99. * versions of MS-DOS up to and including Win95 fail with 256
  100. * heads, so the maximum encountered in practice is 255.
  101. */
  102. unsigned int heads;
  103. /** Number of sectors per track
  104. *
  105. * The sector number field in an INT 13 call is six bits wide,
  106. * giving a maximum of 63 sectors, since sector numbering
  107. * (unlike head and cylinder numbering) starts at 1, not 0.
  108. */
  109. unsigned int sectors_per_track;
  110. /** Underlying device status, if in error */
  111. int block_rc;
  112. /** Status of last operation */
  113. int last_status;
  114. };
  115. /** Vector for chaining to other INT 13 handlers */
  116. static struct segoff __text16 ( int13_vector );
  117. #define int13_vector __use_text16 ( int13_vector )
  118. /** Assembly wrapper */
  119. extern void int13_wrapper ( void );
  120. /** List of registered emulated drives */
  121. static LIST_HEAD ( int13s );
  122. /**
  123. * Number of BIOS drives
  124. *
  125. * Note that this is the number of drives in the system as a whole
  126. * (i.e. a mirror of the counter at 40:75), rather than a count of the
  127. * number of emulated drives.
  128. */
  129. static uint8_t num_drives;
  130. /** An INT 13 command */
  131. struct int13_command {
  132. /** Status */
  133. int rc;
  134. /** INT 13 drive */
  135. struct int13_drive *int13;
  136. /** Underlying block device interface */
  137. struct interface block;
  138. /** Command timeout timer */
  139. struct retry_timer timer;
  140. };
  141. /**
  142. * Record INT 13 drive capacity
  143. *
  144. * @v command INT 13 command
  145. * @v capacity Block device capacity
  146. */
  147. static void int13_command_capacity ( struct int13_command *command,
  148. struct block_device_capacity *capacity ) {
  149. memcpy ( &command->int13->capacity, capacity,
  150. sizeof ( command->int13->capacity ) );
  151. }
  152. /**
  153. * Close INT 13 command
  154. *
  155. * @v command INT 13 command
  156. * @v rc Reason for close
  157. */
  158. static void int13_command_close ( struct int13_command *command, int rc ) {
  159. intf_restart ( &command->block, rc );
  160. stop_timer ( &command->timer );
  161. command->rc = rc;
  162. }
  163. /**
  164. * Handle INT 13 command timer expiry
  165. *
  166. * @v timer Timer
  167. */
  168. static void int13_command_expired ( struct retry_timer *timer,
  169. int over __unused ) {
  170. struct int13_command *command =
  171. container_of ( timer, struct int13_command, timer );
  172. int13_command_close ( command, -ETIMEDOUT );
  173. }
  174. /** INT 13 command interface operations */
  175. static struct interface_operation int13_command_op[] = {
  176. INTF_OP ( intf_close, struct int13_command *, int13_command_close ),
  177. INTF_OP ( block_capacity, struct int13_command *,
  178. int13_command_capacity ),
  179. };
  180. /** INT 13 command interface descriptor */
  181. static struct interface_descriptor int13_command_desc =
  182. INTF_DESC ( struct int13_command, block, int13_command_op );
  183. /**
  184. * Prepare to issue INT 13 command
  185. *
  186. * @v command INT 13 command
  187. * @v int13 Emulated drive
  188. * @ret rc Return status code
  189. */
  190. static int int13_command_start ( struct int13_command *command,
  191. struct int13_drive *int13 ) {
  192. /* Sanity check */
  193. assert ( command->int13 == NULL );
  194. assert ( ! timer_running ( &command->timer ) );
  195. /* Initialise command */
  196. command->rc = -EINPROGRESS;
  197. command->int13 = int13;
  198. start_timer_fixed ( &command->timer, INT13_COMMAND_TIMEOUT );
  199. /* Wait for block control interface to become ready */
  200. while ( ( command->rc == -EINPROGRESS ) &&
  201. ( xfer_window ( &int13->block ) == 0 ) ) {
  202. step();
  203. }
  204. return ( ( command->rc == -EINPROGRESS ) ?
  205. int13->block_rc : command->rc );
  206. }
  207. /**
  208. * Wait for INT 13 command to complete
  209. *
  210. * @v command INT 13 command
  211. * @ret rc Return status code
  212. */
  213. static int int13_command_wait ( struct int13_command *command ) {
  214. /* Sanity check */
  215. assert ( timer_running ( &command->timer ) );
  216. /* Wait for command to complete */
  217. while ( command->rc == -EINPROGRESS )
  218. step();
  219. assert ( ! timer_running ( &command->timer ) );
  220. return command->rc;
  221. }
  222. /**
  223. * Terminate INT 13 command
  224. *
  225. * @v command INT 13 command
  226. */
  227. static void int13_command_stop ( struct int13_command *command ) {
  228. stop_timer ( &command->timer );
  229. command->int13 = NULL;
  230. }
  231. /** The single active INT 13 command */
  232. static struct int13_command int13_command = {
  233. .block = INTF_INIT ( int13_command_desc ),
  234. .timer = TIMER_INIT ( int13_command_expired ),
  235. };
  236. /**
  237. * Read from or write to INT 13 drive
  238. *
  239. * @v int13 Emulated drive
  240. * @v lba Starting logical block address
  241. * @v count Number of logical blocks
  242. * @v buffer Data buffer
  243. * @v block_rw Block read/write method
  244. * @ret rc Return status code
  245. */
  246. static int int13_rw ( struct int13_drive *int13, uint64_t lba,
  247. unsigned int count, userptr_t buffer,
  248. int ( * block_rw ) ( struct interface *control,
  249. struct interface *data,
  250. uint64_t lba, unsigned int count,
  251. userptr_t buffer, size_t len ) ) {
  252. struct int13_command *command = &int13_command;
  253. unsigned int frag_count;
  254. size_t frag_len;
  255. int rc;
  256. while ( count ) {
  257. /* Determine fragment length */
  258. frag_count = count;
  259. if ( frag_count > int13->capacity.max_count )
  260. frag_count = int13->capacity.max_count;
  261. frag_len = ( int13->capacity.blksize * frag_count );
  262. /* Issue command */
  263. if ( ( ( rc = int13_command_start ( command, int13 ) ) != 0 ) ||
  264. ( ( rc = block_rw ( &int13->block, &command->block, lba,
  265. frag_count, buffer,
  266. frag_len ) ) != 0 ) ||
  267. ( ( rc = int13_command_wait ( command ) ) != 0 ) ) {
  268. int13_command_stop ( command );
  269. return rc;
  270. }
  271. int13_command_stop ( command );
  272. /* Move to next fragment */
  273. lba += frag_count;
  274. count -= frag_count;
  275. buffer = userptr_add ( buffer, frag_len );
  276. }
  277. return 0;
  278. }
  279. /**
  280. * Read INT 13 drive capacity
  281. *
  282. * @v int13 Emulated drive
  283. * @ret rc Return status code
  284. */
  285. static int int13_read_capacity ( struct int13_drive *int13 ) {
  286. struct int13_command *command = &int13_command;
  287. int rc;
  288. /* Issue command */
  289. if ( ( ( rc = int13_command_start ( command, int13 ) ) != 0 ) ||
  290. ( ( rc = block_read_capacity ( &int13->block,
  291. &command->block ) ) != 0 ) ||
  292. ( ( rc = int13_command_wait ( command ) ) != 0 ) ) {
  293. int13_command_stop ( command );
  294. return rc;
  295. }
  296. int13_command_stop ( command );
  297. return 0;
  298. }
  299. /**
  300. * Guess INT 13 drive geometry
  301. *
  302. * @v int13 Emulated drive
  303. * @ret rc Return status code
  304. *
  305. * Guesses the drive geometry by inspecting the partition table.
  306. */
  307. static int int13_guess_geometry ( struct int13_drive *int13 ) {
  308. struct master_boot_record mbr;
  309. struct partition_table_entry *partition;
  310. unsigned int guessed_heads = 255;
  311. unsigned int guessed_sectors_per_track = 63;
  312. unsigned long blocks;
  313. unsigned long blocks_per_cyl;
  314. unsigned int i;
  315. int rc;
  316. /* Don't even try when the blksize is invalid for C/H/S access */
  317. if ( int13->capacity.blksize != INT13_BLKSIZE )
  318. return 0;
  319. /* Read partition table */
  320. if ( ( rc = int13_rw ( int13, 0, 1, virt_to_user ( &mbr ),
  321. block_read ) ) != 0 ) {
  322. DBGC ( int13, "INT13 drive %02x could not read partition "
  323. "table to guess geometry: %s\n",
  324. int13->drive, strerror ( rc ) );
  325. return rc;
  326. }
  327. DBGC2 ( int13, "INT13 drive %02x has MBR:\n", int13->drive );
  328. DBGC2_HDA ( int13, 0, &mbr, sizeof ( mbr ) );
  329. DBGC ( int13, "INT13 drive %02x has signature %08x\n",
  330. int13->drive, mbr.signature );
  331. /* Scan through partition table and modify guesses for heads
  332. * and sectors_per_track if we find any used partitions.
  333. */
  334. for ( i = 0 ; i < 4 ; i++ ) {
  335. partition = &mbr.partitions[i];
  336. if ( ! partition->type )
  337. continue;
  338. guessed_heads = ( PART_HEAD ( partition->chs_end ) + 1 );
  339. guessed_sectors_per_track = PART_SECTOR ( partition->chs_end );
  340. DBGC ( int13, "INT13 drive %02x guessing C/H/S xx/%d/%d based "
  341. "on partition %d\n", int13->drive, guessed_heads,
  342. guessed_sectors_per_track, ( i + 1 ) );
  343. }
  344. /* Apply guesses if no geometry already specified */
  345. if ( ! int13->heads )
  346. int13->heads = guessed_heads;
  347. if ( ! int13->sectors_per_track )
  348. int13->sectors_per_track = guessed_sectors_per_track;
  349. if ( ! int13->cylinders ) {
  350. /* Avoid attempting a 64-bit divide on a 32-bit system */
  351. blocks = ( ( int13->capacity.blocks <= ULONG_MAX ) ?
  352. int13->capacity.blocks : ULONG_MAX );
  353. blocks_per_cyl = ( int13->heads * int13->sectors_per_track );
  354. assert ( blocks_per_cyl != 0 );
  355. int13->cylinders = ( blocks / blocks_per_cyl );
  356. if ( int13->cylinders > 1024 )
  357. int13->cylinders = 1024;
  358. }
  359. return 0;
  360. }
  361. /**
  362. * Open (or reopen) INT 13 emulated drive underlying block device
  363. *
  364. * @v int13 Emulated drive
  365. * @ret rc Return status code
  366. */
  367. static int int13_reopen_block ( struct int13_drive *int13 ) {
  368. int rc;
  369. /* Close any existing block device */
  370. intf_restart ( &int13->block, -ECONNRESET );
  371. /* Open block device */
  372. if ( ( rc = xfer_open_uri ( &int13->block, int13->uri ) ) != 0 ) {
  373. DBGC ( int13, "INT13 drive %02x could not reopen block "
  374. "device: %s\n", int13->drive, strerror ( rc ) );
  375. int13->block_rc = rc;
  376. return rc;
  377. }
  378. /* Clear block device error status */
  379. int13->block_rc = 0;
  380. /* Read device capacity */
  381. if ( ( rc = int13_read_capacity ( int13 ) ) != 0 )
  382. return rc;
  383. return 0;
  384. }
  385. /**
  386. * Update BIOS drive count
  387. */
  388. static void int13_set_num_drives ( void ) {
  389. struct int13_drive *int13;
  390. /* Get current drive count */
  391. get_real ( num_drives, BDA_SEG, BDA_NUM_DRIVES );
  392. /* Ensure count is large enough to cover all of our emulated drives */
  393. list_for_each_entry ( int13, &int13s, list ) {
  394. if ( num_drives <= ( int13->drive & 0x7f ) )
  395. num_drives = ( ( int13->drive & 0x7f ) + 1 );
  396. }
  397. /* Update current drive count */
  398. put_real ( num_drives, BDA_SEG, BDA_NUM_DRIVES );
  399. }
  400. /**
  401. * Check number of drives
  402. */
  403. static void int13_check_num_drives ( void ) {
  404. uint8_t check_num_drives;
  405. get_real ( check_num_drives, BDA_SEG, BDA_NUM_DRIVES );
  406. if ( check_num_drives != num_drives ) {
  407. int13_set_num_drives();
  408. DBG ( "INT13 fixing up number of drives from %d to %d\n",
  409. check_num_drives, num_drives );
  410. }
  411. }
  412. /**
  413. * INT 13, 00 - Reset disk system
  414. *
  415. * @v int13 Emulated drive
  416. * @ret status Status code
  417. */
  418. static int int13_reset ( struct int13_drive *int13,
  419. struct i386_all_regs *ix86 __unused ) {
  420. int rc;
  421. DBGC2 ( int13, "Reset drive\n" );
  422. /* Reopen underlying block device */
  423. if ( ( rc = int13_reopen_block ( int13 ) ) != 0 )
  424. return -INT13_STATUS_RESET_FAILED;
  425. return 0;
  426. }
  427. /**
  428. * INT 13, 01 - Get status of last operation
  429. *
  430. * @v int13 Emulated drive
  431. * @ret status Status code
  432. */
  433. static int int13_get_last_status ( struct int13_drive *int13,
  434. struct i386_all_regs *ix86 __unused ) {
  435. DBGC2 ( int13, "Get status of last operation\n" );
  436. return int13->last_status;
  437. }
  438. /**
  439. * Read / write sectors
  440. *
  441. * @v int13 Emulated drive
  442. * @v al Number of sectors to read or write (must be nonzero)
  443. * @v ch Low bits of cylinder number
  444. * @v cl (bits 7:6) High bits of cylinder number
  445. * @v cl (bits 5:0) Sector number
  446. * @v dh Head number
  447. * @v es:bx Data buffer
  448. * @v block_rw Block read/write method
  449. * @ret status Status code
  450. * @ret al Number of sectors read or written
  451. */
  452. static int int13_rw_sectors ( struct int13_drive *int13,
  453. struct i386_all_regs *ix86,
  454. int ( * block_rw ) ( struct interface *control,
  455. struct interface *data,
  456. uint64_t lba,
  457. unsigned int count,
  458. userptr_t buffer,
  459. size_t len ) ) {
  460. unsigned int cylinder, head, sector;
  461. unsigned long lba;
  462. unsigned int count;
  463. userptr_t buffer;
  464. int rc;
  465. /* Validate blocksize */
  466. if ( int13->capacity.blksize != INT13_BLKSIZE ) {
  467. DBGC ( int13, "\nINT 13 drive %02x invalid blocksize (%zd) "
  468. "for non-extended read/write\n",
  469. int13->drive, int13->capacity.blksize );
  470. return -INT13_STATUS_INVALID;
  471. }
  472. /* Calculate parameters */
  473. cylinder = ( ( ( ix86->regs.cl & 0xc0 ) << 2 ) | ix86->regs.ch );
  474. assert ( cylinder < int13->cylinders );
  475. head = ix86->regs.dh;
  476. assert ( head < int13->heads );
  477. sector = ( ix86->regs.cl & 0x3f );
  478. assert ( ( sector >= 1 ) && ( sector <= int13->sectors_per_track ) );
  479. lba = ( ( ( ( cylinder * int13->heads ) + head )
  480. * int13->sectors_per_track ) + sector - 1 );
  481. count = ix86->regs.al;
  482. buffer = real_to_user ( ix86->segs.es, ix86->regs.bx );
  483. DBGC2 ( int13, "C/H/S %d/%d/%d = LBA %08lx <-> %04x:%04x (count %d)\n",
  484. cylinder, head, sector, lba, ix86->segs.es, ix86->regs.bx,
  485. count );
  486. /* Read from / write to block device */
  487. if ( ( rc = int13_rw ( int13, lba, count, buffer, block_rw ) ) != 0 ) {
  488. DBGC ( int13, "INT13 drive %02x I/O failed: %s\n",
  489. int13->drive, strerror ( rc ) );
  490. return -INT13_STATUS_READ_ERROR;
  491. }
  492. return 0;
  493. }
  494. /**
  495. * INT 13, 02 - Read sectors
  496. *
  497. * @v int13 Emulated drive
  498. * @v al Number of sectors to read (must be nonzero)
  499. * @v ch Low bits of cylinder number
  500. * @v cl (bits 7:6) High bits of cylinder number
  501. * @v cl (bits 5:0) Sector number
  502. * @v dh Head number
  503. * @v es:bx Data buffer
  504. * @ret status Status code
  505. * @ret al Number of sectors read
  506. */
  507. static int int13_read_sectors ( struct int13_drive *int13,
  508. struct i386_all_regs *ix86 ) {
  509. DBGC2 ( int13, "Read: " );
  510. return int13_rw_sectors ( int13, ix86, block_read );
  511. }
  512. /**
  513. * INT 13, 03 - Write sectors
  514. *
  515. * @v int13 Emulated drive
  516. * @v al Number of sectors to write (must be nonzero)
  517. * @v ch Low bits of cylinder number
  518. * @v cl (bits 7:6) High bits of cylinder number
  519. * @v cl (bits 5:0) Sector number
  520. * @v dh Head number
  521. * @v es:bx Data buffer
  522. * @ret status Status code
  523. * @ret al Number of sectors written
  524. */
  525. static int int13_write_sectors ( struct int13_drive *int13,
  526. struct i386_all_regs *ix86 ) {
  527. DBGC2 ( int13, "Write: " );
  528. return int13_rw_sectors ( int13, ix86, block_write );
  529. }
  530. /**
  531. * INT 13, 08 - Get drive parameters
  532. *
  533. * @v int13 Emulated drive
  534. * @ret status Status code
  535. * @ret ch Low bits of maximum cylinder number
  536. * @ret cl (bits 7:6) High bits of maximum cylinder number
  537. * @ret cl (bits 5:0) Maximum sector number
  538. * @ret dh Maximum head number
  539. * @ret dl Number of drives
  540. */
  541. static int int13_get_parameters ( struct int13_drive *int13,
  542. struct i386_all_regs *ix86 ) {
  543. unsigned int max_cylinder = int13->cylinders - 1;
  544. unsigned int max_head = int13->heads - 1;
  545. unsigned int max_sector = int13->sectors_per_track; /* sic */
  546. DBGC2 ( int13, "Get drive parameters\n" );
  547. ix86->regs.ch = ( max_cylinder & 0xff );
  548. ix86->regs.cl = ( ( ( max_cylinder >> 8 ) << 6 ) | max_sector );
  549. ix86->regs.dh = max_head;
  550. get_real ( ix86->regs.dl, BDA_SEG, BDA_NUM_DRIVES );
  551. return 0;
  552. }
  553. /**
  554. * INT 13, 15 - Get disk type
  555. *
  556. * @v int13 Emulated drive
  557. * @ret ah Type code
  558. * @ret cx:dx Sector count
  559. * @ret status Status code / disk type
  560. */
  561. static int int13_get_disk_type ( struct int13_drive *int13,
  562. struct i386_all_regs *ix86 ) {
  563. uint32_t blocks;
  564. DBGC2 ( int13, "Get disk type\n" );
  565. blocks = ( ( int13->capacity.blocks <= 0xffffffffUL ) ?
  566. int13->capacity.blocks : 0xffffffffUL );
  567. ix86->regs.cx = ( blocks >> 16 );
  568. ix86->regs.dx = ( blocks & 0xffff );
  569. return INT13_DISK_TYPE_HDD;
  570. }
  571. /**
  572. * INT 13, 41 - Extensions installation check
  573. *
  574. * @v int13 Emulated drive
  575. * @v bx 0x55aa
  576. * @ret bx 0xaa55
  577. * @ret cx Extensions API support bitmap
  578. * @ret status Status code / API version
  579. */
  580. static int int13_extension_check ( struct int13_drive *int13 __unused,
  581. struct i386_all_regs *ix86 ) {
  582. if ( ix86->regs.bx == 0x55aa ) {
  583. DBGC2 ( int13, "INT13 extensions installation check\n" );
  584. ix86->regs.bx = 0xaa55;
  585. ix86->regs.cx = ( INT13_EXTENSION_LINEAR |
  586. INT13_EXTENSION_EDD |
  587. INT13_EXTENSION_64BIT );
  588. return INT13_EXTENSION_VER_3_0;
  589. } else {
  590. return -INT13_STATUS_INVALID;
  591. }
  592. }
  593. /**
  594. * Extended read / write
  595. *
  596. * @v int13 Emulated drive
  597. * @v ds:si Disk address packet
  598. * @v block_rw Block read/write method
  599. * @ret status Status code
  600. */
  601. static int int13_extended_rw ( struct int13_drive *int13,
  602. struct i386_all_regs *ix86,
  603. int ( * block_rw ) ( struct interface *control,
  604. struct interface *data,
  605. uint64_t lba,
  606. unsigned int count,
  607. userptr_t buffer,
  608. size_t len ) ) {
  609. struct int13_disk_address addr;
  610. uint8_t bufsize;
  611. uint64_t lba;
  612. unsigned long count;
  613. userptr_t buffer;
  614. int rc;
  615. /* Get buffer size */
  616. get_real ( bufsize, ix86->segs.ds,
  617. ( ix86->regs.si + offsetof ( typeof ( addr ), bufsize ) ) );
  618. if ( bufsize < offsetof ( typeof ( addr ), buffer_phys ) ) {
  619. DBGC2 ( int13, "<invalid buffer size %#02x\n>\n", bufsize );
  620. return -INT13_STATUS_INVALID;
  621. }
  622. /* Read parameters from disk address structure */
  623. memset ( &addr, 0, sizeof ( addr ) );
  624. copy_from_real ( &addr, ix86->segs.ds, ix86->regs.si, bufsize );
  625. lba = addr.lba;
  626. DBGC2 ( int13, "LBA %08llx <-> ", ( ( unsigned long long ) lba ) );
  627. if ( ( addr.count == 0xff ) ||
  628. ( ( addr.buffer.segment == 0xffff ) &&
  629. ( addr.buffer.offset == 0xffff ) ) ) {
  630. buffer = phys_to_user ( addr.buffer_phys );
  631. DBGC2 ( int13, "%08llx",
  632. ( ( unsigned long long ) addr.buffer_phys ) );
  633. } else {
  634. buffer = real_to_user ( addr.buffer.segment,
  635. addr.buffer.offset );
  636. DBGC2 ( int13, "%04x:%04x", addr.buffer.segment,
  637. addr.buffer.offset );
  638. }
  639. if ( addr.count <= 0x7f ) {
  640. count = addr.count;
  641. } else if ( addr.count == 0xff ) {
  642. count = addr.long_count;
  643. } else {
  644. DBGC2 ( int13, " <invalid count %#02x>\n", addr.count );
  645. return -INT13_STATUS_INVALID;
  646. }
  647. DBGC2 ( int13, " (count %ld)\n", count );
  648. /* Read from / write to block device */
  649. if ( ( rc = int13_rw ( int13, lba, count, buffer, block_rw ) ) != 0 ) {
  650. DBGC ( int13, "INT13 drive %02x extended I/O failed: %s\n",
  651. int13->drive, strerror ( rc ) );
  652. /* Record that no blocks were transferred successfully */
  653. addr.count = 0;
  654. put_real ( addr.count, ix86->segs.ds,
  655. ( ix86->regs.si +
  656. offsetof ( typeof ( addr ), count ) ) );
  657. return -INT13_STATUS_READ_ERROR;
  658. }
  659. return 0;
  660. }
  661. /**
  662. * INT 13, 42 - Extended read
  663. *
  664. * @v int13 Emulated drive
  665. * @v ds:si Disk address packet
  666. * @ret status Status code
  667. */
  668. static int int13_extended_read ( struct int13_drive *int13,
  669. struct i386_all_regs *ix86 ) {
  670. DBGC2 ( int13, "Extended read: " );
  671. return int13_extended_rw ( int13, ix86, block_read );
  672. }
  673. /**
  674. * INT 13, 43 - Extended write
  675. *
  676. * @v int13 Emulated drive
  677. * @v ds:si Disk address packet
  678. * @ret status Status code
  679. */
  680. static int int13_extended_write ( struct int13_drive *int13,
  681. struct i386_all_regs *ix86 ) {
  682. DBGC2 ( int13, "Extended write: " );
  683. return int13_extended_rw ( int13, ix86, block_write );
  684. }
  685. /**
  686. * INT 13, 44 - Verify sectors
  687. *
  688. * @v int13 Emulated drive
  689. * @v ds:si Disk address packet
  690. * @ret status Status code
  691. */
  692. static int int13_extended_verify ( struct int13_drive *int13,
  693. struct i386_all_regs *ix86 ) {
  694. struct int13_disk_address addr;
  695. uint64_t lba;
  696. unsigned long count;
  697. /* Read parameters from disk address structure */
  698. if ( DBG_EXTRA ) {
  699. copy_from_real ( &addr, ix86->segs.ds, ix86->regs.si,
  700. sizeof ( addr ));
  701. lba = addr.lba;
  702. count = addr.count;
  703. DBGC2 ( int13, "Verify: LBA %08llx (count %ld)\n",
  704. ( ( unsigned long long ) lba ), count );
  705. }
  706. /* We have no mechanism for verifying sectors */
  707. return -INT13_STATUS_INVALID;
  708. }
  709. /**
  710. * INT 13, 44 - Extended seek
  711. *
  712. * @v int13 Emulated drive
  713. * @v ds:si Disk address packet
  714. * @ret status Status code
  715. */
  716. int int13_extended_seek ( struct int13_drive *int13,
  717. struct i386_all_regs *ix86 ) {
  718. struct int13_disk_address addr;
  719. uint64_t lba;
  720. unsigned long count;
  721. /* Read parameters from disk address structure */
  722. if ( DBG_EXTRA ) {
  723. copy_from_real ( &addr, ix86->segs.ds, ix86->regs.si,
  724. sizeof ( addr ));
  725. lba = addr.lba;
  726. count = addr.count;
  727. DBGC2 ( int13, "Seek: LBA %08llx (count %ld)\n",
  728. ( ( unsigned long long ) lba ), count );
  729. }
  730. /* Ignore and return success */
  731. return 0;
  732. }
  733. /**
  734. * Build device path information
  735. *
  736. * @v int13 Emulated drive
  737. * @v dpi Device path information
  738. * @ret rc Return status code
  739. */
  740. static int int13_device_path_info ( struct int13_drive *int13,
  741. struct edd_device_path_information *dpi ) {
  742. struct device *device;
  743. struct device_description *desc;
  744. unsigned int i;
  745. uint8_t sum = 0;
  746. int rc;
  747. /* Get underlying hardware device */
  748. device = identify_device ( &int13->block );
  749. if ( ! device ) {
  750. DBGC ( int13, "INT13 drive %02x cannot identify hardware "
  751. "device\n", int13->drive );
  752. return -ENODEV;
  753. }
  754. /* Fill in bus type and interface path */
  755. desc = &device->desc;
  756. switch ( desc->bus_type ) {
  757. case BUS_TYPE_PCI:
  758. dpi->host_bus_type.type = EDD_BUS_TYPE_PCI;
  759. dpi->interface_path.pci.bus = PCI_BUS ( desc->location );
  760. dpi->interface_path.pci.slot = PCI_SLOT ( desc->location );
  761. dpi->interface_path.pci.function = PCI_FUNC ( desc->location );
  762. dpi->interface_path.pci.channel = 0xff; /* unused */
  763. break;
  764. default:
  765. DBGC ( int13, "INT13 drive %02x unrecognised bus type %d\n",
  766. int13->drive, desc->bus_type );
  767. return -ENOTSUP;
  768. }
  769. /* Get EDD block device description */
  770. if ( ( rc = edd_describe ( &int13->block, &dpi->interface_type,
  771. &dpi->device_path ) ) != 0 ) {
  772. DBGC ( int13, "INT13 drive %02x cannot identify block device: "
  773. "%s\n", int13->drive, strerror ( rc ) );
  774. return rc;
  775. }
  776. /* Fill in common fields and fix checksum */
  777. dpi->key = EDD_DEVICE_PATH_INFO_KEY;
  778. dpi->len = sizeof ( *dpi );
  779. for ( i = 0 ; i < sizeof ( *dpi ) ; i++ )
  780. sum += *( ( ( uint8_t * ) dpi ) + i );
  781. dpi->checksum -= sum;
  782. return 0;
  783. }
  784. /**
  785. * INT 13, 48 - Get extended parameters
  786. *
  787. * @v int13 Emulated drive
  788. * @v ds:si Drive parameter table
  789. * @ret status Status code
  790. */
  791. static int int13_get_extended_parameters ( struct int13_drive *int13,
  792. struct i386_all_regs *ix86 ) {
  793. struct int13_disk_parameters params;
  794. struct segoff address;
  795. size_t len = sizeof ( params );
  796. uint16_t bufsize;
  797. int rc;
  798. /* Get buffer size */
  799. get_real ( bufsize, ix86->segs.ds,
  800. ( ix86->regs.si + offsetof ( typeof ( params ), bufsize )));
  801. DBGC2 ( int13, "Get extended drive parameters to %04x:%04x+%02x\n",
  802. ix86->segs.ds, ix86->regs.si, bufsize );
  803. /* Build drive parameters */
  804. memset ( &params, 0, sizeof ( params ) );
  805. params.flags = INT13_FL_DMA_TRANSPARENT;
  806. if ( ( int13->cylinders < 1024 ) &&
  807. ( int13->capacity.blocks <= INT13_MAX_CHS_SECTORS ) ) {
  808. params.flags |= INT13_FL_CHS_VALID;
  809. }
  810. params.cylinders = int13->cylinders;
  811. params.heads = int13->heads;
  812. params.sectors_per_track = int13->sectors_per_track;
  813. params.sectors = int13->capacity.blocks;
  814. params.sector_size = int13->capacity.blksize;
  815. memset ( &params.dpte, 0xff, sizeof ( params.dpte ) );
  816. if ( ( rc = int13_device_path_info ( int13, &params.dpi ) ) != 0 ) {
  817. DBGC ( int13, "INT13 drive %02x could not provide device "
  818. "path information: %s\n",
  819. int13->drive, strerror ( rc ) );
  820. len = offsetof ( typeof ( params ), dpi );
  821. }
  822. /* Calculate returned "buffer size" (which will be less than
  823. * the length actually copied if device path information is
  824. * present).
  825. */
  826. if ( bufsize < offsetof ( typeof ( params ), dpte ) )
  827. return -INT13_STATUS_INVALID;
  828. if ( bufsize < offsetof ( typeof ( params ), dpi ) ) {
  829. params.bufsize = offsetof ( typeof ( params ), dpte );
  830. } else {
  831. params.bufsize = offsetof ( typeof ( params ), dpi );
  832. }
  833. DBGC ( int13, "INT 13 drive %02x described using extended "
  834. "parameters:\n", int13->drive );
  835. address.segment = ix86->segs.ds;
  836. address.offset = ix86->regs.si;
  837. DBGC_HDA ( int13, address, &params, len );
  838. /* Return drive parameters */
  839. if ( len > bufsize )
  840. len = bufsize;
  841. copy_to_real ( ix86->segs.ds, ix86->regs.si, &params, len );
  842. return 0;
  843. }
  844. /**
  845. * INT 13 handler
  846. *
  847. */
  848. static __asmcall void int13 ( struct i386_all_regs *ix86 ) {
  849. int command = ix86->regs.ah;
  850. unsigned int bios_drive = ix86->regs.dl;
  851. struct int13_drive *int13;
  852. int status;
  853. /* Check BIOS hasn't killed off our drive */
  854. int13_check_num_drives();
  855. list_for_each_entry ( int13, &int13s, list ) {
  856. if ( bios_drive != int13->drive ) {
  857. /* Remap any accesses to this drive's natural number */
  858. if ( bios_drive == int13->natural_drive ) {
  859. DBGC2 ( int13, "INT13,%02x (%02x) remapped to "
  860. "(%02x)\n", ix86->regs.ah,
  861. bios_drive, int13->drive );
  862. ix86->regs.dl = int13->drive;
  863. return;
  864. }
  865. continue;
  866. }
  867. DBGC2 ( int13, "INT13,%02x (%02x): ",
  868. ix86->regs.ah, int13->drive );
  869. switch ( command ) {
  870. case INT13_RESET:
  871. status = int13_reset ( int13, ix86 );
  872. break;
  873. case INT13_GET_LAST_STATUS:
  874. status = int13_get_last_status ( int13, ix86 );
  875. break;
  876. case INT13_READ_SECTORS:
  877. status = int13_read_sectors ( int13, ix86 );
  878. break;
  879. case INT13_WRITE_SECTORS:
  880. status = int13_write_sectors ( int13, ix86 );
  881. break;
  882. case INT13_GET_PARAMETERS:
  883. status = int13_get_parameters ( int13, ix86 );
  884. break;
  885. case INT13_GET_DISK_TYPE:
  886. status = int13_get_disk_type ( int13, ix86 );
  887. break;
  888. case INT13_EXTENSION_CHECK:
  889. status = int13_extension_check ( int13, ix86 );
  890. break;
  891. case INT13_EXTENDED_READ:
  892. status = int13_extended_read ( int13, ix86 );
  893. break;
  894. case INT13_EXTENDED_WRITE:
  895. status = int13_extended_write ( int13, ix86 );
  896. break;
  897. case INT13_EXTENDED_VERIFY:
  898. status = int13_extended_verify ( int13, ix86 );
  899. break;
  900. case INT13_EXTENDED_SEEK:
  901. status = int13_extended_seek ( int13, ix86 );
  902. break;
  903. case INT13_GET_EXTENDED_PARAMETERS:
  904. status = int13_get_extended_parameters ( int13, ix86 );
  905. break;
  906. default:
  907. DBGC2 ( int13, "*** Unrecognised INT13 ***\n" );
  908. status = -INT13_STATUS_INVALID;
  909. break;
  910. }
  911. /* Store status for INT 13,01 */
  912. int13->last_status = status;
  913. /* Negative status indicates an error */
  914. if ( status < 0 ) {
  915. status = -status;
  916. DBGC ( int13, "INT13,%02x (%02x) failed with status "
  917. "%02x\n", ix86->regs.ah, int13->drive, status );
  918. } else {
  919. ix86->flags &= ~CF;
  920. }
  921. ix86->regs.ah = status;
  922. /* Set OF to indicate to wrapper not to chain this call */
  923. ix86->flags |= OF;
  924. return;
  925. }
  926. }
  927. /**
  928. * Hook INT 13 handler
  929. *
  930. */
  931. static void int13_hook_vector ( void ) {
  932. /* Assembly wrapper to call int13(). int13() sets OF if we
  933. * should not chain to the previous handler. (The wrapper
  934. * clears CF and OF before calling int13()).
  935. */
  936. __asm__ __volatile__ (
  937. TEXT16_CODE ( "\nint13_wrapper:\n\t"
  938. /* Preserve %ax and %dx for future reference */
  939. "pushw %%bp\n\t"
  940. "movw %%sp, %%bp\n\t"
  941. "pushw %%ax\n\t"
  942. "pushw %%dx\n\t"
  943. /* Clear OF, set CF, call int13() */
  944. "orb $0, %%al\n\t"
  945. "stc\n\t"
  946. "pushl %0\n\t"
  947. "pushw %%cs\n\t"
  948. "call prot_call\n\t"
  949. /* Chain if OF not set */
  950. "jo 1f\n\t"
  951. "pushfw\n\t"
  952. "lcall *%%cs:int13_vector\n\t"
  953. "\n1:\n\t"
  954. /* Overwrite flags for iret */
  955. "pushfw\n\t"
  956. "popw 6(%%bp)\n\t"
  957. /* Fix up %dl:
  958. *
  959. * INT 13,15 : do nothing
  960. * INT 13,08 : load with number of drives
  961. * all others: restore original value
  962. */
  963. "cmpb $0x15, -1(%%bp)\n\t"
  964. "je 2f\n\t"
  965. "movb -4(%%bp), %%dl\n\t"
  966. "cmpb $0x08, -1(%%bp)\n\t"
  967. "jne 2f\n\t"
  968. "pushw %%ds\n\t"
  969. "pushw %1\n\t"
  970. "popw %%ds\n\t"
  971. "movb %c2, %%dl\n\t"
  972. "popw %%ds\n\t"
  973. /* Return */
  974. "\n2:\n\t"
  975. "movw %%bp, %%sp\n\t"
  976. "popw %%bp\n\t"
  977. "iret\n\t" )
  978. : : "i" ( int13 ), "i" ( BDA_SEG ), "i" ( BDA_NUM_DRIVES ) );
  979. hook_bios_interrupt ( 0x13, ( unsigned int ) int13_wrapper,
  980. &int13_vector );
  981. }
  982. /**
  983. * Unhook INT 13 handler
  984. */
  985. static void int13_unhook_vector ( void ) {
  986. unhook_bios_interrupt ( 0x13, ( unsigned int ) int13_wrapper,
  987. &int13_vector );
  988. }
  989. /**
  990. * Handle INT 13 emulated drive underlying block device closing
  991. *
  992. * @v int13 Emulated drive
  993. * @v rc Reason for close
  994. */
  995. static void int13_block_close ( struct int13_drive *int13, int rc ) {
  996. /* Any closing is an error from our point of view */
  997. if ( rc == 0 )
  998. rc = -ENOTCONN;
  999. DBGC ( int13, "INT13 drive %02x went away: %s\n",
  1000. int13->drive, strerror ( rc ) );
  1001. /* Record block device error code */
  1002. int13->block_rc = rc;
  1003. /* Shut down interfaces */
  1004. intf_restart ( &int13->block, rc );
  1005. /* Further INT 13 calls will fail immediately. The caller may
  1006. * use INT 13,00 to reset the drive.
  1007. */
  1008. }
  1009. /** INT 13 drive interface operations */
  1010. static struct interface_operation int13_block_op[] = {
  1011. INTF_OP ( intf_close, struct int13_drive *, int13_block_close ),
  1012. };
  1013. /** INT 13 drive interface descriptor */
  1014. static struct interface_descriptor int13_block_desc =
  1015. INTF_DESC ( struct int13_drive, block, int13_block_op );
  1016. /**
  1017. * Free INT 13 emulated drive
  1018. *
  1019. * @v refcnt Reference count
  1020. */
  1021. static void int13_free ( struct refcnt *refcnt ) {
  1022. struct int13_drive *int13 =
  1023. container_of ( refcnt, struct int13_drive, refcnt );
  1024. uri_put ( int13->uri );
  1025. free ( int13 );
  1026. }
  1027. /**
  1028. * Hook INT 13 emulated drive
  1029. *
  1030. * @v uri URI
  1031. * @v drive Requested drive number
  1032. * @ret drive Assigned drive number, or negative error
  1033. *
  1034. * Registers the drive with the INT 13 emulation subsystem, and hooks
  1035. * the INT 13 interrupt vector (if not already hooked).
  1036. */
  1037. static int int13_hook ( struct uri *uri, unsigned int drive ) {
  1038. struct int13_drive *int13;
  1039. uint8_t num_drives;
  1040. unsigned int natural_drive;
  1041. int rc;
  1042. /* Calculate drive number */
  1043. get_real ( num_drives, BDA_SEG, BDA_NUM_DRIVES );
  1044. natural_drive = ( num_drives | 0x80 );
  1045. if ( drive == INT13_USE_NATURAL_DRIVE )
  1046. drive = natural_drive;
  1047. drive |= 0x80;
  1048. /* Check that drive number is not in use */
  1049. list_for_each_entry ( int13, &int13s, list ) {
  1050. if ( int13->drive == drive ) {
  1051. rc = -EADDRINUSE;
  1052. goto err_in_use;
  1053. }
  1054. }
  1055. /* Allocate and initialise structure */
  1056. int13 = zalloc ( sizeof ( *int13 ) );
  1057. if ( ! int13 ) {
  1058. rc = -ENOMEM;
  1059. goto err_zalloc;
  1060. }
  1061. ref_init ( &int13->refcnt, int13_free );
  1062. intf_init ( &int13->block, &int13_block_desc, &int13->refcnt );
  1063. int13->uri = uri_get ( uri );
  1064. int13->drive = drive;
  1065. int13->natural_drive = natural_drive;
  1066. /* Open block device interface */
  1067. if ( ( rc = int13_reopen_block ( int13 ) ) != 0 )
  1068. goto err_reopen_block;
  1069. /* Give drive a default geometry */
  1070. if ( ( rc = int13_guess_geometry ( int13 ) ) != 0 )
  1071. goto err_guess_geometry;
  1072. DBGC ( int13, "INT13 drive %02x (naturally %02x) registered with C/H/S "
  1073. "geometry %d/%d/%d\n", int13->drive, int13->natural_drive,
  1074. int13->cylinders, int13->heads, int13->sectors_per_track );
  1075. /* Hook INT 13 vector if not already hooked */
  1076. if ( list_empty ( &int13s ) )
  1077. int13_hook_vector();
  1078. /* Add to list of emulated drives */
  1079. list_add ( &int13->list, &int13s );
  1080. /* Update BIOS drive count */
  1081. int13_set_num_drives();
  1082. return int13->drive;
  1083. err_guess_geometry:
  1084. err_reopen_block:
  1085. intf_shutdown ( &int13->block, rc );
  1086. ref_put ( &int13->refcnt );
  1087. err_zalloc:
  1088. err_in_use:
  1089. return rc;
  1090. }
  1091. /**
  1092. * Find INT 13 emulated drive by drive number
  1093. *
  1094. * @v drive Drive number
  1095. * @ret int13 Emulated drive, or NULL
  1096. */
  1097. static struct int13_drive * int13_find ( unsigned int drive ) {
  1098. struct int13_drive *int13;
  1099. list_for_each_entry ( int13, &int13s, list ) {
  1100. if ( int13->drive == drive )
  1101. return int13;
  1102. }
  1103. return NULL;
  1104. }
  1105. /**
  1106. * Unhook INT 13 emulated drive
  1107. *
  1108. * @v drive Drive number
  1109. *
  1110. * Unregisters the drive from the INT 13 emulation subsystem. If this
  1111. * is the last emulated drive, the INT 13 vector is unhooked (if
  1112. * possible).
  1113. */
  1114. static void int13_unhook ( unsigned int drive ) {
  1115. struct int13_drive *int13;
  1116. /* Find drive */
  1117. int13 = int13_find ( drive );
  1118. if ( ! int13 ) {
  1119. DBG ( "INT13 cannot find emulated drive %02x\n", drive );
  1120. return;
  1121. }
  1122. /* Shut down interfaces */
  1123. intf_shutdown ( &int13->block, 0 );
  1124. /* Remove from list of emulated drives */
  1125. list_del ( &int13->list );
  1126. /* Should adjust BIOS drive count, but it's difficult
  1127. * to do so reliably.
  1128. */
  1129. DBGC ( int13, "INT13 drive %02x unregistered\n", int13->drive );
  1130. /* Unhook INT 13 vector if no more drives */
  1131. if ( list_empty ( &int13s ) )
  1132. int13_unhook_vector();
  1133. /* Drop list's reference to drive */
  1134. ref_put ( &int13->refcnt );
  1135. }
  1136. /**
  1137. * Attempt to boot from an INT 13 drive
  1138. *
  1139. * @v drive Drive number
  1140. * @ret rc Return status code
  1141. *
  1142. * This boots from the specified INT 13 drive by loading the Master
  1143. * Boot Record to 0000:7c00 and jumping to it. INT 18 is hooked to
  1144. * capture an attempt by the MBR to boot the next device. (This is
  1145. * the closest thing to a return path from an MBR).
  1146. *
  1147. * Note that this function can never return success, by definition.
  1148. */
  1149. static int int13_boot ( unsigned int drive ) {
  1150. struct memory_map memmap;
  1151. int status, signature;
  1152. int discard_c, discard_d;
  1153. int rc;
  1154. DBG ( "INT13 drive %02x booting\n", drive );
  1155. /* Use INT 13 to read the boot sector */
  1156. __asm__ __volatile__ ( REAL_CODE ( "pushw %%es\n\t"
  1157. "pushw $0\n\t"
  1158. "popw %%es\n\t"
  1159. "stc\n\t"
  1160. "sti\n\t"
  1161. "int $0x13\n\t"
  1162. "sti\n\t" /* BIOS bugs */
  1163. "jc 1f\n\t"
  1164. "xorl %%eax, %%eax\n\t"
  1165. "\n1:\n\t"
  1166. "movzwl %%es:0x7dfe, %%ebx\n\t"
  1167. "popw %%es\n\t" )
  1168. : "=a" ( status ), "=b" ( signature ),
  1169. "=c" ( discard_c ), "=d" ( discard_d )
  1170. : "a" ( 0x0201 ), "b" ( 0x7c00 ),
  1171. "c" ( 1 ), "d" ( drive ) );
  1172. if ( status )
  1173. return -EIO;
  1174. /* Check signature is correct */
  1175. if ( signature != be16_to_cpu ( 0x55aa ) ) {
  1176. DBG ( "INT13 drive %02x invalid disk signature %#04x (should "
  1177. "be 0x55aa)\n", drive, cpu_to_be16 ( signature ) );
  1178. return -ENOEXEC;
  1179. }
  1180. /* Dump out memory map prior to boot, if memmap debugging is
  1181. * enabled. Not required for program flow, but we have so
  1182. * many problems that turn out to be memory-map related that
  1183. * it's worth doing.
  1184. */
  1185. get_memmap ( &memmap );
  1186. /* Jump to boot sector */
  1187. if ( ( rc = call_bootsector ( 0x0, 0x7c00, drive ) ) != 0 ) {
  1188. DBG ( "INT13 drive %02x boot returned: %s\n",
  1189. drive, strerror ( rc ) );
  1190. return rc;
  1191. }
  1192. return -ECANCELED; /* -EIMPOSSIBLE */
  1193. }
  1194. /** A boot firmware table generated by iPXE */
  1195. union xbft_table {
  1196. /** ACPI header */
  1197. struct acpi_description_header acpi;
  1198. /** Padding */
  1199. char pad[768];
  1200. };
  1201. /** The boot firmware table generated by iPXE */
  1202. static union xbft_table __bss16 ( xbftab ) __attribute__ (( aligned ( 16 ) ));
  1203. #define xbftab __use_data16 ( xbftab )
  1204. /**
  1205. * Describe INT 13 emulated drive for SAN-booted operating system
  1206. *
  1207. * @v drive Drive number
  1208. * @ret rc Return status code
  1209. */
  1210. static int int13_describe ( unsigned int drive ) {
  1211. struct int13_drive *int13;
  1212. struct segoff xbft_address;
  1213. int rc;
  1214. /* Find drive */
  1215. int13 = int13_find ( drive );
  1216. if ( ! int13 ) {
  1217. DBG ( "INT13 cannot find emulated drive %02x\n", drive );
  1218. return -ENODEV;
  1219. }
  1220. /* Clear table */
  1221. memset ( &xbftab, 0, sizeof ( xbftab ) );
  1222. /* Fill in common parameters */
  1223. strncpy ( xbftab.acpi.oem_id, "FENSYS",
  1224. sizeof ( xbftab.acpi.oem_id ) );
  1225. strncpy ( xbftab.acpi.oem_table_id, "iPXE",
  1226. sizeof ( xbftab.acpi.oem_table_id ) );
  1227. /* Fill in remaining parameters */
  1228. if ( ( rc = acpi_describe ( &int13->block, &xbftab.acpi,
  1229. sizeof ( xbftab ) ) ) != 0 ) {
  1230. DBGC ( int13, "INT13 drive %02x could not create ACPI "
  1231. "description: %s\n", int13->drive, strerror ( rc ) );
  1232. return rc;
  1233. }
  1234. /* Fix up ACPI checksum */
  1235. acpi_fix_checksum ( &xbftab.acpi );
  1236. xbft_address.segment = rm_ds;
  1237. xbft_address.offset = __from_data16 ( &xbftab );
  1238. DBGC ( int13, "INT13 drive %02x described using boot firmware "
  1239. "table:\n", int13->drive );
  1240. DBGC_HDA ( int13, xbft_address, &xbftab,
  1241. le32_to_cpu ( xbftab.acpi.length ) );
  1242. return 0;
  1243. }
  1244. PROVIDE_SANBOOT ( pcbios, san_hook, int13_hook );
  1245. PROVIDE_SANBOOT ( pcbios, san_unhook, int13_unhook );
  1246. PROVIDE_SANBOOT ( pcbios, san_boot, int13_boot );
  1247. PROVIDE_SANBOOT ( pcbios, san_describe, int13_describe );