Merge some knetbsdcode into kfreebsd one. Serial supoort for knetbsd

This commit is contained in:
Vladimir 'phcoder' Serbinenko 2010-01-15 11:39:05 +01:00
parent def6307401
commit 2386d586b9
3 changed files with 330 additions and 289 deletions

View file

@ -114,6 +114,12 @@ struct grub_freebsd_bootinfo
grub_uint32_t bi_modulep; grub_uint32_t bi_modulep;
} __attribute__ ((packed)); } __attribute__ ((packed));
struct freebsd_tag_header
{
grub_uint32_t type;
grub_uint32_t len;
};
#define OPENBSD_RB_ASKNAME (1 << 0) /* ask for file name to reboot from */ #define OPENBSD_RB_ASKNAME (1 << 0) /* ask for file name to reboot from */
#define OPENBSD_RB_SINGLE (1 << 1) /* reboot to single user only */ #define OPENBSD_RB_SINGLE (1 << 1) /* reboot to single user only */
#define OPENBSD_RB_NOSYNC (1 << 2) /* dont sync before reboot */ #define OPENBSD_RB_NOSYNC (1 << 2) /* dont sync before reboot */
@ -198,48 +204,21 @@ struct grub_openbsd_bootargs
struct grub_netbsd_bootinfo struct grub_netbsd_bootinfo
{ {
grub_uint32_t bi_count; grub_uint32_t bi_count;
grub_addr_t bi_data[1]; grub_addr_t bi_data[0];
}; };
#define NETBSD_BTINFO_BOOTPATH 0 #define NETBSD_BTINFO_BOOTPATH 0
#define NETBSD_BTINFO_ROOTDEVICE 1 #define NETBSD_BTINFO_ROOTDEVICE 1
#define NETBSD_BTINFO_BOOTDISK 3 #define NETBSD_BTINFO_CONSOLE 6
#define NETBSD_BTINFO_MEMMAP 9 #define NETBSD_BTINFO_MEMMAP 9
struct grub_netbsd_btinfo_common struct grub_netbsd_btinfo_common
{ {
int len; grub_uint32_t len;
int type;
};
struct grub_netbsd_btinfo_mmap_header
{
struct grub_netbsd_btinfo_common common;
grub_uint32_t count;
};
struct grub_netbsd_btinfo_mmap_entry
{
grub_uint64_t addr;
grub_uint64_t len;
#define NETBSD_MMAP_AVAILABLE 1
#define NETBSD_MMAP_RESERVED 2
#define NETBSD_MMAP_ACPI 3
#define NETBSD_MMAP_NVS 4
grub_uint32_t type; grub_uint32_t type;
}; };
struct grub_netbsd_btinfo_bootpath #define GRUB_NETBSD_MAX_BOOTPATH_LEN 80
{
struct grub_netbsd_btinfo_common common;
char bootpath[80];
};
struct grub_netbsd_btinfo_rootdevice
{
struct grub_netbsd_btinfo_common common;
char devname[16];
};
struct grub_netbsd_btinfo_bootdisk struct grub_netbsd_btinfo_bootdisk
{ {
@ -254,6 +233,15 @@ struct grub_netbsd_btinfo_bootdisk
int partition; int partition;
}; };
struct grub_netbsd_btinfo_serial
{
char devname[16];
grub_uint32_t addr;
grub_uint32_t speed;
};
#define GRUB_NETBSD_MAX_ROOTDEVICE_LEN 16
grub_err_t grub_freebsd_load_elfmodule32 (struct grub_relocator *relocator, grub_err_t grub_freebsd_load_elfmodule32 (struct grub_relocator *relocator,
grub_file_t file, int argc, grub_file_t file, int argc,
char *argv[], grub_addr_t *kern_end); char *argv[], grub_addr_t *kern_end);
@ -268,8 +256,8 @@ grub_err_t grub_freebsd_load_elf_meta64 (struct grub_relocator *relocator,
grub_file_t file, grub_file_t file,
grub_addr_t *kern_end); grub_addr_t *kern_end);
grub_err_t grub_freebsd_add_meta (grub_uint32_t type, void *data, grub_err_t grub_bsd_add_meta (grub_uint32_t type,
grub_uint32_t len); void *data, grub_uint32_t len);
grub_err_t grub_freebsd_add_meta_module (char *filename, char *type, grub_err_t grub_freebsd_add_meta_module (char *filename, char *type,
int argc, char **argv, int argc, char **argv,
grub_addr_t addr, grub_uint32_t size); grub_addr_t addr, grub_uint32_t size);

View file

@ -51,20 +51,29 @@
#define ALIGN_VAR(a) ((is_64bit) ? (ALIGN_QWORD(a)) : (ALIGN_DWORD(a))) #define ALIGN_VAR(a) ((is_64bit) ? (ALIGN_QWORD(a)) : (ALIGN_DWORD(a)))
#define ALIGN_PAGE(a) ALIGN_UP (a, 4096) #define ALIGN_PAGE(a) ALIGN_UP (a, 4096)
#define MOD_BUF_ALLOC_UNIT 4096
static int kernel_type = KERNEL_TYPE_NONE; static int kernel_type = KERNEL_TYPE_NONE;
static grub_dl_t my_mod; static grub_dl_t my_mod;
static grub_addr_t entry, entry_hi, kern_start, kern_end; static grub_addr_t entry, entry_hi, kern_start, kern_end;
static void *kern_chunk_src; static void *kern_chunk_src;
static grub_uint32_t bootflags; static grub_uint32_t bootflags;
static char *mod_buf;
static grub_uint32_t mod_buf_len, mod_buf_max, kern_end_mdofs;
static int is_elf_kernel, is_64bit; static int is_elf_kernel, is_64bit;
static char *netbsd_root = NULL;
static grub_uint32_t openbsd_root; static grub_uint32_t openbsd_root;
struct grub_relocator *relocator = NULL; struct grub_relocator *relocator = NULL;
struct bsd_tag
{
struct bsd_tag *next;
grub_size_t len;
grub_uint32_t type;
union {
grub_uint8_t a;
grub_uint16_t b;
grub_uint32_t c;
} data[0];
};
struct bsd_tag *tags, *tags_last;
static const struct grub_arg_option freebsd_opts[] = static const struct grub_arg_option freebsd_opts[] =
{ {
{"dual", 'D', 0, N_("Display output on all consoles."), 0, 0}, {"dual", 'D', 0, N_("Display output on all consoles."), 0, 0},
@ -127,6 +136,8 @@ static const struct grub_arg_option netbsd_opts[] =
{"debug", 'x', 0, N_("Boot with debug messages."), 0, 0}, {"debug", 'x', 0, N_("Boot with debug messages."), 0, 0},
{"silent", 'z', 0, N_("Supress normal output (warnings remain)."), 0, 0}, {"silent", 'z', 0, N_("Supress normal output (warnings remain)."), 0, 0},
{"root", 'r', 0, N_("Set root device."), N_("DEVICE"), ARG_TYPE_STRING}, {"root", 'r', 0, N_("Set root device."), N_("DEVICE"), ARG_TYPE_STRING},
{"serial", 'h', GRUB_ARG_OPTION_OPTIONAL,
N_("Use serial console."), N_("ADDR,SPEED"), ARG_TYPE_STRING},
{0, 0, 0, 0, 0, 0} {0, 0, 0, 0, 0, 0}
}; };
@ -139,6 +150,7 @@ static const grub_uint32_t netbsd_flags[] =
}; };
#define NETBSD_ROOT_ARG (ARRAY_SIZE (netbsd_flags) - 1) #define NETBSD_ROOT_ARG (ARRAY_SIZE (netbsd_flags) - 1)
#define NETBSD_SERIAL_ARG (ARRAY_SIZE (netbsd_flags))
static void static void
grub_bsd_get_device (grub_uint32_t * biosdev, grub_bsd_get_device (grub_uint32_t * biosdev,
@ -180,36 +192,23 @@ grub_bsd_get_device (grub_uint32_t * biosdev,
} }
grub_err_t grub_err_t
grub_freebsd_add_meta (grub_uint32_t type, void *data, grub_uint32_t len) grub_bsd_add_meta (grub_uint32_t type, void *data, grub_uint32_t len)
{ {
if (mod_buf_max < mod_buf_len + len + 8) struct bsd_tag *newtag;
{
char *new_buf;
do
{
mod_buf_max += MOD_BUF_ALLOC_UNIT;
}
while (mod_buf_max < mod_buf_len + len + 8);
new_buf = grub_malloc (mod_buf_max);
if (!new_buf)
return grub_errno;
grub_memcpy (new_buf, mod_buf, mod_buf_len);
grub_free (mod_buf);
mod_buf = new_buf;
}
*((grub_uint32_t *) (mod_buf + mod_buf_len)) = type;
*((grub_uint32_t *) (mod_buf + mod_buf_len + 4)) = len;
mod_buf_len += 8;
newtag = grub_malloc (len + sizeof (struct bsd_tag));
if (!newtag)
return grub_errno;
newtag->len = len;
newtag->type = type;
newtag->next = NULL;
if (len) if (len)
grub_memcpy (mod_buf + mod_buf_len, data, len); grub_memcpy (newtag->data, data, len);
if (tags_last)
mod_buf_len = ALIGN_VAR (mod_buf_len + len); tags_last->next = newtag;
else
tags = newtag;
tags_last = newtag;
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
} }
@ -226,13 +225,13 @@ struct grub_e820_mmap
#define GRUB_E820_NVS 4 #define GRUB_E820_NVS 4
#define GRUB_E820_EXEC_CODE 5 #define GRUB_E820_EXEC_CODE 5
static grub_err_t static void
grub_freebsd_add_mmap (void) generate_e820_mmap (grub_size_t *len, grub_size_t *cnt, void *buf)
{ {
grub_size_t len = 0; int count = 0;
struct grub_e820_mmap *mmap_buf = 0;
struct grub_e820_mmap *mmap = 0;
int isfirstrun = 1; int isfirstrun = 1;
struct grub_e820_mmap *mmap = buf;
struct grub_e820_mmap prev, cur;
auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t); auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t);
int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size,
@ -240,86 +239,110 @@ grub_freebsd_add_mmap (void)
{ {
/* FreeBSD assumes that first 64KiB are available. /* FreeBSD assumes that first 64KiB are available.
Not always true but try to prevent panic somehow. */ Not always true but try to prevent panic somehow. */
if (isfirstrun && addr != 0) if (kernel_type == KERNEL_TYPE_FREEBSD && isfirstrun && addr != 0)
{ {
cur.addr = 0;
cur.size = (addr < 0x10000) ? addr : 0x10000;
cur.type = GRUB_E820_RAM;
if (mmap) if (mmap)
{ *mmap++ = cur;
mmap->addr = 0;
mmap->size = (addr < 0x10000) ? addr : 0x10000; prev = cur;
mmap->type = GRUB_E820_RAM; count++;
mmap++;
}
else
len += sizeof (struct grub_e820_mmap);
} }
isfirstrun = 0; isfirstrun = 0;
if (mmap)
cur.addr = addr;
cur.size = size;
switch (type)
{ {
mmap->addr = addr; case GRUB_MACHINE_MEMORY_AVAILABLE:
mmap->size = size; cur.type = GRUB_E820_RAM;
switch (type) break;
{
case GRUB_MACHINE_MEMORY_AVAILABLE:
mmap->type = GRUB_E820_RAM;
break;
#ifdef GRUB_MACHINE_MEMORY_ACPI #ifdef GRUB_MACHINE_MEMORY_ACPI
case GRUB_MACHINE_MEMORY_ACPI: case GRUB_MACHINE_MEMORY_ACPI:
mmap->type = GRUB_E820_ACPI; cur.type = GRUB_E820_ACPI;
break; break;
#endif #endif
#ifdef GRUB_MACHINE_MEMORY_NVS #ifdef GRUB_MACHINE_MEMORY_NVS
case GRUB_MACHINE_MEMORY_NVS: case GRUB_MACHINE_MEMORY_NVS:
mmap->type = GRUB_E820_NVS; cur.type = GRUB_E820_NVS;
break; break;
#endif #endif
default: default:
#ifdef GRUB_MACHINE_MEMORY_CODE #ifdef GRUB_MACHINE_MEMORY_CODE
case GRUB_MACHINE_MEMORY_CODE: case GRUB_MACHINE_MEMORY_CODE:
#endif #endif
#ifdef GRUB_MACHINE_MEMORY_RESERVED #ifdef GRUB_MACHINE_MEMORY_RESERVED
case GRUB_MACHINE_MEMORY_RESERVED: case GRUB_MACHINE_MEMORY_RESERVED:
#endif #endif
mmap->type = GRUB_E820_RESERVED; cur.type = GRUB_E820_RESERVED;
break; break;
} }
/* Merge regions if possible. */ /* Merge regions if possible. */
if (mmap != mmap_buf && mmap->type == mmap[-1].type && if (count && cur.type == prev.type && cur.addr == prev.addr + prev.size)
mmap->addr == mmap[-1].addr + mmap[-1].size) {
mmap[-1].size += mmap->size; prev.size += cur.size;
else if (mmap)
mmap++; mmap[-1] = cur;
} }
else else
len += sizeof (struct grub_e820_mmap); {
if (mmap)
*mmap++ = cur;
prev = cur;
count++;
}
return 0; return 0;
} }
grub_mmap_iterate (hook);
mmap_buf = mmap = grub_malloc (len);
if (! mmap)
return grub_errno;
isfirstrun = 1; isfirstrun = 1;
grub_mmap_iterate (hook); grub_mmap_iterate (hook);
len = (mmap - mmap_buf) * sizeof (struct grub_e820_mmap); if (len)
int i; *len = count * sizeof (struct grub_e820_mmap);
for (i = 0; i < mmap - mmap_buf; i++) *cnt = count;
grub_dprintf ("bsd", "smap %d, %d:%llx - %llx\n", i,
mmap_buf[i].type,
(unsigned long long) mmap_buf[i].addr,
(unsigned long long) mmap_buf[i].size);
grub_dprintf ("bsd", "%ld entries in smap\n", (long) (mmap - mmap_buf)); return;
grub_freebsd_add_meta (FREEBSD_MODINFO_METADATA | }
FREEBSD_MODINFOMD_SMAP, mmap_buf, len);
grub_free (mmap_buf); static grub_err_t
grub_bsd_add_mmap (void)
{
grub_size_t len, cnt;
void *buf = NULL, *buf0;
generate_e820_mmap (&len, &cnt, buf);
if (kernel_type == KERNEL_TYPE_NETBSD)
len += sizeof (grub_uint32_t);
buf = grub_malloc (len);
if (!buf)
return grub_errno;
buf0 = buf;
if (kernel_type == KERNEL_TYPE_NETBSD)
{
*(grub_uint32_t *) buf = cnt;
buf = ((grub_uint32_t *) buf + 1);
}
generate_e820_mmap (NULL, &cnt, buf);
grub_dprintf ("bsd", "%u entries in smap\n", cnt);
if (kernel_type == KERNEL_TYPE_NETBSD)
grub_bsd_add_meta (NETBSD_BTINFO_MEMMAP, buf0, len);
else
grub_bsd_add_meta (FREEBSD_MODINFO_METADATA |
FREEBSD_MODINFOMD_SMAP, buf0, len);
grub_free (buf0);
return grub_errno; return grub_errno;
} }
@ -337,29 +360,22 @@ grub_freebsd_add_meta_module (char *filename, char *type, int argc, char **argv,
if (grub_strcmp (type, "/boot/zfs/zpool.cache") == 0) if (grub_strcmp (type, "/boot/zfs/zpool.cache") == 0)
name = "/boot/zfs/zpool.cache"; name = "/boot/zfs/zpool.cache";
if (grub_freebsd_add_meta (FREEBSD_MODINFO_NAME, name, if (grub_bsd_add_meta (FREEBSD_MODINFO_NAME, name, grub_strlen (name) + 1))
grub_strlen (name) + 1))
return grub_errno; return grub_errno;
if (is_64bit) if (is_64bit)
{ {
grub_uint64_t addr64 = addr, size64 = size; grub_uint64_t addr64 = addr, size64 = size;
if ((grub_freebsd_add_meta (FREEBSD_MODINFO_TYPE, type, if (grub_bsd_add_meta (FREEBSD_MODINFO_TYPE, type, grub_strlen (type) + 1)
grub_strlen (type) + 1)) || || grub_bsd_add_meta (FREEBSD_MODINFO_ADDR, &addr64, sizeof (addr64))
(grub_freebsd_add_meta (FREEBSD_MODINFO_ADDR, &addr64, || grub_bsd_add_meta (FREEBSD_MODINFO_SIZE, &size64, sizeof (size64)))
sizeof (addr64))) ||
(grub_freebsd_add_meta (FREEBSD_MODINFO_SIZE, &size64,
sizeof (size64))))
return grub_errno; return grub_errno;
} }
else else
{ {
if ((grub_freebsd_add_meta (FREEBSD_MODINFO_TYPE, type, if (grub_bsd_add_meta (FREEBSD_MODINFO_TYPE, type, grub_strlen (type) + 1)
grub_strlen (type) + 1)) || || grub_bsd_add_meta (FREEBSD_MODINFO_ADDR, &addr, sizeof (addr))
(grub_freebsd_add_meta (FREEBSD_MODINFO_ADDR, &addr, || grub_bsd_add_meta (FREEBSD_MODINFO_SIZE, &size, sizeof (size)))
sizeof (addr))) ||
(grub_freebsd_add_meta (FREEBSD_MODINFO_SIZE, &size,
sizeof (size))))
return grub_errno; return grub_errno;
} }
@ -386,7 +402,7 @@ grub_freebsd_add_meta_module (char *filename, char *type, int argc, char **argv,
} }
*p = 0; *p = 0;
if (grub_freebsd_add_meta (FREEBSD_MODINFO_ARGS, cmdline, n)) if (grub_bsd_add_meta (FREEBSD_MODINFO_ARGS, cmdline, n))
return grub_errno; return grub_errno;
} }
} }
@ -397,27 +413,23 @@ grub_freebsd_add_meta_module (char *filename, char *type, int argc, char **argv,
static void static void
grub_freebsd_list_modules (void) grub_freebsd_list_modules (void)
{ {
grub_uint32_t pos = 0; struct bsd_tag *tag;
grub_printf (" %-18s %-18s%14s%14s\n", "name", "type", "addr", "size"); grub_printf (" %-18s %-18s%14s%14s\n", "name", "type", "addr", "size");
while (pos < mod_buf_len)
{
grub_uint32_t type, size;
type = *((grub_uint32_t *) (mod_buf + pos)); for (tag = tags; tag; tag = tag->next)
size = *((grub_uint32_t *) (mod_buf + pos + 4)); {
pos += 8; switch (tag->type)
switch (type)
{ {
case FREEBSD_MODINFO_NAME: case FREEBSD_MODINFO_NAME:
case FREEBSD_MODINFO_TYPE: case FREEBSD_MODINFO_TYPE:
grub_printf (" %-18s", mod_buf + pos); grub_printf (" %-18s", (char *) tag->data);
break; break;
case FREEBSD_MODINFO_ADDR: case FREEBSD_MODINFO_ADDR:
{ {
grub_uint32_t addr; grub_uint32_t addr;
addr = *((grub_uint32_t *) (mod_buf + pos)); addr = *((grub_uint32_t *) tag->data);
grub_printf (" 0x%08x", addr); grub_printf (" 0x%08x", addr);
break; break;
} }
@ -425,12 +437,10 @@ grub_freebsd_list_modules (void)
{ {
grub_uint32_t len; grub_uint32_t len;
len = *((grub_uint32_t *) (mod_buf + pos)); len = *((grub_uint32_t *) tag->data);
grub_printf (" 0x%08x\n", len); grub_printf (" 0x%08x\n", len);
} }
} }
pos = ALIGN_VAR (pos + size);
} }
} }
@ -446,6 +456,7 @@ grub_freebsd_boot (void)
grub_size_t p_size = 0; grub_size_t p_size = 0;
grub_uint32_t bootdev, biosdev, unit, slice, part; grub_uint32_t bootdev, biosdev, unit, slice, part;
grub_err_t err; grub_err_t err;
grub_size_t tag_buf_len = 0;
auto int iterate_env (struct grub_env_var *var); auto int iterate_env (struct grub_env_var *var);
int iterate_env (struct grub_env_var *var) int iterate_env (struct grub_env_var *var)
@ -475,7 +486,6 @@ grub_freebsd_boot (void)
return 0; return 0;
} }
grub_memset (&bi, 0, sizeof (bi)); grub_memset (&bi, 0, sizeof (bi));
bi.bi_version = FREEBSD_BOOTINFO_VERSION; bi.bi_version = FREEBSD_BOOTINFO_VERSION;
bi.bi_size = sizeof (bi); bi.bi_size = sizeof (bi);
@ -488,10 +498,29 @@ grub_freebsd_boot (void)
p_size = 0; p_size = 0;
grub_env_iterate (iterate_env_count); grub_env_iterate (iterate_env_count);
if (p_size) if (p_size)
p_size = ALIGN_PAGE (kern_end + p_size + 1) - kern_end; p_size = ALIGN_PAGE (kern_end + p_size + 1) - kern_end;
if (is_elf_kernel) if (is_elf_kernel)
p_size = ALIGN_PAGE (kern_end + p_size + mod_buf_len) - kern_end; {
struct bsd_tag *tag;
err = grub_bsd_add_mmap ();
if (err)
return err;
err = grub_bsd_add_meta (FREEBSD_MODINFO_END, 0, 0);
if (err)
return err;
tag_buf_len = 0;
for (tag = tags; tag; tag = tag->next)
tag_buf_len = ALIGN_VAR (tag_buf_len
+ sizeof (struct freebsd_tag_header)
+ tag->len);
p_size = ALIGN_PAGE (kern_end + p_size + tag_buf_len) - kern_end;
}
if (is_64bit) if (is_64bit)
p_size += 4096 * 3; p_size += 4096 * 3;
@ -515,27 +544,50 @@ grub_freebsd_boot (void)
if (is_elf_kernel) if (is_elf_kernel)
{ {
grub_uint8_t *md_ofs; grub_uint8_t *p_tag = p;
int ofs; struct bsd_tag *tag;
for (tag = tags; tag; tag = tag->next)
{
struct freebsd_tag_header *head
= (struct freebsd_tag_header *) p_tag;
head->type = tag->type;
head->len = tag->len;
p_tag += sizeof (struct freebsd_tag_header);
switch (tag->type)
{
case FREEBSD_MODINFO_METADATA | FREEBSD_MODINFOMD_HOWTO:
if (is_64bit)
*(grub_uint64_t *) p_tag = bootflags;
else
*(grub_uint32_t *) p_tag = bootflags;
break;
if (grub_freebsd_add_meta (FREEBSD_MODINFO_END, 0, 0)) case FREEBSD_MODINFO_METADATA | FREEBSD_MODINFOMD_ENVP:
return grub_errno; if (is_64bit)
*(grub_uint64_t *) p_tag = bi.bi_envp;
else
*(grub_uint32_t *) p_tag = bi.bi_envp;
break;
case FREEBSD_MODINFO_METADATA | FREEBSD_MODINFOMD_KERNEND:
if (is_64bit)
*(grub_uint64_t *) p_tag = kern_end;
else
*(grub_uint32_t *) p_tag = kern_end;
break;
default:
grub_memcpy (p_tag, tag->data, tag->len);
break;
}
p_tag += tag->len;
p_tag = ALIGN_VAR (p_tag - p) + p;
}
grub_memcpy (p, mod_buf, mod_buf_len);
bi.bi_modulep = (p - p0) + p_target; bi.bi_modulep = (p - p0) + p_target;
md_ofs = p + kern_end_mdofs;
p = (ALIGN_PAGE ((p - p0) + p_target) - p_target) + p0; p = (ALIGN_PAGE ((p_tag - p0) + p_target) - p_target) + p0;
if (is_64bit)
p += 4096 * 4;
ofs = (is_64bit) ? 16 : 12;
*((grub_uint32_t *) md_ofs) = kern_end;
md_ofs -= ofs;
*((grub_uint32_t *) md_ofs) = bi.bi_envp;
md_ofs -= ofs;
*((grub_uint32_t *) md_ofs) = bootflags;
} }
bi.bi_kernend = kern_end; bi.bi_kernend = kern_end;
@ -561,7 +613,7 @@ grub_freebsd_boot (void)
grub_fatal ("cannot exit boot services"); grub_fatal ("cannot exit boot services");
#endif #endif
pagetable = p - (4096 * 3); pagetable = p;
fill_bsd64_pagetable (pagetable, (pagetable - p0) + p_target); fill_bsd64_pagetable (pagetable, (pagetable - p0) + p_target);
state.cr3 = (pagetable - p0) + p_target; state.cr3 = (pagetable - p0) + p_target;
@ -721,99 +773,57 @@ static grub_err_t
grub_netbsd_boot (void) grub_netbsd_boot (void)
{ {
struct grub_netbsd_bootinfo *bootinfo; struct grub_netbsd_bootinfo *bootinfo;
int count = 0;
struct grub_netbsd_btinfo_mmap_header *mmap;
struct grub_netbsd_btinfo_mmap_entry *pm;
void *curarg, *arg0; void *curarg, *arg0;
grub_addr_t arg_target, stack_target; grub_addr_t arg_target, stack_target;
grub_uint32_t *stack; grub_uint32_t *stack;
grub_err_t err; grub_err_t err;
struct grub_relocator32_state state; struct grub_relocator32_state state;
grub_size_t tag_buf_len = 0;
int tag_count = 0;
err = grub_bsd_add_mmap ();
if (err)
return err;
auto int NESTED_FUNC_ATTR count_hook (grub_uint64_t, grub_uint64_t, grub_uint32_t);
int NESTED_FUNC_ATTR count_hook (grub_uint64_t addr __attribute__ ((unused)),
grub_uint64_t size __attribute__ ((unused)),
grub_uint32_t type __attribute__ ((unused)))
{ {
count++; struct bsd_tag *tag;
return 0; tag_buf_len = 0;
} for (tag = tags; tag; tag = tag->next)
auto int NESTED_FUNC_ATTR fill_hook (grub_uint64_t, grub_uint64_t, grub_uint32_t);
int NESTED_FUNC_ATTR fill_hook (grub_uint64_t addr, grub_uint64_t size, grub_uint32_t type)
{
pm->addr = addr;
pm->len = size;
switch (type)
{ {
case GRUB_MACHINE_MEMORY_AVAILABLE: tag_buf_len = ALIGN_VAR (tag_buf_len + 2 * sizeof (grub_uint32_t)
pm->type = NETBSD_MMAP_AVAILABLE; + tag->len);
break; tag_count++;
case GRUB_MACHINE_MEMORY_ACPI:
pm->type = NETBSD_MMAP_ACPI;
break;
case GRUB_MACHINE_MEMORY_NVS:
pm->type = NETBSD_MMAP_NVS;
break;
default:
pm->type = NETBSD_MMAP_RESERVED;
break;
} }
pm++;
return 0;
} }
grub_mmap_iterate (count_hook);
arg_target = kern_end; arg_target = kern_end;
err = grub_relocator_alloc_chunk_addr err = grub_relocator_alloc_chunk_addr (relocator, &curarg,
(relocator, &curarg, arg_target, arg_target, tag_buf_len
sizeof (struct grub_netbsd_btinfo_rootdevice) + sizeof (struct grub_netbsd_bootinfo)
+ sizeof (struct grub_netbsd_bootinfo) + tag_count * sizeof (grub_addr_t));
+ sizeof (struct grub_netbsd_btinfo_mmap_header)
+ count * sizeof (struct grub_netbsd_btinfo_mmap_entry));
if (err) if (err)
return err; return err;
arg0 = curarg; arg0 = curarg;
mmap = curarg; bootinfo = (void *) ((grub_uint8_t *) arg0 + tag_buf_len);
pm = (struct grub_netbsd_btinfo_mmap_entry *) (mmap + 1);
grub_mmap_iterate (fill_hook); {
mmap->common.type = NETBSD_BTINFO_MEMMAP; struct bsd_tag *tag;
mmap->common.len = (char *) pm - (char *) mmap; unsigned i;
mmap->count = count;
curarg = pm;
if (netbsd_root) bootinfo->bi_count = tag_count;
{ for (tag = tags, i = 0; tag; i++, tag = tag->next)
struct grub_netbsd_btinfo_rootdevice *rootdev; {
struct grub_netbsd_btinfo_common *head = curarg;
rootdev = (struct grub_netbsd_btinfo_rootdevice *) curarg; bootinfo->bi_data[i] = ((grub_uint8_t *) curarg - (grub_uint8_t *) arg0)
+ arg_target;
rootdev->common.len = sizeof (struct grub_netbsd_btinfo_rootdevice); head->type = tag->type;
rootdev->common.type = NETBSD_BTINFO_ROOTDEVICE; head->len = tag->len + sizeof (*head);
grub_strncpy (rootdev->devname, netbsd_root, sizeof (rootdev->devname)); curarg = head + 1;
grub_memcpy (curarg, tag->data, tag->len);
bootinfo = (struct grub_netbsd_bootinfo *) (rootdev + 1); curarg = (grub_uint8_t *) curarg + tag->len;
bootinfo->bi_count = 2; }
bootinfo->bi_data[0] = ((grub_uint8_t *) mmap - (grub_uint8_t *) arg0) }
+ arg_target;
bootinfo->bi_data[1] = ((grub_uint8_t *) rootdev - (grub_uint8_t *) arg0)
+ arg_target;
}
else
{
bootinfo = (struct grub_netbsd_bootinfo *) curarg;
bootinfo->bi_count = 1;
bootinfo->bi_data[0] = ((grub_uint8_t *) mmap - (grub_uint8_t *) arg0)
+ arg_target;
}
err = grub_relocator_alloc_chunk_align (relocator, (void **) &stack, err = grub_relocator_alloc_chunk_align (relocator, (void **) &stack,
&stack_target, 0x10000, 0x90000, &stack_target, 0x10000, 0x90000,
@ -843,19 +853,18 @@ grub_netbsd_boot (void)
static grub_err_t static grub_err_t
grub_bsd_unload (void) grub_bsd_unload (void)
{ {
if (mod_buf) struct bsd_tag *tag, *next;
for (tag = tags; tag; tag = next)
{ {
grub_free (mod_buf); next = tag->next;
mod_buf = 0; grub_free (tag);
mod_buf_max = 0;
} }
tags = NULL;
tags_last = NULL;
kernel_type = KERNEL_TYPE_NONE; kernel_type = KERNEL_TYPE_NONE;
grub_dl_unref (my_mod); grub_dl_unref (my_mod);
grub_free (netbsd_root);
netbsd_root = NULL;
grub_relocator_unload (relocator); grub_relocator_unload (relocator);
relocator = NULL; relocator = NULL;
@ -1163,28 +1172,22 @@ grub_cmd_freebsd (grub_extcmd_t cmd, int argc, char *argv[])
if (err) if (err)
return err; return err;
err = grub_freebsd_add_meta (FREEBSD_MODINFO_METADATA | err = grub_bsd_add_meta (FREEBSD_MODINFO_METADATA |
FREEBSD_MODINFOMD_HOWTO, &data, 4); FREEBSD_MODINFOMD_HOWTO, &data, 4);
if (err) if (err)
return err; return err;
err = grub_freebsd_add_meta (FREEBSD_MODINFO_METADATA | err = grub_bsd_add_meta (FREEBSD_MODINFO_METADATA |
FREEBSD_MODINFOMD_ENVP, &data, len); FREEBSD_MODINFOMD_ENVP, &data, len);
if (err) if (err)
return err; return err;
err = grub_freebsd_add_meta (FREEBSD_MODINFO_METADATA | err = grub_bsd_add_meta (FREEBSD_MODINFO_METADATA |
FREEBSD_MODINFOMD_KERNEND, &data, len); FREEBSD_MODINFOMD_KERNEND, &data, len);
if (err)
return err;
kern_end_mdofs = mod_buf_len - len;
err = grub_freebsd_add_mmap ();
if (err) if (err)
return err; return err;
} }
grub_loader_set (grub_freebsd_boot, grub_bsd_unload, 1); grub_loader_set (grub_freebsd_boot, grub_bsd_unload, 0);
} }
return grub_errno; return grub_errno;
@ -1239,8 +1242,61 @@ grub_cmd_netbsd (grub_extcmd_t cmd, int argc, char *argv[])
if (grub_bsd_load (argc, argv) == GRUB_ERR_NONE) if (grub_bsd_load (argc, argv) == GRUB_ERR_NONE)
{ {
grub_loader_set (grub_netbsd_boot, grub_bsd_unload, 0); grub_loader_set (grub_netbsd_boot, grub_bsd_unload, 0);
{
char bootpath[GRUB_NETBSD_MAX_BOOTPATH_LEN];
char *name;
name = grub_strrchr (argv[0], '/');
if (name)
name++;
else
name = argv[0];
grub_memset (bootpath, 0, sizeof (bootpath));
grub_strncpy (bootpath, name, sizeof (bootpath) - 1);
grub_bsd_add_meta (NETBSD_BTINFO_BOOTPATH, bootpath, sizeof (bootpath));
}
if (cmd->state[NETBSD_ROOT_ARG].set) if (cmd->state[NETBSD_ROOT_ARG].set)
netbsd_root = grub_strdup (cmd->state[NETBSD_ROOT_ARG].arg); {
char root[GRUB_NETBSD_MAX_ROOTDEVICE_LEN];
grub_memset (root, 0, sizeof (root));
grub_strncpy (root, cmd->state[NETBSD_ROOT_ARG].arg,
sizeof (root) - 1);
grub_bsd_add_meta (NETBSD_BTINFO_ROOTDEVICE, root, sizeof (root));
}
if (cmd->state[NETBSD_SERIAL_ARG].set)
{
struct grub_netbsd_btinfo_serial serial;
char *ptr;
grub_memset (&serial, 0, sizeof (serial));
grub_strcpy (serial.devname, "com");
if (cmd->state[NETBSD_SERIAL_ARG].arg)
{
ptr = cmd->state[NETBSD_SERIAL_ARG].arg;
serial.addr = grub_strtoul (ptr, &ptr, 0);
if (grub_errno)
return grub_errno;
if (*ptr != ',')
return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid format");
ptr++;
serial.speed = grub_strtoul (ptr, &ptr, 0);
if (grub_errno)
return grub_errno;
}
grub_bsd_add_meta (NETBSD_BTINFO_CONSOLE, &serial, sizeof (serial));
}
else
{
struct grub_netbsd_btinfo_serial cons;
grub_memset (&cons, 0, sizeof (cons));
grub_strcpy (cons.devname, "pc");
grub_bsd_add_meta (NETBSD_BTINFO_CONSOLE, &cons, sizeof (cons));
}
} }
return grub_errno; return grub_errno;
@ -1495,10 +1551,5 @@ GRUB_MOD_FINI (bsd)
grub_unregister_command (cmd_freebsd_module); grub_unregister_command (cmd_freebsd_module);
grub_unregister_command (cmd_freebsd_module_elf); grub_unregister_command (cmd_freebsd_module_elf);
if (mod_buf) grub_bsd_unload ();
{
grub_free (mod_buf);
mod_buf = 0;
mod_buf_max = 0;
}
} }

View file

@ -146,13 +146,13 @@ SUFFIX (grub_freebsd_load_elfmodule_obj) (struct grub_relocator *relocator,
argc - 1, argv + 1, module, argc - 1, argv + 1, module,
curload - module); curload - module);
if (! err) if (! err)
err = grub_freebsd_add_meta (FREEBSD_MODINFO_METADATA err = grub_bsd_add_meta (FREEBSD_MODINFO_METADATA
| FREEBSD_MODINFOMD_ELFHDR, | FREEBSD_MODINFOMD_ELFHDR,
&e, sizeof (e)); &e, sizeof (e));
if (! err) if (! err)
err = grub_freebsd_add_meta (FREEBSD_MODINFO_METADATA err = grub_bsd_add_meta (FREEBSD_MODINFO_METADATA
| FREEBSD_MODINFOMD_SHDR, | FREEBSD_MODINFOMD_SHDR,
shdr, e.e_shnum * e.e_shentsize); shdr, e.e_shnum * e.e_shentsize);
return err; return err;
} }
@ -275,9 +275,9 @@ SUFFIX (grub_freebsd_load_elf_meta) (struct grub_relocator *relocator,
if (err) if (err)
return err; return err;
err = grub_freebsd_add_meta (FREEBSD_MODINFO_METADATA | err = grub_bsd_add_meta (FREEBSD_MODINFO_METADATA |
FREEBSD_MODINFOMD_ELFHDR, &e, FREEBSD_MODINFOMD_ELFHDR, &e,
sizeof (e)); sizeof (e));
if (err) if (err)
return err; return err;
@ -346,22 +346,22 @@ SUFFIX (grub_freebsd_load_elf_meta) (struct grub_relocator *relocator,
{ {
dynamic = sym->st_value; dynamic = sym->st_value;
grub_dprintf ("bsd", "dynamic = %llx\n", (unsigned long long) dynamic); grub_dprintf ("bsd", "dynamic = %llx\n", (unsigned long long) dynamic);
err = grub_freebsd_add_meta (FREEBSD_MODINFO_METADATA | err = grub_bsd_add_meta (FREEBSD_MODINFO_METADATA |
FREEBSD_MODINFOMD_DYNAMIC, &dynamic, FREEBSD_MODINFOMD_DYNAMIC, &dynamic,
sizeof (dynamic)); sizeof (dynamic));
if (err) if (err)
return err; return err;
} }
err = grub_freebsd_add_meta (FREEBSD_MODINFO_METADATA | err = grub_bsd_add_meta (FREEBSD_MODINFO_METADATA |
FREEBSD_MODINFOMD_SSYM, &symstart, FREEBSD_MODINFOMD_SSYM, &symstart,
sizeof (symstart)); sizeof (symstart));
if (err) if (err)
return err; return err;
err = grub_freebsd_add_meta (FREEBSD_MODINFO_METADATA | err = grub_bsd_add_meta (FREEBSD_MODINFO_METADATA |
FREEBSD_MODINFOMD_ESYM, &symend, FREEBSD_MODINFOMD_ESYM, &symend,
sizeof (symend)); sizeof (symend));
if (err) if (err)
return err; return err;
@ -369,3 +369,5 @@ SUFFIX (grub_freebsd_load_elf_meta) (struct grub_relocator *relocator,
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
} }