|
@@ -35,6 +35,8 @@
|
35
|
35
|
#include <gpxe/process.h>
|
36
|
36
|
#include <gpxe/serial.h>
|
37
|
37
|
#include <gpxe/init.h>
|
|
38
|
+#include <gpxe/image.h>
|
|
39
|
+#include <usr/imgmgmt.h>
|
38
|
40
|
|
39
|
41
|
/** The "SYSLINUX" version string */
|
40
|
42
|
static char __data16_array ( syslinux_version, [] ) = "gPXE " VERSION;
|
|
@@ -67,10 +69,8 @@ extern void int22_wrapper ( void );
|
67
|
69
|
/* setjmp/longjmp context buffer used to return after loading an image */
|
68
|
70
|
jmp_buf comboot_return;
|
69
|
71
|
|
70
|
|
-/* Command line to execute when returning via comboot_return
|
71
|
|
- * with COMBOOT_RETURN_RUN_KERNEL
|
72
|
|
- */
|
73
|
|
-char *comboot_kernel_cmdline;
|
|
72
|
+/* Replacement image when exiting with COMBOOT_EXIT_RUN_KERNEL */
|
|
73
|
+struct image *comboot_replacement_image;
|
74
|
74
|
|
75
|
75
|
/* Mode flags set by INT 22h AX=0017h */
|
76
|
76
|
static uint16_t comboot_graphics_mode = 0;
|
|
@@ -154,58 +154,81 @@ void comboot_force_text_mode ( void ) {
|
154
|
154
|
|
155
|
155
|
|
156
|
156
|
/**
|
157
|
|
- * Run the kernel specified in comboot_kernel_cmdline
|
|
157
|
+ * Fetch kernel and optional initrd
|
158
|
158
|
*/
|
159
|
|
-void comboot_run_kernel ( )
|
160
|
|
-{
|
161
|
|
- char *initrd;
|
162
|
|
-
|
163
|
|
- comboot_force_text_mode ( );
|
164
|
|
-
|
165
|
|
- DBG ( "COMBOOT: executing image '%s'\n", comboot_kernel_cmdline );
|
|
159
|
+static int comboot_fetch_kernel ( char *kernel_file, char *cmdline ) {
|
|
160
|
+ struct image *kernel;
|
|
161
|
+ struct image *initrd = NULL;
|
|
162
|
+ char *initrd_file;
|
|
163
|
+ int rc;
|
166
|
164
|
|
167
|
165
|
/* Find initrd= parameter, if any */
|
168
|
|
- if ( ( initrd = strstr ( comboot_kernel_cmdline, "initrd=" ) ) ) {
|
169
|
|
- char old_char = '\0';
|
170
|
|
- char *initrd_end = strchr( initrd, ' ' );
|
171
|
|
-
|
172
|
|
- /* Replace space after end of parameter
|
173
|
|
- * with a nul terminator if this is not
|
174
|
|
- * the last parameter
|
175
|
|
- */
|
176
|
|
- if ( initrd_end ) {
|
177
|
|
- old_char = *initrd_end;
|
178
|
|
- *initrd_end = '\0';
|
179
|
|
- }
|
|
166
|
+ if ( ( initrd_file = strstr ( cmdline, "initrd=" ) ) != NULL ) {
|
|
167
|
+ char *initrd_end;
|
180
|
168
|
|
181
|
|
- /* Replace = with space to get 'initrd filename'
|
182
|
|
- * command suitable for system()
|
183
|
|
- */
|
184
|
|
- initrd[6] = ' ';
|
|
169
|
+ /* skip "initrd=" */
|
|
170
|
+ initrd_file += 7;
|
185
|
171
|
|
186
|
|
- DBG( "COMBOOT: loading initrd '%s'\n", initrd );
|
|
172
|
+ /* Find terminating space, if any, and replace with NUL */
|
|
173
|
+ initrd_end = strchr ( initrd_file, ' ' );
|
|
174
|
+ if ( initrd_end )
|
|
175
|
+ *initrd_end = '\0';
|
187
|
176
|
|
188
|
|
- system ( initrd );
|
|
177
|
+ DBG ( "COMBOOT: fetching initrd '%s'\n", initrd_file );
|
189
|
178
|
|
190
|
|
- /* Restore space after parameter */
|
191
|
|
- if ( initrd_end ) {
|
192
|
|
- *initrd_end = old_char;
|
|
179
|
+ /* Allocate and fetch initrd */
|
|
180
|
+ initrd = alloc_image();
|
|
181
|
+ if ( ! initrd ) {
|
|
182
|
+ DBG ( "COMBOOT: could not allocate initrd\n" );
|
|
183
|
+ rc = -ENOMEM;
|
|
184
|
+ goto err_alloc_initrd;
|
|
185
|
+ }
|
|
186
|
+ if ( ( rc = imgfetch ( initrd, initrd_file,
|
|
187
|
+ register_image ) ) != 0 ) {
|
|
188
|
+ DBG ( "COMBOOT: could not fetch initrd: %s\n",
|
|
189
|
+ strerror ( rc ) );
|
|
190
|
+ goto err_fetch_initrd;
|
193
|
191
|
}
|
194
|
192
|
|
195
|
|
- /* Restore = */
|
196
|
|
- initrd[6] = '=';
|
|
193
|
+ /* Restore space after initrd name, if applicable */
|
|
194
|
+ if ( initrd_end )
|
|
195
|
+ *initrd_end = ' ';
|
197
|
196
|
}
|
198
|
197
|
|
199
|
|
- /* Load kernel */
|
200
|
|
- DBG ( "COMBOOT: loading kernel '%s'\n", comboot_kernel_cmdline );
|
201
|
|
- system ( comboot_kernel_cmdline );
|
|
198
|
+ DBG ( "COMBOOT: fetching kernel '%s'\n", kernel_file );
|
202
|
199
|
|
203
|
|
- free ( comboot_kernel_cmdline );
|
|
200
|
+ /* Allocate and fetch kernel */
|
|
201
|
+ kernel = alloc_image();
|
|
202
|
+ if ( ! kernel ) {
|
|
203
|
+ DBG ( "COMBOOT: could not allocate kernel\n" );
|
|
204
|
+ rc = -ENOMEM;
|
|
205
|
+ goto err_alloc_kernel;
|
|
206
|
+ }
|
|
207
|
+ if ( ( rc = imgfetch ( kernel, kernel_file,
|
|
208
|
+ register_image ) ) != 0 ) {
|
|
209
|
+ DBG ( "COMBOOT: could not fetch kernel: %s\n",
|
|
210
|
+ strerror ( rc ) );
|
|
211
|
+ goto err_fetch_kernel;
|
|
212
|
+ }
|
|
213
|
+ if ( ( rc = image_set_cmdline ( kernel, cmdline ) ) != 0 ) {
|
|
214
|
+ DBG ( "COMBOOT: could not set kernel command line: %s\n",
|
|
215
|
+ strerror ( rc ) );
|
|
216
|
+ goto err_set_cmdline;
|
|
217
|
+ }
|
204
|
218
|
|
205
|
|
- /* Boot */
|
206
|
|
- system ( "boot" );
|
|
219
|
+ /* Store kernel as replacement image */
|
|
220
|
+ comboot_replacement_image = kernel;
|
207
|
221
|
|
208
|
|
- DBG ( "COMBOOT: back from executing command\n" );
|
|
222
|
+ return 0;
|
|
223
|
+
|
|
224
|
+ err_set_cmdline:
|
|
225
|
+ err_fetch_kernel:
|
|
226
|
+ image_put ( kernel );
|
|
227
|
+ err_alloc_kernel:
|
|
228
|
+ err_fetch_initrd:
|
|
229
|
+ image_put ( initrd );
|
|
230
|
+ err_alloc_initrd:
|
|
231
|
+ return rc;
|
209
|
232
|
}
|
210
|
233
|
|
211
|
234
|
|
|
@@ -213,7 +236,7 @@ void comboot_run_kernel ( )
|
213
|
236
|
* Terminate program interrupt handler
|
214
|
237
|
*/
|
215
|
238
|
static __asmcall void int20 ( struct i386_all_regs *ix86 __unused ) {
|
216
|
|
- longjmp ( comboot_return, COMBOOT_RETURN_EXIT );
|
|
239
|
+ longjmp ( comboot_return, COMBOOT_EXIT );
|
217
|
240
|
}
|
218
|
241
|
|
219
|
242
|
|
|
@@ -226,7 +249,7 @@ static __asmcall void int21 ( struct i386_all_regs *ix86 ) {
|
226
|
249
|
switch ( ix86->regs.ah ) {
|
227
|
250
|
case 0x00:
|
228
|
251
|
case 0x4C: /* Terminate program */
|
229
|
|
- longjmp ( comboot_return, COMBOOT_RETURN_EXIT );
|
|
252
|
+ longjmp ( comboot_return, COMBOOT_EXIT );
|
230
|
253
|
break;
|
231
|
254
|
|
232
|
255
|
case 0x01: /* Get Key with Echo */
|
|
@@ -323,17 +346,15 @@ static __asmcall void int22 ( struct i386_all_regs *ix86 ) {
|
323
|
346
|
char cmd[len + 1];
|
324
|
347
|
copy_from_user ( cmd, cmd_u, 0, len + 1 );
|
325
|
348
|
DBG ( "COMBOOT: executing command '%s'\n", cmd );
|
326
|
|
-
|
327
|
|
- comboot_kernel_cmdline = strdup ( cmd );
|
328
|
|
-
|
329
|
|
- DBG ( "COMBOOT: returning to run image...\n" );
|
330
|
|
- longjmp ( comboot_return, COMBOOT_RETURN_RUN_KERNEL );
|
|
349
|
+ system ( cmd );
|
|
350
|
+ DBG ( "COMBOOT: exiting after executing command...\n" );
|
|
351
|
+ longjmp ( comboot_return, COMBOOT_EXIT_COMMAND );
|
331
|
352
|
}
|
332
|
353
|
break;
|
333
|
354
|
|
334
|
355
|
case 0x0004: /* Run default command */
|
335
|
356
|
/* FIXME: just exit for now */
|
336
|
|
- longjmp ( comboot_return, COMBOOT_RETURN_EXIT );
|
|
357
|
+ longjmp ( comboot_return, COMBOOT_EXIT_COMMAND );
|
337
|
358
|
break;
|
338
|
359
|
|
339
|
360
|
case 0x0005: /* Force text mode */
|
|
@@ -518,21 +539,21 @@ static __asmcall void int22 ( struct i386_all_regs *ix86 ) {
|
518
|
539
|
userptr_t cmd_u = real_to_user ( ix86->segs.es, ix86->regs.bx );
|
519
|
540
|
int file_len = strlen_user ( file_u, 0 );
|
520
|
541
|
int cmd_len = strlen_user ( cmd_u, 0 );
|
521
|
|
- char file[file_len + 1 + cmd_len + 7 + 1];
|
|
542
|
+ char file[file_len + 1];
|
522
|
543
|
char cmd[cmd_len + 1];
|
523
|
544
|
|
524
|
|
- memcpy( file, "kernel ", 7 );
|
525
|
|
- copy_from_user ( file + 7, file_u, 0, file_len + 1 );
|
|
545
|
+ copy_from_user ( file, file_u, 0, file_len + 1 );
|
526
|
546
|
copy_from_user ( cmd, cmd_u, 0, cmd_len + 1 );
|
527
|
|
- strcat ( file, " " );
|
528
|
|
- strcat ( file, cmd );
|
529
|
|
-
|
530
|
|
- DBG ( "COMBOOT: run kernel image '%s'\n", file );
|
531
|
547
|
|
532
|
|
- comboot_kernel_cmdline = strdup ( file );
|
533
|
|
-
|
534
|
|
- DBG ( "COMBOOT: returning to run image...\n" );
|
535
|
|
- longjmp ( comboot_return, COMBOOT_RETURN_RUN_KERNEL );
|
|
548
|
+ DBG ( "COMBOOT: run kernel %s %s\n", file, cmd );
|
|
549
|
+ comboot_fetch_kernel ( file, cmd );
|
|
550
|
+ /* Technically, we should return if we
|
|
551
|
+ * couldn't load the kernel, but it's not safe
|
|
552
|
+ * to do that since we have just overwritten
|
|
553
|
+ * part of the COMBOOT program's memory space.
|
|
554
|
+ */
|
|
555
|
+ DBG ( "COMBOOT: exiting to run kernel...\n" );
|
|
556
|
+ longjmp ( comboot_return, COMBOOT_EXIT_RUN_KERNEL );
|
536
|
557
|
}
|
537
|
558
|
break;
|
538
|
559
|
|