summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbcollins <tailor@grayson>2006-06-01 13:19:40 -0400
committerBen Collins <bcollins@ubuntu.com>2006-06-01 13:19:40 -0400
commit02638162fbbe9961f29bc739a330eecdd0eab68b (patch)
treeee8d0b51a68d92a4901da65eb769c1bf74afd989
parent3c6d9984aed14af6393538c9b4aa33cd0e760e35 (diff)
downloadsilo-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.c104
-rw-r--r--second/memory.c4
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) {