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;
} __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_SINGLE (1 << 1) /* reboot to single user only */
#define OPENBSD_RB_NOSYNC (1 << 2) /* dont sync before reboot */
@ -198,48 +204,21 @@ struct grub_openbsd_bootargs
struct grub_netbsd_bootinfo
{
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_ROOTDEVICE 1
#define NETBSD_BTINFO_BOOTDISK 3
#define NETBSD_BTINFO_CONSOLE 6
#define NETBSD_BTINFO_MEMMAP 9
struct grub_netbsd_btinfo_common
{
int 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 len;
grub_uint32_t type;
};
struct grub_netbsd_btinfo_bootpath
{
struct grub_netbsd_btinfo_common common;
char bootpath[80];
};
struct grub_netbsd_btinfo_rootdevice
{
struct grub_netbsd_btinfo_common common;
char devname[16];
};
#define GRUB_NETBSD_MAX_BOOTPATH_LEN 80
struct grub_netbsd_btinfo_bootdisk
{
@ -254,6 +233,15 @@ struct grub_netbsd_btinfo_bootdisk
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_file_t file, int argc,
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_addr_t *kern_end);
grub_err_t grub_freebsd_add_meta (grub_uint32_t type, void *data,
grub_uint32_t len);
grub_err_t grub_bsd_add_meta (grub_uint32_t type,
void *data, grub_uint32_t len);
grub_err_t grub_freebsd_add_meta_module (char *filename, char *type,
int argc, char **argv,
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_PAGE(a) ALIGN_UP (a, 4096)
#define MOD_BUF_ALLOC_UNIT 4096
static int kernel_type = KERNEL_TYPE_NONE;
static grub_dl_t my_mod;
static grub_addr_t entry, entry_hi, kern_start, kern_end;
static void *kern_chunk_src;
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 char *netbsd_root = NULL;
static grub_uint32_t openbsd_root;
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[] =
{
{"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},
{"silent", 'z', 0, N_("Supress normal output (warnings remain)."), 0, 0},
{"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}
};
@ -139,6 +150,7 @@ static const grub_uint32_t netbsd_flags[] =
};
#define NETBSD_ROOT_ARG (ARRAY_SIZE (netbsd_flags) - 1)
#define NETBSD_SERIAL_ARG (ARRAY_SIZE (netbsd_flags))
static void
grub_bsd_get_device (grub_uint32_t * biosdev,
@ -180,36 +192,23 @@ grub_bsd_get_device (grub_uint32_t * biosdev,
}
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)
{
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;
struct bsd_tag *newtag;
newtag = grub_malloc (len + sizeof (struct bsd_tag));
if (!newtag)
return grub_errno;
newtag->len = len;
newtag->type = type;
newtag->next = NULL;
if (len)
grub_memcpy (mod_buf + mod_buf_len, data, len);
mod_buf_len = ALIGN_VAR (mod_buf_len + len);
grub_memcpy (newtag->data, data, len);
if (tags_last)
tags_last->next = newtag;
else
tags = newtag;
tags_last = newtag;
return GRUB_ERR_NONE;
}
@ -226,13 +225,13 @@ struct grub_e820_mmap
#define GRUB_E820_NVS 4
#define GRUB_E820_EXEC_CODE 5
static grub_err_t
grub_freebsd_add_mmap (void)
static void
generate_e820_mmap (grub_size_t *len, grub_size_t *cnt, void *buf)
{
grub_size_t len = 0;
struct grub_e820_mmap *mmap_buf = 0;
struct grub_e820_mmap *mmap = 0;
int count = 0;
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);
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.
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)
{
mmap->addr = 0;
mmap->size = (addr < 0x10000) ? addr : 0x10000;
mmap->type = GRUB_E820_RAM;
mmap++;
}
else
len += sizeof (struct grub_e820_mmap);
*mmap++ = cur;
prev = cur;
count++;
}
isfirstrun = 0;
if (mmap)
cur.addr = addr;
cur.size = size;
switch (type)
{
mmap->addr = addr;
mmap->size = size;
switch (type)
{
case GRUB_MACHINE_MEMORY_AVAILABLE:
mmap->type = GRUB_E820_RAM;
break;
case GRUB_MACHINE_MEMORY_AVAILABLE:
cur.type = GRUB_E820_RAM;
break;
#ifdef GRUB_MACHINE_MEMORY_ACPI
case GRUB_MACHINE_MEMORY_ACPI:
mmap->type = GRUB_E820_ACPI;
break;
case GRUB_MACHINE_MEMORY_ACPI:
cur.type = GRUB_E820_ACPI;
break;
#endif
#ifdef GRUB_MACHINE_MEMORY_NVS
case GRUB_MACHINE_MEMORY_NVS:
mmap->type = GRUB_E820_NVS;
break;
case GRUB_MACHINE_MEMORY_NVS:
cur.type = GRUB_E820_NVS;
break;
#endif
default:
default:
#ifdef GRUB_MACHINE_MEMORY_CODE
case GRUB_MACHINE_MEMORY_CODE:
case GRUB_MACHINE_MEMORY_CODE:
#endif
#ifdef GRUB_MACHINE_MEMORY_RESERVED
case GRUB_MACHINE_MEMORY_RESERVED:
case GRUB_MACHINE_MEMORY_RESERVED:
#endif
mmap->type = GRUB_E820_RESERVED;
break;
}
cur.type = GRUB_E820_RESERVED;
break;
}
/* Merge regions if possible. */
if (mmap != mmap_buf && mmap->type == mmap[-1].type &&
mmap->addr == mmap[-1].addr + mmap[-1].size)
mmap[-1].size += mmap->size;
else
mmap++;
/* Merge regions if possible. */
if (count && cur.type == prev.type && cur.addr == prev.addr + prev.size)
{
prev.size += cur.size;
if (mmap)
mmap[-1] = cur;
}
else
len += sizeof (struct grub_e820_mmap);
{
if (mmap)
*mmap++ = cur;
prev = cur;
count++;
}
return 0;
}
grub_mmap_iterate (hook);
mmap_buf = mmap = grub_malloc (len);
if (! mmap)
return grub_errno;
isfirstrun = 1;
grub_mmap_iterate (hook);
len = (mmap - mmap_buf) * sizeof (struct grub_e820_mmap);
int i;
for (i = 0; i < mmap - mmap_buf; i++)
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);
if (len)
*len = count * sizeof (struct grub_e820_mmap);
*cnt = count;
grub_dprintf ("bsd", "%ld entries in smap\n", (long) (mmap - mmap_buf));
grub_freebsd_add_meta (FREEBSD_MODINFO_METADATA |
FREEBSD_MODINFOMD_SMAP, mmap_buf, len);
return;
}
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;
}
@ -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)
name = "/boot/zfs/zpool.cache";
if (grub_freebsd_add_meta (FREEBSD_MODINFO_NAME, name,
grub_strlen (name) + 1))
if (grub_bsd_add_meta (FREEBSD_MODINFO_NAME, name, grub_strlen (name) + 1))
return grub_errno;
if (is_64bit)
{
grub_uint64_t addr64 = addr, size64 = size;
if ((grub_freebsd_add_meta (FREEBSD_MODINFO_TYPE, type,
grub_strlen (type) + 1)) ||
(grub_freebsd_add_meta (FREEBSD_MODINFO_ADDR, &addr64,
sizeof (addr64))) ||
(grub_freebsd_add_meta (FREEBSD_MODINFO_SIZE, &size64,
sizeof (size64))))
if (grub_bsd_add_meta (FREEBSD_MODINFO_TYPE, type, grub_strlen (type) + 1)
|| grub_bsd_add_meta (FREEBSD_MODINFO_ADDR, &addr64, sizeof (addr64))
|| grub_bsd_add_meta (FREEBSD_MODINFO_SIZE, &size64, sizeof (size64)))
return grub_errno;
}
else
{
if ((grub_freebsd_add_meta (FREEBSD_MODINFO_TYPE, type,
grub_strlen (type) + 1)) ||
(grub_freebsd_add_meta (FREEBSD_MODINFO_ADDR, &addr,
sizeof (addr))) ||
(grub_freebsd_add_meta (FREEBSD_MODINFO_SIZE, &size,
sizeof (size))))
if (grub_bsd_add_meta (FREEBSD_MODINFO_TYPE, type, grub_strlen (type) + 1)
|| grub_bsd_add_meta (FREEBSD_MODINFO_ADDR, &addr, sizeof (addr))
|| grub_bsd_add_meta (FREEBSD_MODINFO_SIZE, &size, sizeof (size)))
return grub_errno;
}
@ -386,7 +402,7 @@ grub_freebsd_add_meta_module (char *filename, char *type, int argc, char **argv,
}
*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;
}
}
@ -397,27 +413,23 @@ grub_freebsd_add_meta_module (char *filename, char *type, int argc, char **argv,
static 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");
while (pos < mod_buf_len)
{
grub_uint32_t type, size;
type = *((grub_uint32_t *) (mod_buf + pos));
size = *((grub_uint32_t *) (mod_buf + pos + 4));
pos += 8;
switch (type)
for (tag = tags; tag; tag = tag->next)
{
switch (tag->type)
{
case FREEBSD_MODINFO_NAME:
case FREEBSD_MODINFO_TYPE:
grub_printf (" %-18s", mod_buf + pos);
grub_printf (" %-18s", (char *) tag->data);
break;
case FREEBSD_MODINFO_ADDR:
{
grub_uint32_t addr;
addr = *((grub_uint32_t *) (mod_buf + pos));
addr = *((grub_uint32_t *) tag->data);
grub_printf (" 0x%08x", addr);
break;
}
@ -425,12 +437,10 @@ grub_freebsd_list_modules (void)
{
grub_uint32_t len;
len = *((grub_uint32_t *) (mod_buf + pos));
len = *((grub_uint32_t *) tag->data);
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_uint32_t bootdev, biosdev, unit, slice, part;
grub_err_t err;
grub_size_t tag_buf_len = 0;
auto 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;
}
grub_memset (&bi, 0, sizeof (bi));
bi.bi_version = FREEBSD_BOOTINFO_VERSION;
bi.bi_size = sizeof (bi);
@ -488,10 +498,29 @@ grub_freebsd_boot (void)
p_size = 0;
grub_env_iterate (iterate_env_count);
if (p_size)
p_size = ALIGN_PAGE (kern_end + p_size + 1) - kern_end;
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)
p_size += 4096 * 3;
@ -515,27 +544,50 @@ grub_freebsd_boot (void)
if (is_elf_kernel)
{
grub_uint8_t *md_ofs;
int ofs;
grub_uint8_t *p_tag = p;
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))
return grub_errno;
case FREEBSD_MODINFO_METADATA | FREEBSD_MODINFOMD_ENVP:
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;
md_ofs = p + kern_end_mdofs;
p = (ALIGN_PAGE ((p - 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;
p = (ALIGN_PAGE ((p_tag - p0) + p_target) - p_target) + p0;
}
bi.bi_kernend = kern_end;
@ -561,7 +613,7 @@ grub_freebsd_boot (void)
grub_fatal ("cannot exit boot services");
#endif
pagetable = p - (4096 * 3);
pagetable = p;
fill_bsd64_pagetable (pagetable, (pagetable - p0) + p_target);
state.cr3 = (pagetable - p0) + p_target;
@ -721,99 +773,57 @@ static grub_err_t
grub_netbsd_boot (void)
{
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;
grub_addr_t arg_target, stack_target;
grub_uint32_t *stack;
grub_err_t err;
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++;
return 0;
}
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)
struct bsd_tag *tag;
tag_buf_len = 0;
for (tag = tags; tag; tag = tag->next)
{
case GRUB_MACHINE_MEMORY_AVAILABLE:
pm->type = NETBSD_MMAP_AVAILABLE;
break;
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;
tag_buf_len = ALIGN_VAR (tag_buf_len + 2 * sizeof (grub_uint32_t)
+ tag->len);
tag_count++;
}
pm++;
return 0;
}
grub_mmap_iterate (count_hook);
arg_target = kern_end;
err = grub_relocator_alloc_chunk_addr
(relocator, &curarg, arg_target,
sizeof (struct grub_netbsd_btinfo_rootdevice)
+ sizeof (struct grub_netbsd_bootinfo)
+ sizeof (struct grub_netbsd_btinfo_mmap_header)
+ count * sizeof (struct grub_netbsd_btinfo_mmap_entry));
err = grub_relocator_alloc_chunk_addr (relocator, &curarg,
arg_target, tag_buf_len
+ sizeof (struct grub_netbsd_bootinfo)
+ tag_count * sizeof (grub_addr_t));
if (err)
return err;
arg0 = curarg;
mmap = curarg;
pm = (struct grub_netbsd_btinfo_mmap_entry *) (mmap + 1);
bootinfo = (void *) ((grub_uint8_t *) arg0 + tag_buf_len);
grub_mmap_iterate (fill_hook);
mmap->common.type = NETBSD_BTINFO_MEMMAP;
mmap->common.len = (char *) pm - (char *) mmap;
mmap->count = count;
curarg = pm;
{
struct bsd_tag *tag;
unsigned i;
if (netbsd_root)
{
struct grub_netbsd_btinfo_rootdevice *rootdev;
rootdev = (struct grub_netbsd_btinfo_rootdevice *) curarg;
rootdev->common.len = sizeof (struct grub_netbsd_btinfo_rootdevice);
rootdev->common.type = NETBSD_BTINFO_ROOTDEVICE;
grub_strncpy (rootdev->devname, netbsd_root, sizeof (rootdev->devname));
bootinfo = (struct grub_netbsd_bootinfo *) (rootdev + 1);
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;
}
bootinfo->bi_count = tag_count;
for (tag = tags, i = 0; tag; i++, tag = tag->next)
{
struct grub_netbsd_btinfo_common *head = curarg;
bootinfo->bi_data[i] = ((grub_uint8_t *) curarg - (grub_uint8_t *) arg0)
+ arg_target;
head->type = tag->type;
head->len = tag->len + sizeof (*head);
curarg = head + 1;
grub_memcpy (curarg, tag->data, tag->len);
curarg = (grub_uint8_t *) curarg + tag->len;
}
}
err = grub_relocator_alloc_chunk_align (relocator, (void **) &stack,
&stack_target, 0x10000, 0x90000,
@ -843,19 +853,18 @@ grub_netbsd_boot (void)
static grub_err_t
grub_bsd_unload (void)
{
if (mod_buf)
struct bsd_tag *tag, *next;
for (tag = tags; tag; tag = next)
{
grub_free (mod_buf);
mod_buf = 0;
mod_buf_max = 0;
next = tag->next;
grub_free (tag);
}
tags = NULL;
tags_last = NULL;
kernel_type = KERNEL_TYPE_NONE;
grub_dl_unref (my_mod);
grub_free (netbsd_root);
netbsd_root = NULL;
grub_relocator_unload (relocator);
relocator = NULL;
@ -1163,28 +1172,22 @@ grub_cmd_freebsd (grub_extcmd_t cmd, int argc, char *argv[])
if (err)
return err;
err = grub_freebsd_add_meta (FREEBSD_MODINFO_METADATA |
FREEBSD_MODINFOMD_HOWTO, &data, 4);
err = grub_bsd_add_meta (FREEBSD_MODINFO_METADATA |
FREEBSD_MODINFOMD_HOWTO, &data, 4);
if (err)
return err;
err = grub_freebsd_add_meta (FREEBSD_MODINFO_METADATA |
err = grub_bsd_add_meta (FREEBSD_MODINFO_METADATA |
FREEBSD_MODINFOMD_ENVP, &data, len);
if (err)
return err;
err = grub_freebsd_add_meta (FREEBSD_MODINFO_METADATA |
FREEBSD_MODINFOMD_KERNEND, &data, len);
if (err)
return err;
kern_end_mdofs = mod_buf_len - len;
err = grub_freebsd_add_mmap ();
err = grub_bsd_add_meta (FREEBSD_MODINFO_METADATA |
FREEBSD_MODINFOMD_KERNEND, &data, len);
if (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;
@ -1239,8 +1242,61 @@ grub_cmd_netbsd (grub_extcmd_t cmd, int argc, char *argv[])
if (grub_bsd_load (argc, argv) == GRUB_ERR_NONE)
{
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)
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;
@ -1495,10 +1551,5 @@ GRUB_MOD_FINI (bsd)
grub_unregister_command (cmd_freebsd_module);
grub_unregister_command (cmd_freebsd_module_elf);
if (mod_buf)
{
grub_free (mod_buf);
mod_buf = 0;
mod_buf_max = 0;
}
grub_bsd_unload ();
}

View file

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