1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362
|
Enable kFreeBSD support in GRUB, by Guillem Jover <guillem@debian.org>
Warning: This feature is undocumented because it's highly experimental.
If you don't know how to use it, you better don't!
diff -ur grub-0.95+cvs20040624.old/stage2/boot.c grub-0.95+cvs20040624/stage2/boot.c
--- grub-0.95+cvs20040624.old/stage2/boot.c 2004-03-29 16:54:30.000000000 +0200
+++ grub-0.95+cvs20040624/stage2/boot.c 2004-06-26 03:46:45.000000000 +0200
@@ -29,6 +29,8 @@
entry_func entry_addr;
static struct mod_list mll[99];
static int linux_mem_size;
+static int elf_kernel_addr;
+static int elf_kernel_size;
/*
* The next two functions, 'load_image' and 'load_module', are the building
@@ -594,6 +596,7 @@
/* reset this to zero for now */
cur_addr = 0;
+ elf_kernel_addr = ~0;
/* scan for program segments */
for (i = 0; i < pu.elf->e_phnum; i++)
@@ -630,6 +633,8 @@
/* mark memory as used */
if (cur_addr < memaddr + memsiz)
cur_addr = memaddr + memsiz;
+ if (elf_kernel_addr > cur_addr)
+ elf_kernel_addr = cur_addr;
printf (", <0x%x:0x%x:0x%x>", memaddr, filesiz,
memsiz - filesiz);
/* increment number of segments */
@@ -647,6 +652,8 @@
}
}
+ elf_kernel_size = cur_addr - elf_kernel_addr;
+
if (! errnum)
{
if (! loaded)
@@ -864,6 +871,129 @@
}
#endif
+#define mem_align4k(p) ((p) + 0xFFF) & 0xFFFFF000
+
+static void
+kfreebsd_setenv (char *env, const char *var, const char *value)
+{
+ while (1)
+ {
+ if (env[0] == '\0' && env[1] == '\0')
+ {
+ env++;
+ break;
+ }
+ else
+ env++;
+ }
+
+ grub_sprintf (env, "%s=%s", var, value);
+ env[grub_strlen (env) + 1] = '\0';
+}
+
+static char *
+kfreebsd_read_hints (char *buf)
+{
+ char *buf_end = buf;
+
+ if (grub_open ("/boot/device.hints"))
+ {
+ char *line_start;
+ int line_len = 0;
+ char *envp;
+ int env_len;
+
+ env_len = grub_read (buf, -1);
+ if (env_len)
+ {
+ buf_end += env_len;
+ *(buf_end++) = '\0';
+ }
+ else
+ return buf_end;
+
+ grub_close ();
+
+ envp = line_start = buf;
+ while (*envp)
+ {
+ char *envp_current = envp;
+
+ switch (*envp)
+ {
+ case ' ':
+ while (*envp == ' ')
+ {
+ envp++;
+ env_len--;
+ }
+ grub_memmove (envp_current, envp, env_len + 1);
+ envp = envp_current;
+ break;
+ case '#':
+ while (*envp != '\n')
+ {
+ envp++;
+ env_len--;
+ }
+ if (!line_len)
+ envp++;
+ grub_memmove (envp_current, envp, env_len + 1);
+ envp = envp_current;
+ break;
+ case '\n':
+ if (!line_len)
+ {
+ env_len--;
+ grub_memmove (line_start, envp, env_len + 1);
+ }
+ *(envp++) = '\0';
+ line_len = 0;
+ line_start = envp;
+ default:
+ envp++;
+ line_len++;
+ break;
+ }
+ }
+
+ buf_end = buf + env_len;
+ *(buf_end++) = '\0';
+ }
+
+ return buf_end;
+}
+
+static u32_t *
+kfreebsd_set_module_string (u32_t type, u32_t *dst, char *src)
+{
+ int size;
+
+ *(dst++) = type;
+ *(dst++) = size = grub_strlen (src) + 1;
+ grub_strcpy ((void *) dst, src);
+
+ return dst + (size + sizeof(u32_t) - 1) / sizeof(u32_t);
+}
+
+static u32_t *
+kfreebsd_set_module_var (u32_t type, u32_t *dst, u32_t src)
+{
+ *(dst++) = type;
+ *(dst++) = sizeof(u32_t);
+ *(dst++) = src;
+
+ return dst;
+}
+
+static u32_t *
+kfreebsd_set_modules (u32_t *modulep)
+{
+ /* XXX: Need to copy the whole module structure. */
+ /* XXX: How to pass the module name ? */
+
+ return modulep;
+}
/*
* All "*_boot" commands depend on the images being loaded into memory
@@ -877,7 +1007,10 @@
bsd_boot (kernel_t type, int bootdev, char *arg)
{
char *str;
- int clval = 0, i;
+ char *kernelname;
+ char *bsd_root;
+ int clval = 0;
+ int i;
struct bootinfo bi;
#ifdef GRUB_UTIL
@@ -886,8 +1019,21 @@
stop_floppy ();
#endif
+ while (*arg != '/')
+ arg++;
+ kernelname = arg;
+
while (*(++arg) && *arg != ' ');
+ *(arg++) = 0;
str = arg;
+
+ bsd_root = grub_strstr (str, "root=");
+ if (bsd_root)
+ {
+ bsd_root += 5;
+ /* XXX: should copy the str or terminate it. */
+ }
+
while (*str)
{
if (*str == '-')
@@ -910,6 +1056,8 @@
clval |= RB_GDB;
if (*str == 'h')
clval |= RB_SERIAL;
+ if (*str == 'p')
+ clval |= RB_PAUSE;
if (*str == 'm')
clval |= RB_MUTE;
if (*str == 'r')
@@ -927,14 +1075,17 @@
if (type == KERNEL_TYPE_FREEBSD)
{
+ char *envp;
+ u32_t *modp;
+
clval |= RB_BOOTINFO;
bi.bi_version = BOOTINFO_VERSION;
- *arg = 0;
- while ((--arg) > (char *) MB_CMDLINE_BUF && *arg != '/');
- if (*arg == '/')
- bi.bi_kernelname = arg + 1;
+ bi.bi_pad[0] = bi.bi_pad[1] = 0;
+
+ if (*kernelname == '/')
+ bi.bi_kernelname = kernelname;
else
bi.bi_kernelname = 0;
@@ -961,6 +1112,30 @@
bi.bi_basemem = mbi.mem_lower;
bi.bi_extmem = extended_memory;
+ /* Setup the environment. */
+ bi.bi_envp = cur_addr = mem_align4k (cur_addr);
+ grub_memset ((void *) cur_addr, 0, 2);
+ cur_addr = (int) kfreebsd_read_hints ((void *) cur_addr);
+
+ envp = (char *) bi.bi_envp;
+ kfreebsd_setenv (envp, "kernelname", kernelname);
+ kfreebsd_setenv (envp, "vfs.root.mountfrom", bsd_root);
+
+ /* Setup the modules list. */
+ bi.bi_modulep = cur_addr = mem_align4k (cur_addr);
+ modp = (u32_t *) bi.bi_modulep;
+ /* The first module is the kernel. */
+ modp = kfreebsd_set_module_string (MODINFO_NAME, modp, kernelname);
+ modp = kfreebsd_set_module_string (MODINFO_TYPE, modp, "elf kernel");
+ modp = kfreebsd_set_module_string (MODINFO_ARGS, modp, arg);
+ modp = kfreebsd_set_module_var (MODINFO_ADDR, modp, elf_kernel_addr);
+ modp = kfreebsd_set_module_var (MODINFO_SIZE, modp, elf_kernel_size);
+ /* Now the real modules. */
+ modp = kfreebsd_set_modules(modp);
+
+ /* Set the kernel end. */
+ bi.bi_kernend = cur_addr = mem_align4k (((int) modp) + 1);
+
if (mbi.flags & MB_INFO_AOUT_SYMS)
{
bi.bi_symtab = mbi.syms.a.addr;
@@ -970,8 +1145,9 @@
#if 0
else if (mbi.flags & MB_INFO_ELF_SHDR)
{
- /* FIXME: Should check if a symbol table exists and, if exists,
- pass the table to BI. */
+ bi.bi_symtab = mbi.syms.e.addr;
+ bi.bi_esymtab = mbi.syms.e.addr
+ + mbi.syms.e.size * mbi.syms.e.num * mbi.syms.e.shndx;
}
#endif
else
diff -ur grub-0.95+cvs20040624.old/stage2/freebsd.h grub-0.95+cvs20040624/stage2/freebsd.h
--- grub-0.95+cvs20040624.old/stage2/freebsd.h 2002-11-30 18:33:06.000000000 +0100
+++ grub-0.95+cvs20040624/stage2/freebsd.h 2004-06-26 03:46:45.000000000 +0200
@@ -1,7 +1,7 @@
/*
* GRUB -- GRand Unified Bootloader
- * Copyright (C) 2001 Free Software Foundation, Inc.
+ * Copyright (C) 2001, 2004 Free Software Foundation, Inc.
*
* 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
@@ -35,6 +35,10 @@
#define RB_CDROM 0x2000 /* use cdrom as root */
#define RB_GDB 0x8000 /* use GDB remote debugger instead of DDB */
#define RB_MUTE 0x10000 /* Come up with the console muted */
+#define RB_SELFTEST 0x20000 /* don't complete the boot; do selftest */
+#define RB_RESERVED1 0x40000 /* reserved for internal use of boot blocks */
+#define RB_RESERVED2 0x80000 /* reserved for internal use of boot blocks */
+#define RB_PAUSE 0x100000 /* pause after each output line during probe */
#define RB_MULTIPLE 0x20000000 /* Use multiple consoles */
#define RB_BOOTINFO 0x80000000 /* have `struct bootinfo *' arg */
@@ -70,6 +74,9 @@
#define N_BIOS_GEOM 8
+typedef unsigned char u8_t;
+typedef unsigned int u32_t;
+
/*
* A zero bootinfo field often means that there is no info available.
* Flags are used to indicate the validity of fields where zero is a
@@ -77,19 +84,33 @@
*/
struct bootinfo
{
- unsigned int bi_version;
- unsigned char *bi_kernelname;
- struct nfs_diskless *bi_nfs_diskless;
+ u32_t bi_version;
+ u8_t *bi_kernelname;
+ u32_t bi_nfs_diskless;
/* End of fields that are always present. */
#define bi_endcommon bi_n_bios_used
- unsigned int bi_n_bios_used;
- unsigned long bi_bios_geom[N_BIOS_GEOM];
- unsigned int bi_size;
- unsigned char bi_memsizes_valid;
- unsigned char bi_bios_dev;
- unsigned char bi_pad[2];
- unsigned long bi_basemem;
- unsigned long bi_extmem;
- unsigned long bi_symtab;
- unsigned long bi_esymtab;
+ u32_t bi_n_bios_used;
+ u32_t bi_bios_geom[N_BIOS_GEOM];
+ u32_t bi_size;
+ u8_t bi_memsizes_valid;
+ u8_t bi_bios_dev;
+ u8_t bi_pad[2];
+ u32_t bi_basemem;
+ u32_t bi_extmem;
+ u32_t bi_symtab;
+ u32_t bi_esymtab;
+ /* Items below only from advanced bootloader */
+ u32_t bi_kernend;
+ u32_t bi_envp;
+ u32_t bi_modulep;
};
+
+#define MODINFO_END 0x0000 /* End of list */
+#define MODINFO_NAME 0x0001 /* Name of module (string) */
+#define MODINFO_TYPE 0x0002 /* Type of module (string) */
+#define MODINFO_ADDR 0x0003 /* Loaded address */
+#define MODINFO_SIZE 0x0004 /* Size of module */
+#define MODINFO_EMPTY 0x0005 /* Has been deleted */
+#define MODINFO_ARGS 0x0006 /* Parameters string */
+#define MODINFO_METADATA 0x8000 /* Module-specfic */
+
|