diff options
author | bcollins <tailor@grayson> | 2006-06-01 13:19:40 -0400 |
---|---|---|
committer | Ben Collins <bcollins@ubuntu.com> | 2006-06-01 13:19:40 -0400 |
commit | 02638162fbbe9961f29bc739a330eecdd0eab68b (patch) | |
tree | ee8d0b51a68d92a4901da65eb769c1bf74afd989 | |
parent | 3c6d9984aed14af6393538c9b4aa33cd0e760e35 (diff) | |
download | silo-02638162fbbe9961f29bc739a330eecdd0eab68b.tar.gz |
[silo @ 151]
Implement 64-bit ramdisk location.
Implement a structure for handling HdrS instead of all the pointer
dereferencing. A lot cleaner, and easier to document.#
-rw-r--r-- | second/main.c | 104 | ||||
-rw-r--r-- | second/memory.c | 4 |
2 files changed, 72 insertions, 36 deletions
diff --git a/second/main.c b/second/main.c index 8f8a387..5e78112 100644 --- a/second/main.c +++ b/second/main.c @@ -1,6 +1,6 @@ /* Second stage boot loader - Copyright (C) 1996 Pete A. Zaitcev + Coyright (C) 1996 Pete A. Zaitcev 1996 Maurizio Plaza 1996 David S. Miller 1996 Miguel de Icaza @@ -33,6 +33,26 @@ #define NULL (void *)0 #endif + +struct HdrS_struct { + char magic[4]; + unsigned int linux_ver; + unsigned short ver; + unsigned short root_flags; + unsigned short root_dev; + unsigned short ram_flags; + unsigned int ramdisk_image; + unsigned int ramdisk_size; + /* 0x201 */ + unsigned int reboot_cmd_ptr_high; + unsigned int reboot_cmd_ptr_low; + /* 0x202 */ + unsigned int bootstr_info_ptr_high; + unsigned int bootstr_info_ptr_low; + /* 0x301 */ + unsigned long long ramdisk_image64; +}; + /* This has to be first initialized variable in main.c */ extern unsigned char silo_conf[256]; @@ -68,6 +88,7 @@ int other_part = -1; int solaris = 0; int other = 0; char *password = 0; +int initrd_can_do_64bit_phys = 0; static void parse_name (char *, int, char **, int *, char **); @@ -1018,7 +1039,6 @@ int bootmain (void) char *kernel_params; int part; int isfile, fileok = 0; - char *p; unsigned int ret_offset = 0; char *params_device = 0; int silo_conf_partition; @@ -1217,18 +1237,15 @@ try_again: params = params_device; params_device = sol_params; } else if (!other) { - unsigned short hdrs_ver = 0; + struct HdrS_struct *hdrs; params_device = 0; memcpy (image_base, image_base + off, len); - p = find_linux_HdrS (image_base, image_len); - - if (p) - hdrs_ver = *(unsigned short *)(p + 8); + hdrs = (struct HdrS_struct *)find_linux_HdrS (image_base, image_len); - if (p && hdrs_ver < 0x300 && image_base != (char *)0x4000) { + if (hdrs && hdrs->ver < 0x300 && image_base != (char *)0x4000) { /* Kernel doesn't support being loaded to other than * phys_base, so let's try to copy it down there. */ if ((unsigned int)&_start - 0x4000 < len) { @@ -1249,26 +1266,27 @@ try_again: /* Readjust some things */ ret_offset = 0x4000; - p = find_linux_HdrS (image_base, image_len); + hdrs = (struct HdrS_struct *)find_linux_HdrS (image_base, image_len); printf("done.\n"); } - if (p) { - unsigned int linux_version = *(unsigned int *)(p + 4); + if (hdrs) { + unsigned int linux_ver = hdrs->linux_ver; - printf("Loaded kernel version %d.%d.%d\n", (linux_version >> 16) & 0xff, - (linux_version >> 8) & 0xff, linux_version & 0xff); + printf("Loaded kernel version %d.%d.%d\n", (linux_ver >> 16) & 0xff, + (linux_ver >> 8) & 0xff, linux_ver & 0xff); - if (fill_reboot_cmd && hdrs_ver >= 0x201) { /* ie. uses reboot_command */ - char *q = (char *)(*(unsigned int *)(p + 24)), *r; + if (fill_reboot_cmd && hdrs->ver >= 0x201) { /* ie. uses reboot_command */ + char *q = (char *)hdrs->reboot_cmd_ptr_high; + char *r; extern char bootdevice[]; /* On Ultra there is xword there, this hack makes * it work... */ if (q == (char *)0xfffff800 || !q) - q = (char *)(*(unsigned int *)(p+28)); + q = (char *)hdrs->reboot_cmd_ptr_low; q = (char *)(((unsigned long)q)& 0x003fffff); if (q >= (char *)0x4000 && q <= (char *)0x300000) { if (given_bootargs_by_user) { @@ -1284,7 +1302,7 @@ try_again: strcpy (q, given_bootargs); } } - if (!dig_into_params (params) && !*(unsigned short *)(p + 12)) { + if (!dig_into_params (params) && !hdrs->root_dev) { char *s1, *s2; s1 = cfg_get_strg(0, "root"); @@ -1297,12 +1315,12 @@ try_again: } } - if (hdrs_ver >= 0x202) { + if (hdrs->ver >= 0x202) { if (architecture == sun4u) - kernel_params = (char *)((*(unsigned int *)(p + 36) - 0x400000) + + kernel_params = (char *)((hdrs->bootstr_info_ptr_low - 0x400000) + (image_base - 0x4000)); else - kernel_params = (char *)(*(unsigned int *)(p + 36) & 0x3fffff); + kernel_params = (char *)(hdrs->bootstr_info_ptr_low & 0x3fffff); } /* Some UltraAX machines have /dev/fd1 floppies only. */ @@ -1317,6 +1335,9 @@ try_again: char *q, *r, *initrd_device, *initrd_kname, *initrd_limit, *initrd_cur, c; char *string; int initrd_partno, len, statusok = 0; + + if (hdrs->ver >= 0x301) + initrd_can_do_64bit_phys = 1; q = strchr (initrd_string, '|'); if (q && !initrd_size) { @@ -1366,13 +1387,20 @@ try_again: extern unsigned long long sun4u_initrd_phys; extern unsigned long sun4m_initrd_pa; - if (architecture == sun4u) - *(unsigned int *)(p + 16) = (unsigned int)sun4u_initrd_phys + 0x400000; - else if (sun4m_initrd_pa) - *(unsigned int *)(p + 16) = ((unsigned int)sun4m_initrd_pa); - else - *(unsigned int *)(p + 16) = ((unsigned int)initrd_start | 0xf0000000); - *(unsigned int *)(p + 20) = initrd_size; + if (architecture == sun4u) { + if (initrd_can_do_64bit_phys) { + hdrs->ramdisk_image64 = + sun4u_initrd_phys + 0x400000ULL; + } else { + hdrs->ramdisk_image = + (unsigned int)sun4u_initrd_phys + 0x400000; + } + } else if (sun4m_initrd_pa) { + hdrs->ramdisk_image = ((unsigned int)sun4m_initrd_pa); + } else + hdrs->ramdisk_image = ((unsigned int)initrd_start | 0xf0000000); + + hdrs->ramdisk_size = initrd_size; } else printf ("Error: initial ramdisk loading failed. No initrd will be used.\n"); } else { @@ -1385,14 +1413,20 @@ try_again: extern unsigned long long sun4u_initrd_phys; extern unsigned long sun4m_initrd_pa; - if (architecture == sun4u) - *(unsigned int *)(p + 16) = (unsigned int)sun4u_initrd_phys + 0x400000; - else if (sun4m_initrd_pa) - *(unsigned int *)(p + 16) = ((unsigned int)sun4m_initrd_pa); - else - *(unsigned int *)(p + 16) = ((unsigned int)initrd_start | 0xf0000000); - - *(unsigned int *)(p + 20) = initrd_size; + if (architecture == sun4u) { + if (initrd_can_do_64bit_phys) { + hdrs->ramdisk_image64 = + sun4u_initrd_phys + 0x400000ULL; + } else { + hdrs->ramdisk_image = + (unsigned int)sun4u_initrd_phys + 0x400000; + } + } else if (sun4m_initrd_pa) { + hdrs->ramdisk_image = ((unsigned int)sun4m_initrd_pa); + } else + hdrs->ramdisk_image = ((unsigned int)initrd_start | 0xf0000000); + + hdrs->ramdisk_size = initrd_size; } } else printf ("Error: initial ramdisk loading failed. No initrd will be used.\n"); diff --git a/second/memory.c b/second/memory.c index 31094dd..eea53be 100644 --- a/second/memory.c +++ b/second/memory.c @@ -27,6 +27,8 @@ #define INITRD_VIRT_ADDR 0x40c00000 #define IMAGE_VIRT_ADDR 0x40000000 +extern int initrd_can_do_64bit_phys; + static char *sun4u_memory_find (unsigned int len, int is_kernel); struct linux_prom_registers prom_reg_memlist[64]; @@ -344,7 +346,7 @@ static char *sun4u_memory_find (unsigned int len, int is_kernel) /* Make sure initrd phys isn't greater than 32-bits. We * can only pass unsigned int to the kernel for this * location. */ - if (!is_kernel && p[i].phys >= 0x0000000100000000ULL) + if (!is_kernel && !initrd_can_do_64bit_phys && p[i].phys >= 0x0000000100000000ULL) continue; if (p[i].size >= len) { |