iPXE
int13con.c
Go to the documentation of this file.
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
24FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25
26#include <stdint.h>
27#include <string.h>
28#include <errno.h>
29#include <ipxe/console.h>
30#include <ipxe/init.h>
31#include <realmode.h>
32#include <int13.h>
33#include <config/console.h>
34
35/** @file
36 *
37 * INT13 disk log console
38 *
39 */
40
41/* Set default console usage if applicable */
42#if ! ( defined ( CONSOLE_INT13 ) && CONSOLE_EXPLICIT ( CONSOLE_INT13 ) )
43#undef CONSOLE_INT13
44#define CONSOLE_INT13 ( CONSOLE_USAGE_ALL & ~CONSOLE_USAGE_LOG )
45#endif
46
47/** Disk drive number */
48#define INT13CON_DRIVE 0x80
49
50/** Log partition type */
51#define INT13CON_PARTITION_TYPE 0xe0
52
53/** Maximum number of outstanding unwritten characters */
54#define INT13CON_MAX_UNWRITTEN 64
55
56/** Log partition header */
58 /** Magic signature */
59 char magic[10];
60} __attribute__ (( packed ));
61
62/** Log partition magic signature */
63#define INT13CON_MAGIC "iPXE LOG\n\n"
64
65/** Original INT13 vector */
66static struct segoff __bss16 ( int13con_vector );
67#define int13con_vector __use_data16 ( int13con_vector )
68
69/** Sector buffer */
71#define int13con_buffer __use_data16 ( int13con_buffer )
72
73/** Disk address packet */
75#define int13con_address __use_data16 ( int13con_address )
76
77/** Current LBA */
79
80/** Maximum LBA */
82
83/** Current offset within sector */
84static size_t int13con_offset;
85
86/** Number of unwritten characters */
87static size_t int13con_unwritten;
88
90
91/**
92 * Read/write disk sector
93 *
94 * @v op Operation
95 * @v lba Logical block address
96 * @ret rc Return status code
97 */
98static int int13con_rw ( unsigned int op, uint64_t lba ) {
100
101 /* Construct disk address packet */
102 int13con_address.bufsize = sizeof ( int13con_address );
103 int13con_address.count = 1;
104 int13con_address.buffer.segment = rm_ds;
106 int13con_address.lba = lba;
107
108 /* Emulate INT13 via original vector. We do this since iPXE
109 * (or another subsequent bootloader) may hook INT13 and remap
110 * drive numbers.
111 */
112 __asm__ ( REAL_CODE ( "pushfw\n\t"
113 "cli\n\t"
114 "lcall *int13con_vector\n\t" )
115 : "=a" ( error )
116 : "0" ( op << 8 ), "d" ( INT13CON_DRIVE ),
117 "S" ( __from_data16 ( &int13con_address ) ) );
118 if ( error ) {
119 DBG ( "INT13CON operation %04x failed: %02x\n",
120 op, error );
121 return -EIO;
122 }
123
124 return 0;
125}
126
127/**
128 * Write character to console
129 *
130 * @v character Character
131 */
132static void int13con_putchar ( int character ) {
133 static int busy;
134 int rc;
135
136 /* Ignore if we are already mid-logging */
137 if ( busy )
138 return;
139 busy = 1;
140
141 /* Write character to buffer */
142 int13con_buffer[int13con_offset++] = character;
144
145 /* Write sector to disk, if applicable */
146 if ( ( int13con_offset == INT13_BLKSIZE ) ||
148 ( character == '\n' ) ) {
149
150 /* Write sector to disk */
152 int13con_lba ) ) != 0 ) {
153 DBG ( "INT13CON could not write log\n" );
154 /* Ignore and continue; there's nothing we can do */
155 }
156
157 /* Reset count of unwritten characters */
159 }
160
161 /* Move to next sector, if applicable */
163
164 /* Disable console if we have run out of space */
166 int13con.disabled = 1;
167
168 /* Clear log buffer */
169 memset ( int13con_buffer, 0, sizeof ( int13con_buffer ) );
170 int13con_offset = 0;
171
172 /* Move to next sector */
173 int13con_lba++;
174 }
175
176 /* Clear busy flag */
177 busy = 0;
178}
179
180/**
181 * Find log partition
182 *
183 * @ret rc Return status code
184 */
185static int int13con_find ( void ) {
186 struct master_boot_record *mbr =
187 ( ( struct master_boot_record * ) int13con_buffer );
188 struct int13con_header *hdr =
189 ( ( struct int13con_header * ) int13con_buffer );
190 struct partition_table_entry part[4];
191 unsigned int i;
192 int rc;
193
194 /* Read MBR */
195 if ( ( rc = int13con_rw ( INT13_EXTENDED_READ, 0 ) ) != 0 ) {
196 DBG ( "INT13CON could not read MBR: %s\n", strerror ( rc ) );
197 return rc;
198 }
199
200 /* Check MBR magic */
201 if ( mbr->magic != INT13_MBR_MAGIC ) {
202 DBG ( "INT13CON incorrect MBR magic\n" );
203 DBG2_HDA ( 0, mbr, sizeof ( *mbr ) );
204 return -EINVAL;
205 }
206
207 /* Look for magic partition */
208 memcpy ( part, mbr->partitions, sizeof ( part ) );
209 for ( i = 0 ; i < ( sizeof ( part ) / sizeof ( part[0] ) ) ; i++ ) {
210
211 /* Skip partitions of the wrong type */
212 if ( part[i].type != INT13CON_PARTITION_TYPE )
213 continue;
214
215 /* Read partition header */
217 part[i].start ) ) != 0 ) {
218 DBG ( "INT13CON partition %d could not read header: "
219 "%s\n", ( i + 1 ), strerror ( rc ) );
220 continue;
221 }
222
223 /* Check partition header */
224 if ( memcmp ( hdr->magic, INT13CON_MAGIC,
225 sizeof ( hdr->magic ) ) != 0 ) {
226 DBG ( "INT13CON partition %d bad magic\n", ( i + 1 ) );
227 DBG2_HDA ( 0, hdr, sizeof ( *hdr ) );
228 continue;
229 }
230
231 /* Found log partition */
232 DBG ( "INT13CON partition %d at [%08x,%08x)\n", ( i + 1 ),
233 part[i].start, ( part[i].start + part[i].length ) );
234 int13con_lba = part[i].start;
235 int13con_max_lba = ( part[i].start + part[i].length - 1 );
236
237 /* Initialise log buffer */
238 memset ( &int13con_buffer[ sizeof ( *hdr ) ], 0,
239 ( sizeof ( int13con_buffer ) - sizeof ( *hdr ) ) );
240 int13con_offset = sizeof ( hdr->magic );
241
242 return 0;
243 }
244
245 DBG ( "INT13CON found no log partition\n" );
246 return -ENOENT;
247}
248
249/**
250 * Initialise INT13 console
251 *
252 */
253static void int13con_init ( void ) {
255 uint16_t check;
256 unsigned int discard_c;
257 unsigned int discard_d;
258 int rc;
259
260 /* Check for INT13 extensions */
261 __asm__ __volatile__ ( REAL_CODE ( "int $0x13\n\t"
262 "setc %%al\n\t" )
263 : "=a" ( error ), "=b" ( check ),
264 "=c" ( discard_c ), "=d" ( discard_d )
265 : "0" ( INT13_EXTENSION_CHECK << 8 ),
266 "1" ( 0x55aa ), "3" ( INT13CON_DRIVE ) );
267 if ( error || ( check != 0xaa55 ) ) {
268 DBG ( "INT13CON missing extensions (%02x,%04x)\n",
269 error, check );
270 return;
271 }
272
273 /* Store original INT13 vector */
274 copy_from_real ( &int13con_vector, 0, ( 0x13 * 4 ),
275 sizeof ( int13con_vector ) );
276 DBG ( "INT13CON using original INT13 vector %04x:%04x\n",
277 int13con_vector.segment, int13con_vector.offset );
278
279 /* Locate log partition */
280 if ( ( rc = int13con_find() ) != 0)
281 return;
282
283 /* Enable console */
284 int13con.disabled = 0;
285}
286
287/**
288 * INT13 console initialisation function
289 */
290struct init_fn int13con_init_fn __init_fn ( INIT_CONSOLE ) = {
291 .name = "int13con",
292 .initialise = int13con_init,
293};
294
295/** INT13 console driver */
296struct console_driver int13con __console_driver = {
297 .putchar = int13con_putchar,
298 .disabled = CONSOLE_DISABLED,
299 .usage = CONSOLE_INT13,
300};
struct golan_inbox_hdr hdr
Message header.
Definition CIB_PRM.h:0
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
struct arbelprm_completion_with_error error
Definition arbel.h:1
__asm__ __volatile__("call *%9" :"=a"(result), "=c"(discard_ecx), "=d"(discard_edx) :"d"(0), "a"(code), "b"(0), "c"(in_phys), "D"(0), "S"(out_phys), "m"(hypercall))
unsigned short uint16_t
Definition stdint.h:11
unsigned long long uint64_t
Definition stdint.h:13
unsigned char uint8_t
Definition stdint.h:10
long discard_c
Definition bigint.h:33
#define CONSOLE_INT13
Definition console.h:36
Console configuration.
uint32_t type
Operating system type.
Definition ena.h:1
Error codes.
#define DBG(...)
Print a debugging message.
Definition compiler.h:498
#define DBG2_HDA(...)
Definition compiler.h:516
#define INIT_CONSOLE
Console initialisation.
Definition init.h:31
uint32_t start
Linear start address.
Definition int13.h:272
uint32_t start
Starting offset.
Definition netvsc.h:1
#define INT13_MBR_MAGIC
MBR magic signature.
Definition int13.h:292
uint32_t length
Linear length.
Definition int13.h:274
uint64_t lba
Starting block number.
Definition int13.h:11
uint16_t magic
0x55aa MBR signature
Definition int13.h:288
struct partition_table_entry partitions[4]
Partition table.
Definition int13.h:286
#define INT13_EXTENDED_WRITE
Extended write.
Definition int13.h:39
#define INT13_EXTENDED_READ
Extended read.
Definition int13.h:37
#define INT13_EXTENSION_CHECK
Extensions installation check.
Definition int13.h:35
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:896
#define ENOENT
No such file or directory.
Definition errno.h:515
#define EINVAL
Invalid argument.
Definition errno.h:429
#define EIO
Input/output error.
Definition errno.h:434
#define __attribute__(x)
Definition compiler.h:10
User interaction.
#define CONSOLE_DISABLED
Console is disabled for all uses.
Definition console.h:112
#define __console_driver
Mark a struct console_driver as being part of the console drivers table.
Definition console.h:134
String functions.
void * memcpy(void *dest, const void *src, size_t len) __nonnull
void * memset(void *dest, int character, size_t len) __nonnull
#define __init_fn(init_order)
Declare an initialisation functon.
Definition init.h:24
INT 13 emulation.
#define INT13_BLKSIZE
Block size for non-extended INT 13 calls.
Definition int13.h:72
static void int13con_putchar(int character)
Write character to console.
Definition int13con.c:132
#define INT13CON_MAGIC
Log partition magic signature.
Definition int13con.c:63
#define INT13CON_DRIVE
Disk drive number.
Definition int13con.c:48
static uint64_t int13con_max_lba
Maximum LBA.
Definition int13con.c:81
#define INT13CON_PARTITION_TYPE
Log partition type.
Definition int13con.c:51
static size_t int13con_offset
Current offset within sector.
Definition int13con.c:84
#define INT13CON_MAX_UNWRITTEN
Maximum number of outstanding unwritten characters.
Definition int13con.c:54
#define int13con_address
Definition int13con.c:75
static void int13con_init(void)
Initialise INT13 console.
Definition int13con.c:253
static int int13con_rw(unsigned int op, uint64_t lba)
Read/write disk sector.
Definition int13con.c:98
static int int13con_find(void)
Find log partition.
Definition int13con.c:185
static uint64_t int13con_lba
Current LBA.
Definition int13con.c:78
#define int13con_buffer
Definition int13con.c:71
static size_t int13con_unwritten
Number of unwritten characters.
Definition int13con.c:87
#define int13con_vector
Definition int13con.c:67
#define rm_ds
Definition libkir.h:39
#define REAL_CODE(asm_code_str)
Definition libkir.h:226
#define __bss16(variable)
Definition libkir.h:16
#define __from_data16(pointer)
Definition libkir.h:22
#define copy_from_real
Definition libkir.h:79
#define __bss16_array(variable, array)
Definition libkir.h:17
static uint16_t struct vmbus_xfer_pages_operations * op
Definition netvsc.h:327
__asm__(".section \".rodata\", \"a\", " PROGBITS "\n\t" "\nprivate_key_data:\n\t" ".size private_key_data, ( . - private_key_data )\n\t" ".equ private_key_len, ( . - private_key_data )\n\t" ".previous\n\t")
u16 length
Definition sky2.h:1
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79
int memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
Definition string.c:115
A console driver.
Definition console.h:56
An initialisation function.
Definition init.h:15
An INT 13 disk address packet.
Definition int13.h:88
Log partition header.
Definition int13con.c:57
char magic[10]
Magic signature.
Definition int13con.c:59
A Master Boot Record.
Definition int13.h:278
A partition table entry within the MBR.
Definition int13.h:262