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/disklog.h>
31#include <ipxe/init.h>
32#include <realmode.h>
33#include <int13.h>
34#include <config/console.h>
35
36/** @file
37 *
38 * INT13 disk log console
39 *
40 */
41
42/* Set default console usage if applicable
43 *
44 * We accept either CONSOLE_DISKLOG or CONSOLE_INT13.
45 */
46#if ( defined ( CONSOLE_DISKLOG ) && ! defined ( CONSOLE_INT13 ) )
47#define CONSOLE_INT13 CONSOLE_DISKLOG
48#endif
49#if ! ( defined ( CONSOLE_INT13 ) && CONSOLE_EXPLICIT ( CONSOLE_INT13 ) )
50#undef CONSOLE_INT13
51#define CONSOLE_INT13 ( CONSOLE_USAGE_ALL & ~CONSOLE_USAGE_LOG )
52#endif
53
54/** Disk drive number */
55#define INT13CON_DRIVE 0x80
56
57/** Original INT13 vector */
58static struct segoff __bss16 ( int13con_vector );
59#define int13con_vector __use_data16 ( int13con_vector )
60
61/** Sector buffer */
63#define int13con_buffer __use_data16 ( int13con_buffer )
64
65/** Disk address packet */
67#define int13con_address __use_data16 ( int13con_address )
68
69/** Disk log */
71
73
74/**
75 * Read/write disk sector
76 *
77 * @v op Operation
78 * @v lba Logical block address
79 * @ret rc Return status code
80 */
81static int int13con_rw ( unsigned int op, uint64_t lba ) {
83
84 /* Construct disk address packet */
85 int13con_address.bufsize = sizeof ( int13con_address );
86 int13con_address.count = 1;
87 int13con_address.buffer.segment = rm_ds;
90
91 /* Emulate INT13 via original vector. We do this since iPXE
92 * (or another subsequent bootloader) may hook INT13 and remap
93 * drive numbers.
94 */
95 __asm__ ( REAL_CODE ( "pushfw\n\t"
96 "cli\n\t"
97 "lcall *int13con_vector\n\t" )
98 : "=a" ( error )
99 : "0" ( op << 8 ), "d" ( INT13CON_DRIVE ),
100 "S" ( __from_data16 ( &int13con_address ) ) );
101 if ( error ) {
102 DBG ( "INT13CON operation %04x failed: %02x\n",
103 op, error );
104 return -EIO;
105 }
106
107 return 0;
108}
109
110/**
111 * Write current logical block
112 *
113 * @ret rc Return status code
114 */
115static int int13con_write ( void ) {
116
117 /* Write block */
119}
120
121/** INT13 disk log operations */
123 .write = int13con_write,
124};
125
126/**
127 * Write character to console
128 *
129 * @v character Character
130 */
131static void int13con_putchar ( int character ) {
132
133 /* Write character */
134 disklog_putchar ( &int13con_disklog, character );
135}
136
137/**
138 * Find log partition
139 *
140 * @ret rc Return status code
141 */
142static int int13con_find ( void ) {
143 struct master_boot_record *mbr =
144 ( ( struct master_boot_record * ) int13con_buffer );
145 struct partition_table_entry part[4];
146 unsigned int i;
147 int rc;
148
149 /* Read MBR */
150 if ( ( rc = int13con_rw ( INT13_EXTENDED_READ, 0 ) ) != 0 ) {
151 DBG ( "INT13CON could not read MBR: %s\n", strerror ( rc ) );
152 return rc;
153 }
154
155 /* Check MBR magic */
156 if ( mbr->magic != INT13_MBR_MAGIC ) {
157 DBG ( "INT13CON incorrect MBR magic\n" );
158 DBG2_HDA ( 0, mbr, sizeof ( *mbr ) );
159 return -EINVAL;
160 }
161
162 /* Look for magic partition */
163 memcpy ( part, mbr->partitions, sizeof ( part ) );
164 for ( i = 0 ; i < ( sizeof ( part ) / sizeof ( part[0] ) ) ; i++ ) {
165
166 /* Skip partitions of the wrong type */
167 if ( part[i].type != DISKLOG_PARTITION_TYPE )
168 continue;
169
170 /* Read partition header */
172 part[i].start ) ) != 0 ) {
173 DBG ( "INT13CON partition %d could not read header: "
174 "%s\n", ( i + 1 ), strerror ( rc ) );
175 continue;
176 }
177
178 /* Initialise disk log console */
181 ( part[i].start + part[i].length - 1 ) );
182
183 /* Open disk log console */
184 if ( ( rc = disklog_open ( &int13con_disklog ) ) != 0 ) {
185 DBG ( "INT13CON partition %d could not initialise: "
186 "%s\n", ( i + 1 ), strerror ( rc ) );
187 continue;
188 }
189
190 /* Found log partition */
191 DBG ( "INT13CON partition %d at [%08llx,%08llx)\n", ( i + 1 ),
192 ( ( unsigned long long ) int13con_disklog.lba ),
193 ( ( unsigned long long ) int13con_disklog.max_lba ) );
194
195 return 0;
196 }
197
198 DBG ( "INT13CON found no log partition\n" );
199 return -ENOENT;
200}
201
202/**
203 * Initialise INT13 console
204 *
205 */
206static void int13con_init ( void ) {
208 uint16_t check;
209 unsigned int discard_c;
210 unsigned int discard_d;
211 int rc;
212
213 /* Check for INT13 extensions */
214 __asm__ __volatile__ ( REAL_CODE ( "int $0x13\n\t"
215 "setc %%al\n\t" )
216 : "=a" ( error ), "=b" ( check ),
217 "=c" ( discard_c ), "=d" ( discard_d )
218 : "0" ( INT13_EXTENSION_CHECK << 8 ),
219 "1" ( 0x55aa ), "3" ( INT13CON_DRIVE ) );
220 if ( error || ( check != 0xaa55 ) ) {
221 DBG ( "INT13CON missing extensions (%02x,%04x)\n",
222 error, check );
223 return;
224 }
225
226 /* Store original INT13 vector */
227 copy_from_real ( &int13con_vector, 0, ( 0x13 * 4 ),
228 sizeof ( int13con_vector ) );
229 DBG ( "INT13CON using original INT13 vector %04x:%04x\n",
230 int13con_vector.segment, int13con_vector.offset );
231
232 /* Locate log partition */
233 if ( ( rc = int13con_find() ) != 0)
234 return;
235
236 /* Enable console */
237 int13con.disabled = 0;
238}
239
240/**
241 * INT13 console initialisation function
242 */
243struct init_fn int13con_init_fn __init_fn ( INIT_CONSOLE ) = {
244 .name = "int13con",
245 .initialise = int13con_init,
246};
247
248/** INT13 console driver */
249struct console_driver int13con __console_driver = {
250 .putchar = int13con_putchar,
251 .disabled = CONSOLE_DISABLED,
252 .usage = CONSOLE_INT13,
253};
254
255/* Request a log partition from genfsimg */
256__asm__ ( ".globl ipxe_oem_info_disklog\n\t"
257 ".equ ipxe_oem_info_disklog, 0x0001\n\t" );
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:32
Console configuration.
int disklog_open(struct disklog *disklog)
Open disk log console.
Definition disklog.c:46
void disklog_putchar(struct disklog *disklog, int character)
Write character to disk log console.
Definition disklog.c:85
Disk log console.
#define DISKLOG_PARTITION_TYPE
Disk log partition type.
Definition disklog.h:84
static void disklog_init(struct disklog *disklog, struct disklog_operations *op, struct console_driver *console, void *buffer, size_t blksize, uint64_t lba, uint64_t max_lba)
Initialise disk log console.
Definition disklog.h:66
uint32_t type
Operating system type.
Definition ena.h:1
Error codes.
#define DBG(...)
Print a debugging message.
Definition compiler.h:523
#define DBG2_HDA(...)
Definition compiler.h:541
#define INIT_CONSOLE
Console initialisation.
Definition init.h:31
uint32_t start
Starting offset.
Definition netvsc.h:1
#define INT13_MBR_MAGIC
MBR magic signature.
Definition int13.h:292
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:921
#define ENOENT
No such file or directory.
Definition errno.h:558
#define EINVAL
Invalid argument.
Definition errno.h:472
#define EIO
Input/output error.
Definition errno.h:477
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
#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:131
#define INT13CON_DRIVE
Disk drive number.
Definition int13con.c:55
__asm__(".globl ipxe_oem_info_disklog\n\t" ".equ ipxe_oem_info_disklog, 0x0001\n\t")
static struct disklog_operations int13con_op
INT13 disk log operations.
Definition int13con.c:122
#define int13con_address
Definition int13con.c:67
static void int13con_init(void)
Initialise INT13 console.
Definition int13con.c:206
static int int13con_rw(unsigned int op, uint64_t lba)
Read/write disk sector.
Definition int13con.c:81
#define CONSOLE_INT13
Definition int13con.c:51
static struct disklog int13con_disklog
Disk log.
Definition int13con.c:70
static int int13con_find(void)
Find log partition.
Definition int13con.c:142
#define int13con_buffer
Definition int13con.c:63
static int int13con_write(void)
Write current logical block.
Definition int13con.c:115
#define int13con_vector
Definition int13con.c:59
#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
A console driver.
Definition console.h:56
Disk log operations.
Definition disklog.h:45
A disk log.
Definition disklog.h:25
An initialisation function.
Definition init.h:15
An INT 13 disk address packet.
Definition int13.h:88
A Master Boot Record.
Definition int13.h:278
A partition table entry within the MBR.
Definition int13.h:262