2 * GRUB -- GRand Unified Bootloader
3 * Copyright (C) 2008,2009,2010 Free Software Foundation, Inc.
5 * GRUB is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * GRUB is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
19 #include <grub/loader.h>
20 #include <grub/i386/bsd.h>
21 #include <grub/i386/cpuid.h>
22 #include <grub/memory.h>
23 #include <grub/i386/memory.h>
24 #include <grub/file.h>
28 #include <grub/elfload.h>
30 #include <grub/misc.h>
31 #include <grub/aout.h>
32 #include <grub/command.h>
33 #include <grub/extcmd.h>
34 #include <grub/i18n.h>
35 #include <grub/ns8250.h>
36 #include <grub/bsdlabel.h>
37 #include <grub/crypto.h>
38 #ifdef GRUB_MACHINE_PCBIOS
39 #include <grub/machine/int.h>
42 GRUB_MOD_LICENSE ("GPLv3+");
44 #include <grub/video.h>
45 #ifdef GRUB_MACHINE_PCBIOS
46 #include <grub/machine/biosnum.h>
48 #ifdef GRUB_MACHINE_EFI
49 #include <grub/efi/efi.h>
50 #define NETBSD_DEFAULT_VIDEO_MODE "800x600"
52 #define NETBSD_DEFAULT_VIDEO_MODE "text"
53 #include <grub/i386/pc/vbe.h>
55 #include <grub/video.h>
57 #include <grub/disk.h>
58 #include <grub/device.h>
59 #include <grub/partition.h>
60 #include <grub/relocator.h>
61 #include <grub/i386/relocator.h>
63 #define ALIGN_DWORD(a) ALIGN_UP (a, 4)
64 #define ALIGN_QWORD(a) ALIGN_UP (a, 8)
65 #define ALIGN_VAR(a) ((is_64bit) ? (ALIGN_QWORD(a)) : (ALIGN_DWORD(a)))
66 #define ALIGN_PAGE(a) ALIGN_UP (a, 4096)
68 static int kernel_type
= KERNEL_TYPE_NONE
;
69 static grub_dl_t my_mod
;
70 static grub_addr_t entry
, entry_hi
, kern_start
, kern_end
;
71 static void *kern_chunk_src
;
72 static grub_uint32_t bootflags
;
73 static int is_elf_kernel
, is_64bit
;
74 static grub_uint32_t openbsd_root
;
75 static struct grub_relocator
*relocator
= NULL
;
76 static struct grub_openbsd_ramdisk_descriptor openbsd_ramdisk
;
90 static struct bsd_tag
*tags
, *tags_last
;
94 struct netbsd_module
*next
;
95 struct grub_netbsd_btinfo_module mod
;
98 static struct netbsd_module
*netbsd_mods
, *netbsd_mods_last
;
100 static const struct grub_arg_option freebsd_opts
[] =
102 {"dual", 'D', 0, N_("Display output on all consoles."), 0, 0},
103 {"serial", 'h', 0, N_("Use serial console."), 0, 0},
104 {"askname", 'a', 0, N_("Ask for file name to reboot from."), 0, 0},
105 {"cdrom", 'C', 0, N_("Use CD-ROM as root."), 0, 0},
106 {"config", 'c', 0, N_("Invoke user configuration routing."), 0, 0},
107 {"kdb", 'd', 0, N_("Enter in KDB on boot."), 0, 0},
108 {"gdb", 'g', 0, N_("Use GDB remote debugger instead of DDB."), 0, 0},
109 {"mute", 'm', 0, N_("Disable all boot output."), 0, 0},
110 {"nointr", 'n', 0, "", 0, 0},
111 {"pause", 'p', 0, N_("Wait for keypress after every line of output."), 0, 0},
112 {"quiet", 'q', 0, "", 0, 0},
113 {"dfltroot", 'r', 0, N_("Use compiled-in root device."), 0, 0},
114 {"single", 's', 0, N_("Boot into single mode."), 0, 0},
115 {"verbose", 'v', 0, N_("Boot with verbose messages."), 0, 0},
119 static const grub_uint32_t freebsd_flags
[] =
121 FREEBSD_RB_DUAL
, FREEBSD_RB_SERIAL
, FREEBSD_RB_ASKNAME
,
122 FREEBSD_RB_CDROM
, FREEBSD_RB_CONFIG
, FREEBSD_RB_KDB
,
123 FREEBSD_RB_GDB
, FREEBSD_RB_MUTE
, FREEBSD_RB_NOINTR
,
124 FREEBSD_RB_PAUSE
, FREEBSD_RB_QUIET
, FREEBSD_RB_DFLTROOT
,
125 FREEBSD_RB_SINGLE
, FREEBSD_RB_VERBOSE
, 0
128 static const struct grub_arg_option openbsd_opts
[] =
130 {"askname", 'a', 0, N_("Ask for file name to reboot from."), 0, 0},
131 {"halt", 'b', 0, N_("Don't reboot, just halt."), 0, 0},
132 {"config", 'c', 0, N_("Change configured devices."), 0, 0},
133 {"single", 's', 0, N_("Boot into single mode."), 0, 0},
134 {"kdb", 'd', 0, N_("Enter in KDB on boot."), 0, 0},
135 {"root", 'r', 0, N_("Set root device."), "wdXY", ARG_TYPE_STRING
},
136 {"serial", 'h', GRUB_ARG_OPTION_OPTIONAL
,
137 N_("Use serial console."),
138 /* TRANSLATORS: "com" is static and not to be translated. It refers to
139 serial ports e.g. com1.
141 N_("comUNIT[,SPEED]"), ARG_TYPE_STRING
},
145 static const grub_uint32_t openbsd_flags
[] =
147 OPENBSD_RB_ASKNAME
, OPENBSD_RB_HALT
, OPENBSD_RB_CONFIG
,
148 OPENBSD_RB_SINGLE
, OPENBSD_RB_KDB
, 0
151 #define OPENBSD_ROOT_ARG (ARRAY_SIZE (openbsd_flags) - 1)
152 #define OPENBSD_SERIAL_ARG (ARRAY_SIZE (openbsd_flags))
154 static const struct grub_arg_option netbsd_opts
[] =
156 {"no-smp", '1', 0, N_("Disable SMP."), 0, 0},
157 {"no-acpi", '2', 0, N_("Disable ACPI."), 0, 0},
158 {"askname", 'a', 0, N_("Ask for file name to reboot from."), 0, 0},
159 {"halt", 'b', 0, N_("Don't reboot, just halt."), 0, 0},
160 {"config", 'c', 0, N_("Change configured devices."), 0, 0},
161 {"kdb", 'd', 0, N_("Enter in KDB on boot."), 0, 0},
162 {"miniroot", 'm', 0, "", 0, 0},
163 {"quiet", 'q', 0, N_("Don't display boot diagnostic messages."), 0, 0},
164 {"single", 's', 0, N_("Boot into single mode."), 0, 0},
165 {"verbose", 'v', 0, N_("Boot with verbose messages."), 0, 0},
166 {"debug", 'x', 0, N_("Boot with debug messages."), 0, 0},
167 {"silent", 'z', 0, N_("Suppress normal output (warnings remain)."), 0, 0},
168 {"root", 'r', 0, N_("Set root device."), N_("DEVICE"), ARG_TYPE_STRING
},
169 {"serial", 'h', GRUB_ARG_OPTION_OPTIONAL
,
170 N_("Use serial console."),
171 /* TRANSLATORS: "com" is static and not to be translated. It refers to
172 serial ports e.g. com1.
174 N_("[ADDR|comUNIT][,SPEED]"), ARG_TYPE_STRING
},
178 static const grub_uint32_t netbsd_flags
[] =
180 NETBSD_AB_NOSMP
, NETBSD_AB_NOACPI
, NETBSD_RB_ASKNAME
,
181 NETBSD_RB_HALT
, NETBSD_RB_USERCONFIG
, NETBSD_RB_KDB
,
182 NETBSD_RB_MINIROOT
, NETBSD_AB_QUIET
, NETBSD_RB_SINGLE
,
183 NETBSD_AB_VERBOSE
, NETBSD_AB_DEBUG
, NETBSD_AB_SILENT
, 0
186 #define NETBSD_ROOT_ARG (ARRAY_SIZE (netbsd_flags) - 1)
187 #define NETBSD_SERIAL_ARG (ARRAY_SIZE (netbsd_flags))
190 grub_bsd_get_device (grub_uint32_t
* biosdev
,
191 grub_uint32_t
* unit
,
192 grub_uint32_t
* slice
, grub_uint32_t
* part
)
196 #ifdef GRUB_MACHINE_PCBIOS
197 *biosdev
= grub_get_root_biosnumber () & 0xff;
201 *unit
= (*biosdev
& 0x7f);
204 dev
= grub_device_open (0);
205 if (dev
&& dev
->disk
&& dev
->disk
->partition
)
207 if (dev
->disk
->partition
->parent
)
209 *part
= dev
->disk
->partition
->number
;
210 *slice
= dev
->disk
->partition
->parent
->number
+ 1;
213 *slice
= dev
->disk
->partition
->number
+ 1;
216 grub_device_close (dev
);
220 grub_bsd_add_meta_ptr (grub_uint32_t type
, void **ptr
, grub_uint32_t len
)
222 struct bsd_tag
*newtag
;
224 newtag
= grub_malloc (len
+ sizeof (struct bsd_tag
));
232 if (kernel_type
== KERNEL_TYPE_FREEBSD
233 && type
== (FREEBSD_MODINFO_METADATA
| FREEBSD_MODINFOMD_SMAP
))
237 p
&& p
->type
!= (FREEBSD_MODINFO_METADATA
238 | FREEBSD_MODINFOMD_KERNEND
);
243 newtag
->next
= p
->next
;
245 if (newtag
->next
== NULL
)
247 return GRUB_ERR_NONE
;
252 tags_last
->next
= newtag
;
257 return GRUB_ERR_NONE
;
261 grub_bsd_add_meta (grub_uint32_t type
, const void *data
, grub_uint32_t len
)
266 err
= grub_bsd_add_meta_ptr (type
, &ptr
, len
);
270 grub_memcpy (ptr
, data
, len
);
271 return GRUB_ERR_NONE
;
275 struct grub_e820_mmap
281 #define GRUB_E820_RAM 1
282 #define GRUB_E820_RESERVED 2
283 #define GRUB_E820_ACPI 3
284 #define GRUB_E820_NVS 4
285 #define GRUB_E820_BADRAM 5
286 #define GRUB_E820_COREBOOT_TABLES 0x10
288 /* Context for generate_e820_mmap. */
289 struct generate_e820_mmap_ctx
292 struct grub_e820_mmap
*mmap
;
293 struct grub_e820_mmap prev
, cur
;
296 /* Helper for generate_e820_mmap. */
298 generate_e820_mmap_iter (grub_uint64_t addr
, grub_uint64_t size
,
299 grub_memory_type_t type
, void *data
)
301 struct generate_e820_mmap_ctx
*ctx
= data
;
303 ctx
->cur
.addr
= addr
;
304 ctx
->cur
.size
= size
;
306 if (type
== GRUB_MEMORY_COREBOOT_TABLES
308 /* Nowadays the tables at 0 don't contain anything important but
309 *BSD needs the memory at 0 for own needs.
311 type
= GRUB_E820_RAM
;
313 ctx
->cur
.type
= type
;
315 /* Merge regions if possible. */
316 if (ctx
->count
&& ctx
->cur
.type
== ctx
->prev
.type
317 && ctx
->cur
.addr
== ctx
->prev
.addr
+ ctx
->prev
.size
)
319 ctx
->prev
.size
+= ctx
->cur
.size
;
321 ctx
->mmap
[-1] = ctx
->prev
;
326 *ctx
->mmap
++ = ctx
->cur
;
327 ctx
->prev
= ctx
->cur
;
331 if (kernel_type
== KERNEL_TYPE_OPENBSD
&& ctx
->prev
.addr
< 0x100000
332 && ctx
->prev
.addr
+ ctx
->prev
.size
> 0x100000)
334 ctx
->cur
.addr
= 0x100000;
335 ctx
->cur
.size
= ctx
->prev
.addr
+ ctx
->prev
.size
- 0x100000;
336 ctx
->cur
.type
= ctx
->prev
.type
;
337 ctx
->prev
.size
= 0x100000 - ctx
->prev
.addr
;
340 ctx
->mmap
[-1] = ctx
->prev
;
341 ctx
->mmap
[0] = ctx
->cur
;
344 ctx
->prev
= ctx
->cur
;
352 generate_e820_mmap (grub_size_t
*len
, grub_size_t
*cnt
, void *buf
)
354 struct generate_e820_mmap_ctx ctx
= {
359 grub_mmap_iterate (generate_e820_mmap_iter
, &ctx
);
362 *len
= ctx
.count
* sizeof (struct grub_e820_mmap
);
369 grub_bsd_add_mmap (void)
371 grub_size_t len
, cnt
;
372 void *buf
= NULL
, *buf0
;
374 generate_e820_mmap (&len
, &cnt
, buf
);
376 if (kernel_type
== KERNEL_TYPE_NETBSD
)
377 len
+= sizeof (grub_uint32_t
);
379 if (kernel_type
== KERNEL_TYPE_OPENBSD
)
380 len
+= sizeof (struct grub_e820_mmap
);
382 buf
= grub_malloc (len
);
387 if (kernel_type
== KERNEL_TYPE_NETBSD
)
389 *(grub_uint32_t
*) buf
= cnt
;
390 buf
= ((grub_uint32_t
*) buf
+ 1);
393 generate_e820_mmap (NULL
, &cnt
, buf
);
395 if (kernel_type
== KERNEL_TYPE_OPENBSD
)
396 grub_memset ((grub_uint8_t
*) buf
+ len
- sizeof (struct grub_e820_mmap
), 0,
397 sizeof (struct grub_e820_mmap
));
399 grub_dprintf ("bsd", "%u entries in smap\n", (unsigned) cnt
);
400 if (kernel_type
== KERNEL_TYPE_NETBSD
)
401 grub_bsd_add_meta (NETBSD_BTINFO_MEMMAP
, buf0
, len
);
402 else if (kernel_type
== KERNEL_TYPE_OPENBSD
)
403 grub_bsd_add_meta (OPENBSD_BOOTARG_MMAP
, buf0
, len
);
405 grub_bsd_add_meta (FREEBSD_MODINFO_METADATA
|
406 FREEBSD_MODINFOMD_SMAP
, buf0
, len
);
414 grub_freebsd_add_meta_module (const char *filename
, const char *type
,
415 int argc
, char **argv
,
416 grub_addr_t addr
, grub_uint32_t size
)
419 name
= grub_strrchr (filename
, '/');
424 if (grub_strcmp (type
, "/boot/zfs/zpool.cache") == 0)
425 name
= "/boot/zfs/zpool.cache";
427 if (grub_bsd_add_meta (FREEBSD_MODINFO_NAME
, name
, grub_strlen (name
) + 1))
432 grub_uint64_t addr64
= addr
, size64
= size
;
433 if (grub_bsd_add_meta (FREEBSD_MODINFO_TYPE
, type
, grub_strlen (type
) + 1)
434 || grub_bsd_add_meta (FREEBSD_MODINFO_ADDR
, &addr64
, sizeof (addr64
))
435 || grub_bsd_add_meta (FREEBSD_MODINFO_SIZE
, &size64
, sizeof (size64
)))
440 if (grub_bsd_add_meta (FREEBSD_MODINFO_TYPE
, type
, grub_strlen (type
) + 1)
441 || grub_bsd_add_meta (FREEBSD_MODINFO_ADDR
, &addr
, sizeof (addr
))
442 || grub_bsd_add_meta (FREEBSD_MODINFO_SIZE
, &size
, sizeof (size
)))
451 for (i
= 0; i
< argc
; i
++)
453 n
+= grub_strlen (argv
[i
]) + 1;
461 if (grub_bsd_add_meta_ptr (FREEBSD_MODINFO_ARGS
, &cmdline
, n
))
465 for (i
= 0; i
< argc
; i
++)
467 grub_strcpy (p
, argv
[i
]);
468 p
+= grub_strlen (argv
[i
]);
475 return GRUB_ERR_NONE
;
479 grub_freebsd_list_modules (void)
483 grub_printf (" %-18s %-18s%14s%14s\n", _("name"), _("type"), _("addr"),
486 for (tag
= tags
; tag
; tag
= tag
->next
)
490 case FREEBSD_MODINFO_NAME
:
491 case FREEBSD_MODINFO_TYPE
:
492 grub_printf (" %-18s", (char *) tag
->data
);
494 case FREEBSD_MODINFO_ADDR
:
498 addr
= *((grub_uint32_t
*) tag
->data
);
499 grub_printf (" 0x%08x", addr
);
502 case FREEBSD_MODINFO_SIZE
:
506 len
= *((grub_uint32_t
*) tag
->data
);
507 grub_printf (" 0x%08x\n", len
);
514 grub_netbsd_add_meta_module (char *filename
, grub_uint32_t type
,
515 grub_addr_t addr
, grub_uint32_t size
)
518 struct netbsd_module
*mod
;
519 name
= grub_strrchr (filename
, '/');
526 mod
= grub_zalloc (sizeof (*mod
));
530 grub_strncpy (mod
->mod
.name
, name
, sizeof (mod
->mod
.name
) - 1);
531 mod
->mod
.addr
= addr
;
532 mod
->mod
.type
= type
;
533 mod
->mod
.size
= size
;
535 if (netbsd_mods_last
)
536 netbsd_mods_last
->next
= mod
;
539 netbsd_mods_last
= mod
;
541 return GRUB_ERR_NONE
;
545 grub_netbsd_list_modules (void)
547 struct netbsd_module
*mod
;
549 grub_printf (" %-18s%14s%14s%14s\n", _("name"), _("type"), _("addr"),
552 for (mod
= netbsd_mods
; mod
; mod
= mod
->next
)
553 grub_printf (" %-18s 0x%08x 0x%08x 0x%08x", mod
->mod
.name
,
554 mod
->mod
.type
, mod
->mod
.addr
, mod
->mod
.size
);
557 /* This function would be here but it's under different license. */
558 #include "bsd_pagetable.c"
560 static grub_uint32_t freebsd_bootdev
, freebsd_biosdev
;
561 static grub_uint64_t freebsd_zfsguid
;
564 freebsd_get_zfs (void)
571 dev
= grub_device_open (0);
574 fs
= grub_fs_probe (dev
);
577 if (!fs
->uuid
|| grub_strcmp (fs
->name
, "zfs") != 0)
579 err
= fs
->uuid (dev
, &uuid
);
584 freebsd_zfsguid
= grub_strtoull (uuid
, 0, 16);
589 grub_freebsd_boot (void)
591 struct grub_freebsd_bootinfo bi
;
592 grub_uint8_t
*p
, *p0
;
593 grub_addr_t p_target
;
594 grub_size_t p_size
= 0;
596 grub_size_t tag_buf_len
= 0;
598 struct grub_env_var
*var
;
600 grub_memset (&bi
, 0, sizeof (bi
));
601 bi
.version
= FREEBSD_BOOTINFO_VERSION
;
602 bi
.length
= sizeof (bi
);
604 bi
.boot_device
= freebsd_biosdev
;
608 if ((grub_memcmp (var
->name
, "kFreeBSD.", sizeof("kFreeBSD.") - 1) == 0) && (var
->name
[sizeof("kFreeBSD.") - 1]))
610 p_size
+= grub_strlen (&var
->name
[sizeof("kFreeBSD.") - 1]);
612 p_size
+= grub_strlen (var
->value
) + 1;
616 p_size
= ALIGN_PAGE (kern_end
+ p_size
+ 1) - kern_end
;
622 err
= grub_bsd_add_mmap ();
626 err
= grub_bsd_add_meta (FREEBSD_MODINFO_END
, 0, 0);
631 for (tag
= tags
; tag
; tag
= tag
->next
)
632 tag_buf_len
= ALIGN_VAR (tag_buf_len
633 + sizeof (struct freebsd_tag_header
)
635 p_size
= ALIGN_PAGE (kern_end
+ p_size
+ tag_buf_len
) - kern_end
;
642 grub_relocator_chunk_t ch
;
643 err
= grub_relocator_alloc_chunk_addr (relocator
, &ch
,
647 p
= get_virtual_current_address (ch
);
654 if ((grub_memcmp (var
->name
, "kFreeBSD.", sizeof("kFreeBSD.") - 1) == 0) && (var
->name
[sizeof("kFreeBSD.") - 1]))
656 grub_strcpy ((char *) p
, &var
->name
[sizeof("kFreeBSD.") - 1]);
657 p
+= grub_strlen ((char *) p
);
659 grub_strcpy ((char *) p
, var
->value
);
660 p
+= grub_strlen ((char *) p
) + 1;
667 bi
.environment
= p_target
;
672 grub_uint8_t
*p_tag
= p
;
675 for (tag
= tags
; tag
; tag
= tag
->next
)
677 struct freebsd_tag_header
*head
678 = (struct freebsd_tag_header
*) p_tag
;
679 head
->type
= tag
->type
;
680 head
->len
= tag
->len
;
681 p_tag
+= sizeof (struct freebsd_tag_header
);
684 case FREEBSD_MODINFO_METADATA
| FREEBSD_MODINFOMD_HOWTO
:
686 *(grub_uint64_t
*) p_tag
= bootflags
;
688 *(grub_uint32_t
*) p_tag
= bootflags
;
691 case FREEBSD_MODINFO_METADATA
| FREEBSD_MODINFOMD_ENVP
:
693 *(grub_uint64_t
*) p_tag
= bi
.environment
;
695 *(grub_uint32_t
*) p_tag
= bi
.environment
;
698 case FREEBSD_MODINFO_METADATA
| FREEBSD_MODINFOMD_KERNEND
:
700 *(grub_uint64_t
*) p_tag
= kern_end
;
702 *(grub_uint32_t
*) p_tag
= kern_end
;
706 grub_memcpy (p_tag
, tag
->data
, tag
->len
);
710 p_tag
= ALIGN_VAR (p_tag
- p
) + p
;
713 bi
.tags
= (p
- p0
) + p_target
;
715 p
= (ALIGN_PAGE ((p_tag
- p0
) + p_target
) - p_target
) + p0
;
718 bi
.kern_end
= kern_end
;
720 grub_video_set_mode ("text", 0, 0);
724 struct grub_relocator64_state state
;
725 grub_uint8_t
*pagetable
;
726 grub_uint32_t
*stack
;
727 grub_addr_t stack_target
;
730 grub_relocator_chunk_t ch
;
731 err
= grub_relocator_alloc_chunk_align (relocator
, &ch
,
733 3 * sizeof (grub_uint32_t
)
735 GRUB_RELOCATOR_PREFERENCE_NONE
,
739 stack
= get_virtual_current_address (ch
);
740 stack_target
= get_physical_target_address (ch
);
743 #ifdef GRUB_MACHINE_EFI
744 err
= grub_efi_finish_boot_services (NULL
, NULL
, NULL
, NULL
, NULL
);
750 fill_bsd64_pagetable (pagetable
, (pagetable
- p0
) + p_target
);
752 state
.cr3
= (pagetable
- p0
) + p_target
;
753 state
.rsp
= stack_target
;
754 state
.rip
= (((grub_uint64_t
) entry_hi
) << 32) | entry
;
759 return grub_relocator64_boot (relocator
, state
, 0, 0x40000000);
763 struct grub_relocator32_state state
;
764 grub_uint32_t
*stack
;
765 grub_addr_t stack_target
;
768 grub_relocator_chunk_t ch
;
769 err
= grub_relocator_alloc_chunk_align (relocator
, &ch
,
771 9 * sizeof (grub_uint32_t
)
773 GRUB_RELOCATOR_PREFERENCE_NONE
,
777 stack
= get_virtual_current_address (ch
);
778 stack_target
= get_physical_target_address (ch
);
781 #ifdef GRUB_MACHINE_EFI
782 err
= grub_efi_finish_boot_services (NULL
, NULL
, NULL
, NULL
, NULL
);
787 grub_memcpy (&stack
[9], &bi
, sizeof (bi
));
789 state
.esp
= stack_target
;
790 state
.ebp
= stack_target
;
791 stack
[0] = entry
; /* "Return" address. */
792 stack
[1] = bootflags
| FREEBSD_RB_BOOTINFO
;
793 stack
[2] = freebsd_bootdev
;
794 stack
[3] = freebsd_zfsguid
? 4 : 0;
795 stack
[4] = freebsd_zfsguid
;
796 stack
[5] = freebsd_zfsguid
>> 32;
797 stack
[6] = stack_target
+ 9 * sizeof (grub_uint32_t
);
800 return grub_relocator32_boot (relocator
, state
, 0);
804 return GRUB_ERR_NONE
;
808 grub_openbsd_boot (void)
810 grub_uint32_t
*stack
;
811 struct grub_relocator32_state state
;
812 void *curarg
, *buf0
, *arg0
;
813 grub_addr_t buf_target
;
815 grub_size_t tag_buf_len
;
817 err
= grub_bsd_add_mmap ();
821 #ifdef GRUB_MACHINE_PCBIOS
823 struct grub_bios_int_registers regs
;
825 regs
.flags
= GRUB_CPU_INT_FLAGS_DEFAULT
;
834 grub_bios_interrupt (0x1a, ®s
);
835 if (regs
.edx
== 0x20494350)
837 struct grub_openbsd_bootarg_pcibios pcibios
;
839 pcibios
.characteristics
= regs
.eax
& 0xff;
840 pcibios
.revision
= regs
.ebx
& 0xffff;
841 pcibios
.pm_entry
= regs
.edi
;
842 pcibios
.last_bus
= regs
.ecx
& 0xff;
844 grub_bsd_add_meta (OPENBSD_BOOTARG_PCIBIOS
, &pcibios
,
853 for (tag
= tags
; tag
; tag
= tag
->next
)
854 tag_buf_len
= ALIGN_VAR (tag_buf_len
855 + sizeof (struct grub_openbsd_bootargs
)
859 buf_target
= GRUB_BSD_TEMP_BUFFER
- 9 * sizeof (grub_uint32_t
);
861 grub_relocator_chunk_t ch
;
862 err
= grub_relocator_alloc_chunk_addr (relocator
, &ch
, buf_target
,
864 + sizeof (struct grub_openbsd_bootargs
)
865 + 9 * sizeof (grub_uint32_t
));
868 buf0
= get_virtual_current_address (ch
);
871 stack
= (grub_uint32_t
*) buf0
;
872 arg0
= curarg
= stack
+ 9;
876 struct grub_openbsd_bootargs
*head
;
878 for (tag
= tags
; tag
; tag
= tag
->next
)
881 head
->ba_type
= tag
->type
;
882 head
->ba_size
= tag
->len
+ sizeof (*head
);
884 grub_memcpy (curarg
, tag
->data
, tag
->len
);
885 curarg
= (grub_uint8_t
*) curarg
+ tag
->len
;
886 head
->ba_next
= (grub_uint8_t
*) curarg
- (grub_uint8_t
*) buf0
890 head
->ba_type
= OPENBSD_BOOTARG_END
;
895 grub_video_set_mode ("text", 0, 0);
897 #ifdef GRUB_MACHINE_EFI
898 err
= grub_efi_finish_boot_services (NULL
, NULL
, NULL
, NULL
, NULL
);
904 state
.ebp
= state
.esp
905 = ((grub_uint8_t
*) stack
- (grub_uint8_t
*) buf0
) + buf_target
;
907 stack
[1] = bootflags
;
908 stack
[2] = openbsd_root
;
909 stack
[3] = OPENBSD_BOOTARG_APIVER
;
911 stack
[5] = grub_mmap_get_upper () >> 10;
912 stack
[6] = grub_mmap_get_lower () >> 10;
913 stack
[7] = (grub_uint8_t
*) curarg
- (grub_uint8_t
*) arg0
;
914 stack
[8] = ((grub_uint8_t
*) arg0
- (grub_uint8_t
*) buf0
) + buf_target
;
916 return grub_relocator32_boot (relocator
, state
, 0);
920 grub_netbsd_setup_video (void)
922 struct grub_video_mode_info mode_info
;
925 struct grub_netbsd_btinfo_framebuf params
;
927 grub_video_driver_id_t driv_id
;
929 modevar
= grub_env_get ("gfxpayload");
931 /* Now all graphical modes are acceptable.
932 May change in future if we have modes without framebuffer. */
933 if (modevar
&& *modevar
!= 0)
936 tmp
= grub_xasprintf ("%s;" NETBSD_DEFAULT_VIDEO_MODE
, modevar
);
939 err
= grub_video_set_mode (tmp
, 0, 0);
943 err
= grub_video_set_mode (NETBSD_DEFAULT_VIDEO_MODE
, 0, 0);
948 driv_id
= grub_video_get_driver_id ();
949 if (driv_id
== GRUB_VIDEO_DRIVER_NONE
)
950 return GRUB_ERR_NONE
;
952 err
= grub_video_get_info_and_fini (&mode_info
, &framebuffer
);
957 params
.width
= mode_info
.width
;
958 params
.height
= mode_info
.height
;
959 params
.bpp
= mode_info
.bpp
;
960 params
.pitch
= mode_info
.pitch
;
963 params
.fbaddr
= (grub_addr_t
) framebuffer
;
965 params
.red_mask_size
= mode_info
.red_mask_size
;
966 params
.red_field_pos
= mode_info
.red_field_pos
;
967 params
.green_mask_size
= mode_info
.green_mask_size
;
968 params
.green_field_pos
= mode_info
.green_field_pos
;
969 params
.blue_mask_size
= mode_info
.blue_mask_size
;
970 params
.blue_field_pos
= mode_info
.blue_field_pos
;
972 #ifdef GRUB_MACHINE_PCBIOS
973 /* VESA packed modes may come with zeroed mask sizes, which need
974 to be set here according to DAC Palette width. If we don't,
975 this results in Linux displaying a black screen. */
976 if (mode_info
.bpp
<= 8 && driv_id
== GRUB_VIDEO_DRIVER_VBE
)
978 struct grub_vbe_info_block controller_info
;
982 status
= grub_vbe_bios_get_controller_info (&controller_info
);
984 if (status
== GRUB_VBE_STATUS_OK
&&
985 (controller_info
.capabilities
& GRUB_VBE_CAPABILITY_DACWIDTH
))
986 status
= grub_vbe_bios_set_dac_palette_width (&width
);
988 if (status
!= GRUB_VBE_STATUS_OK
)
989 /* 6 is default after mode reset. */
992 params
.red_mask_size
= params
.green_mask_size
993 = params
.blue_mask_size
= width
;
997 err
= grub_bsd_add_meta (NETBSD_BTINFO_FRAMEBUF
, ¶ms
, sizeof (params
));
1002 grub_netbsd_add_modules (void)
1004 struct netbsd_module
*mod
;
1005 unsigned modcnt
= 0;
1006 struct grub_netbsd_btinfo_modules
*mods
;
1010 for (mod
= netbsd_mods
; mod
; mod
= mod
->next
)
1013 mods
= grub_malloc (sizeof (*mods
) + sizeof (mods
->mods
[0]) * modcnt
);
1018 mods
->last_addr
= kern_end
;
1019 for (mod
= netbsd_mods
, i
= 0; mod
; i
++, mod
= mod
->next
)
1020 mods
->mods
[i
] = mod
->mod
;
1022 err
= grub_bsd_add_meta (NETBSD_BTINFO_MODULES
, mods
,
1023 sizeof (*mods
) + sizeof (mods
->mods
[0]) * modcnt
);
1029 * Adds NetBSD bootinfo bootdisk and bootwedge. The partition identified
1030 * in these bootinfo fields is the root device.
1033 grub_netbsd_add_boot_disk_and_wedge (void)
1037 grub_partition_t part
;
1038 grub_uint32_t biosdev
;
1039 grub_uint32_t partmapsector
;
1041 grub_uint64_t raw
[GRUB_DISK_SECTOR_SIZE
/ 8];
1042 struct grub_partition_bsd_disk_label label
;
1045 if (GRUB_MD_MD5
->mdlen
> GRUB_CRYPTO_MAX_MDLEN
)
1047 grub_error (GRUB_ERR_BUG
, "mdlen too long");
1051 dev
= grub_device_open (0);
1052 if (! (dev
&& dev
->disk
&& dev
->disk
->partition
))
1056 part
= disk
->partition
;
1058 if (disk
->dev
&& disk
->dev
->id
== GRUB_DISK_DEVICE_BIOSDISK_ID
)
1059 biosdev
= (grub_uint32_t
) disk
->id
& 0xff;
1063 /* Absolute sector of the partition map describing this partition. */
1064 partmapsector
= grub_partition_get_start (part
->parent
) + part
->offset
;
1066 disk
->partition
= part
->parent
;
1067 if (grub_disk_read (disk
, part
->offset
, 0, GRUB_DISK_SECTOR_SIZE
, buf
.raw
)
1070 disk
->partition
= part
;
1072 /* Fill bootwedge. */
1074 struct grub_netbsd_btinfo_bootwedge biw
;
1075 grub_uint8_t hash
[GRUB_CRYPTO_MAX_MDLEN
];
1077 grub_memset (&biw
, 0, sizeof (biw
));
1078 biw
.biosdev
= biosdev
;
1079 biw
.startblk
= grub_partition_get_start (part
);
1080 biw
.nblks
= part
->len
;
1081 biw
.matchblk
= partmapsector
;
1084 grub_crypto_hash (GRUB_MD_MD5
, hash
,
1085 buf
.raw
, GRUB_DISK_SECTOR_SIZE
);
1086 grub_memcpy (biw
.matchhash
, hash
, 16);
1088 grub_bsd_add_meta (NETBSD_BTINFO_BOOTWEDGE
, &biw
, sizeof (biw
));
1091 /* Fill bootdisk. */
1093 struct grub_netbsd_btinfo_bootdisk bid
;
1095 grub_memset (&bid
, 0, sizeof (bid
));
1096 /* Check for a NetBSD disk label. */
1097 if (part
->partmap
!= NULL
&&
1098 (grub_strcmp (part
->partmap
->name
, "netbsd") == 0 ||
1099 (part
->parent
== NULL
&& grub_strcmp (part
->partmap
->name
, "bsd") == 0)))
1101 bid
.labelsector
= partmapsector
;
1102 bid
.label
.type
= buf
.label
.type
;
1103 bid
.label
.checksum
= buf
.label
.checksum
;
1104 grub_memcpy (bid
.label
.packname
, buf
.label
.packname
, 16);
1108 bid
.labelsector
= -1;
1110 bid
.biosdev
= biosdev
;
1111 bid
.partition
= part
->number
;
1113 grub_bsd_add_meta (NETBSD_BTINFO_BOOTDISK
, &bid
, sizeof (bid
));
1118 grub_device_close (dev
);
1122 grub_netbsd_boot (void)
1124 struct grub_netbsd_bootinfo
*bootinfo
;
1125 void *curarg
, *arg0
;
1126 grub_addr_t arg_target
, stack_target
;
1127 grub_uint32_t
*stack
;
1129 struct grub_relocator32_state state
;
1130 grub_size_t tag_buf_len
= 0;
1133 err
= grub_bsd_add_mmap ();
1137 err
= grub_netbsd_setup_video ();
1140 grub_print_error ();
1141 grub_puts_ (N_("Booting in blind mode"));
1142 grub_errno
= GRUB_ERR_NONE
;
1145 err
= grub_netbsd_add_modules ();
1149 #ifdef GRUB_MACHINE_EFI
1150 err
= grub_bsd_add_meta (NETBSD_BTINFO_EFI
,
1151 &grub_efi_system_table
,
1152 sizeof (grub_efi_system_table
));
1158 struct bsd_tag
*tag
;
1160 for (tag
= tags
; tag
; tag
= tag
->next
)
1162 tag_buf_len
= ALIGN_VAR (tag_buf_len
1163 + sizeof (struct grub_netbsd_btinfo_common
)
1169 arg_target
= kern_end
;
1171 grub_relocator_chunk_t ch
;
1172 err
= grub_relocator_alloc_chunk_addr (relocator
, &ch
,
1173 arg_target
, tag_buf_len
1174 + sizeof (struct grub_netbsd_bootinfo
)
1175 + tag_count
* sizeof (grub_uint32_t
));
1178 curarg
= get_virtual_current_address (ch
);
1182 bootinfo
= (void *) ((grub_uint8_t
*) arg0
+ tag_buf_len
);
1185 struct bsd_tag
*tag
;
1188 bootinfo
->bi_count
= tag_count
;
1189 for (tag
= tags
, i
= 0; tag
; i
++, tag
= tag
->next
)
1191 struct grub_netbsd_btinfo_common
*head
= curarg
;
1192 bootinfo
->bi_data
[i
] = ((grub_uint8_t
*) curarg
- (grub_uint8_t
*) arg0
)
1194 head
->type
= tag
->type
;
1195 head
->len
= tag
->len
+ sizeof (*head
);
1197 grub_memcpy (curarg
, tag
->data
, tag
->len
);
1198 curarg
= (grub_uint8_t
*) curarg
+ tag
->len
;
1203 grub_relocator_chunk_t ch
;
1204 err
= grub_relocator_alloc_chunk_align (relocator
, &ch
, 0x10000, 0x90000,
1205 7 * sizeof (grub_uint32_t
), 4,
1206 GRUB_RELOCATOR_PREFERENCE_NONE
,
1210 stack
= get_virtual_current_address (ch
);
1211 stack_target
= get_physical_target_address (ch
);
1214 #ifdef GRUB_MACHINE_EFI
1215 err
= grub_efi_finish_boot_services (NULL
, NULL
, NULL
, NULL
, NULL
);
1221 state
.esp
= stack_target
;
1222 state
.ebp
= stack_target
;
1224 stack
[1] = bootflags
;
1226 stack
[3] = ((grub_uint8_t
*) bootinfo
- (grub_uint8_t
*) arg0
) + arg_target
;
1228 stack
[5] = grub_mmap_get_upper () >> 10;
1229 stack
[6] = grub_mmap_get_lower () >> 10;
1231 return grub_relocator32_boot (relocator
, state
, 0);
1235 grub_bsd_unload (void)
1237 struct bsd_tag
*tag
, *next
;
1238 for (tag
= tags
; tag
; tag
= next
)
1246 kernel_type
= KERNEL_TYPE_NONE
;
1247 grub_dl_unref (my_mod
);
1249 grub_relocator_unload (relocator
);
1252 return GRUB_ERR_NONE
;
1256 grub_bsd_load_aout (grub_file_t file
, const char *filename
)
1258 grub_addr_t load_addr
, load_end
;
1259 int ofs
, align_page
;
1260 union grub_aout_header ah
;
1262 grub_size_t bss_size
;
1264 if ((grub_file_seek (file
, 0)) == (grub_off_t
) - 1)
1267 if (grub_file_read (file
, &ah
, sizeof (ah
)) != sizeof (ah
))
1270 grub_error (GRUB_ERR_READ_ERROR
, N_("premature end of file %s"),
1275 if (grub_aout_get_type (&ah
) != AOUT_TYPE_AOUT32
)
1276 return grub_error (GRUB_ERR_BAD_OS
, "invalid a.out header");
1278 entry
= ah
.aout32
.a_entry
& 0xFFFFFF;
1280 if (AOUT_GETMAGIC (ah
.aout32
) == AOUT32_ZMAGIC
)
1288 load_addr
= entry
& 0xF00000;
1289 ofs
= sizeof (struct grub_aout32_header
);
1293 if (load_addr
< 0x100000)
1294 return grub_error (GRUB_ERR_BAD_OS
, "load address below 1M");
1296 kern_start
= load_addr
;
1297 load_end
= kern_end
= load_addr
+ ah
.aout32
.a_text
+ ah
.aout32
.a_data
;
1299 kern_end
= ALIGN_PAGE (kern_end
);
1301 if (ah
.aout32
.a_bss
)
1303 kern_end
+= ah
.aout32
.a_bss
;
1305 kern_end
= ALIGN_PAGE (kern_end
);
1307 bss_size
= kern_end
- load_end
;
1313 grub_relocator_chunk_t ch
;
1315 err
= grub_relocator_alloc_chunk_addr (relocator
, &ch
,
1316 kern_start
, kern_end
- kern_start
);
1319 kern_chunk_src
= get_virtual_current_address (ch
);
1322 return grub_aout_load (file
, ofs
, kern_chunk_src
,
1323 ah
.aout32
.a_text
+ ah
.aout32
.a_data
,
1328 grub_bsd_load_elf (grub_elf_t elf
, const char *filename
)
1335 if (grub_elf_is_elf32 (elf
))
1337 grub_relocator_chunk_t ch
;
1340 entry
= elf
->ehdr
.ehdr32
.e_entry
& 0xFFFFFFF;
1342 FOR_ELF32_PHDRS (elf
, phdr
)
1346 if (phdr
->p_type
!= PT_LOAD
1347 && phdr
->p_type
!= PT_DYNAMIC
)
1350 paddr
= phdr
->p_paddr
& 0xFFFFFFF;
1352 if (paddr
< kern_start
)
1355 if (paddr
+ phdr
->p_memsz
> kern_end
)
1356 kern_end
= paddr
+ phdr
->p_memsz
;
1361 err
= grub_relocator_alloc_chunk_addr (relocator
, &ch
,
1362 kern_start
, kern_end
- kern_start
);
1366 kern_chunk_src
= get_virtual_current_address (ch
);
1368 err
= grub_elf32_load (elf
, filename
, (grub_uint8_t
*) kern_chunk_src
- kern_start
, GRUB_ELF_LOAD_FLAGS_LOAD_PT_DYNAMIC
| GRUB_ELF_LOAD_FLAGS_28BITS
, 0, 0);
1371 if (kernel_type
!= KERNEL_TYPE_OPENBSD
)
1372 return GRUB_ERR_NONE
;
1373 return grub_openbsd_find_ramdisk32 (elf
->file
, filename
, kern_start
,
1374 kern_chunk_src
, &openbsd_ramdisk
);
1376 else if (grub_elf_is_elf64 (elf
))
1382 if (! grub_cpuid_has_longmode
)
1383 return grub_error (GRUB_ERR_BAD_OS
, "your CPU does not implement AMD64 architecture");
1385 /* FreeBSD has 64-bit entry point. */
1386 if (kernel_type
== KERNEL_TYPE_FREEBSD
)
1388 entry
= elf
->ehdr
.ehdr64
.e_entry
& 0xffffffff;
1389 entry_hi
= (elf
->ehdr
.ehdr64
.e_entry
>> 32) & 0xffffffff;
1393 entry
= elf
->ehdr
.ehdr64
.e_entry
& 0x0fffffff;
1397 FOR_ELF64_PHDRS (elf
, phdr
)
1401 if (phdr
->p_type
!= PT_LOAD
1402 && phdr
->p_type
!= PT_DYNAMIC
)
1405 paddr
= phdr
->p_paddr
& 0xFFFFFFF;
1407 if (paddr
< kern_start
)
1410 if (paddr
+ phdr
->p_memsz
> kern_end
)
1411 kern_end
= paddr
+ phdr
->p_memsz
;
1417 grub_dprintf ("bsd", "kern_start = %lx, kern_end = %lx\n",
1418 (unsigned long) kern_start
, (unsigned long) kern_end
);
1420 grub_relocator_chunk_t ch
;
1422 err
= grub_relocator_alloc_chunk_addr (relocator
, &ch
, kern_start
,
1423 kern_end
- kern_start
);
1426 kern_chunk_src
= get_virtual_current_address (ch
);
1429 err
= grub_elf64_load (elf
, filename
,
1430 (grub_uint8_t
*) kern_chunk_src
- kern_start
, GRUB_ELF_LOAD_FLAGS_LOAD_PT_DYNAMIC
| GRUB_ELF_LOAD_FLAGS_28BITS
, 0, 0);
1433 if (kernel_type
!= KERNEL_TYPE_OPENBSD
)
1434 return GRUB_ERR_NONE
;
1435 return grub_openbsd_find_ramdisk64 (elf
->file
, filename
, kern_start
,
1436 kern_chunk_src
, &openbsd_ramdisk
);
1439 return grub_error (GRUB_ERR_BAD_OS
, N_("invalid arch-dependent ELF magic"));
1443 grub_bsd_load (int argc
, char *argv
[])
1448 grub_dl_ref (my_mod
);
1450 grub_loader_unset ();
1452 grub_memset (&openbsd_ramdisk
, 0, sizeof (openbsd_ramdisk
));
1456 grub_error (GRUB_ERR_BAD_ARGUMENT
, N_("filename expected"));
1460 file
= grub_file_open (argv
[0]);
1464 relocator
= grub_relocator_new ();
1467 grub_file_close (file
);
1471 elf
= grub_elf_file (file
, argv
[0]);
1475 grub_bsd_load_elf (elf
, argv
[0]);
1476 grub_elf_close (elf
);
1482 grub_bsd_load_aout (file
, argv
[0]);
1483 grub_file_close (file
);
1486 kern_end
= ALIGN_PAGE (kern_end
);
1490 if (grub_errno
!= GRUB_ERR_NONE
)
1491 grub_dl_unref (my_mod
);
1496 static grub_uint32_t
1497 grub_bsd_parse_flags (const struct grub_arg_list
*state
,
1498 const grub_uint32_t
* flags
)
1500 grub_uint32_t result
= 0;
1503 for (i
= 0; flags
[i
]; i
++)
1511 grub_cmd_freebsd (grub_extcmd_context_t ctxt
, int argc
, char *argv
[])
1513 kernel_type
= KERNEL_TYPE_FREEBSD
;
1514 bootflags
= grub_bsd_parse_flags (ctxt
->state
, freebsd_flags
);
1516 if (grub_bsd_load (argc
, argv
) == GRUB_ERR_NONE
)
1518 grub_uint32_t unit
, slice
, part
;
1520 kern_end
= ALIGN_PAGE (kern_end
);
1524 grub_uint64_t data
= 0;
1526 int len
= is_64bit
? 8 : 4;
1528 err
= grub_freebsd_add_meta_module (argv
[0], is_64bit
1529 ? FREEBSD_MODTYPE_KERNEL64
1530 : FREEBSD_MODTYPE_KERNEL
,
1533 kern_end
- kern_start
);
1537 file
= grub_file_open (argv
[0]);
1542 err
= grub_freebsd_load_elf_meta64 (relocator
, file
, argv
[0],
1545 err
= grub_freebsd_load_elf_meta32 (relocator
, file
, argv
[0],
1550 err
= grub_bsd_add_meta (FREEBSD_MODINFO_METADATA
|
1551 FREEBSD_MODINFOMD_HOWTO
, &data
, 4);
1555 err
= grub_bsd_add_meta (FREEBSD_MODINFO_METADATA
|
1556 FREEBSD_MODINFOMD_ENVP
, &data
, len
);
1560 err
= grub_bsd_add_meta (FREEBSD_MODINFO_METADATA
|
1561 FREEBSD_MODINFOMD_KERNEND
, &data
, len
);
1565 grub_bsd_get_device (&freebsd_biosdev
, &unit
, &slice
, &part
);
1566 freebsd_zfsguid
= 0;
1569 grub_print_error ();
1570 freebsd_bootdev
= (FREEBSD_B_DEVMAGIC
+ ((slice
+ 1) << FREEBSD_B_SLICESHIFT
) +
1571 (unit
<< FREEBSD_B_UNITSHIFT
) + (part
<< FREEBSD_B_PARTSHIFT
));
1573 grub_loader_set (grub_freebsd_boot
, grub_bsd_unload
, 0);
1579 static const char *types
[] = {
1589 grub_cmd_openbsd (grub_extcmd_context_t ctxt
, int argc
, char *argv
[])
1591 grub_uint32_t bootdev
;
1593 kernel_type
= KERNEL_TYPE_OPENBSD
;
1594 bootflags
= grub_bsd_parse_flags (ctxt
->state
, openbsd_flags
);
1596 if (ctxt
->state
[OPENBSD_ROOT_ARG
].set
)
1598 const char *arg
= ctxt
->state
[OPENBSD_ROOT_ARG
].arg
;
1599 unsigned type
, unit
, part
;
1600 for (type
= 0; type
< ARRAY_SIZE (types
); type
++)
1602 && grub_strncmp (arg
, types
[type
],
1603 grub_strlen (types
[type
])) == 0)
1605 arg
+= grub_strlen (types
[type
]);
1608 if (type
== ARRAY_SIZE (types
))
1609 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
1610 "unknown disk type name");
1612 unit
= grub_strtoul (arg
, (char **) &arg
, 10);
1613 if (! (arg
&& *arg
>= 'a' && *arg
<= 'z'))
1614 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
1615 "only device specifications of form "
1616 "<type><number><lowercase letter> are supported");
1620 bootdev
= (OPENBSD_B_DEVMAGIC
| (type
<< OPENBSD_B_TYPESHIFT
)
1621 | (unit
<< OPENBSD_B_UNITSHIFT
)
1622 | (part
<< OPENBSD_B_PARTSHIFT
));
1627 if (ctxt
->state
[OPENBSD_SERIAL_ARG
].set
)
1629 struct grub_openbsd_bootarg_console serial
;
1632 unsigned speed
= 9600;
1634 grub_memset (&serial
, 0, sizeof (serial
));
1636 if (ctxt
->state
[OPENBSD_SERIAL_ARG
].arg
)
1638 ptr
= ctxt
->state
[OPENBSD_SERIAL_ARG
].arg
;
1639 if (grub_memcmp (ptr
, "com", sizeof ("com") - 1) != 0)
1640 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
1641 "only com0-com3 are supported");
1642 ptr
+= sizeof ("com") - 1;
1643 port
= grub_strtoul (ptr
, &ptr
, 0);
1645 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
1646 "only com0-com3 are supported");
1650 speed
= grub_strtoul (ptr
, &ptr
, 0);
1656 serial
.device
= (GRUB_OPENBSD_COM_MAJOR
<< 8) | port
;
1657 serial
.speed
= speed
;
1658 serial
.addr
= grub_ns8250_hw_get_port (port
);
1660 grub_bsd_add_meta (OPENBSD_BOOTARG_CONSOLE
, &serial
, sizeof (serial
));
1661 bootflags
|= OPENBSD_RB_SERCONS
;
1665 struct grub_openbsd_bootarg_console serial
;
1667 grub_memset (&serial
, 0, sizeof (serial
));
1668 serial
.device
= (GRUB_OPENBSD_VGA_MAJOR
<< 8);
1669 serial
.addr
= 0xffffffff;
1670 grub_bsd_add_meta (OPENBSD_BOOTARG_CONSOLE
, &serial
, sizeof (serial
));
1671 bootflags
&= ~OPENBSD_RB_SERCONS
;
1674 if (grub_bsd_load (argc
, argv
) == GRUB_ERR_NONE
)
1676 grub_loader_set (grub_openbsd_boot
, grub_bsd_unload
, 0);
1677 openbsd_root
= bootdev
;
1684 grub_cmd_netbsd (grub_extcmd_context_t ctxt
, int argc
, char *argv
[])
1687 kernel_type
= KERNEL_TYPE_NETBSD
;
1688 bootflags
= grub_bsd_parse_flags (ctxt
->state
, netbsd_flags
);
1690 if (grub_bsd_load (argc
, argv
) == GRUB_ERR_NONE
)
1696 file
= grub_file_open (argv
[0]);
1701 err
= grub_netbsd_load_elf_meta64 (relocator
, file
, argv
[0], &kern_end
);
1703 err
= grub_netbsd_load_elf_meta32 (relocator
, file
, argv
[0], &kern_end
);
1709 char bootpath
[GRUB_NETBSD_MAX_BOOTPATH_LEN
];
1711 name
= grub_strrchr (argv
[0], '/');
1716 grub_memset (bootpath
, 0, sizeof (bootpath
));
1717 grub_strncpy (bootpath
, name
, sizeof (bootpath
) - 1);
1718 grub_bsd_add_meta (NETBSD_BTINFO_BOOTPATH
, bootpath
, sizeof (bootpath
));
1721 if (ctxt
->state
[NETBSD_ROOT_ARG
].set
)
1723 char root
[GRUB_NETBSD_MAX_ROOTDEVICE_LEN
];
1724 grub_memset (root
, 0, sizeof (root
));
1725 grub_strncpy (root
, ctxt
->state
[NETBSD_ROOT_ARG
].arg
,
1727 grub_bsd_add_meta (NETBSD_BTINFO_ROOTDEVICE
, root
, sizeof (root
));
1729 if (ctxt
->state
[NETBSD_SERIAL_ARG
].set
)
1731 struct grub_netbsd_btinfo_serial serial
;
1734 grub_memset (&serial
, 0, sizeof (serial
));
1735 grub_strcpy (serial
.devname
, "com");
1737 serial
.addr
= grub_ns8250_hw_get_port (0);
1738 serial
.speed
= 9600;
1740 if (ctxt
->state
[NETBSD_SERIAL_ARG
].arg
)
1742 ptr
= ctxt
->state
[NETBSD_SERIAL_ARG
].arg
;
1743 if (grub_memcmp (ptr
, "com", sizeof ("com") - 1) == 0)
1745 ptr
+= sizeof ("com") - 1;
1747 = grub_ns8250_hw_get_port (grub_strtoul (ptr
, &ptr
, 0));
1750 serial
.addr
= grub_strtoul (ptr
, &ptr
, 0);
1757 serial
.speed
= grub_strtoul (ptr
, &ptr
, 0);
1763 grub_bsd_add_meta (NETBSD_BTINFO_CONSOLE
, &serial
, sizeof (serial
));
1767 struct grub_netbsd_btinfo_serial cons
;
1769 grub_memset (&cons
, 0, sizeof (cons
));
1770 grub_strcpy (cons
.devname
, "pc");
1772 grub_bsd_add_meta (NETBSD_BTINFO_CONSOLE
, &cons
, sizeof (cons
));
1775 grub_netbsd_add_boot_disk_and_wedge ();
1777 grub_loader_set (grub_netbsd_boot
, grub_bsd_unload
, 0);
1784 grub_cmd_freebsd_loadenv (grub_command_t cmd
__attribute__ ((unused
)),
1785 int argc
, char *argv
[])
1787 grub_file_t file
= 0;
1788 char *buf
= 0, *curr
, *next
;
1791 if (! grub_loader_is_loaded ())
1792 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
1793 N_("you need to load the kernel first"));
1795 if (kernel_type
!= KERNEL_TYPE_FREEBSD
)
1796 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
1797 "only FreeBSD supports environment");
1801 grub_error (GRUB_ERR_BAD_ARGUMENT
, N_("filename expected"));
1805 file
= grub_file_open (argv
[0]);
1806 if ((!file
) || (!file
->size
))
1810 buf
= grub_malloc (len
+ 1);
1814 if (grub_file_read (file
, buf
, len
) != len
)
1825 next
= grub_strchr (curr
, '\n');
1832 if ((*p
!= '\r') && (*p
!= ' ') && (*p
!= '\t'))
1837 if ((p
> curr
) && (*p
== '"'))
1847 p
= grub_strchr (curr
, '=');
1860 name
= grub_xasprintf ("kFreeBSD.%s", curr
);
1863 if (grub_env_set (name
, p
))
1876 grub_file_close (file
);
1882 grub_cmd_freebsd_module (grub_command_t cmd
__attribute__ ((unused
)),
1883 int argc
, char *argv
[])
1885 grub_file_t file
= 0;
1892 if (kernel_type
!= KERNEL_TYPE_FREEBSD
)
1893 return grub_error (GRUB_ERR_BAD_ARGUMENT
, "no FreeBSD loaded");
1896 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
1897 "only ELF kernel supports module");
1899 /* List the current modules if no parameter. */
1902 grub_freebsd_list_modules ();
1906 file
= grub_file_open (argv
[0]);
1907 if ((!file
) || (!file
->size
))
1911 grub_relocator_chunk_t ch
;
1912 err
= grub_relocator_alloc_chunk_addr (relocator
, &ch
, kern_end
,
1916 src
= get_virtual_current_address (ch
);
1920 grub_file_read (file
, src
, file
->size
);
1927 if (modargc
&& (! grub_memcmp (modargv
[0], "type=", 5)))
1929 type
= &modargv
[0][5];
1934 type
= FREEBSD_MODTYPE_RAW
;
1936 err
= grub_freebsd_add_meta_module (argv
[0], type
, modargc
, modargv
,
1937 kern_end
, file
->size
);
1941 kern_end
= ALIGN_PAGE (kern_end
+ file
->size
);
1945 grub_file_close (file
);
1951 grub_netbsd_module_load (char *filename
, grub_uint32_t type
)
1953 grub_file_t file
= 0;
1957 file
= grub_file_open (filename
);
1958 if ((!file
) || (!file
->size
))
1962 grub_relocator_chunk_t ch
;
1963 err
= grub_relocator_alloc_chunk_addr (relocator
, &ch
, kern_end
,
1968 src
= get_virtual_current_address (ch
);
1971 grub_file_read (file
, src
, file
->size
);
1975 err
= grub_netbsd_add_meta_module (filename
, type
, kern_end
, file
->size
);
1980 kern_end
= ALIGN_PAGE (kern_end
+ file
->size
);
1984 grub_file_close (file
);
1990 grub_cmd_netbsd_module (grub_command_t cmd
,
1991 int argc
, char *argv
[])
1995 if (kernel_type
!= KERNEL_TYPE_NETBSD
)
1996 return grub_error (GRUB_ERR_BAD_ARGUMENT
, "no NetBSD loaded");
1999 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
2000 "only ELF kernel supports module");
2002 /* List the current modules if no parameter. */
2005 grub_netbsd_list_modules ();
2009 if (grub_strcmp (cmd
->name
, "knetbsd_module_elf") == 0)
2010 type
= GRUB_NETBSD_MODULE_ELF
;
2012 type
= GRUB_NETBSD_MODULE_RAW
;
2014 return grub_netbsd_module_load (argv
[0], type
);
2018 grub_cmd_freebsd_module_elf (grub_command_t cmd
__attribute__ ((unused
)),
2019 int argc
, char *argv
[])
2021 grub_file_t file
= 0;
2024 if (! grub_loader_is_loaded ())
2025 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
2026 N_("you need to load the kernel first"));
2028 if (kernel_type
!= KERNEL_TYPE_FREEBSD
)
2029 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
2030 "only FreeBSD supports module");
2032 if (! is_elf_kernel
)
2033 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
2034 "only ELF kernel supports module");
2036 /* List the current modules if no parameter. */
2039 grub_freebsd_list_modules ();
2043 file
= grub_file_open (argv
[0]);
2048 grub_file_close (file
);
2053 err
= grub_freebsd_load_elfmodule_obj64 (relocator
, file
,
2054 argc
, argv
, &kern_end
);
2056 err
= grub_freebsd_load_elfmodule32 (relocator
, file
,
2057 argc
, argv
, &kern_end
);
2058 grub_file_close (file
);
2064 grub_cmd_openbsd_ramdisk (grub_command_t cmd
__attribute__ ((unused
)),
2065 int argc
, char *args
[])
2071 return grub_error (GRUB_ERR_BAD_ARGUMENT
, N_("filename expected"));
2073 if (kernel_type
!= KERNEL_TYPE_OPENBSD
)
2074 return grub_error (GRUB_ERR_BAD_OS
, "no kOpenBSD loaded");
2076 if (!openbsd_ramdisk
.max_size
)
2077 return grub_error (GRUB_ERR_BAD_OS
, "your kOpenBSD doesn't support ramdisk");
2079 file
= grub_file_open (args
[0]);
2083 size
= grub_file_size (file
);
2085 if (size
> openbsd_ramdisk
.max_size
)
2087 grub_file_close (file
);
2088 return grub_error (GRUB_ERR_BAD_OS
, "your kOpenBSD supports ramdisk only"
2089 " up to %u bytes, however you supplied a %u bytes one",
2090 openbsd_ramdisk
.max_size
, size
);
2093 if (grub_file_read (file
, openbsd_ramdisk
.target
, size
)
2094 != (grub_ssize_t
) (size
))
2096 grub_file_close (file
);
2098 grub_error (GRUB_ERR_BAD_OS
, N_("premature end of file %s"), args
[0]);
2101 grub_memset (openbsd_ramdisk
.target
+ size
, 0,
2102 openbsd_ramdisk
.max_size
- size
);
2103 *openbsd_ramdisk
.size
= ALIGN_UP (size
, 512);
2105 return GRUB_ERR_NONE
;
2108 static grub_extcmd_t cmd_freebsd
, cmd_openbsd
, cmd_netbsd
;
2109 static grub_command_t cmd_freebsd_loadenv
, cmd_freebsd_module
;
2110 static grub_command_t cmd_netbsd_module
, cmd_freebsd_module_elf
;
2111 static grub_command_t cmd_netbsd_module_elf
, cmd_openbsd_ramdisk
;
2115 /* Net and OpenBSD kernels are often compressed. */
2116 grub_dl_load ("gzio");
2118 cmd_freebsd
= grub_register_extcmd ("kfreebsd", grub_cmd_freebsd
, 0,
2119 N_("FILE"), N_("Load kernel of FreeBSD."),
2121 cmd_openbsd
= grub_register_extcmd ("kopenbsd", grub_cmd_openbsd
, 0,
2122 N_("FILE"), N_("Load kernel of OpenBSD."),
2124 cmd_netbsd
= grub_register_extcmd ("knetbsd", grub_cmd_netbsd
, 0,
2125 N_("FILE"), N_("Load kernel of NetBSD."),
2127 cmd_freebsd_loadenv
=
2128 grub_register_command ("kfreebsd_loadenv", grub_cmd_freebsd_loadenv
,
2129 0, N_("Load FreeBSD env."));
2130 cmd_freebsd_module
=
2131 grub_register_command ("kfreebsd_module", grub_cmd_freebsd_module
,
2132 0, N_("Load FreeBSD kernel module."));
2134 grub_register_command ("knetbsd_module", grub_cmd_netbsd_module
,
2135 0, N_("Load NetBSD kernel module."));
2136 cmd_netbsd_module_elf
=
2137 grub_register_command ("knetbsd_module_elf", grub_cmd_netbsd_module
,
2138 0, N_("Load NetBSD kernel module (ELF)."));
2139 cmd_freebsd_module_elf
=
2140 grub_register_command ("kfreebsd_module_elf", grub_cmd_freebsd_module_elf
,
2141 0, N_("Load FreeBSD kernel module (ELF)."));
2143 cmd_openbsd_ramdisk
= grub_register_command ("kopenbsd_ramdisk",
2144 grub_cmd_openbsd_ramdisk
, 0,
2145 /* TRANSLATORS: ramdisk isn't identifier,
2146 it can be translated. */
2147 N_("Load kOpenBSD ramdisk."));
2154 grub_unregister_extcmd (cmd_freebsd
);
2155 grub_unregister_extcmd (cmd_openbsd
);
2156 grub_unregister_extcmd (cmd_netbsd
);
2158 grub_unregister_command (cmd_freebsd_loadenv
);
2159 grub_unregister_command (cmd_freebsd_module
);
2160 grub_unregister_command (cmd_netbsd_module
);
2161 grub_unregister_command (cmd_freebsd_module_elf
);
2162 grub_unregister_command (cmd_netbsd_module_elf
);
2163 grub_unregister_command (cmd_openbsd_ramdisk
);