iPXE
comboot.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2008 Daniel Verkamp <daniel@drv.nu>.
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., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA.
18 */
19
20/**
21 * @file
22 *
23 * SYSLINUX COMBOOT (16-bit) image format
24 *
25 */
26
27FILE_LICENCE ( GPL2_OR_LATER );
28
29#include <stdint.h>
30#include <stdlib.h>
31#include <string.h>
32#include <strings.h>
33#include <errno.h>
34#include <assert.h>
35#include <realmode.h>
36#include <basemem.h>
37#include <comboot.h>
38#include <ipxe/image.h>
39#include <ipxe/segment.h>
40#include <ipxe/init.h>
41#include <ipxe/features.h>
42#include <ipxe/console.h>
43
45
46/**
47 * COMBOOT PSP, copied to offset 0 of code segment
48 */
50 /** INT 20 instruction, executed if COMBOOT image returns with RET */
52 /** Segment of first non-free paragraph of memory */
54};
55
56/** Offset in PSP of command line */
57#define COMBOOT_PSP_CMDLINE_OFFSET 0x81
58
59/** Maximum length of command line in PSP
60 * (127 bytes minus space and CR) */
61#define COMBOOT_MAX_CMDLINE_LEN 125
62
63
64/**
65 * Copy command line to PSP
66 *
67 * @v image COMBOOT image
68 */
69static void comboot_copy_cmdline ( struct image * image, void *seg ) {
70 const char *cmdline = ( image->cmdline ? image->cmdline : "" );
71 int cmdline_len = strlen ( cmdline );
72 uint8_t *psp_cmdline;
73
74 /* Limit length of command line */
75 if( cmdline_len > COMBOOT_MAX_CMDLINE_LEN )
76 cmdline_len = COMBOOT_MAX_CMDLINE_LEN;
77
78 /* Copy length to byte before command line */
79 psp_cmdline = ( seg + COMBOOT_PSP_CMDLINE_OFFSET );
80 psp_cmdline[-1] = cmdline_len;
81
82 /* Command line starts with space */
83 psp_cmdline[0] = ' ';
84
85 /* Copy command line */
86 memcpy ( &psp_cmdline[1], cmdline, cmdline_len );
87
88 /* Command line ends with CR */
89 psp_cmdline[ 1 + cmdline_len ] = '\r';
90}
91
92/**
93 * Initialize PSP
94 *
95 * @v image COMBOOT image
96 * @v seg segment to initialize
97 */
98static void comboot_init_psp ( struct image * image, void *seg ) {
99 struct comboot_psp *psp;
100
101 /* Fill PSP */
102 psp = seg;
103
104 /* INT 20h instruction, byte order reversed */
105 psp->int20 = 0x20CD;
106
107 /* get_fbms() returns BIOS free base memory counter, which is in
108 * kilobytes; x * 1024 / 16 == x * 64 == x << 6 */
109 psp->first_non_free_para = get_fbms() << 6;
110
111 DBGC ( image, "COMBOOT %s: first non-free paragraph = 0x%x\n",
113
114 /* Copy the command line to the PSP */
116}
117
118/**
119 * Execute COMBOOT image
120 *
121 * @v image COMBOOT image
122 * @ret rc Return status code
123 */
124static int comboot_exec_loop ( struct image *image ) {
125 void *seg = real_to_virt ( COMBOOT_PSP_SEG, 0 );
126 int state;
127
129
130 switch ( state ) {
131 case 0: /* First time through; invoke COMBOOT program */
132
133 /* Initialize PSP */
135
136 /* Hook COMBOOT API interrupts */
138
139 DBGC ( image, "executing 16-bit COMBOOT image at %4x:0100\n",
141
142 /* Unregister image, so that a "boot" command doesn't
143 * throw us into an execution loop. We never
144 * reregister ourselves; COMBOOT images expect to be
145 * removed on exit.
146 */
148
149 /* Store stack segment at 0x38 and stack pointer at 0x3A
150 * in the PSP and jump to the image */
152 REAL_CODE ( /* Save return address with segment on old stack */
153 "popw %%ax\n\t"
154 "pushw %%cs\n\t"
155 "pushw %%ax\n\t"
156 /* Set DS=ES=segment with image */
157 "movw %w0, %%ds\n\t"
158 "movw %w0, %%es\n\t"
159 /* Set SS:SP to new stack (end of image segment) */
160 "movw %w0, %%ss\n\t"
161 "xor %%sp, %%sp\n\t"
162 "pushw $0\n\t"
163 "pushw %w0\n\t"
164 "pushw $0x100\n\t"
165 /* Zero registers (some COM files assume GP regs are 0) */
166 "xorw %%ax, %%ax\n\t"
167 "xorw %%bx, %%bx\n\t"
168 "xorw %%cx, %%cx\n\t"
169 "xorw %%dx, %%dx\n\t"
170 "xorw %%si, %%si\n\t"
171 "xorw %%di, %%di\n\t"
172 "xorw %%bp, %%bp\n\t"
173 "lret\n\t" )
174 : : "R" ( COMBOOT_PSP_SEG ) : "eax" );
175 DBGC ( image, "COMBOOT %s: returned\n", image->name );
176 break;
177
178 case COMBOOT_EXIT:
179 DBGC ( image, "COMBOOT %s: exited\n", image->name );
180 break;
181
184 DBGC ( image, "COMBOOT %s: exited to run kernel %s\n",
186 break;
187
189 DBGC ( image, "COMBOOT %s: exited after executing command\n",
190 image->name );
191 break;
192
193 default:
194 assert ( 0 );
195 break;
196 }
197
200
201 return 0;
202}
203
204/**
205 * Check image name extension
206 *
207 * @v image COMBOOT image
208 * @ret rc Return status code
209 */
210static int comboot_identify ( struct image *image ) {
211 const char *ext;
212
213 ext = strrchr( image->name, '.' );
214
215 if ( ! ext ) {
216 DBGC ( image, "COMBOOT %s: no extension\n",
217 image->name );
218 return -ENOEXEC;
219 }
220
221 ++ext;
222
223 if ( strcasecmp( ext, "cbt" ) ) {
224 DBGC ( image, "COMBOOT %s: unrecognized extension %s\n",
225 image->name, ext );
226 return -ENOEXEC;
227 }
228
229 return 0;
230}
231
232/**
233 * Load COMBOOT image into memory, preparing a segment and returning it
234 * @v image COMBOOT image
235 * @ret rc Return status code
236 */
237static int comboot_prepare_segment ( struct image *image )
238{
239 void *seg;
240 size_t filesz, memsz;
241 int rc;
242
243 /* Load image in segment */
245
246 /* Allow etra 0x100 bytes before image for PSP */
247 filesz = image->len + 0x100;
248
249 /* Ensure the entire 64k segment is free */
250 memsz = 0xFFFF;
251
252 /* Prepare, verify, and load the real-mode segment */
253 if ( ( rc = prep_segment ( seg, filesz, memsz ) ) != 0 ) {
254 DBGC ( image, "COMBOOT %s: could not prepare segment: %s\n",
255 image->name, strerror ( rc ) );
256 return rc;
257 }
258
259 /* Zero PSP */
260 memset ( seg, 0, 0x100 );
261
262 /* Copy image to segment:0100 */
263 memcpy ( ( seg + 0x100 ), image->data, image->len );
264
265 return 0;
266}
267
268/**
269 * Probe COMBOOT image
270 *
271 * @v image COMBOOT image
272 * @ret rc Return status code
273 */
274static int comboot_probe ( struct image *image ) {
275 int rc;
276
277 /* Check if this is a COMBOOT image */
278 if ( ( rc = comboot_identify ( image ) ) != 0 ) {
279
280 return rc;
281 }
282
283 return 0;
284}
285
286/**
287 * Execute COMBOOT image
288 *
289 * @v image COMBOOT image
290 * @ret rc Return status code
291 */
292static int comboot_exec ( struct image *image ) {
293 int rc;
294
295 /* Sanity check for filesize */
296 if( image->len >= 0xFF00 ) {
297 DBGC( image, "COMBOOT %s: image too large\n",
298 image->name );
299 return -ENOEXEC;
300 }
301
302 /* Prepare segment and load image */
303 if ( ( rc = comboot_prepare_segment ( image ) ) != 0 ) {
304 return rc;
305 }
306
307 /* Reset console */
309
310 return comboot_exec_loop ( image );
311}
312
313/** SYSLINUX COMBOOT (16-bit) image type */
314struct image_type comboot_image_type __image_type ( PROBE_NORMAL ) = {
315 .name = "COMBOOT",
316 .probe = comboot_probe,
317 .exec = comboot_exec,
318};
struct golan_mkey_seg seg
Definition CIB_PRM.h:0
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
__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 char uint8_t
Definition stdint.h:10
Assertions.
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:50
Base memory allocation.
static unsigned int get_fbms(void)
Read the BIOS free base memory counter.
Definition basemem.h:21
static int comboot_identify(struct image *image)
Check image name extension.
Definition comboot.c:210
static void comboot_copy_cmdline(struct image *image, void *seg)
Copy command line to PSP.
Definition comboot.c:69
static int comboot_exec_loop(struct image *image)
Execute COMBOOT image.
Definition comboot.c:124
static void comboot_init_psp(struct image *image, void *seg)
Initialize PSP.
Definition comboot.c:98
#define COMBOOT_MAX_CMDLINE_LEN
Maximum length of command line in PSP (127 bytes minus space and CR)
Definition comboot.c:61
#define COMBOOT_PSP_CMDLINE_OFFSET
Offset in PSP of command line.
Definition comboot.c:57
static int comboot_exec(struct image *image)
Execute COMBOOT image.
Definition comboot.c:292
static int comboot_probe(struct image *image)
Probe COMBOOT image.
Definition comboot.c:274
static int comboot_prepare_segment(struct image *image)
Load COMBOOT image into memory, preparing a segment and returning it.
Definition comboot.c:237
SYSLINUX COMBOOT.
#define COMBOOT_EXIT
Definition comboot.h:119
#define COMBOOT_PSP_SEG
Segment used for COMBOOT PSP and image.
Definition comboot.h:17
#define COMBOOT_EXIT_COMMAND
Definition comboot.h:121
#define COMBOOT_EXIT_RUN_KERNEL
Definition comboot.h:120
void unhook_comboot_interrupts()
Unhook BIOS interrupts related to COMBOOT API (INT 20h, 21h, 22h)
rmjmp_buf comboot_return
void hook_comboot_interrupts()
Hook BIOS interrupts related to COMBOOT API (INT 20h, 21h, 22h)
void comboot_force_text_mode(void)
Set default text mode.
uint16_t ext
Extended status.
Definition ena.h:9
Error codes.
uint8_t state
State.
Definition eth_slow.h:36
static size_t memsz
Definition fdtmem.c:51
#define DBGC(...)
Definition compiler.h:505
#define DHCP_EB_FEATURE_COMBOOT
COMBOOT format.
Definition features.h:52
#define FEATURE_IMAGE
Image formats.
Definition features.h:23
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:896
#define ENOEXEC
Exec format error.
Definition errno.h:520
void unregister_image(struct image *image)
Unregister executable image.
Definition image.c:358
Executable images.
#define PROBE_NORMAL
Normal image probe priority.
Definition image.h:156
#define __image_type(probe_order)
An executable image type.
Definition image.h:170
User interaction.
static void console_reset(void)
Reset console.
Definition console.h:215
String functions.
void * memcpy(void *dest, const void *src, size_t len) __nonnull
void * memset(void *dest, int character, size_t len) __nonnull
String functions.
Feature list.
#define FEATURE(category, text, feature_opt, version)
Declare a feature.
Definition features.h:101
#define REAL_CODE(asm_code_str)
Definition libkir.h:226
uint32_t cmdline
Definition multiboot.h:4
__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")
static __always_inline void * real_to_virt(unsigned int segment, unsigned int offset)
Convert segment:offset address to virtual address.
Definition realmode.h:77
#define rmsetjmp(_env)
Definition rmsetjmp.h:17
int prep_segment(void *segment, size_t filesz, size_t memsz)
Prepare segment for loading.
Definition segment.c:61
Executable image segments.
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79
int strcasecmp(const char *first, const char *second)
Compare case-insensitive strings.
Definition string.c:209
char * strrchr(const char *src, int character)
Find rightmost character within a string.
Definition string.c:290
size_t strlen(const char *src)
Get length of string.
Definition string.c:244
COMBOOT PSP, copied to offset 0 of code segment.
Definition comboot.c:49
uint16_t first_non_free_para
Segment of first non-free paragraph of memory.
Definition comboot.c:53
uint16_t int20
INT 20 instruction, executed if COMBOOT image returns with RET.
Definition comboot.c:51
An executable image type.
Definition image.h:95
An executable image.
Definition image.h:24
struct image * replacement
Replacement image.
Definition image.h:73
const void * data
Read-only data.
Definition image.h:51
char * name
Name.
Definition image.h:38
size_t len
Length of raw file image.
Definition image.h:56
char * cmdline
Command line to pass to image.
Definition image.h:43