diff options
Diffstat (limited to 'contrib/syslinux/syslinux-4.03/com32/gfxboot/gfxboot.c')
-rw-r--r-- | contrib/syslinux/syslinux-4.03/com32/gfxboot/gfxboot.c | 960 |
1 files changed, 0 insertions, 960 deletions
diff --git a/contrib/syslinux/syslinux-4.03/com32/gfxboot/gfxboot.c b/contrib/syslinux/syslinux-4.03/com32/gfxboot/gfxboot.c deleted file mode 100644 index 2323f8e..0000000 --- a/contrib/syslinux/syslinux-4.03/com32/gfxboot/gfxboot.c +++ /dev/null @@ -1,960 +0,0 @@ -/* - * - * gfxboot.c - * - * A com32 module to load gfxboot graphics. - * - * Copyright (c) 2009 Steffen Winterfeldt. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation, Inc., 53 Temple Place Ste 330, Boston MA - * 02111-1307, USA; either version 2 of the License, or (at your option) any - * later version; incorporated herein by reference. - * - */ - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <string.h> -#include <fcntl.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <minmax.h> - -#include <syslinux/loadfile.h> -#include <syslinux/config.h> -#include <syslinux/linux.h> -#include <syslinux/boot.h> -#include <console.h> -#include <com32.h> - - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -#define MAX_CONFIG_LINE_LEN 2048 -#define MAX_CMDLINE_LEN 2048 - -// buffer for realmode callback -// must be at least block size; can in theory be larger than 4k, but there's -// not enough space left -#define REALMODE_BUF_SIZE 4096 - -// gfxboot working memory in MB -#define GFX_MEMORY_SIZE 7 - -// read chunk size for progress bar -#define CHUNK_SIZE (64 << 10) - -// callback function numbers -#define GFX_CB_INIT 0 -#define GFX_CB_DONE 1 -#define GFX_CB_INPUT 2 -#define GFX_CB_MENU_INIT 3 -#define GFX_CB_INFOBOX_INIT 4 -#define GFX_CB_INFOBOX_DONE 5 -#define GFX_CB_PROGRESS_INIT 6 -#define GFX_CB_PROGRESS_DONE 7 -#define GFX_CB_PROGRESS_UPDATE 8 -#define GFX_CB_PROGRESS_LIMIT 9 // unused -#define GFX_CB_PASSWORD_INIT 10 -#define GFX_CB_PASSWORD_DONE 11 - -// real mode code chunk, will be placed into bounce buffer -extern void realmode_callback_start, realmode_callback_end; - -// gets in the way -#undef linux - - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// gfxboot config data (64 bytes) -typedef struct __attribute__ ((packed)) { - uint8_t bootloader; // 0: boot loader type (0: lilo, 1: syslinux, 2: grub) - uint8_t sector_shift; // 1: sector shift - uint8_t media_type; // 2: media type (0: disk, 1: floppy, 2: cdrom) - uint8_t failsafe; // 3: turn on failsafe mode (bitmask) - // 0: SHIFT pressed - // 1: skip gfxboot - // 2: skip monitor detection - uint8_t sysconfig_size; // 4: size of sysconfig data - uint8_t boot_drive; // 5: BIOS boot drive - uint16_t callback; // 6: offset to callback handler - uint16_t bootloader_seg; // 8: code/data segment used by bootloader; must follow gfx_callback - uint16_t serial_port; // 10: syslinux initialized serial port from 'serial' option - uint32_t user_info_0; // 12: data for info box - uint32_t user_info_1; // 16: data for info box - uint32_t bios_mem_size; // 20: BIOS memory size (in bytes) - uint16_t xmem_0; // 24: extended mem area 0 (start:size in MB; 12:4 bits) - obsolete - uint16_t xmem_1; // 26: extended mem area 1 - obsolete - uint16_t xmem_2; // 28: extended mem area 2 - obsolete - uint16_t xmem_3; // 30: extended mem area 3 - obsolete - uint32_t file; // 32: start of gfx file - uint32_t archive_start; // 36: start of cpio archive - uint32_t archive_end; // 40: end of cpio archive - uint32_t mem0_start; // 44: low free memory start - uint32_t mem0_end; // 48: low free memory end - uint32_t xmem_start; // 52: extended mem start - uint32_t xmem_end; // 56: extended mem end - uint16_t features; // 60: feature flags returned by GFX_CB_INIT - // 0: GFX_CB_MENU_INIT accepts 32 bit addresses - // 1: knows about xmem_start, xmem_end - uint16_t reserved_1; // 62: -} gfx_config_t; - - -// gfxboot menu description (18 bytes) -typedef struct __attribute__ ((packed)) { - uint16_t entries; - char *default_entry; - char *label_list; - uint16_t label_size; - char *arg_list; - uint16_t arg_size; -} gfx_menu_t; - - -// menu description -typedef struct menu_s { - struct menu_s *next; - char *label; // config entry name - char *menu_label; // text to show in boot menu - char *kernel; // name of program to load - char *alt_kernel; // alternative name in case user has replaced it - char *linux; // de facto an alias for 'kernel' - char *localboot; // boot from local disk - char *initrd; // initrd as separate line (instead of as part of 'append') - char *append; // kernel args - char *ipappend; // append special pxelinux args (see doc) -} menu_t; - - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -gfx_config_t gfx_config; -gfx_menu_t gfx_menu; - -menu_t *menu; -menu_t *menu_default; -static menu_t *menu_ptr, **menu_next; - -struct { - uint32_t jmp_table[12]; - uint16_t code_seg; - char fname_buf[64]; -} gfx; - -void *lowmem_buf; -unsigned lowmem_buf_size; - -int timeout; - -char cmdline[MAX_CMDLINE_LEN]; - -void *save_buf; -unsigned save_buf_size; - -// progress bar is visible -unsigned progress_active; - - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void show_message(char *file); -char *get_config_file_name(void); -char *skip_spaces(char *s); -char *skip_nonspaces(char *s); -void chop_line(char *s); -int read_config_file(const char *filename); -unsigned magic_ok(unsigned char *buf, unsigned *code_size); -unsigned find_file(unsigned char *buf, unsigned len, unsigned *gfx_file_start, unsigned *file_len, unsigned *code_size); -int gfx_init(char *file); -int gfx_menu_init(void); -void gfx_done(void); -int gfx_input(void); -void gfx_infobox(int type, char *str1, char *str2); -void gfx_progress_init(ssize_t kernel_size, char *label); -void gfx_progress_update(ssize_t size); -void gfx_progress_done(void); -ssize_t save_read(int fd, void *buf, size_t size); -void *load_one(char *file, ssize_t *file_size); -void boot(int index); -void boot_entry(menu_t *menu_ptr, char *arg); - - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -int main(int argc, char **argv) -{ - int menu_index; - const union syslinux_derivative_info *sdi; - - openconsole(&dev_stdcon_r, &dev_stdcon_w); - - lowmem_buf = __com32.cs_bounce; - lowmem_buf_size = __com32.cs_bounce_size; - - sdi = syslinux_derivative_info(); - - gfx_config.sector_shift = sdi->disk.sector_shift; - gfx_config.boot_drive = sdi->disk.drive_number; - - if(sdi->c.filesystem == SYSLINUX_FS_PXELINUX) { - gfx_config.sector_shift = 11; - gfx_config.boot_drive = 0; - } - - gfx_config.media_type = gfx_config.boot_drive < 0x80 ? 1 : 0; - - if(sdi->c.filesystem == SYSLINUX_FS_ISOLINUX) { - gfx_config.media_type = sdi->iso.cd_mode ? 0 : 2; - } - - gfx_config.bootloader = 1; - gfx_config.sysconfig_size = sizeof gfx_config; - gfx_config.bootloader_seg = 0; // apparently not needed - - save_buf_size = lowmem_buf_size; - save_buf = malloc(save_buf_size); - - if(argc < 2) { - printf("Usage: gfxboot.c32 bootlogo_file [message_file]\n"); - if(argc > 2) show_message(argv[2]); - - return 0; - } - - if(read_config_file("~")) { - printf("Error reading config file\n"); - if(argc > 2) show_message(argv[2]); - - return 0; - } - - if(gfx_init(argv[1])) { - printf("Error setting up gfxboot\n"); - if(argc > 2) show_message(argv[2]); - - return 0; - } - - gfx_menu_init(); - - for(;;) { - menu_index = gfx_input(); - - // abort gfx, return to text mode prompt - if(menu_index == -1) { - gfx_done(); - break; - } - - // does not return if it succeeds - boot(menu_index); - } - - if(argc > 2) show_message(argv[2]); - - return 0; -} - - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void show_message(char *file) -{ - int c; - FILE *f; - - if(!(f = fopen(file, "r"))) return; - - while((c = getc(f)) != EOF) { - if(c < ' ' && c != '\n' && c != '\t') continue; - printf("%c", c); - } - - fclose(f); -} - - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -char *skip_spaces(char *s) -{ - while(*s && (*s == ' ' || *s == '\t')) s++; - - return s; -} - - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -char *skip_nonspaces(char *s) -{ - while(*s && *s != ' ' && *s != '\t') s++; - - return s; -} - - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void chop_line(char *s) -{ - int i = strlen(s); - - if(!i) return; - - while(--i >= 0) { - if(s[i] == ' ' || s[i] == '\t' || s[i] == '\n') { - s[i] = 0; - } - else { - break; - } - } -} - - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// Read and parse syslinux config file. -// -// return: -// 0: ok, 1: error -// -int read_config_file(const char *filename) -{ - FILE *f; - char *s, *t, buf[MAX_CONFIG_LINE_LEN]; - unsigned u, top_level = 0; - - if(!strcmp(filename, "~")) { - top_level = 1; - filename = syslinux_config_file(); - gfx_menu.entries = 0; - gfx_menu.label_size = 0; - gfx_menu.arg_size = 0; - menu_ptr = NULL; - menu_next = &menu; - menu_default = calloc(1, sizeof *menu_default); - } - - if(!(f = fopen(filename, "r"))) return 1; - - while((s = fgets(buf, sizeof buf, f))) { - chop_line(s); - s = skip_spaces(s); - if(!*s || *s == '#') continue; - t = skip_nonspaces(s); - if(*t) *t++ = 0; - t = skip_spaces(t); - - if(!strcasecmp(s, "timeout")) { - timeout = atoi(t); - continue; - } - - if(!strcasecmp(s, "default")) { - menu_default->label = strdup(t); - u = strlen(t); - if(u > gfx_menu.label_size) gfx_menu.label_size = u; - continue; - } - - if(!strcasecmp(s, "label")) { - menu_ptr = *menu_next = calloc(1, sizeof **menu_next); - menu_next = &menu_ptr->next; - gfx_menu.entries++; - menu_ptr->label = menu_ptr->menu_label = strdup(t); - u = strlen(t); - if(u > gfx_menu.label_size) gfx_menu.label_size = u; - continue; - } - - if(!strcasecmp(s, "kernel") && menu_ptr) { - menu_ptr->kernel = strdup(t); - continue; - } - - if(!strcasecmp(s, "linux") && menu_ptr) { - menu_ptr->linux = strdup(t); - continue; - } - - if(!strcasecmp(s, "localboot") && menu_ptr) { - menu_ptr->localboot = strdup(t); - continue; - } - - if(!strcasecmp(s, "initrd") && menu_ptr) { - menu_ptr->initrd = strdup(t); - continue; - } - - if(!strcasecmp(s, "append")) { - (menu_ptr ?: menu_default)->append = strdup(t); - u = strlen(t); - if(u > gfx_menu.arg_size) gfx_menu.arg_size = u; - continue; - } - - if(!strcasecmp(s, "ipappend")) { - (menu_ptr ?: menu_default)->ipappend = strdup(t); - continue; - } - - if(!strcasecmp(s, "menu") && menu_ptr) { - s = skip_spaces(t); - t = skip_nonspaces(s); - if(*t) *t++ = 0; - t = skip_spaces(t); - - if(!strcasecmp(s, "label")) { - menu_ptr->menu_label = strdup(t); - u = strlen(t); - if(u > gfx_menu.label_size) gfx_menu.label_size = u; - continue; - } - - if(!strcasecmp(s, "include")) { - goto do_include; - } - } - - if (!strcasecmp(s, "include")) { -do_include: - s = t; - t = skip_nonspaces(s); - if (*t) *t = 0; - read_config_file(s); - } - } - - fclose(f); - - if (!top_level) - return 0; - - // final '\0' - gfx_menu.label_size++; - gfx_menu.arg_size++; - - // ensure we have a default entry - if(!menu_default->label) menu_default->label = menu->label; - - if(menu_default->label) { - for(menu_ptr = menu; menu_ptr; menu_ptr = menu_ptr->next) { - if(!strcmp(menu_default->label, menu_ptr->label)) { - menu_default->menu_label = menu_ptr->menu_label; - break; - } - } - } - - gfx_menu.default_entry = menu_default->menu_label; - gfx_menu.label_list = calloc(gfx_menu.entries, gfx_menu.label_size); - gfx_menu.arg_list = calloc(gfx_menu.entries, gfx_menu.arg_size); - - for(u = 0, menu_ptr = menu; menu_ptr; menu_ptr = menu_ptr->next, u++) { - if(!menu_ptr->append) menu_ptr->append = menu_default->append; - if(!menu_ptr->ipappend) menu_ptr->ipappend = menu_default->ipappend; - - if(menu_ptr->menu_label) strcpy(gfx_menu.label_list + u * gfx_menu.label_size, menu_ptr->menu_label); - if(menu_ptr->append) strcpy(gfx_menu.arg_list + u * gfx_menu.arg_size, menu_ptr->append); - } - - return 0; -} - - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// Check header and return code start offset. -// -unsigned magic_ok(unsigned char *buf, unsigned *code_size) -{ - if( - *(unsigned *) buf == 0x0b2d97f00 && // magic id - (buf[4] == 8) // version 8 - ) { - *code_size = *(unsigned *) (buf + 12); - return *(unsigned *) (buf + 8); - } - - return 0; -} - - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// Search (cpio archive) for gfx file. -// -unsigned find_file(unsigned char *buf, unsigned len, unsigned *gfx_file_start, unsigned *file_len, unsigned *code_size) -{ - unsigned i, fname_len, code_start = 0; - - *gfx_file_start = 0; - *code_size = 0; - - if((code_start = magic_ok(buf, code_size))) return code_start; - - for(i = 0; i < len;) { - if((len - i) >= 0x1a && (buf[i] + (buf[i + 1] << 8)) == 0x71c7) { - fname_len = *(unsigned short *) (buf + i + 20); - *file_len = *(unsigned short *) (buf + i + 24) + (*(unsigned short *) (buf + i + 22) << 16); - i += 26 + fname_len; - i = ((i + 1) & ~1); - if((code_start = magic_ok(buf + i, code_size))) { - *gfx_file_start = i; - return code_start; - } - i += *file_len; - i = ((i + 1) & ~1); - } - else { - break; - } - } - - return code_start; -} - - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// Initialize gfxboot code. -// -// return: -// 0: ok, 1: error -// -int gfx_init(char *file) -{ - size_t archive_size = 0; - void *archive; - unsigned code_start, code_size, file_start, file_len, u; - com32sys_t r; - void *lowmem = lowmem_buf; - unsigned lowmem_size = lowmem_buf_size; - - progress_active = 0; - - printf("Loading %s...\n", file); - if(loadfile(file, &archive, &archive_size)) return 1; - - if(!archive_size) return 1; - - // printf("%s: %d\n", file, archive_size); - - gfx_config.archive_start = (uint32_t) archive; - gfx_config.archive_end = gfx_config.archive_start + archive_size; - - // locate file inside cpio archive - if(!(code_start = find_file(archive, archive_size, &file_start, &file_len, &code_size))) { - printf("%s: invalid file format\n", file); - return 1; - } - -#if 0 - printf( - "code_start = 0x%x, code_size = 0x%x\n" - "archive_start = 0x%x, archive size = 0x%x\n" - "file_start = 0x%x, file_len = 0x%x\n", - code_start, code_size, - gfx_config.archive_start, archive_size, - file_start, file_len - ); -#endif - - gfx_config.file = gfx_config.archive_start + file_start; - - u = &realmode_callback_end - &realmode_callback_start; - u = (u + REALMODE_BUF_SIZE + 0xf) & ~0xf; - - if(u + code_size > lowmem_size) { - printf("bounce buffer too small: size %u, needed %u\n", lowmem_size, u + code_size); - return 1; - } - - memcpy(lowmem + REALMODE_BUF_SIZE, &realmode_callback_start, &realmode_callback_end - &realmode_callback_start); - - // fill in buffer size and location - *(uint16_t *) (lowmem + REALMODE_BUF_SIZE) = REALMODE_BUF_SIZE; - *(uint16_t *) (lowmem + REALMODE_BUF_SIZE + 2) = (uint32_t) lowmem >> 4; - - gfx_config.bootloader_seg = ((uint32_t) lowmem + REALMODE_BUF_SIZE) >> 4; - gfx_config.callback = 4; // start address - - lowmem += u; - lowmem_size -= u; - - memcpy(lowmem, archive + file_start + code_start, code_size); - - gfx_config.mem0_start = (uint32_t) lowmem + code_size; - gfx_config.mem0_end = (uint32_t) lowmem + lowmem_size; - // align a bit - gfx_config.mem0_start = (gfx_config.mem0_start + 0xf) & ~0xf; - - gfx_config.xmem_start = (uint32_t) malloc(GFX_MEMORY_SIZE << 20); - if(gfx_config.xmem_start) { - gfx_config.xmem_end = gfx_config.xmem_start + (GFX_MEMORY_SIZE << 20); - } - - // fake; not used anyway - gfx_config.bios_mem_size = 256 << 20; - - gfx.code_seg = (uint32_t) lowmem >> 4; - - for(u = 0; u < sizeof gfx.jmp_table / sizeof *gfx.jmp_table; u++) { - gfx.jmp_table[u] = (gfx.code_seg << 16) + *(uint16_t *) (lowmem + 2 * u); - } - -#if 0 - for(u = 0; u < sizeof gfx.jmp_table / sizeof *gfx.jmp_table; u++) { - printf("%d: 0x%08x\n", u, gfx.jmp_table[u]); - } -#endif - - // we are ready to start - - r.esi.l = (uint32_t) &gfx_config; - __farcall(gfx.code_seg, gfx.jmp_table[GFX_CB_INIT], &r, &r); - - if((r.eflags.l & EFLAGS_CF)) { - printf("graphics initialization failed\n"); - - return 1; - } - - if((gfx_config.features & 3) != 3) { - gfx_done(); - - printf("%s: boot graphics code too old, please use newer version\n", file); - - return 1; - } - - - return 0; -} - - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -int gfx_menu_init(void) -{ - com32sys_t r; - - r.esi.l = (uint32_t) &gfx_menu; - __farcall(gfx.code_seg, gfx.jmp_table[GFX_CB_MENU_INIT], &r, &r); - - return 0; -} - - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void gfx_done(void) -{ - com32sys_t r; - - gfx_progress_done(); - - __farcall(gfx.code_seg, gfx.jmp_table[GFX_CB_DONE], &r, &r); -} - - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// Run gfxboot main loop. -// -// return: -// boot menu index (-1: go to text mode prompt) -// -int gfx_input(void) -{ - com32sys_t r; - - r.edi.l = (uint32_t) cmdline; - r.ecx.l = sizeof cmdline; - r.eax.l = timeout * 182 / 100; - timeout = 0; // use timeout only first time - __farcall(gfx.code_seg, gfx.jmp_table[GFX_CB_INPUT], &r, &r); - if((r.eflags.l & EFLAGS_CF)) r.eax.l = 1; - - if(r.eax.l == 1) return -1; - - return r.ebx.l; -} - - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void gfx_infobox(int type, char *str1, char *str2) -{ - com32sys_t r; - - r.eax.l = type; - r.esi.l = (uint32_t) str1; - r.edi.l = (uint32_t) str2; - __farcall(gfx.code_seg, gfx.jmp_table[GFX_CB_INFOBOX_INIT], &r, &r); - r.edi.l = r.eax.l = 0; - __farcall(gfx.code_seg, gfx.jmp_table[GFX_CB_INPUT], &r, &r); - __farcall(gfx.code_seg, gfx.jmp_table[GFX_CB_INFOBOX_DONE], &r, &r); -} - - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void gfx_progress_init(ssize_t kernel_size, char *label) -{ - com32sys_t r; - - if(!progress_active) { - r.eax.l = kernel_size >> gfx_config.sector_shift; // in sectors - r.esi.l = (uint32_t) label; - __farcall(gfx.code_seg, gfx.jmp_table[GFX_CB_PROGRESS_INIT], &r, &r); - } - - progress_active = 1; -} - - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void gfx_progress_update(ssize_t advance) -{ - com32sys_t r; - - if(progress_active) { - r.eax.l = advance >> gfx_config.sector_shift; // in sectors - __farcall(gfx.code_seg, gfx.jmp_table[GFX_CB_PROGRESS_UPDATE], &r, &r); - } -} - - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void gfx_progress_done(void) -{ - com32sys_t r; - - if(progress_active) { - __farcall(gfx.code_seg, gfx.jmp_table[GFX_CB_PROGRESS_DONE], &r, &r); - } - - progress_active = 0; -} - - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// Like read(2) but preserve bounce buffer. -// -ssize_t save_read(int fd, void *buf, size_t size) -{ - ssize_t i; - - memcpy(save_buf, lowmem_buf, save_buf_size); - i = read(fd, buf, size); - memcpy(lowmem_buf, save_buf, save_buf_size); - - return i; -} - - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// Read file and update progress bar. -// -void *load_one(char *file, ssize_t *file_size) -{ - int fd; - void *buf = NULL; - char *str; - struct stat sbuf; - ssize_t size = 0, cur, i; - - *file_size = 0; - - if((fd = open(file, O_RDONLY)) == -1) { - asprintf(&str, "%s: file not found", file); - gfx_infobox(0, str, NULL); - free(str); - return buf; - } - - if(!fstat(fd, &sbuf) && S_ISREG(sbuf.st_mode)) size = sbuf.st_size; - - i = 0; - - if(size) { - buf = malloc(size); - for(i = 1, cur = 0 ; cur < size && i > 0; cur += i) { - i = save_read(fd, buf + cur, min(CHUNK_SIZE, size - cur)); - if(i == -1) break; - gfx_progress_update(i); - } - } - else { - do { - buf = realloc(buf, size + CHUNK_SIZE); - i = save_read(fd, buf + size, CHUNK_SIZE); - if(i == -1) break; - size += i; - gfx_progress_update(i); - } while(i > 0); - } - - close(fd); - - if(i == -1) { - asprintf(&str, "%s: read error @ %d", file, size); - gfx_infobox(0, str, NULL); - free(str); - free(buf); - buf = NULL; - size = 0; - } - - *file_size = size; - - return buf; -} - - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// Boot menu entry. -// -// cmdline can optionally start with label string. -// -void boot(int index) -{ - char *arg, *alt_kernel; - menu_t *menu_ptr; - int i, label_len; - unsigned ipapp; - const struct syslinux_ipappend_strings *ipappend; - - for(menu_ptr = menu; menu_ptr; menu_ptr = menu_ptr->next, index--) { - if(!index) break; - } - - // invalid index or menu entry - if(!menu_ptr || !menu_ptr->menu_label) return; - - arg = skip_spaces(cmdline); - label_len = strlen(menu_ptr->menu_label); - - // if it does not start with label string, assume first word is kernel name - if(strncmp(arg, menu_ptr->menu_label, label_len)) { - alt_kernel = arg; - arg = skip_nonspaces(arg); - if(*arg) *arg++ = 0; - if(*alt_kernel) menu_ptr->alt_kernel = alt_kernel; - } - else { - arg += label_len; - } - - arg = skip_spaces(arg); - - // handle IPAPPEND - if(menu_ptr->ipappend && (ipapp = atoi(menu_ptr->ipappend))) { - ipappend = syslinux_ipappend_strings(); - for(i = 0; i < ipappend->count; i++) { - if((ipapp & (1 << i)) && ipappend->ptr[i]) { - sprintf(arg + strlen(arg), " %s", ipappend->ptr[i]); - } - } - } - - boot_entry(menu_ptr, arg); - - gfx_progress_done(); -} - - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// Load & run kernel. -// -// Returns only on error. -// -void boot_entry(menu_t *menu_ptr, char *arg) -{ - void *kernel, *initrd_buf; - ssize_t kernel_size = 0, initrd_size = 0; - struct initramfs *initrd = NULL; - char *file, *cmd_buf; - int fd; - struct stat sbuf; - char *s, *s0, *t, *initrd_arg; - - if(!menu_ptr) return; - - if(menu_ptr->localboot) { - gfx_done(); - syslinux_local_boot(strtol(menu_ptr->localboot, NULL, 0)); - - return; - } - - file = menu_ptr->alt_kernel; - if(!file) file = menu_ptr->kernel; - if(!file) file = menu_ptr->linux; - if(!file) { - gfx_done(); - asprintf(&cmd_buf, "%s %s", menu_ptr->label, arg); - syslinux_run_command(cmd_buf); - return; - } - - // first, load kernel - - kernel_size = 0; - - if((fd = open(file, O_RDONLY)) >= 0) { - if(!fstat(fd, &sbuf) && S_ISREG(sbuf.st_mode)) kernel_size = sbuf.st_size; - close(fd); - } - - gfx_progress_init(kernel_size, file); - - kernel = load_one(file, &kernel_size); - - if(!kernel) { - return; - } - - if(kernel_size < 1024 || *(uint32_t *) (kernel + 0x202) != 0x53726448) { - // not a linux kernel - gfx_done(); - asprintf(&cmd_buf, "%s %s", menu_ptr->label, arg); - syslinux_run_command(cmd_buf); - return; - } - - // printf("kernel = %p, size = %d\n", kernel, kernel_size); - - // parse cmdline for "initrd" option - - initrd_arg = menu_ptr->initrd; - - s = s0 = strdup(arg); - - while(*s && strncmp(s, "initrd=", sizeof "initrd=" - 1)) { - s = skip_spaces(skip_nonspaces(s)); - } - - if(*s) { - s += sizeof "initrd=" - 1; - *skip_nonspaces(s) = 0; - initrd_arg = s; - } - - if(initrd_arg) { - initrd = initramfs_init(); - - while((t = strsep(&s, ","))) { - initrd_buf = load_one(t, &initrd_size); - - if(!initrd_buf) { - printf("%s: read error\n", t); - free(s0); - return; - } - - initramfs_add_data(initrd, initrd_buf, initrd_size, initrd_size, 4); - - // printf("initrd = %p, size = %d\n", initrd_buf, initrd_size); - } - } - - free(s0); - - gfx_done(); - - syslinux_boot_linux(kernel, kernel_size, initrd, arg); -} - - |