Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

int13con.c 7.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. /*
  2. * Copyright (C) 2015 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 (at your option) 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., 51 Franklin Street, Fifth Floor, Boston, MA
  17. * 02110-1301, USA.
  18. *
  19. * You can also choose to distribute this program under the terms of
  20. * the Unmodified Binary Distribution Licence (as given in the file
  21. * COPYING.UBDL), provided that you have satisfied its requirements.
  22. */
  23. FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
  24. #include <stdint.h>
  25. #include <string.h>
  26. #include <errno.h>
  27. #include <ipxe/console.h>
  28. #include <ipxe/init.h>
  29. #include <realmode.h>
  30. #include <int13.h>
  31. #include <config/console.h>
  32. /** @file
  33. *
  34. * INT13 disk log console
  35. *
  36. */
  37. /* Set default console usage if applicable */
  38. #if ! ( defined ( CONSOLE_INT13 ) && CONSOLE_EXPLICIT ( CONSOLE_INT13 ) )
  39. #undef CONSOLE_INT13
  40. #define CONSOLE_INT13 ( CONSOLE_USAGE_ALL & ~CONSOLE_USAGE_LOG )
  41. #endif
  42. /** Disk drive number */
  43. #define INT13CON_DRIVE 0x80
  44. /** Log partition type */
  45. #define INT13CON_PARTITION_TYPE 0xe0
  46. /** Maximum number of outstanding unwritten characters */
  47. #define INT13CON_MAX_UNWRITTEN 64
  48. /** Log partition header */
  49. struct int13con_header {
  50. /** Magic signature */
  51. char magic[10];
  52. } __attribute__ (( packed ));
  53. /** Log partition magic signature */
  54. #define INT13CON_MAGIC "iPXE LOG\n\n"
  55. /** Sector buffer */
  56. static uint8_t __bss16_array ( int13con_buffer, [INT13_BLKSIZE] );
  57. #define int13con_buffer __use_data16 ( int13con_buffer )
  58. /** Disk address packet */
  59. static struct int13_disk_address __bss16 ( int13con_address );
  60. #define int13con_address __use_data16 ( int13con_address )
  61. /** Current LBA */
  62. static uint64_t int13con_lba;
  63. /** Maximum LBA */
  64. static uint64_t int13con_max_lba;
  65. /** Current offset within sector */
  66. static size_t int13con_offset;
  67. /** Number of unwritten characters */
  68. static size_t int13con_unwritten;
  69. struct console_driver int13con __console_driver;
  70. /**
  71. * Read/write disk sector
  72. *
  73. * @v op Operation
  74. * @v lba Logical block address
  75. * @ret rc Return status code
  76. */
  77. static int int13con_rw ( unsigned int op, uint64_t lba ) {
  78. uint8_t error;
  79. /* Construct disk address packet */
  80. int13con_address.bufsize = sizeof ( int13con_address );
  81. int13con_address.count = 1;
  82. int13con_address.buffer.segment = rm_ds;
  83. int13con_address.buffer.offset = __from_data16 ( int13con_buffer );
  84. int13con_address.lba = lba;
  85. /* Issue INT13 */
  86. __asm__ ( REAL_CODE ( "int $0x13\n\t" )
  87. : "=a" ( error )
  88. : "0" ( op << 8 ), "d" ( INT13CON_DRIVE ),
  89. "S" ( __from_data16 ( &int13con_address ) ) );
  90. if ( error ) {
  91. DBG ( "INT13CON operation %04x failed: %02x\n",
  92. op, error );
  93. return -EIO;
  94. }
  95. return 0;
  96. }
  97. /**
  98. * Write character to console
  99. *
  100. * @v character Character
  101. */
  102. static void int13con_putchar ( int character ) {
  103. static int busy;
  104. int rc;
  105. /* Ignore if we are already mid-logging */
  106. if ( busy )
  107. return;
  108. busy = 1;
  109. /* Write character to buffer */
  110. int13con_buffer[int13con_offset++] = character;
  111. int13con_unwritten++;
  112. /* Write sector to disk, if applicable */
  113. if ( ( int13con_offset == INT13_BLKSIZE ) ||
  114. ( int13con_unwritten == INT13CON_MAX_UNWRITTEN ) ||
  115. ( character == '\n' ) ) {
  116. /* Write sector to disk */
  117. if ( ( rc = int13con_rw ( INT13_EXTENDED_WRITE,
  118. int13con_lba ) ) != 0 ) {
  119. DBG ( "INT13CON could not write log\n" );
  120. /* Ignore and continue; there's nothing we can do */
  121. }
  122. /* Reset count of unwritten characters */
  123. int13con_unwritten = 0;
  124. }
  125. /* Move to next sector, if applicable */
  126. if ( int13con_offset == INT13_BLKSIZE ) {
  127. /* Disable console if we have run out of space */
  128. if ( int13con_lba >= int13con_max_lba )
  129. int13con.disabled = 1;
  130. /* Clear log buffer */
  131. memset ( int13con_buffer, 0, sizeof ( int13con_buffer ) );
  132. int13con_offset = 0;
  133. /* Move to next sector */
  134. int13con_lba++;
  135. }
  136. /* Clear busy flag */
  137. busy = 0;
  138. }
  139. /**
  140. * Find log partition
  141. *
  142. * @ret rc Return status code
  143. */
  144. static int int13con_find ( void ) {
  145. struct master_boot_record *mbr =
  146. ( ( struct master_boot_record * ) int13con_buffer );
  147. struct int13con_header *hdr =
  148. ( ( struct int13con_header * ) int13con_buffer );
  149. struct partition_table_entry part[4];
  150. unsigned int i;
  151. int rc;
  152. /* Read MBR */
  153. if ( ( rc = int13con_rw ( INT13_EXTENDED_READ, 0 ) ) != 0 ) {
  154. DBG ( "INT13CON could not read MBR: %s\n", strerror ( rc ) );
  155. return rc;
  156. }
  157. /* Check MBR magic */
  158. if ( mbr->magic != INT13_MBR_MAGIC ) {
  159. DBG ( "INT13CON incorrect MBR magic\n" );
  160. DBG2_HDA ( 0, mbr, sizeof ( *mbr ) );
  161. return -EINVAL;
  162. }
  163. /* Look for magic partition */
  164. memcpy ( part, mbr->partitions, sizeof ( part ) );
  165. for ( i = 0 ; i < ( sizeof ( part ) / sizeof ( part[0] ) ) ; i++ ) {
  166. /* Skip partitions of the wrong type */
  167. if ( part[i].type != INT13CON_PARTITION_TYPE )
  168. continue;
  169. /* Read partition header */
  170. if ( ( rc = int13con_rw ( INT13_EXTENDED_READ,
  171. part[i].start ) ) != 0 ) {
  172. DBG ( "INT13CON partition %d could not read header: "
  173. "%s\n", ( i + 1 ), strerror ( rc ) );
  174. continue;
  175. }
  176. /* Check partition header */
  177. if ( memcmp ( hdr->magic, INT13CON_MAGIC,
  178. sizeof ( hdr->magic ) ) != 0 ) {
  179. DBG ( "INT13CON partition %d bad magic\n", ( i + 1 ) );
  180. DBG2_HDA ( 0, hdr, sizeof ( *hdr ) );
  181. continue;
  182. }
  183. /* Found log partition */
  184. DBG ( "INT13CON partition %d at [%08x,%08x)\n", ( i + 1 ),
  185. part[i].start, ( part[i].start + part[i].length ) );
  186. int13con_lba = part[i].start;
  187. int13con_max_lba = ( part[i].start + part[i].length - 1 );
  188. /* Initialise log buffer */
  189. memset ( &int13con_buffer[ sizeof ( *hdr ) ], 0,
  190. ( sizeof ( int13con_buffer ) - sizeof ( *hdr ) ) );
  191. int13con_offset = sizeof ( hdr->magic );
  192. return 0;
  193. }
  194. DBG ( "INT13CON found no log partition\n" );
  195. return -ENOENT;
  196. }
  197. /**
  198. * Initialise INT13 console
  199. *
  200. */
  201. static void int13con_init ( void ) {
  202. uint8_t error;
  203. uint16_t check;
  204. unsigned int discard_c;
  205. unsigned int discard_d;
  206. int rc;
  207. /* Check for INT13 extensions */
  208. __asm__ __volatile__ ( REAL_CODE ( "int $0x13\n\t"
  209. "setc %%al\n\t" )
  210. : "=a" ( error ), "=b" ( check ),
  211. "=c" ( discard_c ), "=d" ( discard_d )
  212. : "0" ( INT13_EXTENSION_CHECK << 8 ),
  213. "1" ( 0x55aa ), "3" ( INT13CON_DRIVE ) );
  214. if ( error || ( check != 0xaa55 ) ) {
  215. DBG ( "INT13CON missing extensions (%02x,%04x)\n",
  216. error, check );
  217. return;
  218. }
  219. /* Locate log partition */
  220. if ( ( rc = int13con_find() ) != 0)
  221. return;
  222. /* Enable console */
  223. int13con.disabled = 0;
  224. }
  225. /**
  226. * INT13 console initialisation function
  227. */
  228. struct init_fn int13con_init_fn __init_fn ( INIT_CONSOLE ) = {
  229. .initialise = int13con_init,
  230. };
  231. /** INT13 console driver */
  232. struct console_driver int13con __console_driver = {
  233. .putchar = int13con_putchar,
  234. .disabled = CONSOLE_DISABLED,
  235. .usage = CONSOLE_INT13,
  236. };