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
->type
!= (FREEBSD_MODINFO_METADATA
| FREEBSD_MODINFOMD_KERNEND
);
242 newtag
->next
= p
->next
;
244 if (newtag
->next
== NULL
)
246 return GRUB_ERR_NONE
;
251 tags_last
->next
= newtag
;
256 return GRUB_ERR_NONE
;
260 grub_bsd_add_meta (grub_uint32_t type
, const void *data
, grub_uint32_t len
)
265 err
= grub_bsd_add_meta_ptr (type
, &ptr
, len
);
269 grub_memcpy (ptr
, data
, len
);
270 return GRUB_ERR_NONE
;
274 struct grub_e820_mmap
280 #define GRUB_E820_RAM 1
281 #define GRUB_E820_RESERVED 2
282 #define GRUB_E820_ACPI 3
283 #define GRUB_E820_NVS 4
284 #define GRUB_E820_BADRAM 5
285 #define GRUB_E820_COREBOOT_TABLES 0x10
287 /* Context for generate_e820_mmap. */
288 struct generate_e820_mmap_ctx
291 struct grub_e820_mmap
*mmap
;
292 struct grub_e820_mmap prev
, cur
;
295 /* Helper for generate_e820_mmap. */
297 generate_e820_mmap_iter (grub_uint64_t addr
, grub_uint64_t size
,
298 grub_memory_type_t type
, void *data
)
300 struct generate_e820_mmap_ctx
*ctx
= data
;
302 ctx
->cur
.addr
= addr
;
303 ctx
->cur
.size
= size
;
305 if (type
== GRUB_MEMORY_COREBOOT_TABLES
307 /* Nowadays the tables at 0 don't contain anything important but
308 *BSD needs the memory at 0 for own needs.
310 type
= GRUB_E820_RAM
;
312 ctx
->cur
.type
= type
;
314 /* Merge regions if possible. */
315 if (ctx
->count
&& ctx
->cur
.type
== ctx
->prev
.type
316 && ctx
->cur
.addr
== ctx
->prev
.addr
+ ctx
->prev
.size
)
318 ctx
->prev
.size
+= ctx
->cur
.size
;
320 ctx
->mmap
[-1] = ctx
->prev
;
325 *ctx
->mmap
++ = ctx
->cur
;
326 ctx
->prev
= ctx
->cur
;
330 if (kernel_type
== KERNEL_TYPE_OPENBSD
&& ctx
->prev
.addr
< 0x100000
331 && ctx
->prev
.addr
+ ctx
->prev
.size
> 0x100000)
333 ctx
->cur
.addr
= 0x100000;
334 ctx
->cur
.size
= ctx
->prev
.addr
+ ctx
->prev
.size
- 0x100000;
335 ctx
->cur
.type
= ctx
->prev
.type
;
336 ctx
->prev
.size
= 0x100000 - ctx
->prev
.addr
;
339 ctx
->mmap
[-1] = ctx
->prev
;
340 ctx
->mmap
[0] = ctx
->cur
;
343 ctx
->prev
= ctx
->cur
;
351 generate_e820_mmap (grub_size_t
*len
, grub_size_t
*cnt
, void *buf
)
353 struct generate_e820_mmap_ctx ctx
= {
358 grub_mmap_iterate (generate_e820_mmap_iter
, &ctx
);
361 *len
= ctx
.count
* sizeof (struct grub_e820_mmap
);
368 grub_bsd_add_mmap (void)
370 grub_size_t len
, cnt
;
371 void *buf
= NULL
, *buf0
;
373 generate_e820_mmap (&len
, &cnt
, buf
);
375 if (kernel_type
== KERNEL_TYPE_NETBSD
)
376 len
+= sizeof (grub_uint32_t
);
378 if (kernel_type
== KERNEL_TYPE_OPENBSD
)
379 len
+= sizeof (struct grub_e820_mmap
);
381 buf
= grub_malloc (len
);
386 if (kernel_type
== KERNEL_TYPE_NETBSD
)
388 *(grub_uint32_t
*) buf
= cnt
;
389 buf
= ((grub_uint32_t
*) buf
+ 1);
392 generate_e820_mmap (NULL
, &cnt
, buf
);
394 if (kernel_type
== KERNEL_TYPE_OPENBSD
)
395 grub_memset ((grub_uint8_t
*) buf
+ len
- sizeof (struct grub_e820_mmap
), 0,
396 sizeof (struct grub_e820_mmap
));
398 grub_dprintf ("bsd", "%u entries in smap\n", (unsigned) cnt
);
399 if (kernel_type
== KERNEL_TYPE_NETBSD
)
400 grub_bsd_add_meta (NETBSD_BTINFO_MEMMAP
, buf0
, len
);
401 else if (kernel_type
== KERNEL_TYPE_OPENBSD
)
402 grub_bsd_add_meta (OPENBSD_BOOTARG_MMAP
, buf0
, len
);
404 grub_bsd_add_meta (FREEBSD_MODINFO_METADATA
|
405 FREEBSD_MODINFOMD_SMAP
, buf0
, len
);
413 grub_freebsd_add_meta_module (const char *filename
, const char *type
,
414 int argc
, char **argv
,
415 grub_addr_t addr
, grub_uint32_t size
)
418 name
= grub_strrchr (filename
, '/');
423 if (grub_strcmp (type
, "/boot/zfs/zpool.cache") == 0)
424 name
= "/boot/zfs/zpool.cache";
426 if (grub_bsd_add_meta (FREEBSD_MODINFO_NAME
, name
, grub_strlen (name
) + 1))
431 grub_uint64_t addr64
= addr
, size64
= size
;
432 if (grub_bsd_add_meta (FREEBSD_MODINFO_TYPE
, type
, grub_strlen (type
) + 1)
433 || grub_bsd_add_meta (FREEBSD_MODINFO_ADDR
, &addr64
, sizeof (addr64
))
434 || grub_bsd_add_meta (FREEBSD_MODINFO_SIZE
, &size64
, sizeof (size64
)))
439 if (grub_bsd_add_meta (FREEBSD_MODINFO_TYPE
, type
, grub_strlen (type
) + 1)
440 || grub_bsd_add_meta (FREEBSD_MODINFO_ADDR
, &addr
, sizeof (addr
))
441 || grub_bsd_add_meta (FREEBSD_MODINFO_SIZE
, &size
, sizeof (size
)))
450 for (i
= 0; i
< argc
; i
++)
452 n
+= grub_strlen (argv
[i
]) + 1;
460 if (grub_bsd_add_meta_ptr (FREEBSD_MODINFO_ARGS
, &cmdline
, n
))
464 for (i
= 0; i
< argc
; i
++)
466 grub_strcpy (p
, argv
[i
]);
467 p
+= grub_strlen (argv
[i
]);
474 return GRUB_ERR_NONE
;
478 grub_freebsd_list_modules (void)
482 grub_printf (" %-18s %-18s%14s%14s\n", _("name"), _("type"), _("addr"),
485 for (tag
= tags
; tag
; tag
= tag
->next
)
489 case FREEBSD_MODINFO_NAME
:
490 case FREEBSD_MODINFO_TYPE
:
491 grub_printf (" %-18s", (char *) tag
->data
);
493 case FREEBSD_MODINFO_ADDR
:
497 addr
= *((grub_uint32_t
*) tag
->data
);
498 grub_printf (" 0x%08x", addr
);
501 case FREEBSD_MODINFO_SIZE
:
505 len
= *((grub_uint32_t
*) tag
->data
);
506 grub_printf (" 0x%08x\n", len
);
513 grub_netbsd_add_meta_module (char *filename
, grub_uint32_t type
,
514 grub_addr_t addr
, grub_uint32_t size
)
517 struct netbsd_module
*mod
;
518 name
= grub_strrchr (filename
, '/');
525 mod
= grub_zalloc (sizeof (*mod
));
529 grub_strncpy (mod
->mod
.name
, name
, sizeof (mod
->mod
.name
) - 1);
530 mod
->mod
.addr
= addr
;
531 mod
->mod
.type
= type
;
532 mod
->mod
.size
= size
;
534 if (netbsd_mods_last
)
535 netbsd_mods_last
->next
= mod
;
538 netbsd_mods_last
= mod
;
540 return GRUB_ERR_NONE
;
544 grub_netbsd_list_modules (void)
546 struct netbsd_module
*mod
;
548 grub_printf (" %-18s%14s%14s%14s\n", _("name"), _("type"), _("addr"),
551 for (mod
= netbsd_mods
; mod
; mod
= mod
->next
)
552 grub_printf (" %-18s 0x%08x 0x%08x 0x%08x", mod
->mod
.name
,
553 mod
->mod
.type
, mod
->mod
.addr
, mod
->mod
.size
);
556 /* This function would be here but it's under different license. */
557 #include "bsd_pagetable.c"
559 static grub_uint32_t freebsd_bootdev
, freebsd_biosdev
;
560 static grub_uint64_t freebsd_zfsguid
;
563 freebsd_get_zfs (void)
570 dev
= grub_device_open (0);
573 fs
= grub_fs_probe (dev
);
576 if (!fs
->uuid
|| grub_strcmp (fs
->name
, "zfs") != 0)
578 err
= fs
->uuid (dev
, &uuid
);
583 freebsd_zfsguid
= grub_strtoull (uuid
, 0, 16);
588 grub_freebsd_boot (void)
590 struct grub_freebsd_bootinfo bi
;
591 grub_uint8_t
*p
, *p0
;
592 grub_addr_t p_target
;
593 grub_size_t p_size
= 0;
595 grub_size_t tag_buf_len
= 0;
597 struct grub_env_var
*var
;
599 grub_memset (&bi
, 0, sizeof (bi
));
600 bi
.version
= FREEBSD_BOOTINFO_VERSION
;
601 bi
.length
= sizeof (bi
);
603 bi
.boot_device
= freebsd_biosdev
;
607 if ((grub_memcmp (var
->name
, "kFreeBSD.", sizeof("kFreeBSD.") - 1) == 0) && (var
->name
[sizeof("kFreeBSD.") - 1]))
609 p_size
+= grub_strlen (&var
->name
[sizeof("kFreeBSD.") - 1]);
611 p_size
+= grub_strlen (var
->value
) + 1;
615 p_size
= ALIGN_PAGE (kern_end
+ p_size
+ 1) - kern_end
;
621 err
= grub_bsd_add_mmap ();
625 err
= grub_bsd_add_meta (FREEBSD_MODINFO_END
, 0, 0);
630 for (tag
= tags
; tag
; tag
= tag
->next
)
631 tag_buf_len
= ALIGN_VAR (tag_buf_len
632 + sizeof (struct freebsd_tag_header
)
634 p_size
= ALIGN_PAGE (kern_end
+ p_size
+ tag_buf_len
) - kern_end
;
641 grub_relocator_chunk_t ch
;
642 err
= grub_relocator_alloc_chunk_addr (relocator
, &ch
,
646 p
= get_virtual_current_address (ch
);
653 if ((grub_memcmp (var
->name
, "kFreeBSD.", sizeof("kFreeBSD.") - 1) == 0) && (var
->name
[sizeof("kFreeBSD.") - 1]))
655 grub_strcpy ((char *) p
, &var
->name
[sizeof("kFreeBSD.") - 1]);
656 p
+= grub_strlen ((char *) p
);
658 grub_strcpy ((char *) p
, var
->value
);
659 p
+= grub_strlen ((char *) p
) + 1;
666 bi
.environment
= p_target
;
671 grub_uint8_t
*p_tag
= p
;
674 for (tag
= tags
; tag
; tag
= tag
->next
)
676 struct freebsd_tag_header
*head
677 = (struct freebsd_tag_header
*) p_tag
;
678 head
->type
= tag
->type
;
679 head
->len
= tag
->len
;
680 p_tag
+= sizeof (struct freebsd_tag_header
);
683 case FREEBSD_MODINFO_METADATA
| FREEBSD_MODINFOMD_HOWTO
:
685 *(grub_uint64_t
*) p_tag
= bootflags
;
687 *(grub_uint32_t
*) p_tag
= bootflags
;
690 case FREEBSD_MODINFO_METADATA
| FREEBSD_MODINFOMD_ENVP
:
692 *(grub_uint64_t
*) p_tag
= bi
.environment
;
694 *(grub_uint32_t
*) p_tag
= bi
.environment
;
697 case FREEBSD_MODINFO_METADATA
| FREEBSD_MODINFOMD_KERNEND
:
699 *(grub_uint64_t
*) p_tag
= kern_end
;
701 *(grub_uint32_t
*) p_tag
= kern_end
;
705 grub_memcpy (p_tag
, tag
->data
, tag
->len
);
709 p_tag
= ALIGN_VAR (p_tag
- p
) + p
;
712 bi
.tags
= (p
- p0
) + p_target
;
714 p
= (ALIGN_PAGE ((p_tag
- p0
) + p_target
) - p_target
) + p0
;
717 bi
.kern_end
= kern_end
;
719 grub_video_set_mode ("text", 0, 0);
723 struct grub_relocator64_state state
;
724 grub_uint8_t
*pagetable
;
725 grub_uint32_t
*stack
;
726 grub_addr_t stack_target
;
729 grub_relocator_chunk_t ch
;
730 err
= grub_relocator_alloc_chunk_align (relocator
, &ch
,
732 3 * sizeof (grub_uint32_t
)
734 GRUB_RELOCATOR_PREFERENCE_NONE
,
738 stack
= get_virtual_current_address (ch
);
739 stack_target
= get_physical_target_address (ch
);
742 #ifdef GRUB_MACHINE_EFI
743 err
= grub_efi_finish_boot_services (NULL
, NULL
, NULL
, NULL
, NULL
);
749 fill_bsd64_pagetable (pagetable
, (pagetable
- p0
) + p_target
);
751 state
.cr3
= (pagetable
- p0
) + p_target
;
752 state
.rsp
= stack_target
;
753 state
.rip
= (((grub_uint64_t
) entry_hi
) << 32) | entry
;
758 return grub_relocator64_boot (relocator
, state
, 0, 0x40000000);
762 struct grub_relocator32_state state
;
763 grub_uint32_t
*stack
;
764 grub_addr_t stack_target
;
767 grub_relocator_chunk_t ch
;
768 err
= grub_relocator_alloc_chunk_align (relocator
, &ch
,
770 9 * sizeof (grub_uint32_t
)
772 GRUB_RELOCATOR_PREFERENCE_NONE
,
776 stack
= get_virtual_current_address (ch
);
777 stack_target
= get_physical_target_address (ch
);
780 #ifdef GRUB_MACHINE_EFI
781 err
= grub_efi_finish_boot_services (NULL
, NULL
, NULL
, NULL
, NULL
);
786 grub_memcpy (&stack
[9], &bi
, sizeof (bi
));
788 state
.esp
= stack_target
;
789 state
.ebp
= stack_target
;
790 stack
[0] = entry
; /* "Return" address. */
791 stack
[1] = bootflags
| FREEBSD_RB_BOOTINFO
;
792 stack
[2] = freebsd_bootdev
;
793 stack
[3] = freebsd_zfsguid
? 4 : 0;
794 stack
[4] = freebsd_zfsguid
;
795 stack
[5] = freebsd_zfsguid
>> 32;
796 stack
[6] = stack_target
+ 9 * sizeof (grub_uint32_t
);
799 return grub_relocator32_boot (relocator
, state
, 0);
803 return GRUB_ERR_NONE
;
807 grub_openbsd_boot (void)
809 grub_uint32_t
*stack
;
810 struct grub_relocator32_state state
;
811 void *curarg
, *buf0
, *arg0
;
812 grub_addr_t buf_target
;
814 grub_size_t tag_buf_len
;
816 err
= grub_bsd_add_mmap ();
820 #ifdef GRUB_MACHINE_PCBIOS
822 struct grub_bios_int_registers regs
;
824 regs
.flags
= GRUB_CPU_INT_FLAGS_DEFAULT
;
833 grub_bios_interrupt (0x1a, ®s
);
834 if (regs
.edx
== 0x20494350)
836 struct grub_openbsd_bootarg_pcibios pcibios
;
838 pcibios
.characteristics
= regs
.eax
& 0xff;
839 pcibios
.revision
= regs
.ebx
& 0xffff;
840 pcibios
.pm_entry
= regs
.edi
;
841 pcibios
.last_bus
= regs
.ecx
& 0xff;
843 grub_bsd_add_meta (OPENBSD_BOOTARG_PCIBIOS
, &pcibios
,
852 for (tag
= tags
; tag
; tag
= tag
->next
)
853 tag_buf_len
= ALIGN_VAR (tag_buf_len
854 + sizeof (struct grub_openbsd_bootargs
)
858 buf_target
= GRUB_BSD_TEMP_BUFFER
- 9 * sizeof (grub_uint32_t
);
860 grub_relocator_chunk_t ch
;
861 err
= grub_relocator_alloc_chunk_addr (relocator
, &ch
, buf_target
,
863 + sizeof (struct grub_openbsd_bootargs
)
864 + 9 * sizeof (grub_uint32_t
));
867 buf0
= get_virtual_current_address (ch
);
870 stack
= (grub_uint32_t
*) buf0
;
871 arg0
= curarg
= stack
+ 9;
875 struct grub_openbsd_bootargs
*head
;
877 for (tag
= tags
; tag
; tag
= tag
->next
)
880 head
->ba_type
= tag
->type
;
881 head
->ba_size
= tag
->len
+ sizeof (*head
);
883 grub_memcpy (curarg
, tag
->data
, tag
->len
);
884 curarg
= (grub_uint8_t
*) curarg
+ tag
->len
;
885 head
->ba_next
= (grub_uint8_t
*) curarg
- (grub_uint8_t
*) buf0
889 head
->ba_type
= OPENBSD_BOOTARG_END
;
894 grub_video_set_mode ("text", 0, 0);
896 #ifdef GRUB_MACHINE_EFI
897 err
= grub_efi_finish_boot_services (NULL
, NULL
, NULL
, NULL
, NULL
);
903 state
.ebp
= state
.esp
904 = ((grub_uint8_t
*) stack
- (grub_uint8_t
*) buf0
) + buf_target
;
906 stack
[1] = bootflags
;
907 stack
[2] = openbsd_root
;
908 stack
[3] = OPENBSD_BOOTARG_APIVER
;
910 stack
[5] = grub_mmap_get_upper () >> 10;
911 stack
[6] = grub_mmap_get_lower () >> 10;
912 stack
[7] = (grub_uint8_t
*) curarg
- (grub_uint8_t
*) arg0
;
913 stack
[8] = ((grub_uint8_t
*) arg0
- (grub_uint8_t
*) buf0
) + buf_target
;
915 return grub_relocator32_boot (relocator
, state
, 0);
919 grub_netbsd_setup_video (void)
921 struct grub_video_mode_info mode_info
;
924 struct grub_netbsd_btinfo_framebuf params
;
926 grub_video_driver_id_t driv_id
;
928 modevar
= grub_env_get ("gfxpayload");
930 /* Now all graphical modes are acceptable.
931 May change in future if we have modes without framebuffer. */
932 if (modevar
&& *modevar
!= 0)
935 tmp
= grub_xasprintf ("%s;" NETBSD_DEFAULT_VIDEO_MODE
, modevar
);
938 err
= grub_video_set_mode (tmp
, 0, 0);
942 err
= grub_video_set_mode (NETBSD_DEFAULT_VIDEO_MODE
, 0, 0);
947 driv_id
= grub_video_get_driver_id ();
948 if (driv_id
== GRUB_VIDEO_DRIVER_NONE
)
949 return GRUB_ERR_NONE
;
951 err
= grub_video_get_info_and_fini (&mode_info
, &framebuffer
);
956 params
.width
= mode_info
.width
;
957 params
.height
= mode_info
.height
;
958 params
.bpp
= mode_info
.bpp
;
959 params
.pitch
= mode_info
.pitch
;
962 params
.fbaddr
= (grub_addr_t
) framebuffer
;
964 params
.red_mask_size
= mode_info
.red_mask_size
;
965 params
.red_field_pos
= mode_info
.red_field_pos
;
966 params
.green_mask_size
= mode_info
.green_mask_size
;
967 params
.green_field_pos
= mode_info
.green_field_pos
;
968 params
.blue_mask_size
= mode_info
.blue_mask_size
;
969 params
.blue_field_pos
= mode_info
.blue_field_pos
;
971 #ifdef GRUB_MACHINE_PCBIOS
972 /* VESA packed modes may come with zeroed mask sizes, which need
973 to be set here according to DAC Palette width. If we don't,
974 this results in Linux displaying a black screen. */
975 if (mode_info
.bpp
<= 8 && driv_id
== GRUB_VIDEO_DRIVER_VBE
)
977 struct grub_vbe_info_block controller_info
;
981 status
= grub_vbe_bios_get_controller_info (&controller_info
);
983 if (status
== GRUB_VBE_STATUS_OK
&&
984 (controller_info
.capabilities
& GRUB_VBE_CAPABILITY_DACWIDTH
))
985 status
= grub_vbe_bios_set_dac_palette_width (&width
);
987 if (status
!= GRUB_VBE_STATUS_OK
)
988 /* 6 is default after mode reset. */
991 params
.red_mask_size
= params
.green_mask_size
992 = params
.blue_mask_size
= width
;
996 err
= grub_bsd_add_meta (NETBSD_BTINFO_FRAMEBUF
, ¶ms
, sizeof (params
));
1001 grub_netbsd_add_modules (void)
1003 struct netbsd_module
*mod
;
1004 unsigned modcnt
= 0;
1005 struct grub_netbsd_btinfo_modules
*mods
;
1009 for (mod
= netbsd_mods
; mod
; mod
= mod
->next
)
1012 mods
= grub_malloc (sizeof (*mods
) + sizeof (mods
->mods
[0]) * modcnt
);
1017 mods
->last_addr
= kern_end
;
1018 for (mod
= netbsd_mods
, i
= 0; mod
; i
++, mod
= mod
->next
)
1019 mods
->mods
[i
] = mod
->mod
;
1021 err
= grub_bsd_add_meta (NETBSD_BTINFO_MODULES
, mods
,
1022 sizeof (*mods
) + sizeof (mods
->mods
[0]) * modcnt
);
1028 * Adds NetBSD bootinfo bootdisk and bootwedge. The partition identified
1029 * in these bootinfo fields is the root device.
1032 grub_netbsd_add_boot_disk_and_wedge (void)
1036 grub_partition_t part
;
1037 grub_uint32_t biosdev
;
1038 grub_uint32_t partmapsector
;
1040 grub_uint64_t raw
[GRUB_DISK_SECTOR_SIZE
/ 8];
1041 struct grub_partition_bsd_disk_label label
;
1044 if (GRUB_MD_MD5
->mdlen
> GRUB_CRYPTO_MAX_MDLEN
)
1046 grub_error (GRUB_ERR_BUG
, "mdlen too long");
1050 dev
= grub_device_open (0);
1051 if (! (dev
&& dev
->disk
&& dev
->disk
->partition
))
1055 part
= disk
->partition
;
1057 if (disk
->dev
&& disk
->dev
->id
== GRUB_DISK_DEVICE_BIOSDISK_ID
)
1058 biosdev
= (grub_uint32_t
) disk
->id
& 0xff;
1062 /* Absolute sector of the partition map describing this partition. */
1063 partmapsector
= grub_partition_get_start (part
->parent
) + part
->offset
;
1065 disk
->partition
= part
->parent
;
1066 if (grub_disk_read (disk
, part
->offset
, 0, GRUB_DISK_SECTOR_SIZE
, buf
.raw
)
1069 disk
->partition
= part
;
1071 /* Fill bootwedge. */
1073 struct grub_netbsd_btinfo_bootwedge biw
;
1074 grub_uint8_t hash
[GRUB_CRYPTO_MAX_MDLEN
];
1076 grub_memset (&biw
, 0, sizeof (biw
));
1077 biw
.biosdev
= biosdev
;
1078 biw
.startblk
= grub_partition_get_start (part
);
1079 biw
.nblks
= part
->len
;
1080 biw
.matchblk
= partmapsector
;
1083 grub_crypto_hash (GRUB_MD_MD5
, hash
,
1084 buf
.raw
, GRUB_DISK_SECTOR_SIZE
);
1085 memcpy (biw
.matchhash
, hash
, 16);
1087 grub_bsd_add_meta (NETBSD_BTINFO_BOOTWEDGE
, &biw
, sizeof (biw
));
1090 /* Fill bootdisk. */
1092 struct grub_netbsd_btinfo_bootdisk bid
;
1094 grub_memset (&bid
, 0, sizeof (bid
));
1095 /* Check for a NetBSD disk label. */
1096 if (part
->partmap
!= NULL
&&
1097 (grub_strcmp (part
->partmap
->name
, "netbsd") == 0 ||
1098 (part
->parent
== NULL
&& grub_strcmp (part
->partmap
->name
, "bsd") == 0)))
1100 bid
.labelsector
= partmapsector
;
1101 bid
.label
.type
= buf
.label
.type
;
1102 bid
.label
.checksum
= buf
.label
.checksum
;
1103 memcpy (bid
.label
.packname
, buf
.label
.packname
, 16);
1107 bid
.labelsector
= -1;
1109 bid
.biosdev
= biosdev
;
1110 bid
.partition
= part
->number
;
1112 grub_bsd_add_meta (NETBSD_BTINFO_BOOTDISK
, &bid
, sizeof (bid
));
1117 grub_device_close (dev
);
1121 grub_netbsd_boot (void)
1123 struct grub_netbsd_bootinfo
*bootinfo
;
1124 void *curarg
, *arg0
;
1125 grub_addr_t arg_target
, stack_target
;
1126 grub_uint32_t
*stack
;
1128 struct grub_relocator32_state state
;
1129 grub_size_t tag_buf_len
= 0;
1132 err
= grub_bsd_add_mmap ();
1136 err
= grub_netbsd_setup_video ();
1139 grub_print_error ();
1140 grub_puts_ (N_("Booting in blind mode"));
1141 grub_errno
= GRUB_ERR_NONE
;
1144 err
= grub_netbsd_add_modules ();
1149 struct bsd_tag
*tag
;
1151 for (tag
= tags
; tag
; tag
= tag
->next
)
1153 tag_buf_len
= ALIGN_VAR (tag_buf_len
1154 + sizeof (struct grub_netbsd_btinfo_common
)
1160 arg_target
= kern_end
;
1162 grub_relocator_chunk_t ch
;
1163 err
= grub_relocator_alloc_chunk_addr (relocator
, &ch
,
1164 arg_target
, tag_buf_len
1165 + sizeof (struct grub_netbsd_bootinfo
)
1166 + tag_count
* sizeof (grub_uint32_t
));
1169 curarg
= get_virtual_current_address (ch
);
1173 bootinfo
= (void *) ((grub_uint8_t
*) arg0
+ tag_buf_len
);
1176 struct bsd_tag
*tag
;
1179 bootinfo
->bi_count
= tag_count
;
1180 for (tag
= tags
, i
= 0; tag
; i
++, tag
= tag
->next
)
1182 struct grub_netbsd_btinfo_common
*head
= curarg
;
1183 bootinfo
->bi_data
[i
] = ((grub_uint8_t
*) curarg
- (grub_uint8_t
*) arg0
)
1185 head
->type
= tag
->type
;
1186 head
->len
= tag
->len
+ sizeof (*head
);
1188 grub_memcpy (curarg
, tag
->data
, tag
->len
);
1189 curarg
= (grub_uint8_t
*) curarg
+ tag
->len
;
1194 grub_relocator_chunk_t ch
;
1195 err
= grub_relocator_alloc_chunk_align (relocator
, &ch
, 0x10000, 0x90000,
1196 7 * sizeof (grub_uint32_t
), 4,
1197 GRUB_RELOCATOR_PREFERENCE_NONE
,
1201 stack
= get_virtual_current_address (ch
);
1202 stack_target
= get_physical_target_address (ch
);
1205 #ifdef GRUB_MACHINE_EFI
1206 err
= grub_efi_finish_boot_services (NULL
, NULL
, NULL
, NULL
, NULL
);
1212 state
.esp
= stack_target
;
1213 state
.ebp
= stack_target
;
1215 stack
[1] = bootflags
;
1217 stack
[3] = ((grub_uint8_t
*) bootinfo
- (grub_uint8_t
*) arg0
) + arg_target
;
1219 stack
[5] = grub_mmap_get_upper () >> 10;
1220 stack
[6] = grub_mmap_get_lower () >> 10;
1222 return grub_relocator32_boot (relocator
, state
, 0);
1226 grub_bsd_unload (void)
1228 struct bsd_tag
*tag
, *next
;
1229 for (tag
= tags
; tag
; tag
= next
)
1237 kernel_type
= KERNEL_TYPE_NONE
;
1238 grub_dl_unref (my_mod
);
1240 grub_relocator_unload (relocator
);
1243 return GRUB_ERR_NONE
;
1247 grub_bsd_load_aout (grub_file_t file
, const char *filename
)
1249 grub_addr_t load_addr
, load_end
;
1250 int ofs
, align_page
;
1251 union grub_aout_header ah
;
1253 grub_size_t bss_size
;
1255 if ((grub_file_seek (file
, 0)) == (grub_off_t
) - 1)
1258 if (grub_file_read (file
, &ah
, sizeof (ah
)) != sizeof (ah
))
1261 grub_error (GRUB_ERR_READ_ERROR
, N_("premature end of file %s"),
1266 if (grub_aout_get_type (&ah
) != AOUT_TYPE_AOUT32
)
1267 return grub_error (GRUB_ERR_BAD_OS
, "invalid a.out header");
1269 entry
= ah
.aout32
.a_entry
& 0xFFFFFF;
1271 if (AOUT_GETMAGIC (ah
.aout32
) == AOUT32_ZMAGIC
)
1279 load_addr
= entry
& 0xF00000;
1280 ofs
= sizeof (struct grub_aout32_header
);
1284 if (load_addr
< 0x100000)
1285 return grub_error (GRUB_ERR_BAD_OS
, "load address below 1M");
1287 kern_start
= load_addr
;
1288 load_end
= kern_end
= load_addr
+ ah
.aout32
.a_text
+ ah
.aout32
.a_data
;
1290 kern_end
= ALIGN_PAGE (kern_end
);
1292 if (ah
.aout32
.a_bss
)
1294 kern_end
+= ah
.aout32
.a_bss
;
1296 kern_end
= ALIGN_PAGE (kern_end
);
1298 bss_size
= kern_end
- load_end
;
1304 grub_relocator_chunk_t ch
;
1306 err
= grub_relocator_alloc_chunk_addr (relocator
, &ch
,
1307 kern_start
, kern_end
- kern_start
);
1310 kern_chunk_src
= get_virtual_current_address (ch
);
1313 return grub_aout_load (file
, ofs
, kern_chunk_src
,
1314 ah
.aout32
.a_text
+ ah
.aout32
.a_data
,
1319 grub_bsd_load_elf (grub_elf_t elf
, const char *filename
)
1326 if (grub_elf_is_elf32 (elf
))
1328 grub_relocator_chunk_t ch
;
1331 entry
= elf
->ehdr
.ehdr32
.e_entry
& 0xFFFFFFF;
1333 FOR_ELF32_PHDRS (elf
, phdr
)
1337 if (phdr
->p_type
!= PT_LOAD
1338 && phdr
->p_type
!= PT_DYNAMIC
)
1341 paddr
= phdr
->p_paddr
& 0xFFFFFFF;
1343 if (paddr
< kern_start
)
1346 if (paddr
+ phdr
->p_memsz
> kern_end
)
1347 kern_end
= paddr
+ phdr
->p_memsz
;
1352 err
= grub_relocator_alloc_chunk_addr (relocator
, &ch
,
1353 kern_start
, kern_end
- kern_start
);
1357 kern_chunk_src
= get_virtual_current_address (ch
);
1359 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);
1362 if (kernel_type
!= KERNEL_TYPE_OPENBSD
)
1363 return GRUB_ERR_NONE
;
1364 return grub_openbsd_find_ramdisk32 (elf
->file
, filename
, kern_start
,
1365 kern_chunk_src
, &openbsd_ramdisk
);
1367 else if (grub_elf_is_elf64 (elf
))
1373 if (! grub_cpuid_has_longmode
)
1374 return grub_error (GRUB_ERR_BAD_OS
, "your CPU does not implement AMD64 architecture");
1376 /* FreeBSD has 64-bit entry point. */
1377 if (kernel_type
== KERNEL_TYPE_FREEBSD
)
1379 entry
= elf
->ehdr
.ehdr64
.e_entry
& 0xffffffff;
1380 entry_hi
= (elf
->ehdr
.ehdr64
.e_entry
>> 32) & 0xffffffff;
1384 entry
= elf
->ehdr
.ehdr64
.e_entry
& 0x0fffffff;
1388 FOR_ELF64_PHDRS (elf
, phdr
)
1392 if (phdr
->p_type
!= PT_LOAD
1393 && phdr
->p_type
!= PT_DYNAMIC
)
1396 paddr
= phdr
->p_paddr
& 0xFFFFFFF;
1398 if (paddr
< kern_start
)
1401 if (paddr
+ phdr
->p_memsz
> kern_end
)
1402 kern_end
= paddr
+ phdr
->p_memsz
;
1408 grub_dprintf ("bsd", "kern_start = %lx, kern_end = %lx\n",
1409 (unsigned long) kern_start
, (unsigned long) kern_end
);
1411 grub_relocator_chunk_t ch
;
1413 err
= grub_relocator_alloc_chunk_addr (relocator
, &ch
, kern_start
,
1414 kern_end
- kern_start
);
1417 kern_chunk_src
= get_virtual_current_address (ch
);
1420 err
= grub_elf64_load (elf
, filename
,
1421 (grub_uint8_t
*) kern_chunk_src
- kern_start
, GRUB_ELF_LOAD_FLAGS_LOAD_PT_DYNAMIC
| GRUB_ELF_LOAD_FLAGS_28BITS
, 0, 0);
1424 if (kernel_type
!= KERNEL_TYPE_OPENBSD
)
1425 return GRUB_ERR_NONE
;
1426 return grub_openbsd_find_ramdisk64 (elf
->file
, filename
, kern_start
,
1427 kern_chunk_src
, &openbsd_ramdisk
);
1430 return grub_error (GRUB_ERR_BAD_OS
, N_("invalid arch-dependent ELF magic"));
1434 grub_bsd_load (int argc
, char *argv
[])
1439 grub_dl_ref (my_mod
);
1441 grub_loader_unset ();
1443 grub_memset (&openbsd_ramdisk
, 0, sizeof (openbsd_ramdisk
));
1447 grub_error (GRUB_ERR_BAD_ARGUMENT
, N_("filename expected"));
1451 file
= grub_file_open (argv
[0]);
1455 relocator
= grub_relocator_new ();
1458 grub_file_close (file
);
1462 elf
= grub_elf_file (file
, argv
[0]);
1466 grub_bsd_load_elf (elf
, argv
[0]);
1467 grub_elf_close (elf
);
1473 grub_bsd_load_aout (file
, argv
[0]);
1474 grub_file_close (file
);
1477 kern_end
= ALIGN_PAGE (kern_end
);
1481 if (grub_errno
!= GRUB_ERR_NONE
)
1482 grub_dl_unref (my_mod
);
1487 static grub_uint32_t
1488 grub_bsd_parse_flags (const struct grub_arg_list
*state
,
1489 const grub_uint32_t
* flags
)
1491 grub_uint32_t result
= 0;
1494 for (i
= 0; flags
[i
]; i
++)
1502 grub_cmd_freebsd (grub_extcmd_context_t ctxt
, int argc
, char *argv
[])
1504 kernel_type
= KERNEL_TYPE_FREEBSD
;
1505 bootflags
= grub_bsd_parse_flags (ctxt
->state
, freebsd_flags
);
1507 if (grub_bsd_load (argc
, argv
) == GRUB_ERR_NONE
)
1509 grub_uint32_t unit
, slice
, part
;
1511 kern_end
= ALIGN_PAGE (kern_end
);
1515 grub_uint64_t data
= 0;
1517 int len
= is_64bit
? 8 : 4;
1519 err
= grub_freebsd_add_meta_module (argv
[0], is_64bit
1520 ? FREEBSD_MODTYPE_KERNEL64
1521 : FREEBSD_MODTYPE_KERNEL
,
1524 kern_end
- kern_start
);
1528 file
= grub_file_open (argv
[0]);
1533 err
= grub_freebsd_load_elf_meta64 (relocator
, file
, argv
[0],
1536 err
= grub_freebsd_load_elf_meta32 (relocator
, file
, argv
[0],
1541 err
= grub_bsd_add_meta (FREEBSD_MODINFO_METADATA
|
1542 FREEBSD_MODINFOMD_HOWTO
, &data
, 4);
1546 err
= grub_bsd_add_meta (FREEBSD_MODINFO_METADATA
|
1547 FREEBSD_MODINFOMD_ENVP
, &data
, len
);
1551 err
= grub_bsd_add_meta (FREEBSD_MODINFO_METADATA
|
1552 FREEBSD_MODINFOMD_KERNEND
, &data
, len
);
1556 grub_bsd_get_device (&freebsd_biosdev
, &unit
, &slice
, &part
);
1557 freebsd_zfsguid
= 0;
1560 grub_print_error ();
1561 freebsd_bootdev
= (FREEBSD_B_DEVMAGIC
+ ((slice
+ 1) << FREEBSD_B_SLICESHIFT
) +
1562 (unit
<< FREEBSD_B_UNITSHIFT
) + (part
<< FREEBSD_B_PARTSHIFT
));
1564 grub_loader_set (grub_freebsd_boot
, grub_bsd_unload
, 0);
1570 static const char *types
[] = {
1580 grub_cmd_openbsd (grub_extcmd_context_t ctxt
, int argc
, char *argv
[])
1582 grub_uint32_t bootdev
;
1584 kernel_type
= KERNEL_TYPE_OPENBSD
;
1585 bootflags
= grub_bsd_parse_flags (ctxt
->state
, openbsd_flags
);
1587 if (ctxt
->state
[OPENBSD_ROOT_ARG
].set
)
1589 const char *arg
= ctxt
->state
[OPENBSD_ROOT_ARG
].arg
;
1590 unsigned type
, unit
, part
;
1591 for (type
= 0; type
< ARRAY_SIZE (types
); type
++)
1593 && grub_strncmp (arg
, types
[type
],
1594 grub_strlen (types
[type
])) == 0)
1596 arg
+= grub_strlen (types
[type
]);
1599 if (type
== ARRAY_SIZE (types
))
1600 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
1601 "unknown disk type name");
1603 unit
= grub_strtoul (arg
, (char **) &arg
, 10);
1604 if (! (arg
&& *arg
>= 'a' && *arg
<= 'z'))
1605 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
1606 "only device specifications of form "
1607 "<type><number><lowercase letter> are supported");
1611 bootdev
= (OPENBSD_B_DEVMAGIC
| (type
<< OPENBSD_B_TYPESHIFT
)
1612 | (unit
<< OPENBSD_B_UNITSHIFT
)
1613 | (part
<< OPENBSD_B_PARTSHIFT
));
1618 if (ctxt
->state
[OPENBSD_SERIAL_ARG
].set
)
1620 struct grub_openbsd_bootarg_console serial
;
1623 unsigned speed
= 9600;
1625 grub_memset (&serial
, 0, sizeof (serial
));
1627 if (ctxt
->state
[OPENBSD_SERIAL_ARG
].arg
)
1629 ptr
= ctxt
->state
[OPENBSD_SERIAL_ARG
].arg
;
1630 if (grub_memcmp (ptr
, "com", sizeof ("com") - 1) != 0)
1631 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
1632 "only com0-com3 are supported");
1633 ptr
+= sizeof ("com") - 1;
1634 port
= grub_strtoul (ptr
, &ptr
, 0);
1636 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
1637 "only com0-com3 are supported");
1641 speed
= grub_strtoul (ptr
, &ptr
, 0);
1647 serial
.device
= (GRUB_OPENBSD_COM_MAJOR
<< 8) | port
;
1648 serial
.speed
= speed
;
1650 grub_bsd_add_meta (OPENBSD_BOOTARG_CONSOLE
, &serial
, sizeof (serial
));
1651 bootflags
|= OPENBSD_RB_SERCONS
;
1655 struct grub_openbsd_bootarg_console serial
;
1657 grub_memset (&serial
, 0, sizeof (serial
));
1658 serial
.device
= (GRUB_OPENBSD_VGA_MAJOR
<< 8);
1659 grub_bsd_add_meta (OPENBSD_BOOTARG_CONSOLE
, &serial
, sizeof (serial
));
1660 bootflags
&= ~OPENBSD_RB_SERCONS
;
1663 if (grub_bsd_load (argc
, argv
) == GRUB_ERR_NONE
)
1665 grub_loader_set (grub_openbsd_boot
, grub_bsd_unload
, 0);
1666 openbsd_root
= bootdev
;
1673 grub_cmd_netbsd (grub_extcmd_context_t ctxt
, int argc
, char *argv
[])
1676 kernel_type
= KERNEL_TYPE_NETBSD
;
1677 bootflags
= grub_bsd_parse_flags (ctxt
->state
, netbsd_flags
);
1679 if (grub_bsd_load (argc
, argv
) == GRUB_ERR_NONE
)
1685 file
= grub_file_open (argv
[0]);
1690 err
= grub_netbsd_load_elf_meta64 (relocator
, file
, argv
[0], &kern_end
);
1692 err
= grub_netbsd_load_elf_meta32 (relocator
, file
, argv
[0], &kern_end
);
1698 char bootpath
[GRUB_NETBSD_MAX_BOOTPATH_LEN
];
1700 name
= grub_strrchr (argv
[0], '/');
1705 grub_memset (bootpath
, 0, sizeof (bootpath
));
1706 grub_strncpy (bootpath
, name
, sizeof (bootpath
) - 1);
1707 grub_bsd_add_meta (NETBSD_BTINFO_BOOTPATH
, bootpath
, sizeof (bootpath
));
1710 if (ctxt
->state
[NETBSD_ROOT_ARG
].set
)
1712 char root
[GRUB_NETBSD_MAX_ROOTDEVICE_LEN
];
1713 grub_memset (root
, 0, sizeof (root
));
1714 grub_strncpy (root
, ctxt
->state
[NETBSD_ROOT_ARG
].arg
,
1716 grub_bsd_add_meta (NETBSD_BTINFO_ROOTDEVICE
, root
, sizeof (root
));
1718 if (ctxt
->state
[NETBSD_SERIAL_ARG
].set
)
1720 struct grub_netbsd_btinfo_serial serial
;
1723 grub_memset (&serial
, 0, sizeof (serial
));
1724 grub_strcpy (serial
.devname
, "com");
1726 serial
.addr
= grub_ns8250_hw_get_port (0);
1727 serial
.speed
= 9600;
1729 if (ctxt
->state
[NETBSD_SERIAL_ARG
].arg
)
1731 ptr
= ctxt
->state
[NETBSD_SERIAL_ARG
].arg
;
1732 if (grub_memcmp (ptr
, "com", sizeof ("com") - 1) == 0)
1734 ptr
+= sizeof ("com") - 1;
1736 = grub_ns8250_hw_get_port (grub_strtoul (ptr
, &ptr
, 0));
1739 serial
.addr
= grub_strtoul (ptr
, &ptr
, 0);
1746 serial
.speed
= grub_strtoul (ptr
, &ptr
, 0);
1752 grub_bsd_add_meta (NETBSD_BTINFO_CONSOLE
, &serial
, sizeof (serial
));
1756 struct grub_netbsd_btinfo_serial cons
;
1758 grub_memset (&cons
, 0, sizeof (cons
));
1759 grub_strcpy (cons
.devname
, "pc");
1761 grub_bsd_add_meta (NETBSD_BTINFO_CONSOLE
, &cons
, sizeof (cons
));
1764 grub_netbsd_add_boot_disk_and_wedge ();
1766 grub_loader_set (grub_netbsd_boot
, grub_bsd_unload
, 0);
1773 grub_cmd_freebsd_loadenv (grub_command_t cmd
__attribute__ ((unused
)),
1774 int argc
, char *argv
[])
1776 grub_file_t file
= 0;
1777 char *buf
= 0, *curr
, *next
;
1780 if (! grub_loader_is_loaded ())
1781 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
1782 N_("you need to load the kernel first"));
1784 if (kernel_type
!= KERNEL_TYPE_FREEBSD
)
1785 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
1786 "only FreeBSD supports environment");
1790 grub_error (GRUB_ERR_BAD_ARGUMENT
, N_("filename expected"));
1794 file
= grub_file_open (argv
[0]);
1795 if ((!file
) || (!file
->size
))
1799 buf
= grub_malloc (len
+ 1);
1803 if (grub_file_read (file
, buf
, len
) != len
)
1814 next
= grub_strchr (curr
, '\n');
1821 if ((*p
!= '\r') && (*p
!= ' ') && (*p
!= '\t'))
1826 if ((p
> curr
) && (*p
== '"'))
1836 p
= grub_strchr (curr
, '=');
1849 name
= grub_xasprintf ("kFreeBSD.%s", curr
);
1852 if (grub_env_set (name
, p
))
1865 grub_file_close (file
);
1871 grub_cmd_freebsd_module (grub_command_t cmd
__attribute__ ((unused
)),
1872 int argc
, char *argv
[])
1874 grub_file_t file
= 0;
1881 if (kernel_type
!= KERNEL_TYPE_FREEBSD
)
1882 return grub_error (GRUB_ERR_BAD_ARGUMENT
, "no FreeBSD loaded");
1885 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
1886 "only ELF kernel supports module");
1888 /* List the current modules if no parameter. */
1891 grub_freebsd_list_modules ();
1895 file
= grub_file_open (argv
[0]);
1896 if ((!file
) || (!file
->size
))
1900 grub_relocator_chunk_t ch
;
1901 err
= grub_relocator_alloc_chunk_addr (relocator
, &ch
, kern_end
,
1905 src
= get_virtual_current_address (ch
);
1909 grub_file_read (file
, src
, file
->size
);
1916 if (modargc
&& (! grub_memcmp (modargv
[0], "type=", 5)))
1918 type
= &modargv
[0][5];
1923 type
= FREEBSD_MODTYPE_RAW
;
1925 err
= grub_freebsd_add_meta_module (argv
[0], type
, modargc
, modargv
,
1926 kern_end
, file
->size
);
1930 kern_end
= ALIGN_PAGE (kern_end
+ file
->size
);
1934 grub_file_close (file
);
1940 grub_netbsd_module_load (char *filename
, grub_uint32_t type
)
1942 grub_file_t file
= 0;
1946 file
= grub_file_open (filename
);
1947 if ((!file
) || (!file
->size
))
1951 grub_relocator_chunk_t ch
;
1952 err
= grub_relocator_alloc_chunk_addr (relocator
, &ch
, kern_end
,
1957 src
= get_virtual_current_address (ch
);
1960 grub_file_read (file
, src
, file
->size
);
1964 err
= grub_netbsd_add_meta_module (filename
, type
, kern_end
, file
->size
);
1969 kern_end
= ALIGN_PAGE (kern_end
+ file
->size
);
1973 grub_file_close (file
);
1979 grub_cmd_netbsd_module (grub_command_t cmd
,
1980 int argc
, char *argv
[])
1984 if (kernel_type
!= KERNEL_TYPE_NETBSD
)
1985 return grub_error (GRUB_ERR_BAD_ARGUMENT
, "no NetBSD loaded");
1988 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
1989 "only ELF kernel supports module");
1991 /* List the current modules if no parameter. */
1994 grub_netbsd_list_modules ();
1998 if (grub_strcmp (cmd
->name
, "knetbsd_module_elf") == 0)
1999 type
= GRUB_NETBSD_MODULE_ELF
;
2001 type
= GRUB_NETBSD_MODULE_RAW
;
2003 return grub_netbsd_module_load (argv
[0], type
);
2007 grub_cmd_freebsd_module_elf (grub_command_t cmd
__attribute__ ((unused
)),
2008 int argc
, char *argv
[])
2010 grub_file_t file
= 0;
2013 if (! grub_loader_is_loaded ())
2014 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
2015 N_("you need to load the kernel first"));
2017 if (kernel_type
!= KERNEL_TYPE_FREEBSD
)
2018 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
2019 "only FreeBSD supports module");
2021 if (! is_elf_kernel
)
2022 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
2023 "only ELF kernel supports module");
2025 /* List the current modules if no parameter. */
2028 grub_freebsd_list_modules ();
2032 file
= grub_file_open (argv
[0]);
2037 grub_file_close (file
);
2042 err
= grub_freebsd_load_elfmodule_obj64 (relocator
, file
,
2043 argc
, argv
, &kern_end
);
2045 err
= grub_freebsd_load_elfmodule32 (relocator
, file
,
2046 argc
, argv
, &kern_end
);
2047 grub_file_close (file
);
2053 grub_cmd_openbsd_ramdisk (grub_command_t cmd
__attribute__ ((unused
)),
2054 int argc
, char *args
[])
2060 return grub_error (GRUB_ERR_BAD_ARGUMENT
, N_("filename expected"));
2062 if (kernel_type
!= KERNEL_TYPE_OPENBSD
)
2063 return grub_error (GRUB_ERR_BAD_OS
, "no kOpenBSD loaded");
2065 if (!openbsd_ramdisk
.max_size
)
2066 return grub_error (GRUB_ERR_BAD_OS
, "your kOpenBSD doesn't support ramdisk");
2068 file
= grub_file_open (args
[0]);
2072 size
= grub_file_size (file
);
2074 if (size
> openbsd_ramdisk
.max_size
)
2076 grub_file_close (file
);
2077 return grub_error (GRUB_ERR_BAD_OS
, "your kOpenBSD supports ramdisk only"
2078 " up to %u bytes, however you supplied a %u bytes one",
2079 openbsd_ramdisk
.max_size
, size
);
2082 if (grub_file_read (file
, openbsd_ramdisk
.target
, size
)
2083 != (grub_ssize_t
) (size
))
2085 grub_file_close (file
);
2087 grub_error (GRUB_ERR_BAD_OS
, N_("premature end of file %s"), args
[0]);
2090 grub_memset (openbsd_ramdisk
.target
+ size
, 0,
2091 openbsd_ramdisk
.max_size
- size
);
2092 *openbsd_ramdisk
.size
= ALIGN_UP (size
, 512);
2094 return GRUB_ERR_NONE
;
2097 static grub_extcmd_t cmd_freebsd
, cmd_openbsd
, cmd_netbsd
;
2098 static grub_command_t cmd_freebsd_loadenv
, cmd_freebsd_module
;
2099 static grub_command_t cmd_netbsd_module
, cmd_freebsd_module_elf
;
2100 static grub_command_t cmd_netbsd_module_elf
, cmd_openbsd_ramdisk
;
2104 /* Net and OpenBSD kernels are often compressed. */
2105 grub_dl_load ("gzio");
2107 cmd_freebsd
= grub_register_extcmd ("kfreebsd", grub_cmd_freebsd
, 0,
2108 N_("FILE"), N_("Load kernel of FreeBSD."),
2110 cmd_openbsd
= grub_register_extcmd ("kopenbsd", grub_cmd_openbsd
, 0,
2111 N_("FILE"), N_("Load kernel of OpenBSD."),
2113 cmd_netbsd
= grub_register_extcmd ("knetbsd", grub_cmd_netbsd
, 0,
2114 N_("FILE"), N_("Load kernel of NetBSD."),
2116 cmd_freebsd_loadenv
=
2117 grub_register_command ("kfreebsd_loadenv", grub_cmd_freebsd_loadenv
,
2118 0, N_("Load FreeBSD env."));
2119 cmd_freebsd_module
=
2120 grub_register_command ("kfreebsd_module", grub_cmd_freebsd_module
,
2121 0, N_("Load FreeBSD kernel module."));
2123 grub_register_command ("knetbsd_module", grub_cmd_netbsd_module
,
2124 0, N_("Load NetBSD kernel module."));
2125 cmd_netbsd_module_elf
=
2126 grub_register_command ("knetbsd_module_elf", grub_cmd_netbsd_module
,
2127 0, N_("Load NetBSD kernel module (ELF)."));
2128 cmd_freebsd_module_elf
=
2129 grub_register_command ("kfreebsd_module_elf", grub_cmd_freebsd_module_elf
,
2130 0, N_("Load FreeBSD kernel module (ELF)."));
2132 cmd_openbsd_ramdisk
= grub_register_command ("kopenbsd_ramdisk",
2133 grub_cmd_openbsd_ramdisk
, 0,
2134 /* TRANSLATORS: ramdisk isn't identifier,
2135 it can be translated. */
2136 N_("Load kOpenBSD ramdisk."));
2143 grub_unregister_extcmd (cmd_freebsd
);
2144 grub_unregister_extcmd (cmd_openbsd
);
2145 grub_unregister_extcmd (cmd_netbsd
);
2147 grub_unregister_command (cmd_freebsd_loadenv
);
2148 grub_unregister_command (cmd_freebsd_module
);
2149 grub_unregister_command (cmd_netbsd_module
);
2150 grub_unregister_command (cmd_freebsd_module_elf
);
2151 grub_unregister_command (cmd_netbsd_module_elf
);
2152 grub_unregister_command (cmd_openbsd_ramdisk
);