Compare commits

...
85 Commits
Author SHA1 Message Date
Vladimir Serbinenko 6e4e4ee33f dwc2 counterpart of previous patch 2016-03-01 20:09:54 +01:00
Vladimir Serbinenko e1444e5399 Rename portstatus to reset_port.
The way we currently use portstatus always uses
enable=1 and we use it for its reset side effect.
Change confusing name and remove unused parameter.
2016-03-01 20:09:47 +01:00
Vladimir Serbinenko ef57ad6164 detect_dev 2016-03-01 19:59:52 +01:00
Vladimir Serbinenko 72bd5756af dwc2 skeleton 2016-02-27 16:15:43 +01:00
Vladimir Serbinenko 295e041189 clone ehci to dwc1 2016-02-25 19:55:39 +01:00
Vladimir Serbinenko 3f6f84f9e0 fix mkimage.c split 2016-02-25 19:52:46 +01:00
Vladimir Serbinenko 9f8f747605 usbtrans: Fix memory coherence 2016-02-23 12:07:01 +01:00
Vladimir Serbinenko 102016960d ehci: Fix memory coherence 2016-02-23 12:06:48 +01:00
Vladimir Serbinenko 07cd46627b arm: implement grub_arch_sync_dma_caches 2016-02-23 12:06:00 +01:00
Vladimir Serbinenko 9e161d1302 Make dma_caches accept volatile 2016-02-23 11:45:29 +01:00
Vladimir Serbinenko 06c92907c1 cros fix 2016-02-23 11:26:35 +01:00
Vladimir Serbinenko 74cef4ab78 cleaner 2016-02-23 10:19:26 +01:00
Vladimir Serbinenko f4116c3a42 Decrease frame timeout 2016-02-23 10:15:05 +01:00
Vladimir Serbinenko 2d56c1b117 cleaner 2016-02-23 09:52:08 +01:00
Vladimir Serbinenko 1f72ca020d cleaner 2016-02-23 09:50:43 +01:00
Vladimir Serbinenko 3d300d7247 cleaner 2016-02-23 09:43:57 +01:00
Vladimir Serbinenko 03104c2d98 always use older cros protocol. We don't realy need new one 2016-02-23 09:42:09 +01:00
Vladimir Serbinenko 40562ddf1e cros e0 fix 2016-02-22 21:12:50 +01:00
Vladimir Serbinenko 1ea06af1ae EHCI FDT missing file 2016-02-22 20:40:16 +01:00
Vladimir Serbinenko df21b9363d cleaner 2016-02-22 19:44:39 +01:00
Vladimir Serbinenko 8efde40d0c cleaner 2016-02-22 19:44:09 +01:00
Vladimir Serbinenko d624e04af1 cleaner 2016-02-22 19:39:30 +01:00
Vladimir Serbinenko bbd85a0292 cleaner 2016-02-22 19:38:26 +01:00
Vladimir Serbinenko 4f06545767 cleaner 2016-02-22 19:37:37 +01:00
Vladimir Serbinenko 66d0e16425 cleaner 2016-02-22 19:35:46 +01:00
Vladimir Serbinenko a98c706755 cleaner 2016-02-22 19:35:16 +01:00
Vladimir Serbinenko 95f663ec1d cleaner 2016-02-22 19:34:30 +01:00
Vladimir Serbinenko 2b2a338ad6 cleaner 2016-02-22 19:33:34 +01:00
Vladimir Serbinenko 6c9512b610 cleaner 2016-02-22 19:33:13 +01:00
Vladimir Serbinenko f447b3d2bb Dirty cros keyboard import 2016-02-22 19:29:47 +01:00
Vladimir Serbinenko 295fe6c548 Dirty cros keyboard 2016-02-22 19:29:08 +01:00
Vladimir Serbinenko 9cd85f276f frequency 2016-02-22 03:34:35 +01:00
Vladimir Serbinenko 502a7c48e9 ARM caches 2016-02-22 03:34:16 +01:00
Vladimir Serbinenko 418b32f8e9 EHCI reset fix 2016-02-22 03:33:59 +01:00
Vladimir Serbinenko 98490fc328 DMA split 2016-02-22 03:33:18 +01:00
Vladimir Serbinenko 3625fdc0b9 Improve EHCI logging 2016-02-22 03:32:50 +01:00
Vladimir Serbinenko 1ec2b7758b ehci split fixup 2016-02-22 03:28:10 +01:00
Vladimir Serbinenko f51e8d0dda coreboot 2016-02-22 03:27:39 +01:00
Vladimir Serbinenko ee52ea80d6 Remove useless include 2016-02-22 03:25:50 +01:00
Vladimir Serbinenko c55f74a5c5 ehci split 2016-02-22 01:08:27 +01:00
Vladimir Serbinenko 3b1bb7f3eb DTB overrides 2016-02-22 00:05:40 +01:00
Vladimir Serbinenko 0b71582111 coreboot 2016-02-21 20:28:10 +01:00
Vladimir Serbinenko dc491ff04a fdtbus 2016-02-21 20:27:50 +01:00
Vladimir Serbinenko 192243b13e Out-of-place FDT handling 2016-02-21 20:27:28 +01:00
Vladimir Serbinenko 0f3ae7324a fdt 2016-02-21 19:48:57 +01:00
Vladimir Serbinenko ab8770a314 pre-located image for veyron 2016-02-21 19:28:56 +01:00
Vladimir Serbinenko f2df41cffa coreboot 2016-02-21 19:28:40 +01:00
Vladimir Serbinenko b0227ce4b9 fdt: relax align requirement 2016-02-21 19:28:23 +01:00
Vladimir Serbinenko f900bea454 coreboot 2016-02-21 18:59:14 +01:00
Vladimir Serbinenko dc51ac70ee switch to layout 2016-02-21 18:47:29 +01:00
Vladimir Serbinenko 869a0bc476 coreboot 2016-02-21 18:44:55 +01:00
Vladimir Serbinenko f9ee0c3e5d Simplify reloc 2016-02-21 18:44:18 +01:00
Vladimir Serbinenko 8af26e386c coreboot reloc 2016-02-21 18:42:35 +01:00
Vladimir Serbinenko 78e9b82d2c coreboot memory before _start 2016-02-21 18:41:39 +01:00
Vladimir Serbinenko 86139504b7 pl050 2016-02-21 01:53:44 +01:00
Vladimir Serbinenko 35c1d629f9 fdtbus 2016-02-21 01:53:07 +01:00
Vladimir Serbinenko bacb8f911f coreboot 2016-02-21 00:05:38 +01:00
Vladimir Serbinenko fbda565356 fdt 2016-02-21 00:05:21 +01:00
Vladimir Serbinenko 598185f806 fdtbus 2016-02-21 00:04:18 +01:00
Vladimir Serbinenko ca2fd6c93f ps2 split 2016-02-20 18:45:42 +01:00
Vladimir Serbinenko a29fb4722c coreboot 2016-02-20 16:26:23 +01:00
Vladimir Serbinenko 7562f4ab53 bus fdt improvements 2016-02-20 16:25:39 +01:00
Vladimir Serbinenko c7d0aa5450 fdtbus 2016-02-20 14:30:43 +01:00
Vladimir Serbinenko ceb68c6648 missing files 2016-02-20 14:29:01 +01:00
Vladimir Serbinenko 99291427d2 fdtlib 2016-02-20 14:28:37 +01:00
Vladimir Serbinenko 6ffee98e1b Useless fdt.lst 2016-02-20 14:22:34 +01:00
Vladimir Serbinenko a6649f5b8e FDT lib improvements 2016-02-20 12:30:06 +01:00
Vladimir Serbinenko c3c14cffef refresh before abort 2016-02-20 09:12:15 +01:00
Vladimir Serbinenko 84939af253 generic timer safeguard 2016-02-20 09:12:02 +01:00
Vladimir Serbinenko ba6d40e8bb WIP2 2016-02-19 16:47:36 +01:00
Vladimir Serbinenko 2c3a054f4f WIP 2016-02-19 12:41:50 +01:00
Vladimir Serbinenko b8eda96422 rename 2016-02-19 12:17:56 +01:00
Vladimir Serbinenko ca3962ca7b fix relocate 2016-02-19 12:17:20 +01:00
Vladimir Serbinenko a4f7d77f7d fs 2016-02-19 04:48:50 +01:00
Vladimir Serbinenko 5099975ace fd 2016-02-19 04:48:17 +01:00
Vladimir Serbinenko 2f98d7648e Move cbfb 2016-02-19 04:47:02 +01:00
Vladimir Serbinenko 018e382144 decouple 2016-02-19 04:31:59 +01:00
Vladimir Serbinenko f5cba79512 Declare arm-coreboot 2016-02-19 03:24:49 +01:00
Vladimir Serbinenko 46569db585 arm-uboot: Make self-relocatable to allow loading at any address 2016-02-19 03:22:10 +01:00
Vladimir Serbinenko 575c7a6e3c Allow _start == 0 with relocatable images 2016-02-19 02:03:28 +01:00
Vladimir Serbinenko fc489a889d Provide __bss_start and _end symbols in grub-mkimage.
For this ensure that all bss sections are merged.
2016-02-19 02:02:50 +01:00
Vladimir Serbinenko bfb517bc3b encapsulate 2016-02-19 01:58:11 +01:00
Vladimir Serbinenko 437dba573f Remove useless ifdef 2016-02-19 01:28:16 +01:00
Vladimir Serbinenko 974ba94330 mkimagexx: Split PE and generic part. 2016-02-19 01:14:12 +01:00
Vladimir Serbinenko 963d21b76c file split 2016-02-19 01:14:12 +01:00
70 changed files with 5905 additions and 1663 deletions

No files matched your search

+10
View File
@@ -172,6 +172,8 @@ program = {
common = util/grub-mkimage.c; common = util/grub-mkimage.c;
common = util/mkimage.c; common = util/mkimage.c;
common = util/grub-mkimage32.c;
common = util/grub-mkimage64.c;
common = util/resolve.c; common = util/resolve.c;
common = grub-core/kern/emu/argp_common.c; common = grub-core/kern/emu/argp_common.c;
common = grub-core/osdep/init.c; common = grub-core/osdep/init.c;
@@ -510,6 +512,8 @@ program = {
common = util/render-label.c; common = util/render-label.c;
common = util/glue-efi.c; common = util/glue-efi.c;
common = util/mkimage.c; common = util/mkimage.c;
common = util/grub-mkimage32.c;
common = util/grub-mkimage64.c;
common = util/grub-install-common.c; common = util/grub-install-common.c;
common = util/setup_bios.c; common = util/setup_bios.c;
common = util/setup_sparc.c; common = util/setup_sparc.c;
@@ -552,6 +556,8 @@ program = {
common = util/render-label.c; common = util/render-label.c;
common = util/glue-efi.c; common = util/glue-efi.c;
common = util/mkimage.c; common = util/mkimage.c;
common = util/grub-mkimage32.c;
common = util/grub-mkimage64.c;
common = util/grub-install-common.c; common = util/grub-install-common.c;
common = util/setup_bios.c; common = util/setup_bios.c;
common = util/setup_sparc.c; common = util/setup_sparc.c;
@@ -595,6 +601,8 @@ program = {
common = util/grub-install.c; common = util/grub-install.c;
common = util/probe.c; common = util/probe.c;
common = util/mkimage.c; common = util/mkimage.c;
common = util/grub-mkimage32.c;
common = util/grub-mkimage64.c;
common = util/grub-install-common.c; common = util/grub-install-common.c;
common = util/setup_bios.c; common = util/setup_bios.c;
common = util/setup_sparc.c; common = util/setup_sparc.c;
@@ -632,6 +640,8 @@ program = {
common = util/grub-mknetdir.c; common = util/grub-mknetdir.c;
common = util/mkimage.c; common = util/mkimage.c;
common = util/grub-mkimage32.c;
common = util/grub-mkimage64.c;
common = util/grub-install-common.c; common = util/grub-install-common.c;
common = util/setup_bios.c; common = util/setup_bios.c;
common = util/setup_sparc.c; common = util/setup_sparc.c;
+3 -1
View File
@@ -86,9 +86,11 @@ CPPFLAGS_TERMINAL_LIST += '-Dgrub_term_register_output(...)=OUTPUT_TERMINAL_LIST
CPPFLAGS_COMMAND_LIST = '-Dgrub_register_command(...)=COMMAND_LIST_MARKER(__VA_ARGS__)' CPPFLAGS_COMMAND_LIST = '-Dgrub_register_command(...)=COMMAND_LIST_MARKER(__VA_ARGS__)'
CPPFLAGS_COMMAND_LIST += '-Dgrub_register_extcmd(...)=EXTCOMMAND_LIST_MARKER(__VA_ARGS__)' CPPFLAGS_COMMAND_LIST += '-Dgrub_register_extcmd(...)=EXTCOMMAND_LIST_MARKER(__VA_ARGS__)'
CPPFLAGS_COMMAND_LIST += '-Dgrub_register_command_p1(...)=P1COMMAND_LIST_MARKER(__VA_ARGS__)' CPPFLAGS_COMMAND_LIST += '-Dgrub_register_command_p1(...)=P1COMMAND_LIST_MARKER(__VA_ARGS__)'
CPPFLAGS_FDT_LIST := '-Dgrub_fdtbus_register(...)=FDT_DRIVER_LIST_MARKER(__VA_ARGS__)'
CPPFLAGS_MARKER = $(CPPFLAGS_FS_LIST) $(CPPFLAGS_VIDEO_LIST) \ CPPFLAGS_MARKER = $(CPPFLAGS_FS_LIST) $(CPPFLAGS_VIDEO_LIST) \
$(CPPFLAGS_PARTTOOL_LIST) $(CPPFLAGS_PARTMAP_LIST) \ $(CPPFLAGS_PARTTOOL_LIST) $(CPPFLAGS_PARTMAP_LIST) \
$(CPPFLAGS_TERMINAL_LIST) $(CPPFLAGS_COMMAND_LIST) $(CPPFLAGS_TERMINAL_LIST) $(CPPFLAGS_COMMAND_LIST) \
$(CPPFLAGS_FDT_LIST)
# Define these variables to calm down automake # Define these variables to calm down automake
+2
View File
@@ -167,6 +167,7 @@ case "$target_cpu"-"$platform" in
mipsel-fuloong) platform=loongson ;; mipsel-fuloong) platform=loongson ;;
mipsel-loongson) ;; mipsel-loongson) ;;
arm-uboot) ;; arm-uboot) ;;
arm-coreboot) ;;
arm-efi) ;; arm-efi) ;;
arm64-efi) ;; arm64-efi) ;;
*-emu) ;; *-emu) ;;
@@ -1872,6 +1873,7 @@ AM_CONDITIONAL([COND_mipsel], [test x$target_cpu = xmipsel])
AM_CONDITIONAL([COND_mipseb], [test x$target_cpu = xmips]) AM_CONDITIONAL([COND_mipseb], [test x$target_cpu = xmips])
AM_CONDITIONAL([COND_arm], [test x$target_cpu = xarm ]) AM_CONDITIONAL([COND_arm], [test x$target_cpu = xarm ])
AM_CONDITIONAL([COND_arm_uboot], [test x$target_cpu = xarm -a x$platform = xuboot]) AM_CONDITIONAL([COND_arm_uboot], [test x$target_cpu = xarm -a x$platform = xuboot])
AM_CONDITIONAL([COND_arm_coreboot], [test x$target_cpu = xarm -a x$platform = xcoreboot])
AM_CONDITIONAL([COND_arm_efi], [test x$target_cpu = xarm -a x$platform = xefi]) AM_CONDITIONAL([COND_arm_efi], [test x$target_cpu = xarm -a x$platform = xefi])
AM_CONDITIONAL([COND_arm64], [test x$target_cpu = xarm64 ]) AM_CONDITIONAL([COND_arm64], [test x$target_cpu = xarm64 ])
AM_CONDITIONAL([COND_arm64_efi], [test x$target_cpu = xarm64 -a x$platform = xefi]) AM_CONDITIONAL([COND_arm64_efi], [test x$target_cpu = xarm64 -a x$platform = xefi])
+6 -4
View File
@@ -31,7 +31,8 @@ GRUB_PLATFORMS = [ "emu", "i386_pc", "i386_efi", "i386_qemu", "i386_coreboot",
"i386_xen", "x86_64_xen", "i386_xen", "x86_64_xen",
"mips_loongson", "sparc64_ieee1275", "mips_loongson", "sparc64_ieee1275",
"powerpc_ieee1275", "mips_arc", "ia64_efi", "powerpc_ieee1275", "mips_arc", "ia64_efi",
"mips_qemu_mips", "arm_uboot", "arm_efi", "arm64_efi" ] "mips_qemu_mips", "arm_uboot", "arm_efi", "arm64_efi",
"arm_coreboot"]
GROUPS = {} GROUPS = {}
@@ -44,7 +45,7 @@ GROUPS["x86"] = GROUPS["i386"] + GROUPS["x86_64"]
GROUPS["mips"] = [ "mips_loongson", "mips_qemu_mips", "mips_arc" ] GROUPS["mips"] = [ "mips_loongson", "mips_qemu_mips", "mips_arc" ]
GROUPS["sparc64"] = [ "sparc64_ieee1275" ] GROUPS["sparc64"] = [ "sparc64_ieee1275" ]
GROUPS["powerpc"] = [ "powerpc_ieee1275" ] GROUPS["powerpc"] = [ "powerpc_ieee1275" ]
GROUPS["arm"] = [ "arm_uboot", "arm_efi" ] GROUPS["arm"] = [ "arm_uboot", "arm_efi", "arm_coreboot" ]
GROUPS["arm64"] = [ "arm64_efi" ] GROUPS["arm64"] = [ "arm64_efi" ]
# Groups based on firmware # Groups based on firmware
@@ -52,6 +53,7 @@ GROUPS["efi"] = [ "i386_efi", "x86_64_efi", "ia64_efi", "arm_efi", "arm64_efi"
GROUPS["ieee1275"] = [ "i386_ieee1275", "sparc64_ieee1275", "powerpc_ieee1275" ] GROUPS["ieee1275"] = [ "i386_ieee1275", "sparc64_ieee1275", "powerpc_ieee1275" ]
GROUPS["uboot"] = [ "arm_uboot" ] GROUPS["uboot"] = [ "arm_uboot" ]
GROUPS["xen"] = [ "i386_xen", "x86_64_xen" ] GROUPS["xen"] = [ "i386_xen", "x86_64_xen" ]
GROUPS["coreboot"] = [ "i386_coreboot", "arm_coreboot" ]
# emu is a special case so many core functionality isn't needed on this platform # emu is a special case so many core functionality isn't needed on this platform
GROUPS["noemu"] = GRUB_PLATFORMS[:]; GROUPS["noemu"].remove("emu") GROUPS["noemu"] = GRUB_PLATFORMS[:]; GROUPS["noemu"].remove("emu")
@@ -61,10 +63,10 @@ GROUPS["cmos"] = GROUPS["x86"][:] + ["mips_loongson", "mips_qemu_mips",
"sparc64_ieee1275", "powerpc_ieee1275"] "sparc64_ieee1275", "powerpc_ieee1275"]
GROUPS["cmos"].remove("i386_efi"); GROUPS["cmos"].remove("x86_64_efi"); GROUPS["cmos"].remove("i386_efi"); GROUPS["cmos"].remove("x86_64_efi");
GROUPS["pci"] = GROUPS["x86"] + ["mips_loongson"] GROUPS["pci"] = GROUPS["x86"] + ["mips_loongson"]
GROUPS["usb"] = GROUPS["pci"] GROUPS["usb"] = GROUPS["pci"] + ["arm_coreboot"]
# If gfxterm is main output console integrate it into kernel # If gfxterm is main output console integrate it into kernel
GROUPS["videoinkernel"] = ["mips_loongson", "i386_coreboot" ] GROUPS["videoinkernel"] = ["mips_loongson", "i386_coreboot", "arm_coreboot" ]
GROUPS["videomodules"] = GRUB_PLATFORMS[:]; GROUPS["videomodules"] = GRUB_PLATFORMS[:];
for i in GROUPS["videoinkernel"]: GROUPS["videomodules"].remove(i) for i in GROUPS["videoinkernel"]: GROUPS["videomodules"].remove(i)
+25 -1
View File
@@ -112,7 +112,7 @@ endif
if COND_i386_coreboot if COND_i386_coreboot
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/tsc.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/tsc.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/coreboot/lbio.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/coreboot/lbio.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/video.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/video.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/video_fb.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/video_fb.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/gfxterm.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/gfxterm.h
@@ -239,6 +239,20 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/arm/system.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/arm/system.h
endif endif
if COND_arm_coreboot
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/keyboard_layouts.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/arm/system.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/video.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/video_fb.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/gfxterm.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/font.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/bufio.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/fdt.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/dma.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/arm/coreboot/kernel.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/fdtbus.h
endif
if COND_arm_efi if COND_arm_efi
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/arm/efi/loader.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/arm/efi/loader.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h
@@ -358,6 +372,16 @@ terminal.lst: $(MARKER_FILES)
platform_DATA += terminal.lst platform_DATA += terminal.lst
CLEANFILES += terminal.lst CLEANFILES += terminal.lst
fdt.lst: $(MARKER_FILES)
(for pp in $^; do \
b=`basename $$pp .marker`; \
sed -n \
-e "/FDT_DRIVER_LIST_MARKER *( *\"/{s/.*( *\"\([^\"]*\)\".*/i\1: $$b/;p;}" \
-e "/FDT_DRIVER_LIST_MARKER *( *\"/{s/.*( *\"\([^\"]*\)\".*/o\1: $$b/;p;}" $$pp; \
done) | sort -u > $@
platform_DATA += fdt.lst
CLEANFILES += fdt.lst
parttool.lst: $(MARKER_FILES) parttool.lst: $(MARKER_FILES)
(for pp in $^; do \ (for pp in $^; do \
b=`basename $$pp .marker`; \ b=`basename $$pp .marker`; \
+39 -6
View File
@@ -90,8 +90,10 @@ kernel = {
i386_qemu_cppflags = '-DGRUB_BOOT_MACHINE_LINK_ADDR=$(GRUB_BOOT_MACHINE_LINK_ADDR)'; i386_qemu_cppflags = '-DGRUB_BOOT_MACHINE_LINK_ADDR=$(GRUB_BOOT_MACHINE_LINK_ADDR)';
emu_cflags = '$(CFLAGS_GNULIB)'; emu_cflags = '$(CFLAGS_GNULIB)';
emu_cppflags = '$(CPPFLAGS_GNULIB)'; emu_cppflags = '$(CPPFLAGS_GNULIB)';
arm_uboot_ldflags = '-Wl,-Ttext=0x08000000'; arm_uboot_ldflags = '-Wl,-r,-d';
arm_uboot_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version'; arm_uboot_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version';
arm_coreboot_ldflags = '-Wl,-r,-d';
arm_coreboot_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version';
i386_pc_startup = kern/i386/pc/startup.S; i386_pc_startup = kern/i386/pc/startup.S;
i386_efi_startup = kern/i386/efi/startup.S; i386_efi_startup = kern/i386/efi/startup.S;
@@ -105,7 +107,8 @@ kernel = {
mips_startup = kern/mips/startup.S; mips_startup = kern/mips/startup.S;
sparc64_ieee1275_startup = kern/sparc64/ieee1275/crt0.S; sparc64_ieee1275_startup = kern/sparc64/ieee1275/crt0.S;
powerpc_ieee1275_startup = kern/powerpc/ieee1275/startup.S; powerpc_ieee1275_startup = kern/powerpc/ieee1275/startup.S;
arm_uboot_startup = kern/arm/uboot/startup.S; arm_uboot_startup = kern/arm/startup.S;
arm_coreboot_startup = kern/arm/startup.S;
arm_efi_startup = kern/arm/efi/startup.S; arm_efi_startup = kern/arm/efi/startup.S;
arm64_efi_startup = kern/arm64/efi/startup.S; arm64_efi_startup = kern/arm64/efi/startup.S;
@@ -149,6 +152,20 @@ kernel = {
uboot = kern/uboot/init.c; uboot = kern/uboot/init.c;
uboot = kern/uboot/hw.c; uboot = kern/uboot/hw.c;
uboot = term/uboot/console.c; uboot = term/uboot/console.c;
arm_uboot = kern/arm/uboot/init.c;
arm_uboot = kern/arm/uboot/uboot.S;
arm_coreboot = kern/arm/coreboot/init.c;
arm_coreboot = kern/arm/coreboot/timer.c;
arm_coreboot = kern/arm/coreboot/coreboot.S;
arm_coreboot = lib/fdt.c;
arm_coreboot = bus/fdt.c;
arm_coreboot = term/ps2.c;
arm_coreboot = term/arm/pl050.c;
arm_coreboot = term/arm/cros.c;
arm_coreboot = term/arm/cros_ec.c;
arm_coreboot = commands/keylayouts.c;
arm_coreboot = kern/arm/coreboot/dma.c;
terminfoinkernel = term/terminfo.c; terminfoinkernel = term/terminfo.c;
terminfoinkernel = term/tparm.c; terminfoinkernel = term/tparm.c;
@@ -164,7 +181,7 @@ kernel = {
i386_multiboot = kern/i386/coreboot/init.c; i386_multiboot = kern/i386/coreboot/init.c;
i386_qemu = kern/i386/qemu/init.c; i386_qemu = kern/i386/qemu/init.c;
i386_coreboot_multiboot_qemu = term/i386/pc/vga_text.c; i386_coreboot_multiboot_qemu = term/i386/pc/vga_text.c;
i386_coreboot = video/i386/coreboot/cbfb.c; coreboot = video/coreboot/cbfb.c;
efi = disk/efi/efidisk.c; efi = disk/efi/efidisk.c;
efi = kern/efi/efi.c; efi = kern/efi/efi.c;
@@ -223,8 +240,9 @@ kernel = {
i386_qemu = kern/vga_init.c; i386_qemu = kern/vga_init.c;
i386_qemu = kern/i386/qemu/mmap.c; i386_qemu = kern/i386/qemu/mmap.c;
i386_coreboot = kern/i386/coreboot/mmap.c; coreboot = kern/coreboot/mmap.c;
i386_coreboot = kern/i386/coreboot/cbtable.c; i386_coreboot = kern/i386/coreboot/cbtable.c;
arm_coreboot = kern/arm/coreboot/cbtable.c;
i386_multiboot = kern/i386/multiboot_mmap.c; i386_multiboot = kern/i386/multiboot_mmap.c;
@@ -236,6 +254,7 @@ kernel = {
mips_qemu_mips = term/ns8250.c; mips_qemu_mips = term/ns8250.c;
mips_qemu_mips = term/serial.c; mips_qemu_mips = term/serial.c;
mips_qemu_mips = term/at_keyboard.c; mips_qemu_mips = term/at_keyboard.c;
mips_qemu_mips = term/ps2.c;
mips_qemu_mips = commands/boot.c; mips_qemu_mips = commands/boot.c;
mips_qemu_mips = commands/keylayouts.c; mips_qemu_mips = commands/keylayouts.c;
mips_qemu_mips = term/i386/pc/vga_text.c; mips_qemu_mips = term/i386/pc/vga_text.c;
@@ -251,6 +270,7 @@ kernel = {
mips_loongson = bus/pci.c; mips_loongson = bus/pci.c;
mips_loongson = kern/mips/loongson/init.c; mips_loongson = kern/mips/loongson/init.c;
mips_loongson = term/at_keyboard.c; mips_loongson = term/at_keyboard.c;
mips_loongson = term/ps2.c;
mips_loongson = commands/boot.c; mips_loongson = commands/boot.c;
mips_loongson = term/serial.c; mips_loongson = term/serial.c;
mips_loongson = video/sm712.c; mips_loongson = video/sm712.c;
@@ -572,7 +592,17 @@ module = {
module = { module = {
name = ehci; name = ehci;
common = bus/usb/ehci.c; common = bus/usb/ehci.c;
arm_coreboot = bus/usb/ehci-fdt.c;
pci = bus/usb/ehci-pci.c;
enable = pci; enable = pci;
enable = arm_coreboot;
};
module = {
name = dwc2;
common = bus/usb/dwc2.c;
arm_coreboot = bus/usb/dwc2-fdt.c;
enable = arm_coreboot;
}; };
module = { module = {
@@ -752,6 +782,7 @@ module = {
enable = arm_efi; enable = arm_efi;
enable = arm64_efi; enable = arm64_efi;
enable = arm_uboot; enable = arm_uboot;
enable = arm_coreboot;
}; };
module = { module = {
@@ -819,7 +850,7 @@ module = {
common = commands/gptsync.c; common = commands/gptsync.c;
}; };
module = { /*module = {
name = halt; name = halt;
nopc = commands/halt.c; nopc = commands/halt.c;
i386_pc = commands/i386/pc/halt.c; i386_pc = commands/i386/pc/halt.c;
@@ -854,7 +885,7 @@ module = {
xen = lib/xen/reboot.c; xen = lib/xen/reboot.c;
uboot = lib/uboot/reboot.c; uboot = lib/uboot/reboot.c;
common = commands/reboot.c; common = commands/reboot.c;
}; };*/
module = { module = {
name = hashsum; name = hashsum;
@@ -1546,6 +1577,7 @@ module = {
cmos = lib/cmos_datetime.c; cmos = lib/cmos_datetime.c;
efi = lib/efi/datetime.c; efi = lib/efi/datetime.c;
uboot = lib/uboot/datetime.c; uboot = lib/uboot/datetime.c;
arm_coreboot = lib/uboot/datetime.c;
sparc64_ieee1275 = lib/ieee1275/datetime.c; sparc64_ieee1275 = lib/ieee1275/datetime.c;
powerpc_ieee1275 = lib/ieee1275/datetime.c; powerpc_ieee1275 = lib/ieee1275/datetime.c;
sparc64_ieee1275 = lib/ieee1275/cmos.c; sparc64_ieee1275 = lib/ieee1275/cmos.c;
@@ -1866,6 +1898,7 @@ module = {
module = { module = {
name = at_keyboard; name = at_keyboard;
common = term/at_keyboard.c; common = term/at_keyboard.c;
common = term/ps2.c;
enable = x86; enable = x86;
}; };
+255
View File
@@ -0,0 +1,255 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2016 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* 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/fdtbus.h>
#include <grub/fdt.h>
#include <grub/term.h>
static const void *dtb;
static grub_size_t root_address_cells, root_size_cells;
/* Pointer to this symbol signals invalid mapping. */
char grub_fdtbus_invalid_mapping[1];
struct grub_fdtbus_dev
{
struct grub_fdtbus_dev *next;
struct grub_fdtbus_dev *parent;
int node;
struct grub_fdtbus_driver *driver;
};
struct grub_fdtbus_dev *devs;
struct grub_fdtbus_driver *drivers;
static int
is_compatible (struct grub_fdtbus_driver *driver,
int node)
{
grub_size_t compatible_size;
const char *compatible = grub_fdt_get_prop (dtb, node, "compatible",
&compatible_size);
const char *compatible_end = compatible + compatible_size;
while (compatible < compatible_end)
{
if (grub_strcmp (driver->compatible, compatible) == 0)
return 1;
compatible += grub_strlen (compatible) + 1;
}
return 0;
}
static void
fdtbus_scan (struct grub_fdtbus_dev *parent)
{
int node;
for (node = grub_fdt_first_node (dtb, parent ? parent->node : 0); node >= 0;
node = grub_fdt_next_node (dtb, node))
{
struct grub_fdtbus_dev *dev;
struct grub_fdtbus_driver *driver;
dev = grub_zalloc (sizeof (*dev));
if (!dev)
{
grub_print_error ();
return;
}
dev->node = node;
dev->next = devs;
dev->parent = parent;
devs = dev;
FOR_LIST_ELEMENTS(driver, drivers)
if (!dev->driver && is_compatible (driver, node))
{
if (driver->attach(dev) == GRUB_ERR_NONE)
{
dev->driver = driver;
break;
}
grub_print_error ();
}
fdtbus_scan (dev);
}
}
void
grub_fdtbus_register (struct grub_fdtbus_driver *driver)
{
struct grub_fdtbus_dev *dev;
grub_list_push (GRUB_AS_LIST_P (&drivers),
GRUB_AS_LIST (driver));
for (dev = devs; dev; dev = dev->next)
if (!dev->driver && is_compatible (driver, dev->node))
{
if (driver->attach(dev) == GRUB_ERR_NONE)
dev->driver = driver;
grub_print_error ();
}
}
void
grub_fdtbus_unregister (struct grub_fdtbus_driver *driver)
{
grub_list_remove (GRUB_AS_LIST (driver));
struct grub_fdtbus_dev *dev;
for (dev = devs; dev; dev = dev->next)
if (dev->driver == driver)
{
if (driver->detach)
driver->detach(dev);
dev->driver = 0;
}
}
void
grub_fdtbus_init (const void *dtb_in, grub_size_t size)
{
if (!dtb_in || grub_fdt_check_header (dtb_in, size) < 0)
grub_fatal ("invalid FDT");
dtb = dtb_in;
const grub_uint32_t *prop = grub_fdt_get_prop (dtb, 0, "#address-cells", 0);
if (prop)
root_address_cells = grub_be_to_cpu32 (*prop);
else
root_address_cells = 1;
prop = grub_fdt_get_prop (dtb, 0, "#size-cells", 0);
if (prop)
root_size_cells = grub_be_to_cpu32 (*prop);
else
root_size_cells = 1;
fdtbus_scan (0);
}
static int
get_address_cells (const struct grub_fdtbus_dev *dev)
{
const grub_uint32_t *prop;
if (!dev)
return root_address_cells;
prop = grub_fdt_get_prop (dtb, dev->node, "#address-cells", 0);
if (prop)
return grub_be_to_cpu32 (*prop);
return 1;
}
static int
get_size_cells (const struct grub_fdtbus_dev *dev)
{
const grub_uint32_t *prop;
if (!dev)
return root_size_cells;
prop = grub_fdt_get_prop (dtb, dev->node, "#size-cells", 0);
if (prop)
return grub_be_to_cpu32 (*prop);
return 1;
}
static grub_uint64_t
get64 (const grub_uint32_t *reg, grub_size_t cells)
{
grub_uint64_t val = 0;
if (cells >= 1)
val = grub_be_to_cpu32 (reg[cells - 1]);
if (cells >= 2)
val |= ((grub_uint64_t) grub_be_to_cpu32 (reg[cells - 2])) << 32;
return val;
}
static volatile void *
translate (const struct grub_fdtbus_dev *dev, const grub_uint32_t *reg)
{
volatile void *ret;
const grub_uint32_t *ranges;
grub_size_t ranges_size, cells_per_mapping;
grub_size_t parent_address_cells, child_address_cells, child_size_cells;
grub_size_t nmappings, i;
if (dev == 0)
{
grub_uint64_t val;
val = get64 (reg, root_address_cells);
if (sizeof (void *) == 4 && (val >> 32))
return grub_fdtbus_invalid_mapping;
return (void *) (grub_addr_t) val;
}
ranges = grub_fdt_get_prop (dtb, dev->node, "ranges", &ranges_size);
if (!ranges)
return grub_fdtbus_invalid_mapping;
if (ranges_size == 0)
return translate (dev->parent, reg);
parent_address_cells = get_address_cells (dev->parent);
child_address_cells = get_address_cells (dev);
child_size_cells = get_size_cells (dev);
cells_per_mapping = parent_address_cells + child_address_cells + child_size_cells;
nmappings = ranges_size / 4 / cells_per_mapping;
for (i = 0; i < nmappings; i++)
{
const grub_uint32_t *child_addr = &ranges[i * cells_per_mapping];
const grub_uint32_t *parent_addr = child_addr + child_address_cells;
grub_uint64_t child_size = get64 (parent_addr + parent_address_cells, child_size_cells);
if (child_address_cells > 2 && grub_memcmp (reg, child_addr, (child_address_cells - 2) * 4) != 0)
continue;
if (get64 (reg, child_address_cells) < get64 (child_addr, child_address_cells))
continue;
grub_uint64_t offset = get64 (reg, child_address_cells) - get64 (child_addr, child_address_cells);
if (offset >= child_size)
continue;
ret = translate (dev->parent, parent_addr);
if (grub_fdtbus_is_mapping_valid (ret))
ret = (volatile char *) ret + offset;
return ret;
}
return grub_fdtbus_invalid_mapping;
}
volatile void *
grub_fdtbus_map_reg (const struct grub_fdtbus_dev *dev, int regno, grub_size_t *size)
{
grub_size_t address_cells, size_cells;
address_cells = get_address_cells (dev->parent);
size_cells = get_size_cells (dev->parent);
const grub_uint32_t *reg = grub_fdt_get_prop (dtb, dev->node, "reg", 0);
if (size && size_cells)
*size = reg[(address_cells + size_cells) * regno + address_cells];
if (size && !size_cells)
*size = 0;
return translate (dev->parent, reg + (address_cells + size_cells) * regno);
}
const char *
grub_fdtbus_get_name (const struct grub_fdtbus_dev *dev)
{
return grub_fdt_get_nodename (dtb, dev->node);
}
const void *
grub_fdtbus_get_prop (const struct grub_fdtbus_dev *dev,
const char *name,
grub_uint32_t *len)
{
return grub_fdt_get_prop (dtb, dev->node, name, len);
}
const void *
grub_fdtbus_get_fdt (void)
{
return dtb;
}
+45
View File
@@ -0,0 +1,45 @@
/* ehci.c - EHCI Support. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2011 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* 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/misc.h>
#include <grub/mm.h>
#include <grub/time.h>
#include <grub/usb.h>
#include <grub/fdtbus.h>
static grub_err_t
dwc2_attach(const struct grub_fdtbus_dev *dev)
{
grub_dprintf ("dwc2", "Found snps-dwc2\n");
grub_dwc2_init_device (grub_fdtbus_map_reg (dev, 0, 0));
return 0;
}
struct grub_fdtbus_driver dwc2 =
{
.compatible = "snps,dwc2",
.attach = dwc2_attach
};
void
grub_dwc2_pci_scan (void)
{
grub_fdtbus_register (&dwc2);
}
File diff suppressed because it is too large. Load diff
+45
View File
@@ -0,0 +1,45 @@
/* ehci.c - EHCI Support. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2011 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* 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/misc.h>
#include <grub/mm.h>
#include <grub/time.h>
#include <grub/usb.h>
#include <grub/fdtbus.h>
static grub_err_t
ehci_attach(const struct grub_fdtbus_dev *dev)
{
grub_dprintf ("ehci", "Found generic-ehci\n");
grub_ehci_init_device (grub_fdtbus_map_reg (dev, 0, 0));
return 0;
}
struct grub_fdtbus_driver ehci =
{
.compatible = "generic-ehci",
.attach = ehci_attach
};
void
grub_ehci_pci_scan (void)
{
grub_fdtbus_register (&ehci);
}
+208
View File
@@ -0,0 +1,208 @@
/* ehci.c - EHCI Support. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2011 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* 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/pci.h>
#include <grub/cpu/pci.h>
#include <grub/cs5536.h>
#include <grub/misc.h>
#include <grub/mm.h>
#include <grub/time.h>
#include <grub/usb.h>
#define GRUB_EHCI_PCI_SBRN_REG 0x60
#define GRUB_EHCI_ADDR_MEM_MASK (~0xff)
/* USBLEGSUP bits and related OS OWNED byte offset */
enum
{
GRUB_EHCI_BIOS_OWNED = (1 << 16),
GRUB_EHCI_OS_OWNED = (1 << 24)
};
/* PCI iteration function... */
static int
grub_ehci_pci_iter (grub_pci_device_t dev, grub_pci_id_t pciid,
void *data __attribute__ ((unused)))
{
volatile grub_uint32_t *regs;
grub_uint32_t base, base_h;
grub_uint32_t eecp_offset;
grub_uint32_t usblegsup = 0;
grub_uint64_t maxtime;
grub_uint32_t interf;
grub_uint32_t subclass;
grub_uint32_t class;
grub_uint8_t release;
grub_uint32_t class_code;
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: begin\n");
if (pciid == GRUB_CS5536_PCIID)
{
grub_uint64_t basereg;
basereg = grub_cs5536_read_msr (dev, GRUB_CS5536_MSR_USB_EHCI_BASE);
if (!(basereg & GRUB_CS5536_MSR_USB_BASE_MEMORY_ENABLE))
{
/* Shouldn't happen. */
grub_dprintf ("ehci", "No EHCI address is assigned\n");
return 0;
}
base = (basereg & GRUB_CS5536_MSR_USB_BASE_ADDR_MASK);
basereg |= GRUB_CS5536_MSR_USB_BASE_BUS_MASTER;
basereg &= ~GRUB_CS5536_MSR_USB_BASE_PME_ENABLED;
basereg &= ~GRUB_CS5536_MSR_USB_BASE_PME_STATUS;
basereg &= ~GRUB_CS5536_MSR_USB_BASE_SMI_ENABLE;
grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_USB_EHCI_BASE, basereg);
}
else
{
grub_pci_address_t addr;
addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS);
class_code = grub_pci_read (addr) >> 8;
interf = class_code & 0xFF;
subclass = (class_code >> 8) & 0xFF;
class = class_code >> 16;
/* If this is not an EHCI controller, just return. */
if (class != 0x0c || subclass != 0x03 || interf != 0x20)
return 0;
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: class OK\n");
/* Check Serial Bus Release Number */
addr = grub_pci_make_address (dev, GRUB_EHCI_PCI_SBRN_REG);
release = grub_pci_read_byte (addr);
if (release != 0x20)
{
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: Wrong SBRN: %0x\n",
release);
return 0;
}
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: bus rev. num. OK\n");
/* Determine EHCI EHCC registers base address. */
addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0);
base = grub_pci_read (addr);
addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG1);
base_h = grub_pci_read (addr);
/* Stop if registers are mapped above 4G - GRUB does not currently
* work with registers mapped above 4G */
if (((base & GRUB_PCI_ADDR_MEM_TYPE_MASK) != GRUB_PCI_ADDR_MEM_TYPE_32)
&& (base_h != 0))
{
grub_dprintf ("ehci",
"EHCI grub_ehci_pci_iter: registers above 4G are not supported\n");
return 0;
}
base &= GRUB_PCI_ADDR_MEM_MASK;
if (!base)
{
grub_dprintf ("ehci",
"EHCI: EHCI is not mapped\n");
return 0;
}
/* Set bus master - needed for coreboot, VMware, broken BIOSes etc. */
addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND);
grub_pci_write_word(addr,
GRUB_PCI_COMMAND_MEM_ENABLED
| GRUB_PCI_COMMAND_BUS_MASTER
| grub_pci_read_word(addr));
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: 32-bit EHCI OK\n");
}
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: iobase of EHCC: %08x\n",
(base & GRUB_EHCI_ADDR_MEM_MASK));
regs = grub_pci_device_map_range (dev,
(base & GRUB_EHCI_ADDR_MEM_MASK),
0x100);
/* Is there EECP ? */
eecp_offset = (grub_le_to_cpu32 (regs[2]) >> 8) & 0xff;
/* Determine and change ownership. */
/* EECP offset valid in HCCPARAMS */
/* Ownership can be changed via EECP only */
if (pciid != GRUB_CS5536_PCIID && eecp_offset >= 0x40)
{
grub_pci_address_t pciaddr_eecp;
pciaddr_eecp = grub_pci_make_address (dev, eecp_offset);
usblegsup = grub_pci_read (pciaddr_eecp);
if (usblegsup & GRUB_EHCI_BIOS_OWNED)
{
grub_boot_time ("Taking ownership of EHCI controller");
grub_dprintf ("ehci",
"EHCI grub_ehci_pci_iter: EHCI owned by: BIOS\n");
/* Ownership change - set OS_OWNED bit */
grub_pci_write (pciaddr_eecp, usblegsup | GRUB_EHCI_OS_OWNED);
/* Ensure PCI register is written */
grub_pci_read (pciaddr_eecp);
/* Wait for finish of ownership change, EHCI specification
* doesn't say how long it can take... */
maxtime = grub_get_time_ms () + 1000;
while ((grub_pci_read (pciaddr_eecp) & GRUB_EHCI_BIOS_OWNED)
&& (grub_get_time_ms () < maxtime));
if (grub_pci_read (pciaddr_eecp) & GRUB_EHCI_BIOS_OWNED)
{
grub_dprintf ("ehci",
"EHCI grub_ehci_pci_iter: EHCI change ownership timeout");
/* Change ownership in "hard way" - reset BIOS ownership */
grub_pci_write (pciaddr_eecp, GRUB_EHCI_OS_OWNED);
/* Ensure PCI register is written */
grub_pci_read (pciaddr_eecp);
}
}
else if (usblegsup & GRUB_EHCI_OS_OWNED)
/* XXX: What to do in this case - nothing ? Can it happen ? */
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: EHCI owned by: OS\n");
else
{
grub_dprintf ("ehci",
"EHCI grub_ehci_pci_iter: EHCI owned by: NONE\n");
/* XXX: What to do in this case ? Can it happen ?
* Is code below correct ? */
/* Ownership change - set OS_OWNED bit */
grub_pci_write (pciaddr_eecp, GRUB_EHCI_OS_OWNED);
/* Ensure PCI register is written */
grub_pci_read (pciaddr_eecp);
}
/* Disable SMI, just to be sure. */
pciaddr_eecp = grub_pci_make_address (dev, eecp_offset + 4);
grub_pci_write (pciaddr_eecp, 0);
/* Ensure PCI register is written */
grub_pci_read (pciaddr_eecp);
}
grub_dprintf ("ehci", "inithw: EHCI grub_ehci_pci_iter: ownership OK\n");
grub_ehci_init_device (regs);
return 0;
}
void
grub_ehci_pci_scan (void)
{
grub_pci_iterate (grub_ehci_pci_iter, NULL);
}
+74 -206
View File
@@ -22,13 +22,11 @@
#include <grub/usb.h> #include <grub/usb.h>
#include <grub/usbtrans.h> #include <grub/usbtrans.h>
#include <grub/misc.h> #include <grub/misc.h>
#include <grub/pci.h>
#include <grub/cpu/pci.h>
#include <grub/cpu/io.h>
#include <grub/time.h> #include <grub/time.h>
#include <grub/loader.h> #include <grub/loader.h>
#include <grub/cs5536.h>
#include <grub/disk.h> #include <grub/disk.h>
#include <grub/dma.h>
#include <grub/cache.h>
GRUB_MOD_LICENSE ("GPLv3+"); GRUB_MOD_LICENSE ("GPLv3+");
@@ -38,8 +36,6 @@ GRUB_MOD_LICENSE ("GPLv3+");
* - is not supporting interrupt transfers * - is not supporting interrupt transfers
*/ */
#define GRUB_EHCI_PCI_SBRN_REG 0x60
/* Capability registers offsets */ /* Capability registers offsets */
enum enum
{ {
@@ -53,7 +49,6 @@ enum
#define GRUB_EHCI_EECP_MASK (0xff << 8) #define GRUB_EHCI_EECP_MASK (0xff << 8)
#define GRUB_EHCI_EECP_SHIFT 8 #define GRUB_EHCI_EECP_SHIFT 8
#define GRUB_EHCI_ADDR_MEM_MASK (~0xff)
#define GRUB_EHCI_POINTER_MASK (~0x1f) #define GRUB_EHCI_POINTER_MASK (~0x1f)
/* Capability register SPARAMS bits */ /* Capability register SPARAMS bits */
@@ -84,13 +79,6 @@ enum
#define GRUB_EHCI_QH_EMPTY 1 #define GRUB_EHCI_QH_EMPTY 1
/* USBLEGSUP bits and related OS OWNED byte offset */
enum
{
GRUB_EHCI_BIOS_OWNED = (1 << 16),
GRUB_EHCI_OS_OWNED = (1 << 24)
};
/* Operational registers offsets */ /* Operational registers offsets */
enum enum
{ {
@@ -337,6 +325,21 @@ struct grub_ehci
static struct grub_ehci *ehci; static struct grub_ehci *ehci;
static void
sync_all_caches (struct grub_ehci *e)
{
if (!e)
return;
if (e->td_virt)
grub_arch_sync_dma_caches (e->td_virt, sizeof (struct grub_ehci_td) *
GRUB_EHCI_N_TD);
if (e->qh_virt)
grub_arch_sync_dma_caches (e->qh_virt, sizeof (struct grub_ehci_qh) *
GRUB_EHCI_N_QH);
if (e->framelist_virt)
grub_arch_sync_dma_caches (e->framelist_virt, 4096);
}
/* EHCC registers access functions */ /* EHCC registers access functions */
static inline grub_uint32_t static inline grub_uint32_t
grub_ehci_ehcc_read32 (struct grub_ehci *e, grub_uint32_t addr) grub_ehci_ehcc_read32 (struct grub_ehci *e, grub_uint32_t addr)
@@ -437,9 +440,12 @@ grub_ehci_reset (struct grub_ehci *e)
{ {
grub_uint64_t maxtime; grub_uint64_t maxtime;
sync_all_caches (e);
grub_dprintf ("ehci", "reset\n");
grub_ehci_oper_write32 (e, GRUB_EHCI_COMMAND, grub_ehci_oper_write32 (e, GRUB_EHCI_COMMAND,
GRUB_EHCI_CMD_HC_RESET GRUB_EHCI_CMD_HC_RESET);
| grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND));
/* Ensure command is written */ /* Ensure command is written */
grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND); grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND);
/* XXX: How long time could take reset of HC ? */ /* XXX: How long time could take reset of HC ? */
@@ -455,116 +461,24 @@ grub_ehci_reset (struct grub_ehci *e)
} }
/* PCI iteration function... */ /* PCI iteration function... */
static int void
grub_ehci_pci_iter (grub_pci_device_t dev, grub_pci_id_t pciid, grub_ehci_init_device (volatile void *regs)
void *data __attribute__ ((unused)))
{ {
grub_uint8_t release;
grub_uint32_t class_code;
grub_uint32_t interf;
grub_uint32_t subclass;
grub_uint32_t class;
grub_uint32_t base, base_h;
struct grub_ehci *e; struct grub_ehci *e;
grub_uint32_t eecp_offset;
grub_uint32_t fp; grub_uint32_t fp;
int i; int i;
grub_uint32_t usblegsup = 0;
grub_uint64_t maxtime;
grub_uint32_t n_ports; grub_uint32_t n_ports;
grub_uint8_t caplen; grub_uint8_t caplen;
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: begin\n");
if (pciid == GRUB_CS5536_PCIID)
{
grub_uint64_t basereg;
basereg = grub_cs5536_read_msr (dev, GRUB_CS5536_MSR_USB_EHCI_BASE);
if (!(basereg & GRUB_CS5536_MSR_USB_BASE_MEMORY_ENABLE))
{
/* Shouldn't happen. */
grub_dprintf ("ehci", "No EHCI address is assigned\n");
return 0;
}
base = (basereg & GRUB_CS5536_MSR_USB_BASE_ADDR_MASK);
basereg |= GRUB_CS5536_MSR_USB_BASE_BUS_MASTER;
basereg &= ~GRUB_CS5536_MSR_USB_BASE_PME_ENABLED;
basereg &= ~GRUB_CS5536_MSR_USB_BASE_PME_STATUS;
basereg &= ~GRUB_CS5536_MSR_USB_BASE_SMI_ENABLE;
grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_USB_EHCI_BASE, basereg);
}
else
{
grub_pci_address_t addr;
addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS);
class_code = grub_pci_read (addr) >> 8;
interf = class_code & 0xFF;
subclass = (class_code >> 8) & 0xFF;
class = class_code >> 16;
/* If this is not an EHCI controller, just return. */
if (class != 0x0c || subclass != 0x03 || interf != 0x20)
return 0;
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: class OK\n");
/* Check Serial Bus Release Number */
addr = grub_pci_make_address (dev, GRUB_EHCI_PCI_SBRN_REG);
release = grub_pci_read_byte (addr);
if (release != 0x20)
{
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: Wrong SBRN: %0x\n",
release);
return 0;
}
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: bus rev. num. OK\n");
/* Determine EHCI EHCC registers base address. */
addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0);
base = grub_pci_read (addr);
addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG1);
base_h = grub_pci_read (addr);
/* Stop if registers are mapped above 4G - GRUB does not currently
* work with registers mapped above 4G */
if (((base & GRUB_PCI_ADDR_MEM_TYPE_MASK) != GRUB_PCI_ADDR_MEM_TYPE_32)
&& (base_h != 0))
{
grub_dprintf ("ehci",
"EHCI grub_ehci_pci_iter: registers above 4G are not supported\n");
return 0;
}
base &= GRUB_PCI_ADDR_MEM_MASK;
if (!base)
{
grub_dprintf ("ehci",
"EHCI: EHCI is not mapped\n");
return 0;
}
/* Set bus master - needed for coreboot, VMware, broken BIOSes etc. */
addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND);
grub_pci_write_word(addr,
GRUB_PCI_COMMAND_MEM_ENABLED
| GRUB_PCI_COMMAND_BUS_MASTER
| grub_pci_read_word(addr));
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: 32-bit EHCI OK\n");
}
/* Allocate memory for the controller and fill basic values. */ /* Allocate memory for the controller and fill basic values. */
e = grub_zalloc (sizeof (*e)); e = grub_zalloc (sizeof (*e));
if (!e) if (!e)
return 1; return;
e->framelist_chunk = NULL; e->framelist_chunk = NULL;
e->td_chunk = NULL; e->td_chunk = NULL;
e->qh_chunk = NULL; e->qh_chunk = NULL;
e->iobase_ehcc = grub_pci_device_map_range (dev, e->iobase_ehcc = regs;
(base & GRUB_EHCI_ADDR_MEM_MASK),
0x100);
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: iobase of EHCC: %08x\n",
(base & GRUB_EHCI_ADDR_MEM_MASK));
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: CAPLEN: %02x\n", grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: CAPLEN: %02x\n",
grub_ehci_ehcc_read8 (e, GRUB_EHCI_EHCC_CAPLEN)); grub_ehci_ehcc_read8 (e, GRUB_EHCI_EHCC_CAPLEN));
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: VERSION: %04x\n", grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: VERSION: %04x\n",
@@ -580,7 +494,7 @@ grub_ehci_pci_iter (grub_pci_device_t dev, grub_pci_id_t pciid,
if (caplen & (sizeof (grub_uint32_t) - 1)) if (caplen & (sizeof (grub_uint32_t) - 1))
{ {
grub_dprintf ("ehci", "Unaligned caplen\n"); grub_dprintf ("ehci", "Unaligned caplen\n");
return 0; return;
} }
e->iobase = ((volatile grub_uint32_t *) e->iobase_ehcc e->iobase = ((volatile grub_uint32_t *) e->iobase_ehcc
+ (caplen / sizeof (grub_uint32_t))); + (caplen / sizeof (grub_uint32_t)));
@@ -591,7 +505,7 @@ grub_ehci_pci_iter (grub_pci_device_t dev, grub_pci_id_t pciid,
grub_dprintf ("ehci", grub_dprintf ("ehci",
"EHCI grub_ehci_pci_iter: iobase of oper. regs: %08x\n", "EHCI grub_ehci_pci_iter: iobase of oper. regs: %08x\n",
(base & GRUB_EHCI_ADDR_MEM_MASK) + caplen); (grub_addr_t) e->iobase_ehcc + caplen);
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: COMMAND: %08x\n", grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: COMMAND: %08x\n",
grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND)); grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND));
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: STATUS: %08x\n", grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: STATUS: %08x\n",
@@ -607,10 +521,6 @@ grub_ehci_pci_iter (grub_pci_device_t dev, grub_pci_id_t pciid,
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: CONFIG_FLAG: %08x\n", grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: CONFIG_FLAG: %08x\n",
grub_ehci_oper_read32 (e, GRUB_EHCI_CONFIG_FLAG)); grub_ehci_oper_read32 (e, GRUB_EHCI_CONFIG_FLAG));
/* Is there EECP ? */
eecp_offset = (grub_ehci_ehcc_read32 (e, GRUB_EHCI_EHCC_CPARAMS)
& GRUB_EHCI_EECP_MASK) >> GRUB_EHCI_EECP_SHIFT;
/* Check format of data structures requested by EHCI */ /* Check format of data structures requested by EHCI */
/* XXX: In fact it is not used at any place, it is prepared for future /* XXX: In fact it is not used at any place, it is prepared for future
* This implementation uses 32-bits pointers only */ * This implementation uses 32-bits pointers only */
@@ -714,65 +624,6 @@ grub_ehci_pci_iter (grub_pci_device_t dev, grub_pci_id_t pciid,
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: QH/TD init. OK\n"); grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: QH/TD init. OK\n");
/* Determine and change ownership. */
/* EECP offset valid in HCCPARAMS */
/* Ownership can be changed via EECP only */
if (pciid != GRUB_CS5536_PCIID && eecp_offset >= 0x40)
{
grub_pci_address_t pciaddr_eecp;
pciaddr_eecp = grub_pci_make_address (dev, eecp_offset);
usblegsup = grub_pci_read (pciaddr_eecp);
if (usblegsup & GRUB_EHCI_BIOS_OWNED)
{
grub_boot_time ("Taking ownership of EHCI controller");
grub_dprintf ("ehci",
"EHCI grub_ehci_pci_iter: EHCI owned by: BIOS\n");
/* Ownership change - set OS_OWNED bit */
grub_pci_write (pciaddr_eecp, usblegsup | GRUB_EHCI_OS_OWNED);
/* Ensure PCI register is written */
grub_pci_read (pciaddr_eecp);
/* Wait for finish of ownership change, EHCI specification
* doesn't say how long it can take... */
maxtime = grub_get_time_ms () + 1000;
while ((grub_pci_read (pciaddr_eecp) & GRUB_EHCI_BIOS_OWNED)
&& (grub_get_time_ms () < maxtime));
if (grub_pci_read (pciaddr_eecp) & GRUB_EHCI_BIOS_OWNED)
{
grub_dprintf ("ehci",
"EHCI grub_ehci_pci_iter: EHCI change ownership timeout");
/* Change ownership in "hard way" - reset BIOS ownership */
grub_pci_write (pciaddr_eecp, GRUB_EHCI_OS_OWNED);
/* Ensure PCI register is written */
grub_pci_read (pciaddr_eecp);
}
}
else if (usblegsup & GRUB_EHCI_OS_OWNED)
/* XXX: What to do in this case - nothing ? Can it happen ? */
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: EHCI owned by: OS\n");
else
{
grub_dprintf ("ehci",
"EHCI grub_ehci_pci_iter: EHCI owned by: NONE\n");
/* XXX: What to do in this case ? Can it happen ?
* Is code below correct ? */
/* Ownership change - set OS_OWNED bit */
grub_pci_write (pciaddr_eecp, GRUB_EHCI_OS_OWNED);
/* Ensure PCI register is written */
grub_pci_read (pciaddr_eecp);
}
/* Disable SMI, just to be sure. */
pciaddr_eecp = grub_pci_make_address (dev, eecp_offset + 4);
grub_pci_write (pciaddr_eecp, 0);
/* Ensure PCI register is written */
grub_pci_read (pciaddr_eecp);
}
grub_dprintf ("ehci", "inithw: EHCI grub_ehci_pci_iter: ownership OK\n");
/* Now we can setup EHCI (maybe...) */ /* Now we can setup EHCI (maybe...) */
/* Check if EHCI is halted and halt it if not */ /* Check if EHCI is halted and halt it if not */
@@ -840,11 +691,13 @@ grub_ehci_pci_iter (grub_pci_device_t dev, grub_pci_id_t pciid,
e->next = ehci; e->next = ehci;
ehci = e; ehci = e;
sync_all_caches (e);
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: OK at all\n"); grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: OK at all\n");
grub_dprintf ("ehci", grub_dprintf ("ehci",
"EHCI grub_ehci_pci_iter: iobase of oper. regs: %08x\n", "EHCI grub_ehci_pci_iter: iobase of oper. regs: %08x\n",
(base & GRUB_EHCI_ADDR_MEM_MASK)); (grub_addr_t) regs);
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: COMMAND: %08x\n", grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: COMMAND: %08x\n",
grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND)); grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND));
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: STATUS: %08x\n", grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: STATUS: %08x\n",
@@ -860,7 +713,7 @@ grub_ehci_pci_iter (grub_pci_device_t dev, grub_pci_id_t pciid,
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: CONFIG_FLAG: %08x\n", grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: CONFIG_FLAG: %08x\n",
grub_ehci_oper_read32 (e, GRUB_EHCI_CONFIG_FLAG)); grub_ehci_oper_read32 (e, GRUB_EHCI_CONFIG_FLAG));
return 0; return;
fail: fail:
if (e) if (e)
@@ -874,7 +727,7 @@ fail:
} }
grub_free (e); grub_free (e);
return 0; return;
} }
static int static int
@@ -1020,6 +873,7 @@ grub_ehci_find_qh (struct grub_ehci *e, grub_usb_transfer_t transfer)
/* Found proper existing (and linked) QH, do setup of QH */ /* Found proper existing (and linked) QH, do setup of QH */
grub_dprintf ("ehci", "find_qh: found, QH=%p\n", qh_iter); grub_dprintf ("ehci", "find_qh: found, QH=%p\n", qh_iter);
grub_ehci_setup_qh (qh_iter, transfer); grub_ehci_setup_qh (qh_iter, transfer);
sync_all_caches (e);
return qh_iter; return qh_iter;
} }
@@ -1289,16 +1143,28 @@ grub_ehci_setup_transfer (grub_usb_controller_t dev,
grub_ehci_td_t td_prev = NULL; grub_ehci_td_t td_prev = NULL;
int i; int i;
struct grub_ehci_transfer_controller_data *cdata; struct grub_ehci_transfer_controller_data *cdata;
grub_uint32_t status;
sync_all_caches (e);
/* Check if EHCI is running and AL is enabled */ /* Check if EHCI is running and AL is enabled */
if ((grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS) status = grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS);
& GRUB_EHCI_ST_HC_HALTED) != 0) if ((status & GRUB_EHCI_ST_HC_HALTED) != 0)
/* XXX: Fix it: Currently we don't do anything to restart EHCI */ /* XXX: Fix it: Currently we don't do anything to restart EHCI */
{
grub_dprintf ("ehci", "setup_transfer: halted, status = 0x%x\n",
status);
return GRUB_USB_ERR_INTERNAL; return GRUB_USB_ERR_INTERNAL;
if ((grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS) }
status = grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS);
if ((status
& (GRUB_EHCI_ST_AS_STATUS | GRUB_EHCI_ST_PS_STATUS)) == 0) & (GRUB_EHCI_ST_AS_STATUS | GRUB_EHCI_ST_PS_STATUS)) == 0)
/* XXX: Fix it: Currently we don't do anything to restart EHCI */ /* XXX: Fix it: Currently we don't do anything to restart EHCI */
{
grub_dprintf ("ehci", "setup_transfer: no AS/PS, status = 0x%x\n",
status);
return GRUB_USB_ERR_INTERNAL; return GRUB_USB_ERR_INTERNAL;
}
/* Allocate memory for controller transfer data. */ /* Allocate memory for controller transfer data. */
cdata = grub_malloc (sizeof (*cdata)); cdata = grub_malloc (sizeof (*cdata));
@@ -1310,6 +1176,7 @@ grub_ehci_setup_transfer (grub_usb_controller_t dev,
cdata->qh_virt = grub_ehci_find_qh (e, transfer); cdata->qh_virt = grub_ehci_find_qh (e, transfer);
if (!cdata->qh_virt) if (!cdata->qh_virt)
{ {
grub_dprintf ("ehci", "setup_transfer: no QH\n");
grub_free (cdata); grub_free (cdata);
return GRUB_USB_ERR_INTERNAL; return GRUB_USB_ERR_INTERNAL;
} }
@@ -1319,6 +1186,7 @@ grub_ehci_setup_transfer (grub_usb_controller_t dev,
cdata->td_alt_virt = grub_ehci_alloc_td (e); cdata->td_alt_virt = grub_ehci_alloc_td (e);
if (!cdata->td_alt_virt) if (!cdata->td_alt_virt)
{ {
grub_dprintf ("ehci", "setup_transfer: no TDs\n");
grub_free (cdata); grub_free (cdata);
return GRUB_USB_ERR_INTERNAL; return GRUB_USB_ERR_INTERNAL;
} }
@@ -1345,6 +1213,7 @@ grub_ehci_setup_transfer (grub_usb_controller_t dev,
grub_ehci_free_tds (e, cdata->td_first_virt, NULL, &actual); grub_ehci_free_tds (e, cdata->td_first_virt, NULL, &actual);
grub_free (cdata); grub_free (cdata);
grub_dprintf ("ehci", "setup_transfer: no TD\n");
return GRUB_USB_ERR_INTERNAL; return GRUB_USB_ERR_INTERNAL;
} }
@@ -1386,6 +1255,8 @@ grub_ehci_setup_transfer (grub_usb_controller_t dev,
* i.e. reset token */ * i.e. reset token */
cdata->qh_virt->td_overlay.token = grub_cpu_to_le32_compile_time (0); cdata->qh_virt->td_overlay.token = grub_cpu_to_le32_compile_time (0);
sync_all_caches (e);
/* Finito */ /* Finito */
transfer->controller_data = cdata; transfer->controller_data = cdata;
@@ -1434,6 +1305,8 @@ grub_ehci_parse_notrun (grub_usb_controller_t dev,
grub_ehci_free_td (e, cdata->td_alt_virt); grub_ehci_free_td (e, cdata->td_alt_virt);
grub_free (cdata); grub_free (cdata);
sync_all_caches (e);
/* Additionally, do something with EHCI to make it running (what?) */ /* Additionally, do something with EHCI to make it running (what?) */
/* Try enable EHCI and AL */ /* Try enable EHCI and AL */
grub_ehci_oper_write32 (e, GRUB_EHCI_COMMAND, grub_ehci_oper_write32 (e, GRUB_EHCI_COMMAND,
@@ -1469,6 +1342,8 @@ grub_ehci_parse_halt (grub_usb_controller_t dev,
grub_ehci_free_td (e, cdata->td_alt_virt); grub_ehci_free_td (e, cdata->td_alt_virt);
grub_free (cdata); grub_free (cdata);
sync_all_caches (e);
/* Evaluation of error code - currently we don't have GRUB USB error /* Evaluation of error code - currently we don't have GRUB USB error
* codes for some EHCI states, GRUB_USB_ERR_DATA is used for them. * codes for some EHCI states, GRUB_USB_ERR_DATA is used for them.
* Order of evaluation is critical, specially bubble/stall. */ * Order of evaluation is critical, specially bubble/stall. */
@@ -1502,6 +1377,8 @@ grub_ehci_parse_success (grub_usb_controller_t dev,
grub_ehci_free_td (e, cdata->td_alt_virt); grub_ehci_free_td (e, cdata->td_alt_virt);
grub_free (cdata); grub_free (cdata);
sync_all_caches (e);
return GRUB_USB_ERR_NONE; return GRUB_USB_ERR_NONE;
} }
@@ -1515,6 +1392,8 @@ grub_ehci_check_transfer (grub_usb_controller_t dev,
transfer->controller_data; transfer->controller_data;
grub_uint32_t token, token_ftd; grub_uint32_t token, token_ftd;
sync_all_caches (e);
grub_dprintf ("ehci", grub_dprintf ("ehci",
"check_transfer: EHCI STATUS=%08x, cdata=%p, qh=%p\n", "check_transfer: EHCI STATUS=%08x, cdata=%p, qh=%p\n",
grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS), grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS),
@@ -1581,6 +1460,9 @@ grub_ehci_cancel_transfer (grub_usb_controller_t dev,
int i; int i;
grub_uint64_t maxtime; grub_uint64_t maxtime;
grub_uint32_t qh_phys; grub_uint32_t qh_phys;
sync_all_caches (e);
grub_uint32_t interrupt = grub_uint32_t interrupt =
cdata->qh_virt->ep_cap & GRUB_EHCI_SMASK_MASK; cdata->qh_virt->ep_cap & GRUB_EHCI_SMASK_MASK;
@@ -1600,6 +1482,7 @@ grub_ehci_cancel_transfer (grub_usb_controller_t dev,
grub_ehci_free_tds (e, cdata->td_first_virt, transfer, &actual); grub_ehci_free_tds (e, cdata->td_first_virt, transfer, &actual);
grub_ehci_free_td (e, cdata->td_alt_virt); grub_ehci_free_td (e, cdata->td_alt_virt);
grub_free (cdata); grub_free (cdata);
sync_all_caches (e);
grub_dprintf ("ehci", "cancel_transfer: end - EHCI not running\n"); grub_dprintf ("ehci", "cancel_transfer: end - EHCI not running\n");
return GRUB_USB_ERR_NONE; return GRUB_USB_ERR_NONE;
} }
@@ -1622,6 +1505,8 @@ grub_ehci_cancel_transfer (grub_usb_controller_t dev,
/* Unlink QH from AL */ /* Unlink QH from AL */
e->qh_virt[i].qh_hptr = cdata->qh_virt->qh_hptr; e->qh_virt[i].qh_hptr = cdata->qh_virt->qh_hptr;
sync_all_caches (e);
/* If this is an interrupt transfer, we just wait for the periodic /* If this is an interrupt transfer, we just wait for the periodic
* schedule to advance a few times and then assume that the EHCI * schedule to advance a few times and then assume that the EHCI
* controller has read the updated QH. */ * controller has read the updated QH. */
@@ -1676,6 +1561,8 @@ grub_ehci_cancel_transfer (grub_usb_controller_t dev,
grub_dprintf ("ehci", "cancel_transfer: end\n"); grub_dprintf ("ehci", "cancel_transfer: end\n");
sync_all_caches (e);
return GRUB_USB_ERR_NONE; return GRUB_USB_ERR_NONE;
} }
@@ -1692,8 +1579,8 @@ grub_ehci_hubports (grub_usb_controller_t dev)
} }
static grub_usb_err_t static grub_usb_err_t
grub_ehci_portstatus (grub_usb_controller_t dev, grub_ehci_reset_port (grub_usb_controller_t dev,
unsigned int port, unsigned int enable) unsigned int port)
{ {
struct grub_ehci *e = (struct grub_ehci *) dev->data; struct grub_ehci *e = (struct grub_ehci *) dev->data;
grub_uint64_t endtime; grub_uint64_t endtime;
@@ -1715,14 +1602,6 @@ grub_ehci_portstatus (grub_usb_controller_t dev,
if (grub_get_time_ms () > endtime) if (grub_get_time_ms () > endtime)
return GRUB_USB_ERR_TIMEOUT; return GRUB_USB_ERR_TIMEOUT;
if (!enable) /* We don't need reset port */
{
grub_dprintf ("ehci", "portstatus: Disabled.\n");
grub_dprintf ("ehci", "portstatus: end, status=0x%02x\n",
grub_ehci_port_read (e, port));
return GRUB_USB_ERR_NONE;
}
grub_dprintf ("ehci", "portstatus: enable\n"); grub_dprintf ("ehci", "portstatus: enable\n");
grub_boot_time ("Resetting port %d", port); grub_boot_time ("Resetting port %d", port);
@@ -1777,11 +1656,6 @@ grub_ehci_detect_dev (grub_usb_controller_t dev, int port, int *changed)
status = grub_ehci_port_read (e, port); status = grub_ehci_port_read (e, port);
grub_dprintf ("ehci", "detect_dev: EHCI STATUS: %08x\n",
grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS));
grub_dprintf ("ehci", "detect_dev: iobase=%p, port=%d, status=0x%02x\n",
e->iobase, port, status);
/* Connect Status Change bit - it detects change of connection */ /* Connect Status Change bit - it detects change of connection */
if (status & GRUB_EHCI_PORT_CONNECT_CH) if (status & GRUB_EHCI_PORT_CONNECT_CH)
{ {
@@ -1842,12 +1716,6 @@ grub_ehci_detect_dev (grub_usb_controller_t dev, int port, int *changed)
} }
} }
static void
grub_ehci_inithw (void)
{
grub_pci_iterate (grub_ehci_pci_iter, NULL);
}
static grub_err_t static grub_err_t
grub_ehci_restore_hw (void) grub_ehci_restore_hw (void)
{ {
@@ -1934,7 +1802,7 @@ static struct grub_usb_controller_dev usb_controller = {
.check_transfer = grub_ehci_check_transfer, .check_transfer = grub_ehci_check_transfer,
.cancel_transfer = grub_ehci_cancel_transfer, .cancel_transfer = grub_ehci_cancel_transfer,
.hubports = grub_ehci_hubports, .hubports = grub_ehci_hubports,
.portstatus = grub_ehci_portstatus, .reset_port = grub_ehci_reset_port,
.detect_dev = grub_ehci_detect_dev, .detect_dev = grub_ehci_detect_dev,
/* estimated max. count of TDs for one bulk transfer */ /* estimated max. count of TDs for one bulk transfer */
.max_bulk_tds = GRUB_EHCI_N_TD * 3 / 4 .max_bulk_tds = GRUB_EHCI_N_TD * 3 / 4
@@ -1948,7 +1816,7 @@ GRUB_MOD_INIT (ehci)
grub_stop_disk_firmware (); grub_stop_disk_firmware ();
grub_boot_time ("Initing EHCI hardware"); grub_boot_time ("Initing EHCI hardware");
grub_ehci_inithw (); grub_ehci_pci_scan ();
grub_boot_time ("Registering EHCI driver"); grub_boot_time ("Registering EHCI driver");
grub_usb_controller_dev_register (&usb_controller); grub_usb_controller_dev_register (&usb_controller);
grub_boot_time ("EHCI driver registered"); grub_boot_time ("EHCI driver registered");
+3 -19
View File
@@ -1224,8 +1224,8 @@ grub_ohci_cancel_transfer (grub_usb_controller_t dev,
} }
static grub_usb_err_t static grub_usb_err_t
grub_ohci_portstatus (grub_usb_controller_t dev, grub_ohci_rest_port (grub_usb_controller_t dev,
unsigned int port, unsigned int enable) unsigned int port)
{ {
struct grub_ohci *o = (struct grub_ohci *) dev->data; struct grub_ohci *o = (struct grub_ohci *) dev->data;
grub_uint64_t endtime; grub_uint64_t endtime;
@@ -1234,22 +1234,6 @@ grub_ohci_portstatus (grub_usb_controller_t dev,
grub_dprintf ("ohci", "begin of portstatus=0x%02x\n", grub_dprintf ("ohci", "begin of portstatus=0x%02x\n",
grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBPORT + port)); grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBPORT + port));
if (!enable) /* We don't need reset port */
{
/* Disable the port and wait for it. */
grub_ohci_writereg32 (o, GRUB_OHCI_REG_RHUBPORT + port,
GRUB_OHCI_CLEAR_PORT_ENABLE);
endtime = grub_get_time_ms () + 1000;
while ((grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBPORT + port)
& (1 << 1)))
if (grub_get_time_ms () > endtime)
return GRUB_USB_ERR_TIMEOUT;
grub_dprintf ("ohci", "end of portstatus=0x%02x\n",
grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBPORT + port));
return GRUB_USB_ERR_NONE;
}
/* OHCI does one reset signal 10ms long but USB spec. /* OHCI does one reset signal 10ms long but USB spec.
* requests 50ms for root hub (no need to be continuous). * requests 50ms for root hub (no need to be continuous).
* So, we do reset 5 times... */ * So, we do reset 5 times... */
@@ -1438,7 +1422,7 @@ static struct grub_usb_controller_dev usb_controller =
.check_transfer = grub_ohci_check_transfer, .check_transfer = grub_ohci_check_transfer,
.cancel_transfer = grub_ohci_cancel_transfer, .cancel_transfer = grub_ohci_cancel_transfer,
.hubports = grub_ohci_hubports, .hubports = grub_ohci_hubports,
.portstatus = grub_ohci_portstatus, .reset_port = grub_ohci_reset_port,
.detect_dev = grub_ohci_detect_dev, .detect_dev = grub_ohci_detect_dev,
/* estimated max. count of TDs for one bulk transfer */ /* estimated max. count of TDs for one bulk transfer */
.max_bulk_tds = GRUB_OHCI_TDS * 3 / 4 .max_bulk_tds = GRUB_OHCI_TDS * 3 / 4
+3 -18
View File
@@ -710,8 +710,8 @@ grub_uhci_iterate (grub_usb_controller_iterate_hook_t hook, void *hook_data)
} }
static grub_usb_err_t static grub_usb_err_t
grub_uhci_portstatus (grub_usb_controller_t dev, grub_uhci_reset_port (grub_usb_controller_t dev,
unsigned int port, unsigned int enable) unsigned int port)
{ {
struct grub_uhci *u = (struct grub_uhci *) dev->data; struct grub_uhci *u = (struct grub_uhci *) dev->data;
int reg; int reg;
@@ -732,21 +732,6 @@ grub_uhci_portstatus (grub_usb_controller_t dev,
status = grub_uhci_readreg16 (u, reg); status = grub_uhci_readreg16 (u, reg);
grub_dprintf ("uhci", "detect=0x%02x\n", status); grub_dprintf ("uhci", "detect=0x%02x\n", status);
if (!enable) /* We don't need reset port */
{
/* Disable the port. */
grub_uhci_writereg16 (u, reg, 0 << 2);
grub_dprintf ("uhci", "waiting for the port to be disabled\n");
endtime = grub_get_time_ms () + 1000;
while ((grub_uhci_readreg16 (u, reg) & (1 << 2)))
if (grub_get_time_ms () > endtime)
return GRUB_USB_ERR_TIMEOUT;
status = grub_uhci_readreg16 (u, reg);
grub_dprintf ("uhci", ">3detect=0x%02x\n", status);
return GRUB_USB_ERR_NONE;
}
/* Reset the port. */ /* Reset the port. */
status = grub_uhci_readreg16 (u, reg) & ~GRUB_UHCI_PORTSC_RWC; status = grub_uhci_readreg16 (u, reg) & ~GRUB_UHCI_PORTSC_RWC;
grub_uhci_writereg16 (u, reg, status | (1 << 9)); grub_uhci_writereg16 (u, reg, status | (1 << 9));
@@ -843,7 +828,7 @@ static struct grub_usb_controller_dev usb_controller =
.check_transfer = grub_uhci_check_transfer, .check_transfer = grub_uhci_check_transfer,
.cancel_transfer = grub_uhci_cancel_transfer, .cancel_transfer = grub_uhci_cancel_transfer,
.hubports = grub_uhci_hubports, .hubports = grub_uhci_hubports,
.portstatus = grub_uhci_portstatus, .reset_port = grub_uhci_reset_port,
.detect_dev = grub_uhci_detect_dev, .detect_dev = grub_uhci_detect_dev,
/* estimated max. count of TDs for one bulk transfer */ /* estimated max. count of TDs for one bulk transfer */
.max_bulk_tds = N_TD * 3 / 4 .max_bulk_tds = N_TD * 3 / 4
+2 -2
View File
@@ -207,8 +207,8 @@ attach_root_port (struct grub_usb_hub *hub, int portno,
grub_boot_time ("After detect_dev"); grub_boot_time ("After detect_dev");
/* Enable the port. */ /* Reset port. */
err = hub->controller->dev->portstatus (hub->controller, portno, 1); err = hub->controller->dev->reset_port (hub->controller, portno);
if (err) if (err)
return; return;
hub->controller->dev->pending_reset = grub_get_time_ms () + 5000; hub->controller->dev->pending_reset = grub_get_time_ms () + 5000;
+16 -2
View File
@@ -18,12 +18,13 @@
*/ */
#include <grub/dl.h> #include <grub/dl.h>
#include <grub/pci.h> #include <grub/dma.h>
#include <grub/mm.h> #include <grub/mm.h>
#include <grub/misc.h> #include <grub/misc.h>
#include <grub/usb.h> #include <grub/usb.h>
#include <grub/usbtrans.h> #include <grub/usbtrans.h>
#include <grub/time.h> #include <grub/time.h>
#include <grub/cache.h>
static inline unsigned int static inline unsigned int
@@ -101,6 +102,8 @@ grub_usb_control_msg (grub_usb_device_t dev,
data_addr = grub_dma_get_phys (data_chunk); data_addr = grub_dma_get_phys (data_chunk);
grub_memcpy ((char *) data, data_in, size); grub_memcpy ((char *) data, data_in, size);
grub_arch_sync_dma_caches (data, size);
grub_dprintf ("usb", grub_dprintf ("usb",
"control: reqtype=0x%02x req=0x%02x val=0x%02x idx=0x%02x size=%lu\n", "control: reqtype=0x%02x req=0x%02x val=0x%02x idx=0x%02x size=%lu\n",
reqtype, request, value, index, (unsigned long)size); reqtype, request, value, index, (unsigned long)size);
@@ -161,6 +164,8 @@ grub_usb_control_msg (grub_usb_device_t dev,
setupdata->value = value; setupdata->value = value;
setupdata->index = index; setupdata->index = index;
setupdata->length = size; setupdata->length = size;
grub_arch_sync_dma_caches (setupdata, sizeof (*setupdata));
transfer->transactions[0].size = sizeof (*setupdata); transfer->transactions[0].size = sizeof (*setupdata);
transfer->transactions[0].pid = GRUB_USB_TRANSFER_TYPE_SETUP; transfer->transactions[0].pid = GRUB_USB_TRANSFER_TYPE_SETUP;
transfer->transactions[0].data = setupdata_addr; transfer->transactions[0].data = setupdata_addr;
@@ -202,11 +207,13 @@ grub_usb_control_msg (grub_usb_device_t dev,
grub_free (transfer->transactions); grub_free (transfer->transactions);
grub_free (transfer); grub_free (transfer);
grub_dma_free (data_chunk);
grub_dma_free (setupdata_chunk); grub_dma_free (setupdata_chunk);
grub_arch_sync_dma_caches (data, size0);
grub_memcpy (data_in, (char *) data, size0); grub_memcpy (data_in, (char *) data, size0);
grub_dma_free (data_chunk);
return err; return err;
} }
@@ -236,7 +243,10 @@ grub_usb_bulk_setup_readwrite (grub_usb_device_t dev,
data = grub_dma_get_virt (data_chunk); data = grub_dma_get_virt (data_chunk);
data_addr = grub_dma_get_phys (data_chunk); data_addr = grub_dma_get_phys (data_chunk);
if (type == GRUB_USB_TRANSFER_TYPE_OUT) if (type == GRUB_USB_TRANSFER_TYPE_OUT)
{
grub_memcpy ((char *) data, data_in, size); grub_memcpy ((char *) data, data_in, size);
grub_arch_sync_dma_caches (data, size);
}
/* Create a transfer. */ /* Create a transfer. */
transfer = grub_malloc (sizeof (struct grub_usb_transfer)); transfer = grub_malloc (sizeof (struct grub_usb_transfer));
@@ -306,9 +316,13 @@ grub_usb_bulk_finish_readwrite (grub_usb_transfer_t transfer)
dev->toggle[transfer->endpoint] = toggle; dev->toggle[transfer->endpoint] = toggle;
if (transfer->dir == GRUB_USB_TRANSFER_TYPE_IN) if (transfer->dir == GRUB_USB_TRANSFER_TYPE_IN)
{
grub_arch_sync_dma_caches (grub_dma_get_virt (transfer->data_chunk),
transfer->size + 1);
grub_memcpy (transfer->data, (void *) grub_memcpy (transfer->data, (void *)
grub_dma_get_virt (transfer->data_chunk), grub_dma_get_virt (transfer->data_chunk),
transfer->size + 1); transfer->size + 1);
}
grub_free (transfer->transactions); grub_free (transfer->transactions);
grub_dma_free (transfer->data_chunk); grub_dma_free (transfer->data_chunk);
@@ -20,7 +20,7 @@
#include <grub/misc.h> #include <grub/misc.h>
#include <grub/command.h> #include <grub/command.h>
#include <grub/i18n.h> #include <grub/i18n.h>
#include <grub/i386/coreboot/lbio.h> #include <grub/coreboot/lbio.h>
#include <grub/i386/tsc.h> #include <grub/i386/tsc.h>
GRUB_MOD_LICENSE ("GPLv3+"); GRUB_MOD_LICENSE ("GPLv3+");
+1 -1
View File
@@ -20,7 +20,7 @@
#include <grub/misc.h> #include <grub/misc.h>
#include <grub/command.h> #include <grub/command.h>
#include <grub/i18n.h> #include <grub/i18n.h>
#include <grub/i386/coreboot/lbio.h> #include <grub/coreboot/lbio.h>
#include <grub/i386/tsc.h> #include <grub/i386/tsc.h>
GRUB_MOD_LICENSE ("GPLv3+"); GRUB_MOD_LICENSE ("GPLv3+");
+34
View File
@@ -29,6 +29,8 @@ void grub_arm_clean_dcache_range_armv6 (grub_addr_t start, grub_addr_t end,
grub_addr_t dlinesz); grub_addr_t dlinesz);
void grub_arm_clean_dcache_range_armv7 (grub_addr_t start, grub_addr_t end, void grub_arm_clean_dcache_range_armv7 (grub_addr_t start, grub_addr_t end,
grub_addr_t dlinesz); grub_addr_t dlinesz);
void grub_arm_clean_dcache_range_poc_armv7 (grub_addr_t start, grub_addr_t end,
grub_addr_t dlinesz);
void grub_arm_invalidate_icache_range_armv6 (grub_addr_t start, grub_addr_t end, void grub_arm_invalidate_icache_range_armv6 (grub_addr_t start, grub_addr_t end,
grub_addr_t dlinesz); grub_addr_t dlinesz);
void grub_arm_invalidate_icache_range_armv7 (grub_addr_t start, grub_addr_t end, void grub_arm_invalidate_icache_range_armv7 (grub_addr_t start, grub_addr_t end,
@@ -252,6 +254,38 @@ grub_arch_sync_caches (void *address, grub_size_t len)
} }
} }
void
grub_arch_sync_dma_caches (volatile void *address, grub_size_t len)
{
grub_addr_t start = (grub_addr_t) address;
grub_addr_t end = start + len;
if (type == ARCH_UNKNOWN)
probe_caches ();
start = ALIGN_DOWN (start, grub_arch_cache_max_linesz);
end = ALIGN_UP (end, grub_arch_cache_max_linesz);
switch (type)
{
case ARCH_ARMV6:
grub_arm_clean_dcache_range_armv6 (start, end, grub_arch_cache_dlinesz);
grub_arm_invalidate_icache_range_armv6 (start, end,
grub_arch_cache_ilinesz);
break;
case ARCH_ARMV5_WRITE_THROUGH:
case ARCH_ARMV6_UNIFIED:
grub_arm_clean_dcache_range_armv6 (start, end, grub_arch_cache_dlinesz);
break;
case ARCH_ARMV7:
grub_arm_clean_dcache_range_poc_armv7 (start, end, grub_arch_cache_dlinesz);
grub_arm_invalidate_icache_range_armv7 (start, end,
grub_arch_cache_ilinesz);
break;
/* Pacify GCC. */
case ARCH_UNKNOWN:
break;
}
}
void void
grub_arm_disable_caches_mmu (void) grub_arm_disable_caches_mmu (void)
{ {
+12
View File
@@ -33,6 +33,18 @@
# define ISB isb # define ISB isb
#define ARMV7 1 #define ARMV7 1
FUNCTION(grub_arm_clean_dcache_range_poc_armv7)
DSB
@ Clean data cache for range to point-of-coherence
1: cmp r0, r1
bge 2f
mcr p15, 0, r0, c7, c14, 1 @ DCCMVAC
add r0, r0, r2 @ Next line
b 1b
2: DSB
bx lr
@ r0 - CLIDR @ r0 - CLIDR
@ r1 - LoC @ r1 - LoC
@ r2 - current level @ r2 - current level
+74
View File
@@ -0,0 +1,74 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2007,2008,2013 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* 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/coreboot/lbio.h>
#include <grub/types.h>
#include <grub/err.h>
#include <grub/misc.h>
#include <grub/dl.h>
#include <grub/arm/startup.h>
GRUB_MOD_LICENSE ("GPLv3+");
#pragma GCC diagnostic ignored "-Wcast-align"
/* Helper for grub_linuxbios_table_iterate. */
static int
check_signature (grub_linuxbios_table_header_t tbl_header)
{
if (! grub_memcmp (tbl_header->signature, "LBIO", 4))
return 1;
return 0;
}
grub_err_t
grub_linuxbios_table_iterate (int (*hook) (grub_linuxbios_table_item_t,
void *),
void *hook_data)
{
grub_linuxbios_table_header_t table_header
= (grub_linuxbios_table_header_t) grub_arm_saved_registers.r[0];
grub_linuxbios_table_item_t table_item;
if (!check_signature (table_header))
return 0;
signature_found:
table_item =
(grub_linuxbios_table_item_t) ((char *) table_header +
table_header->header_size);
for (; table_item < (grub_linuxbios_table_item_t) ((char *) table_header
+ table_header->header_size
+ table_header->table_size);
table_item = (grub_linuxbios_table_item_t) ((char *) table_item + table_item->size))
{
if (table_item->tag == GRUB_LINUXBIOS_MEMBER_LINK
&& check_signature ((grub_linuxbios_table_header_t) (grub_addr_t)
*(grub_uint64_t *) (table_item + 1)))
{
table_header = (grub_linuxbios_table_header_t) (grub_addr_t)
*(grub_uint64_t *) (table_item + 1);
goto signature_found;
}
if (hook (table_item, hook_data))
return 1;
}
return 0;
}
+44
View File
@@ -0,0 +1,44 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2016 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* 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/symbol.h>
.file "coreboot.S"
.text
.syntax unified
#if !defined (__thumb2__)
.arch armv7a
.arm
#else
.arch armv7
.thumb
#endif
FUNCTION(grub_arm_pfr1)
mrc p15, 0, r0, c0, c1, 1
bx lr
FUNCTION(grub_armv7_get_timer_value)
isb
mrrc p15, 1, r0, r1, c14
bx lr
FUNCTION(grub_armv7_get_timer_frequency)
mrc p15, 0, r0, c14, c0, 0
bx lr
+59
View File
@@ -0,0 +1,59 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2007,2009 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* 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/dl.h>
#include <grub/dma.h>
#include <grub/mm.h>
#include <grub/misc.h>
#include <grub/mm_private.h>
#include <grub/cache.h>
struct grub_pci_dma_chunk *
grub_memalign_dma32 (grub_size_t align, grub_size_t size)
{
void *ret;
if (align < 64)
align = 64;
size = ALIGN_UP (size, align);
ret = grub_memalign (align, size);
if (!ret)
return 0;
grub_arch_sync_dma_caches (ret, size);
return ret;
}
void
grub_dma_free (struct grub_pci_dma_chunk *ch)
{
grub_size_t size = (((struct grub_mm_header *) ch) - 1)->size * GRUB_MM_ALIGN;
grub_arch_sync_dma_caches (ch, size);
grub_free (ch);
}
volatile void *
grub_dma_get_virt (struct grub_pci_dma_chunk *ch)
{
return (void *) ch;
}
grub_uint32_t
grub_dma_get_phys (struct grub_pci_dma_chunk *ch)
{
return (grub_uint32_t) (grub_addr_t) ch;
}
+169
View File
@@ -0,0 +1,169 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2009,2013 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* 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/kernel.h>
#include <grub/mm.h>
#include <grub/memory.h>
#include <grub/machine/console.h>
#include <grub/machine/kernel.h>
#include <grub/offsets.h>
#include <grub/types.h>
#include <grub/err.h>
#include <grub/dl.h>
#include <grub/misc.h>
#include <grub/loader.h>
#include <grub/env.h>
#include <grub/cache.h>
#include <grub/time.h>
#include <grub/symbol.h>
#include <grub/video.h>
#include <grub/coreboot/lbio.h>
#include <grub/fdtbus.h>
extern grub_uint8_t _start[];
extern grub_uint8_t _end[];
extern grub_uint8_t _edata[];
grub_addr_t start_of_ram = ~(grub_addr_t)0;
void __attribute__ ((noreturn))
grub_exit (void)
{
/* We can't use grub_fatal() in this function. This would create an infinite
loop, since grub_fatal() calls grub_abort() which in turn calls grub_exit(). */
while (1)
grub_cpu_idle ();
}
static grub_uint64_t modend;
static int have_memory = 0;
/* Helper for grub_machine_init. */
static int
heap_init (grub_uint64_t addr, grub_uint64_t size, grub_memory_type_t type,
void *data __attribute__ ((unused)))
{
grub_uint64_t begin = addr, end = addr + size;
#if GRUB_CPU_SIZEOF_VOID_P == 4
/* Restrict ourselves to 32-bit memory space. */
if (begin > GRUB_ULONG_MAX)
return 0;
if (end > GRUB_ULONG_MAX)
end = GRUB_ULONG_MAX;
#endif
if (start_of_ram > begin)
start_of_ram = begin;
if (type != GRUB_MEMORY_AVAILABLE)
return 0;
if (modend && begin < modend)
{
if (begin < (grub_addr_t)_start)
{
grub_mm_init_region ((void *) (grub_addr_t) begin, (grub_size_t) ((grub_addr_t)_start - begin));
have_memory = 1;
}
begin = modend;
}
/* Avoid DMA problems. */
if (end >= 0xfe000000)
end = 0xfe000000;
if (end <= begin)
return 0;
grub_mm_init_region ((void *) (grub_addr_t) begin, (grub_size_t) (end - begin));
have_memory = 1;
return 0;
}
static const void *dtb;
static grub_size_t dtb_size;
static int
iterate_linuxbios_table (grub_linuxbios_table_item_t table_item, void *data __attribute__ ((unused)))
{
if (table_item->tag != GRUB_LINUXBIOS_MEMBER_DTB)
return 0;
if (grub_fdt_check_header (table_item + 1, table_item->size) >= 0)
{
dtb = table_item + 1;
dtb_size = table_item->size;
}
else
grub_printf ("Invalid DTB supplied by coreboot\n");
return 0;
}
void
grub_machine_init (void)
{
struct grub_module_header *header;
modend = grub_modules_get_end ();
grub_video_coreboot_fb_early_init ();
grub_machine_mmap_iterate (heap_init, NULL);
if (!have_memory)
grub_fatal ("No memory found");
grub_video_coreboot_fb_late_init ();
grub_font_init ();
grub_gfxterm_init ();
FOR_MODULES (header)
if (header->type == OBJ_TYPE_DTB)
{
char *dtb_orig_addr, *dtb_copy;
dtb_orig_addr = (char *) header + sizeof (struct grub_module_header);
dtb_size = header->size - sizeof (struct grub_module_header);
dtb = dtb_copy = grub_malloc (dtb_size);
grub_memmove (dtb_copy, dtb_orig_addr, dtb_size);
break;
}
if (!dtb)
grub_linuxbios_table_iterate (iterate_linuxbios_table, 0);
if (!dtb)
grub_fatal ("No DTB found");
grub_fdtbus_init (dtb, dtb_size);
grub_machine_timer_init ();
grub_cros_init ();
grub_pl050_init ();
}
void
grub_machine_get_bootlocation (char **device __attribute__ ((unused)),
char **path __attribute__ ((unused)))
{
}
void
grub_machine_fini (int flags __attribute__ ((unused)))
{
}
+101
View File
@@ -0,0 +1,101 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2016 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* 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/mm.h>
#include <grub/machine/kernel.h>
#include <grub/types.h>
#include <grub/err.h>
#include <grub/time.h>
#include <grub/fdtbus.h>
#include <grub/misc.h>
grub_uint64_t
grub_armv7_get_timer_value(void);
grub_uint32_t
grub_armv7_get_timer_frequency(void);
grub_uint32_t
grub_arm_pfr1(void);
static int have_timer = 0;
static volatile grub_uint32_t *sp804_regs;
static grub_uint64_t
sp804_get_time_ms (void)
{
static grub_uint32_t high, last_low;
grub_uint32_t low = ~sp804_regs[1];
if (last_low > low)
high++;
last_low = low;
return grub_divmod64 ((((grub_uint64_t) high) << 32) | low,
1000, 0);
}
static grub_err_t
sp804_attach(const struct grub_fdtbus_dev *dev)
{
if (have_timer)
return GRUB_ERR_NONE;
sp804_regs = grub_fdtbus_map_reg (dev, 0, 0);
if (!grub_fdtbus_is_mapping_valid (sp804_regs))
return grub_error (GRUB_ERR_IO, "could not map sp804: %p", sp804_regs);
grub_install_get_time_ms (sp804_get_time_ms);
have_timer = 1;
return GRUB_ERR_NONE;
}
struct grub_fdtbus_driver sp804 =
{
.compatible = "arm,sp804",
.attach = sp804_attach
};
static grub_uint32_t timer_frequency_in_khz;
static grub_uint64_t
generic_get_time_ms (void)
{
return grub_divmod64 (grub_armv7_get_timer_value(), timer_frequency_in_khz, 0);
}
static int
try_generic_timer (void)
{
if (((grub_arm_pfr1 () >> 16) & 0xf) != 1)
return 0;
grub_printf ("freq = %x\n", grub_armv7_get_timer_frequency());
timer_frequency_in_khz = 0x016e3600 / 1000; //grub_armv7_get_timer_frequency() / 1000;
if (timer_frequency_in_khz == 0)
return 0;
grub_install_get_time_ms (generic_get_time_ms);
have_timer = 1;
return 1;
}
void
grub_machine_timer_init (void)
{
grub_fdtbus_register (&sp804);
if (!have_timer)
try_generic_timer ();
if (!have_timer)
grub_fatal ("No timer found");
}
@@ -24,6 +24,7 @@
* GRUB is called from U-Boot as a Linux Kernel type image, which * GRUB is called from U-Boot as a Linux Kernel type image, which
* means among other things that it always enters in ARM state. * means among other things that it always enters in ARM state.
* *
* coreboot starts in ARM mode as well.
* *
* Overview of GRUB image layout: * Overview of GRUB image layout:
* *
@@ -55,10 +56,6 @@ FUNCTION(_start)
VARIABLE(grub_total_module_size) VARIABLE(grub_total_module_size)
.long 0 .long 0
VARIABLE(grub_uboot_machine_type)
.long 0
VARIABLE(grub_uboot_boot_data)
.long 0
VARIABLE(grub_modbase) VARIABLE(grub_modbase)
.long 0 .long 0
bss_start_ptr: bss_start_ptr:
@@ -66,34 +63,73 @@ bss_start_ptr:
end_ptr: end_ptr:
.long EXT_C(_end) .long EXT_C(_end)
@ Memory map at start:
@ * text+data
@ * list relocations
@ * modules
@ Before we enter C, we need to apply the relocations
@ and get following map:
@ * text+data
@ * BSS (cleared)
@ * stack
@ * modules
@
@ To make things easier we ensure
@ that BSS+stack is larger than list of relocations
@ by increasing stack if necessarry.
@ This allows us to always unconditionally copy backwards
@ Currently list of relocations is ~5K and stack is set
@ to be at least 256K
FUNCTION(codestart) FUNCTION(codestart)
@ Store context: Machine ID, atags/dtb, ... @ Store context: Machine ID, atags/dtb, ...
@ U-Boot API signature is stored on the U-Boot heap @ U-Boot API signature is stored on the U-Boot heap
@ Stack pointer used as start address for signature probing @ Stack pointer used as start address for signature probing
mov r12, sp mov r12, sp
adr sp, entry_state adr sp, entry_state
push {r4-r12,lr} @ store U-Boot context (sp in r12) push {r0-r12,lr} @ store U-Boot context (sp in r12)
str r1, EXT_C(grub_uboot_machine_type) adr r1, _start
str r2, EXT_C(grub_uboot_boot_data)
@ Modules have been stored as a blob in BSS,
@ they need to be manually relocated to _end
ldr r0, bss_start_ptr @ src ldr r0, bss_start_ptr @ src
add r0, r0, r1
add r0, r0, #(GRUB_KERNEL_MACHINE_MOD_ALIGN - 1)
mvn r2, #(GRUB_KERNEL_MACHINE_MOD_ALIGN - 1)
and r0, r0, r2
1:
ldr r3, [r0], #4 @load next offset
@ both -2 and -1 are treated the same as we have only one type of relocs
@ -2 means "end of this type of relocs" and -1 means "end of all relocs"
add r2, r3, #2
cmp r2, #1
bls reloc_done
@ Adjust next offset
ldr r2, [r3, r1]
add r2, r2, r1
str r2, [r3, r1]
b 1b
reloc_done:
@ Modules have been stored as a blob
@ they need to be manually relocated to _end
add r0, r0, #(GRUB_KERNEL_MACHINE_MOD_ALIGN - 1) add r0, r0, #(GRUB_KERNEL_MACHINE_MOD_ALIGN - 1)
mvn r1, #(GRUB_KERNEL_MACHINE_MOD_ALIGN - 1) mvn r1, #(GRUB_KERNEL_MACHINE_MOD_ALIGN - 1)
and r0, r0, r1 and r0, r0, r1 @ src = aligned end of relocations
ldr r1, end_ptr @ dst = End of BSS ldr r1, end_ptr @ dst = End of BSS
ldr r2, grub_total_module_size @ blob size ldr r2, grub_total_module_size @ blob size
add r1, r1, #GRUB_KERNEL_MACHINE_STACK_SIZE add r1, r1, #GRUB_KERNEL_MACHINE_STACK_SIZE
and r1, r1, #~0x7 @ Ensure 8-byte alignment and r1, r1, #~0x7 @ Ensure 8-byte alignment
sub sp, r1, #8 sub sp, r1, #8
add r1, r1, #1024 add r1, r1, #1024
str r1, EXT_C(grub_modbase) str r1, EXT_C(grub_modbase)
/* Coreboot already places modules at right place. */
#ifndef GRUB_MACHINE_COREBOOT
add r1, r1, r2 add r1, r1, r2
add r0, r0, r2 add r0, r0, r2
sub r1, r1, #4 sub r1, r1, #4
@@ -103,6 +139,7 @@ FUNCTION(codestart)
str r3, [r1], #-4 @ *dst-- = r3 str r3, [r1], #-4 @ *dst-- = r3
subs r2, #4 @ remaining -= 4 subs r2, #4 @ remaining -= 4
bne 1b @ while remaining != 0 bne 1b @ while remaining != 0
#endif
@ Since we _are_ the C run-time, we need to manually zero the BSS @ Since we _are_ the C run-time, we need to manually zero the BSS
@ region before continuing @ region before continuing
@@ -120,64 +157,21 @@ FUNCTION(codestart)
b EXT_C(grub_main) b EXT_C(grub_main)
/*
* uboot_syscall():
* This function is effectively a veneer, so it cannot
* modify the stack or corrupt any registers other than
* r12 (ip). Furthermore it needs to restore r8 for
* U-Boot (Global Data Pointer) and preserve it for Grub.
*/
FUNCTION(grub_uboot_syscall)
str r8, transition_space
str lr, transition_space + 4
str r9, transition_space + 8
ldr r8, gd_backup
ldr r9, gd_backup + 4
bl do_syscall
ldr r8, transition_space
ldr lr, transition_space + 4
ldr r9, transition_space + 8
bx lr
do_syscall:
ldr ip, grub_uboot_syscall_ptr
bx ip
FUNCTION(grub_uboot_return)
adr sp, entry_state_end
pop {r4-r12, lr}
mov sp, r12
bx lr
.align 3 .align 3
@ U-boot context stack space @ U-boot/coreboot context stack space
entry_state_end: VARIABLE(grub_arm_saved_registers)
.long 0 @ r0
.long 0 @ r1
.long 0 @ r2
.long 0 @ r3
.long 0 @ r4 .long 0 @ r4
.long 0 @ r5 .long 0 @ r5
.long 0 @ r6 .long 0 @ r6
.long 0 @ r7 .long 0 @ r7
gd_backup: .long 0 @ r8
.long 0 @ r8 - U-Boot global data pointer up to 2013-09-21 .long 0 @ r9
.long 0 @ r9 - U-Boot global data pointer 2013-09-21 onwards
.long 0 @ r10 .long 0 @ r10
.long 0 @ r11 .long 0 @ r11
VARIABLE(grub_uboot_search_hint)@ U-Boot stack pointer - .long 0 @ sp
.long 0 @ also API signature address hint.
.long 0 @ lr .long 0 @ lr
entry_state: @ backup for U-Boot context entry_state:
@ GRUB context stack space
transition_space:
.long 0 @ r8
.long 0 @ lr
.long 0 @ r9
VARIABLE(grub_uboot_syscall_ptr)
.long 0 @
END
+70
View File
@@ -0,0 +1,70 @@
/* init.c - generic U-Boot initialization and finalization */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2016 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* 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/uboot/uboot.h>
#include <grub/arm/startup.h>
#include <grub/uboot/api_public.h>
extern int (*grub_uboot_syscall_ptr) (int, int *, ...);
grub_uint32_t
grub_uboot_get_machine_type (void)
{
return grub_arm_saved_registers.r[1];
}
const void *
grub_uboot_get_boot_data (void)
{
return (const void *) grub_arm_saved_registers.r[2];
}
int
grub_uboot_api_init (void)
{
struct api_signature *start, *end;
struct api_signature *p;
grub_addr_t grub_uboot_search_hint = grub_arm_saved_registers.sp;
if (grub_uboot_search_hint)
{
/* Extended search range to work around Trim Slice U-Boot issue */
start = (struct api_signature *) ((grub_uboot_search_hint & ~0x000fffff)
- 0x00500000);
end =
(struct api_signature *) ((grub_addr_t) start + UBOOT_API_SEARCH_LEN -
API_SIG_MAGLEN + 0x00500000);
}
else
{
start = 0;
end = (struct api_signature *) (256 * 1024 * 1024);
}
/* Structure alignment is (at least) 8 bytes */
for (p = start; p < end; p = (void *) ((grub_addr_t) p + 8))
{
if (grub_memcmp (&(p->magic), API_SIG_MAGIC, API_SIG_MAGLEN) == 0)
{
grub_uboot_syscall_ptr = p->syscall;
return p->version;
}
}
return 0;
}
+73
View File
@@ -0,0 +1,73 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2013 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* 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/offsets.h>
#include <grub/symbol.h>
#include <grub/machine/kernel.h>
/*
* uboot_syscall():
* This function is effectively a veneer, so it cannot
* modify the stack or corrupt any registers other than
* r12 (ip). Furthermore it needs to restore r8 for
* U-Boot (Global Data Pointer) and preserve it for Grub.
*/
FUNCTION(grub_uboot_syscall)
str r8, transition_space
str lr, transition_space + 4
str r9, transition_space + 8
ldr ip, saved_registers_ptr
ldr r8, [ip, #4 * 8]
ldr r9, [ip, #4 * 9]
bl do_syscall
ldr r8, transition_space
ldr lr, transition_space + 4
ldr r9, transition_space + 8
bx lr
do_syscall:
ldr ip, grub_uboot_syscall_ptr
bx ip
FUNCTION(grub_uboot_return)
ldr ip, saved_registers_ptr
ldr sp, [ip, #4 * 4]
pop {r4-r12, lr}
mov sp, r12
bx lr
.align 3
@ GRUB context stack space
transition_space:
.long 0 @ r8
.long 0 @ lr
.long 0 @ r9
saved_registers_ptr:
.long EXT_C(grub_arm_saved_registers)
VARIABLE(grub_uboot_syscall_ptr)
.long 0 @
END
@@ -16,8 +16,8 @@
* along with GRUB. If not, see <http://www.gnu.org/licenses/>. * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <grub/machine/memory.h> #include <grub/memory.h>
#include <grub/machine/lbio.h> #include <grub/coreboot/lbio.h>
#include <grub/types.h> #include <grub/types.h>
#include <grub/err.h> #include <grub/err.h>
#include <grub/misc.h> #include <grub/misc.h>
@@ -49,6 +49,7 @@ iterate_linuxbios_table (grub_linuxbios_table_item_t table_item, void *data)
{ {
grub_uint64_t start = mem_region->addr; grub_uint64_t start = mem_region->addr;
grub_uint64_t end = mem_region->addr + mem_region->size; grub_uint64_t end = mem_region->addr + mem_region->size;
#ifdef __i386__
/* Mark region 0xa0000 - 0x100000 as reserved. */ /* Mark region 0xa0000 - 0x100000 as reserved. */
if (start < 0x100000 && end >= 0xa0000 if (start < 0x100000 && end >= 0xa0000
&& mem_region->type == GRUB_MACHINE_MEMORY_AVAILABLE) && mem_region->type == GRUB_MACHINE_MEMORY_AVAILABLE)
@@ -75,6 +76,7 @@ iterate_linuxbios_table (grub_linuxbios_table_item_t table_item, void *data)
if (end <= start) if (end <= start)
continue; continue;
} }
#endif
if (ctx->hook (start, end - start, if (ctx->hook (start, end - start,
/* Multiboot mmaps match with the coreboot mmap /* Multiboot mmaps match with the coreboot mmap
definition. Therefore, we can just pass type definition. Therefore, we can just pass type
+1 -1
View File
@@ -17,7 +17,7 @@
*/ */
#include <grub/i386/coreboot/memory.h> #include <grub/i386/coreboot/memory.h>
#include <grub/i386/coreboot/lbio.h> #include <grub/coreboot/lbio.h>
#include <grub/types.h> #include <grub/types.h>
#include <grub/err.h> #include <grub/err.h>
#include <grub/misc.h> #include <grub/misc.h>
+2
View File
@@ -1106,6 +1106,8 @@ grub_fatal (const char *fmt, ...)
grub_vprintf (_(fmt), ap); grub_vprintf (_(fmt), ap);
va_end (ap); va_end (ap);
grub_refresh ();
grub_abort (); grub_abort ();
} }
-16
View File
@@ -36,30 +36,14 @@
extern char __bss_start[]; extern char __bss_start[];
extern char _end[]; extern char _end[];
extern grub_size_t grub_total_module_size; extern grub_size_t grub_total_module_size;
extern int (*grub_uboot_syscall_ptr) (int, int *, ...);
static unsigned long timer_start; static unsigned long timer_start;
extern grub_uint32_t grub_uboot_machine_type;
extern grub_addr_t grub_uboot_boot_data;
void void
grub_exit (void) grub_exit (void)
{ {
grub_uboot_return (0); grub_uboot_return (0);
} }
grub_uint32_t
grub_uboot_get_machine_type (void)
{
return grub_uboot_machine_type;
}
grub_addr_t
grub_uboot_get_boot_data (void)
{
return grub_uboot_boot_data;
}
static grub_uint64_t static grub_uint64_t
uboot_timer_ms (void) uboot_timer_ms (void)
{ {
-35
View File
@@ -39,48 +39,13 @@
* returns: 0 if the call not found, 1 if serviced * returns: 0 if the call not found, 1 if serviced
*/ */
extern int (*grub_uboot_syscall_ptr) (int, int *, ...);
extern int grub_uboot_syscall (int, int *, ...); extern int grub_uboot_syscall (int, int *, ...);
extern grub_addr_t grub_uboot_search_hint;
static struct sys_info uboot_sys_info; static struct sys_info uboot_sys_info;
static struct mem_region uboot_mem_info[5]; static struct mem_region uboot_mem_info[5];
static struct device_info * devices; static struct device_info * devices;
static int num_devices; static int num_devices;
int
grub_uboot_api_init (void)
{
struct api_signature *start, *end;
struct api_signature *p;
if (grub_uboot_search_hint)
{
/* Extended search range to work around Trim Slice U-Boot issue */
start = (struct api_signature *) ((grub_uboot_search_hint & ~0x000fffff)
- 0x00500000);
end =
(struct api_signature *) ((grub_addr_t) start + UBOOT_API_SEARCH_LEN -
API_SIG_MAGLEN + 0x00500000);
}
else
{
start = 0;
end = (struct api_signature *) (256 * 1024 * 1024);
}
/* Structure alignment is (at least) 8 bytes */
for (p = start; p < end; p = (void *) ((grub_addr_t) p + 8))
{
if (grub_memcmp (&(p->magic), API_SIG_MAGIC, API_SIG_MAGLEN) == 0)
{
grub_uboot_syscall_ptr = p->syscall;
return p->version;
}
}
return 0;
}
/* /*
* All functions below are wrappers around the grub_uboot_syscall() function * All functions below are wrappers around the grub_uboot_syscall() function
+104 -34
View File
@@ -102,13 +102,13 @@ static grub_uint32_t *get_next_node (const void *fdt, char *node_name)
static int get_mem_rsvmap_size (const void *fdt) static int get_mem_rsvmap_size (const void *fdt)
{ {
int size = 0; int size = 0;
grub_uint64_t *ptr = (void *) ((grub_addr_t) fdt grub_unaligned_uint64_t *ptr = (void *) ((grub_addr_t) fdt
+ grub_fdt_get_off_mem_rsvmap (fdt)); + grub_fdt_get_off_mem_rsvmap (fdt));
do do
{ {
size += 2 * sizeof(*ptr); size += 2 * sizeof(*ptr);
if (!*ptr && !*(ptr + 1)) if (!ptr[0].val && !ptr[1].val)
return size; return size;
ptr += 2; ptr += 2;
} while ((grub_addr_t) ptr <= (grub_addr_t) fdt + grub_fdt_get_totalsize (fdt) } while ((grub_addr_t) ptr <= (grub_addr_t) fdt + grub_fdt_get_totalsize (fdt)
@@ -229,7 +229,7 @@ static int rearrange_blocks (void *fdt, unsigned int clearance)
return 0; return 0;
} }
static grub_uint32_t *find_prop (void *fdt, unsigned int nodeoffset, static grub_uint32_t *find_prop (const void *fdt, unsigned int nodeoffset,
const char *name) const char *name)
{ {
grub_uint32_t *prop = (void *) ((grub_addr_t) fdt grub_uint32_t *prop = (void *) ((grub_addr_t) fdt
@@ -268,9 +268,9 @@ static grub_uint32_t *find_prop (void *fdt, unsigned int nodeoffset,
the size allocated for the FDT; if this function is called before the other the size allocated for the FDT; if this function is called before the other
functions in this file and returns success, the other functions are functions in this file and returns success, the other functions are
guaranteed not to access memory locations outside the allocated memory. */ guaranteed not to access memory locations outside the allocated memory. */
int grub_fdt_check_header_nosize (void *fdt) int grub_fdt_check_header_nosize (const void *fdt)
{ {
if (((grub_addr_t) fdt & 0x7) || (grub_fdt_get_magic (fdt) != FDT_MAGIC) if (((grub_addr_t) fdt & 0x3) || (grub_fdt_get_magic (fdt) != FDT_MAGIC)
|| (grub_fdt_get_version (fdt) < FDT_SUPPORTED_VERSION) || (grub_fdt_get_version (fdt) < FDT_SUPPORTED_VERSION)
|| (grub_fdt_get_last_comp_version (fdt) > FDT_SUPPORTED_VERSION) || (grub_fdt_get_last_comp_version (fdt) > FDT_SUPPORTED_VERSION)
|| (grub_fdt_get_off_dt_struct (fdt) & 0x00000003) || (grub_fdt_get_off_dt_struct (fdt) & 0x00000003)
@@ -286,7 +286,7 @@ int grub_fdt_check_header_nosize (void *fdt)
return 0; return 0;
} }
int grub_fdt_check_header (void *fdt, unsigned int size) int grub_fdt_check_header (const void *fdt, unsigned int size)
{ {
if (size < sizeof (grub_fdt_header_t) if (size < sizeof (grub_fdt_header_t)
|| (grub_fdt_get_totalsize (fdt) > size) || (grub_fdt_get_totalsize (fdt) > size)
@@ -295,41 +295,29 @@ int grub_fdt_check_header (void *fdt, unsigned int size)
return 0; return 0;
} }
/* Find a direct sub-node of a given parent node. */ static const grub_uint32_t *
int grub_fdt_find_subnode (const void *fdt, unsigned int parentoffset, advance_token (const void *fdt, const grub_uint32_t *token, const grub_uint32_t *end, int skip_current)
const char *name)
{ {
grub_uint32_t *token, *end; for (; token < end; skip_current = 0)
char *node_name;
if (parentoffset & 0x3)
return -1;
token = (void *) ((grub_addr_t) fdt + grub_fdt_get_off_dt_struct(fdt)
+ parentoffset);
end = (void *) struct_end (fdt);
if ((token >= end) || (grub_be_to_cpu32(*token) != FDT_BEGIN_NODE))
return -1;
SKIP_NODE_NAME(node_name, token, end);
while (token < end)
{ {
switch (grub_be_to_cpu32(*token)) switch (grub_be_to_cpu32 (*token))
{ {
case FDT_BEGIN_NODE: case FDT_BEGIN_NODE:
node_name = (char *) (token + 1); if (skip_current)
if (node_name + grub_strlen (name) >= (char *) end) {
return -1; token = get_next_node (fdt, (char *) (token + 1));
if (!grub_strcmp (node_name, name)) continue;
return (int) ((grub_addr_t) token - (grub_addr_t) fdt }
- grub_fdt_get_off_dt_struct (fdt)); char *ptr;
token = get_next_node (fdt, node_name); for (ptr = (char *) (token + 1); *ptr && ptr < (char *) end; ptr++);
if (!token) if (ptr >= (char *) end)
return -1; return 0;
break; return token;
case FDT_PROP: case FDT_PROP:
/* Skip property token and following data (len, nameoff and property /* Skip property token and following data (len, nameoff and property
value). */ value). */
if (token >= end - 1) if (token >= end - 1)
return -1; return 0;
token += prop_entry_size(grub_be_to_cpu32(*(token + 1))) token += prop_entry_size(grub_be_to_cpu32(*(token + 1)))
/ sizeof(*token); / sizeof(*token);
break; break;
@@ -337,10 +325,74 @@ int grub_fdt_find_subnode (const void *fdt, unsigned int parentoffset,
token++; token++;
break; break;
default: default:
return -1; return 0;
} }
} }
return 0;
}
int grub_fdt_next_node (const void *fdt, unsigned int currentoffset)
{
const grub_uint32_t *token = (const grub_uint32_t *) fdt + (currentoffset + grub_fdt_get_off_dt_struct (fdt)) / 4;
token = advance_token (fdt, token, (const void *) struct_end (fdt), 1);
if (!token)
return -1; return -1;
return (int) ((grub_addr_t) token - (grub_addr_t) fdt
- grub_fdt_get_off_dt_struct (fdt));
}
int grub_fdt_first_node (const void *fdt, unsigned int parentoffset)
{
const grub_uint32_t *token, *end;
char *node_name;
if (parentoffset & 0x3)
return -1;
token = (const void *) ((grub_addr_t) fdt + grub_fdt_get_off_dt_struct(fdt)
+ parentoffset);
end = (const void *) struct_end (fdt);
if ((token >= end) || (grub_be_to_cpu32(*token) != FDT_BEGIN_NODE))
return -1;
SKIP_NODE_NAME(node_name, token, end);
token = advance_token (fdt, token, end, 0);
if (!token)
return -1;
return (int) ((grub_addr_t) token - (grub_addr_t) fdt
- grub_fdt_get_off_dt_struct (fdt));
}
/* Find a direct sub-node of a given parent node. */
int grub_fdt_find_subnode (const void *fdt, unsigned int parentoffset,
const char *name)
{
const grub_uint32_t *token, *end;
const char *node_name;
int skip_current = 0;
if (parentoffset & 0x3)
return -1;
token = (const void *) ((grub_addr_t) fdt + grub_fdt_get_off_dt_struct(fdt)
+ parentoffset);
end = (const void *) struct_end (fdt);
if ((token >= end) || (grub_be_to_cpu32(*token) != FDT_BEGIN_NODE))
return -1;
SKIP_NODE_NAME(node_name, token, end);
while (1) {
token = advance_token (fdt, token, end, skip_current);
if (!token)
return -1;
skip_current = 1;
node_name = (const char *) token + 4;
if (grub_strcmp (node_name, name) == 0)
return (int) ((grub_addr_t) token - (grub_addr_t) fdt
- grub_fdt_get_off_dt_struct (fdt));
}
}
const char *
grub_fdt_get_nodename (const void *fdt, unsigned int nodeoffset)
{
return (const char *) fdt + grub_fdt_get_off_dt_struct(fdt) + nodeoffset + 4;
} }
int grub_fdt_add_subnode (void *fdt, unsigned int parentoffset, int grub_fdt_add_subnode (void *fdt, unsigned int parentoffset,
@@ -359,6 +411,24 @@ int grub_fdt_add_subnode (void *fdt, unsigned int parentoffset,
return add_subnode (fdt, parentoffset, name); return add_subnode (fdt, parentoffset, name);
} }
const void *
grub_fdt_get_prop (const void *fdt, unsigned int nodeoffset, const char *name,
grub_uint32_t *len)
{
grub_uint32_t *prop;
if ((nodeoffset >= grub_fdt_get_size_dt_struct (fdt)) || (nodeoffset & 0x3)
|| (grub_be_to_cpu32(*(grub_uint32_t *) ((grub_addr_t) fdt
+ grub_fdt_get_off_dt_struct (fdt) + nodeoffset))
!= FDT_BEGIN_NODE))
return 0;
prop = find_prop (fdt, nodeoffset, name);
if (!prop)
return 0;
if (len)
*len = grub_be_to_cpu32 (*(prop + 1));
return prop + 3;
}
int grub_fdt_set_prop (void *fdt, unsigned int nodeoffset, const char *name, int grub_fdt_set_prop (void *fdt, unsigned int nodeoffset, const char *name,
const void *val, grub_uint32_t len) const void *val, grub_uint32_t len)
{ {
+64 -59
View File
@@ -42,7 +42,7 @@ static grub_size_t linux_size;
static char *linux_args; static char *linux_args;
static grub_uint32_t machine_type; static grub_uint32_t machine_type;
static void *fdt_addr; static const void *current_fdt;
typedef void (*kernel_entry_t) (int, unsigned long, void *); typedef void (*kernel_entry_t) (int, unsigned long, void *);
@@ -54,9 +54,9 @@ typedef void (*kernel_entry_t) (int, unsigned long, void *);
#define LINUX_FDT_PHYS_OFFSET (LINUX_INITRD_PHYS_OFFSET - 0x10000) #define LINUX_FDT_PHYS_OFFSET (LINUX_INITRD_PHYS_OFFSET - 0x10000)
static grub_size_t static grub_size_t
get_atag_size (grub_uint32_t *atag) get_atag_size (const grub_uint32_t *atag)
{ {
grub_uint32_t *atag0 = atag; const grub_uint32_t *atag0 = atag;
while (atag[0] && atag[1]) while (atag[0] && atag[1])
atag += atag[0]; atag += atag[0];
return atag - atag0; return atag - atag0;
@@ -68,10 +68,11 @@ get_atag_size (grub_uint32_t *atag)
* Merges in command line parameters and sets up initrd addresses. * Merges in command line parameters and sets up initrd addresses.
*/ */
static grub_err_t static grub_err_t
linux_prepare_atag (void) linux_prepare_atag (void *target_atag)
{ {
grub_uint32_t *atag_orig = (grub_uint32_t *) fdt_addr; const grub_uint32_t *atag_orig = (const grub_uint32_t *) current_fdt;
grub_uint32_t *tmp_atag, *from, *to; grub_uint32_t *tmp_atag, *to;
const grub_uint32_t *from;
grub_size_t tmp_size; grub_size_t tmp_size;
grub_size_t arg_size = grub_strlen (linux_args); grub_size_t arg_size = grub_strlen (linux_args);
char *cmdline_orig = NULL; char *cmdline_orig = NULL;
@@ -142,7 +143,7 @@ linux_prepare_atag (void)
to += 2; to += 2;
/* Copy updated FDT to its launch location */ /* Copy updated FDT to its launch location */
grub_memcpy (atag_orig, tmp_atag, sizeof (grub_uint32_t) * (to - tmp_atag)); grub_memcpy (target_atag, tmp_atag, sizeof (grub_uint32_t) * (to - tmp_atag));
grub_free (tmp_atag); grub_free (tmp_atag);
grub_dprintf ("loader", "ATAG updated for Linux boot\n"); grub_dprintf ("loader", "ATAG updated for Linux boot\n");
@@ -156,19 +157,19 @@ linux_prepare_atag (void)
* Merges in command line parameters and sets up initrd addresses. * Merges in command line parameters and sets up initrd addresses.
*/ */
static grub_err_t static grub_err_t
linux_prepare_fdt (void) linux_prepare_fdt (void *target_fdt)
{ {
int node; int node;
int retval; int retval;
int tmp_size; int tmp_size;
void *tmp_fdt; void *tmp_fdt;
tmp_size = grub_fdt_get_totalsize (fdt_addr) + 0x100 + grub_strlen (linux_args); tmp_size = grub_fdt_get_totalsize (current_fdt) + 0x100 + grub_strlen (linux_args);
tmp_fdt = grub_malloc (tmp_size); tmp_fdt = grub_malloc (tmp_size);
if (!tmp_fdt) if (!tmp_fdt)
return grub_errno; return grub_errno;
grub_memcpy (tmp_fdt, fdt_addr, grub_fdt_get_totalsize (fdt_addr)); grub_memcpy (tmp_fdt, current_fdt, grub_fdt_get_totalsize (current_fdt));
grub_fdt_set_totalsize (tmp_fdt, tmp_size); grub_fdt_set_totalsize (tmp_fdt, tmp_size);
/* Find or create '/chosen' node */ /* Find or create '/chosen' node */
@@ -209,7 +210,7 @@ linux_prepare_fdt (void)
} }
/* Copy updated FDT to its launch location */ /* Copy updated FDT to its launch location */
grub_memcpy (fdt_addr, tmp_fdt, tmp_size); grub_memcpy (target_fdt, tmp_fdt, tmp_size);
grub_free (tmp_fdt); grub_free (tmp_fdt);
grub_dprintf ("loader", "FDT updated for Linux boot\n"); grub_dprintf ("loader", "FDT updated for Linux boot\n");
@@ -226,16 +227,17 @@ linux_boot (void)
{ {
kernel_entry_t linuxmain; kernel_entry_t linuxmain;
int fdt_valid, atag_valid; int fdt_valid, atag_valid;
void *target_fdt = 0;
fdt_valid = (fdt_addr && grub_fdt_check_header_nosize (fdt_addr) == 0); fdt_valid = (current_fdt && grub_fdt_check_header_nosize (current_fdt) == 0);
atag_valid = ((((grub_uint16_t *) fdt_addr)[3] & ~3) == 0x5440 atag_valid = ((((const grub_uint16_t *) current_fdt)[3] & ~3) == 0x5440
&& *((grub_uint32_t *) fdt_addr)); && *((const grub_uint32_t *) current_fdt));
grub_dprintf ("loader", "atag: %p, %x, %x, %s, %s\n", grub_dprintf ("loader", "atag: %p, %x, %x, %s, %s\n",
fdt_addr, current_fdt,
((grub_uint16_t *) fdt_addr)[3], ((const grub_uint16_t *) current_fdt)[3],
*((grub_uint32_t *) fdt_addr), *((const grub_uint32_t *) current_fdt),
(char *) fdt_addr, (const char *) current_fdt,
(char *) fdt_addr + 1); (const char *) current_fdt + 1);
if (!fdt_valid && machine_type == GRUB_ARM_MACHINE_TYPE_FDT) if (!fdt_valid && machine_type == GRUB_ARM_MACHINE_TYPE_FDT)
return grub_error (GRUB_ERR_FILE_NOT_FOUND, return grub_error (GRUB_ERR_FILE_NOT_FOUND,
@@ -245,23 +247,40 @@ linux_boot (void)
grub_dprintf ("loader", "Kernel at: 0x%x\n", linux_addr); grub_dprintf ("loader", "Kernel at: 0x%x\n", linux_addr);
if (fdt_valid || atag_valid)
{
#ifdef GRUB_MACHINE_EFI
grub_size_t size;
if (fdt_valid)
size = grub_fdt_get_totalsize (fdt_addr);
else
size = 4 * get_atag_size (atag_orig);
size += grub_strlen (linux_args) + 256;
target_fdt = grub_efi_allocate_loader_memory (LINUX_FDT_PHYS_OFFSET, size);
if (!fdt_addr)
return grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
#else
target_fdt = (void *) LINUX_FDT_ADDRESS;
#endif
}
if (fdt_valid) if (fdt_valid)
{ {
grub_err_t err; grub_err_t err;
err = linux_prepare_fdt (); err = linux_prepare_fdt (target_fdt);
if (err) if (err)
return err; return err;
grub_dprintf ("loader", "FDT @ 0x%p\n", fdt_addr); grub_dprintf ("loader", "FDT @ %p\n", target_fdt);
} }
else if (atag_valid) else if (atag_valid)
{ {
grub_err_t err; grub_err_t err;
err = linux_prepare_atag (); err = linux_prepare_atag (target_fdt);
if (err) if (err)
return err; return err;
grub_dprintf ("loader", "ATAG @ 0x%p\n", fdt_addr); grub_dprintf ("loader", "ATAG @ %p\n", target_fdt);
} }
grub_dprintf ("loader", "Jumping to Linux...\n"); grub_dprintf ("loader", "Jumping to Linux...\n");
@@ -285,7 +304,7 @@ linux_boot (void)
grub_arm_disable_caches_mmu (); grub_arm_disable_caches_mmu ();
linuxmain (0, machine_type, fdt_addr); linuxmain (0, machine_type, target_fdt);
return grub_error (GRUB_ERR_BAD_OS, "Linux call returned"); return grub_error (GRUB_ERR_BAD_OS, "Linux call returned");
} }
@@ -444,11 +463,26 @@ fail:
static grub_err_t static grub_err_t
load_dtb (grub_file_t dtb, int size) load_dtb (grub_file_t dtb, int size)
{ {
if ((grub_file_read (dtb, fdt_addr, size) != size) void *new_fdt = grub_zalloc (size);
|| (grub_fdt_check_header (fdt_addr, size) != 0)) if (!new_fdt)
return grub_errno;
grub_dprintf ("loader", "Loading device tree to %p\n",
new_fdt);
if ((grub_file_read (dtb, new_fdt, size) != size)
|| (grub_fdt_check_header (new_fdt, size) != 0))
{
grub_free (new_fdt);
return grub_error (GRUB_ERR_BAD_OS, N_("invalid device tree")); return grub_error (GRUB_ERR_BAD_OS, N_("invalid device tree"));
}
grub_fdt_set_totalsize (new_fdt, size);
current_fdt = new_fdt;
/*
* We've successfully loaded an FDT, so any machine type passed
* from firmware is now obsolete.
*/
machine_type = GRUB_ARM_MACHINE_TYPE_FDT;
grub_fdt_set_totalsize (fdt_addr, size);
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
} }
@@ -464,42 +498,13 @@ grub_cmd_devicetree (grub_command_t cmd __attribute__ ((unused)),
dtb = grub_file_open (argv[0]); dtb = grub_file_open (argv[0]);
if (!dtb) if (!dtb)
goto out; return grub_errno;
size = grub_file_size (dtb); size = grub_file_size (dtb);
if (size == 0) if (size == 0)
{
grub_error (GRUB_ERR_BAD_OS, "empty file"); grub_error (GRUB_ERR_BAD_OS, "empty file");
goto out; else
}
#ifdef GRUB_MACHINE_EFI
fdt_addr = grub_efi_allocate_loader_memory (LINUX_FDT_PHYS_OFFSET, size);
if (!fdt_addr)
{
grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
goto out;
}
#else
fdt_addr = (void *) LINUX_FDT_ADDRESS;
#endif
grub_dprintf ("loader", "Loading device tree to 0x%08x\n",
(grub_addr_t) fdt_addr);
load_dtb (dtb, size); load_dtb (dtb, size);
if (grub_errno != GRUB_ERR_NONE)
{
fdt_addr = NULL;
goto out;
}
/*
* We've successfully loaded an FDT, so any machine type passed
* from firmware is now obsolete.
*/
machine_type = GRUB_ARM_MACHINE_TYPE_FDT;
out:
grub_file_close (dtb); grub_file_close (dtb);
return grub_errno; return grub_errno;
@@ -517,7 +522,7 @@ GRUB_MOD_INIT (linux)
/* TRANSLATORS: DTB stands for device tree blob. */ /* TRANSLATORS: DTB stands for device tree blob. */
0, N_("Load DTB file.")); 0, N_("Load DTB file."));
my_mod = mod; my_mod = mod;
fdt_addr = (void *) grub_arm_firmware_get_boot_data (); current_fdt = grub_arm_firmware_get_boot_data ();
machine_type = grub_arm_firmware_get_machine_type (); machine_type = grub_arm_firmware_get_machine_type ();
} }
+117
View File
@@ -0,0 +1,117 @@
/*
* GRUB -- GRand Unified Bootloader
*
* Copyright (C) 2012 Google Inc.
* Copyright (C) 2016 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* 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/ps2.h>
#include <grub/fdtbus.h>
#include <grub/err.h>
#include <grub/machine/kernel.h>
#include <grub/misc.h>
#include <grub/term.h>
#include <grub/time.h>
#include <grub/fdtbus.h>
#include <grub/arm/cros_ec.h>
struct grub_ps2_state ps2_state;
struct grub_cros_ec_keyscan old_scan;
static grub_uint8_t map_code[GRUB_CROS_EC_KEYSCAN_COLS][GRUB_CROS_EC_KEYSCAN_ROWS];
static grub_uint8_t e0_translate[16] =
{
0x1c, 0x1d, 0x35, 0x00,
0x38, 0x00, 0x47, 0x48,
0x49, 0x4b, 0x4d, 0x4f,
0x50, 0x51, 0x52, 0x53,
};
/* If there is a character pending, return it;
otherwise return GRUB_TERM_NO_KEY. */
static int
grub_cros_keyboard_getkey (struct grub_term_input *term __attribute__ ((unused)))
{
struct grub_cros_ec_keyscan scan;
int i, j;
if (grub_cros_ec_scan_keyboard(&scan) < 0)
return GRUB_TERM_NO_KEY;
for (i = 0; i < GRUB_CROS_EC_KEYSCAN_COLS; i++)
if (scan.data[i] ^ old_scan.data[i])
for (j = 0; j < GRUB_CROS_EC_KEYSCAN_ROWS; j++)
if ((scan.data[i] ^ old_scan.data[i]) & (1 << j))
{
grub_uint8_t code = map_code[i][j];
int ret;
grub_uint8_t brk = 0;
if (!(scan.data[i] & (1 << j)))
brk = 0x80;
grub_dprintf ("cros_keyboard", "key <%d, %d> code %x\n", i, j, code);
if (code < 0x60)
ret = grub_ps2_process_incoming_byte (&ps2_state, code | brk);
else if (code >= 0x60 && code < 0x70 && e0_translate[code - 0x60])
{
grub_ps2_process_incoming_byte (&ps2_state, 0xe0);
ret = grub_ps2_process_incoming_byte (&ps2_state, e0_translate[code - 0x60] | brk);
}
else
ret = GRUB_TERM_NO_KEY;
old_scan.data[i] ^= (1 << j);
if (ret != GRUB_TERM_NO_KEY)
return ret;
}
return GRUB_TERM_NO_KEY;
}
static struct grub_term_input grub_cros_keyboard_term =
{
.name = "cros_keyboard",
.getkey = grub_cros_keyboard_getkey
};
static grub_err_t
cros_attach(const struct grub_fdtbus_dev *dev __attribute__ ((unused)))
{
grub_size_t keymap_size, i;
const grub_uint8_t *keymap = grub_fdtbus_get_prop (dev, "linux,keymap", &keymap_size);
if (keymap)
{
for (i = 0; i + 3 < keymap_size; i += 4)
if (keymap[i+1] < GRUB_CROS_EC_KEYSCAN_COLS && keymap[i] < GRUB_CROS_EC_KEYSCAN_ROWS
&& keymap[i+2] == 0 && keymap[i+3] < 0x80)
map_code[keymap[i+1]][keymap[i]] = keymap[i+3];
}
ps2_state.current_set = 1;
ps2_state.at_keyboard_status = 0;
grub_term_register_input ("cros_keyboard", &grub_cros_keyboard_term);
return GRUB_ERR_NONE;
}
struct grub_fdtbus_driver cros =
{
.compatible = "google,cros-ec-keyb",
.attach = cros_attach
};
void
grub_cros_init (void)
{
grub_fdtbus_register (&cros);
}
+270
View File
@@ -0,0 +1,270 @@
/*
* GRUB -- GRand Unified Bootloader
*
* Copyright (C) 2012 Google Inc.
* Copyright (C) 2016 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* 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/mm.h>
#include <grub/time.h>
#include <grub/misc.h>
#include <grub/arm/cros_ec.h>
static grub_uint64_t
grub_get_time_us (void)
{
return 1000 * grub_get_time_ms();
}
static void
grub_microsleep (grub_uint64_t len)
{
grub_uint64_t end_time = grub_get_time_us () + len;
while (grub_get_time_us () < end_time)
grub_cpu_idle ();
}
volatile grub_uint32_t *spi = (volatile grub_uint32_t *) 0xff110000;
static int
spi_send (const void *data, grub_size_t sz)
{
const grub_uint8_t *ptr = data, *end = ptr + sz;
spi[2] = 0;
spi[1] = sz - 1;
spi[0] = ((1 << 18) | spi[0]) & ~(1 << 19);
spi[2] = 1;
while (ptr < end)
{
while (spi[9] & 2);
spi[256] = *ptr++;
}
while (spi[9] & 1);
return 0;
}
static int
spi_read (void *data, grub_size_t sz)
{
grub_uint8_t *ptr = data, *end = ptr + sz;
spi[2] = 0;
spi[1] = sz - 1;
spi[0] = ((1 << 19) | spi[0]) & ~(1 << 18);
spi[2] = 1;
while (ptr < end)
{
while (spi[9] & 8);
*ptr++ = spi[512];
}
while (spi[9] & 1);
return 0;
}
static int
spi_start (void)
{
spi[3] = 1;
return 0;
}
static void
spi_stop (void)
{
spi[3] = 0;
}
#define uint8_t grub_uint8_t
#define uint16_t grub_uint16_t
#define uint32_t grub_uint32_t
#define uint64_t grub_uint64_t
#define mdelay grub_millisleep
#define memcpy grub_memcpy
static const uint64_t FramingTimeoutUs = 300 * 1000;
static const uint8_t EcFramingByte = 0xec;
#define EC_CMD_MKBP_STATE 0x60
#define EC_CMD_VERSION0 0xdc
static uint64_t last_transfer;
static void stop_bus(void)
{
spi_stop();
last_transfer = grub_get_time_us();
}
static int wait_for_frame(void)
{
uint64_t start = grub_get_time_us();
uint8_t byte;
do {
if (spi_read(&byte, 1))
return -1;
if (byte != EcFramingByte &&
grub_get_time_us() - start > FramingTimeoutUs) {
grub_dprintf("cros", "Timeout waiting for framing byte.\n");
return -1;
}
} while (byte != EcFramingByte);
return 0;
}
/*
* Calculate a simple 8-bit checksum of a data block
*
* @param data Data block to checksum
* @param size Size of data block in bytes
* @return checksum value (0 to 255)
*/
static uint8_t cros_ec_calc_checksum(const void *data, int size)
{
uint8_t csum;
const uint8_t *bytes = data;
int i;
for (i = csum = 0; i < size; i++)
csum += bytes[i];
return csum & 0xff;
}
enum {
// response, arglen
CROS_EC_SPI_IN_HDR_SIZE = 2,
// version, cmd, arglen
CROS_EC_SPI_OUT_HDR_SIZE = 3
};
static grub_uint8_t busbuf[256];
#define MSG_BYTES ((int)sizeof (busbuf))
static int ec_command(int cmd, int cmd_version,
const void *dout, int dout_len,
void *din, int din_len)
{
uint8_t *bytes;
// Header + data + checksum.
uint32_t out_bytes = CROS_EC_SPI_OUT_HDR_SIZE + dout_len + 1;
uint32_t in_bytes = CROS_EC_SPI_IN_HDR_SIZE + din_len + 1;
/*
* Sanity-check I/O sizes given transaction overhead in internal
* buffers.
*/
if (out_bytes > MSG_BYTES) {
grub_dprintf("cros", "Cannot send %d bytes\n", dout_len);
return -1;
}
if (in_bytes > MSG_BYTES) {
grub_dprintf("cros", "Cannot receive %d bytes\n", din_len);
return -1;
}
// Prepare the output.
bytes = busbuf;
*bytes++ = EC_CMD_VERSION0 + cmd_version;
*bytes++ = cmd;
*bytes++ = dout_len;
memcpy(bytes, dout, dout_len);
bytes += dout_len;
*bytes++ = cros_ec_calc_checksum(busbuf,
CROS_EC_SPI_OUT_HDR_SIZE + dout_len);
while (grub_get_time_us() - last_transfer < 200)
;
if (spi_start())
return -1;
// Allow EC to ramp up clock after being awoken.
// See chrome-os-partner:32223 for more details.
grub_microsleep (100);
if (spi_send(busbuf, out_bytes)) {
stop_bus();
return -1;
}
// Wait until the EC is ready.
if (wait_for_frame()) {
stop_bus();
return -1;
}
// Read the response code and the data length.
bytes = busbuf;
if (spi_read(bytes, 2)) {
stop_bus();
return -1;
}
uint8_t result = *bytes++;
uint8_t length = *bytes++;
// Make sure there's enough room for the data.
if (CROS_EC_SPI_IN_HDR_SIZE + length + 1 > MSG_BYTES) {
grub_dprintf("cros", "Received length %#02x too large\n",
length);
stop_bus();
return -1;
}
// Read the data and the checksum, and finish up.
if (spi_read(bytes, length + 1)) {
stop_bus();
return -1;
}
bytes += length;
int expected = *bytes++;
stop_bus();
// Check the integrity of the response.
if (result != 0) {
grub_dprintf("cros", "Received bad result code %d\n", result);
return -result;
}
int csum = cros_ec_calc_checksum(busbuf,
CROS_EC_SPI_IN_HDR_SIZE + length);
if (csum != expected) {
grub_dprintf("cros", "Invalid checksum rx %#02x, calced %#02x\n",
expected, csum);
return -1;
}
// If the caller wants the response, copy it out for them.
if (length < din_len)
din_len = length;
if (din) {
memcpy(din, (uint8_t *)busbuf + CROS_EC_SPI_IN_HDR_SIZE,
din_len);
}
return din_len;
}
int
grub_cros_ec_scan_keyboard(struct grub_cros_ec_keyscan *scan)
{
if (ec_command(EC_CMD_MKBP_STATE, 0, NULL, 0, scan,
sizeof(*scan)) < (int)sizeof(*scan))
return -1;
return 0;
}
+189
View File
@@ -0,0 +1,189 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2007,2008,2009 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* 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/ps2.h>
#include <grub/fdtbus.h>
#include <grub/err.h>
#include <grub/machine/kernel.h>
#include <grub/at_keyboard.h>
#include <grub/misc.h>
#include <grub/term.h>
#include <grub/time.h>
#include <grub/ps2.h>
#include <grub/fdtbus.h>
static volatile grub_uint32_t *pl050_regs;
struct grub_ps2_state ps2_state;
static void
keyboard_controller_wait_until_ready (void)
{
while (! (pl050_regs[1] & 0x40));
}
static grub_uint8_t
wait_ack (void)
{
grub_uint64_t endtime;
grub_uint8_t ack;
endtime = grub_get_time_ms () + 20;
do
ack = pl050_regs[2];
while (ack != GRUB_AT_ACK && ack != GRUB_AT_NACK
&& grub_get_time_ms () < endtime);
return ack;
}
static int
write_mode (int mode)
{
unsigned i;
for (i = 0; i < GRUB_AT_TRIES; i++)
{
grub_uint8_t ack;
keyboard_controller_wait_until_ready ();
pl050_regs[2] = 0xf0;
keyboard_controller_wait_until_ready ();
pl050_regs[2] = mode;
keyboard_controller_wait_until_ready ();
ack = wait_ack ();
if (ack == GRUB_AT_NACK)
continue;
if (ack == GRUB_AT_ACK)
break;
return 0;
}
return (i != GRUB_AT_TRIES);
}
static int
query_mode (void)
{
grub_uint8_t ret;
int e;
e = write_mode (0);
if (!e)
return 0;
keyboard_controller_wait_until_ready ();
do
ret = pl050_regs[2];
while (ret == GRUB_AT_ACK);
/* QEMU translates the set even in no-translate mode. */
if (ret == 0x43 || ret == 1)
return 1;
if (ret == 0x41 || ret == 2)
return 2;
if (ret == 0x3f || ret == 3)
return 3;
return 0;
}
static void
set_scancodes (void)
{
write_mode (2);
ps2_state.current_set = query_mode ();
grub_dprintf ("atkeyb", "returned set %d\n", ps2_state.current_set);
if (ps2_state.current_set == 2)
return;
write_mode (1);
ps2_state.current_set = query_mode ();
grub_dprintf ("atkeyb", "returned set %d\n", ps2_state.current_set);
if (ps2_state.current_set == 1)
return;
grub_dprintf ("atkeyb", "no supported scancode set found\n");
}
static void
keyboard_controller_led (grub_uint8_t leds)
{
keyboard_controller_wait_until_ready ();
pl050_regs[2] = 0xed;
keyboard_controller_wait_until_ready ();
pl050_regs[2] = leds & 0x7;
}
/* If there is a character pending, return it;
otherwise return GRUB_TERM_NO_KEY. */
static int
grub_pl050_keyboard_getkey (struct grub_term_input *term __attribute__ ((unused)))
{
grub_uint8_t at_key;
int ret;
grub_uint8_t old_led;
if (!(pl050_regs[1] & 0x10))
return -1;
at_key = pl050_regs[2];
old_led = ps2_state.led_status;
ret = grub_ps2_process_incoming_byte (&ps2_state, at_key);
if (old_led != ps2_state.led_status)
keyboard_controller_led (ps2_state.led_status);
return ret;
}
static struct grub_term_input grub_pl050_keyboard_term =
{
.name = "pl050_keyboard",
.getkey = grub_pl050_keyboard_getkey
};
static grub_err_t
pl050_attach(const struct grub_fdtbus_dev *dev)
{
const grub_uint32_t *reg;
reg = grub_fdtbus_get_prop (dev, "reg", 0);
/* Mouse. Nothing to do. */
if (grub_be_to_cpu32 (*reg) == 0x7000)
return 0;
pl050_regs = grub_fdtbus_map_reg (dev, 0, 0);
if (!grub_fdtbus_is_mapping_valid (pl050_regs))
return grub_error (GRUB_ERR_IO, "could not map pl050");
ps2_state.at_keyboard_status = 0;
set_scancodes ();
keyboard_controller_led (ps2_state.led_status);
grub_term_register_input ("pl050_keyboard", &grub_pl050_keyboard_term);
return GRUB_ERR_NONE;
}
struct grub_fdtbus_driver pl050 =
{
.compatible = "arm,pl050",
.attach = pl050_attach
};
void
grub_pl050_init (void)
{
grub_fdtbus_register (&pl050);
}
+29 -397
View File
@@ -22,212 +22,21 @@
#include <grub/cpu/io.h> #include <grub/cpu/io.h>
#include <grub/misc.h> #include <grub/misc.h>
#include <grub/term.h> #include <grub/term.h>
#include <grub/keyboard_layouts.h>
#include <grub/time.h> #include <grub/time.h>
#include <grub/loader.h> #include <grub/loader.h>
#include <grub/ps2.h>
GRUB_MOD_LICENSE ("GPLv3+"); GRUB_MOD_LICENSE ("GPLv3+");
static short at_keyboard_status = 0;
static int e0_received = 0;
static int f0_received = 0;
static grub_uint8_t led_status;
#define KEYBOARD_LED_SCROLL (1 << 0)
#define KEYBOARD_LED_NUM (1 << 1)
#define KEYBOARD_LED_CAPS (1 << 2)
static grub_uint8_t grub_keyboard_controller_orig; static grub_uint8_t grub_keyboard_controller_orig;
static grub_uint8_t grub_keyboard_orig_set; static grub_uint8_t grub_keyboard_orig_set;
static grub_uint8_t current_set; struct grub_ps2_state ps2_state;
static int ping_sent;
static void static void
grub_keyboard_controller_init (void); grub_keyboard_controller_init (void);
static const grub_uint8_t set1_mapping[128] =
{
/* 0x00 */ 0 /* Unused */, GRUB_KEYBOARD_KEY_ESCAPE,
/* 0x02 */ GRUB_KEYBOARD_KEY_1, GRUB_KEYBOARD_KEY_2,
/* 0x04 */ GRUB_KEYBOARD_KEY_3, GRUB_KEYBOARD_KEY_4,
/* 0x06 */ GRUB_KEYBOARD_KEY_5, GRUB_KEYBOARD_KEY_6,
/* 0x08 */ GRUB_KEYBOARD_KEY_7, GRUB_KEYBOARD_KEY_8,
/* 0x0a */ GRUB_KEYBOARD_KEY_9, GRUB_KEYBOARD_KEY_0,
/* 0x0c */ GRUB_KEYBOARD_KEY_DASH, GRUB_KEYBOARD_KEY_EQUAL,
/* 0x0e */ GRUB_KEYBOARD_KEY_BACKSPACE, GRUB_KEYBOARD_KEY_TAB,
/* 0x10 */ GRUB_KEYBOARD_KEY_Q, GRUB_KEYBOARD_KEY_W,
/* 0x12 */ GRUB_KEYBOARD_KEY_E, GRUB_KEYBOARD_KEY_R,
/* 0x14 */ GRUB_KEYBOARD_KEY_T, GRUB_KEYBOARD_KEY_Y,
/* 0x16 */ GRUB_KEYBOARD_KEY_U, GRUB_KEYBOARD_KEY_I,
/* 0x18 */ GRUB_KEYBOARD_KEY_O, GRUB_KEYBOARD_KEY_P,
/* 0x1a */ GRUB_KEYBOARD_KEY_LBRACKET, GRUB_KEYBOARD_KEY_RBRACKET,
/* 0x1c */ GRUB_KEYBOARD_KEY_ENTER, GRUB_KEYBOARD_KEY_LEFT_CTRL,
/* 0x1e */ GRUB_KEYBOARD_KEY_A, GRUB_KEYBOARD_KEY_S,
/* 0x20 */ GRUB_KEYBOARD_KEY_D, GRUB_KEYBOARD_KEY_F,
/* 0x22 */ GRUB_KEYBOARD_KEY_G, GRUB_KEYBOARD_KEY_H,
/* 0x24 */ GRUB_KEYBOARD_KEY_J, GRUB_KEYBOARD_KEY_K,
/* 0x26 */ GRUB_KEYBOARD_KEY_L, GRUB_KEYBOARD_KEY_SEMICOLON,
/* 0x28 */ GRUB_KEYBOARD_KEY_DQUOTE, GRUB_KEYBOARD_KEY_RQUOTE,
/* 0x2a */ GRUB_KEYBOARD_KEY_LEFT_SHIFT, GRUB_KEYBOARD_KEY_BACKSLASH,
/* 0x2c */ GRUB_KEYBOARD_KEY_Z, GRUB_KEYBOARD_KEY_X,
/* 0x2e */ GRUB_KEYBOARD_KEY_C, GRUB_KEYBOARD_KEY_V,
/* 0x30 */ GRUB_KEYBOARD_KEY_B, GRUB_KEYBOARD_KEY_N,
/* 0x32 */ GRUB_KEYBOARD_KEY_M, GRUB_KEYBOARD_KEY_COMMA,
/* 0x34 */ GRUB_KEYBOARD_KEY_DOT, GRUB_KEYBOARD_KEY_SLASH,
/* 0x36 */ GRUB_KEYBOARD_KEY_RIGHT_SHIFT, GRUB_KEYBOARD_KEY_NUMMUL,
/* 0x38 */ GRUB_KEYBOARD_KEY_LEFT_ALT, GRUB_KEYBOARD_KEY_SPACE,
/* 0x3a */ GRUB_KEYBOARD_KEY_CAPS_LOCK, GRUB_KEYBOARD_KEY_F1,
/* 0x3c */ GRUB_KEYBOARD_KEY_F2, GRUB_KEYBOARD_KEY_F3,
/* 0x3e */ GRUB_KEYBOARD_KEY_F4, GRUB_KEYBOARD_KEY_F5,
/* 0x40 */ GRUB_KEYBOARD_KEY_F6, GRUB_KEYBOARD_KEY_F7,
/* 0x42 */ GRUB_KEYBOARD_KEY_F8, GRUB_KEYBOARD_KEY_F9,
/* 0x44 */ GRUB_KEYBOARD_KEY_F10, GRUB_KEYBOARD_KEY_NUM_LOCK,
/* 0x46 */ GRUB_KEYBOARD_KEY_SCROLL_LOCK, GRUB_KEYBOARD_KEY_NUM7,
/* 0x48 */ GRUB_KEYBOARD_KEY_NUM8, GRUB_KEYBOARD_KEY_NUM9,
/* 0x4a */ GRUB_KEYBOARD_KEY_NUMMINUS, GRUB_KEYBOARD_KEY_NUM4,
/* 0x4c */ GRUB_KEYBOARD_KEY_NUM5, GRUB_KEYBOARD_KEY_NUM6,
/* 0x4e */ GRUB_KEYBOARD_KEY_NUMPLUS, GRUB_KEYBOARD_KEY_NUM1,
/* 0x50 */ GRUB_KEYBOARD_KEY_NUM2, GRUB_KEYBOARD_KEY_NUM3,
/* 0x52 */ GRUB_KEYBOARD_KEY_NUMDOT, GRUB_KEYBOARD_KEY_NUMDOT,
/* 0x54 */ 0, 0,
/* 0x56 */ GRUB_KEYBOARD_KEY_102ND, GRUB_KEYBOARD_KEY_F11,
/* 0x58 */ GRUB_KEYBOARD_KEY_F12, 0,
/* 0x5a */ 0, 0,
/* 0x5c */ 0, 0,
/* 0x5e */ 0, 0,
/* 0x60 */ 0, 0,
/* 0x62 */ 0, 0,
/* OLPC keys. Just mapped to normal keys. */
/* 0x64 */ 0, GRUB_KEYBOARD_KEY_UP,
/* 0x66 */ GRUB_KEYBOARD_KEY_DOWN, GRUB_KEYBOARD_KEY_LEFT,
/* 0x68 */ GRUB_KEYBOARD_KEY_RIGHT, 0,
/* 0x6a */ 0, 0,
/* 0x6c */ 0, 0,
/* 0x6e */ 0, 0,
/* 0x70 */ 0, 0,
/* 0x72 */ 0, GRUB_KEYBOARD_KEY_JP_RO,
/* 0x74 */ 0, 0,
/* 0x76 */ 0, 0,
/* 0x78 */ 0, 0,
/* 0x7a */ 0, 0,
/* 0x7c */ 0, GRUB_KEYBOARD_KEY_JP_YEN,
/* 0x7e */ GRUB_KEYBOARD_KEY_KPCOMMA
};
static const struct
{
grub_uint8_t from, to;
} set1_e0_mapping[] =
{
{0x1c, GRUB_KEYBOARD_KEY_NUMENTER},
{0x1d, GRUB_KEYBOARD_KEY_RIGHT_CTRL},
{0x35, GRUB_KEYBOARD_KEY_NUMSLASH },
{0x38, GRUB_KEYBOARD_KEY_RIGHT_ALT},
{0x47, GRUB_KEYBOARD_KEY_HOME},
{0x48, GRUB_KEYBOARD_KEY_UP},
{0x49, GRUB_KEYBOARD_KEY_PPAGE},
{0x4b, GRUB_KEYBOARD_KEY_LEFT},
{0x4d, GRUB_KEYBOARD_KEY_RIGHT},
{0x4f, GRUB_KEYBOARD_KEY_END},
{0x50, GRUB_KEYBOARD_KEY_DOWN},
{0x51, GRUB_KEYBOARD_KEY_NPAGE},
{0x52, GRUB_KEYBOARD_KEY_INSERT},
{0x53, GRUB_KEYBOARD_KEY_DELETE},
};
static const grub_uint8_t set2_mapping[256] =
{
/* 0x00 */ 0, GRUB_KEYBOARD_KEY_F9,
/* 0x02 */ 0, GRUB_KEYBOARD_KEY_F5,
/* 0x04 */ GRUB_KEYBOARD_KEY_F3, GRUB_KEYBOARD_KEY_F1,
/* 0x06 */ GRUB_KEYBOARD_KEY_F2, GRUB_KEYBOARD_KEY_F12,
/* 0x08 */ 0, GRUB_KEYBOARD_KEY_F10,
/* 0x0a */ GRUB_KEYBOARD_KEY_F8, GRUB_KEYBOARD_KEY_F6,
/* 0x0c */ GRUB_KEYBOARD_KEY_F4, GRUB_KEYBOARD_KEY_TAB,
/* 0x0e */ GRUB_KEYBOARD_KEY_RQUOTE, 0,
/* 0x10 */ 0, GRUB_KEYBOARD_KEY_LEFT_ALT,
/* 0x12 */ GRUB_KEYBOARD_KEY_LEFT_SHIFT, 0,
/* 0x14 */ GRUB_KEYBOARD_KEY_LEFT_CTRL, GRUB_KEYBOARD_KEY_Q,
/* 0x16 */ GRUB_KEYBOARD_KEY_1, 0,
/* 0x18 */ 0, 0,
/* 0x1a */ GRUB_KEYBOARD_KEY_Z, GRUB_KEYBOARD_KEY_S,
/* 0x1c */ GRUB_KEYBOARD_KEY_A, GRUB_KEYBOARD_KEY_W,
/* 0x1e */ GRUB_KEYBOARD_KEY_2, 0,
/* 0x20 */ 0, GRUB_KEYBOARD_KEY_C,
/* 0x22 */ GRUB_KEYBOARD_KEY_X, GRUB_KEYBOARD_KEY_D,
/* 0x24 */ GRUB_KEYBOARD_KEY_E, GRUB_KEYBOARD_KEY_4,
/* 0x26 */ GRUB_KEYBOARD_KEY_3, 0,
/* 0x28 */ 0, GRUB_KEYBOARD_KEY_SPACE,
/* 0x2a */ GRUB_KEYBOARD_KEY_V, GRUB_KEYBOARD_KEY_F,
/* 0x2c */ GRUB_KEYBOARD_KEY_T, GRUB_KEYBOARD_KEY_R,
/* 0x2e */ GRUB_KEYBOARD_KEY_5, 0,
/* 0x30 */ 0, GRUB_KEYBOARD_KEY_N,
/* 0x32 */ GRUB_KEYBOARD_KEY_B, GRUB_KEYBOARD_KEY_H,
/* 0x34 */ GRUB_KEYBOARD_KEY_G, GRUB_KEYBOARD_KEY_Y,
/* 0x36 */ GRUB_KEYBOARD_KEY_6, 0,
/* 0x38 */ 0, 0,
/* 0x3a */ GRUB_KEYBOARD_KEY_M, GRUB_KEYBOARD_KEY_J,
/* 0x3c */ GRUB_KEYBOARD_KEY_U, GRUB_KEYBOARD_KEY_7,
/* 0x3e */ GRUB_KEYBOARD_KEY_8, 0,
/* 0x40 */ 0, GRUB_KEYBOARD_KEY_COMMA,
/* 0x42 */ GRUB_KEYBOARD_KEY_K, GRUB_KEYBOARD_KEY_I,
/* 0x44 */ GRUB_KEYBOARD_KEY_O, GRUB_KEYBOARD_KEY_0,
/* 0x46 */ GRUB_KEYBOARD_KEY_9, 0,
/* 0x48 */ 0, GRUB_KEYBOARD_KEY_DOT,
/* 0x4a */ GRUB_KEYBOARD_KEY_SLASH, GRUB_KEYBOARD_KEY_L,
/* 0x4c */ GRUB_KEYBOARD_KEY_SEMICOLON, GRUB_KEYBOARD_KEY_P,
/* 0x4e */ GRUB_KEYBOARD_KEY_DASH, 0,
/* 0x50 */ 0, GRUB_KEYBOARD_KEY_JP_RO,
/* 0x52 */ GRUB_KEYBOARD_KEY_DQUOTE, 0,
/* 0x54 */ GRUB_KEYBOARD_KEY_LBRACKET, GRUB_KEYBOARD_KEY_EQUAL,
/* 0x56 */ 0, 0,
/* 0x58 */ GRUB_KEYBOARD_KEY_CAPS_LOCK, GRUB_KEYBOARD_KEY_RIGHT_SHIFT,
/* 0x5a */ GRUB_KEYBOARD_KEY_ENTER, GRUB_KEYBOARD_KEY_RBRACKET,
/* 0x5c */ 0, GRUB_KEYBOARD_KEY_BACKSLASH,
/* 0x5e */ 0, 0,
/* 0x60 */ 0, GRUB_KEYBOARD_KEY_102ND,
/* 0x62 */ 0, 0,
/* 0x64 */ 0, 0,
/* 0x66 */ GRUB_KEYBOARD_KEY_BACKSPACE, 0,
/* 0x68 */ 0, GRUB_KEYBOARD_KEY_NUM1,
/* 0x6a */ GRUB_KEYBOARD_KEY_JP_YEN, GRUB_KEYBOARD_KEY_NUM4,
/* 0x6c */ GRUB_KEYBOARD_KEY_NUM7, GRUB_KEYBOARD_KEY_KPCOMMA,
/* 0x6e */ 0, 0,
/* 0x70 */ GRUB_KEYBOARD_KEY_NUMDOT, GRUB_KEYBOARD_KEY_NUM0,
/* 0x72 */ GRUB_KEYBOARD_KEY_NUM2, GRUB_KEYBOARD_KEY_NUM5,
/* 0x74 */ GRUB_KEYBOARD_KEY_NUM6, GRUB_KEYBOARD_KEY_NUM8,
/* 0x76 */ GRUB_KEYBOARD_KEY_ESCAPE, GRUB_KEYBOARD_KEY_NUM_LOCK,
/* 0x78 */ GRUB_KEYBOARD_KEY_F11, GRUB_KEYBOARD_KEY_NUMPLUS,
/* 0x7a */ GRUB_KEYBOARD_KEY_NUM3, GRUB_KEYBOARD_KEY_NUMMINUS,
/* 0x7c */ GRUB_KEYBOARD_KEY_NUMMUL, GRUB_KEYBOARD_KEY_NUM9,
/* 0x7e */ GRUB_KEYBOARD_KEY_SCROLL_LOCK, 0,
/* 0x80 */ 0, 0,
/* 0x82 */ 0, GRUB_KEYBOARD_KEY_F7,
};
static const struct
{
grub_uint8_t from, to;
} set2_e0_mapping[] =
{
{0x11, GRUB_KEYBOARD_KEY_RIGHT_ALT},
{0x14, GRUB_KEYBOARD_KEY_RIGHT_CTRL},
{0x4a, GRUB_KEYBOARD_KEY_NUMSLASH},
{0x5a, GRUB_KEYBOARD_KEY_NUMENTER},
{0x69, GRUB_KEYBOARD_KEY_END},
{0x6b, GRUB_KEYBOARD_KEY_LEFT},
{0x6c, GRUB_KEYBOARD_KEY_HOME},
{0x70, GRUB_KEYBOARD_KEY_INSERT},
{0x71, GRUB_KEYBOARD_KEY_DELETE},
{0x72, GRUB_KEYBOARD_KEY_DOWN},
{0x74, GRUB_KEYBOARD_KEY_RIGHT},
{0x75, GRUB_KEYBOARD_KEY_UP},
{0x7a, GRUB_KEYBOARD_KEY_NPAGE},
{0x7d, GRUB_KEYBOARD_KEY_PPAGE},
};
static int ping_sent;
static void static void
keyboard_controller_wait_until_ready (void) keyboard_controller_wait_until_ready (void)
{ {
@@ -350,12 +159,12 @@ set_scancodes (void)
if (!grub_keyboard_orig_set) if (!grub_keyboard_orig_set)
{ {
grub_dprintf ("atkeyb", "No sets support assumed\n"); grub_dprintf ("atkeyb", "No sets support assumed\n");
current_set = 1; ps2_state.current_set = 1;
return; return;
} }
#if !USE_SCANCODE_SET #if !USE_SCANCODE_SET
current_set = 1; ps2_state.current_set = 1;
return; return;
#else #else
@@ -363,15 +172,15 @@ set_scancodes (void)
& ~KEYBOARD_AT_TRANSLATE); & ~KEYBOARD_AT_TRANSLATE);
write_mode (2); write_mode (2);
current_set = query_mode (); ps2_state.current_set = query_mode ();
grub_dprintf ("atkeyb", "returned set %d\n", current_set); grub_dprintf ("atkeyb", "returned set %d\n", ps2_state.current_set);
if (current_set == 2) if (ps2_state.current_set == 2)
return; return;
write_mode (1); write_mode (1);
current_set = query_mode (); ps2_state.current_set = query_mode ();
grub_dprintf ("atkeyb", "returned set %d\n", current_set); grub_dprintf ("atkeyb", "returned set %d\n", ps2_state.current_set);
if (current_set == 1) if (ps2_state.current_set == 1)
return; return;
grub_dprintf ("atkeyb", "no supported scancode set found\n"); grub_dprintf ("atkeyb", "no supported scancode set found\n");
#endif #endif
@@ -386,164 +195,10 @@ keyboard_controller_led (grub_uint8_t leds)
grub_outb (leds & 0x7, KEYBOARD_REG_DATA); grub_outb (leds & 0x7, KEYBOARD_REG_DATA);
} }
static int
fetch_key (int *is_break)
{
int was_ext = 0;
grub_uint8_t at_key;
int ret = 0;
if (! KEYBOARD_ISREADY (grub_inb (KEYBOARD_REG_STATUS)))
return -1;
at_key = grub_inb (KEYBOARD_REG_DATA);
/* May happen if no keyboard is connected. Just ignore this. */
if (at_key == 0xff)
return -1;
if (at_key == 0xe0)
{
e0_received = 1;
return -1;
}
if ((current_set == 2 || current_set == 3) && at_key == 0xf0)
{
f0_received = 1;
return -1;
}
/* Setting LEDs may generate ACKs. */
if (at_key == GRUB_AT_ACK)
return -1;
was_ext = e0_received;
e0_received = 0;
switch (current_set)
{
case 1:
*is_break = !!(at_key & 0x80);
if (!was_ext)
ret = set1_mapping[at_key & 0x7f];
else
{
unsigned i;
for (i = 0; i < ARRAY_SIZE (set1_e0_mapping); i++)
if (set1_e0_mapping[i].from == (at_key & 0x7f))
{
ret = set1_e0_mapping[i].to;
break;
}
}
break;
case 2:
*is_break = f0_received;
f0_received = 0;
if (!was_ext)
ret = set2_mapping[at_key];
else
{
unsigned i;
for (i = 0; i < ARRAY_SIZE (set2_e0_mapping); i++)
if (set2_e0_mapping[i].from == at_key)
{
ret = set2_e0_mapping[i].to;
break;
}
}
break;
default:
return -1;
}
if (!ret)
{
if (was_ext)
grub_dprintf ("atkeyb", "Unknown key 0xe0+0x%02x from set %d\n",
at_key, current_set);
else
grub_dprintf ("atkeyb", "Unknown key 0x%02x from set %d\n",
at_key, current_set);
return -1;
}
return ret;
}
/* FIXME: This should become an interrupt service routine. For now
it's just used to catch events from control keys. */
static int
grub_keyboard_isr (grub_keyboard_key_t key, int is_break)
{
if (!is_break)
switch (key)
{
case GRUB_KEYBOARD_KEY_LEFT_SHIFT:
at_keyboard_status |= GRUB_TERM_STATUS_LSHIFT;
return 1;
case GRUB_KEYBOARD_KEY_RIGHT_SHIFT:
at_keyboard_status |= GRUB_TERM_STATUS_RSHIFT;
return 1;
case GRUB_KEYBOARD_KEY_LEFT_CTRL:
at_keyboard_status |= GRUB_TERM_STATUS_LCTRL;
return 1;
case GRUB_KEYBOARD_KEY_RIGHT_CTRL:
at_keyboard_status |= GRUB_TERM_STATUS_RCTRL;
return 1;
case GRUB_KEYBOARD_KEY_RIGHT_ALT:
at_keyboard_status |= GRUB_TERM_STATUS_RALT;
return 1;
case GRUB_KEYBOARD_KEY_LEFT_ALT:
at_keyboard_status |= GRUB_TERM_STATUS_LALT;
return 1;
default:
return 0;
}
else
switch (key)
{
case GRUB_KEYBOARD_KEY_LEFT_SHIFT:
at_keyboard_status &= ~GRUB_TERM_STATUS_LSHIFT;
return 1;
case GRUB_KEYBOARD_KEY_RIGHT_SHIFT:
at_keyboard_status &= ~GRUB_TERM_STATUS_RSHIFT;
return 1;
case GRUB_KEYBOARD_KEY_LEFT_CTRL:
at_keyboard_status &= ~GRUB_TERM_STATUS_LCTRL;
return 1;
case GRUB_KEYBOARD_KEY_RIGHT_CTRL:
at_keyboard_status &= ~GRUB_TERM_STATUS_RCTRL;
return 1;
case GRUB_KEYBOARD_KEY_RIGHT_ALT:
at_keyboard_status &= ~GRUB_TERM_STATUS_RALT;
return 1;
case GRUB_KEYBOARD_KEY_LEFT_ALT:
at_keyboard_status &= ~GRUB_TERM_STATUS_LALT;
return 1;
default:
return 0;
}
}
/* If there is a raw key pending, return it; otherwise return -1. */
static int
grub_keyboard_getkey (void)
{
int key;
int is_break = 0;
key = fetch_key (&is_break);
if (key == -1)
return -1;
if (grub_keyboard_isr (key, is_break))
return -1;
if (is_break)
return -1;
return key;
}
int int
grub_at_keyboard_is_alive (void) grub_at_keyboard_is_alive (void)
{ {
if (current_set != 0) if (ps2_state.current_set != 0)
return 1; return 1;
if (ping_sent if (ping_sent
&& KEYBOARD_COMMAND_ISREADY (grub_inb (KEYBOARD_REG_STATUS)) && KEYBOARD_COMMAND_ISREADY (grub_inb (KEYBOARD_REG_STATUS))
@@ -566,51 +221,28 @@ grub_at_keyboard_is_alive (void)
static int static int
grub_at_keyboard_getkey (struct grub_term_input *term __attribute__ ((unused))) grub_at_keyboard_getkey (struct grub_term_input *term __attribute__ ((unused)))
{ {
int code; grub_uint8_t at_key;
int ret;
grub_uint8_t old_led;
if (!grub_at_keyboard_is_alive ()) if (!grub_at_keyboard_is_alive ())
return GRUB_TERM_NO_KEY; return GRUB_TERM_NO_KEY;
code = grub_keyboard_getkey (); if (! KEYBOARD_ISREADY (grub_inb (KEYBOARD_REG_STATUS)))
if (code == -1) return -1;
return GRUB_TERM_NO_KEY; at_key = grub_inb (KEYBOARD_REG_DATA);
#ifdef DEBUG_AT_KEYBOARD old_led = ps2_state.led_status;
grub_dprintf ("atkeyb", "Detected key 0x%x\n", code);
#endif
switch (code)
{
case GRUB_KEYBOARD_KEY_CAPS_LOCK:
at_keyboard_status ^= GRUB_TERM_STATUS_CAPS;
led_status ^= KEYBOARD_LED_CAPS;
keyboard_controller_led (led_status);
#ifdef DEBUG_AT_KEYBOARD ret = grub_ps2_process_incoming_byte (&ps2_state, at_key);
grub_dprintf ("atkeyb", "caps_lock = %d\n", !!(at_keyboard_status & GRUB_KEYBOARD_STATUS_CAPS_LOCK)); if (old_led != ps2_state.led_status)
#endif keyboard_controller_led (ps2_state.led_status);
return GRUB_TERM_NO_KEY; return ret;
case GRUB_KEYBOARD_KEY_NUM_LOCK:
at_keyboard_status ^= GRUB_TERM_STATUS_NUM;
led_status ^= KEYBOARD_LED_NUM;
keyboard_controller_led (led_status);
#ifdef DEBUG_AT_KEYBOARD
grub_dprintf ("atkeyb", "num_lock = %d\n", !!(at_keyboard_status & GRUB_KEYBOARD_STATUS_NUM_LOCK));
#endif
return GRUB_TERM_NO_KEY;
case GRUB_KEYBOARD_KEY_SCROLL_LOCK:
at_keyboard_status ^= GRUB_TERM_STATUS_SCROLL;
led_status ^= KEYBOARD_LED_SCROLL;
keyboard_controller_led (led_status);
return GRUB_TERM_NO_KEY;
default:
return grub_term_map_key (code, at_keyboard_status);
}
} }
static void static void
grub_keyboard_controller_init (void) grub_keyboard_controller_init (void)
{ {
at_keyboard_status = 0; ps2_state.at_keyboard_status = 0;
/* Drain input buffer. */ /* Drain input buffer. */
while (1) while (1)
{ {
@@ -632,13 +264,13 @@ grub_keyboard_controller_init (void)
grub_keyboard_orig_set = query_mode (); grub_keyboard_orig_set = query_mode ();
#endif #endif
set_scancodes (); set_scancodes ();
keyboard_controller_led (led_status); keyboard_controller_led (ps2_state.led_status);
} }
static grub_err_t static grub_err_t
grub_keyboard_controller_fini (struct grub_term_input *term __attribute__ ((unused))) grub_keyboard_controller_fini (struct grub_term_input *term __attribute__ ((unused)))
{ {
if (current_set == 0) if (ps2_state.current_set == 0)
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
if (grub_keyboard_orig_set) if (grub_keyboard_orig_set)
write_mode (grub_keyboard_orig_set); write_mode (grub_keyboard_orig_set);
@@ -655,7 +287,7 @@ grub_at_fini_hw (int noreturn __attribute__ ((unused)))
static grub_err_t static grub_err_t
grub_at_restore_hw (void) grub_at_restore_hw (void)
{ {
if (current_set == 0) if (ps2_state.current_set == 0)
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
/* Drain input buffer. */ /* Drain input buffer. */
@@ -668,7 +300,7 @@ grub_at_restore_hw (void)
grub_inb (KEYBOARD_REG_DATA); grub_inb (KEYBOARD_REG_DATA);
} }
set_scancodes (); set_scancodes ();
keyboard_controller_led (led_status); keyboard_controller_led (ps2_state.led_status);
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
} }
+1 -1
View File
@@ -23,7 +23,7 @@
#include <grub/time.h> #include <grub/time.h>
#include <grub/terminfo.h> #include <grub/terminfo.h>
#include <grub/dl.h> #include <grub/dl.h>
#include <grub/i386/coreboot/lbio.h> #include <grub/coreboot/lbio.h>
#include <grub/command.h> #include <grub/command.h>
#include <grub/normal.h> #include <grub/normal.h>
+387
View File
@@ -0,0 +1,387 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2007,2008,2009 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* 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/dl.h>
#include <grub/misc.h>
#include <grub/term.h>
#include <grub/keyboard_layouts.h>
#include <grub/ps2.h>
#define KEYBOARD_LED_SCROLL (1 << 0)
#define KEYBOARD_LED_NUM (1 << 1)
#define KEYBOARD_LED_CAPS (1 << 2)
static const grub_uint8_t set1_mapping[128] =
{
/* 0x00 */ 0 /* Unused */, GRUB_KEYBOARD_KEY_ESCAPE,
/* 0x02 */ GRUB_KEYBOARD_KEY_1, GRUB_KEYBOARD_KEY_2,
/* 0x04 */ GRUB_KEYBOARD_KEY_3, GRUB_KEYBOARD_KEY_4,
/* 0x06 */ GRUB_KEYBOARD_KEY_5, GRUB_KEYBOARD_KEY_6,
/* 0x08 */ GRUB_KEYBOARD_KEY_7, GRUB_KEYBOARD_KEY_8,
/* 0x0a */ GRUB_KEYBOARD_KEY_9, GRUB_KEYBOARD_KEY_0,
/* 0x0c */ GRUB_KEYBOARD_KEY_DASH, GRUB_KEYBOARD_KEY_EQUAL,
/* 0x0e */ GRUB_KEYBOARD_KEY_BACKSPACE, GRUB_KEYBOARD_KEY_TAB,
/* 0x10 */ GRUB_KEYBOARD_KEY_Q, GRUB_KEYBOARD_KEY_W,
/* 0x12 */ GRUB_KEYBOARD_KEY_E, GRUB_KEYBOARD_KEY_R,
/* 0x14 */ GRUB_KEYBOARD_KEY_T, GRUB_KEYBOARD_KEY_Y,
/* 0x16 */ GRUB_KEYBOARD_KEY_U, GRUB_KEYBOARD_KEY_I,
/* 0x18 */ GRUB_KEYBOARD_KEY_O, GRUB_KEYBOARD_KEY_P,
/* 0x1a */ GRUB_KEYBOARD_KEY_LBRACKET, GRUB_KEYBOARD_KEY_RBRACKET,
/* 0x1c */ GRUB_KEYBOARD_KEY_ENTER, GRUB_KEYBOARD_KEY_LEFT_CTRL,
/* 0x1e */ GRUB_KEYBOARD_KEY_A, GRUB_KEYBOARD_KEY_S,
/* 0x20 */ GRUB_KEYBOARD_KEY_D, GRUB_KEYBOARD_KEY_F,
/* 0x22 */ GRUB_KEYBOARD_KEY_G, GRUB_KEYBOARD_KEY_H,
/* 0x24 */ GRUB_KEYBOARD_KEY_J, GRUB_KEYBOARD_KEY_K,
/* 0x26 */ GRUB_KEYBOARD_KEY_L, GRUB_KEYBOARD_KEY_SEMICOLON,
/* 0x28 */ GRUB_KEYBOARD_KEY_DQUOTE, GRUB_KEYBOARD_KEY_RQUOTE,
/* 0x2a */ GRUB_KEYBOARD_KEY_LEFT_SHIFT, GRUB_KEYBOARD_KEY_BACKSLASH,
/* 0x2c */ GRUB_KEYBOARD_KEY_Z, GRUB_KEYBOARD_KEY_X,
/* 0x2e */ GRUB_KEYBOARD_KEY_C, GRUB_KEYBOARD_KEY_V,
/* 0x30 */ GRUB_KEYBOARD_KEY_B, GRUB_KEYBOARD_KEY_N,
/* 0x32 */ GRUB_KEYBOARD_KEY_M, GRUB_KEYBOARD_KEY_COMMA,
/* 0x34 */ GRUB_KEYBOARD_KEY_DOT, GRUB_KEYBOARD_KEY_SLASH,
/* 0x36 */ GRUB_KEYBOARD_KEY_RIGHT_SHIFT, GRUB_KEYBOARD_KEY_NUMMUL,
/* 0x38 */ GRUB_KEYBOARD_KEY_LEFT_ALT, GRUB_KEYBOARD_KEY_SPACE,
/* 0x3a */ GRUB_KEYBOARD_KEY_CAPS_LOCK, GRUB_KEYBOARD_KEY_F1,
/* 0x3c */ GRUB_KEYBOARD_KEY_F2, GRUB_KEYBOARD_KEY_F3,
/* 0x3e */ GRUB_KEYBOARD_KEY_F4, GRUB_KEYBOARD_KEY_F5,
/* 0x40 */ GRUB_KEYBOARD_KEY_F6, GRUB_KEYBOARD_KEY_F7,
/* 0x42 */ GRUB_KEYBOARD_KEY_F8, GRUB_KEYBOARD_KEY_F9,
/* 0x44 */ GRUB_KEYBOARD_KEY_F10, GRUB_KEYBOARD_KEY_NUM_LOCK,
/* 0x46 */ GRUB_KEYBOARD_KEY_SCROLL_LOCK, GRUB_KEYBOARD_KEY_NUM7,
/* 0x48 */ GRUB_KEYBOARD_KEY_NUM8, GRUB_KEYBOARD_KEY_NUM9,
/* 0x4a */ GRUB_KEYBOARD_KEY_NUMMINUS, GRUB_KEYBOARD_KEY_NUM4,
/* 0x4c */ GRUB_KEYBOARD_KEY_NUM5, GRUB_KEYBOARD_KEY_NUM6,
/* 0x4e */ GRUB_KEYBOARD_KEY_NUMPLUS, GRUB_KEYBOARD_KEY_NUM1,
/* 0x50 */ GRUB_KEYBOARD_KEY_NUM2, GRUB_KEYBOARD_KEY_NUM3,
/* 0x52 */ GRUB_KEYBOARD_KEY_NUMDOT, GRUB_KEYBOARD_KEY_NUMDOT,
/* 0x54 */ 0, 0,
/* 0x56 */ GRUB_KEYBOARD_KEY_102ND, GRUB_KEYBOARD_KEY_F11,
/* 0x58 */ GRUB_KEYBOARD_KEY_F12, 0,
/* 0x5a */ 0, 0,
/* 0x5c */ 0, 0,
/* 0x5e */ 0, 0,
/* 0x60 */ 0, 0,
/* 0x62 */ 0, 0,
/* OLPC keys. Just mapped to normal keys. */
/* 0x64 */ 0, GRUB_KEYBOARD_KEY_UP,
/* 0x66 */ GRUB_KEYBOARD_KEY_DOWN, GRUB_KEYBOARD_KEY_LEFT,
/* 0x68 */ GRUB_KEYBOARD_KEY_RIGHT, 0,
/* 0x6a */ 0, 0,
/* 0x6c */ 0, 0,
/* 0x6e */ 0, 0,
/* 0x70 */ 0, 0,
/* 0x72 */ 0, GRUB_KEYBOARD_KEY_JP_RO,
/* 0x74 */ 0, 0,
/* 0x76 */ 0, 0,
/* 0x78 */ 0, 0,
/* 0x7a */ 0, 0,
/* 0x7c */ 0, GRUB_KEYBOARD_KEY_JP_YEN,
/* 0x7e */ GRUB_KEYBOARD_KEY_KPCOMMA
};
static const struct
{
grub_uint8_t from, to;
} set1_e0_mapping[] =
{
{0x1c, GRUB_KEYBOARD_KEY_NUMENTER},
{0x1d, GRUB_KEYBOARD_KEY_RIGHT_CTRL},
{0x35, GRUB_KEYBOARD_KEY_NUMSLASH },
{0x38, GRUB_KEYBOARD_KEY_RIGHT_ALT},
{0x47, GRUB_KEYBOARD_KEY_HOME},
{0x48, GRUB_KEYBOARD_KEY_UP},
{0x49, GRUB_KEYBOARD_KEY_PPAGE},
{0x4b, GRUB_KEYBOARD_KEY_LEFT},
{0x4d, GRUB_KEYBOARD_KEY_RIGHT},
{0x4f, GRUB_KEYBOARD_KEY_END},
{0x50, GRUB_KEYBOARD_KEY_DOWN},
{0x51, GRUB_KEYBOARD_KEY_NPAGE},
{0x52, GRUB_KEYBOARD_KEY_INSERT},
{0x53, GRUB_KEYBOARD_KEY_DELETE},
};
static const grub_uint8_t set2_mapping[256] =
{
/* 0x00 */ 0, GRUB_KEYBOARD_KEY_F9,
/* 0x02 */ 0, GRUB_KEYBOARD_KEY_F5,
/* 0x04 */ GRUB_KEYBOARD_KEY_F3, GRUB_KEYBOARD_KEY_F1,
/* 0x06 */ GRUB_KEYBOARD_KEY_F2, GRUB_KEYBOARD_KEY_F12,
/* 0x08 */ 0, GRUB_KEYBOARD_KEY_F10,
/* 0x0a */ GRUB_KEYBOARD_KEY_F8, GRUB_KEYBOARD_KEY_F6,
/* 0x0c */ GRUB_KEYBOARD_KEY_F4, GRUB_KEYBOARD_KEY_TAB,
/* 0x0e */ GRUB_KEYBOARD_KEY_RQUOTE, 0,
/* 0x10 */ 0, GRUB_KEYBOARD_KEY_LEFT_ALT,
/* 0x12 */ GRUB_KEYBOARD_KEY_LEFT_SHIFT, 0,
/* 0x14 */ GRUB_KEYBOARD_KEY_LEFT_CTRL, GRUB_KEYBOARD_KEY_Q,
/* 0x16 */ GRUB_KEYBOARD_KEY_1, 0,
/* 0x18 */ 0, 0,
/* 0x1a */ GRUB_KEYBOARD_KEY_Z, GRUB_KEYBOARD_KEY_S,
/* 0x1c */ GRUB_KEYBOARD_KEY_A, GRUB_KEYBOARD_KEY_W,
/* 0x1e */ GRUB_KEYBOARD_KEY_2, 0,
/* 0x20 */ 0, GRUB_KEYBOARD_KEY_C,
/* 0x22 */ GRUB_KEYBOARD_KEY_X, GRUB_KEYBOARD_KEY_D,
/* 0x24 */ GRUB_KEYBOARD_KEY_E, GRUB_KEYBOARD_KEY_4,
/* 0x26 */ GRUB_KEYBOARD_KEY_3, 0,
/* 0x28 */ 0, GRUB_KEYBOARD_KEY_SPACE,
/* 0x2a */ GRUB_KEYBOARD_KEY_V, GRUB_KEYBOARD_KEY_F,
/* 0x2c */ GRUB_KEYBOARD_KEY_T, GRUB_KEYBOARD_KEY_R,
/* 0x2e */ GRUB_KEYBOARD_KEY_5, 0,
/* 0x30 */ 0, GRUB_KEYBOARD_KEY_N,
/* 0x32 */ GRUB_KEYBOARD_KEY_B, GRUB_KEYBOARD_KEY_H,
/* 0x34 */ GRUB_KEYBOARD_KEY_G, GRUB_KEYBOARD_KEY_Y,
/* 0x36 */ GRUB_KEYBOARD_KEY_6, 0,
/* 0x38 */ 0, 0,
/* 0x3a */ GRUB_KEYBOARD_KEY_M, GRUB_KEYBOARD_KEY_J,
/* 0x3c */ GRUB_KEYBOARD_KEY_U, GRUB_KEYBOARD_KEY_7,
/* 0x3e */ GRUB_KEYBOARD_KEY_8, 0,
/* 0x40 */ 0, GRUB_KEYBOARD_KEY_COMMA,
/* 0x42 */ GRUB_KEYBOARD_KEY_K, GRUB_KEYBOARD_KEY_I,
/* 0x44 */ GRUB_KEYBOARD_KEY_O, GRUB_KEYBOARD_KEY_0,
/* 0x46 */ GRUB_KEYBOARD_KEY_9, 0,
/* 0x48 */ 0, GRUB_KEYBOARD_KEY_DOT,
/* 0x4a */ GRUB_KEYBOARD_KEY_SLASH, GRUB_KEYBOARD_KEY_L,
/* 0x4c */ GRUB_KEYBOARD_KEY_SEMICOLON, GRUB_KEYBOARD_KEY_P,
/* 0x4e */ GRUB_KEYBOARD_KEY_DASH, 0,
/* 0x50 */ 0, GRUB_KEYBOARD_KEY_JP_RO,
/* 0x52 */ GRUB_KEYBOARD_KEY_DQUOTE, 0,
/* 0x54 */ GRUB_KEYBOARD_KEY_LBRACKET, GRUB_KEYBOARD_KEY_EQUAL,
/* 0x56 */ 0, 0,
/* 0x58 */ GRUB_KEYBOARD_KEY_CAPS_LOCK, GRUB_KEYBOARD_KEY_RIGHT_SHIFT,
/* 0x5a */ GRUB_KEYBOARD_KEY_ENTER, GRUB_KEYBOARD_KEY_RBRACKET,
/* 0x5c */ 0, GRUB_KEYBOARD_KEY_BACKSLASH,
/* 0x5e */ 0, 0,
/* 0x60 */ 0, GRUB_KEYBOARD_KEY_102ND,
/* 0x62 */ 0, 0,
/* 0x64 */ 0, 0,
/* 0x66 */ GRUB_KEYBOARD_KEY_BACKSPACE, 0,
/* 0x68 */ 0, GRUB_KEYBOARD_KEY_NUM1,
/* 0x6a */ GRUB_KEYBOARD_KEY_JP_YEN, GRUB_KEYBOARD_KEY_NUM4,
/* 0x6c */ GRUB_KEYBOARD_KEY_NUM7, GRUB_KEYBOARD_KEY_KPCOMMA,
/* 0x6e */ 0, 0,
/* 0x70 */ GRUB_KEYBOARD_KEY_NUMDOT, GRUB_KEYBOARD_KEY_NUM0,
/* 0x72 */ GRUB_KEYBOARD_KEY_NUM2, GRUB_KEYBOARD_KEY_NUM5,
/* 0x74 */ GRUB_KEYBOARD_KEY_NUM6, GRUB_KEYBOARD_KEY_NUM8,
/* 0x76 */ GRUB_KEYBOARD_KEY_ESCAPE, GRUB_KEYBOARD_KEY_NUM_LOCK,
/* 0x78 */ GRUB_KEYBOARD_KEY_F11, GRUB_KEYBOARD_KEY_NUMPLUS,
/* 0x7a */ GRUB_KEYBOARD_KEY_NUM3, GRUB_KEYBOARD_KEY_NUMMINUS,
/* 0x7c */ GRUB_KEYBOARD_KEY_NUMMUL, GRUB_KEYBOARD_KEY_NUM9,
/* 0x7e */ GRUB_KEYBOARD_KEY_SCROLL_LOCK, 0,
/* 0x80 */ 0, 0,
/* 0x82 */ 0, GRUB_KEYBOARD_KEY_F7,
};
static const struct
{
grub_uint8_t from, to;
} set2_e0_mapping[] =
{
{0x11, GRUB_KEYBOARD_KEY_RIGHT_ALT},
{0x14, GRUB_KEYBOARD_KEY_RIGHT_CTRL},
{0x4a, GRUB_KEYBOARD_KEY_NUMSLASH},
{0x5a, GRUB_KEYBOARD_KEY_NUMENTER},
{0x69, GRUB_KEYBOARD_KEY_END},
{0x6b, GRUB_KEYBOARD_KEY_LEFT},
{0x6c, GRUB_KEYBOARD_KEY_HOME},
{0x70, GRUB_KEYBOARD_KEY_INSERT},
{0x71, GRUB_KEYBOARD_KEY_DELETE},
{0x72, GRUB_KEYBOARD_KEY_DOWN},
{0x74, GRUB_KEYBOARD_KEY_RIGHT},
{0x75, GRUB_KEYBOARD_KEY_UP},
{0x7a, GRUB_KEYBOARD_KEY_NPAGE},
{0x7d, GRUB_KEYBOARD_KEY_PPAGE},
};
static int
fetch_key (struct grub_ps2_state *ps2_state, grub_uint8_t at_key, int *is_break)
{
int was_ext = 0;
int ret = 0;
/* May happen if no keyboard is connected. Just ignore this. */
if (at_key == 0xff)
return -1;
if (at_key == 0xe0)
{
ps2_state->e0_received = 1;
return -1;
}
if ((ps2_state->current_set == 2 || ps2_state->current_set == 3) && at_key == 0xf0)
{
ps2_state->f0_received = 1;
return -1;
}
/* Setting LEDs may generate ACKs. */
if (at_key == GRUB_AT_ACK)
return -1;
was_ext = ps2_state->e0_received;
ps2_state->e0_received = 0;
switch (ps2_state->current_set)
{
case 1:
*is_break = !!(at_key & 0x80);
if (!was_ext)
ret = set1_mapping[at_key & 0x7f];
else
{
unsigned i;
for (i = 0; i < ARRAY_SIZE (set1_e0_mapping); i++)
if (set1_e0_mapping[i].from == (at_key & 0x7f))
{
ret = set1_e0_mapping[i].to;
break;
}
}
break;
case 2:
*is_break = ps2_state->f0_received;
ps2_state->f0_received = 0;
if (!was_ext)
ret = set2_mapping[at_key];
else
{
unsigned i;
for (i = 0; i < ARRAY_SIZE (set2_e0_mapping); i++)
if (set2_e0_mapping[i].from == at_key)
{
ret = set2_e0_mapping[i].to;
break;
}
}
break;
default:
return -1;
}
if (!ret)
{
if (was_ext)
grub_dprintf ("atkeyb", "Unknown key 0xe0+0x%02x from set %d\n",
at_key, ps2_state->current_set);
else
grub_dprintf ("atkeyb", "Unknown key 0x%02x from set %d\n",
at_key, ps2_state->current_set);
return -1;
}
return ret;
}
/* FIXME: This should become an interrupt service routine. For now
it's just used to catch events from control keys. */
static int
grub_keyboard_isr (struct grub_ps2_state *ps2_state,
grub_keyboard_key_t key, int is_break)
{
if (!is_break)
switch (key)
{
case GRUB_KEYBOARD_KEY_LEFT_SHIFT:
ps2_state->at_keyboard_status |= GRUB_TERM_STATUS_LSHIFT;
return 1;
case GRUB_KEYBOARD_KEY_RIGHT_SHIFT:
ps2_state->at_keyboard_status |= GRUB_TERM_STATUS_RSHIFT;
return 1;
case GRUB_KEYBOARD_KEY_LEFT_CTRL:
ps2_state->at_keyboard_status |= GRUB_TERM_STATUS_LCTRL;
return 1;
case GRUB_KEYBOARD_KEY_RIGHT_CTRL:
ps2_state->at_keyboard_status |= GRUB_TERM_STATUS_RCTRL;
return 1;
case GRUB_KEYBOARD_KEY_RIGHT_ALT:
ps2_state->at_keyboard_status |= GRUB_TERM_STATUS_RALT;
return 1;
case GRUB_KEYBOARD_KEY_LEFT_ALT:
ps2_state->at_keyboard_status |= GRUB_TERM_STATUS_LALT;
return 1;
default:
return 0;
}
else
switch (key)
{
case GRUB_KEYBOARD_KEY_LEFT_SHIFT:
ps2_state->at_keyboard_status &= ~GRUB_TERM_STATUS_LSHIFT;
return 1;
case GRUB_KEYBOARD_KEY_RIGHT_SHIFT:
ps2_state->at_keyboard_status &= ~GRUB_TERM_STATUS_RSHIFT;
return 1;
case GRUB_KEYBOARD_KEY_LEFT_CTRL:
ps2_state->at_keyboard_status &= ~GRUB_TERM_STATUS_LCTRL;
return 1;
case GRUB_KEYBOARD_KEY_RIGHT_CTRL:
ps2_state->at_keyboard_status &= ~GRUB_TERM_STATUS_RCTRL;
return 1;
case GRUB_KEYBOARD_KEY_RIGHT_ALT:
ps2_state->at_keyboard_status &= ~GRUB_TERM_STATUS_RALT;
return 1;
case GRUB_KEYBOARD_KEY_LEFT_ALT:
ps2_state->at_keyboard_status &= ~GRUB_TERM_STATUS_LALT;
return 1;
default:
return 0;
}
}
/* If there is a key pending, return it; otherwise return GRUB_TERM_NO_KEY. */
int
grub_ps2_process_incoming_byte (struct grub_ps2_state *ps2_state,
grub_uint8_t at_key)
{
int code;
int is_break = 0;
code = fetch_key (ps2_state, at_key, &is_break);
if (code == -1)
return GRUB_TERM_NO_KEY;
if (grub_keyboard_isr (ps2_state, code, is_break))
return GRUB_TERM_NO_KEY;
if (is_break)
return GRUB_TERM_NO_KEY;
#ifdef DEBUG_AT_KEYBOARD
grub_dprintf ("atkeyb", "Detected key 0x%x\n", code);
#endif
switch (code)
{
case GRUB_KEYBOARD_KEY_CAPS_LOCK:
ps2_state->at_keyboard_status ^= GRUB_TERM_STATUS_CAPS;
ps2_state->led_status ^= KEYBOARD_LED_CAPS;
#ifdef DEBUG_AT_KEYBOARD
grub_dprintf ("atkeyb", "caps_lock = %d\n", !!(ps2_state->at_keyboard_status & GRUB_KEYBOARD_STATUS_CAPS_LOCK));
#endif
return GRUB_TERM_NO_KEY;
case GRUB_KEYBOARD_KEY_NUM_LOCK:
ps2_state->at_keyboard_status ^= GRUB_TERM_STATUS_NUM;
ps2_state->led_status ^= KEYBOARD_LED_NUM;
#ifdef DEBUG_AT_KEYBOARD
grub_dprintf ("atkeyb", "num_lock = %d\n", !!(ps2_state->at_keyboard_status & GRUB_KEYBOARD_STATUS_NUM_LOCK));
#endif
return GRUB_TERM_NO_KEY;
case GRUB_KEYBOARD_KEY_SCROLL_LOCK:
ps2_state->at_keyboard_status ^= GRUB_TERM_STATUS_SCROLL;
ps2_state->led_status ^= KEYBOARD_LED_SCROLL;
return GRUB_TERM_NO_KEY;
default:
return grub_term_map_key (code, ps2_state->at_keyboard_status);
}
}
-1
View File
@@ -19,7 +19,6 @@
#include <grub/term.h> #include <grub/term.h>
#include <grub/time.h> #include <grub/time.h>
#include <grub/cpu/io.h>
#include <grub/misc.h> #include <grub/misc.h>
#include <grub/term.h> #include <grub/term.h>
#include <grub/usb.h> #include <grub/usb.h>
@@ -25,7 +25,7 @@
#include <grub/mm.h> #include <grub/mm.h>
#include <grub/video.h> #include <grub/video.h>
#include <grub/video_fb.h> #include <grub/video_fb.h>
#include <grub/machine/lbio.h> #include <grub/coreboot/lbio.h>
#include <grub/machine/console.h> #include <grub/machine/console.h>
struct grub_linuxbios_table_framebuffer *grub_video_coreboot_fbtable; struct grub_linuxbios_table_framebuffer *grub_video_coreboot_fbtable;
+29
View File
@@ -0,0 +1,29 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2009 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* 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/>.
*/
#ifndef GRUB_MACHINE_CONSOLE_HEADER
#define GRUB_MACHINE_CONSOLE_HEADER 1
void grub_video_coreboot_fb_init (void);
void grub_video_coreboot_fb_early_init (void);
void grub_video_coreboot_fb_late_init (void);
void grub_video_coreboot_fb_fini (void);
extern struct grub_linuxbios_table_framebuffer *grub_video_coreboot_fbtable;
#endif /* ! GRUB_MACHINE_CONSOLE_HEADER */
+44
View File
@@ -0,0 +1,44 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2013 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* 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/>.
*/
#ifndef GRUB_KERNEL_MACHINE_HEADER
#define GRUB_KERNEL_MACHINE_HEADER 1
#ifndef ASM_FILE
#include <grub/symbol.h>
#include <grub/types.h>
struct grub_fdt_board
{
const char *vendor, *part;
const grub_uint8_t *dtb;
grub_size_t dtb_size;
};
extern struct grub_fdt_board grub_fdt_boards[];
void grub_machine_timer_init (void);
void grub_pl050_init (void);
void
grub_cros_init (void);
extern grub_addr_t EXPORT_VAR (start_of_ram);
#endif /* ! ASM_FILE */
#define GRUB_KERNEL_MACHINE_STACK_SIZE GRUB_KERNEL_ARM_STACK_SIZE
#endif /* ! GRUB_KERNEL_MACHINE_HEADER */
View File
Whitespace-only changes.
+16
View File
@@ -0,0 +1,16 @@
#ifndef GRUB_ARM_CROS_EC_H
#define GRUB_ARM_CROS_EC_H 1
#include <grub/types.h>
#define GRUB_CROS_EC_KEYSCAN_COLS 13
#define GRUB_CROS_EC_KEYSCAN_ROWS 8
struct grub_cros_ec_keyscan {
grub_uint8_t data[GRUB_CROS_EC_KEYSCAN_COLS];
};
int
grub_cros_ec_scan_keyboard(struct grub_cros_ec_keyscan *scan);
#endif
+18 -2
View File
@@ -25,7 +25,7 @@
#include "system.h" #include "system.h"
#if defined GRUB_MACHINE_UBOOT #if defined (GRUB_MACHINE_UBOOT)
# include <grub/uboot/uboot.h> # include <grub/uboot/uboot.h>
# define LINUX_ADDRESS (start_of_ram + 0x8000) # define LINUX_ADDRESS (start_of_ram + 0x8000)
# define LINUX_INITRD_ADDRESS (start_of_ram + 0x02000000) # define LINUX_INITRD_ADDRESS (start_of_ram + 0x02000000)
@@ -40,7 +40,7 @@
# define LINUX_PHYS_OFFSET (0x00008000) # define LINUX_PHYS_OFFSET (0x00008000)
# define LINUX_INITRD_PHYS_OFFSET (LINUX_PHYS_OFFSET + 0x02000000) # define LINUX_INITRD_PHYS_OFFSET (LINUX_PHYS_OFFSET + 0x02000000)
# define LINUX_FDT_PHYS_OFFSET (LINUX_INITRD_PHYS_OFFSET - 0x10000) # define LINUX_FDT_PHYS_OFFSET (LINUX_INITRD_PHYS_OFFSET - 0x10000)
static inline grub_addr_t static inline const void *
grub_arm_firmware_get_boot_data (void) grub_arm_firmware_get_boot_data (void)
{ {
return 0; return 0;
@@ -50,6 +50,22 @@ grub_arm_firmware_get_machine_type (void)
{ {
return GRUB_ARM_MACHINE_TYPE_FDT; return GRUB_ARM_MACHINE_TYPE_FDT;
} }
#elif defined (GRUB_MACHINE_COREBOOT)
#include <grub/fdtbus.h>
#include <grub/machine/kernel.h>
# define LINUX_ADDRESS (start_of_ram + 0x8000)
# define LINUX_INITRD_ADDRESS (start_of_ram + 0x02000000)
# define LINUX_FDT_ADDRESS (LINUX_INITRD_ADDRESS - 0x10000)
static inline const void *
grub_arm_firmware_get_boot_data (void)
{
return grub_fdtbus_get_fdt ();
}
static inline grub_uint32_t
grub_arm_firmware_get_machine_type (void)
{
return GRUB_ARM_MACHINE_TYPE_FDT;
}
#endif #endif
#define FDT_ADDITIONAL_ENTRIES_SIZE 0x300 #define FDT_ADDITIONAL_ENTRIES_SIZE 0x300
+16
View File
@@ -0,0 +1,16 @@
#ifndef GRUB_STARTUP_CPU_HEADER
#define GRUB_STARTUP_CPU_HEADER
struct grub_arm_startup_registers
{
/* registers 0-11 */
/* for U-boot r[1] is machine type */
/* for U-boot r[2] is boot data */
grub_uint32_t r[12];
grub_uint32_t sp;
grub_uint32_t lr;
};
extern struct grub_arm_startup_registers grub_arm_saved_registers;
#endif
+1 -1
View File
@@ -26,7 +26,7 @@
#endif /* ! ASM_FILE */ #endif /* ! ASM_FILE */
#define GRUB_KERNEL_MACHINE_STACK_SIZE 0x40000 #define GRUB_KERNEL_MACHINE_STACK_SIZE GRUB_KERNEL_ARM_STACK_SIZE
#define GRUB_KERNEL_MACHINE_HEAP_SIZE (grub_size_t) (16 * 1024 * 1024) #define GRUB_KERNEL_MACHINE_HEAP_SIZE (grub_size_t) (16 * 1024 * 1024)
#endif /* ! GRUB_KERNEL_MACHINE_HEADER */ #endif /* ! GRUB_KERNEL_MACHINE_HEADER */
-4
View File
@@ -27,10 +27,6 @@
#define KEYBOARD_AT_TRANSLATE 0x40 #define KEYBOARD_AT_TRANSLATE 0x40
#define GRUB_AT_ACK 0xfa
#define GRUB_AT_NACK 0xfe
#define GRUB_AT_TRIES 5
#define KEYBOARD_ISMAKE(x) !((x) & 0x80) #define KEYBOARD_ISMAKE(x) !((x) & 0x80)
#define KEYBOARD_ISREADY(x) ((x) & 0x01) #define KEYBOARD_ISREADY(x) ((x) & 0x01)
#define KEYBOARD_SCANCODE(x) ((x) & 0x7f) #define KEYBOARD_SCANCODE(x) ((x) & 0x7f)
+3 -3
View File
@@ -34,14 +34,14 @@ void EXPORT_FUNC(grub_arch_sync_caches) (void *address, grub_size_t len);
#endif #endif
#ifndef GRUB_MACHINE_EMU #ifndef GRUB_MACHINE_EMU
#ifdef _mips #if defined (__i386__) || defined (__x86_64__)
void EXPORT_FUNC(grub_arch_sync_dma_caches) (void *address, grub_size_t len);
#else
static inline void static inline void
grub_arch_sync_dma_caches (void *address __attribute__ ((unused)), grub_arch_sync_dma_caches (void *address __attribute__ ((unused)),
grub_size_t len __attribute__ ((unused))) grub_size_t len __attribute__ ((unused)))
{ {
} }
#else
void EXPORT_FUNC(grub_arch_sync_dma_caches) (volatile void *address, grub_size_t len);
#endif #endif
#endif #endif
@@ -20,6 +20,9 @@
#ifndef _GRUB_MACHINE_LBIO_HEADER #ifndef _GRUB_MACHINE_LBIO_HEADER
#define _GRUB_MACHINE_LBIO_HEADER 1 #define _GRUB_MACHINE_LBIO_HEADER 1
#include <grub/types.h>
#include <grub/err.h>
struct grub_linuxbios_table_header struct grub_linuxbios_table_header
{ {
grub_uint8_t signature[4]; grub_uint8_t signature[4];
@@ -68,7 +71,8 @@ enum
GRUB_LINUXBIOS_MEMBER_LINK = 0x11, GRUB_LINUXBIOS_MEMBER_LINK = 0x11,
GRUB_LINUXBIOS_MEMBER_FRAMEBUFFER = 0x12, GRUB_LINUXBIOS_MEMBER_FRAMEBUFFER = 0x12,
GRUB_LINUXBIOS_MEMBER_TIMESTAMPS = 0x16, GRUB_LINUXBIOS_MEMBER_TIMESTAMPS = 0x16,
GRUB_LINUXBIOS_MEMBER_CBMEMC = 0x17 GRUB_LINUXBIOS_MEMBER_CBMEMC = 0x17,
GRUB_LINUXBIOS_MEMBER_DTB = 0x33,
}; };
struct grub_linuxbios_table_framebuffer { struct grub_linuxbios_table_framebuffer {
+44
View File
@@ -0,0 +1,44 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2008,2009 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* 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/>.
*/
#ifndef GRUB_DMA_H
#define GRUB_DMA_H 1
struct grub_pci_dma_chunk;
struct grub_pci_dma_chunk *EXPORT_FUNC(grub_memalign_dma32) (grub_size_t align,
grub_size_t size);
void EXPORT_FUNC(grub_dma_free) (struct grub_pci_dma_chunk *ch);
volatile void *EXPORT_FUNC(grub_dma_get_virt) (struct grub_pci_dma_chunk *ch);
grub_uint32_t EXPORT_FUNC(grub_dma_get_phys) (struct grub_pci_dma_chunk *ch);
static inline void *
grub_dma_phys2virt (grub_uint32_t phys, struct grub_pci_dma_chunk *chunk)
{
return ((grub_uint8_t *) grub_dma_get_virt (chunk)
+ (phys - grub_dma_get_phys (chunk)));
}
static inline grub_uint32_t
grub_dma_virt2phys (volatile void *virt, struct grub_pci_dma_chunk *chunk)
{
return (((grub_uint8_t *) virt - (grub_uint8_t *) grub_dma_get_virt (chunk))
+ grub_dma_get_phys (chunk));
}
#endif
+13 -6
View File
@@ -20,6 +20,7 @@
#define GRUB_FDT_HEADER 1 #define GRUB_FDT_HEADER 1
#include <grub/types.h> #include <grub/types.h>
#include <grub/symbol.h>
#define FDT_MAGIC 0xD00DFEED #define FDT_MAGIC 0xD00DFEED
@@ -95,15 +96,21 @@ struct grub_fdt_empty_tree {
#define grub_fdt_set_size_dt_struct(fdt, value) \ #define grub_fdt_set_size_dt_struct(fdt, value) \
grub_fdt_set_header(fdt, size_dt_struct, value) grub_fdt_set_header(fdt, size_dt_struct, value)
int grub_fdt_create_empty_tree (void *fdt, unsigned int size); int EXPORT_FUNC(grub_fdt_create_empty_tree) (void *fdt, unsigned int size);
int grub_fdt_check_header (void *fdt, unsigned int size); int EXPORT_FUNC(grub_fdt_check_header) (const void *fdt, unsigned int size);
int grub_fdt_check_header_nosize (void *fdt); int EXPORT_FUNC(grub_fdt_check_header_nosize) (const void *fdt);
int grub_fdt_find_subnode (const void *fdt, unsigned int parentoffset, int EXPORT_FUNC(grub_fdt_find_subnode) (const void *fdt, unsigned int parentoffset,
const char *name); const char *name);
int grub_fdt_add_subnode (void *fdt, unsigned int parentoffset, int EXPORT_FUNC(grub_fdt_first_node) (const void *fdt, unsigned int parentoffset);
int EXPORT_FUNC(grub_fdt_next_node) (const void *fdt, unsigned int currentoffset);
int EXPORT_FUNC(grub_fdt_add_subnode) (void *fdt, unsigned int parentoffset,
const char *name); const char *name);
const char *
EXPORT_FUNC(grub_fdt_get_nodename) (const void *fdt, unsigned int nodeoffset);
const void *EXPORT_FUNC(grub_fdt_get_prop) (const void *fdt, unsigned int nodeoffset, const char *name,
grub_uint32_t *len);
int grub_fdt_set_prop (void *fdt, unsigned int nodeoffset, const char *name, int EXPORT_FUNC(grub_fdt_set_prop) (void *fdt, unsigned int nodeoffset, const char *name,
const void *val, grub_uint32_t len); const void *val, grub_uint32_t len);
#define grub_fdt_set_prop32(fdt, nodeoffset, name, val) \ #define grub_fdt_set_prop32(fdt, nodeoffset, name, val) \
({ \ ({ \
+73
View File
@@ -0,0 +1,73 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2016 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* 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/>.
*/
#ifndef GRUB_FDTBUS_HEADER
#define GRUB_FDTBUS_HEADER 1
#include <grub/fdt.h>
#include <grub/err.h>
struct grub_fdtbus_dev;
struct grub_fdtbus_driver
{
struct grub_fdtbus_driver *next;
struct grub_fdtbus_driver **prev;
const char *compatible;
grub_err_t (*attach) (const struct grub_fdtbus_dev *dev);
void (*detach) (const struct grub_fdtbus_dev *dev);
};
extern char EXPORT_VAR(grub_fdtbus_invalid_mapping)[1];
static inline int
grub_fdtbus_is_mapping_valid (volatile void *m)
{
return m != grub_fdtbus_invalid_mapping;
}
volatile void *
EXPORT_FUNC(grub_fdtbus_map_reg) (const struct grub_fdtbus_dev *dev, int reg, grub_size_t *size);
const void *
EXPORT_FUNC(grub_fdtbus_get_fdt) (void);
const char *
EXPORT_FUNC(grub_fdtbus_get_name) (const struct grub_fdtbus_dev *dev);
const void *
EXPORT_FUNC(grub_fdtbus_get_prop) (const struct grub_fdtbus_dev *dev,
const char *name,
grub_uint32_t *len);
void
EXPORT_FUNC(grub_fdtbus_register) (struct grub_fdtbus_driver *driver);
void
EXPORT_FUNC(grub_fdtbus_unregister) (struct grub_fdtbus_driver *driver);
/* Must be called before any register(). */
/* dtb is assumed to be unfreeable and must remain
valid for lifetime of GRUB.
*/
void
grub_fdtbus_init (const void *dtb, grub_size_t size);
#endif
+2 -1
View File
@@ -28,7 +28,8 @@ enum
OBJ_TYPE_MEMDISK, OBJ_TYPE_MEMDISK,
OBJ_TYPE_CONFIG, OBJ_TYPE_CONFIG,
OBJ_TYPE_PREFIX, OBJ_TYPE_PREFIX,
OBJ_TYPE_PUBKEY OBJ_TYPE_PUBKEY,
OBJ_TYPE_DTB
}; };
/* The module header. */ /* The module header. */
+5 -1
View File
@@ -120,7 +120,11 @@
#define GRUB_KERNEL_ARM_UBOOT_MOD_ALIGN 0x8 #define GRUB_KERNEL_ARM_UBOOT_MOD_ALIGN 0x8
#define GRUB_KERNEL_ARM_UBOOT_TOTAL_MODULE_SIZE 0x4 #define GRUB_KERNEL_ARM_UBOOT_TOTAL_MODULE_SIZE 0x4
#define GRUB_KERNEL_ARM_UBOOT_LINK_ADDR 0x08000000 #define GRUB_KERNEL_ARM_COREBOOT_MOD_ALIGN 0x8
#define GRUB_KERNEL_ARM_COREBOOT_TOTAL_MODULE_SIZE 0x4
#define GRUB_KERNEL_ARM_STACK_SIZE 0x40000
#define GRUB_KERNEL_ARM_COREBOOT_MOD_GAP (GRUB_KERNEL_ARM_STACK_SIZE + 1024)
/* Minimal gap between _end and the start of the modules. It's a hack /* Minimal gap between _end and the start of the modules. It's a hack
for PowerMac to prevent "CLAIM failed" error. The real fix is to for PowerMac to prevent "CLAIM failed" error. The real fix is to
+1 -21
View File
@@ -142,27 +142,7 @@ grub_pci_address_t EXPORT_FUNC(grub_pci_make_address) (grub_pci_device_t dev,
void EXPORT_FUNC(grub_pci_iterate) (grub_pci_iteratefunc_t hook, void EXPORT_FUNC(grub_pci_iterate) (grub_pci_iteratefunc_t hook,
void *hook_data); void *hook_data);
struct grub_pci_dma_chunk; #include <grub/dma.h>
struct grub_pci_dma_chunk *EXPORT_FUNC(grub_memalign_dma32) (grub_size_t align,
grub_size_t size);
void EXPORT_FUNC(grub_dma_free) (struct grub_pci_dma_chunk *ch);
volatile void *EXPORT_FUNC(grub_dma_get_virt) (struct grub_pci_dma_chunk *ch);
grub_uint32_t EXPORT_FUNC(grub_dma_get_phys) (struct grub_pci_dma_chunk *ch);
static inline void *
grub_dma_phys2virt (grub_uint32_t phys, struct grub_pci_dma_chunk *chunk)
{
return ((grub_uint8_t *) grub_dma_get_virt (chunk)
+ (phys - grub_dma_get_phys (chunk)));
}
static inline grub_uint32_t
grub_dma_virt2phys (volatile void *virt, struct grub_pci_dma_chunk *chunk)
{
return (((grub_uint8_t *) virt - (grub_uint8_t *) grub_dma_get_virt (chunk))
+ grub_dma_get_phys (chunk));
}
grub_uint8_t grub_uint8_t
EXPORT_FUNC (grub_pci_find_capability) (grub_pci_device_t dev, grub_uint8_t cap); EXPORT_FUNC (grub_pci_find_capability) (grub_pci_device_t dev, grub_uint8_t cap);
+43
View File
@@ -0,0 +1,43 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2007,2008,2009 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* 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/>.
*/
#ifndef GRUB_PS2_HEADER
#define GRUB_PS2_HEADER 1
#include <grub/types.h>
#define GRUB_AT_ACK 0xfa
#define GRUB_AT_NACK 0xfe
#define GRUB_AT_TRIES 5
/* Make sure it's zeroed-out and set current_set at init. */
struct grub_ps2_state
{
int e0_received;
int f0_received;
grub_uint8_t led_status;
short at_keyboard_status;
grub_uint8_t current_set;
};
/* If there is a key pending, return it; otherwise return GRUB_TERM_NO_KEY. */
int
grub_ps2_process_incoming_byte (struct grub_ps2_state *ps2_state,
grub_uint8_t data);
#endif
+1 -1
View File
@@ -37,7 +37,7 @@ grub_err_t grub_uboot_probe_hardware (void);
extern grub_addr_t EXPORT_VAR (start_of_ram); extern grub_addr_t EXPORT_VAR (start_of_ram);
grub_uint32_t EXPORT_FUNC (grub_uboot_get_machine_type) (void); grub_uint32_t EXPORT_FUNC (grub_uboot_get_machine_type) (void);
grub_addr_t EXPORT_FUNC (grub_uboot_get_boot_data) (void); const void *EXPORT_FUNC (grub_uboot_get_boot_data) (void);
/* /*
+9 -2
View File
@@ -116,8 +116,7 @@ struct grub_usb_controller_dev
int (*hubports) (grub_usb_controller_t dev); int (*hubports) (grub_usb_controller_t dev);
grub_usb_err_t (*portstatus) (grub_usb_controller_t dev, unsigned int port, grub_usb_err_t (*reset_port) (grub_usb_controller_t dev, unsigned int port);
unsigned int enable);
grub_usb_speed_t (*detect_dev) (grub_usb_controller_t dev, int port, int *changed); grub_usb_speed_t (*detect_dev) (grub_usb_controller_t dev, int port, int *changed);
@@ -321,5 +320,13 @@ grub_usb_err_t
grub_usb_check_transfer (grub_usb_transfer_t trans, grub_size_t *actual); grub_usb_check_transfer (grub_usb_transfer_t trans, grub_size_t *actual);
void void
grub_usb_cancel_transfer (grub_usb_transfer_t trans); grub_usb_cancel_transfer (grub_usb_transfer_t trans);
void
grub_ehci_init_device (volatile void *regs);
void
grub_ehci_pci_scan (void);
void
grub_dwc2_init_device (volatile void *regs);
void
grub_dwc2_pci_scan (void);
#endif /* GRUB_USB_H */ #endif /* GRUB_USB_H */
+1 -1
View File
@@ -176,7 +176,7 @@ grub_install_generate_image (const char *dir, const char *prefix,
char *config_path, char *config_path,
const struct grub_install_image_target_desc *image_target, const struct grub_install_image_target_desc *image_target,
int note, int note,
grub_compression_t comp); grub_compression_t comp, const char *dtb_file);
const struct grub_install_image_target_desc * const struct grub_install_image_target_desc *
grub_install_get_image_target (const char *arg); grub_install_get_image_target (const char *arg);
+185
View File
@@ -0,0 +1,185 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2013 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* 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/>.
*/
#ifndef GRUB_UTIL_MKIMAGE_HEADER
#define GRUB_UTIL_MKIMAGE_HEADER 1
struct grub_mkimage_layout
{
size_t exec_size;
size_t kernel_size;
size_t bss_size;
grub_uint64_t start_address;
void *reloc_section;
size_t reloc_size;
size_t align;
grub_size_t ia64jmp_off;
grub_size_t tramp_off;
grub_size_t ia64_got_off;
grub_size_t got_size;
unsigned ia64jmpnum;
grub_uint32_t bss_start;
grub_uint32_t end;
};
/* Private header. Use only in mkimage-related sources. */
char *
grub_mkimage_load_image32 (const char *kernel_path,
size_t total_module_size,
struct grub_mkimage_layout *layout,
const struct grub_install_image_target_desc *image_target);
char *
grub_mkimage_load_image64 (const char *kernel_path,
size_t total_module_size,
struct grub_mkimage_layout *layout,
const struct grub_install_image_target_desc *image_target);
void
grub_mkimage_generate_elf32 (const struct grub_install_image_target_desc *image_target,
int note, char **core_img, size_t *core_size,
Elf32_Addr target_addr,
struct grub_mkimage_layout *layout);
void
grub_mkimage_generate_elf64 (const struct grub_install_image_target_desc *image_target,
int note, char **core_img, size_t *core_size,
Elf64_Addr target_addr,
struct grub_mkimage_layout *layout);
struct grub_install_image_target_desc
{
const char *dirname;
const char *names[6];
grub_size_t voidp_sizeof;
int bigendian;
enum {
IMAGE_I386_PC, IMAGE_EFI, IMAGE_COREBOOT,
IMAGE_SPARC64_AOUT, IMAGE_SPARC64_RAW, IMAGE_SPARC64_CDCORE,
IMAGE_I386_IEEE1275,
IMAGE_LOONGSON_ELF, IMAGE_QEMU, IMAGE_PPC, IMAGE_YEELOONG_FLASH,
IMAGE_FULOONG2F_FLASH, IMAGE_I386_PC_PXE, IMAGE_MIPS_ARC,
IMAGE_QEMU_MIPS_FLASH, IMAGE_UBOOT, IMAGE_XEN, IMAGE_I386_PC_ELTORITO
} id;
enum
{
PLATFORM_FLAGS_NONE = 0,
PLATFORM_FLAGS_DECOMPRESSORS = 2,
PLATFORM_FLAGS_MODULES_BEFORE_KERNEL = 4,
} flags;
unsigned total_module_size;
unsigned decompressor_compressed_size;
unsigned decompressor_uncompressed_size;
unsigned decompressor_uncompressed_addr;
unsigned reloc_table_offset;
unsigned link_align;
grub_uint16_t elf_target;
unsigned section_align;
signed vaddr_offset;
grub_uint64_t link_addr;
unsigned mod_gap, mod_align;
grub_compression_t default_compression;
grub_uint16_t pe_target;
};
#define grub_target_to_host32(x) (grub_target_to_host32_real (image_target, (x)))
#define grub_host_to_target32(x) (grub_host_to_target32_real (image_target, (x)))
#define grub_target_to_host64(x) (grub_target_to_host64_real (image_target, (x)))
#define grub_host_to_target64(x) (grub_host_to_target64_real (image_target, (x)))
#define grub_host_to_target_addr(x) (grub_host_to_target_addr_real (image_target, (x)))
#define grub_target_to_host16(x) (grub_target_to_host16_real (image_target, (x)))
#define grub_host_to_target16(x) (grub_host_to_target16_real (image_target, (x)))
static inline grub_uint32_t
grub_target_to_host32_real (const struct grub_install_image_target_desc *image_target,
grub_uint32_t in)
{
if (image_target->bigendian)
return grub_be_to_cpu32 (in);
else
return grub_le_to_cpu32 (in);
}
static inline grub_uint64_t
grub_target_to_host64_real (const struct grub_install_image_target_desc *image_target,
grub_uint64_t in)
{
if (image_target->bigendian)
return grub_be_to_cpu64 (in);
else
return grub_le_to_cpu64 (in);
}
static inline grub_uint64_t
grub_host_to_target64_real (const struct grub_install_image_target_desc *image_target,
grub_uint64_t in)
{
if (image_target->bigendian)
return grub_cpu_to_be64 (in);
else
return grub_cpu_to_le64 (in);
}
static inline grub_uint32_t
grub_host_to_target32_real (const struct grub_install_image_target_desc *image_target,
grub_uint32_t in)
{
if (image_target->bigendian)
return grub_cpu_to_be32 (in);
else
return grub_cpu_to_le32 (in);
}
static inline grub_uint16_t
grub_target_to_host16_real (const struct grub_install_image_target_desc *image_target,
grub_uint16_t in)
{
if (image_target->bigendian)
return grub_be_to_cpu16 (in);
else
return grub_le_to_cpu16 (in);
}
static inline grub_uint16_t
grub_host_to_target16_real (const struct grub_install_image_target_desc *image_target,
grub_uint16_t in)
{
if (image_target->bigendian)
return grub_cpu_to_be16 (in);
else
return grub_cpu_to_le16 (in);
}
static inline grub_uint64_t
grub_host_to_target_addr_real (const struct grub_install_image_target_desc *image_target, grub_uint64_t in)
{
if (image_target->voidp_sizeof == 8)
return grub_host_to_target64_real (image_target, in);
else
return grub_host_to_target32_real (image_target, in);
}
static inline grub_uint64_t
grub_target_to_host_real (const struct grub_install_image_target_desc *image_target, grub_uint64_t in)
{
if (image_target->voidp_sizeof == 8)
return grub_target_to_host64_real (image_target, in);
else
return grub_target_to_host32_real (image_target, in);
}
#define grub_target_to_host(val) grub_target_to_host_real(image_target, (val))
#endif
+1 -1
View File
@@ -499,7 +499,7 @@ grub_install_make_image_wrap_file (const char *dir, const char *prefix,
grub_install_generate_image (dir, prefix, fp, outname, grub_install_generate_image (dir, prefix, fp, outname,
modules.entries, memdisk_path, modules.entries, memdisk_path,
pubkeys, npubkeys, config_path, tgt, pubkeys, npubkeys, config_path, tgt,
note, compression); note, compression, 0);
while (dc--) while (dc--)
grub_install_pop_module (); grub_install_pop_module ();
} }
+10 -1
View File
@@ -71,6 +71,7 @@ static struct argp_option options[] = {
N_("embed FILE as a memdisk image\n" N_("embed FILE as a memdisk image\n"
"Implies `-p (memdisk)/boot/grub' and overrides any prefix supplied previously," "Implies `-p (memdisk)/boot/grub' and overrides any prefix supplied previously,"
" but the prefix itself can be overridden by later options"), 0}, " but the prefix itself can be overridden by later options"), 0},
{"dtb", 'D', N_("FILE"), 0, N_("embed FILE as a device tree (DTB)\n"), 0},
/* TRANSLATORS: "embed" is a verb (command description). "*/ /* TRANSLATORS: "embed" is a verb (command description). "*/
{"config", 'c', N_("FILE"), 0, N_("embed FILE as an early config"), 0}, {"config", 'c', N_("FILE"), 0, N_("embed FILE as an early config"), 0},
/* TRANSLATORS: "embed" is a verb (command description). "*/ /* TRANSLATORS: "embed" is a verb (command description). "*/
@@ -117,6 +118,7 @@ struct arguments
char *dir; char *dir;
char *prefix; char *prefix;
char *memdisk; char *memdisk;
char *dtb;
char **pubkeys; char **pubkeys;
size_t npubkeys; size_t npubkeys;
char *font; char *font;
@@ -176,6 +178,13 @@ argp_parser (int key, char *arg, struct argp_state *state)
arguments->prefix = xstrdup ("(memdisk)/boot/grub"); arguments->prefix = xstrdup ("(memdisk)/boot/grub");
break; break;
case 'D':
if (arguments->dtb)
free (arguments->dtb);
arguments->dtb = xstrdup (arg);
break;
case 'k': case 'k':
arguments->pubkeys = xrealloc (arguments->pubkeys, arguments->pubkeys = xrealloc (arguments->pubkeys,
sizeof (arguments->pubkeys[0]) sizeof (arguments->pubkeys[0])
@@ -299,7 +308,7 @@ main (int argc, char *argv[])
arguments.memdisk, arguments.pubkeys, arguments.memdisk, arguments.pubkeys,
arguments.npubkeys, arguments.config, arguments.npubkeys, arguments.config,
arguments.image_target, arguments.note, arguments.image_target, arguments.note,
arguments.comp); arguments.comp, arguments.dtb);
grub_util_file_sync (fp); grub_util_file_sync (fp);
fclose (fp); fclose (fp);
+22
View File
@@ -0,0 +1,22 @@
#define MKIMAGE_ELF32 1
# define SUFFIX(x) x ## 32
# define ELFCLASSXX ELFCLASS32
# define Elf_Ehdr Elf32_Ehdr
# define Elf_Phdr Elf32_Phdr
# define Elf_Nhdr Elf32_Nhdr
# define Elf_Addr Elf32_Addr
# define Elf_Sym Elf32_Sym
# define Elf_Off Elf32_Off
# define Elf_Shdr Elf32_Shdr
# define Elf_Rela Elf32_Rela
# define Elf_Rel Elf32_Rel
# define Elf_Word Elf32_Word
# define Elf_Half Elf32_Half
# define Elf_Section Elf32_Section
# define ELF_R_SYM(val) ELF32_R_SYM(val)
# define ELF_R_TYPE(val) ELF32_R_TYPE(val)
# define ELF_ST_TYPE(val) ELF32_ST_TYPE(val)
#define XEN_NOTE_SIZE 132
#include "grub-mkimagexx.c"
+22
View File
@@ -0,0 +1,22 @@
#define MKIMAGE_ELF64 1
# define SUFFIX(x) x ## 64
# define ELFCLASSXX ELFCLASS64
# define Elf_Ehdr Elf64_Ehdr
# define Elf_Phdr Elf64_Phdr
# define Elf_Nhdr Elf64_Nhdr
# define Elf_Addr Elf64_Addr
# define Elf_Sym Elf64_Sym
# define Elf_Off Elf64_Off
# define Elf_Shdr Elf64_Shdr
# define Elf_Rela Elf64_Rela
# define Elf_Rel Elf64_Rel
# define Elf_Word Elf64_Word
# define Elf_Half Elf64_Half
# define Elf_Section Elf64_Section
# define ELF_R_SYM(val) ELF64_R_SYM(val)
# define ELF_R_TYPE(val) ELF64_R_TYPE(val)
# define ELF_ST_TYPE(val) ELF64_ST_TYPE(val)
#define XEN_NOTE_SIZE 120
#include "grub-mkimagexx.c"
+827 -426
View File
File diff suppressed because it is too large. Load diff
+122 -319
View File
@@ -46,6 +46,7 @@
#include <grub/ia64/reloc.h> #include <grub/ia64/reloc.h>
#include <grub/osdep/hostfile.h> #include <grub/osdep/hostfile.h>
#include <grub/util/install.h> #include <grub/util/install.h>
#include <grub/util/mkimage.h>
#define ALIGN_ADDR(x) (ALIGN_UP((x), image_target->voidp_sizeof)) #define ALIGN_ADDR(x) (ALIGN_UP((x), image_target->voidp_sizeof))
@@ -55,43 +56,11 @@
#define TARGET_NO_FIELD 0xffffffff #define TARGET_NO_FIELD 0xffffffff
#pragma GCC diagnostic ignored "-Wcast-align"
/* use 2015-01-01T00:00:00+0000 as a stock timestamp */ /* use 2015-01-01T00:00:00+0000 as a stock timestamp */
#define STABLE_EMBEDDING_TIMESTAMP 1420070400 #define STABLE_EMBEDDING_TIMESTAMP 1420070400
struct grub_install_image_target_desc
{
const char *dirname;
const char *names[6];
grub_size_t voidp_sizeof;
int bigendian;
enum {
IMAGE_I386_PC, IMAGE_EFI, IMAGE_COREBOOT,
IMAGE_SPARC64_AOUT, IMAGE_SPARC64_RAW, IMAGE_SPARC64_CDCORE,
IMAGE_I386_IEEE1275,
IMAGE_LOONGSON_ELF, IMAGE_QEMU, IMAGE_PPC, IMAGE_YEELOONG_FLASH,
IMAGE_FULOONG2F_FLASH, IMAGE_I386_PC_PXE, IMAGE_MIPS_ARC,
IMAGE_QEMU_MIPS_FLASH, IMAGE_UBOOT, IMAGE_XEN, IMAGE_I386_PC_ELTORITO
} id;
enum
{
PLATFORM_FLAGS_NONE = 0,
PLATFORM_FLAGS_DECOMPRESSORS = 2,
PLATFORM_FLAGS_MODULES_BEFORE_KERNEL = 4,
} flags;
unsigned total_module_size;
unsigned decompressor_compressed_size;
unsigned decompressor_uncompressed_size;
unsigned decompressor_uncompressed_addr;
unsigned link_align;
grub_uint16_t elf_target;
unsigned section_align;
signed vaddr_offset;
grub_uint64_t link_addr;
unsigned mod_gap, mod_align;
grub_compression_t default_compression;
grub_uint16_t pe_target;
};
#define EFI32_HEADER_SIZE ALIGN_UP (GRUB_PE32_MSDOS_STUB_SIZE \ #define EFI32_HEADER_SIZE ALIGN_UP (GRUB_PE32_MSDOS_STUB_SIZE \
+ GRUB_PE32_SIGNATURE_SIZE \ + GRUB_PE32_SIGNATURE_SIZE \
+ sizeof (struct grub_pe32_coff_header) \ + sizeof (struct grub_pe32_coff_header) \
@@ -119,6 +88,7 @@ static const struct grub_install_image_target_desc image_targets[] =
.decompressor_compressed_size = TARGET_NO_FIELD, .decompressor_compressed_size = TARGET_NO_FIELD,
.decompressor_uncompressed_size = TARGET_NO_FIELD, .decompressor_uncompressed_size = TARGET_NO_FIELD,
.decompressor_uncompressed_addr = TARGET_NO_FIELD, .decompressor_uncompressed_addr = TARGET_NO_FIELD,
.reloc_table_offset = TARGET_NO_FIELD,
.section_align = 1, .section_align = 1,
.vaddr_offset = 0, .vaddr_offset = 0,
.link_addr = GRUB_KERNEL_I386_COREBOOT_LINK_ADDR, .link_addr = GRUB_KERNEL_I386_COREBOOT_LINK_ADDR,
@@ -558,12 +528,49 @@ static const struct grub_install_image_target_desc image_targets[] =
.decompressor_uncompressed_addr = TARGET_NO_FIELD, .decompressor_uncompressed_addr = TARGET_NO_FIELD,
.section_align = GRUB_KERNEL_ARM_UBOOT_MOD_ALIGN, .section_align = GRUB_KERNEL_ARM_UBOOT_MOD_ALIGN,
.vaddr_offset = 0, .vaddr_offset = 0,
.link_addr = GRUB_KERNEL_ARM_UBOOT_LINK_ADDR,
.elf_target = EM_ARM, .elf_target = EM_ARM,
.mod_gap = GRUB_KERNEL_ARM_UBOOT_MOD_GAP, .mod_gap = GRUB_KERNEL_ARM_UBOOT_MOD_GAP,
.mod_align = GRUB_KERNEL_ARM_UBOOT_MOD_ALIGN, .mod_align = GRUB_KERNEL_ARM_UBOOT_MOD_ALIGN,
.link_align = 4 .link_align = 4
}, },
{
.dirname = "arm-coreboot",
.names = { "arm-coreboot", NULL },
.voidp_sizeof = 4,
.bigendian = 0,
.id = IMAGE_COREBOOT,
.flags = PLATFORM_FLAGS_NONE,
.total_module_size = GRUB_KERNEL_ARM_COREBOOT_TOTAL_MODULE_SIZE,
.decompressor_compressed_size = TARGET_NO_FIELD,
.decompressor_uncompressed_size = TARGET_NO_FIELD,
.decompressor_uncompressed_addr = TARGET_NO_FIELD,
.section_align = GRUB_KERNEL_ARM_COREBOOT_MOD_ALIGN,
.vaddr_offset = 0,
.elf_target = EM_ARM,
.mod_gap = GRUB_KERNEL_ARM_COREBOOT_MOD_GAP,
.mod_align = GRUB_KERNEL_ARM_COREBOOT_MOD_ALIGN,
.link_align = 4,
},
/* For coreboot versions that don't support self-relocating images. */
{
.dirname = "arm-coreboot-veyron",
.names = { "arm-coreboot-veyron", NULL },
.voidp_sizeof = 4,
.bigendian = 0,
.id = IMAGE_COREBOOT,
.flags = PLATFORM_FLAGS_NONE,
.total_module_size = GRUB_KERNEL_ARM_COREBOOT_TOTAL_MODULE_SIZE,
.decompressor_compressed_size = TARGET_NO_FIELD,
.decompressor_uncompressed_size = TARGET_NO_FIELD,
.decompressor_uncompressed_addr = TARGET_NO_FIELD,
.section_align = GRUB_KERNEL_ARM_COREBOOT_MOD_ALIGN,
.vaddr_offset = 0,
.elf_target = EM_ARM,
.mod_gap = GRUB_KERNEL_ARM_COREBOOT_MOD_GAP,
.mod_align = GRUB_KERNEL_ARM_COREBOOT_MOD_ALIGN,
.link_align = 4,
.link_addr = 0x43000000,
},
{ {
.dirname = "arm-efi", .dirname = "arm-efi",
.names = { "arm-efi", NULL }, .names = { "arm-efi", NULL },
@@ -603,119 +610,6 @@ static const struct grub_install_image_target_desc image_targets[] =
}, },
}; };
#define grub_target_to_host32(x) (grub_target_to_host32_real (image_target, (x)))
#define grub_host_to_target32(x) (grub_host_to_target32_real (image_target, (x)))
#define grub_target_to_host64(x) (grub_target_to_host64_real (image_target, (x)))
#define grub_host_to_target64(x) (grub_host_to_target64_real (image_target, (x)))
#define grub_host_to_target_addr(x) (grub_host_to_target_addr_real (image_target, (x)))
#define grub_target_to_host16(x) (grub_target_to_host16_real (image_target, (x)))
#define grub_host_to_target16(x) (grub_host_to_target16_real (image_target, (x)))
static inline grub_uint32_t
grub_target_to_host32_real (const struct grub_install_image_target_desc *image_target,
grub_uint32_t in)
{
if (image_target->bigendian)
return grub_be_to_cpu32 (in);
else
return grub_le_to_cpu32 (in);
}
static inline grub_uint64_t
grub_target_to_host64_real (const struct grub_install_image_target_desc *image_target,
grub_uint64_t in)
{
if (image_target->bigendian)
return grub_be_to_cpu64 (in);
else
return grub_le_to_cpu64 (in);
}
static inline grub_uint64_t
grub_host_to_target64_real (const struct grub_install_image_target_desc *image_target,
grub_uint64_t in)
{
if (image_target->bigendian)
return grub_cpu_to_be64 (in);
else
return grub_cpu_to_le64 (in);
}
static inline grub_uint32_t
grub_host_to_target32_real (const struct grub_install_image_target_desc *image_target,
grub_uint32_t in)
{
if (image_target->bigendian)
return grub_cpu_to_be32 (in);
else
return grub_cpu_to_le32 (in);
}
static inline grub_uint16_t
grub_target_to_host16_real (const struct grub_install_image_target_desc *image_target,
grub_uint16_t in)
{
if (image_target->bigendian)
return grub_be_to_cpu16 (in);
else
return grub_le_to_cpu16 (in);
}
static inline grub_uint16_t
grub_host_to_target16_real (const struct grub_install_image_target_desc *image_target,
grub_uint16_t in)
{
if (image_target->bigendian)
return grub_cpu_to_be16 (in);
else
return grub_cpu_to_le16 (in);
}
static inline grub_uint64_t
grub_host_to_target_addr_real (const struct grub_install_image_target_desc *image_target, grub_uint64_t in)
{
if (image_target->voidp_sizeof == 8)
return grub_host_to_target64_real (image_target, in);
else
return grub_host_to_target32_real (image_target, in);
}
static inline grub_uint64_t
grub_target_to_host_real (const struct grub_install_image_target_desc *image_target, grub_uint64_t in)
{
if (image_target->voidp_sizeof == 8)
return grub_target_to_host64_real (image_target, in);
else
return grub_target_to_host32_real (image_target, in);
}
#define GRUB_IEEE1275_NOTE_NAME "PowerPC"
#define GRUB_IEEE1275_NOTE_TYPE 0x1275
/* These structures are defined according to the CHRP binding to IEEE1275,
"Client Program Format" section. */
struct grub_ieee1275_note_desc
{
grub_uint32_t real_mode;
grub_uint32_t real_base;
grub_uint32_t real_size;
grub_uint32_t virt_base;
grub_uint32_t virt_size;
grub_uint32_t load_base;
};
struct grub_ieee1275_note
{
Elf32_Nhdr header;
char name[ALIGN_UP(sizeof (GRUB_IEEE1275_NOTE_NAME), 4)];
struct grub_ieee1275_note_desc descriptor;
};
#define GRUB_XEN_NOTE_NAME "Xen"
#define grub_target_to_host(val) grub_target_to_host_real(image_target, (val))
#include <grub/lib/LzmaEnc.h> #include <grub/lib/LzmaEnc.h>
static void *SzAlloc(void *p __attribute__ ((unused)), size_t size) { return xmalloc(size); } static void *SzAlloc(void *p __attribute__ ((unused)), size_t size) { return xmalloc(size); }
@@ -830,111 +724,6 @@ compress_kernel (const struct grub_install_image_target_desc *image_target, char
*core_size = kernel_size; *core_size = kernel_size;
} }
struct fixup_block_list
{
struct fixup_block_list *next;
int state;
struct grub_pe32_fixup_block b;
};
/*
* R_ARM_THM_CALL/THM_JUMP24
*
* Relocate Thumb (T32) instruction set relative branches:
* B.W, BL and BLX
*/
static grub_err_t
grub_arm_reloc_thm_call (grub_uint16_t *target, Elf32_Addr sym_addr)
{
grub_int32_t offset;
offset = grub_arm_thm_call_get_offset (target);
grub_dprintf ("dl", " sym_addr = 0x%08x", sym_addr);
offset += sym_addr;
grub_dprintf("dl", " BL*: target=%p, sym_addr=0x%08x, offset=%d\n",
target, sym_addr, offset);
/* Keep traditional (pre-Thumb2) limits on blx. In any case if the kernel
is bigger than 2M (currently under 150K) then we probably have a problem
somewhere else. */
if (offset < -0x200000 || offset >= 0x200000)
return grub_error (GRUB_ERR_BAD_MODULE,
"THM_CALL Relocation out of range.");
grub_dprintf ("dl", " relative destination = %p",
(char *) target + offset);
return grub_arm_thm_call_set_offset (target, offset);
}
/*
* R_ARM_THM_JUMP19
*
* Relocate conditional Thumb (T32) B<c>.W
*/
static grub_err_t
grub_arm_reloc_thm_jump19 (grub_uint16_t *target, Elf32_Addr sym_addr)
{
grub_int32_t offset;
if (!(sym_addr & 1))
return grub_error (GRUB_ERR_BAD_MODULE,
"Relocation targeting wrong execution state");
offset = grub_arm_thm_jump19_get_offset (target);
/* Adjust and re-truncate offset */
offset += sym_addr;
if (!grub_arm_thm_jump19_check_offset (offset))
return grub_error (GRUB_ERR_BAD_MODULE,
"THM_JUMP19 Relocation out of range.");
grub_arm_thm_jump19_set_offset (target, offset);
return GRUB_ERR_NONE;
}
/*
* R_ARM_JUMP24
*
* Relocate ARM (A32) B
*/
static grub_err_t
grub_arm_reloc_jump24 (grub_uint32_t *target, Elf32_Addr sym_addr)
{
grub_int32_t offset;
if (sym_addr & 1)
return grub_error (GRUB_ERR_BAD_MODULE,
"Relocation targeting wrong execution state");
offset = grub_arm_jump24_get_offset (target);
offset += sym_addr;
if (!grub_arm_jump24_check_offset (offset))
return grub_error (GRUB_ERR_BAD_MODULE,
"JUMP24 Relocation out of range.");
grub_arm_jump24_set_offset (target, offset);
return GRUB_ERR_NONE;
}
#pragma GCC diagnostic ignored "-Wcast-align"
#define MKIMAGE_ELF32 1
#include "grub-mkimagexx.c"
#undef MKIMAGE_ELF32
#define MKIMAGE_ELF64 1
#include "grub-mkimagexx.c"
#undef MKIMAGE_ELF64
const struct grub_install_image_target_desc * const struct grub_install_image_target_desc *
grub_install_get_image_target (const char *arg) grub_install_get_image_target (const char *arg)
{ {
@@ -987,21 +776,17 @@ grub_install_generate_image (const char *dir, const char *prefix,
char *memdisk_path, char **pubkey_paths, char *memdisk_path, char **pubkey_paths,
size_t npubkeys, char *config_path, size_t npubkeys, char *config_path,
const struct grub_install_image_target_desc *image_target, const struct grub_install_image_target_desc *image_target,
int note, int note, grub_compression_t comp, const char *dtb_path)
grub_compression_t comp)
{ {
char *kernel_img, *core_img; char *kernel_img, *core_img;
size_t kernel_size, total_module_size, core_size, exec_size; size_t total_module_size, core_size;
size_t memdisk_size = 0, config_size = 0; size_t memdisk_size = 0, config_size = 0;
size_t prefix_size = 0; size_t prefix_size = 0, dtb_size = 0;
char *kernel_path; char *kernel_path;
size_t offset; size_t offset;
struct grub_util_path_list *path_list, *p; struct grub_util_path_list *path_list, *p;
size_t bss_size;
grub_uint64_t start_address;
void *rel_section = 0;
size_t reloc_size = 0, align;
size_t decompress_size = 0; size_t decompress_size = 0;
struct grub_mkimage_layout layout;
if (comp == GRUB_COMPRESSION_AUTO) if (comp == GRUB_COMPRESSION_AUTO)
comp = image_target->default_compression; comp = image_target->default_compression;
@@ -1041,6 +826,12 @@ grub_install_generate_image (const char *dir, const char *prefix,
total_module_size += memdisk_size + sizeof (struct grub_module_header); total_module_size += memdisk_size + sizeof (struct grub_module_header);
} }
if (dtb_path)
{
dtb_size = ALIGN_UP(grub_util_get_image_size (dtb_path), 4);
total_module_size += dtb_size + sizeof (struct grub_module_header);
}
if (config_path) if (config_path)
{ {
config_size = ALIGN_ADDR (grub_util_get_image_size (config_path) + 1); config_size = ALIGN_ADDR (grub_util_get_image_size (config_path) + 1);
@@ -1063,15 +854,13 @@ grub_install_generate_image (const char *dir, const char *prefix,
(unsigned long long) total_module_size); (unsigned long long) total_module_size);
if (image_target->voidp_sizeof == 4) if (image_target->voidp_sizeof == 4)
kernel_img = load_image32 (kernel_path, &exec_size, &kernel_size, &bss_size, kernel_img = grub_mkimage_load_image32 (kernel_path, total_module_size,
total_module_size, &start_address, &rel_section, &layout, image_target);
&reloc_size, &align, image_target);
else else
kernel_img = load_image64 (kernel_path, &exec_size, &kernel_size, &bss_size, kernel_img = grub_mkimage_load_image64 (kernel_path, total_module_size,
total_module_size, &start_address, &rel_section, &layout, image_target);
&reloc_size, &align, image_target); if (image_target->id == IMAGE_XEN && layout.align < 4096)
if (image_target->id == IMAGE_XEN && align < 4096) layout.align = 4096;
align = 4096;
if ((image_target->flags & PLATFORM_FLAGS_DECOMPRESSORS) if ((image_target->flags & PLATFORM_FLAGS_DECOMPRESSORS)
&& (image_target->total_module_size != TARGET_NO_FIELD)) && (image_target->total_module_size != TARGET_NO_FIELD))
@@ -1080,7 +869,7 @@ grub_install_generate_image (const char *dir, const char *prefix,
if (image_target->flags & PLATFORM_FLAGS_MODULES_BEFORE_KERNEL) if (image_target->flags & PLATFORM_FLAGS_MODULES_BEFORE_KERNEL)
{ {
memmove (kernel_img + total_module_size, kernel_img, kernel_size); memmove (kernel_img + total_module_size, kernel_img, layout.kernel_size);
memset (kernel_img, 0, total_module_size); memset (kernel_img, 0, total_module_size);
} }
@@ -1091,14 +880,14 @@ grub_install_generate_image (const char *dir, const char *prefix,
if (image_target->flags & PLATFORM_FLAGS_MODULES_BEFORE_KERNEL) if (image_target->flags & PLATFORM_FLAGS_MODULES_BEFORE_KERNEL)
modinfo = (struct grub_module_info64 *) kernel_img; modinfo = (struct grub_module_info64 *) kernel_img;
else else
modinfo = (struct grub_module_info64 *) (kernel_img + kernel_size); modinfo = (struct grub_module_info64 *) (kernel_img + layout.kernel_size);
modinfo->magic = grub_host_to_target32 (GRUB_MODULE_MAGIC); modinfo->magic = grub_host_to_target32 (GRUB_MODULE_MAGIC);
modinfo->offset = grub_host_to_target_addr (sizeof (struct grub_module_info64)); modinfo->offset = grub_host_to_target_addr (sizeof (struct grub_module_info64));
modinfo->size = grub_host_to_target_addr (total_module_size); modinfo->size = grub_host_to_target_addr (total_module_size);
if (image_target->flags & PLATFORM_FLAGS_MODULES_BEFORE_KERNEL) if (image_target->flags & PLATFORM_FLAGS_MODULES_BEFORE_KERNEL)
offset = sizeof (struct grub_module_info64); offset = sizeof (struct grub_module_info64);
else else
offset = kernel_size + sizeof (struct grub_module_info64); offset = layout.kernel_size + sizeof (struct grub_module_info64);
} }
else else
{ {
@@ -1107,14 +896,14 @@ grub_install_generate_image (const char *dir, const char *prefix,
if (image_target->flags & PLATFORM_FLAGS_MODULES_BEFORE_KERNEL) if (image_target->flags & PLATFORM_FLAGS_MODULES_BEFORE_KERNEL)
modinfo = (struct grub_module_info32 *) kernel_img; modinfo = (struct grub_module_info32 *) kernel_img;
else else
modinfo = (struct grub_module_info32 *) (kernel_img + kernel_size); modinfo = (struct grub_module_info32 *) (kernel_img + layout.kernel_size);
modinfo->magic = grub_host_to_target32 (GRUB_MODULE_MAGIC); modinfo->magic = grub_host_to_target32 (GRUB_MODULE_MAGIC);
modinfo->offset = grub_host_to_target_addr (sizeof (struct grub_module_info32)); modinfo->offset = grub_host_to_target_addr (sizeof (struct grub_module_info32));
modinfo->size = grub_host_to_target_addr (total_module_size); modinfo->size = grub_host_to_target_addr (total_module_size);
if (image_target->flags & PLATFORM_FLAGS_MODULES_BEFORE_KERNEL) if (image_target->flags & PLATFORM_FLAGS_MODULES_BEFORE_KERNEL)
offset = sizeof (struct grub_module_info32); offset = sizeof (struct grub_module_info32);
else else
offset = kernel_size + sizeof (struct grub_module_info32); offset = layout.kernel_size + sizeof (struct grub_module_info32);
} }
for (p = path_list; p; p = p->next) for (p = path_list; p; p = p->next)
@@ -1165,6 +954,19 @@ grub_install_generate_image (const char *dir, const char *prefix,
offset += memdisk_size; offset += memdisk_size;
} }
if (dtb_path)
{
struct grub_module_header *header;
header = (struct grub_module_header *) (kernel_img + offset);
header->type = grub_host_to_target32 (OBJ_TYPE_DTB);
header->size = grub_host_to_target32 (dtb_size + sizeof (*header));
offset += sizeof (*header);
grub_util_load_image (dtb_path, kernel_img + offset);
offset += dtb_size;
}
if (config_path) if (config_path)
{ {
struct grub_module_header *header; struct grub_module_header *header;
@@ -1193,8 +995,8 @@ grub_install_generate_image (const char *dir, const char *prefix,
grub_util_info ("kernel_img=%p, kernel_size=0x%" GRUB_HOST_PRIxLONG_LONG, grub_util_info ("kernel_img=%p, kernel_size=0x%" GRUB_HOST_PRIxLONG_LONG,
kernel_img, kernel_img,
(unsigned long long) kernel_size); (unsigned long long) layout.kernel_size);
compress_kernel (image_target, kernel_img, kernel_size + total_module_size, compress_kernel (image_target, kernel_img, layout.kernel_size + total_module_size,
&core_img, &core_size, comp); &core_img, &core_size, comp);
free (kernel_img); free (kernel_img);
@@ -1246,7 +1048,7 @@ grub_install_generate_image (const char *dir, const char *prefix,
if (image_target->decompressor_uncompressed_size != TARGET_NO_FIELD) if (image_target->decompressor_uncompressed_size != TARGET_NO_FIELD)
*((grub_uint32_t *) (decompress_img *((grub_uint32_t *) (decompress_img
+ image_target->decompressor_uncompressed_size)) + image_target->decompressor_uncompressed_size))
= grub_host_to_target32 (kernel_size + total_module_size); = grub_host_to_target32 (layout.kernel_size + total_module_size);
if (image_target->decompressor_uncompressed_addr != TARGET_NO_FIELD) if (image_target->decompressor_uncompressed_addr != TARGET_NO_FIELD)
{ {
@@ -1279,16 +1081,17 @@ grub_install_generate_image (const char *dir, const char *prefix,
case IMAGE_I386_PC_ELTORITO: case IMAGE_I386_PC_ELTORITO:
if (GRUB_KERNEL_I386_PC_LINK_ADDR + core_size > 0x78000 if (GRUB_KERNEL_I386_PC_LINK_ADDR + core_size > 0x78000
|| (core_size > (0xffff << GRUB_DISK_SECTOR_BITS)) || (core_size > (0xffff << GRUB_DISK_SECTOR_BITS))
|| (kernel_size + bss_size + GRUB_KERNEL_I386_PC_LINK_ADDR > 0x68000)) || (layout.kernel_size + layout.bss_size
+ GRUB_KERNEL_I386_PC_LINK_ADDR > 0x68000))
grub_util_error (_("core image is too big (0x%x > 0x%x)"), grub_util_error (_("core image is too big (0x%x > 0x%x)"),
GRUB_KERNEL_I386_PC_LINK_ADDR + (unsigned) core_size, GRUB_KERNEL_I386_PC_LINK_ADDR + (unsigned) core_size,
0x78000); 0x78000);
/* fallthrough */ /* fallthrough */
case IMAGE_COREBOOT: case IMAGE_COREBOOT:
case IMAGE_QEMU: case IMAGE_QEMU:
if (kernel_size + bss_size + GRUB_KERNEL_I386_PC_LINK_ADDR > 0x68000) if (image_target->elf_target != EM_ARM && layout.kernel_size + layout.bss_size + GRUB_KERNEL_I386_PC_LINK_ADDR > 0x68000)
grub_util_error (_("kernel image is too big (0x%x > 0x%x)"), grub_util_error (_("kernel image is too big (0x%x > 0x%x)"),
(unsigned) kernel_size + (unsigned) bss_size (unsigned) layout.kernel_size + (unsigned) layout.bss_size
+ GRUB_KERNEL_I386_PC_LINK_ADDR, + GRUB_KERNEL_I386_PC_LINK_ADDR,
0x68000); 0x68000);
break; break;
@@ -1410,13 +1213,13 @@ grub_install_generate_image (const char *dir, const char *prefix,
reloc_addr = ALIGN_UP (header_size + core_size, reloc_addr = ALIGN_UP (header_size + core_size,
image_target->section_align); image_target->section_align);
pe_size = ALIGN_UP (reloc_addr + reloc_size, pe_size = ALIGN_UP (reloc_addr + layout.reloc_size,
image_target->section_align); image_target->section_align);
pe_img = xmalloc (reloc_addr + reloc_size); pe_img = xmalloc (reloc_addr + layout.reloc_size);
memset (pe_img, 0, header_size); memset (pe_img, 0, header_size);
memcpy ((char *) pe_img + header_size, core_img, core_size); memcpy ((char *) pe_img + header_size, core_img, core_size);
memset ((char *) pe_img + header_size + core_size, 0, reloc_addr - (header_size + core_size)); memset ((char *) pe_img + header_size + core_size, 0, reloc_addr - (header_size + core_size));
memcpy ((char *) pe_img + reloc_addr, rel_section, reloc_size); memcpy ((char *) pe_img + reloc_addr, layout.reloc_section, layout.reloc_size);
header = pe_img; header = pe_img;
/* The magic. */ /* The magic. */
@@ -1450,14 +1253,14 @@ grub_install_generate_image (const char *dir, const char *prefix,
(header + GRUB_PE32_MSDOS_STUB_SIZE + GRUB_PE32_SIGNATURE_SIZE (header + GRUB_PE32_MSDOS_STUB_SIZE + GRUB_PE32_SIGNATURE_SIZE
+ sizeof (struct grub_pe32_coff_header)); + sizeof (struct grub_pe32_coff_header));
o->magic = grub_host_to_target16 (GRUB_PE32_PE32_MAGIC); o->magic = grub_host_to_target16 (GRUB_PE32_PE32_MAGIC);
o->code_size = grub_host_to_target32 (exec_size); o->code_size = grub_host_to_target32 (layout.exec_size);
o->data_size = grub_cpu_to_le32 (reloc_addr - exec_size o->data_size = grub_cpu_to_le32 (reloc_addr - layout.exec_size
- header_size); - header_size);
o->bss_size = grub_cpu_to_le32 (bss_size); o->bss_size = grub_cpu_to_le32 (layout.bss_size);
o->entry_addr = grub_cpu_to_le32 (start_address); o->entry_addr = grub_cpu_to_le32 (layout.start_address);
o->code_base = grub_cpu_to_le32 (header_size); o->code_base = grub_cpu_to_le32 (header_size);
o->data_base = grub_host_to_target32 (header_size + exec_size); o->data_base = grub_host_to_target32 (header_size + layout.exec_size);
o->image_base = 0; o->image_base = 0;
o->section_alignment = grub_host_to_target32 (image_target->section_align); o->section_alignment = grub_host_to_target32 (image_target->section_align);
@@ -1475,7 +1278,7 @@ grub_install_generate_image (const char *dir, const char *prefix,
o->num_data_directories = grub_host_to_target32 (GRUB_PE32_NUM_DATA_DIRECTORIES); o->num_data_directories = grub_host_to_target32 (GRUB_PE32_NUM_DATA_DIRECTORIES);
o->base_relocation_table.rva = grub_host_to_target32 (reloc_addr); o->base_relocation_table.rva = grub_host_to_target32 (reloc_addr);
o->base_relocation_table.size = grub_host_to_target32 (reloc_size); o->base_relocation_table.size = grub_host_to_target32 (layout.reloc_size);
sections = o + 1; sections = o + 1;
} }
else else
@@ -1488,11 +1291,11 @@ grub_install_generate_image (const char *dir, const char *prefix,
(header + GRUB_PE32_MSDOS_STUB_SIZE + GRUB_PE32_SIGNATURE_SIZE (header + GRUB_PE32_MSDOS_STUB_SIZE + GRUB_PE32_SIGNATURE_SIZE
+ sizeof (struct grub_pe32_coff_header)); + sizeof (struct grub_pe32_coff_header));
o->magic = grub_host_to_target16 (GRUB_PE32_PE64_MAGIC); o->magic = grub_host_to_target16 (GRUB_PE32_PE64_MAGIC);
o->code_size = grub_host_to_target32 (exec_size); o->code_size = grub_host_to_target32 (layout.exec_size);
o->data_size = grub_cpu_to_le32 (reloc_addr - exec_size o->data_size = grub_cpu_to_le32 (reloc_addr - layout.exec_size
- header_size); - header_size);
o->bss_size = grub_cpu_to_le32 (bss_size); o->bss_size = grub_cpu_to_le32 (layout.bss_size);
o->entry_addr = grub_cpu_to_le32 (start_address); o->entry_addr = grub_cpu_to_le32 (layout.start_address);
o->code_base = grub_cpu_to_le32 (header_size); o->code_base = grub_cpu_to_le32 (header_size);
o->image_base = 0; o->image_base = 0;
o->section_alignment = grub_host_to_target32 (image_target->section_align); o->section_alignment = grub_host_to_target32 (image_target->section_align);
@@ -1511,15 +1314,15 @@ grub_install_generate_image (const char *dir, const char *prefix,
= grub_host_to_target32 (GRUB_PE32_NUM_DATA_DIRECTORIES); = grub_host_to_target32 (GRUB_PE32_NUM_DATA_DIRECTORIES);
o->base_relocation_table.rva = grub_host_to_target32 (reloc_addr); o->base_relocation_table.rva = grub_host_to_target32 (reloc_addr);
o->base_relocation_table.size = grub_host_to_target32 (reloc_size); o->base_relocation_table.size = grub_host_to_target32 (layout.reloc_size);
sections = o + 1; sections = o + 1;
} }
/* The sections. */ /* The sections. */
text_section = sections; text_section = sections;
strcpy (text_section->name, ".text"); strcpy (text_section->name, ".text");
text_section->virtual_size = grub_cpu_to_le32 (exec_size); text_section->virtual_size = grub_cpu_to_le32 (layout.exec_size);
text_section->virtual_address = grub_cpu_to_le32 (header_size); text_section->virtual_address = grub_cpu_to_le32 (header_size);
text_section->raw_data_size = grub_cpu_to_le32 (exec_size); text_section->raw_data_size = grub_cpu_to_le32 (layout.exec_size);
text_section->raw_data_offset = grub_cpu_to_le32 (header_size); text_section->raw_data_offset = grub_cpu_to_le32 (header_size);
text_section->characteristics = grub_cpu_to_le32_compile_time ( text_section->characteristics = grub_cpu_to_le32_compile_time (
GRUB_PE32_SCN_CNT_CODE GRUB_PE32_SCN_CNT_CODE
@@ -1528,10 +1331,10 @@ grub_install_generate_image (const char *dir, const char *prefix,
data_section = text_section + 1; data_section = text_section + 1;
strcpy (data_section->name, ".data"); strcpy (data_section->name, ".data");
data_section->virtual_size = grub_cpu_to_le32 (kernel_size - exec_size); data_section->virtual_size = grub_cpu_to_le32 (layout.kernel_size - layout.exec_size);
data_section->virtual_address = grub_cpu_to_le32 (header_size + exec_size); data_section->virtual_address = grub_cpu_to_le32 (header_size + layout.exec_size);
data_section->raw_data_size = grub_cpu_to_le32 (kernel_size - exec_size); data_section->raw_data_size = grub_cpu_to_le32 (layout.kernel_size - layout.exec_size);
data_section->raw_data_offset = grub_cpu_to_le32 (header_size + exec_size); data_section->raw_data_offset = grub_cpu_to_le32 (header_size + layout.exec_size);
data_section->characteristics data_section->characteristics
= grub_cpu_to_le32_compile_time (GRUB_PE32_SCN_CNT_INITIALIZED_DATA = grub_cpu_to_le32_compile_time (GRUB_PE32_SCN_CNT_INITIALIZED_DATA
| GRUB_PE32_SCN_MEM_READ | GRUB_PE32_SCN_MEM_READ
@@ -1540,8 +1343,8 @@ grub_install_generate_image (const char *dir, const char *prefix,
#if 0 #if 0
bss_section = data_section + 1; bss_section = data_section + 1;
strcpy (bss_section->name, ".bss"); strcpy (bss_section->name, ".bss");
bss_section->virtual_size = grub_cpu_to_le32 (bss_size); bss_section->virtual_size = grub_cpu_to_le32 (layout.bss_size);
bss_section->virtual_address = grub_cpu_to_le32 (header_size + kernel_size); bss_section->virtual_address = grub_cpu_to_le32 (header_size + layout.kernel_size);
bss_section->raw_data_size = 0; bss_section->raw_data_size = 0;
bss_section->raw_data_offset = 0; bss_section->raw_data_offset = 0;
bss_section->characteristics bss_section->characteristics
@@ -1554,10 +1357,10 @@ grub_install_generate_image (const char *dir, const char *prefix,
mods_section = data_section + 1; mods_section = data_section + 1;
strcpy (mods_section->name, "mods"); strcpy (mods_section->name, "mods");
mods_section->virtual_size = grub_cpu_to_le32 (reloc_addr - kernel_size - header_size); mods_section->virtual_size = grub_cpu_to_le32 (reloc_addr - layout.kernel_size - header_size);
mods_section->virtual_address = grub_cpu_to_le32 (header_size + kernel_size + bss_size); mods_section->virtual_address = grub_cpu_to_le32 (header_size + layout.kernel_size + layout.bss_size);
mods_section->raw_data_size = grub_cpu_to_le32 (reloc_addr - kernel_size - header_size); mods_section->raw_data_size = grub_cpu_to_le32 (reloc_addr - layout.kernel_size - header_size);
mods_section->raw_data_offset = grub_cpu_to_le32 (header_size + kernel_size); mods_section->raw_data_offset = grub_cpu_to_le32 (header_size + layout.kernel_size);
mods_section->characteristics mods_section->characteristics
= grub_cpu_to_le32_compile_time (GRUB_PE32_SCN_CNT_INITIALIZED_DATA = grub_cpu_to_le32_compile_time (GRUB_PE32_SCN_CNT_INITIALIZED_DATA
| GRUB_PE32_SCN_MEM_READ | GRUB_PE32_SCN_MEM_READ
@@ -1565,9 +1368,9 @@ grub_install_generate_image (const char *dir, const char *prefix,
reloc_section = mods_section + 1; reloc_section = mods_section + 1;
strcpy (reloc_section->name, ".reloc"); strcpy (reloc_section->name, ".reloc");
reloc_section->virtual_size = grub_cpu_to_le32 (reloc_size); reloc_section->virtual_size = grub_cpu_to_le32 (layout.reloc_size);
reloc_section->virtual_address = grub_cpu_to_le32 (reloc_addr + bss_size); reloc_section->virtual_address = grub_cpu_to_le32 (reloc_addr + layout.bss_size);
reloc_section->raw_data_size = grub_cpu_to_le32 (reloc_size); reloc_section->raw_data_size = grub_cpu_to_le32 (layout.reloc_size);
reloc_section->raw_data_offset = grub_cpu_to_le32 (reloc_addr); reloc_section->raw_data_offset = grub_cpu_to_le32 (reloc_addr);
reloc_section->characteristics reloc_section->characteristics
= grub_cpu_to_le32_compile_time (GRUB_PE32_SCN_CNT_INITIALIZED_DATA = grub_cpu_to_le32_compile_time (GRUB_PE32_SCN_CNT_INITIALIZED_DATA
@@ -1775,9 +1578,9 @@ grub_install_generate_image (const char *dir, const char *prefix,
hdr->ih_magic = grub_cpu_to_be32_compile_time (GRUB_UBOOT_IH_MAGIC); hdr->ih_magic = grub_cpu_to_be32_compile_time (GRUB_UBOOT_IH_MAGIC);
hdr->ih_time = grub_cpu_to_be32 (STABLE_EMBEDDING_TIMESTAMP); hdr->ih_time = grub_cpu_to_be32 (STABLE_EMBEDDING_TIMESTAMP);
hdr->ih_size = grub_cpu_to_be32 (core_size); hdr->ih_size = grub_cpu_to_be32 (core_size);
hdr->ih_load = grub_cpu_to_be32 (image_target->link_addr); hdr->ih_load = 0;
hdr->ih_ep = grub_cpu_to_be32 (image_target->link_addr); hdr->ih_ep = 0;
hdr->ih_type = GRUB_UBOOT_IH_TYPE_KERNEL; hdr->ih_type = GRUB_UBOOT_IH_TYPE_KERNEL_NOLOAD;
hdr->ih_os = GRUB_UBOOT_IH_OS_LINUX; hdr->ih_os = GRUB_UBOOT_IH_OS_LINUX;
hdr->ih_arch = GRUB_UBOOT_IH_ARCH_ARM; hdr->ih_arch = GRUB_UBOOT_IH_ARCH_ARM;
hdr->ih_comp = GRUB_UBOOT_IH_COMP_NONE; hdr->ih_comp = GRUB_UBOOT_IH_COMP_NONE;
@@ -1838,7 +1641,7 @@ grub_install_generate_image (const char *dir, const char *prefix,
target_addr = (image_target->link_addr - decompress_size); target_addr = (image_target->link_addr - decompress_size);
else else
target_addr = ALIGN_UP (image_target->link_addr target_addr = ALIGN_UP (image_target->link_addr
+ kernel_size + total_module_size, 32); + layout.kernel_size + total_module_size, 32);
ecoff_img = xmalloc (program_size + sizeof (*head) + sizeof (*section)); ecoff_img = xmalloc (program_size + sizeof (*head) + sizeof (*section));
grub_memset (ecoff_img, 0, program_size + sizeof (*head) + sizeof (*section)); grub_memset (ecoff_img, 0, program_size + sizeof (*head) + sizeof (*section));
@@ -1885,16 +1688,16 @@ grub_install_generate_image (const char *dir, const char *prefix,
target_addr = (image_target->link_addr - decompress_size); target_addr = (image_target->link_addr - decompress_size);
else else
target_addr = ALIGN_UP (image_target->link_addr target_addr = ALIGN_UP (image_target->link_addr
+ kernel_size + total_module_size, 32); + layout.kernel_size + total_module_size, 32);
} }
else else
target_addr = image_target->link_addr; target_addr = image_target->link_addr;
if (image_target->voidp_sizeof == 4) if (image_target->voidp_sizeof == 4)
generate_elf32 (image_target, note, &core_img, &core_size, grub_mkimage_generate_elf32 (image_target, note, &core_img, &core_size,
target_addr, align, kernel_size, bss_size); target_addr, &layout);
else else
generate_elf64 (image_target, note, &core_img, &core_size, grub_mkimage_generate_elf64 (image_target, note, &core_img, &core_size,
target_addr, align, kernel_size, bss_size); target_addr, &layout);
} }
break; break;
} }
@@ -1902,7 +1705,7 @@ grub_install_generate_image (const char *dir, const char *prefix,
grub_util_write_image (core_img, core_size, out, outname); grub_util_write_image (core_img, core_size, out, outname);
free (core_img); free (core_img);
free (kernel_path); free (kernel_path);
free (rel_section); free (layout.reloc_section);
grub_util_free_path_list (path_list); grub_util_free_path_list (path_list);
} }