1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17#include <stdio.h>
18#include <stdlib.h>
19#include <unistd.h>
20#include <string.h>
21#include <fcntl.h>
22#include <sys/types.h>
23#include <sys/stat.h>
24#include <minmax.h>
25#include <ctype.h>
26
27#include <syslinux/loadfile.h>
28#include <syslinux/config.h>
29#include <syslinux/linux.h>
30#include <syslinux/boot.h>
31#include <console.h>
32#include <com32.h>
33
34
35
36#define MAX_CONFIG_LINE_LEN 2048
37#define MAX_CMDLINE_LEN 2048
38
39
40
41
42#define REALMODE_BUF_SIZE 4096
43#define LOWMEM_BUF_SIZE 65536
44
45
46#define GFX_MEMORY_SIZE 7
47
48
49#define CHUNK_SIZE (64 << 10)
50
51
52#define GFX_CB_INIT 0
53#define GFX_CB_DONE 1
54#define GFX_CB_INPUT 2
55#define GFX_CB_MENU_INIT 3
56#define GFX_CB_INFOBOX_INIT 4
57#define GFX_CB_INFOBOX_DONE 5
58#define GFX_CB_PROGRESS_INIT 6
59#define GFX_CB_PROGRESS_DONE 7
60#define GFX_CB_PROGRESS_UPDATE 8
61#define GFX_CB_PROGRESS_LIMIT 9
62#define GFX_CB_PASSWORD_INIT 10
63#define GFX_CB_PASSWORD_DONE 11
64
65
66extern const char realmode_callback_start[], realmode_callback_end[];
67
68
69#undef linux
70
71
72
73
74typedef struct __attribute__ ((packed)) {
75 uint8_t bootloader;
76 uint8_t sector_shift;
77 uint8_t media_type;
78 uint8_t failsafe;
79
80
81
82 uint8_t sysconfig_size;
83 uint8_t boot_drive;
84 uint16_t callback;
85 uint16_t bootloader_seg;
86 uint16_t serial_port;
87 uint32_t user_info_0;
88 uint32_t user_info_1;
89 uint32_t bios_mem_size;
90 uint16_t xmem_0;
91 uint16_t xmem_1;
92 uint16_t xmem_2;
93 uint16_t xmem_3;
94 uint32_t file;
95 uint32_t archive_start;
96 uint32_t archive_end;
97 uint32_t mem0_start;
98 uint32_t mem0_end;
99 uint32_t xmem_start;
100 uint32_t xmem_end;
101 uint16_t features;
102
103
104 uint16_t reserved_1;
105} gfx_config_t;
106
107
108
109typedef struct __attribute__ ((packed)) {
110 uint16_t entries;
111 char *default_entry;
112 char *label_list;
113 uint16_t label_size;
114 char *arg_list;
115 uint16_t arg_size;
116} gfx_menu_t;
117
118
119
120typedef struct menu_s {
121 struct menu_s *next;
122 char *label;
123 char *menu_label;
124 char *kernel;
125 char *alt_kernel;
126 char *linux;
127 char *localboot;
128 char *initrd;
129 char *append;
130 char *ipappend;
131} menu_t;
132
133
134
135gfx_config_t gfx_config;
136gfx_menu_t gfx_menu;
137
138menu_t *menu;
139menu_t *menu_default;
140static menu_t *menu_ptr, **menu_next;
141
142struct {
143 uint32_t jmp_table[12];
144 uint16_t code_seg;
145 char fname_buf[64];
146} gfx;
147
148void *lowmem_buf;
149
150int timeout;
151
152char cmdline[MAX_CMDLINE_LEN];
153
154
155unsigned progress_active;
156
157
158
159void show_message(char *file);
160char *get_config_file_name(void);
161char *skip_nonspaces(char *s);
162void chop_line(char *s);
163int read_config_file(const char *filename);
164unsigned magic_ok(unsigned char *buf, unsigned *code_size);
165unsigned find_file(unsigned char *buf, unsigned len, unsigned *gfx_file_start, unsigned *file_len, unsigned *code_size);
166int gfx_init(char *file);
167int gfx_menu_init(void);
168void gfx_done(void);
169int gfx_input(void);
170void gfx_infobox(int type, char *str1, char *str2);
171void gfx_progress_init(ssize_t kernel_size, char *label);
172void gfx_progress_update(ssize_t size);
173void gfx_progress_done(void);
174void *load_one(char *file, ssize_t *file_size);
175void boot(int index);
176void boot_entry(menu_t *menu_ptr, char *arg);
177
178
179
180int main(int argc, char **argv)
181{
182 int menu_index;
183 const union syslinux_derivative_info *sdi;
184
185 openconsole(&dev_stdcon_r, &dev_stdcon_w);
186
187 lowmem_buf = lmalloc(LOWMEM_BUF_SIZE);
188 if (!lowmem_buf) {
189 printf("Could not allocate memory.\n");
190 return 1;
191 }
192
193 sdi = syslinux_derivative_info();
194
195 gfx_config.sector_shift = sdi->disk.sector_shift;
196 gfx_config.boot_drive = sdi->disk.drive_number;
197
198 if(sdi->c.filesystem == SYSLINUX_FS_PXELINUX) {
199 gfx_config.sector_shift = 11;
200 gfx_config.boot_drive = 0;
201 }
202
203 gfx_config.media_type = gfx_config.boot_drive < 0x80 ? 1 : 0;
204
205 if(sdi->c.filesystem == SYSLINUX_FS_ISOLINUX) {
206 gfx_config.media_type = sdi->iso.cd_mode ? 0 : 2;
207 }
208
209 gfx_config.bootloader = 1;
210 gfx_config.sysconfig_size = sizeof gfx_config;
211 gfx_config.bootloader_seg = 0;
212
213 if(argc < 2) {
214 printf("Usage: gfxboot.c32 bootlogo_file [message_file]\n");
215 if(argc > 2) show_message(argv[2]);
216
217 return 0;
218 }
219
220 if(read_config_file("~")) {
221 printf("Error reading config file\n");
222 if(argc > 2) show_message(argv[2]);
223
224 return 0;
225 }
226
227 if(gfx_init(argv[1])) {
228 printf("Error setting up gfxboot\n");
229 if(argc > 2) show_message(argv[2]);
230
231 return 0;
232 }
233
234 gfx_menu_init();
235
236 for(;;) {
237 menu_index = gfx_input();
238
239
240 if(menu_index == -1) {
241 gfx_done();
242 break;
243 }
244
245
246 boot(menu_index);
247 }
248
249 if(argc > 2) show_message(argv[2]);
250
251 return 0;
252}
253
254
255
256void show_message(char *file)
257{
258 int c;
259 FILE *f;
260
261 if(!(f = fopen(file, "r"))) return;
262
263 while((c = getc(f)) != EOF) {
264 if(c < ' ' && c != '\n' && c != '\t') continue;
265 printf("%c", c);
266 }
267
268 fclose(f);
269}
270
271
272
273char *skip_nonspaces(char *s)
274{
275 while(*s && *s != ' ' && *s != '\t') s++;
276
277 return s;
278}
279
280
281
282void chop_line(char *s)
283{
284 int i = strlen(s);
285
286 if(!i) return;
287
288 while(--i >= 0) {
289 if(s[i] == ' ' || s[i] == '\t' || s[i] == '\n') {
290 s[i] = 0;
291 }
292 else {
293 break;
294 }
295 }
296}
297
298
299
300
301
302
303
304
305int read_config_file(const char *filename)
306{
307 FILE *f;
308 char *s, *t, buf[MAX_CONFIG_LINE_LEN];
309 unsigned u, top_level = 0, text = 0;
310
311 if(!strcmp(filename, "~")) {
312 top_level = 1;
313 filename = syslinux_config_file();
314 gfx_menu.entries = 0;
315 gfx_menu.label_size = 0;
316 gfx_menu.arg_size = 0;
317 menu_ptr = NULL;
318 menu_next = &menu;
319 menu_default = calloc(1, sizeof *menu_default);
320 }
321
322 if(!(f = fopen(filename, "r"))) return 1;
323
324 while((s = fgets(buf, sizeof buf, f))) {
325 chop_line(s);
326 s = skipspace(s);
327 if(!*s || *s == '#') continue;
328 t = skip_nonspaces(s);
329 if(*t) *t++ = 0;
330 t = skipspace(t);
331
332 if(!strcasecmp(s, "endtext")) {
333 text = 0;
334 continue;
335 }
336
337 if (text)
338 continue;
339
340 if(!strcasecmp(s, "timeout")) {
341 timeout = atoi(t);
342 continue;
343 }
344
345 if(!strcasecmp(s, "default")) {
346 menu_default->label = strdup(t);
347 u = strlen(t);
348 if(u > gfx_menu.label_size) gfx_menu.label_size = u;
349 continue;
350 }
351
352 if(!strcasecmp(s, "label")) {
353 menu_ptr = *menu_next = calloc(1, sizeof **menu_next);
354 menu_next = &menu_ptr->next;
355 gfx_menu.entries++;
356 menu_ptr->label = menu_ptr->menu_label = strdup(t);
357 u = strlen(t);
358 if(u > gfx_menu.label_size) gfx_menu.label_size = u;
359 continue;
360 }
361
362 if(!strcasecmp(s, "kernel") && menu_ptr) {
363 menu_ptr->kernel = strdup(t);
364 continue;
365 }
366
367 if(!strcasecmp(s, "linux") && menu_ptr) {
368 menu_ptr->linux = strdup(t);
369 continue;
370 }
371
372 if(!strcasecmp(s, "localboot") && menu_ptr) {
373 menu_ptr->localboot = strdup(t);
374 continue;
375 }
376
377 if(!strcasecmp(s, "initrd") && menu_ptr) {
378 menu_ptr->initrd = strdup(t);
379 continue;
380 }
381
382 if(!strcasecmp(s, "append")) {
383 (menu_ptr ?: menu_default)->append = strdup(t);
384 u = strlen(t);
385 if(u > gfx_menu.arg_size) gfx_menu.arg_size = u;
386 continue;
387 }
388
389 if(!strcasecmp(s, "ipappend")) {
390 (menu_ptr ?: menu_default)->ipappend = strdup(t);
391 continue;
392 }
393
394 if(!strcasecmp(s, "text")) {
395 text = 1;
396 continue;
397 }
398
399 if(!strcasecmp(s, "menu") && menu_ptr) {
400 s = skipspace(t);
401 t = skip_nonspaces(s);
402 if(*t) *t++ = 0;
403 t = skipspace(t);
404
405 if(!strcasecmp(s, "label")) {
406 menu_ptr->menu_label = strdup(t);
407 u = strlen(t);
408 if(u > gfx_menu.label_size) gfx_menu.label_size = u;
409 continue;
410 }
411
412 if(!strcasecmp(s, "include")) {
413 goto do_include;
414 }
415 }
416
417 if (!strcasecmp(s, "include")) {
418do_include:
419 s = t;
420 t = skip_nonspaces(s);
421 if (*t) *t = 0;
422 read_config_file(s);
423 }
424 }
425
426 fclose(f);
427
428 if (!top_level)
429 return 0;
430
431 if (gfx_menu.entries == 0) {
432 printf("No LABEL keywords found.\n");
433 return 1;
434 }
435
436
437 gfx_menu.label_size++;
438 gfx_menu.arg_size++;
439
440
441 if(!menu_default->label) menu_default->label = menu->label;
442
443 if(menu_default->label) {
444 for(menu_ptr = menu; menu_ptr; menu_ptr = menu_ptr->next) {
445 if(!strcmp(menu_default->label, menu_ptr->label)) {
446 menu_default->menu_label = menu_ptr->menu_label;
447 break;
448 }
449 }
450 }
451
452 gfx_menu.default_entry = menu_default->menu_label;
453 gfx_menu.label_list = calloc(gfx_menu.entries, gfx_menu.label_size);
454 gfx_menu.arg_list = calloc(gfx_menu.entries, gfx_menu.arg_size);
455
456 for(u = 0, menu_ptr = menu; menu_ptr; menu_ptr = menu_ptr->next, u++) {
457 if(!menu_ptr->append) menu_ptr->append = menu_default->append;
458 if(!menu_ptr->ipappend) menu_ptr->ipappend = menu_default->ipappend;
459
460 if(menu_ptr->menu_label) strcpy(gfx_menu.label_list + u * gfx_menu.label_size, menu_ptr->menu_label);
461 if(menu_ptr->append) strcpy(gfx_menu.arg_list + u * gfx_menu.arg_size, menu_ptr->append);
462 }
463
464 return 0;
465}
466
467
468
469
470
471unsigned magic_ok(unsigned char *buf, unsigned *code_size)
472{
473 if(
474 *(unsigned *) buf == 0x0b2d97f00 &&
475 (buf[4] == 8)
476 ) {
477 *code_size = *(unsigned *) (buf + 12);
478 return *(unsigned *) (buf + 8);
479 }
480
481 return 0;
482}
483
484
485
486
487
488unsigned find_file(unsigned char *buf, unsigned len, unsigned *gfx_file_start, unsigned *file_len, unsigned *code_size)
489{
490 unsigned i, fname_len, code_start = 0;
491
492 *gfx_file_start = 0;
493 *code_size = 0;
494
495 if((code_start = magic_ok(buf, code_size))) return code_start;
496
497 for(i = 0; i < len;) {
498 if((len - i) >= 0x1a && (buf[i] + (buf[i + 1] << 8)) == 0x71c7) {
499 fname_len = *(unsigned short *) (buf + i + 20);
500 *file_len = *(unsigned short *) (buf + i + 24) + (*(unsigned short *) (buf + i + 22) << 16);
501 i += 26 + fname_len;
502 i = ((i + 1) & ~1);
503 if((code_start = magic_ok(buf + i, code_size))) {
504 *gfx_file_start = i;
505 return code_start;
506 }
507 i += *file_len;
508 i = ((i + 1) & ~1);
509 }
510 else {
511 break;
512 }
513 }
514
515 return code_start;
516}
517
518
519
520
521
522
523
524
525int gfx_init(char *file)
526{
527 size_t archive_size = 0;
528 void *archive;
529 unsigned code_start, code_size, file_start, file_len, u;
530 com32sys_t r;
531 void *lowmem = lowmem_buf;
532 unsigned lowmem_size = LOWMEM_BUF_SIZE;
533
534 progress_active = 0;
535
536 printf("Loading %s...\n", file);
537 if(loadfile(file, &archive, &archive_size)) return 1;
538
539 if(!archive_size) return 1;
540
541
542
543 gfx_config.archive_start = (uint32_t) archive;
544 gfx_config.archive_end = gfx_config.archive_start + archive_size;
545
546
547 if(!(code_start = find_file(archive, archive_size, &file_start, &file_len, &code_size))) {
548 printf("%s: invalid file format\n", file);
549 return 1;
550 }
551
552#if 0
553 printf(
554 "code_start = 0x%x, code_size = 0x%x\n"
555 "archive_start = 0x%x, archive size = 0x%x\n"
556 "file_start = 0x%x, file_len = 0x%x\n",
557 code_start, code_size,
558 gfx_config.archive_start, archive_size,
559 file_start, file_len
560 );
561#endif
562
563 gfx_config.file = gfx_config.archive_start + file_start;
564
565 u = realmode_callback_end - realmode_callback_start;
566 u = (u + REALMODE_BUF_SIZE + 0xf) & ~0xf;
567
568 if(u + code_size > lowmem_size) {
569 printf("lowmem buffer too small: size %u, needed %u\n", lowmem_size, u + code_size);
570 return 1;
571 }
572
573 memcpy(lowmem + REALMODE_BUF_SIZE, realmode_callback_start,
574 realmode_callback_end - realmode_callback_start);
575
576
577 *(uint16_t *) (lowmem + REALMODE_BUF_SIZE) = REALMODE_BUF_SIZE;
578 *(uint16_t *) (lowmem + REALMODE_BUF_SIZE + 2) = (uint32_t) lowmem >> 4;
579
580 gfx_config.bootloader_seg = ((uint32_t) lowmem + REALMODE_BUF_SIZE) >> 4;
581 gfx_config.callback = 4;
582
583 lowmem += u;
584 lowmem_size -= u;
585
586 memcpy(lowmem, archive + file_start + code_start, code_size);
587
588 gfx_config.mem0_start = (uint32_t) lowmem + code_size;
589 gfx_config.mem0_end = (uint32_t) lowmem + lowmem_size;
590
591 gfx_config.mem0_start = (gfx_config.mem0_start + 0xf) & ~0xf;
592
593 gfx_config.xmem_start = (uint32_t) malloc(GFX_MEMORY_SIZE << 20);
594 if(gfx_config.xmem_start) {
595 gfx_config.xmem_end = gfx_config.xmem_start + (GFX_MEMORY_SIZE << 20);
596 }
597
598
599 gfx_config.bios_mem_size = 256 << 20;
600
601 gfx.code_seg = (uint32_t) lowmem >> 4;
602
603 for(u = 0; u < sizeof gfx.jmp_table / sizeof *gfx.jmp_table; u++) {
604 gfx.jmp_table[u] = (gfx.code_seg << 16) + *(uint16_t *) (lowmem + 2 * u);
605 }
606
607#if 0
608 for(u = 0; u < sizeof gfx.jmp_table / sizeof *gfx.jmp_table; u++) {
609 printf("%d: 0x%08x\n", u, gfx.jmp_table[u]);
610 }
611#endif
612
613
614
615 r.esi.l = (uint32_t) &gfx_config;
616 __farcall(gfx.code_seg, gfx.jmp_table[GFX_CB_INIT], &r, &r);
617
618 if((r.eflags.l & EFLAGS_CF)) {
619 printf("graphics initialization failed\n");
620
621 return 1;
622 }
623
624 if((gfx_config.features & 3) != 3) {
625 gfx_done();
626
627 printf("%s: boot graphics code too old, please use newer version\n", file);
628
629 return 1;
630 }
631
632
633 return 0;
634}
635
636
637
638int gfx_menu_init(void)
639{
640 com32sys_t r;
641
642 r.esi.l = (uint32_t) &gfx_menu;
643 __farcall(gfx.code_seg, gfx.jmp_table[GFX_CB_MENU_INIT], &r, &r);
644
645 return 0;
646}
647
648
649
650void gfx_done(void)
651{
652 com32sys_t r;
653
654 gfx_progress_done();
655
656 __farcall(gfx.code_seg, gfx.jmp_table[GFX_CB_DONE], &r, &r);
657}
658
659
660
661
662
663
664
665
666int gfx_input(void)
667{
668 com32sys_t r;
669
670 r.edi.l = (uint32_t) cmdline;
671 r.ecx.l = sizeof cmdline;
672 r.eax.l = timeout * 182 / 100;
673 timeout = 0;
674 __farcall(gfx.code_seg, gfx.jmp_table[GFX_CB_INPUT], &r, &r);
675 if((r.eflags.l & EFLAGS_CF)) r.eax.l = 1;
676
677 if(r.eax.l == 1) return -1;
678
679 return r.ebx.l;
680}
681
682
683
684void gfx_infobox(int type, char *str1, char *str2)
685{
686 com32sys_t r;
687
688 r.eax.l = type;
689 r.esi.l = (uint32_t) str1;
690 r.edi.l = (uint32_t) str2;
691 __farcall(gfx.code_seg, gfx.jmp_table[GFX_CB_INFOBOX_INIT], &r, &r);
692 r.edi.l = r.eax.l = 0;
693 __farcall(gfx.code_seg, gfx.jmp_table[GFX_CB_INPUT], &r, &r);
694 __farcall(gfx.code_seg, gfx.jmp_table[GFX_CB_INFOBOX_DONE], &r, &r);
695}
696
697
698
699void gfx_progress_init(ssize_t kernel_size, char *label)
700{
701 com32sys_t r;
702
703 if(!progress_active) {
704 r.eax.l = kernel_size >> gfx_config.sector_shift;
705 r.esi.l = (uint32_t) label;
706 __farcall(gfx.code_seg, gfx.jmp_table[GFX_CB_PROGRESS_INIT], &r, &r);
707 }
708
709 progress_active = 1;
710}
711
712
713
714void gfx_progress_update(ssize_t advance)
715{
716 com32sys_t r;
717
718 if(progress_active) {
719 r.eax.l = advance >> gfx_config.sector_shift;
720 __farcall(gfx.code_seg, gfx.jmp_table[GFX_CB_PROGRESS_UPDATE], &r, &r);
721 }
722}
723
724
725
726void gfx_progress_done(void)
727{
728 com32sys_t r;
729
730 if(progress_active) {
731 __farcall(gfx.code_seg, gfx.jmp_table[GFX_CB_PROGRESS_DONE], &r, &r);
732 }
733
734 progress_active = 0;
735}
736
737
738
739
740
741void *load_one(char *file, ssize_t *file_size)
742{
743 int fd;
744 void *buf = NULL;
745 char *str;
746 struct stat sbuf;
747 ssize_t size = 0, cur, i;
748
749 *file_size = 0;
750
751 if((fd = open(file, O_RDONLY)) == -1) {
752 asprintf(&str, "%s: file not found", file);
753 gfx_infobox(0, str, NULL);
754 free(str);
755 return buf;
756 }
757
758 if(!fstat(fd, &sbuf) && S_ISREG(sbuf.st_mode)) size = sbuf.st_size;
759
760 i = 0;
761
762 if(size) {
763 buf = malloc(size);
764 for(i = 1, cur = 0 ; cur < size && i > 0; cur += i) {
765 i = read(fd, buf + cur, min(CHUNK_SIZE, size - cur));
766 if(i == -1) break;
767 gfx_progress_update(i);
768 }
769 }
770 else {
771 do {
772 buf = realloc(buf, size + CHUNK_SIZE);
773 i = read(fd, buf + size, CHUNK_SIZE);
774 if(i == -1) break;
775 size += i;
776 gfx_progress_update(i);
777 } while(i > 0);
778 }
779
780 close(fd);
781
782 if(i == -1) {
783 asprintf(&str, "%s: read error @ %d", file, size);
784 gfx_infobox(0, str, NULL);
785 free(str);
786 free(buf);
787 buf = NULL;
788 size = 0;
789 }
790
791 *file_size = size;
792
793 return buf;
794}
795
796
797
798
799
800
801
802void boot(int index)
803{
804 char *arg, *alt_kernel;
805 menu_t *menu_ptr;
806 int i, label_len;
807 unsigned ipapp;
808 const struct syslinux_ipappend_strings *ipappend;
809
810 for(menu_ptr = menu; menu_ptr; menu_ptr = menu_ptr->next, index--) {
811 if(!index) break;
812 }
813
814
815 if(!menu_ptr || !menu_ptr->menu_label) return;
816
817 arg = skipspace(cmdline);
818 label_len = strlen(menu_ptr->menu_label);
819
820
821 if(strncmp(arg, menu_ptr->menu_label, label_len)) {
822 alt_kernel = arg;
823 arg = skip_nonspaces(arg);
824 if(*arg) *arg++ = 0;
825 if(*alt_kernel) menu_ptr->alt_kernel = alt_kernel;
826 }
827 else {
828 arg += label_len;
829 }
830
831 arg = skipspace(arg);
832
833
834 if(menu_ptr->ipappend && (ipapp = atoi(menu_ptr->ipappend))) {
835 ipappend = syslinux_ipappend_strings();
836 for(i = 0; i < ipappend->count; i++) {
837 if((ipapp & (1 << i)) && ipappend->ptr[i]) {
838 sprintf(arg + strlen(arg), " %s", ipappend->ptr[i]);
839 }
840 }
841 }
842
843 boot_entry(menu_ptr, arg);
844
845 gfx_progress_done();
846}
847
848
849
850
851
852
853
854void boot_entry(menu_t *menu_ptr, char *arg)
855{
856 void *kernel, *initrd_buf;
857 ssize_t kernel_size = 0, initrd_size = 0;
858 struct initramfs *initrd = NULL;
859 char *file, *cmd_buf;
860 int fd;
861 struct stat sbuf;
862 char *s, *s0, *t, *initrd_arg;
863
864 if(!menu_ptr) return;
865
866 if(menu_ptr->localboot) {
867 gfx_done();
868 syslinux_local_boot(strtol(menu_ptr->localboot, NULL, 0));
869
870 return;
871 }
872
873 file = menu_ptr->alt_kernel;
874 if(!file) file = menu_ptr->kernel;
875 if(!file) file = menu_ptr->linux;
876 if(!file) {
877 gfx_done();
878 asprintf(&cmd_buf, "%s %s", menu_ptr->label, arg);
879 syslinux_run_command(cmd_buf);
880 return;
881 }
882
883
884
885 kernel_size = 0;
886
887 if((fd = open(file, O_RDONLY)) >= 0) {
888 if(!fstat(fd, &sbuf) && S_ISREG(sbuf.st_mode)) kernel_size = sbuf.st_size;
889 close(fd);
890 }
891
892 gfx_progress_init(kernel_size, file);
893
894 kernel = load_one(file, &kernel_size);
895
896 if(!kernel) {
897 return;
898 }
899
900 if(kernel_size < 1024 || *(uint32_t *) (kernel + 0x202) != 0x53726448) {
901
902 gfx_done();
903 asprintf(&cmd_buf, "%s %s", menu_ptr->label, arg);
904 syslinux_run_command(cmd_buf);
905 return;
906 }
907
908
909
910
911
912 initrd_arg = menu_ptr->initrd;
913
914 s = s0 = strdup(arg);
915
916 while(*s && strncmp(s, "initrd=", sizeof "initrd=" - 1)) {
917 s = skipspace(skip_nonspaces(s));
918 }
919
920 if(*s) {
921 s += sizeof "initrd=" - 1;
922 *skip_nonspaces(s) = 0;
923 initrd_arg = s;
924 }
925
926 if(initrd_arg) {
927 initrd = initramfs_init();
928
929 while((t = strsep(&s, ","))) {
930 initrd_buf = load_one(t, &initrd_size);
931
932 if(!initrd_buf) {
933 printf("%s: read error\n", t);
934 free(s0);
935 return;
936 }
937
938 initramfs_add_data(initrd, initrd_buf, initrd_size, initrd_size, 4);
939
940
941 }
942 }
943
944 free(s0);
945
946 gfx_done();
947
948 syslinux_boot_linux(kernel, kernel_size, initrd, arg);
949}
950
951
952