/* Second stage boot loader Copyright (C) 1996 Pete A. Zaitcev 1996 Maurizio Plaza 1996 David S. Miller 1996 Miguel de Icaza 1996 Jakub Jelinek 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; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "silo.h" #include /* This has to be first initialized variable in main.c */ extern char silo_conf[256]; extern char silo_conf_part; extern int start; int useconf = 0; struct linux_nodeops *prom_nodeops; int prom_root_node; struct linux_romvec *romvec; enum arch architecture; static int timer_status = 0; static char *initrd_start; static int initrd_size; static int initrd_defpart; static char *initrd_defdevice; static char *initrd_string; static int initrd_prompt; static int pause_after; static char *pause_message = "Press ENTER to continue."; static int show_arguments = 0; static char given_bootargs [512]; static int given_bootargs_by_user = 0; static char sol_params [512]; static int fill_reboot_cmd = 0; static char other_device [512]; int other_part = -1; int solaris = 0; int other = 0; char *password = 0; void maintabfunc (void) { cfg_print_images (); printf ("boot: %s", cbuff); } void parse_name (char *imagename, int defpart, char **device, int *part, char **kname) { static char parsebuf[1024]; strcpy (parsebuf, imagename); imagename = parsebuf; *device = 0; *kname = 0; if (!strncmp (imagename, "!cd", 3)) { *kname = imagename; *part = 0; return; } if (romvec->pv_romvers < 2) { static char v0_buffer[20]; *kname = v0_device (imagename); if (*kname) { memcpy (v0_buffer, imagename, *kname - imagename + 1); v0_buffer [*kname - imagename + 1] = 0; (*kname)++; *device = v0_buffer; } else *kname = imagename; } else { *kname = strchr (imagename, ';'); if (!*kname) *kname = imagename; else { **kname = 0; (*kname)++; *device = imagename; } } /* Range */ if (**kname >= '0' && **kname <= '8' && (*kname)[1] == '[') { *part = **kname - '0'; (*kname)++; return; } if (**kname == '[') { *part = 0; return; } /* Path */ if (**kname >= '1' && **kname <= '8') { if ((*kname)[1] == '/' || !(*kname)[1]) { *part = **kname - '0'; if (!(*kname)[1]) { *kname = 0; } else (*kname)++; } } else if (**kname == '/') { if (defpart != -2) { if (defpart != -1) *part = defpart; else *part = 1; } } else *kname = 0; } void check_initrd (char *label, int defpart, char *defdevice) { char *p; initrd_string = cfg_get_strg (label, "initrd"); if (initrd_string) { initrd_defpart = defpart; initrd_defdevice = defdevice; initrd_size = 0; p = cfg_get_strg (label, "initrd-size"); if (p) initrd_size = atoi (p); initrd_prompt = cfg_get_flag (label, "initrd-prompt"); } } void dig_into_params (char *params) { char *p, *q; char *last_root = 0; p = params; for (;;) { while (*p == ' ') p++; if (!*p) break; if (!strncmp (p, "initrd", 6)) { p += 6; if (*p == '=') { for (q = p++; *q && *q != ' '; q++); if (p != q) { initrd_string = malloc (q - p + 1); memcpy (initrd_string, p, q - p); initrd_string [q - p] = 0; memset (p - 7, ' ', q - p + 7); } } else if (!strncmp (p, "-prompt", 7)) { initrd_prompt = 1; memset (p - 6, ' ', 7 + 6); } else if (!strncmp (p, "-size=", 6)) { int i; p += 6; i = atoi (p); if (i > 0) { initrd_size = i; for (q = p; *q >= '0' && *q <= '9'; q++); memset (p - 12, ' ', q - p + 12); } } } else if (!strncmp (p, "pause-after", 11)) { pause_after = 1; memset (p, ' ', 11); } else if (!strncmp (p, "show-arguments", 14)) { show_arguments = 1; memset (p, ' ', 14); } else if (!strncmp (p, "root=", 5)) { if (last_root) { while (*last_root != ' ') *last_root++ = ' '; } last_root = p; } while (*p && *p != ' ') p++; } } void halt (struct linux_romvec *promvec) { close (); if (timer_status >= 1) close_timer (promvec); (*promvec->pv_halt) (); } void check_password(char *str) { int i; for (i = 0; i < 3; i++) { printf ("\n%sassword: ", str); passwdbuff[0] = 0; cmdedit ((void (*)(void)) 0, 1); printf ("\n"); if (!strncmp (password, passwdbuff)) return; if (i < 2) printf ("Wrong password. Please try again..."); } printf ("Seems like you don't know the access password...\n"); halt(romvec); } int get_params (struct linux_romvec *promvec, char **device, int *part, char **kname, char **params) { int defpart = -1; char *defdevice = 0; char *p, *q; int c; char *imagename = 0, *label = 0; int timeout = -1, beg = 0, end; static char buffer[2048], buffer2[2048]; static int first = 1; int from_prom = 0; int from_siloconf = 0; static int no_prom_args = 0; int tabbedout = 0; char *bootblock = 0; other = 0; fill_reboot_cmd = 0; solaris = 0; initrd_string = 0; pause_after = 0; cmdinit (); *params = ""; if (useconf) { defdevice = cfg_get_strg (0, "device"); p = cfg_get_strg (0, "partition"); if (p && *p >= '1' && *p <= '8' && !p[1]) defpart = *p - '0'; if (first) { first = 0; p = cfg_get_strg (0, "timeout"); if (p && *p) timeout = atoi (p); if (no_prom_args) p = 0; else p = get_bootargs (promvec, 0); if (p) while (*p == ' ') p++; if (p && *p) { for (q = p; *q && *q != ' '; q++); if (*q == ' ') { *q++ = 0; while (*q == ' ') q++; if (*q) *params = q; } imagename = p; from_prom = 1; printf ("\n"); } else if (!timeout) { printf ("boot: "); c = nbgetchar (promvec); if (c != -1 && c != '\n' && c != '\r') { if (c == '\t') { maintabfunc (); tabbedout = 1; } else if (c >= ' ') { cbuff[0] = c; cbuff[1] = 0; } } else { imagename = cfg_get_default (); printf ("\n"); } } else if (timeout != -1) { if (!timer_status) { if (!init_timer (promvec)) timer_status = 1; else timer_status = -1; } else timer_status++; if (timer_status <= 0) { printf ("\nYour timeout %d.%ds will never expire, since counter couldn't" "\nbe initialized\nboot: ", timeout/10, timeout % 10); } else { printf ("boot: "); reset_ticks (); c = nbgetchar (promvec); if (c == -1) { beg = get_ticks (); end = beg + 10 * timeout; do { c = nbgetchar (promvec); if (c != -1) break; } while (get_ticks () <= end); } if (c != -1 && c != '\n' && c != '\r') { if (c == '\t') { maintabfunc (); tabbedout = 1; } else if (c >= ' ') { cbuff[0] = c; cbuff[1] = 0; } } else { imagename = cfg_get_default (); printf ("\n"); } if (timer_status >= 1) { timer_status--; close_timer (promvec); } } } } if (!imagename) { if ((!*cbuff || (timeout > 0 && timer_status < 0)) && !tabbedout) printf ("boot: "); cmdedit (maintabfunc, 0); strcpy (given_bootargs, cbuff); given_bootargs_by_user = 1; printf ("\n"); if (!*cbuff) imagename = cfg_get_default (); else { p = strchr (cbuff, ' '); if (!p) *params = ""; else { *p++ = 0; while (*p && *p <= ' ') p++; *params = p; } imagename = cbuff; } } p = cfg_get_strg (imagename, "image"); if (p && *p) { label = imagename; imagename = p; } else label = 0; p = cfg_get_strg (0, "pause-message"); if (p) pause_message = p; if (label) { if (**params && password) check_password ("To specify image arguments you need to enter p"); from_siloconf = 1; defdevice = cfg_get_strg (label, "device"); p = cfg_get_strg (label, "partition"); if (p && *p >= '1' && *p <= '8' && !p[1]) defpart = *p - '0'; *buffer = 0; q = buffer; if (cfg_get_flag (label, "fill-reboot-cmd")) fill_reboot_cmd = 1; if (cfg_get_strg (label, "other")) other = 1; else if (cfg_get_flag (label, "solaris")) solaris = 1; p = cfg_get_strg (label, "literal"); if (!p && other) p = cfg_get_strg (label, "append"); if (p) { strcpy (q, p); q = strchr (q, 0); if (**params) { if (*p) *q++ = ' '; strcpy (q, *params); } } else if (!solaris && !other) { p = cfg_get_strg (label, "root"); if (p) { strcpy (q, "root="); strcpy (q + 5, p); q = strchr (q, 0); *q++ = ' '; } if (cfg_get_flag (label, "read-only")) { strcpy (q, "ro "); q += 3; } if (cfg_get_flag (label, "read-write")) { strcpy (q, "rw "); q += 3; } p = cfg_get_strg (label, "ramdisk"); if (p) { strcpy (q, "ramdisk="); strcpy (q + 8, p); q = strchr (q, 0); *q++ = ' '; } p = cfg_get_strg (label, "append"); if (p) { strcpy (q, p); q = strchr (q, 0); *q++ = ' '; } check_initrd (label, defpart, defdevice); if (**params) strcpy (q, *params); } if (other) { char *oth_device = 0; char *oth_kname = 0; other_part = -1; parse_name (imagename, -1, &oth_device, &other_part, &oth_kname); if (other_part == -1 || oth_kname) { printf ("Wrong syntax for other= parameter. The parameter should be\n"); if (romvec->pv_romvers < 2) printf ("either a single number 1-8 (ie. partition of the current disk)\n" "or sd(X,Y,Z)N (ie. some other disk plus partition number)\n" "e.g. sd(0,3,2)4\n"); else printf ("either a single number 1-8 (ie. partition of the current disk)\n" "or /prom/path/name;N (ie. some other disk plus partition number)\n" "e.g. /iommu/sbus/espdma/esp/sd@3,0;3 \n"); *kname = 0; return 0; } if (!oth_device) { if (defdevice) oth_device = defdevice; else oth_device = bootdevice; } strcpy (other_device, oth_device); p = cfg_get_strg (label, "bootblock"); if (p) imagename = p; else { static char bufx[8]; strcpy (bufx, "x[1-16]"); *bufx = other_part + '0'; defdevice = other_device; defpart = other_part; } } pause_after = cfg_get_flag (label, "pause-after"); p = cfg_get_strg (label, "pause-message"); if (p) pause_message = p; *params = buffer; } } else { if (first) { first = 0; if (no_prom_args) p = 0; else p = get_bootargs (promvec, 0); if (p) while (*p == ' ') p++; if (p && *p) { for (q = p; *q && *q != ' '; q++); if (*q == ' ') { *q++ = 0; while (*q == ' ') q++; if (*q) *params = q; } imagename = p; from_prom = 1; printf ("\n"); } } if (!imagename) { printf ("boot: "); cmdedit ((void (*)(void)) 0, 0); strcpy (given_bootargs, cbuff); given_bootargs_by_user = 1; printf ("\n"); p = strchr (cbuff, ' '); if (!p) *params = ""; else { *p = 0; p++; while (*p && *p <= ' ') p++; *params = p; } imagename = cbuff; } } if (!strcmp (imagename, "halt")) return 1; if (!label && password) check_password ("To boot a custom image you need to type here your p"); if (!strcmp (imagename, "xxdebug")) return 2; if (!strcmp (imagename, "help")) { if (promvec->pv_romvers < 2) printf ("You have to type image name as {XY(...)}partno/path or {XY(...)}partno[mm-nn],\n" "where XY(...) is the optional v0 prom device name (if partition number is specified,\n" "it should be Sun partition number (zero based) of any partition starting at cyl. 0)\n" "({} means that it is optional) and partno is a Linux partition number from 1 to 8.\n" "You can specify a path into filesystem (ext2fs, ufs) - has to start with / - or\n" "[mm-nn] as range of phys. blocks (512B).\n"); else printf ("You have to type image name as [prom_path;]partno/path, where partno is a\n" "number from 1 to 8. If partno is not specified, either default from silo.conf\n" "(partition=X) or 1 will be used. Instead of /path you can type [mm-nn] to\n" "specify a range of phys. blocks (512B)\n"); printf ("If you use silo.conf and have some image= sections there, you can type\n" "its label or alias name instead of the above described image names.\n" "Pressing just enter will load default image with default arguments. Special\n" "image names `halt' and `help' can be used to fall back to PROM or display\n" "help. All three types of image names can be followed by additional arguments.\n" "Examples:\n"); if (promvec->pv_romvers < 2) printf (" /boot/vmlinux.gz root=/dev/sda4\n" " 2/boot/mykernel.gz root=/dev/sda2\n" " sd(0,6,2)5/boot/old.b\n" " sd(1,2,0)[1-16] root=/dev/sda4\n"); else printf (" /iommu/sbus/espdma/esp/sd@3,0;4/boot/vmlinux.gz root=/dev/sda4\n" " 1/boot/old.b\n" " /sbus/espdma/esp/sd@0,0;3[1-16] root=/dev/sda4\n"); printf (" linux root=/dev/sda4\n" " live\n"); *kname = 0; return 0; } strcpy (buffer2, imagename); *part = -2; parse_name (imagename, -2, device, part, kname); if (!*device) *device = defdevice; if (*kname && *part == -2) { if (defpart != -1) *part = defpart; else *part = 1; } if (!*kname) { if (*part != -2) { other_part = *part; if (!*device) strcpy (other_device, bootdevice); else strcpy (other_device, *device); p = strstr (*params, "bootblock="); if (p && (p == *params || p[-1] == ' ') && p[10] && p[10] != ' ') { char tmp[512], *q; q = tmp; p += 10; while (*p && *p != ' ') *q++ = *p++; *q = 0; parse_name (tmp, defpart, device, part, kname); if (*kname) { p = strstr (*params, "bootblock="); memset (p, ' ', q - tmp + 10); other = 1; return 0; } else { printf ("Syntax of your bootblock= parameter is wrong. Please see help\n"); } } else { other = 1; *kname = strdup ("[1-16]"); return 0; } } else { if (defpart != -1) *part = defpart; else *part = 1; } if (from_prom) { int options_node, len; int is_from_prom = 0; char *v = ""; char buffer3[2048]; if ((options_node = prom_searchsiblings (prom_getchild (prom_root_node), "options")) != 0) { if (promvec->pv_romvers >= 2) { prom_getstring (options_node, v = "boot-file", buffer3, 2048); len = prom_getproplen (options_node, v); if (len < 0) len = 0; buffer3[len] = 0; if (!strcmp (buffer3, *promvec->pv_v2bootargs.bootargs)) is_from_prom = 1; else { prom_getstring (options_node, v = "diag-file", buffer3, 2048); len = prom_getproplen (options_node, v); if (len < 0) len = 0; buffer3[len] = 0; if (!strcmp (buffer3, *promvec->pv_v2bootargs.bootargs)) is_from_prom = 1; } } else { prom_getstring (options_node, v = "boot-from", buffer3, 2048); len = prom_getproplen (options_node, v); if (len < 0) len = 0; buffer3[len] = 0; if (!strcmp (buffer3, ((*(promvec->pv_v0bootargs))->argv)[0])) is_from_prom = 1; } } if (is_from_prom) { first = 1; no_prom_args = 1; *given_bootargs = 0; given_bootargs_by_user = 1; printf ("You have `%s' string in your %s variable.\n" "This string doesn't contain valid arguments to SILO.\n" "Consider doing setenv %s. Anyway, SILO will continue as\n" "if there were no arguments in %s.\n", buffer3, v, v, v); return 0; } } printf ("Your imagename `%s' and arguments `%s' have either wrong syntax,\n" "or describe a label which is not present in silo.conf\n" "Type `help' at the boot: prompt if you need it and then try again.\n", buffer2, *params ? *params : ""); } else if (!solaris) { p = strstr (*params, "solaris"); if (p && (p == *params || p[-1] == ' ') && (!p[7] || p[7] == ' ')) { memset (p, ' ', 7); solaris = 1; } else if (!strcmp (*kname, "/kernel/unix")) solaris = 1; if (!fill_reboot_cmd) { p = strstr (*params, "fill-reboot-cmd"); if (p && (p == *params || p[-1] == ' ') && (!p[15] || p[15] == ' ')) { memset (p, ' ', 15); fill_reboot_cmd = 1; } } } return 0; } void initrd_lenfunc (int len, char **filebuffer, char **filelimit) { initrd_start = memory_find ((len + 16383) & ~16383); if (!initrd_start) { fatal ("You do not have enough continuous available memory for such initial ramdisk."); halt (romvec); } initrd_size = len; printf ("Loading initial ramdisk....\n"); *filebuffer = initrd_start; *filelimit = initrd_start + ((len + 16383) & ~16383); } /* Here we are launched */ int bootmain (struct linux_romvec *promvec) { unsigned off; int len, image_len; char *kname, *params, *device; int part; union { char *b; struct aout_hdr *a; Elf32_Ehdr *e; } hp; int isfile, fileok = 0; char *p; unsigned int ret_offset; char *params_device = 0; romvec = promvec; prom_nodeops = promvec->pv_nodeops; prom_root_node = prom_getsibling (0); get_idprom(); prom_ranges_init (); architecture = get_architecture (promvec); strcpy (given_bootargs, get_bootargs (promvec, 1)); printf (" "); if (diskinit (promvec) == -1) (*promvec->pv_halt) (); /* Here should be code #ifdef TFTP, that will handle loading of silo.conf via tftp and this code should be on the other side #ifndef TFTP */ if (*silo_conf && silo_conf_part >= 1 && silo_conf_part <= 8) { int len; solaris = 0; fileok = load_file (0, silo_conf_part, silo_conf, (unsigned char *) 0x4000, (unsigned char *) &start, &len, 1, 0); if (!fileok || (unsigned) len >= 65535) printf ("\nCouldn't load %s\n", silo_conf); else { if (!cfg_parse (silo_conf, (unsigned char *) 0x4000, len)) { char *p, *q; int len = 0; int defpart = -1; int i; p = cfg_get_strg (0, "message"); if (p) { q = cfg_get_strg (0, "partition"); if (q && *q >= '1' && *q <= '8' && !q[1]) defpart = *q - '0'; parse_name (p, defpart, &device, &part, &kname); if (kname) { if (!device) device = cfg_get_strg (0, "device"); solaris = 0; if (load_file (device, part, kname, (unsigned char *) 0x4000, (unsigned char *) &start, &len, 1, 0)) { *(unsigned char *) (0x4000 + len) = 0; printf ("\n"); print_message ((char *) 0x4000); } } } useconf = 1; password = cfg_get_strg (0, "password"); if (password && !cfg_get_flag (0, "restricted")) { check_password ("P"); password = 0; } } else { printf ("Syntax error in %s\nPlease check the file for obvious bugs, and if you think it is correct, get" "latest version of SILO. If problems still survive, contact the author\n", silo_conf); } } } else printf ("\n"); if (!useconf) printf ("No config file loaded, you can boot just from this command line\n" "Type [prompath;]part/path_to_image [parameters] on the prompt\n" "E.g. /iommu/sbus/espdma/esp/sd@3,0;4/vmlinux root=/dev/sda4\n" "or 2/vmlinux.live (to load vmlinux.live from 2nd partition of boot disk)\n"); isfile = 0; /* RC = 0 invalid file or not an executable */ while (!isfile) { switch (get_params (promvec, &device, &part, &kname, ¶ms)) { case 1: halt (promvec); case 2: (*promvec->pv_abort) (); continue; } if (!kname) continue; if (solaris) { char *p = seed_part_into_device ((!device || !*device) ? bootdevice : device, part); strcpy (sol_params, p); params_device = strchr (sol_params, 0) + 1; strcpy (params_device, kname); if (params && *params) { strcat (params_device, " "); strcat (params_device, params); } } fileok = load_file (device, part, kname, (unsigned char *) 0x4000, (unsigned char *) &start, &image_len, 1, 0); ret_offset = 0x4000; if (fileok) { /* By this point the first sector is loaded (and the rest of */ /* the kernel) so we check if it is an executable file, either */ /* an a.out or an elf binary */ hp.b = (char *) 0x4000; if (hp.a->magic == 0x01030107) { if (solaris) { printf ("\nYour Solaris `ufsboot' is not an ELF image. Try again.\n"); continue; } off = sizeof (struct aout_hdr); if (image_len > hp.a->ltext + hp.a->ldata) len = hp.a->ltext + hp.a->ldata; else len = image_len; isfile = 1; } else { Elf32_Phdr *p; if (hp.e->e_ident[EI_MAG0] == ELFMAG0 && hp.e->e_ident[EI_MAG1] == ELFMAG1 && hp.e->e_ident[EI_MAG2] == ELFMAG2 && hp.e->e_ident[EI_MAG3] == ELFMAG3) { unsigned int e_entry; if (hp.e->e_ident[EI_CLASS] != ELFCLASS32) { fatal ("Image is not a 32bit ELF"); halt (promvec); } if (hp.e->e_ident[EI_DATA] != ELFDATA2MSB) { fatal ("Image is not a MSB ELF"); halt (promvec); } p = (Elf32_Phdr *) (hp.b + hp.e->e_phoff); if (p->p_type != PT_LOAD) { fatal ("Cannot find a loadable segment in your ELF image"); halt (promvec); } if (solaris) { int i; for (i = 0; i < hp.e->e_phnum; i++, p++) { if (p->p_vaddr < 0x4000 + image_len || p->p_vaddr + p->p_memsz >= 0x280000) { fatal("Unable to handle your Solaris `ufsboot' bootloader."); halt (promvec); } memcpy ((char *)p->p_vaddr, (char *)(0x4000 + p->p_offset), p->p_filesz); if (p->p_filesz < p->p_memsz) memset ((char *)(p->p_vaddr + p->p_filesz), 0, p->p_memsz - p->p_filesz); } isfile = 1; ret_offset = hp.e->e_entry; } else { off = p->p_offset + hp.e->e_entry - p->p_vaddr; len = p->p_filesz; if (len > image_len) len = image_len; isfile = 1; } } else printf ("\nUnknown %s image format\n", kname); } } else printf ("\nImage not found.... try again\n"); } if (solaris) { params = params_device; params_device = sol_params; } else if (!other) { params_device = 0; memcpy ((unsigned char *) 0x4000, ((unsigned char *) 0x4000) + off, len); p = find_linux_HdrS (image_len); if (p) { if (fill_reboot_cmd && *(unsigned short *)(p + 8) >= 0x201) { /* ie. uses reboot_command */ char *q = (char *)(*(unsigned int *)(p + 24) - 0xF0000000), *r; extern char bootdevice[]; if (q >= (char *)0x4000 && q <= (char *)0x300000) { if (given_bootargs_by_user) { if (strlen (bootdevice) <= 254) { strcpy (q, bootdevice); r = strchr (q, 0); if (strlen (given_bootargs) < 255 - (r - q)) { *r++ = ' '; strcpy (r, given_bootargs); } } } else if (strlen (given_bootargs) <= 255) strcpy (q, given_bootargs); } } dig_into_params (params); if (initrd_string) { char *q, *r, *initrd_device, *initrd_kname, *initrd_limit, *initrd_cur, c; char *string; int initrd_partno, len, statusok = 0; q = strchr (initrd_string, '|'); if (q && !initrd_size) { fatal ("When more than one initial ramdisk piece is specified, you have to give\n" "a non-zero initrd-size option which is no shorter than sum of all pieces\n" "lengths. Try again...\n"); halt (promvec); } if (q) { initrd_start = memory_find ((initrd_size + 16383) & ~16383); if (!initrd_start) { fatal ("You do not have enough continuous available memory for such initial ramdisk."); halt (promvec); } string = strdup (initrd_string); q = strchr (string, '|'); r = string; initrd_cur = initrd_start; initrd_limit = initrd_start + ((initrd_size + 16383) & ~16383); printf ("Loading parts of initial ramdisk...\n"); for (;;) { c = *q; *q = 0; parse_name (r, initrd_defpart, &initrd_device, &initrd_partno, &initrd_kname); if (!initrd_kname) break; if (!initrd_device) initrd_device = initrd_defdevice; if (!load_file (initrd_device, initrd_partno, initrd_kname, initrd_cur, initrd_limit, &len, 0, 0)) break; if (!c) { statusok = 1; break; } initrd_cur += len; r = q + 1; q = strchr (r, '|'); if (!q) q = strchr (r, 0); if (initrd_prompt) { close (); printf ("Insert next media and press ENTER"); dpin (); printf ("\n"); } } free (string); if (statusok) { *(unsigned int *)(p + 16) = ((unsigned int)initrd_start | 0xf0000000); *(unsigned int *)(p + 20) = initrd_size; } else printf ("Error: initial ramdisk loading failed. No initrd will be used.\n"); } else { parse_name (initrd_string, initrd_defpart, &initrd_device, &initrd_partno, &initrd_kname); if (initrd_kname) { if (!initrd_device) initrd_device = initrd_defdevice; if (load_file (initrd_device, initrd_partno, initrd_kname, (unsigned char *) 0x300000, (unsigned char *) 0x380000, 0, 0, initrd_lenfunc)) { *(unsigned int *)(p + 16) = ((unsigned int)initrd_start | 0xf0000000); *(unsigned int *)(p + 20) = initrd_size; } } } } } } else { char *p; memcpy ((unsigned char *) 0x4000, ((unsigned char *) 0x4000) + off, len); p = seed_part_into_device (other_device, other_part); strcpy (other_device, p); params_device = other_device; } close (); if (timer_status >= 1) close_timer (promvec); set_bootargs (promvec, params, params_device); if (show_arguments) { show_bootargs (promvec); pause_after = 1; } if (pause_after) { printf ("%s", pause_message); dpin (); printf ("\n"); } return ret_offset; }