/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2008,2009,2010 Free Software Foundation, Inc.
*
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/bsdlabel.h>
GRUB_MOD_LICENSE ("GPLv3+");
#ifdef GRUB_MACHINE_PCBIOS
#endif
#ifdef GRUB_MACHINE_EFI
#else
#endif
#include <grub/partition.h>
#include <grub/relocator.h>
static void *kern_chunk_src;
struct bsd_tag
{
union {
grub_uint8_t a;
} data[0];
};
struct netbsd_module
{
};
{
{"nointr", 'n', 0, "", 0, 0},
{"quiet", 'q', 0, "", 0, 0},
{0, 0, 0, 0, 0, 0}
};
{
};
{
{0, 0, 0, 0, 0, 0}
};
{
};
{
{"miniroot", 'm', 0, "", 0, 0},
{0, 0, 0, 0, 0, 0}
};
{
};
static void
{
#ifdef GRUB_MACHINE_PCBIOS
#else
*biosdev = 0xff;
#endif
*slice = 0xff;
*part = 0xff;
dev = grub_device_open (0);
{
{
}
else
}
if (dev)
}
{
if (!newtag)
return grub_errno;
if (len)
if (kernel_type == KERNEL_TYPE_FREEBSD
{
struct bsd_tag *p;
for (p = tags;
p = p->next);
if (p)
{
return GRUB_ERR_NONE;
}
}
if (tags_last)
else
return GRUB_ERR_NONE;
}
struct grub_e820_mmap
{
} __attribute__((packed));
static void
{
int count = 0;
{
switch (type)
{
case GRUB_MEMORY_AVAILABLE:
break;
case GRUB_MEMORY_ACPI:
break;
case GRUB_MEMORY_NVS:
break;
default:
case GRUB_MEMORY_CODE:
case GRUB_MEMORY_RESERVED:
break;
}
/* Merge regions if possible. */
{
if (mmap)
}
else
{
if (mmap)
count++;
}
{
if (mmap)
{
mmap++;
}
count++;
}
return 0;
}
if (len)
return;
}
static grub_err_t
grub_bsd_add_mmap (void)
{
if (kernel_type == KERNEL_TYPE_NETBSD)
len += sizeof (grub_uint32_t);
if (kernel_type == KERNEL_TYPE_OPENBSD)
len += sizeof (struct grub_e820_mmap);
if (!buf)
return grub_errno;
if (kernel_type == KERNEL_TYPE_NETBSD)
{
}
if (kernel_type == KERNEL_TYPE_OPENBSD)
sizeof (struct grub_e820_mmap));
if (kernel_type == KERNEL_TYPE_NETBSD)
else if (kernel_type == KERNEL_TYPE_OPENBSD)
else
return grub_errno;
}
{
const char *name;
if (name)
name++;
else
name = "/boot/zfs/zpool.cache";
return grub_errno;
if (is_64bit)
{
return grub_errno;
}
else
{
return grub_errno;
}
if (argc)
{
int i, n;
n = 0;
for (i = 0; i < argc; i++)
{
}
if (n)
{
char cmdline[n], *p;
p = cmdline;
for (i = 0; i < argc; i++)
{
grub_strcpy (p, argv[i]);
p += grub_strlen (argv[i]);
*(p++) = ' ';
}
*p = 0;
return grub_errno;
}
}
return GRUB_ERR_NONE;
}
static void
grub_freebsd_list_modules (void)
{
_("size"));
{
{
case FREEBSD_MODINFO_NAME:
case FREEBSD_MODINFO_TYPE:
break;
case FREEBSD_MODINFO_ADDR:
{
break;
}
case FREEBSD_MODINFO_SIZE:
{
}
}
}
}
static grub_err_t
{
char *name;
if (name)
name++;
else
if (!mod)
return grub_errno;
if (netbsd_mods_last)
else
netbsd_mods = mod;
return GRUB_ERR_NONE;
}
static void
grub_netbsd_list_modules (void)
{
_("size"));
}
/* This function would be here but it's under different license. */
#include "bsd_pagetable.c"
static grub_err_t
grub_freebsd_boot (void)
{
{
if ((!grub_memcmp (var->name, "kFreeBSD.", sizeof("kFreeBSD.") - 1)) && (var->name[sizeof("kFreeBSD.") - 1]))
{
p += grub_strlen ((char *) p);
*(p++) = '=';
p += grub_strlen ((char *) p) + 1;
}
return 0;
}
{
if ((!grub_memcmp (var->name, "kFreeBSD.", sizeof("kFreeBSD.") - 1)) && (var->name[sizeof("kFreeBSD.") - 1]))
{
p_size++;
}
return 0;
}
p_size = 0;
if (p_size)
if (is_elf_kernel)
{
err = grub_bsd_add_mmap ();
if (err)
return err;
if (err)
return err;
tag_buf_len = 0;
+ sizeof (struct freebsd_tag_header)
}
if (is_64bit)
{
if (err)
return err;
p = get_virtual_current_address (ch);
}
p0 = p;
if (p != p0)
{
*(p++) = 0;
}
if (is_elf_kernel)
{
{
= (struct freebsd_tag_header *) p_tag;
p_tag += sizeof (struct freebsd_tag_header);
{
if (is_64bit)
else
break;
if (is_64bit)
else
break;
if (is_64bit)
else
break;
default:
break;
}
}
}
grub_video_set_mode ("text", 0, 0);
if (is_64bit)
{
{
0x10000, 0x90000,
3 * sizeof (grub_uint32_t)
+ sizeof (bi), 4,
if (err)
return err;
}
#ifdef GRUB_MACHINE_EFI
if (err)
return err;
#endif
pagetable = p;
}
else
{
{
0x10000, 0x90000,
9 * sizeof (grub_uint32_t)
+ sizeof (bi), 4,
if (err)
return err;
}
#ifdef GRUB_MACHINE_EFI
if (err)
return err;
#endif
stack[3] = 0;
stack[4] = 0;
stack[5] = 0;
}
/* Not reached. */
return GRUB_ERR_NONE;
}
static grub_err_t
grub_openbsd_boot (void)
{
err = grub_bsd_add_mmap ();
if (err)
return err;
{
tag_buf_len = 0;
+ sizeof (struct grub_openbsd_bootargs)
}
{
+ sizeof (struct grub_openbsd_bootargs)
+ 9 * sizeof (grub_uint32_t));
if (err)
return err;
}
{
{
+ buf_target;
}
}
grub_video_set_mode ("text", 0, 0);
#ifdef GRUB_MACHINE_EFI
if (err)
return err;
#endif
stack[4] = 0;
}
static grub_err_t
grub_netbsd_setup_video (void)
{
void *framebuffer;
const char *modevar;
/* Now all graphical modes are acceptable.
May change in future if we have modes without framebuffer. */
{
char *tmp;
if (! tmp)
return grub_errno;
}
else
if (err)
return err;
if (driv_id == GRUB_VIDEO_DRIVER_NONE)
return GRUB_ERR_NONE;
if (err)
return err;
#ifdef GRUB_MACHINE_PCBIOS
/* VESA packed modes may come with zeroed mask sizes, which need
to be set here according to DAC Palette width. If we don't,
this results in Linux displaying a black screen. */
{
int status;
if (status == GRUB_VBE_STATUS_OK &&
if (status != GRUB_VBE_STATUS_OK)
/* 6 is default after mode reset. */
width = 6;
}
#endif
return err;
}
static grub_err_t
grub_netbsd_add_modules (void)
{
unsigned modcnt = 0;
unsigned i;
modcnt++;
if (!mods)
return grub_errno;
return err;
}
/*
* Adds NetBSD bootinfo bootdisk and bootwedge. The partition identified
* in these bootinfo fields is the root device.
*/
static void
{
union {
} buf;
dev = grub_device_open (0);
goto fail;
else
biosdev = 0xff;
/* Absolute sector of the partition map describing this partition. */
!= GRUB_ERR_NONE)
goto fail;
/* Fill bootwedge. */
{
}
/* Fill bootdisk if this a NetBSD disk label. */
{
}
fail:
if (dev)
}
static grub_err_t
grub_netbsd_boot (void)
{
int tag_count = 0;
err = grub_bsd_add_mmap ();
if (err)
return err;
err = grub_netbsd_setup_video ();
if (err)
{
grub_print_error ();
}
err = grub_netbsd_add_modules ();
if (err)
return err;
{
tag_buf_len = 0;
{
+ sizeof (struct grub_netbsd_btinfo_common)
tag_count++;
}
}
{
+ sizeof (struct grub_netbsd_bootinfo)
+ tag_count * sizeof (grub_uint32_t));
if (err)
return err;
}
{
unsigned i;
{
+ arg_target;
}
}
{
if (err)
return err;
}
#ifdef GRUB_MACHINE_EFI
if (err)
return err;
#endif
stack[2] = 0;
stack[4] = 0;
}
static grub_err_t
grub_bsd_unload (void)
{
{
}
return GRUB_ERR_NONE;
}
static grub_err_t
{
return grub_errno;
{
if (!grub_errno)
filename);
return grub_errno;
}
{
ofs = 0x1000;
align_page = 0;
}
else
{
ofs = sizeof (struct grub_aout32_header);
align_page = 1;
}
if (load_addr < 0x100000)
if (align_page)
{
if (align_page)
}
else
bss_size = 0;
{
if (err)
return err;
}
bss_size);
}
static int NESTED_FUNC_ATTR
{
return 0;
if (paddr < kern_start)
kern_start = paddr;
return 0;
}
static grub_err_t
{
{
*do_load = 0;
return 0;
}
*do_load = 1;
return GRUB_ERR_NONE;
}
static int NESTED_FUNC_ATTR
{
return 0;
if (paddr < kern_start)
kern_start = paddr;
return 0;
}
static grub_err_t
{
{
*do_load = 0;
return 0;
}
*do_load = 1;
return GRUB_ERR_NONE;
}
static grub_err_t
{
kern_end = 0;
kern_start = ~0;
if (grub_elf_is_elf32 (elf))
{
if (err)
return err;
if (err)
return err;
if (err)
return err;
if (kernel_type != KERNEL_TYPE_OPENBSD)
return GRUB_ERR_NONE;
}
else if (grub_elf_is_elf64 (elf))
{
is_64bit = 1;
if (! grub_cpuid_has_longmode)
/* FreeBSD has 64-bit entry point. */
if (kernel_type == KERNEL_TYPE_FREEBSD)
{
}
else
{
entry_hi = 0;
}
if (err)
return err;
(unsigned long) kern_start, (unsigned long) kern_end);
{
kern_end - kern_start);
if (err)
return err;
}
if (err)
return err;
if (kernel_type != KERNEL_TYPE_OPENBSD)
return GRUB_ERR_NONE;
}
else
}
static grub_err_t
{
if (argc == 0)
{
goto fail;
}
if (!file)
goto fail;
relocator = grub_relocator_new ();
if (!relocator)
{
goto fail;
}
if (elf)
{
is_elf_kernel = 1;
}
else
{
is_elf_kernel = 0;
grub_errno = 0;
}
fail:
if (grub_errno != GRUB_ERR_NONE)
return grub_errno;
}
static grub_uint32_t
const grub_uint32_t * flags)
{
unsigned i;
for (i = 0; flags[i]; i++)
return result;
}
static grub_err_t
{
{
if (is_elf_kernel)
{
kern_end - kern_start);
if (err)
return err;
if (! file)
return grub_errno;
if (is_64bit)
else
if (err)
return err;
if (err)
return err;
if (err)
return err;
if (err)
return err;
}
}
return grub_errno;
}
static grub_err_t
{
{
return grub_error (GRUB_ERR_BAD_ARGUMENT,
"only device specifications of form "
"wd<number><lowercase letter> are supported");
return grub_error (GRUB_ERR_BAD_ARGUMENT,
"only device specifications of form "
"wd<number><lowercase letter> are supported");
(part << OPENBSD_B_PARTSHIFT));
}
else
bootdev = 0;
{
char *ptr;
unsigned port = 0;
{
return grub_error (GRUB_ERR_BAD_ARGUMENT,
"only com0-com3 are supported");
if (port >= 4)
return grub_error (GRUB_ERR_BAD_ARGUMENT,
"only com0-com3 are supported");
if (*ptr == ',')
{
ptr++;
if (grub_errno)
return grub_errno;
}
}
}
else
{
}
{
}
return grub_errno;
}
static grub_err_t
{
{
if (is_elf_kernel)
{
if (! file)
return grub_errno;
if (is_64bit)
else
if (err)
return err;
}
{
char *name;
if (name)
name++;
else
}
{
sizeof (root) - 1);
}
{
char *ptr;
{
{
}
else
if (grub_errno)
return grub_errno;
if (*ptr == ',')
{
ptr++;
if (grub_errno)
return grub_errno;
}
}
}
else
{
}
}
return grub_errno;
}
static grub_err_t
{
int len;
if (! grub_loader_is_loaded ())
return grub_error (GRUB_ERR_BAD_ARGUMENT,
"you need to load the kernel first");
if (kernel_type != KERNEL_TYPE_FREEBSD)
return grub_error (GRUB_ERR_BAD_ARGUMENT,
"only FreeBSD supports environment");
if (argc == 0)
{
goto fail;
}
goto fail;
if (!buf)
goto fail;
goto fail;
while (next)
{
char *p;
if (next)
{
p = next - 1;
while (p > curr)
{
if ((*p != '\r') && (*p != ' ') && (*p != '\t'))
break;
p--;
}
if ((p > curr) && (*p == '"'))
p--;
*(p + 1) = 0;
next++;
}
if (*curr == '#')
continue;
if (!p)
continue;
*(p++) = 0;
if (*curr)
{
char *name;
if (*p == '"')
p++;
if (!name)
goto fail;
if (grub_env_set (name, p))
{
goto fail;
}
}
}
fail:
if (file)
return grub_errno;
}
static grub_err_t
{
int modargc;
char **modargv;
const char *type;
void *src;
if (kernel_type != KERNEL_TYPE_FREEBSD)
if (!is_elf_kernel)
return grub_error (GRUB_ERR_BAD_ARGUMENT,
"only ELF kernel supports module");
/* List the current modules if no parameter. */
if (!argc)
{
return 0;
}
goto fail;
{
if (err)
goto fail;
}
if (grub_errno)
goto fail;
{
modargc--;
modargv++;
}
else
if (err)
goto fail;
fail:
if (file)
return grub_errno;
}
static grub_err_t
{
void *src;
goto fail;
{
if (err)
goto fail;
}
if (grub_errno)
goto fail;
if (err)
goto fail;
fail:
if (file)
return grub_errno;
}
static grub_err_t
{
if (kernel_type != KERNEL_TYPE_NETBSD)
if (!is_elf_kernel)
return grub_error (GRUB_ERR_BAD_ARGUMENT,
"only ELF kernel supports module");
/* List the current modules if no parameter. */
if (!argc)
{
return 0;
}
else
}
static grub_err_t
{
if (! grub_loader_is_loaded ())
return grub_error (GRUB_ERR_BAD_ARGUMENT,
"you need to load the kernel first");
if (kernel_type != KERNEL_TYPE_FREEBSD)
return grub_error (GRUB_ERR_BAD_ARGUMENT,
"only FreeBSD supports module");
if (! is_elf_kernel)
return grub_error (GRUB_ERR_BAD_ARGUMENT,
"only ELF kernel supports module");
/* List the current modules if no parameter. */
if (! argc)
{
return 0;
}
if (!file)
return grub_errno;
{
return grub_errno;
}
if (is_64bit)
else
return err;
}
static grub_err_t
{
if (argc != 1)
if (kernel_type != KERNEL_TYPE_OPENBSD)
if (!openbsd_ramdisk.max_size)
if (! file)
return grub_errno;
{
" up to %u bytes, however you supplied a %u bytes one",
}
!= (grub_ssize_t) (size))
{
if (!grub_errno)
return grub_errno;
}
return GRUB_ERR_NONE;
}
{
/* Net and OpenBSD kernels are often compressed. */
grub_dl_load ("gzio");
0, N_("Load FreeBSD env."));
0, N_("Load FreeBSD kernel module."));
0, N_("Load NetBSD kernel module."));
0, N_("Load NetBSD kernel module (ELF)."));
0, N_("Load FreeBSD kernel module (ELF)."));
N_("Load kOpenBSD ramdisk."));
}
{
grub_bsd_unload ();
}