iPXE
com32.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 COM32 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/uaccess.h>
39#include <ipxe/image.h>
40#include <ipxe/segment.h>
41#include <ipxe/init.h>
42#include <ipxe/memmap.h>
43#include <ipxe/console.h>
44
45/**
46 * Execute COMBOOT image
47 *
48 * @v image COM32 image
49 * @ret rc Return status code
50 */
51static int com32_exec_loop ( struct image *image ) {
52 struct memmap_region region;
53 int state;
54 uint32_t avail_mem_top;
55
57
58 switch ( state ) {
59 case 0: /* First time through; invoke COM32 program */
60
61 /* Find end of block covering COM32 image loading area */
62 memmap_describe ( COM32_START_PHYS, 1, &region );
63 assert ( memmap_is_usable ( &region ) );
64 avail_mem_top = ( COM32_START_PHYS + memmap_size ( &region ) );
65 DBGC ( image, "COM32 %s: available memory top = 0x%x\n",
66 image->name, avail_mem_top );
67 assert ( avail_mem_top != 0 );
68
69 /* Hook COMBOOT API interrupts */
71
72 /* Unregister image, so that a "boot" command doesn't
73 * throw us into an execution loop. We never
74 * reregister ourselves; COMBOOT images expect to be
75 * removed on exit.
76 */
78
80 /* Preserve registers */
81 "pushal\n\t"
82 /* Preserve stack pointer */
83 "subl $4, %k0\n\t"
84 "movl %%esp, (%k0)\n\t"
85 /* Switch to COM32 stack */
86 "movl %k0, %%esp\n\t"
87 /* Enable interrupts */
88 "sti\n\t"
89 /* Construct stack frame */
90 "pushl %k1\n\t"
91 "pushl %k2\n\t"
92 "pushl %k3\n\t"
93 "pushl %k4\n\t"
94 "pushl %k5\n\t"
95 "pushl %k6\n\t"
96 "pushl $6\n\t"
97 /* Call COM32 entry point */
98 "movl %k7, %k0\n\t"
99 "call *%k0\n\t"
100 /* Disable interrupts */
101 "cli\n\t"
102 /* Restore stack pointer */
103 "movl 28(%%esp), %%esp\n\t"
104 /* Restore registers */
105 "popal\n\t" )
106 :
107 : "R" ( avail_mem_top ),
108 "R" ( virt_to_phys ( com32_cfarcall_wrapper ) ),
109 "R" ( virt_to_phys ( com32_farcall_wrapper ) ),
110 "R" ( get_fbms() * 1024 - ( COM32_BOUNCE_SEG << 4 ) ),
111 "i" ( COM32_BOUNCE_SEG << 4 ),
112 "R" ( virt_to_phys ( com32_intcall_wrapper ) ),
113 "R" ( virt_to_phys ( image->cmdline ?
114 image->cmdline : "" ) ),
115 "i" ( COM32_START_PHYS )
116 : "memory" );
117 DBGC ( image, "COM32 %s: returned\n", image->name );
118 break;
119
120 case COMBOOT_EXIT:
121 DBGC ( image, "COM32 %s: exited\n", image->name );
122 break;
123
126 DBGC ( image, "COM32 %s: exited to run kernel %s\n",
128 break;
129
131 DBGC ( image, "COM32 %s: exited after executing command\n",
132 image->name );
133 break;
134
135 default:
136 assert ( 0 );
137 break;
138 }
139
142
143 return 0;
144}
145
146/**
147 * Check image name extension
148 *
149 * @v image COM32 image
150 * @ret rc Return status code
151 */
152static int com32_identify ( struct image *image ) {
153 const char *ext;
154 static const uint8_t magic[] = { 0xB8, 0xFF, 0x4C, 0xCD, 0x21 };
155
156 if ( image->len >= sizeof ( magic ) ) {
157 /* Check for magic number
158 * mov eax,21cd4cffh
159 * B8 FF 4C CD 21
160 */
161 if ( memcmp ( image->data, magic, sizeof ( magic) ) == 0 ) {
162 DBGC ( image, "COM32 %s: found magic number\n",
163 image->name );
164 return 0;
165 }
166 }
167
168 /* Magic number not found; check filename extension */
169
170 ext = strrchr( image->name, '.' );
171
172 if ( ! ext ) {
173 DBGC ( image, "COM32 %s: no extension\n",
174 image->name );
175 return -ENOEXEC;
176 }
177
178 ++ext;
179
180 if ( strcasecmp( ext, "c32" ) ) {
181 DBGC ( image, "COM32 %s: unrecognized extension %s\n",
182 image->name, ext );
183 return -ENOEXEC;
184 }
185
186 return 0;
187}
188
189
190/**
191 * Load COM32 image into memory
192 * @v image COM32 image
193 * @ret rc Return status code
194 */
195static int com32_load_image ( struct image *image ) {
196 size_t filesz, memsz;
197 void *buffer;
198 int rc;
199
200 filesz = image->len;
201 memsz = filesz;
202 buffer = phys_to_virt ( COM32_START_PHYS );
203 if ( ( rc = prep_segment ( buffer, filesz, memsz ) ) != 0 ) {
204 DBGC ( image, "COM32 %s: could not prepare segment: %s\n",
205 image->name, strerror ( rc ) );
206 return rc;
207 }
208
209 /* Copy image to segment */
210 memcpy ( buffer, image->data, filesz );
211
212 return 0;
213}
214
215/**
216 * Prepare COM32 low memory bounce buffer
217 * @v image COM32 image
218 * @ret rc Return status code
219 */
220static int com32_prepare_bounce_buffer ( struct image * image ) {
221 void *seg;
222 size_t filesz, memsz;
223 int rc;
224
226
227 /* Ensure the entire 64k segment is free */
228 memsz = 0xFFFF;
229 filesz = 0;
230
231 /* Prepare, verify, and load the real-mode segment */
232 if ( ( rc = prep_segment ( seg, filesz, memsz ) ) != 0 ) {
233 DBGC ( image, "COM32 %s: could not prepare bounce buffer segment: %s\n",
234 image->name, strerror ( rc ) );
235 return rc;
236 }
237
238 return 0;
239}
240
241/**
242 * Probe COM32 image
243 *
244 * @v image COM32 image
245 * @ret rc Return status code
246 */
247static int com32_probe ( struct image *image ) {
248 int rc;
249
250 /* Check if this is a COMBOOT image */
251 if ( ( rc = com32_identify ( image ) ) != 0 ) {
252 return rc;
253 }
254
255 return 0;
256}
257
258/**
259 * Execute COMBOOT image
260 *
261 * @v image COM32 image
262 * @ret rc Return status code
263 */
264static int com32_exec ( struct image *image ) {
265 int rc;
266
267 /* Load image */
268 if ( ( rc = com32_load_image ( image ) ) != 0 ) {
269 return rc;
270 }
271
272 /* Prepare bounce buffer segment */
273 if ( ( rc = com32_prepare_bounce_buffer ( image ) ) != 0 ) {
274 return rc;
275 }
276
277 /* Reset console */
279
280 return com32_exec_loop ( image );
281}
282
283/** SYSLINUX COM32 image type */
284struct image_type com32_image_type __image_type ( PROBE_NORMAL ) = {
285 .name = "COM32",
286 .probe = com32_probe,
287 .exec = com32_exec,
288};
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 int uint32_t
Definition stdint.h:12
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
uint16_t magic
Magic signature.
Definition bzimage.h:1
static int com32_exec(struct image *image)
Execute COMBOOT image.
Definition com32.c:264
static int com32_prepare_bounce_buffer(struct image *image)
Prepare COM32 low memory bounce buffer.
Definition com32.c:220
static int com32_exec_loop(struct image *image)
Execute COMBOOT image.
Definition com32.c:51
static int com32_probe(struct image *image)
Probe COM32 image.
Definition com32.c:247
static int com32_load_image(struct image *image)
Load COM32 image into memory.
Definition com32.c:195
static int com32_identify(struct image *image)
Check image name extension.
Definition com32.c:152
SYSLINUX COMBOOT.
#define COMBOOT_EXIT
Definition comboot.h:119
void com32_farcall_wrapper()
#define COMBOOT_EXIT_COMMAND
Definition comboot.h:121
void com32_cfarcall_wrapper()
#define COMBOOT_EXIT_RUN_KERNEL
Definition comboot.h:120
#define COM32_BOUNCE_SEG
COM32 bounce buffer segment.
Definition comboot.h:23
#define COM32_START_PHYS
Entry point address of COM32 images.
Definition comboot.h:20
void com32_intcall_wrapper()
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
uint32_t buffer
Buffer index (or NETVSC_RNDIS_NO_BUFFER)
Definition netvsc.h:5
#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
System memory map.
static int memmap_is_usable(const struct memmap_region *region)
Check if memory region is usable.
Definition memmap.h:87
void memmap_describe(uint64_t min, int hide, struct memmap_region *region)
Describe memory region from system memory map.
Definition null_memmap.h:29
static uint64_t memmap_size(const struct memmap_region *region)
Get remaining size of memory region (from the described address upwards)
Definition memmap.h:99
String functions.
void * memcpy(void *dest, const void *src, size_t len) __nonnull
String functions.
Access to external ("user") memory.
#define PHYS_CODE(asm_code_str)
Definition librm.h:167
__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 memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
Definition string.c:115
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
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
A memory region descriptor.
Definition memmap.h:49