summaryrefslogtreecommitdiffstats
path: root/contrib/syslinux/latest/com32/gfxboot/gfxboot.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/syslinux/latest/com32/gfxboot/gfxboot.c')
-rw-r--r--contrib/syslinux/latest/com32/gfxboot/gfxboot.c960
1 files changed, 0 insertions, 960 deletions
diff --git a/contrib/syslinux/latest/com32/gfxboot/gfxboot.c b/contrib/syslinux/latest/com32/gfxboot/gfxboot.c
deleted file mode 100644
index 2323f8e..0000000
--- a/contrib/syslinux/latest/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);
-}
-
-