mirror of
http://cgit.git.savannah.gnu.org/git/grub.git
synced 2026-04-28 14:33:34 +00:00
Compare commits
168 Commits
phcoder/c3
...
phcoder/ar
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6e4e4ee33f | ||
|
|
e1444e5399 | ||
|
|
ef57ad6164 | ||
|
|
72bd5756af | ||
|
|
295e041189 | ||
|
|
3f6f84f9e0 | ||
|
|
9f8f747605 | ||
|
|
102016960d | ||
|
|
07cd46627b | ||
|
|
9e161d1302 | ||
|
|
06c92907c1 | ||
|
|
74cef4ab78 | ||
|
|
f4116c3a42 | ||
|
|
2d56c1b117 | ||
|
|
1f72ca020d | ||
|
|
3d300d7247 | ||
|
|
03104c2d98 | ||
|
|
40562ddf1e | ||
|
|
1ea06af1ae | ||
|
|
df21b9363d | ||
|
|
8efde40d0c | ||
|
|
d624e04af1 | ||
|
|
bbd85a0292 | ||
|
|
4f06545767 | ||
|
|
66d0e16425 | ||
|
|
a98c706755 | ||
|
|
95f663ec1d | ||
|
|
2b2a338ad6 | ||
|
|
6c9512b610 | ||
|
|
f447b3d2bb | ||
|
|
295fe6c548 | ||
|
|
9cd85f276f | ||
|
|
502a7c48e9 | ||
|
|
418b32f8e9 | ||
|
|
98490fc328 | ||
|
|
3625fdc0b9 | ||
|
|
1ec2b7758b | ||
|
|
f51e8d0dda | ||
|
|
ee52ea80d6 | ||
|
|
c55f74a5c5 | ||
|
|
3b1bb7f3eb | ||
|
|
0b71582111 | ||
|
|
dc491ff04a | ||
|
|
192243b13e | ||
|
|
0f3ae7324a | ||
|
|
ab8770a314 | ||
|
|
f2df41cffa | ||
|
|
b0227ce4b9 | ||
|
|
f900bea454 | ||
|
|
dc51ac70ee | ||
|
|
869a0bc476 | ||
|
|
f9ee0c3e5d | ||
|
|
8af26e386c | ||
|
|
78e9b82d2c | ||
|
|
86139504b7 | ||
|
|
35c1d629f9 | ||
|
|
bacb8f911f | ||
|
|
fbda565356 | ||
|
|
598185f806 | ||
|
|
ca2fd6c93f | ||
|
|
a29fb4722c | ||
|
|
7562f4ab53 | ||
|
|
c7d0aa5450 | ||
|
|
ceb68c6648 | ||
|
|
99291427d2 | ||
|
|
6ffee98e1b | ||
|
|
a6649f5b8e | ||
|
|
c3c14cffef | ||
|
|
84939af253 | ||
|
|
ba6d40e8bb | ||
|
|
2c3a054f4f | ||
|
|
b8eda96422 | ||
|
|
ca3962ca7b | ||
|
|
a4f7d77f7d | ||
|
|
5099975ace | ||
|
|
2f98d7648e | ||
|
|
018e382144 | ||
|
|
f5cba79512 | ||
|
|
46569db585 | ||
|
|
575c7a6e3c | ||
|
|
fc489a889d | ||
|
|
bfb517bc3b | ||
|
|
437dba573f | ||
|
|
974ba94330 | ||
|
|
963d21b76c | ||
|
|
e3745f9087 | ||
|
|
01d50c2539 | ||
|
|
8d69065f52 | ||
|
|
59ec05bcf8 | ||
|
|
fabde8324d | ||
|
|
5cae910665 | ||
|
|
25492a0f04 | ||
|
|
080a20861c | ||
|
|
f96b34224e | ||
|
|
a2ab8c2172 | ||
|
|
ce01054ec3 | ||
|
|
feef882f98 | ||
|
|
eba6db6323 | ||
|
|
6e1ace590a | ||
|
|
7c35f65aac | ||
|
|
4598cafa7d | ||
|
|
6f4189ffc1 | ||
|
|
127cfea8be | ||
|
|
22aa31bcc3 | ||
|
|
e72de13b9e | ||
|
|
342d6edb97 | ||
|
|
e5c9300191 | ||
|
|
d9a3bfead8 | ||
|
|
1933d37371 | ||
|
|
b29638222e | ||
|
|
8ad190cac2 | ||
|
|
281baeecd3 | ||
|
|
df4df4d887 | ||
|
|
2d425ffdd5 | ||
|
|
67dba97e45 | ||
|
|
7290bb5623 | ||
|
|
ff84a9b868 | ||
|
|
605eecc985 | ||
|
|
b6a03dfd32 | ||
|
|
5f2b285bf8 | ||
|
|
ae3b83a4d4 | ||
|
|
dab148891e | ||
|
|
64e2d139fe | ||
|
|
0edd750e50 | ||
|
|
cc2ed41039 | ||
|
|
7c6c2ad42c | ||
|
|
47e67d809c | ||
|
|
92bbf25714 | ||
|
|
95440b41d3 | ||
|
|
f826d914e2 | ||
|
|
77002c65d3 | ||
|
|
d4561cd080 | ||
|
|
9b4256bf05 | ||
|
|
eefa3239c2 | ||
|
|
4f8fe948b9 | ||
|
|
b95e926788 | ||
|
|
26533fe6bc | ||
|
|
29862fdc3a | ||
|
|
9daf7aae8b | ||
|
|
a4b1326f0d | ||
|
|
dbb0f9fa4f | ||
|
|
e9d71db53a | ||
|
|
6c35ce72ba | ||
|
|
f3c84fa798 | ||
|
|
5db2190f2c | ||
|
|
1bff60e5aa | ||
|
|
8fe17d91af | ||
|
|
66768b99f1 | ||
|
|
962b69d950 | ||
|
|
528256932b | ||
|
|
269a522c7d | ||
|
|
5a5a3c6963 | ||
|
|
670c43af27 | ||
|
|
dc27d254f2 | ||
|
|
31f6506c57 | ||
|
|
9fecb0588e | ||
|
|
aafd205c92 | ||
|
|
bd60f5a207 | ||
|
|
725548a285 | ||
|
|
d5cc487d39 | ||
|
|
fa2af21ec8 | ||
|
|
0e075ac385 | ||
|
|
57e7f1b775 | ||
|
|
67d9ce82ac | ||
|
|
12bf87466f | ||
|
|
97c41e1216 | ||
|
|
8ab2675ede | ||
|
|
efc04d65c7 |
@@ -409,8 +409,9 @@ BOOTCHECK_TIMEOUT=180
|
||||
bootcheck: $(BOOTCHECKS)
|
||||
|
||||
if COND_i386_coreboot
|
||||
default_payload.elf: grub-mkstandalone grub-mkimage
|
||||
pkgdatadir=. ./grub-mkstandalone --grub-mkimage=./grub-mkimage -O i386-coreboot -o $@ --modules='ahci pata ehci uhci ohci usb_keyboard usbms part_msdos xfs ext2 fat at_keyboard part_gpt usbserial_usbdebug cbfs' --install-modules='ls linux search configfile normal cbtime cbls memrw iorw minicmd lsmmap lspci halt reboot hexdump pcidump regexp setpci lsacpi chain test serial multiboot cbmemc linux16 gzio echo help' --fonts= --themes= --locales= -d grub-core/ /boot/grub/grub.cfg=$(srcdir)/coreboot.cfg
|
||||
default_payload.elf: grub-mkstandalone grub-mkimage FORCE
|
||||
rm $@
|
||||
pkgdatadir=. ./grub-mkstandalone --grub-mkimage=./grub-mkimage -O i386-coreboot -o $@ --modules='ahci pata ehci uhci ohci usb_keyboard usbms part_msdos ext2 fat at_keyboard part_gpt usbserial_usbdebug cbfs' --install-modules='ls linux search configfile normal cbtime cbls memrw iorw minicmd lsmmap lspci halt reboot hexdump pcidump regexp setpci lsacpi chain test serial multiboot cbmemc linux16 gzio echo help syslinuxcfg xnu $(shell cat grub-core/fs.lst) password_pbkdf2 $(EXTRA_PAYLOAD_MODULES)' --fonts= --themes= --locales= -d grub-core/ /boot/grub/grub.cfg=$(srcdir)/coreboot.cfg
|
||||
endif
|
||||
|
||||
endif
|
||||
|
||||
@@ -172,6 +172,8 @@ program = {
|
||||
|
||||
common = util/grub-mkimage.c;
|
||||
common = util/mkimage.c;
|
||||
common = util/grub-mkimage32.c;
|
||||
common = util/grub-mkimage64.c;
|
||||
common = util/resolve.c;
|
||||
common = grub-core/kern/emu/argp_common.c;
|
||||
common = grub-core/osdep/init.c;
|
||||
@@ -510,6 +512,8 @@ program = {
|
||||
common = util/render-label.c;
|
||||
common = util/glue-efi.c;
|
||||
common = util/mkimage.c;
|
||||
common = util/grub-mkimage32.c;
|
||||
common = util/grub-mkimage64.c;
|
||||
common = util/grub-install-common.c;
|
||||
common = util/setup_bios.c;
|
||||
common = util/setup_sparc.c;
|
||||
@@ -552,6 +556,8 @@ program = {
|
||||
common = util/render-label.c;
|
||||
common = util/glue-efi.c;
|
||||
common = util/mkimage.c;
|
||||
common = util/grub-mkimage32.c;
|
||||
common = util/grub-mkimage64.c;
|
||||
common = util/grub-install-common.c;
|
||||
common = util/setup_bios.c;
|
||||
common = util/setup_sparc.c;
|
||||
@@ -595,6 +601,8 @@ program = {
|
||||
common = util/grub-install.c;
|
||||
common = util/probe.c;
|
||||
common = util/mkimage.c;
|
||||
common = util/grub-mkimage32.c;
|
||||
common = util/grub-mkimage64.c;
|
||||
common = util/grub-install-common.c;
|
||||
common = util/setup_bios.c;
|
||||
common = util/setup_sparc.c;
|
||||
@@ -632,6 +640,8 @@ program = {
|
||||
common = util/grub-mknetdir.c;
|
||||
|
||||
common = util/mkimage.c;
|
||||
common = util/grub-mkimage32.c;
|
||||
common = util/grub-mkimage64.c;
|
||||
common = util/grub-install-common.c;
|
||||
common = util/setup_bios.c;
|
||||
common = util/setup_sparc.c;
|
||||
|
||||
4
TODO
4
TODO
@@ -7,7 +7,3 @@ glance. So write to <grub-devel@gnu.org> first.
|
||||
For bug tracking, refer to:
|
||||
|
||||
http://savannah.gnu.org/bugs/?group=grub
|
||||
|
||||
Our wiki also lists some areas that need work:
|
||||
|
||||
http://grub.enbug.org/
|
||||
|
||||
@@ -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_extcmd(...)=EXTCOMMAND_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_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
|
||||
|
||||
|
||||
@@ -167,6 +167,7 @@ case "$target_cpu"-"$platform" in
|
||||
mipsel-fuloong) platform=loongson ;;
|
||||
mipsel-loongson) ;;
|
||||
arm-uboot) ;;
|
||||
arm-coreboot) ;;
|
||||
arm-efi) ;;
|
||||
arm64-efi) ;;
|
||||
*-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_arm], [test x$target_cpu = xarm ])
|
||||
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_arm64], [test x$target_cpu = xarm64 ])
|
||||
AM_CONDITIONAL([COND_arm64_efi], [test x$target_cpu = xarm64 -a x$platform = xefi])
|
||||
|
||||
@@ -2538,6 +2538,8 @@ team are:
|
||||
85:3
|
||||
@item Asus EeePC 1005PE
|
||||
84:1 (unconfirmed)
|
||||
@item LENOVO ThinkPad T410s (2912W1C)
|
||||
101:3
|
||||
@end table
|
||||
|
||||
To take full advantage of this function, install GRUB into the MBR
|
||||
@@ -4073,12 +4075,15 @@ after @command{configfile} returns.
|
||||
@node cpuid
|
||||
@subsection cpuid
|
||||
|
||||
@deffn Command cpuid [-l]
|
||||
@deffn Command cpuid [-l] [-p]
|
||||
Check for CPU features. This command is only available on x86 systems.
|
||||
|
||||
With the @option{-l} option, return true if the CPU supports long mode
|
||||
(64-bit).
|
||||
|
||||
With the @option{-p} option, return true if the CPU supports Physical
|
||||
Address Extension (PAE).
|
||||
|
||||
If invoked without options, this command currently behaves as if it had been
|
||||
invoked with @option{-l}. This may change in the future.
|
||||
@end deffn
|
||||
@@ -5042,6 +5047,8 @@ the length of @var{string} is zero
|
||||
@var{expression} is false
|
||||
@item @var{expression1} @code{-a} @var{expression2}
|
||||
both @var{expression1} and @var{expression2} are true
|
||||
@item @var{expression1} @var{expression2}
|
||||
both @var{expression1} and @var{expression2} are true. This syntax is not POSIX-compliant and is not recommended.
|
||||
@item @var{expression1} @code{-o} @var{expression2}
|
||||
either @var{expression1} or @var{expression2} is true
|
||||
@end table
|
||||
|
||||
10
gentpl.py
10
gentpl.py
@@ -31,7 +31,8 @@ GRUB_PLATFORMS = [ "emu", "i386_pc", "i386_efi", "i386_qemu", "i386_coreboot",
|
||||
"i386_xen", "x86_64_xen",
|
||||
"mips_loongson", "sparc64_ieee1275",
|
||||
"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 = {}
|
||||
|
||||
@@ -44,7 +45,7 @@ GROUPS["x86"] = GROUPS["i386"] + GROUPS["x86_64"]
|
||||
GROUPS["mips"] = [ "mips_loongson", "mips_qemu_mips", "mips_arc" ]
|
||||
GROUPS["sparc64"] = [ "sparc64_ieee1275" ]
|
||||
GROUPS["powerpc"] = [ "powerpc_ieee1275" ]
|
||||
GROUPS["arm"] = [ "arm_uboot", "arm_efi" ]
|
||||
GROUPS["arm"] = [ "arm_uboot", "arm_efi", "arm_coreboot" ]
|
||||
GROUPS["arm64"] = [ "arm64_efi" ]
|
||||
|
||||
# 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["uboot"] = [ "arm_uboot" ]
|
||||
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
|
||||
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"]
|
||||
GROUPS["cmos"].remove("i386_efi"); GROUPS["cmos"].remove("x86_64_efi");
|
||||
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
|
||||
GROUPS["videoinkernel"] = ["mips_loongson", "i386_coreboot" ]
|
||||
GROUPS["videoinkernel"] = ["mips_loongson", "i386_coreboot", "arm_coreboot" ]
|
||||
GROUPS["videomodules"] = GRUB_PLATFORMS[:];
|
||||
for i in GROUPS["videoinkernel"]: GROUPS["videomodules"].remove(i)
|
||||
|
||||
|
||||
@@ -107,11 +107,12 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/tsc.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/pci.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pmtimer.h
|
||||
endif
|
||||
|
||||
if COND_i386_coreboot
|
||||
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_fb.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/gfxterm.h
|
||||
@@ -162,6 +163,7 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/tsc.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/pci.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pmtimer.h
|
||||
endif
|
||||
|
||||
if COND_ia64_efi
|
||||
@@ -237,6 +239,20 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/arm/system.h
|
||||
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
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/arm/efi/loader.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h
|
||||
@@ -356,6 +372,16 @@ terminal.lst: $(MARKER_FILES)
|
||||
platform_DATA += 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)
|
||||
(for pp in $^; do \
|
||||
b=`basename $$pp .marker`; \
|
||||
|
||||
@@ -90,8 +90,10 @@ kernel = {
|
||||
i386_qemu_cppflags = '-DGRUB_BOOT_MACHINE_LINK_ADDR=$(GRUB_BOOT_MACHINE_LINK_ADDR)';
|
||||
emu_cflags = '$(CFLAGS_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_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_efi_startup = kern/i386/efi/startup.S;
|
||||
@@ -105,7 +107,8 @@ kernel = {
|
||||
mips_startup = kern/mips/startup.S;
|
||||
sparc64_ieee1275_startup = kern/sparc64/ieee1275/crt0.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;
|
||||
arm64_efi_startup = kern/arm64/efi/startup.S;
|
||||
|
||||
@@ -149,6 +152,20 @@ kernel = {
|
||||
uboot = kern/uboot/init.c;
|
||||
uboot = kern/uboot/hw.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/tparm.c;
|
||||
@@ -164,7 +181,7 @@ kernel = {
|
||||
i386_multiboot = kern/i386/coreboot/init.c;
|
||||
i386_qemu = kern/i386/qemu/init.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 = kern/efi/efi.c;
|
||||
@@ -213,7 +230,7 @@ kernel = {
|
||||
arm_efi = kern/arm/efi/init.c;
|
||||
arm_efi = kern/arm/efi/misc.c;
|
||||
|
||||
arm64_efi = kern/arm/efi/init.c;
|
||||
arm64_efi = kern/arm64/efi/init.c;
|
||||
|
||||
i386_pc = kern/i386/pc/init.c;
|
||||
i386_pc = kern/i386/pc/mmap.c;
|
||||
@@ -223,8 +240,9 @@ kernel = {
|
||||
i386_qemu = kern/vga_init.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;
|
||||
arm_coreboot = kern/arm/coreboot/cbtable.c;
|
||||
|
||||
i386_multiboot = kern/i386/multiboot_mmap.c;
|
||||
|
||||
@@ -236,6 +254,7 @@ kernel = {
|
||||
mips_qemu_mips = term/ns8250.c;
|
||||
mips_qemu_mips = term/serial.c;
|
||||
mips_qemu_mips = term/at_keyboard.c;
|
||||
mips_qemu_mips = term/ps2.c;
|
||||
mips_qemu_mips = commands/boot.c;
|
||||
mips_qemu_mips = commands/keylayouts.c;
|
||||
mips_qemu_mips = term/i386/pc/vga_text.c;
|
||||
@@ -251,6 +270,7 @@ kernel = {
|
||||
mips_loongson = bus/pci.c;
|
||||
mips_loongson = kern/mips/loongson/init.c;
|
||||
mips_loongson = term/at_keyboard.c;
|
||||
mips_loongson = term/ps2.c;
|
||||
mips_loongson = commands/boot.c;
|
||||
mips_loongson = term/serial.c;
|
||||
mips_loongson = video/sm712.c;
|
||||
@@ -572,7 +592,17 @@ module = {
|
||||
module = {
|
||||
name = ehci;
|
||||
common = bus/usb/ehci.c;
|
||||
arm_coreboot = bus/usb/ehci-fdt.c;
|
||||
pci = bus/usb/ehci-pci.c;
|
||||
enable = pci;
|
||||
enable = arm_coreboot;
|
||||
};
|
||||
|
||||
module = {
|
||||
name = dwc2;
|
||||
common = bus/usb/dwc2.c;
|
||||
arm_coreboot = bus/usb/dwc2-fdt.c;
|
||||
enable = arm_coreboot;
|
||||
};
|
||||
|
||||
module = {
|
||||
@@ -752,6 +782,7 @@ module = {
|
||||
enable = arm_efi;
|
||||
enable = arm64_efi;
|
||||
enable = arm_uboot;
|
||||
enable = arm_coreboot;
|
||||
};
|
||||
|
||||
module = {
|
||||
@@ -819,7 +850,7 @@ module = {
|
||||
common = commands/gptsync.c;
|
||||
};
|
||||
|
||||
module = {
|
||||
/*module = {
|
||||
name = halt;
|
||||
nopc = commands/halt.c;
|
||||
i386_pc = commands/i386/pc/halt.c;
|
||||
@@ -854,7 +885,7 @@ module = {
|
||||
xen = lib/xen/reboot.c;
|
||||
uboot = lib/uboot/reboot.c;
|
||||
common = commands/reboot.c;
|
||||
};
|
||||
};*/
|
||||
|
||||
module = {
|
||||
name = hashsum;
|
||||
@@ -1546,6 +1577,7 @@ module = {
|
||||
cmos = lib/cmos_datetime.c;
|
||||
efi = lib/efi/datetime.c;
|
||||
uboot = lib/uboot/datetime.c;
|
||||
arm_coreboot = lib/uboot/datetime.c;
|
||||
sparc64_ieee1275 = lib/ieee1275/datetime.c;
|
||||
powerpc_ieee1275 = lib/ieee1275/datetime.c;
|
||||
sparc64_ieee1275 = lib/ieee1275/cmos.c;
|
||||
@@ -1685,7 +1717,32 @@ module = {
|
||||
x86 = loader/i386/xnu.c;
|
||||
x86 = loader/xnu.c;
|
||||
|
||||
enable = x86;
|
||||
/* Code is pretty generic but relies on RNG which
|
||||
is available only on few platforms. It's not a
|
||||
big deal as xnu needs ACPI anyway and we have
|
||||
RNG on all platforms with ACPI.
|
||||
*/
|
||||
enable = i386_multiboot;
|
||||
enable = i386_coreboot;
|
||||
enable = i386_pc;
|
||||
enable = i386_efi;
|
||||
enable = x86_64_efi;
|
||||
};
|
||||
|
||||
module = {
|
||||
name = random;
|
||||
x86 = lib/i386/random.c;
|
||||
common = lib/random.c;
|
||||
|
||||
i386_multiboot = kern/i386/tsc_pmtimer.c;
|
||||
i386_coreboot = kern/i386/tsc_pmtimer.c;
|
||||
i386_pc = kern/i386/tsc_pmtimer.c;
|
||||
|
||||
enable = i386_multiboot;
|
||||
enable = i386_coreboot;
|
||||
enable = i386_pc;
|
||||
enable = i386_efi;
|
||||
enable = x86_64_efi;
|
||||
};
|
||||
|
||||
module = {
|
||||
@@ -1841,6 +1898,7 @@ module = {
|
||||
module = {
|
||||
name = at_keyboard;
|
||||
common = term/at_keyboard.c;
|
||||
common = term/ps2.c;
|
||||
enable = x86;
|
||||
};
|
||||
|
||||
|
||||
255
grub-core/bus/fdt.c
Normal file
255
grub-core/bus/fdt.c
Normal 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
grub-core/bus/usb/dwc2-fdt.c
Normal file
45
grub-core/bus/usb/dwc2-fdt.c
Normal 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);
|
||||
}
|
||||
1791
grub-core/bus/usb/dwc2.c
Normal file
1791
grub-core/bus/usb/dwc2.c
Normal file
File diff suppressed because it is too large
Load Diff
45
grub-core/bus/usb/ehci-fdt.c
Normal file
45
grub-core/bus/usb/ehci-fdt.c
Normal 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
grub-core/bus/usb/ehci-pci.c
Normal file
208
grub-core/bus/usb/ehci-pci.c
Normal 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);
|
||||
}
|
||||
@@ -22,13 +22,11 @@
|
||||
#include <grub/usb.h>
|
||||
#include <grub/usbtrans.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/loader.h>
|
||||
#include <grub/cs5536.h>
|
||||
#include <grub/disk.h>
|
||||
#include <grub/dma.h>
|
||||
#include <grub/cache.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
@@ -38,8 +36,6 @@ GRUB_MOD_LICENSE ("GPLv3+");
|
||||
* - is not supporting interrupt transfers
|
||||
*/
|
||||
|
||||
#define GRUB_EHCI_PCI_SBRN_REG 0x60
|
||||
|
||||
/* Capability registers offsets */
|
||||
enum
|
||||
{
|
||||
@@ -53,7 +49,6 @@ enum
|
||||
#define GRUB_EHCI_EECP_MASK (0xff << 8)
|
||||
#define GRUB_EHCI_EECP_SHIFT 8
|
||||
|
||||
#define GRUB_EHCI_ADDR_MEM_MASK (~0xff)
|
||||
#define GRUB_EHCI_POINTER_MASK (~0x1f)
|
||||
|
||||
/* Capability register SPARAMS bits */
|
||||
@@ -84,13 +79,6 @@ enum
|
||||
|
||||
#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 */
|
||||
enum
|
||||
{
|
||||
@@ -337,6 +325,21 @@ struct grub_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 */
|
||||
static inline grub_uint32_t
|
||||
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;
|
||||
|
||||
sync_all_caches (e);
|
||||
|
||||
grub_dprintf ("ehci", "reset\n");
|
||||
|
||||
grub_ehci_oper_write32 (e, GRUB_EHCI_COMMAND,
|
||||
GRUB_EHCI_CMD_HC_RESET
|
||||
| grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND));
|
||||
GRUB_EHCI_CMD_HC_RESET);
|
||||
/* Ensure command is written */
|
||||
grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND);
|
||||
/* XXX: How long time could take reset of HC ? */
|
||||
@@ -455,116 +461,24 @@ grub_ehci_reset (struct grub_ehci *e)
|
||||
}
|
||||
|
||||
/* PCI iteration function... */
|
||||
static int
|
||||
grub_ehci_pci_iter (grub_pci_device_t dev, grub_pci_id_t pciid,
|
||||
void *data __attribute__ ((unused)))
|
||||
void
|
||||
grub_ehci_init_device (volatile void *regs)
|
||||
{
|
||||
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;
|
||||
grub_uint32_t eecp_offset;
|
||||
grub_uint32_t fp;
|
||||
int i;
|
||||
grub_uint32_t usblegsup = 0;
|
||||
grub_uint64_t maxtime;
|
||||
grub_uint32_t n_ports;
|
||||
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. */
|
||||
e = grub_zalloc (sizeof (*e));
|
||||
if (!e)
|
||||
return 1;
|
||||
return;
|
||||
e->framelist_chunk = NULL;
|
||||
e->td_chunk = NULL;
|
||||
e->qh_chunk = NULL;
|
||||
e->iobase_ehcc = grub_pci_device_map_range (dev,
|
||||
(base & GRUB_EHCI_ADDR_MEM_MASK),
|
||||
0x100);
|
||||
e->iobase_ehcc = regs;
|
||||
|
||||
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_ehci_ehcc_read8 (e, GRUB_EHCI_EHCC_CAPLEN));
|
||||
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))
|
||||
{
|
||||
grub_dprintf ("ehci", "Unaligned caplen\n");
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
e->iobase = ((volatile grub_uint32_t *) e->iobase_ehcc
|
||||
+ (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",
|
||||
"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_ehci_oper_read32 (e, GRUB_EHCI_COMMAND));
|
||||
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_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 */
|
||||
/* XXX: In fact it is not used at any place, it is prepared for future
|
||||
* 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");
|
||||
|
||||
/* 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...) */
|
||||
|
||||
/* 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;
|
||||
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: 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_ehci_oper_read32 (e, GRUB_EHCI_COMMAND));
|
||||
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_ehci_oper_read32 (e, GRUB_EHCI_CONFIG_FLAG));
|
||||
|
||||
return 0;
|
||||
return;
|
||||
|
||||
fail:
|
||||
if (e)
|
||||
@@ -874,7 +727,7 @@ fail:
|
||||
}
|
||||
grub_free (e);
|
||||
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
|
||||
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 */
|
||||
grub_dprintf ("ehci", "find_qh: found, QH=%p\n", qh_iter);
|
||||
grub_ehci_setup_qh (qh_iter, transfer);
|
||||
sync_all_caches (e);
|
||||
return qh_iter;
|
||||
}
|
||||
|
||||
@@ -1121,7 +975,7 @@ grub_ehci_free_tds (struct grub_ehci *e, grub_ehci_td_t td,
|
||||
token = grub_le_to_cpu32 (td->token);
|
||||
to_transfer = (token & GRUB_EHCI_TOTAL_MASK) >> GRUB_EHCI_TOTAL_OFF;
|
||||
|
||||
/* Check state of TD - if it did not transfered
|
||||
/* Check state of TD - if it did not transfer
|
||||
* whole data then set last_trans - it should be last executed TD
|
||||
* in case when something went wrong. */
|
||||
if (transfer && (td->size != to_transfer))
|
||||
@@ -1289,16 +1143,28 @@ grub_ehci_setup_transfer (grub_usb_controller_t dev,
|
||||
grub_ehci_td_t td_prev = NULL;
|
||||
int i;
|
||||
struct grub_ehci_transfer_controller_data *cdata;
|
||||
grub_uint32_t status;
|
||||
|
||||
sync_all_caches (e);
|
||||
|
||||
/* Check if EHCI is running and AL is enabled */
|
||||
if ((grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS)
|
||||
& GRUB_EHCI_ST_HC_HALTED) != 0)
|
||||
status = grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS);
|
||||
if ((status & GRUB_EHCI_ST_HC_HALTED) != 0)
|
||||
/* XXX: Fix it: Currently we don't do anything to restart EHCI */
|
||||
return GRUB_USB_ERR_INTERNAL;
|
||||
if ((grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS)
|
||||
{
|
||||
grub_dprintf ("ehci", "setup_transfer: halted, status = 0x%x\n",
|
||||
status);
|
||||
return GRUB_USB_ERR_INTERNAL;
|
||||
}
|
||||
status = grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS);
|
||||
if ((status
|
||||
& (GRUB_EHCI_ST_AS_STATUS | GRUB_EHCI_ST_PS_STATUS)) == 0)
|
||||
/* XXX: Fix it: Currently we don't do anything to restart EHCI */
|
||||
return GRUB_USB_ERR_INTERNAL;
|
||||
{
|
||||
grub_dprintf ("ehci", "setup_transfer: no AS/PS, status = 0x%x\n",
|
||||
status);
|
||||
return GRUB_USB_ERR_INTERNAL;
|
||||
}
|
||||
|
||||
/* Allocate memory for controller transfer data. */
|
||||
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);
|
||||
if (!cdata->qh_virt)
|
||||
{
|
||||
grub_dprintf ("ehci", "setup_transfer: no QH\n");
|
||||
grub_free (cdata);
|
||||
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);
|
||||
if (!cdata->td_alt_virt)
|
||||
{
|
||||
grub_dprintf ("ehci", "setup_transfer: no TDs\n");
|
||||
grub_free (cdata);
|
||||
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_free (cdata);
|
||||
grub_dprintf ("ehci", "setup_transfer: no TD\n");
|
||||
return GRUB_USB_ERR_INTERNAL;
|
||||
}
|
||||
|
||||
@@ -1386,6 +1255,8 @@ grub_ehci_setup_transfer (grub_usb_controller_t dev,
|
||||
* i.e. reset token */
|
||||
cdata->qh_virt->td_overlay.token = grub_cpu_to_le32_compile_time (0);
|
||||
|
||||
sync_all_caches (e);
|
||||
|
||||
/* Finito */
|
||||
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_free (cdata);
|
||||
|
||||
sync_all_caches (e);
|
||||
|
||||
/* Additionally, do something with EHCI to make it running (what?) */
|
||||
/* Try enable EHCI and AL */
|
||||
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_free (cdata);
|
||||
|
||||
sync_all_caches (e);
|
||||
|
||||
/* 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.
|
||||
* 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_free (cdata);
|
||||
|
||||
sync_all_caches (e);
|
||||
|
||||
return GRUB_USB_ERR_NONE;
|
||||
}
|
||||
|
||||
@@ -1515,6 +1392,8 @@ grub_ehci_check_transfer (grub_usb_controller_t dev,
|
||||
transfer->controller_data;
|
||||
grub_uint32_t token, token_ftd;
|
||||
|
||||
sync_all_caches (e);
|
||||
|
||||
grub_dprintf ("ehci",
|
||||
"check_transfer: EHCI STATUS=%08x, cdata=%p, qh=%p\n",
|
||||
grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS),
|
||||
@@ -1581,6 +1460,9 @@ grub_ehci_cancel_transfer (grub_usb_controller_t dev,
|
||||
int i;
|
||||
grub_uint64_t maxtime;
|
||||
grub_uint32_t qh_phys;
|
||||
|
||||
sync_all_caches (e);
|
||||
|
||||
grub_uint32_t interrupt =
|
||||
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_td (e, cdata->td_alt_virt);
|
||||
grub_free (cdata);
|
||||
sync_all_caches (e);
|
||||
grub_dprintf ("ehci", "cancel_transfer: end - EHCI not running\n");
|
||||
return GRUB_USB_ERR_NONE;
|
||||
}
|
||||
@@ -1622,6 +1505,8 @@ grub_ehci_cancel_transfer (grub_usb_controller_t dev,
|
||||
/* Unlink QH from AL */
|
||||
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
|
||||
* schedule to advance a few times and then assume that the EHCI
|
||||
* 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");
|
||||
|
||||
sync_all_caches (e);
|
||||
|
||||
return GRUB_USB_ERR_NONE;
|
||||
}
|
||||
|
||||
@@ -1692,8 +1579,8 @@ grub_ehci_hubports (grub_usb_controller_t dev)
|
||||
}
|
||||
|
||||
static grub_usb_err_t
|
||||
grub_ehci_portstatus (grub_usb_controller_t dev,
|
||||
unsigned int port, unsigned int enable)
|
||||
grub_ehci_reset_port (grub_usb_controller_t dev,
|
||||
unsigned int port)
|
||||
{
|
||||
struct grub_ehci *e = (struct grub_ehci *) dev->data;
|
||||
grub_uint64_t endtime;
|
||||
@@ -1715,14 +1602,6 @@ grub_ehci_portstatus (grub_usb_controller_t dev,
|
||||
if (grub_get_time_ms () > endtime)
|
||||
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_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);
|
||||
|
||||
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 */
|
||||
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
|
||||
grub_ehci_restore_hw (void)
|
||||
{
|
||||
@@ -1934,7 +1802,7 @@ static struct grub_usb_controller_dev usb_controller = {
|
||||
.check_transfer = grub_ehci_check_transfer,
|
||||
.cancel_transfer = grub_ehci_cancel_transfer,
|
||||
.hubports = grub_ehci_hubports,
|
||||
.portstatus = grub_ehci_portstatus,
|
||||
.reset_port = grub_ehci_reset_port,
|
||||
.detect_dev = grub_ehci_detect_dev,
|
||||
/* estimated max. count of TDs for one bulk transfer */
|
||||
.max_bulk_tds = GRUB_EHCI_N_TD * 3 / 4
|
||||
@@ -1948,7 +1816,7 @@ GRUB_MOD_INIT (ehci)
|
||||
grub_stop_disk_firmware ();
|
||||
|
||||
grub_boot_time ("Initing EHCI hardware");
|
||||
grub_ehci_inithw ();
|
||||
grub_ehci_pci_scan ();
|
||||
grub_boot_time ("Registering EHCI driver");
|
||||
grub_usb_controller_dev_register (&usb_controller);
|
||||
grub_boot_time ("EHCI driver registered");
|
||||
|
||||
@@ -1224,8 +1224,8 @@ grub_ohci_cancel_transfer (grub_usb_controller_t dev,
|
||||
}
|
||||
|
||||
static grub_usb_err_t
|
||||
grub_ohci_portstatus (grub_usb_controller_t dev,
|
||||
unsigned int port, unsigned int enable)
|
||||
grub_ohci_rest_port (grub_usb_controller_t dev,
|
||||
unsigned int port)
|
||||
{
|
||||
struct grub_ohci *o = (struct grub_ohci *) dev->data;
|
||||
grub_uint64_t endtime;
|
||||
@@ -1233,22 +1233,6 @@ grub_ohci_portstatus (grub_usb_controller_t dev,
|
||||
|
||||
grub_dprintf ("ohci", "begin of portstatus=0x%02x\n",
|
||||
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.
|
||||
* requests 50ms for root hub (no need to be continuous).
|
||||
@@ -1438,7 +1422,7 @@ static struct grub_usb_controller_dev usb_controller =
|
||||
.check_transfer = grub_ohci_check_transfer,
|
||||
.cancel_transfer = grub_ohci_cancel_transfer,
|
||||
.hubports = grub_ohci_hubports,
|
||||
.portstatus = grub_ohci_portstatus,
|
||||
.reset_port = grub_ohci_reset_port,
|
||||
.detect_dev = grub_ohci_detect_dev,
|
||||
/* estimated max. count of TDs for one bulk transfer */
|
||||
.max_bulk_tds = GRUB_OHCI_TDS * 3 / 4
|
||||
|
||||
@@ -710,8 +710,8 @@ grub_uhci_iterate (grub_usb_controller_iterate_hook_t hook, void *hook_data)
|
||||
}
|
||||
|
||||
static grub_usb_err_t
|
||||
grub_uhci_portstatus (grub_usb_controller_t dev,
|
||||
unsigned int port, unsigned int enable)
|
||||
grub_uhci_reset_port (grub_usb_controller_t dev,
|
||||
unsigned int port)
|
||||
{
|
||||
struct grub_uhci *u = (struct grub_uhci *) dev->data;
|
||||
int reg;
|
||||
@@ -731,21 +731,6 @@ grub_uhci_portstatus (grub_usb_controller_t dev,
|
||||
|
||||
status = grub_uhci_readreg16 (u, reg);
|
||||
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. */
|
||||
status = grub_uhci_readreg16 (u, reg) & ~GRUB_UHCI_PORTSC_RWC;
|
||||
@@ -843,7 +828,7 @@ static struct grub_usb_controller_dev usb_controller =
|
||||
.check_transfer = grub_uhci_check_transfer,
|
||||
.cancel_transfer = grub_uhci_cancel_transfer,
|
||||
.hubports = grub_uhci_hubports,
|
||||
.portstatus = grub_uhci_portstatus,
|
||||
.reset_port = grub_uhci_reset_port,
|
||||
.detect_dev = grub_uhci_detect_dev,
|
||||
/* estimated max. count of TDs for one bulk transfer */
|
||||
.max_bulk_tds = N_TD * 3 / 4
|
||||
|
||||
@@ -207,8 +207,8 @@ attach_root_port (struct grub_usb_hub *hub, int portno,
|
||||
|
||||
grub_boot_time ("After detect_dev");
|
||||
|
||||
/* Enable the port. */
|
||||
err = hub->controller->dev->portstatus (hub->controller, portno, 1);
|
||||
/* Reset port. */
|
||||
err = hub->controller->dev->reset_port (hub->controller, portno);
|
||||
if (err)
|
||||
return;
|
||||
hub->controller->dev->pending_reset = grub_get_time_ms () + 5000;
|
||||
|
||||
@@ -18,12 +18,13 @@
|
||||
*/
|
||||
|
||||
#include <grub/dl.h>
|
||||
#include <grub/pci.h>
|
||||
#include <grub/dma.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/usb.h>
|
||||
#include <grub/usbtrans.h>
|
||||
#include <grub/time.h>
|
||||
#include <grub/cache.h>
|
||||
|
||||
|
||||
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);
|
||||
grub_memcpy ((char *) data, data_in, size);
|
||||
|
||||
grub_arch_sync_dma_caches (data, size);
|
||||
|
||||
grub_dprintf ("usb",
|
||||
"control: reqtype=0x%02x req=0x%02x val=0x%02x idx=0x%02x size=%lu\n",
|
||||
reqtype, request, value, index, (unsigned long)size);
|
||||
@@ -161,6 +164,8 @@ grub_usb_control_msg (grub_usb_device_t dev,
|
||||
setupdata->value = value;
|
||||
setupdata->index = index;
|
||||
setupdata->length = size;
|
||||
grub_arch_sync_dma_caches (setupdata, sizeof (*setupdata));
|
||||
|
||||
transfer->transactions[0].size = sizeof (*setupdata);
|
||||
transfer->transactions[0].pid = GRUB_USB_TRANSFER_TYPE_SETUP;
|
||||
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);
|
||||
grub_dma_free (data_chunk);
|
||||
grub_dma_free (setupdata_chunk);
|
||||
|
||||
grub_arch_sync_dma_caches (data, size0);
|
||||
grub_memcpy (data_in, (char *) data, size0);
|
||||
|
||||
grub_dma_free (data_chunk);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -236,7 +243,10 @@ grub_usb_bulk_setup_readwrite (grub_usb_device_t dev,
|
||||
data = grub_dma_get_virt (data_chunk);
|
||||
data_addr = grub_dma_get_phys (data_chunk);
|
||||
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. */
|
||||
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;
|
||||
|
||||
if (transfer->dir == GRUB_USB_TRANSFER_TYPE_IN)
|
||||
grub_memcpy (transfer->data, (void *)
|
||||
grub_dma_get_virt (transfer->data_chunk),
|
||||
transfer->size + 1);
|
||||
{
|
||||
grub_arch_sync_dma_caches (grub_dma_get_virt (transfer->data_chunk),
|
||||
transfer->size + 1);
|
||||
grub_memcpy (transfer->data, (void *)
|
||||
grub_dma_get_virt (transfer->data_chunk),
|
||||
transfer->size + 1);
|
||||
}
|
||||
|
||||
grub_free (transfer->transactions);
|
||||
grub_dma_free (transfer->data_chunk);
|
||||
|
||||
@@ -593,6 +593,9 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args)
|
||||
if (! table->addr)
|
||||
{
|
||||
free_tables ();
|
||||
grub_free (exclude);
|
||||
grub_free (load_only);
|
||||
grub_free (table);
|
||||
return grub_errno;
|
||||
}
|
||||
table->next = acpi_tables;
|
||||
|
||||
@@ -45,7 +45,7 @@ static grub_err_t
|
||||
grub_cmd_cmostest (struct grub_command *cmd __attribute__ ((unused)),
|
||||
int argc, char *argv[])
|
||||
{
|
||||
int byte, bit;
|
||||
int byte = 0, bit = 0;
|
||||
grub_err_t err;
|
||||
grub_uint8_t value;
|
||||
|
||||
@@ -67,7 +67,7 @@ static grub_err_t
|
||||
grub_cmd_cmosclean (struct grub_command *cmd __attribute__ ((unused)),
|
||||
int argc, char *argv[])
|
||||
{
|
||||
int byte, bit;
|
||||
int byte = 0, bit = 0;
|
||||
grub_err_t err;
|
||||
grub_uint8_t value;
|
||||
|
||||
@@ -85,7 +85,7 @@ static grub_err_t
|
||||
grub_cmd_cmosset (struct grub_command *cmd __attribute__ ((unused)),
|
||||
int argc, char *argv[])
|
||||
{
|
||||
int byte, bit;
|
||||
int byte = 0, bit = 0;
|
||||
grub_err_t err;
|
||||
grub_uint8_t value;
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
#include <grub/misc.h>
|
||||
#include <grub/command.h>
|
||||
#include <grub/i18n.h>
|
||||
#include <grub/i386/coreboot/lbio.h>
|
||||
#include <grub/coreboot/lbio.h>
|
||||
#include <grub/i386/tsc.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
#include <grub/misc.h>
|
||||
#include <grub/command.h>
|
||||
#include <grub/i18n.h>
|
||||
#include <grub/i386/coreboot/lbio.h>
|
||||
#include <grub/coreboot/lbio.h>
|
||||
#include <grub/i386/tsc.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
@@ -253,6 +253,7 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)),
|
||||
struct grub_command *cmd;
|
||||
char **cutargs;
|
||||
int cutargc;
|
||||
grub_err_t err = GRUB_ERR_NONE;
|
||||
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
@@ -314,6 +315,8 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)),
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
|
||||
|
||||
cutargs = grub_malloc (sizeof (cutargs[0]) * (argc - 1));
|
||||
if (!cutargs)
|
||||
return grub_errno;
|
||||
cutargc = argc - 1;
|
||||
grub_memcpy (cutargs + 1, args + 2, sizeof (cutargs[0]) * (argc - 2));
|
||||
cutargs[0] = args[0];
|
||||
@@ -333,7 +336,7 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)),
|
||||
if (!(cmd->func) (cmd, cutargc, cutargs))
|
||||
{
|
||||
kernel_type = LINUX;
|
||||
return GRUB_ERR_NONE;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
@@ -348,7 +351,7 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)),
|
||||
if (!(cmd->func) (cmd, argc, args))
|
||||
{
|
||||
kernel_type = MULTIBOOT;
|
||||
return GRUB_ERR_NONE;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
@@ -413,7 +416,7 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)),
|
||||
if (!(cmd->func) (cmd, cutargc, cutargs))
|
||||
{
|
||||
kernel_type = KFREEBSD;
|
||||
return GRUB_ERR_NONE;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
@@ -422,6 +425,8 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)),
|
||||
char **bsdargs;
|
||||
int bsdargc;
|
||||
char bsddevname[sizeof ("wdXXXXXXXXXXXXY")];
|
||||
int found = 0;
|
||||
|
||||
if (bsd_device == -1)
|
||||
{
|
||||
bsdargs = cutargs;
|
||||
@@ -432,6 +437,11 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)),
|
||||
char rbuf[3] = "-r";
|
||||
bsdargc = cutargc + 2;
|
||||
bsdargs = grub_malloc (sizeof (bsdargs[0]) * bsdargc);
|
||||
if (!bsdargs)
|
||||
{
|
||||
err = grub_errno;
|
||||
goto out;
|
||||
}
|
||||
grub_memcpy (bsdargs, args, argc * sizeof (bsdargs[0]));
|
||||
bsdargs[argc] = rbuf;
|
||||
bsdargs[argc + 1] = bsddevname;
|
||||
@@ -447,7 +457,8 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)),
|
||||
if (!(cmd->func) (cmd, bsdargc, bsdargs))
|
||||
{
|
||||
kernel_type = KNETBSD;
|
||||
return GRUB_ERR_NONE;
|
||||
found = 1;
|
||||
goto free_bsdargs;
|
||||
}
|
||||
}
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
@@ -460,20 +471,28 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)),
|
||||
if (!(cmd->func) (cmd, bsdargc, bsdargs))
|
||||
{
|
||||
kernel_type = KOPENBSD;
|
||||
return GRUB_ERR_NONE;
|
||||
found = 1;
|
||||
goto free_bsdargs;
|
||||
}
|
||||
}
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
free_bsdargs:
|
||||
if (bsdargs != cutargs)
|
||||
grub_free (bsdargs);
|
||||
if (found)
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
while (0);
|
||||
|
||||
return grub_error (GRUB_ERR_BAD_OS, "couldn't load file %s",
|
||||
args[0]);
|
||||
err = grub_error (GRUB_ERR_BAD_OS, "couldn't load file %s",
|
||||
args[0]);
|
||||
out:
|
||||
grub_free (cutargs);
|
||||
return err;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
@@ -534,15 +553,17 @@ grub_cmd_legacy_initrdnounzip (struct grub_command *mycmd __attribute__ ((unused
|
||||
char **newargs;
|
||||
grub_err_t err;
|
||||
char nounzipbuf[10] = "--nounzip";
|
||||
|
||||
cmd = grub_command_find ("module");
|
||||
if (!cmd)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("can't find command `%s'"),
|
||||
"module");
|
||||
|
||||
newargs = grub_malloc ((argc + 1) * sizeof (newargs[0]));
|
||||
if (!newargs)
|
||||
return grub_errno;
|
||||
grub_memcpy (newargs + 1, args, argc * sizeof (newargs[0]));
|
||||
newargs[0] = nounzipbuf;
|
||||
cmd = grub_command_find ("module");
|
||||
if (!cmd)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("can't find command `%s'"),
|
||||
"module");
|
||||
|
||||
err = cmd->func (cmd, argc + 1, newargs);
|
||||
grub_free (newargs);
|
||||
|
||||
@@ -198,7 +198,10 @@ grub_cmd_nativedisk (grub_command_t cmd __attribute__ ((unused)),
|
||||
return grub_errno;
|
||||
|
||||
if (get_uuid (NULL, &uuid_root, 0))
|
||||
return grub_errno;
|
||||
{
|
||||
grub_free (mods);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
prefdev = grub_file_get_device_name (prefix);
|
||||
if (grub_errno)
|
||||
@@ -210,6 +213,8 @@ grub_cmd_nativedisk (grub_command_t cmd __attribute__ ((unused)),
|
||||
if (get_uuid (prefdev, &uuid_prefix, 0))
|
||||
{
|
||||
grub_free (uuid_root);
|
||||
grub_free (prefdev);
|
||||
grub_free (mods);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
@@ -289,12 +294,15 @@ grub_cmd_nativedisk (grub_command_t cmd __attribute__ ((unused)),
|
||||
}
|
||||
grub_free (uuid_root);
|
||||
grub_free (uuid_prefix);
|
||||
grub_free (prefdev);
|
||||
grub_free (mods);
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
|
||||
fail:
|
||||
grub_free (uuid_root);
|
||||
grub_free (uuid_prefix);
|
||||
grub_free (prefdev);
|
||||
|
||||
for (i = 0; i < mods_loaded; i++)
|
||||
if (mods[i])
|
||||
@@ -302,6 +310,8 @@ grub_cmd_nativedisk (grub_command_t cmd __attribute__ ((unused)),
|
||||
mods[i]->fini = 0;
|
||||
grub_dl_unload (mods[i]);
|
||||
}
|
||||
grub_free (mods);
|
||||
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
|
||||
@@ -283,6 +283,7 @@ grub_cmd_parttool (grub_command_t cmd __attribute__ ((unused)),
|
||||
}
|
||||
if (! cur)
|
||||
{
|
||||
grub_free (parsed);
|
||||
grub_device_close (dev);
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("unknown argument `%s'"),
|
||||
args[i]);
|
||||
|
||||
@@ -45,6 +45,7 @@ check_password (const char *user, const char *entered, void *pin)
|
||||
grub_uint8_t *buf;
|
||||
struct pbkdf2_password *pass = pin;
|
||||
gcry_err_code_t err;
|
||||
grub_err_t ret;
|
||||
|
||||
buf = grub_malloc (pass->buflen);
|
||||
if (!buf)
|
||||
@@ -55,17 +56,17 @@ check_password (const char *user, const char *entered, void *pin)
|
||||
pass->salt, pass->saltlen, pass->c,
|
||||
buf, pass->buflen);
|
||||
if (err)
|
||||
ret = grub_crypto_gcry_error (err);
|
||||
else if (grub_crypto_memcmp (buf, pass->expected, pass->buflen) != 0)
|
||||
ret = GRUB_ACCESS_DENIED;
|
||||
else
|
||||
{
|
||||
grub_free (buf);
|
||||
return grub_crypto_gcry_error (err);
|
||||
grub_auth_authenticate (user);
|
||||
ret = GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
if (grub_crypto_memcmp (buf, pass->expected, pass->buflen) != 0)
|
||||
return GRUB_ACCESS_DENIED;
|
||||
|
||||
grub_auth_authenticate (user);
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
grub_free (buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int
|
||||
|
||||
@@ -324,19 +324,19 @@ grub_load_public_key (grub_file_t f)
|
||||
if (grub_file_read (f, &l, sizeof (l)) != sizeof (l))
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
|
||||
goto fail;
|
||||
break;
|
||||
}
|
||||
|
||||
lb = (grub_be_to_cpu16 (l) + GRUB_CHAR_BIT - 1) / GRUB_CHAR_BIT;
|
||||
if (lb > READBUF_SIZE - sizeof (grub_uint16_t))
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
|
||||
goto fail;
|
||||
break;
|
||||
}
|
||||
if (grub_file_read (f, buffer + sizeof (grub_uint16_t), lb) != (grub_ssize_t) lb)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
|
||||
goto fail;
|
||||
break;
|
||||
}
|
||||
grub_memcpy (buffer, &l, sizeof (l));
|
||||
|
||||
@@ -346,10 +346,16 @@ grub_load_public_key (grub_file_t f)
|
||||
buffer, lb + sizeof (grub_uint16_t), 0))
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
|
||||
goto fail;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i < pkalgos[pk].nmpipub)
|
||||
{
|
||||
grub_free (sk);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
GRUB_MD_SHA1->final (fingerprint_context);
|
||||
|
||||
grub_memcpy (sk->fingerprint, GRUB_MD_SHA1->read (fingerprint_context), 20);
|
||||
|
||||
@@ -32,7 +32,7 @@ GRUB_MOD_LICENSE ("GPLv3+");
|
||||
struct grub_ahci_cmd_head
|
||||
{
|
||||
grub_uint32_t config;
|
||||
grub_uint32_t transfered;
|
||||
grub_uint32_t transferred;
|
||||
grub_uint64_t command_table_base;
|
||||
grub_uint32_t unused[4];
|
||||
};
|
||||
@@ -954,7 +954,7 @@ grub_ahci_readwrite_real (struct grub_ahci_device *dev,
|
||||
grub_dprintf ("ahci", "AHCI tfd = %x\n",
|
||||
dev->hba->ports[dev->port].task_file_data);
|
||||
|
||||
dev->command_list[0].transfered = 0;
|
||||
dev->command_list[0].transferred = 0;
|
||||
dev->command_list[0].command_table_base
|
||||
= grub_dma_get_phys (dev->command_table_chunk);
|
||||
|
||||
@@ -1044,7 +1044,7 @@ grub_ahci_readwrite_real (struct grub_ahci_device *dev,
|
||||
dev->hba->ports[dev->port].command_issue,
|
||||
dev->hba->ports[dev->port].intstatus,
|
||||
dev->hba->ports[dev->port].task_file_data,
|
||||
dev->command_list[0].transfered,
|
||||
dev->command_list[0].transferred,
|
||||
dev->hba->ports[dev->port].sata_error,
|
||||
((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x00],
|
||||
((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x18]);
|
||||
|
||||
@@ -85,6 +85,12 @@ make_devices (void)
|
||||
{
|
||||
/* Uggh. */
|
||||
grub_free (handles);
|
||||
while (devices)
|
||||
{
|
||||
d = devices->next;
|
||||
grub_free (devices);
|
||||
devices = d;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -154,7 +154,10 @@ grub_efiemu_init_segments (grub_efiemu_segment_t *segs, const Elf_Ehdr *e)
|
||||
s->sh_flags & SHF_EXECINSTR ? GRUB_EFI_RUNTIME_SERVICES_CODE
|
||||
: GRUB_EFI_RUNTIME_SERVICES_DATA);
|
||||
if (seg->handle < 0)
|
||||
return grub_errno;
|
||||
{
|
||||
grub_free (seg);
|
||||
return grub_errno;
|
||||
}
|
||||
seg->off = 0;
|
||||
}
|
||||
|
||||
@@ -343,7 +346,7 @@ SUFFIX (grub_efiemu_loadcore_init) (void *core, const char *filename,
|
||||
return grub_error (GRUB_ERR_BAD_MODULE, N_("this ELF file is not of the right type"));
|
||||
|
||||
/* Make sure that every section is within the core. */
|
||||
if ((grub_size_t) core_size < e->e_shoff + e->e_shentsize * e->e_shnum)
|
||||
if ((grub_size_t) core_size < e->e_shoff + (grub_uint32_t) e->e_shentsize * e->e_shnum)
|
||||
return grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
|
||||
filename);
|
||||
|
||||
|
||||
@@ -196,7 +196,7 @@ grub_efiemu_load_file (const char *filename)
|
||||
{
|
||||
grub_file_close (file);
|
||||
grub_efiemu_unload ();
|
||||
return grub_errno;
|
||||
return err;
|
||||
}
|
||||
|
||||
grub_dprintf ("efiemu", "mm initialized\n");
|
||||
|
||||
@@ -99,7 +99,8 @@ grub_efiemu_request_memalign (grub_size_t align, grub_size_t size,
|
||||
grub_size_t align_overhead;
|
||||
struct grub_efiemu_memrequest *ret, *cur, *prev;
|
||||
/* Check that the request is correct */
|
||||
if (type >= GRUB_EFI_MAX_MEMORY_TYPE || type <= GRUB_EFI_LOADER_CODE)
|
||||
if (type <= GRUB_EFI_LOADER_CODE || type == GRUB_EFI_PERSISTENT_MEMORY ||
|
||||
type >= GRUB_EFI_MAX_MEMORY_TYPE)
|
||||
return -2;
|
||||
|
||||
/* Add new size to requested size */
|
||||
@@ -166,6 +167,13 @@ efiemu_alloc_requests (void)
|
||||
GRUB_EFI_MEMORY_MAPPED_IO,
|
||||
GRUB_EFI_MEMORY_MAPPED_IO_PORT_SPACE,
|
||||
GRUB_EFI_PAL_CODE
|
||||
|
||||
/*
|
||||
* These are not allocatable:
|
||||
* GRUB_EFI_RESERVED_MEMORY_TYPE
|
||||
* GRUB_EFI_PERSISTENT_MEMORY
|
||||
* >= GRUB_EFI_MAX_MEMORY_TYPE
|
||||
*/
|
||||
};
|
||||
|
||||
/* Compute total memory needed */
|
||||
@@ -402,6 +410,10 @@ fill_hook (grub_uint64_t addr, grub_uint64_t size, grub_memory_type_t type,
|
||||
return grub_efiemu_add_to_mmap (addr, size,
|
||||
GRUB_EFI_ACPI_MEMORY_NVS);
|
||||
|
||||
case GRUB_MEMORY_PERSISTENT:
|
||||
case GRUB_MEMORY_PERSISTENT_LEGACY:
|
||||
return grub_efiemu_add_to_mmap (addr, size,
|
||||
GRUB_EFI_PERSISTENT_MEMORY);
|
||||
default:
|
||||
grub_dprintf ("efiemu",
|
||||
"Unknown memory type %d. Assuming unusable\n", type);
|
||||
@@ -445,7 +457,7 @@ grub_efiemu_mmap_iterate (grub_memory_hook_t hook, void *hook_data)
|
||||
case GRUB_EFI_MEMORY_MAPPED_IO:
|
||||
case GRUB_EFI_MEMORY_MAPPED_IO_PORT_SPACE:
|
||||
case GRUB_EFI_PAL_CODE:
|
||||
case GRUB_EFI_MAX_MEMORY_TYPE:
|
||||
default:
|
||||
hook (efiemu_mmap[i].physical_start, efiemu_mmap[i].num_pages * 4096,
|
||||
GRUB_MEMORY_RESERVED, hook_data);
|
||||
break;
|
||||
@@ -468,6 +480,12 @@ grub_efiemu_mmap_iterate (grub_memory_hook_t hook, void *hook_data)
|
||||
hook (efiemu_mmap[i].physical_start, efiemu_mmap[i].num_pages * 4096,
|
||||
GRUB_MEMORY_NVS, hook_data);
|
||||
break;
|
||||
|
||||
case GRUB_EFI_PERSISTENT_MEMORY:
|
||||
hook (efiemu_mmap[i].physical_start, efiemu_mmap[i].num_pages * 4096,
|
||||
GRUB_MEMORY_PERSISTENT, hook_data);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -503,7 +521,8 @@ grub_efiemu_mmap_sort_and_uniq (void)
|
||||
[GRUB_EFI_ACPI_MEMORY_NVS] = 3,
|
||||
[GRUB_EFI_MEMORY_MAPPED_IO] = 4,
|
||||
[GRUB_EFI_MEMORY_MAPPED_IO_PORT_SPACE] = 4,
|
||||
[GRUB_EFI_PAL_CODE] = 4
|
||||
[GRUB_EFI_PAL_CODE] = 4,
|
||||
[GRUB_EFI_PERSISTENT_MEMORY] = 4
|
||||
};
|
||||
|
||||
int i, j, k, done;
|
||||
|
||||
@@ -83,10 +83,16 @@ SUFFIX (grub_efiemu_prepare) (struct grub_efiemu_prepare_hook *prepare_hooks,
|
||||
((grub_uint8_t *) grub_efiemu_mm_obtain_request (handle) + off);
|
||||
|
||||
/* Put pointer to the list of configuration tables in system table */
|
||||
grub_efiemu_write_value
|
||||
(&(SUFFIX (grub_efiemu_system_table)->configuration_table), 0,
|
||||
conftable_handle, 0, 1,
|
||||
sizeof (SUFFIX (grub_efiemu_system_table)->configuration_table));
|
||||
err = grub_efiemu_write_value
|
||||
(&(SUFFIX (grub_efiemu_system_table)->configuration_table), 0,
|
||||
conftable_handle, 0, 1,
|
||||
sizeof (SUFFIX (grub_efiemu_system_table)->configuration_table));
|
||||
if (err)
|
||||
{
|
||||
grub_efiemu_unload ();
|
||||
return err;
|
||||
}
|
||||
|
||||
SUFFIX(grub_efiemu_system_table)->num_table_entries = cntconftables;
|
||||
|
||||
/* Fill the list of configuration tables */
|
||||
|
||||
@@ -1308,6 +1308,7 @@ grub_hfs_open (struct grub_file *file, const char *name)
|
||||
if (grub_hfs_find_dir (data, name, &found, GRUB_FSHELP_REG))
|
||||
{
|
||||
grub_free (data);
|
||||
grub_free (found);
|
||||
grub_dl_unref (my_mod);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
@@ -104,7 +104,7 @@ decomp_block (struct grub_ntfs_comp *cc, grub_uint8_t *dest)
|
||||
if (tag & 1)
|
||||
{
|
||||
grub_uint32_t i, len, delta, code, lmask, dshift;
|
||||
grub_uint16_t word;
|
||||
grub_uint16_t word = 0;
|
||||
|
||||
if (decomp_get16 (cc, &word))
|
||||
return grub_errno;
|
||||
|
||||
@@ -775,7 +775,10 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
|
||||
c = de->name[de->len];
|
||||
de->name[de->len] = '\0';
|
||||
if (iterate_dir_call_hook (ino, de->name, &ctx))
|
||||
return 1;
|
||||
{
|
||||
de->name[de->len] = c;
|
||||
return 1;
|
||||
}
|
||||
de->name[de->len] = c;
|
||||
|
||||
de = grub_xfs_inline_next_de(dir->data, head, de);
|
||||
|
||||
@@ -3132,7 +3132,7 @@ make_mdn (dnode_end_t * mdn, struct grub_zfs_data *data)
|
||||
{
|
||||
void *osp;
|
||||
blkptr_t *bp;
|
||||
grub_size_t ospsize;
|
||||
grub_size_t ospsize = 0;
|
||||
grub_err_t err;
|
||||
|
||||
grub_dprintf ("zfs", "endian = %d\n", mdn->endian);
|
||||
|
||||
@@ -184,6 +184,8 @@ LZ4_uncompress_unknownOutputSize(const char *source,
|
||||
}
|
||||
}
|
||||
/* copy literals */
|
||||
if ((grub_addr_t) length > ~(grub_addr_t)op)
|
||||
goto _output_error;
|
||||
cpy = op + length;
|
||||
if ((cpy > oend - COPYLENGTH) ||
|
||||
(ip + length > iend - COPYLENGTH)) {
|
||||
|
||||
@@ -45,6 +45,7 @@ grub_font_draw_string (const char *str, grub_font_t font,
|
||||
grub_uint32_t *logical;
|
||||
grub_ssize_t logical_len, visual_len;
|
||||
struct grub_unicode_glyph *visual, *ptr;
|
||||
grub_err_t err;
|
||||
|
||||
logical_len = grub_utf8_to_ucs4_alloc (str, &logical, 0);
|
||||
if (logical_len < 0)
|
||||
@@ -56,24 +57,28 @@ grub_font_draw_string (const char *str, grub_font_t font,
|
||||
if (visual_len < 0)
|
||||
return grub_errno;
|
||||
|
||||
err = GRUB_ERR_NONE;
|
||||
for (ptr = visual, x = left_x; ptr < visual + visual_len; ptr++)
|
||||
{
|
||||
grub_err_t err;
|
||||
struct grub_font_glyph *glyph;
|
||||
glyph = grub_font_construct_glyph (font, ptr);
|
||||
if (!glyph)
|
||||
return grub_errno;
|
||||
{
|
||||
err = grub_errno;
|
||||
goto out;
|
||||
}
|
||||
err = grub_font_draw_glyph (glyph, color, x, baseline_y);
|
||||
x += glyph->device_width;
|
||||
if (err)
|
||||
return err;
|
||||
goto out;
|
||||
x += glyph->device_width;
|
||||
}
|
||||
|
||||
out:
|
||||
for (ptr = visual; ptr < visual + visual_len; ptr++)
|
||||
grub_unicode_destroy_glyph (ptr);
|
||||
grub_free (visual);
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Get the width in pixels of the specified UTF-8 string, when rendered in
|
||||
|
||||
@@ -63,14 +63,14 @@ grub_gfxmenu_try (int entry, grub_menu_t menu, int nested)
|
||||
return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("variable `%s' isn't set"),
|
||||
"theme");
|
||||
|
||||
instance = grub_zalloc (sizeof (*instance));
|
||||
if (!instance)
|
||||
return grub_errno;
|
||||
|
||||
err = grub_video_get_info (&mode_info);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
instance = grub_zalloc (sizeof (*instance));
|
||||
if (!instance)
|
||||
return grub_errno;
|
||||
|
||||
if (theme_path[0] != '/' && theme_path[0] != '(')
|
||||
{
|
||||
const char *prefix;
|
||||
|
||||
@@ -32,3 +32,88 @@ grub_byte_checksum (void *base, grub_size_t size)
|
||||
ret += *ptr;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void *
|
||||
grub_acpi_rsdt_find_table (struct grub_acpi_table_header *rsdt, const char *sig)
|
||||
{
|
||||
grub_size_t s;
|
||||
grub_unaligned_uint32_t *ptr;
|
||||
|
||||
if (!rsdt)
|
||||
return 0;
|
||||
|
||||
if (grub_memcmp (rsdt->signature, "RSDT", 4) != 0)
|
||||
return 0;
|
||||
|
||||
ptr = (grub_unaligned_uint32_t *) (rsdt + 1);
|
||||
s = (rsdt->length - sizeof (*rsdt)) / sizeof (grub_uint32_t);
|
||||
for (; s; s--, ptr++)
|
||||
{
|
||||
struct grub_acpi_table_header *tbl;
|
||||
tbl = (struct grub_acpi_table_header *) (grub_addr_t) ptr->val;
|
||||
if (grub_memcmp (tbl->signature, sig, 4) == 0)
|
||||
return tbl;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void *
|
||||
grub_acpi_xsdt_find_table (struct grub_acpi_table_header *xsdt, const char *sig)
|
||||
{
|
||||
grub_size_t s;
|
||||
grub_unaligned_uint64_t *ptr;
|
||||
|
||||
if (!xsdt)
|
||||
return 0;
|
||||
|
||||
if (grub_memcmp (xsdt->signature, "XSDT", 4) != 0)
|
||||
return 0;
|
||||
|
||||
ptr = (grub_unaligned_uint64_t *) (xsdt + 1);
|
||||
s = (xsdt->length - sizeof (*xsdt)) / sizeof (grub_uint32_t);
|
||||
for (; s; s--, ptr++)
|
||||
{
|
||||
struct grub_acpi_table_header *tbl;
|
||||
#if GRUB_CPU_SIZEOF_VOID_P != 8
|
||||
if (ptr->val >> 32)
|
||||
continue;
|
||||
#endif
|
||||
tbl = (struct grub_acpi_table_header *) (grub_addr_t) ptr->val;
|
||||
if (grub_memcmp (tbl->signature, sig, 4) == 0)
|
||||
return tbl;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct grub_acpi_fadt *
|
||||
grub_acpi_find_fadt (void)
|
||||
{
|
||||
struct grub_acpi_fadt *fadt = 0;
|
||||
struct grub_acpi_rsdp_v10 *rsdpv1;
|
||||
struct grub_acpi_rsdp_v20 *rsdpv2;
|
||||
rsdpv1 = grub_machine_acpi_get_rsdpv1 ();
|
||||
if (rsdpv1)
|
||||
fadt = grub_acpi_rsdt_find_table ((struct grub_acpi_table_header *)
|
||||
(grub_addr_t) rsdpv1->rsdt_addr,
|
||||
GRUB_ACPI_FADT_SIGNATURE);
|
||||
if (fadt)
|
||||
return fadt;
|
||||
rsdpv2 = grub_machine_acpi_get_rsdpv2 ();
|
||||
if (rsdpv2)
|
||||
fadt = grub_acpi_rsdt_find_table ((struct grub_acpi_table_header *)
|
||||
(grub_addr_t) rsdpv2->rsdpv1.rsdt_addr,
|
||||
GRUB_ACPI_FADT_SIGNATURE);
|
||||
if (fadt)
|
||||
return fadt;
|
||||
if (rsdpv2
|
||||
#if GRUB_CPU_SIZEOF_VOID_P != 8
|
||||
&& !(rsdpv2->xsdt_addr >> 32)
|
||||
#endif
|
||||
)
|
||||
fadt = grub_acpi_xsdt_find_table ((struct grub_acpi_table_header *)
|
||||
(grub_addr_t) rsdpv2->xsdt_addr,
|
||||
GRUB_ACPI_FADT_SIGNATURE);
|
||||
if (fadt)
|
||||
return fadt;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -29,6 +29,8 @@ void grub_arm_clean_dcache_range_armv6 (grub_addr_t start, grub_addr_t end,
|
||||
grub_addr_t dlinesz);
|
||||
void grub_arm_clean_dcache_range_armv7 (grub_addr_t start, grub_addr_t end,
|
||||
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,
|
||||
grub_addr_t dlinesz);
|
||||
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
|
||||
grub_arm_disable_caches_mmu (void)
|
||||
{
|
||||
|
||||
@@ -33,6 +33,18 @@
|
||||
# define ISB isb
|
||||
#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
|
||||
@ r1 - LoC
|
||||
@ r2 - current level
|
||||
@@ -123,4 +135,4 @@ clean_invalidate_dcache:
|
||||
pop {r4-r12, lr}
|
||||
bx lr
|
||||
|
||||
#include "cache.S"
|
||||
#include "cache.S"
|
||||
|
||||
74
grub-core/kern/arm/coreboot/cbtable.c
Normal file
74
grub-core/kern/arm/coreboot/cbtable.c
Normal 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
grub-core/kern/arm/coreboot/coreboot.S
Normal file
44
grub-core/kern/arm/coreboot/coreboot.S
Normal 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
grub-core/kern/arm/coreboot/dma.c
Normal file
59
grub-core/kern/arm/coreboot/dma.c
Normal 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
grub-core/kern/arm/coreboot/init.c
Normal file
169
grub-core/kern/arm/coreboot/init.c
Normal 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
grub-core/kern/arm/coreboot/timer.c
Normal file
101
grub-core/kern/arm/coreboot/timer.c
Normal 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
|
||||
* means among other things that it always enters in ARM state.
|
||||
*
|
||||
* coreboot starts in ARM mode as well.
|
||||
*
|
||||
* Overview of GRUB image layout:
|
||||
*
|
||||
@@ -55,10 +56,6 @@ FUNCTION(_start)
|
||||
VARIABLE(grub_total_module_size)
|
||||
.long 0
|
||||
|
||||
VARIABLE(grub_uboot_machine_type)
|
||||
.long 0
|
||||
VARIABLE(grub_uboot_boot_data)
|
||||
.long 0
|
||||
VARIABLE(grub_modbase)
|
||||
.long 0
|
||||
bss_start_ptr:
|
||||
@@ -66,34 +63,73 @@ bss_start_ptr:
|
||||
end_ptr:
|
||||
.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)
|
||||
@ Store context: Machine ID, atags/dtb, ...
|
||||
@ U-Boot API signature is stored on the U-Boot heap
|
||||
@ Stack pointer used as start address for signature probing
|
||||
mov r12, sp
|
||||
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)
|
||||
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
|
||||
adr r1, _start
|
||||
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)
|
||||
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 r2, grub_total_module_size @ blob size
|
||||
|
||||
add r1, r1, #GRUB_KERNEL_MACHINE_STACK_SIZE
|
||||
and r1, r1, #~0x7 @ Ensure 8-byte alignment
|
||||
|
||||
sub sp, r1, #8
|
||||
add r1, r1, #1024
|
||||
|
||||
str r1, EXT_C(grub_modbase)
|
||||
|
||||
/* Coreboot already places modules at right place. */
|
||||
#ifndef GRUB_MACHINE_COREBOOT
|
||||
add r1, r1, r2
|
||||
add r0, r0, r2
|
||||
sub r1, r1, #4
|
||||
@@ -103,6 +139,7 @@ FUNCTION(codestart)
|
||||
str r3, [r1], #-4 @ *dst-- = r3
|
||||
subs r2, #4 @ remaining -= 4
|
||||
bne 1b @ while remaining != 0
|
||||
#endif
|
||||
|
||||
@ Since we _are_ the C run-time, we need to manually zero the BSS
|
||||
@ region before continuing
|
||||
@@ -120,64 +157,21 @@ FUNCTION(codestart)
|
||||
|
||||
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
|
||||
@ U-boot context stack space
|
||||
entry_state_end:
|
||||
@ U-boot/coreboot context stack space
|
||||
VARIABLE(grub_arm_saved_registers)
|
||||
.long 0 @ r0
|
||||
.long 0 @ r1
|
||||
.long 0 @ r2
|
||||
.long 0 @ r3
|
||||
.long 0 @ r4
|
||||
.long 0 @ r5
|
||||
.long 0 @ r6
|
||||
.long 0 @ r7
|
||||
gd_backup:
|
||||
.long 0 @ r8 - U-Boot global data pointer up to 2013-09-21
|
||||
.long 0 @ r9 - U-Boot global data pointer 2013-09-21 onwards
|
||||
.long 0 @ r7
|
||||
.long 0 @ r8
|
||||
.long 0 @ r9
|
||||
.long 0 @ r10
|
||||
.long 0 @ r11
|
||||
VARIABLE(grub_uboot_search_hint)@ U-Boot stack pointer -
|
||||
.long 0 @ also API signature address hint.
|
||||
.long 0 @ sp
|
||||
.long 0 @ lr
|
||||
entry_state: @ backup for U-Boot context
|
||||
|
||||
@ GRUB context stack space
|
||||
transition_space:
|
||||
.long 0 @ r8
|
||||
.long 0 @ lr
|
||||
.long 0 @ r9
|
||||
|
||||
VARIABLE(grub_uboot_syscall_ptr)
|
||||
.long 0 @
|
||||
|
||||
END
|
||||
entry_state:
|
||||
70
grub-core/kern/arm/uboot/init.c
Normal file
70
grub-core/kern/arm/uboot/init.c
Normal 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
grub-core/kern/arm/uboot/uboot.S
Normal file
73
grub-core/kern/arm/uboot/uboot.S
Normal 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
|
||||
@@ -132,6 +132,12 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr,
|
||||
*abs_place = (grub_uint64_t) sym_addr;
|
||||
}
|
||||
break;
|
||||
case R_AARCH64_ADD_ABS_LO12_NC:
|
||||
grub_arm64_set_abs_lo12 (place, sym_addr);
|
||||
break;
|
||||
case R_AARCH64_LDST64_ABS_LO12_NC:
|
||||
grub_arm64_set_abs_lo12_ldst64 (place, sym_addr);
|
||||
break;
|
||||
case R_AARCH64_CALL26:
|
||||
case R_AARCH64_JUMP26:
|
||||
{
|
||||
@@ -154,6 +160,18 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr,
|
||||
grub_arm64_set_xxxx26_offset (place, offset);
|
||||
}
|
||||
break;
|
||||
case R_AARCH64_ADR_PREL_PG_HI21:
|
||||
{
|
||||
grub_int64_t offset = (sym_addr & ~0xfffULL) - (((grub_uint64_t) place) & ~0xfffULL);
|
||||
|
||||
if (!grub_arm64_check_hi21_signed (offset))
|
||||
return grub_error (GRUB_ERR_BAD_MODULE,
|
||||
"HI21 out of range");
|
||||
|
||||
grub_arm64_set_hi21 (place, offset);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
||||
N_("relocation 0x%x is not implemented yet"),
|
||||
|
||||
@@ -53,3 +53,43 @@ grub_arm64_set_xxxx26_offset (grub_uint32_t *place, grub_int64_t offset)
|
||||
*place &= insmask;
|
||||
*place |= grub_cpu_to_le32 (offset >> 2) & ~insmask;
|
||||
}
|
||||
|
||||
int
|
||||
grub_arm64_check_hi21_signed (grub_int64_t offset)
|
||||
{
|
||||
if (offset != (grub_int64_t)(grub_int32_t)offset)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
grub_arm64_set_hi21 (grub_uint32_t *place, grub_int64_t offset)
|
||||
{
|
||||
const grub_uint32_t insmask = grub_cpu_to_le32_compile_time (0x9f00001f);
|
||||
grub_uint32_t val;
|
||||
|
||||
offset >>= 12;
|
||||
|
||||
val = ((offset & 3) << 29) | (((offset >> 2) & 0x7ffff) << 5);
|
||||
|
||||
*place &= insmask;
|
||||
*place |= grub_cpu_to_le32 (val) & ~insmask;
|
||||
}
|
||||
|
||||
void
|
||||
grub_arm64_set_abs_lo12 (grub_uint32_t *place, grub_int64_t target)
|
||||
{
|
||||
const grub_uint32_t insmask = grub_cpu_to_le32_compile_time (0xffc003ff);
|
||||
|
||||
*place &= insmask;
|
||||
*place |= grub_cpu_to_le32 (target << 10) & ~insmask;
|
||||
}
|
||||
|
||||
void
|
||||
grub_arm64_set_abs_lo12_ldst64 (grub_uint32_t *place, grub_int64_t target)
|
||||
{
|
||||
const grub_uint32_t insmask = grub_cpu_to_le32_compile_time (0xfff803ff);
|
||||
|
||||
*place &= insmask;
|
||||
*place |= grub_cpu_to_le32 (target << 7) & ~insmask;
|
||||
}
|
||||
|
||||
60
grub-core/kern/arm64/efi/init.c
Normal file
60
grub-core/kern/arm64/efi/init.c
Normal file
@@ -0,0 +1,60 @@
|
||||
/* init.c - initialize an arm-based EFI system */
|
||||
/*
|
||||
* 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/env.h>
|
||||
#include <grub/kernel.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/time.h>
|
||||
#include <grub/efi/efi.h>
|
||||
#include <grub/loader.h>
|
||||
|
||||
static grub_uint64_t timer_frequency_in_khz;
|
||||
|
||||
static grub_uint64_t
|
||||
grub_efi_get_time_ms (void)
|
||||
{
|
||||
grub_uint64_t tmr;
|
||||
asm volatile("mrs %0, cntvct_el0" : "=r" (tmr));
|
||||
|
||||
return tmr / timer_frequency_in_khz;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
grub_machine_init (void)
|
||||
{
|
||||
grub_uint64_t timer_frequency;
|
||||
|
||||
grub_efi_init ();
|
||||
|
||||
asm volatile("mrs %0, cntfrq_el0" : "=r" (timer_frequency));
|
||||
timer_frequency_in_khz = timer_frequency / 1000;
|
||||
|
||||
grub_install_get_time_ms (grub_efi_get_time_ms);
|
||||
}
|
||||
|
||||
void
|
||||
grub_machine_fini (int flags)
|
||||
{
|
||||
if (!(flags & GRUB_LOADER_FLAG_NORETURN))
|
||||
return;
|
||||
|
||||
grub_efi_fini ();
|
||||
}
|
||||
@@ -16,8 +16,8 @@
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/machine/memory.h>
|
||||
#include <grub/machine/lbio.h>
|
||||
#include <grub/memory.h>
|
||||
#include <grub/coreboot/lbio.h>
|
||||
#include <grub/types.h>
|
||||
#include <grub/err.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 end = mem_region->addr + mem_region->size;
|
||||
#ifdef __i386__
|
||||
/* Mark region 0xa0000 - 0x100000 as reserved. */
|
||||
if (start < 0x100000 && end >= 0xa0000
|
||||
&& 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)
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
if (ctx->hook (start, end - start,
|
||||
/* Multiboot mmaps match with the coreboot mmap
|
||||
definition. Therefore, we can just pass type
|
||||
@@ -333,8 +333,11 @@ grub_dl_resolve_symbols (grub_dl_t mod, Elf_Ehdr *e)
|
||||
if (s->sh_type == SHT_SYMTAB)
|
||||
break;
|
||||
|
||||
/* Module without symbol table may still be used to pull in dependencies.
|
||||
We verify at build time that such modules do not contain any relocations
|
||||
that may reference symbol table. */
|
||||
if (i == e->e_shnum)
|
||||
return grub_error (GRUB_ERR_BAD_MODULE, N_("no symbol table"));
|
||||
return GRUB_ERR_NONE;
|
||||
|
||||
#ifdef GRUB_MODULES_MACHINE_READONLY
|
||||
mod->symtab = grub_malloc (s->sh_size);
|
||||
@@ -576,6 +579,9 @@ grub_dl_relocate_symbols (grub_dl_t mod, void *ehdr)
|
||||
|
||||
if (seg)
|
||||
{
|
||||
if (!mod->symtab)
|
||||
return grub_error (GRUB_ERR_BAD_MODULE, "relocation without symbol table");
|
||||
|
||||
err = grub_arch_dl_relocate_symbols (mod, ehdr, s, seg);
|
||||
if (err)
|
||||
return err;
|
||||
@@ -605,7 +611,7 @@ grub_dl_load_core_noinit (void *addr, grub_size_t size)
|
||||
}
|
||||
|
||||
/* Make sure that every section is within the core. */
|
||||
if (size < e->e_shoff + e->e_shentsize * e->e_shnum)
|
||||
if (size < e->e_shoff + (grub_uint32_t) e->e_shentsize * e->e_shnum)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_OS, "ELF sections outside core");
|
||||
return 0;
|
||||
|
||||
@@ -12,7 +12,7 @@ grub_elfXX_load_phdrs (grub_elf_t elf)
|
||||
if (elf->phdrs)
|
||||
return GRUB_ERR_NONE;
|
||||
|
||||
phdrs_size = elf->ehdr.ehdrXX.e_phnum * elf->ehdr.ehdrXX.e_phentsize;
|
||||
phdrs_size = (grub_uint32_t) elf->ehdr.ehdrXX.e_phnum * elf->ehdr.ehdrXX.e_phentsize;
|
||||
|
||||
grub_dprintf ("elf", "Loading program headers at 0x%llx, size 0x%lx.\n",
|
||||
(unsigned long long) elf->ehdr.ehdrXX.e_phoff,
|
||||
|
||||
@@ -161,9 +161,9 @@ grub_util_biosdisk_open (const char *name, grub_disk_t disk)
|
||||
{
|
||||
struct stat st;
|
||||
# if GRUB_DISK_DEVS_ARE_CHAR
|
||||
if (fstat (fd, &st) < 0 || ! S_ISCHR (st.st_mode))
|
||||
if (fstat (fd, &st) >= 0 && S_ISCHR (st.st_mode))
|
||||
# else
|
||||
if (fstat (fd, &st) < 0 || ! S_ISBLK (st.st_mode))
|
||||
if (fstat (fd, &st) >= 0 && S_ISBLK (st.st_mode))
|
||||
# endif
|
||||
data->is_disk = 1;
|
||||
}
|
||||
|
||||
@@ -65,6 +65,12 @@ grub_reboot (void)
|
||||
longjmp (main_env, 1);
|
||||
}
|
||||
|
||||
void
|
||||
grub_exit (void)
|
||||
{
|
||||
grub_reboot ();
|
||||
}
|
||||
|
||||
void
|
||||
grub_machine_init (void)
|
||||
{
|
||||
@@ -195,7 +201,7 @@ main (int argc, char *argv[])
|
||||
volatile int hold = 0;
|
||||
size_t total_module_size = sizeof (struct grub_module_info), memdisk_size = 0;
|
||||
struct grub_module_info *modinfo;
|
||||
char *mods;
|
||||
void *mods;
|
||||
|
||||
grub_util_host_init (&argc, &argv);
|
||||
|
||||
@@ -226,10 +232,10 @@ main (int argc, char *argv[])
|
||||
struct grub_module_header *header = (struct grub_module_header *) mods;
|
||||
header->type = OBJ_TYPE_MEMDISK;
|
||||
header->size = memdisk_size + sizeof (*header);
|
||||
mods += sizeof (*header);
|
||||
mods = header + 1;
|
||||
|
||||
grub_util_load_image (arguments.mem_disk, mods);
|
||||
mods += memdisk_size;
|
||||
mods = (char *) mods + memdisk_size;
|
||||
}
|
||||
|
||||
grub_modbase = (grub_addr_t) modinfo;
|
||||
|
||||
@@ -134,11 +134,13 @@ xasprintf (const char *fmt, ...)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined (GRUB_MACHINE_EMU) || defined (GRUB_UTIL)
|
||||
void
|
||||
grub_exit (void)
|
||||
{
|
||||
exit (1);
|
||||
}
|
||||
#endif
|
||||
|
||||
grub_uint64_t
|
||||
grub_get_time_ms (void)
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
*/
|
||||
|
||||
#include <grub/i386/coreboot/memory.h>
|
||||
#include <grub/i386/coreboot/lbio.h>
|
||||
#include <grub/coreboot/lbio.h>
|
||||
#include <grub/types.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/misc.h>
|
||||
|
||||
@@ -44,6 +44,13 @@ FUNCTION(grub_bios_interrupt)
|
||||
movl 24(%edx), %esi
|
||||
movl 28(%edx), %edx
|
||||
|
||||
/*
|
||||
Via C3 CPUs have cache coherence problems, so we need to call
|
||||
wbinvd at these 2 points. As wbinvd slows down boot, don't do
|
||||
it on non-VIA. 9090 is nop nop. */
|
||||
VARIABLE(grub_bios_via_workaround1)
|
||||
.byte 0x90, 0x90
|
||||
|
||||
PROT_TO_REAL
|
||||
.code16
|
||||
pushf
|
||||
@@ -92,6 +99,10 @@ intno:
|
||||
movw %ax, LOCAL(bios_register_es)
|
||||
|
||||
popf
|
||||
|
||||
VARIABLE(grub_bios_via_workaround2)
|
||||
.byte 0x90, 0x90
|
||||
|
||||
REAL_TO_PROT
|
||||
.code32
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <grub/env.h>
|
||||
#include <grub/cache.h>
|
||||
#include <grub/time.h>
|
||||
#include <grub/cpu/cpuid.h>
|
||||
#include <grub/cpu/tsc.h>
|
||||
#include <grub/machine/time.h>
|
||||
|
||||
@@ -184,6 +185,26 @@ mmap_iterate_hook (grub_uint64_t addr, grub_uint64_t size,
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern grub_uint16_t grub_bios_via_workaround1, grub_bios_via_workaround2;
|
||||
|
||||
/* Via needs additional wbinvd. */
|
||||
static void
|
||||
grub_via_workaround_init (void)
|
||||
{
|
||||
grub_uint32_t manufacturer[3], max_cpuid;
|
||||
if (! grub_cpu_is_cpuid_supported ())
|
||||
return;
|
||||
|
||||
grub_cpuid (0, max_cpuid, manufacturer[0], manufacturer[2], manufacturer[1]);
|
||||
|
||||
if (grub_memcmp (manufacturer, "CentaurHauls", 12) != 0)
|
||||
return;
|
||||
|
||||
grub_bios_via_workaround1 = 0x090f;
|
||||
grub_bios_via_workaround2 = 0x090f;
|
||||
asm volatile ("wbinvd");
|
||||
}
|
||||
|
||||
void
|
||||
grub_machine_init (void)
|
||||
{
|
||||
@@ -193,6 +214,9 @@ grub_machine_init (void)
|
||||
#endif
|
||||
grub_addr_t modend;
|
||||
|
||||
/* This has to happen before any BIOS calls. */
|
||||
grub_via_workaround_init ();
|
||||
|
||||
grub_modbase = GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR + (_edata - _start);
|
||||
|
||||
/* Initialize the console as early as possible. */
|
||||
|
||||
@@ -43,22 +43,6 @@ grub_tsc_get_time_ms (void)
|
||||
return ((al * grub_tsc_rate) >> 32) + ah * grub_tsc_rate;
|
||||
}
|
||||
|
||||
static __inline int
|
||||
grub_cpu_is_tsc_supported (void)
|
||||
{
|
||||
#ifndef GRUB_MACHINE_XEN
|
||||
grub_uint32_t a,b,c,d;
|
||||
if (! grub_cpu_is_cpuid_supported ())
|
||||
return 0;
|
||||
|
||||
grub_cpuid(1,a,b,c,d);
|
||||
|
||||
return (d & (1 << 4)) != 0;
|
||||
#else
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
calibrate_tsc_hardcode (void)
|
||||
{
|
||||
|
||||
@@ -24,129 +24,35 @@
|
||||
#include <grub/time.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/i386/tsc.h>
|
||||
#include <grub/i386/pmtimer.h>
|
||||
#include <grub/acpi.h>
|
||||
#include <grub/cpu/io.h>
|
||||
|
||||
static void *
|
||||
grub_acpi_rsdt_find_table (struct grub_acpi_table_header *rsdt, const char *sig)
|
||||
{
|
||||
grub_size_t s;
|
||||
grub_uint32_t *ptr;
|
||||
|
||||
if (!rsdt)
|
||||
return 0;
|
||||
|
||||
if (grub_memcmp (rsdt->signature, "RSDT", 4) != 0)
|
||||
return 0;
|
||||
|
||||
ptr = (grub_uint32_t *) (rsdt + 1);
|
||||
s = (rsdt->length - sizeof (*rsdt)) / sizeof (grub_uint32_t);
|
||||
for (; s; s--, ptr++)
|
||||
{
|
||||
struct grub_acpi_table_header *tbl;
|
||||
tbl = (struct grub_acpi_table_header *) (grub_addr_t) *ptr;
|
||||
if (grub_memcmp (tbl->signature, sig, 4) == 0)
|
||||
return tbl;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void *
|
||||
grub_acpi_xsdt_find_table (struct grub_acpi_table_header *xsdt, const char *sig)
|
||||
{
|
||||
grub_size_t s;
|
||||
grub_uint64_t *ptr;
|
||||
|
||||
if (!xsdt)
|
||||
return 0;
|
||||
|
||||
if (grub_memcmp (xsdt->signature, "XSDT", 4) != 0)
|
||||
return 0;
|
||||
|
||||
ptr = (grub_uint64_t *) (xsdt + 1);
|
||||
s = (xsdt->length - sizeof (*xsdt)) / sizeof (grub_uint32_t);
|
||||
for (; s; s--, ptr++)
|
||||
{
|
||||
struct grub_acpi_table_header *tbl;
|
||||
#if GRUB_CPU_SIZEOF_VOID_P != 8
|
||||
if (*ptr >> 32)
|
||||
continue;
|
||||
#endif
|
||||
tbl = (struct grub_acpi_table_header *) (grub_addr_t) *ptr;
|
||||
if (grub_memcmp (tbl->signature, sig, 4) == 0)
|
||||
return tbl;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct grub_acpi_fadt *
|
||||
grub_acpi_find_fadt (void)
|
||||
{
|
||||
struct grub_acpi_fadt *fadt = 0;
|
||||
struct grub_acpi_rsdp_v10 *rsdpv1;
|
||||
struct grub_acpi_rsdp_v20 *rsdpv2;
|
||||
rsdpv1 = grub_machine_acpi_get_rsdpv1 ();
|
||||
if (rsdpv1)
|
||||
fadt = grub_acpi_rsdt_find_table ((struct grub_acpi_table_header *)
|
||||
(grub_addr_t) rsdpv1->rsdt_addr,
|
||||
GRUB_ACPI_FADT_SIGNATURE);
|
||||
if (fadt)
|
||||
return fadt;
|
||||
rsdpv2 = grub_machine_acpi_get_rsdpv2 ();
|
||||
if (rsdpv2)
|
||||
fadt = grub_acpi_rsdt_find_table ((struct grub_acpi_table_header *)
|
||||
(grub_addr_t) rsdpv2->rsdpv1.rsdt_addr,
|
||||
GRUB_ACPI_FADT_SIGNATURE);
|
||||
if (fadt)
|
||||
return fadt;
|
||||
if (rsdpv2
|
||||
#if GRUB_CPU_SIZEOF_VOID_P != 8
|
||||
&& !(rsdpv2->xsdt_addr >> 32)
|
||||
#endif
|
||||
)
|
||||
fadt = grub_acpi_xsdt_find_table ((struct grub_acpi_table_header *)
|
||||
(grub_addr_t) rsdpv2->xsdt_addr,
|
||||
GRUB_ACPI_FADT_SIGNATURE);
|
||||
if (fadt)
|
||||
return fadt;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
grub_tsc_calibrate_from_pmtimer (void)
|
||||
grub_uint64_t
|
||||
grub_pmtimer_wait_count_tsc (grub_port_t pmtimer,
|
||||
grub_uint16_t num_pm_ticks)
|
||||
{
|
||||
grub_uint32_t start;
|
||||
grub_uint32_t last;
|
||||
grub_uint32_t cur, end;
|
||||
struct grub_acpi_fadt *fadt;
|
||||
grub_port_t p;
|
||||
grub_uint64_t start_tsc;
|
||||
grub_uint64_t end_tsc;
|
||||
int num_iter = 0;
|
||||
|
||||
fadt = grub_acpi_find_fadt ();
|
||||
if (!fadt)
|
||||
return 0;
|
||||
p = fadt->pmtimer;
|
||||
if (!p)
|
||||
return 0;
|
||||
|
||||
start = grub_inl (p) & 0xffffff;
|
||||
start = grub_inl (pmtimer) & 0xffffff;
|
||||
last = start;
|
||||
/* It's 3.579545 MHz clock. Wait 1 ms. */
|
||||
end = start + 3580;
|
||||
end = start + num_pm_ticks;
|
||||
start_tsc = grub_get_tsc ();
|
||||
while (1)
|
||||
{
|
||||
cur = grub_inl (p) & 0xffffff;
|
||||
cur = grub_inl (pmtimer) & 0xffffff;
|
||||
if (cur < last)
|
||||
cur |= 0x1000000;
|
||||
num_iter++;
|
||||
if (cur >= end)
|
||||
{
|
||||
end_tsc = grub_get_tsc ();
|
||||
grub_tsc_rate = grub_divmod64 ((1ULL << 32), end_tsc - start_tsc, 0);
|
||||
return 1;
|
||||
return end_tsc - start_tsc;
|
||||
}
|
||||
/* Check for broken PM timer.
|
||||
50000000 TSCs is between 5 ms (10GHz) and 200 ms (250 MHz)
|
||||
@@ -158,3 +64,25 @@ grub_tsc_calibrate_from_pmtimer (void)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
grub_tsc_calibrate_from_pmtimer (void)
|
||||
{
|
||||
struct grub_acpi_fadt *fadt;
|
||||
grub_port_t pmtimer;
|
||||
grub_uint64_t tsc_diff;
|
||||
|
||||
fadt = grub_acpi_find_fadt ();
|
||||
if (!fadt)
|
||||
return 0;
|
||||
pmtimer = fadt->pmtimer;
|
||||
if (!pmtimer)
|
||||
return 0;
|
||||
|
||||
/* It's 3.579545 MHz clock. Wait 1 ms. */
|
||||
tsc_diff = grub_pmtimer_wait_count_tsc (pmtimer, 3580);
|
||||
if (tsc_diff == 0)
|
||||
return 0;
|
||||
grub_tsc_rate = grub_divmod64 ((1ULL << 32), tsc_diff, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -46,11 +46,19 @@
|
||||
#define HEAP_MIN_SIZE (unsigned long) (2 * 1024 * 1024)
|
||||
|
||||
/* The maximum heap size we're going to claim */
|
||||
#ifdef __i386__
|
||||
#define HEAP_MAX_SIZE (unsigned long) (64 * 1024 * 1024)
|
||||
#else
|
||||
#define HEAP_MAX_SIZE (unsigned long) (32 * 1024 * 1024)
|
||||
#endif
|
||||
|
||||
/* If possible, we will avoid claiming heap above this address, because it
|
||||
seems to cause relocation problems with OSes that link at 4 MiB */
|
||||
#ifdef __i386__
|
||||
#define HEAP_MAX_ADDR (unsigned long) (64 * 1024 * 1024)
|
||||
#else
|
||||
#define HEAP_MAX_ADDR (unsigned long) (32 * 1024 * 1024)
|
||||
#endif
|
||||
|
||||
extern char _start[];
|
||||
extern char _end[];
|
||||
|
||||
@@ -740,6 +740,12 @@ parse_printf_args (const char *fmt0, struct printf_args *args,
|
||||
fmt++;
|
||||
|
||||
c = *fmt++;
|
||||
if (c == '%')
|
||||
{
|
||||
n--;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c == 'l')
|
||||
{
|
||||
c = *fmt++;
|
||||
@@ -876,6 +882,7 @@ grub_vsnprintf_real (char *str, grub_size_t max_len, const char *fmt0,
|
||||
if (c == '%')
|
||||
{
|
||||
write_char (str, &count, max_len,c);
|
||||
n--;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1099,6 +1106,8 @@ grub_fatal (const char *fmt, ...)
|
||||
grub_vprintf (_(fmt), ap);
|
||||
va_end (ap);
|
||||
|
||||
grub_refresh ();
|
||||
|
||||
grub_abort ();
|
||||
}
|
||||
|
||||
|
||||
@@ -325,6 +325,15 @@ grub_memalign (grub_size_t align, grub_size_t size)
|
||||
if (!grub_mm_base)
|
||||
goto fail;
|
||||
|
||||
if (size > ~(grub_size_t) align)
|
||||
goto fail;
|
||||
|
||||
/* We currently assume at least a 32-bit grub_size_t,
|
||||
so limiting allocations to <adress space size> - 1MiB
|
||||
in name of sanity is beneficial. */
|
||||
if ((size + align) > ~(grub_size_t) 0x100000)
|
||||
goto fail;
|
||||
|
||||
align = (align >> GRUB_MM_ALIGN_LOG2);
|
||||
if (align == 0)
|
||||
align = 1;
|
||||
|
||||
@@ -43,13 +43,17 @@ grub_rescue_parse_line (char *line,
|
||||
|
||||
/* In case of an assignment set the environment accordingly
|
||||
instead of calling a function. */
|
||||
if (n == 1 && grub_strchr (line, '='))
|
||||
if (n == 1)
|
||||
{
|
||||
char *val = grub_strchr (args[0], '=');
|
||||
val[0] = 0;
|
||||
grub_env_set (args[0], val + 1);
|
||||
val[0] = '=';
|
||||
goto quit;
|
||||
|
||||
if (val)
|
||||
{
|
||||
val[0] = 0;
|
||||
grub_env_set (args[0], val + 1);
|
||||
val[0] = '=';
|
||||
goto quit;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the command name. */
|
||||
@@ -72,6 +76,7 @@ grub_rescue_parse_line (char *line,
|
||||
}
|
||||
|
||||
quit:
|
||||
/* Arguments are returned in single memory chunk separated by zeroes */
|
||||
grub_free (args[0]);
|
||||
grub_free (args);
|
||||
|
||||
|
||||
@@ -36,30 +36,14 @@
|
||||
extern char __bss_start[];
|
||||
extern char _end[];
|
||||
extern grub_size_t grub_total_module_size;
|
||||
extern int (*grub_uboot_syscall_ptr) (int, int *, ...);
|
||||
static unsigned long timer_start;
|
||||
|
||||
extern grub_uint32_t grub_uboot_machine_type;
|
||||
extern grub_addr_t grub_uboot_boot_data;
|
||||
|
||||
void
|
||||
grub_exit (void)
|
||||
{
|
||||
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
|
||||
uboot_timer_ms (void)
|
||||
{
|
||||
|
||||
@@ -39,48 +39,13 @@
|
||||
* 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 grub_addr_t grub_uboot_search_hint;
|
||||
|
||||
static struct sys_info uboot_sys_info;
|
||||
static struct mem_region uboot_mem_info[5];
|
||||
static struct device_info * 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
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
int size = 0;
|
||||
grub_uint64_t *ptr = (void *) ((grub_addr_t) fdt
|
||||
+ grub_fdt_get_off_mem_rsvmap (fdt));
|
||||
grub_unaligned_uint64_t *ptr = (void *) ((grub_addr_t) fdt
|
||||
+ grub_fdt_get_off_mem_rsvmap (fdt));
|
||||
|
||||
do
|
||||
{
|
||||
size += 2 * sizeof(*ptr);
|
||||
if (!*ptr && !*(ptr + 1))
|
||||
if (!ptr[0].val && !ptr[1].val)
|
||||
return size;
|
||||
ptr += 2;
|
||||
} 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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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
|
||||
functions in this file and returns success, the other functions are
|
||||
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_last_comp_version (fdt) > FDT_SUPPORTED_VERSION)
|
||||
|| (grub_fdt_get_off_dt_struct (fdt) & 0x00000003)
|
||||
@@ -286,7 +286,7 @@ int grub_fdt_check_header_nosize (void *fdt)
|
||||
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)
|
||||
|| (grub_fdt_get_totalsize (fdt) > size)
|
||||
@@ -295,41 +295,29 @@ int grub_fdt_check_header (void *fdt, unsigned int size)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Find a direct sub-node of a given parent node. */
|
||||
int grub_fdt_find_subnode (const void *fdt, unsigned int parentoffset,
|
||||
const char *name)
|
||||
static const grub_uint32_t *
|
||||
advance_token (const void *fdt, const grub_uint32_t *token, const grub_uint32_t *end, int skip_current)
|
||||
{
|
||||
grub_uint32_t *token, *end;
|
||||
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)
|
||||
for (; token < end; skip_current = 0)
|
||||
{
|
||||
switch (grub_be_to_cpu32(*token))
|
||||
switch (grub_be_to_cpu32 (*token))
|
||||
{
|
||||
case FDT_BEGIN_NODE:
|
||||
node_name = (char *) (token + 1);
|
||||
if (node_name + grub_strlen (name) >= (char *) end)
|
||||
return -1;
|
||||
if (!grub_strcmp (node_name, name))
|
||||
return (int) ((grub_addr_t) token - (grub_addr_t) fdt
|
||||
- grub_fdt_get_off_dt_struct (fdt));
|
||||
token = get_next_node (fdt, node_name);
|
||||
if (!token)
|
||||
return -1;
|
||||
break;
|
||||
if (skip_current)
|
||||
{
|
||||
token = get_next_node (fdt, (char *) (token + 1));
|
||||
continue;
|
||||
}
|
||||
char *ptr;
|
||||
for (ptr = (char *) (token + 1); *ptr && ptr < (char *) end; ptr++);
|
||||
if (ptr >= (char *) end)
|
||||
return 0;
|
||||
return token;
|
||||
case FDT_PROP:
|
||||
/* Skip property token and following data (len, nameoff and property
|
||||
value). */
|
||||
if (token >= end - 1)
|
||||
return -1;
|
||||
return 0;
|
||||
token += prop_entry_size(grub_be_to_cpu32(*(token + 1)))
|
||||
/ sizeof(*token);
|
||||
break;
|
||||
@@ -337,10 +325,74 @@ int grub_fdt_find_subnode (const void *fdt, unsigned int parentoffset,
|
||||
token++;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
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 (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,
|
||||
@@ -359,6 +411,24 @@ int grub_fdt_add_subnode (void *fdt, unsigned int parentoffset,
|
||||
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,
|
||||
const void *val, grub_uint32_t len)
|
||||
{
|
||||
|
||||
103
grub-core/lib/i386/random.c
Normal file
103
grub-core/lib/i386/random.c
Normal file
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* 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/random.h>
|
||||
#include <grub/i386/io.h>
|
||||
#include <grub/i386/tsc.h>
|
||||
#include <grub/i386/pmtimer.h>
|
||||
#include <grub/acpi.h>
|
||||
|
||||
static int have_tsc = -1, have_pmtimer = -1;
|
||||
static grub_port_t pmtimer_port;
|
||||
|
||||
static int
|
||||
detect_pmtimer (void)
|
||||
{
|
||||
struct grub_acpi_fadt *fadt;
|
||||
fadt = grub_acpi_find_fadt ();
|
||||
if (!fadt)
|
||||
return 0;
|
||||
pmtimer_port = fadt->pmtimer;
|
||||
if (!pmtimer_port)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
pmtimer_tsc_get_random_bit (void)
|
||||
{
|
||||
/* It's hard to come up with figures about pmtimer and tsc jitter but
|
||||
50 ppm seems to be typical. So we need 10^6/50 tsc cycles to get drift
|
||||
of one tsc cycle. With TSC at least of 800 MHz it means 1/(50*800)
|
||||
= 1/40000 s or about 3579545 / 40000 = 90 pmtimer ticks.
|
||||
This gives us rate of 40000 bit/s or 5 kB/s.
|
||||
*/
|
||||
grub_uint64_t tsc_diff;
|
||||
tsc_diff = grub_pmtimer_wait_count_tsc (pmtimer_port, 90);
|
||||
if (tsc_diff == 0)
|
||||
{
|
||||
have_pmtimer = 0;
|
||||
return -1;
|
||||
}
|
||||
return tsc_diff & 1;
|
||||
}
|
||||
|
||||
static int
|
||||
pmtimer_tsc_get_random_byte (void)
|
||||
{
|
||||
grub_uint8_t ret = 0;
|
||||
int i, c;
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
c = pmtimer_tsc_get_random_bit ();
|
||||
if (c < 0)
|
||||
return -1;
|
||||
ret |= c << i;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
pmtimer_fill_buffer (void *buffer, grub_size_t sz)
|
||||
{
|
||||
grub_uint8_t *p = buffer;
|
||||
int c;
|
||||
while (sz)
|
||||
{
|
||||
c = pmtimer_tsc_get_random_byte ();
|
||||
if (c < 0)
|
||||
return 0;
|
||||
*p++ = c;
|
||||
sz--;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
grub_crypto_arch_get_random (void *buffer, grub_size_t sz)
|
||||
{
|
||||
if (have_tsc == -1)
|
||||
have_tsc = grub_cpu_is_tsc_supported ();
|
||||
if (!have_tsc)
|
||||
return 0;
|
||||
if (have_pmtimer == -1)
|
||||
have_pmtimer = detect_pmtimer ();
|
||||
if (!have_pmtimer)
|
||||
return 0;
|
||||
return pmtimer_fill_buffer (buffer, sz);
|
||||
}
|
||||
@@ -31,7 +31,6 @@ GRUB_MOD_LICENSE ("GPLv2+");
|
||||
desired derived output length DKLEN. Output buffer is DK which
|
||||
must have room for at least DKLEN octets. The output buffer will
|
||||
be filled with the derived data. */
|
||||
#pragma GCC diagnostic ignored "-Wunreachable-code"
|
||||
|
||||
gcry_err_code_t
|
||||
grub_crypto_pbkdf2 (const struct gcry_md_spec *md,
|
||||
|
||||
120
grub-core/lib/random.c
Normal file
120
grub-core/lib/random.c
Normal file
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* 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/random.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/lib/hexdump.h>
|
||||
#include <grub/command.h>
|
||||
#include <grub/mm.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
grub_err_t
|
||||
grub_crypto_get_random (void *buffer, grub_size_t sz)
|
||||
{
|
||||
/* This is an arbitrer between different methods.
|
||||
TODO: Add more methods in the future. */
|
||||
/* TODO: Add some PRNG smartness to reduce damage from bad entropy. */
|
||||
if (grub_crypto_arch_get_random (buffer, sz))
|
||||
return GRUB_ERR_NONE;
|
||||
return grub_error (GRUB_ERR_IO, "no random sources found");
|
||||
}
|
||||
|
||||
static int
|
||||
get_num_digits (int val)
|
||||
{
|
||||
int ret = 0;
|
||||
while (val != 0)
|
||||
{
|
||||
ret++;
|
||||
val /= 10;
|
||||
}
|
||||
if (ret == 0)
|
||||
return 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#pragma GCC diagnostic ignored "-Wformat-nonliteral"
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_hexdump_random (grub_command_t cmd __attribute__ ((unused)), int argc, char **args)
|
||||
{
|
||||
grub_size_t length = 64;
|
||||
grub_err_t err;
|
||||
void *buffer;
|
||||
grub_uint8_t *ptr;
|
||||
int stats[256];
|
||||
int i, digits = 2;
|
||||
char template[10];
|
||||
|
||||
if (argc >= 1)
|
||||
length = grub_strtoull (args[0], 0, 0);
|
||||
|
||||
if (length == 0)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "length pust be positive");
|
||||
|
||||
buffer = grub_malloc (length);
|
||||
if (!buffer)
|
||||
return grub_errno;
|
||||
|
||||
err = grub_crypto_get_random (buffer, length);
|
||||
if (err)
|
||||
{
|
||||
grub_free (buffer);
|
||||
return err;
|
||||
}
|
||||
|
||||
hexdump (0, buffer, length);
|
||||
grub_memset(stats, 0, sizeof(stats));
|
||||
for (ptr = buffer; ptr < (grub_uint8_t *) buffer + length; ptr++)
|
||||
stats[*ptr]++;
|
||||
grub_printf ("Statistics:\n");
|
||||
for (i = 0; i < 256; i++)
|
||||
{
|
||||
int z = get_num_digits (stats[i]);
|
||||
if (z > digits)
|
||||
digits = z;
|
||||
}
|
||||
|
||||
grub_snprintf (template, sizeof (template), "%%0%dd ", digits);
|
||||
|
||||
for (i = 0; i < 256; i++)
|
||||
{
|
||||
grub_printf ("%s", template);//, stats[i]);
|
||||
if ((i & 0xf) == 0xf)
|
||||
grub_printf ("\n");
|
||||
}
|
||||
|
||||
grub_free (buffer);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_command_t cmd;
|
||||
|
||||
GRUB_MOD_INIT (random)
|
||||
{
|
||||
cmd = grub_register_command ("hexdump_random", grub_cmd_hexdump_random,
|
||||
N_("[LENGTH]"),
|
||||
N_("Hexdump random data."));
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI (random)
|
||||
{
|
||||
grub_unregister_command (cmd);
|
||||
}
|
||||
@@ -736,26 +736,36 @@ malloc_in_range (struct grub_relocator *rel,
|
||||
}
|
||||
isinsideafter = (!ncollisions && (nstarted || ((nlefto || nstartedfw)
|
||||
&& !nblockfw)));
|
||||
if (!isinsidebefore && isinsideafter)
|
||||
starta = from_low_priv ? ALIGN_UP (events[j].pos, align)
|
||||
: ALIGN_DOWN (events[j].pos - size, align) + size;
|
||||
if (isinsidebefore && !isinsideafter && from_low_priv)
|
||||
{
|
||||
target = starta;
|
||||
if (target < start)
|
||||
target = start;
|
||||
if (target + size <= end && target + size <= events[j].pos)
|
||||
/* Found an usable address. */
|
||||
goto found;
|
||||
}
|
||||
if (isinsidebefore && !isinsideafter && !from_low_priv)
|
||||
{
|
||||
target = starta - size;
|
||||
if (target > end - size)
|
||||
target = end - size;
|
||||
if (target >= start && target >= events[j].pos)
|
||||
goto found;
|
||||
}
|
||||
if (from_low_priv) {
|
||||
if (!isinsidebefore && isinsideafter)
|
||||
starta = ALIGN_UP (events[j].pos, align);
|
||||
|
||||
if (isinsidebefore && !isinsideafter)
|
||||
{
|
||||
target = starta;
|
||||
if (target < start)
|
||||
target = start;
|
||||
if (target + size <= end && target + size <= events[j].pos)
|
||||
/* Found an usable address. */
|
||||
goto found;
|
||||
}
|
||||
} else {
|
||||
if (!isinsidebefore && isinsideafter)
|
||||
{
|
||||
if (events[j].pos >= size)
|
||||
starta = ALIGN_DOWN (events[j].pos - size, align) + size;
|
||||
else
|
||||
starta = 0;
|
||||
}
|
||||
if (isinsidebefore && !isinsideafter && starta >= size)
|
||||
{
|
||||
target = starta - size;
|
||||
if (target > end - size)
|
||||
target = end - size;
|
||||
if (target >= start && target >= events[j].pos)
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ static grub_size_t linux_size;
|
||||
static char *linux_args;
|
||||
|
||||
static grub_uint32_t machine_type;
|
||||
static void *fdt_addr;
|
||||
static const void *current_fdt;
|
||||
|
||||
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)
|
||||
|
||||
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])
|
||||
atag += atag[0];
|
||||
return atag - atag0;
|
||||
@@ -68,10 +68,11 @@ get_atag_size (grub_uint32_t *atag)
|
||||
* Merges in command line parameters and sets up initrd addresses.
|
||||
*/
|
||||
static grub_err_t
|
||||
linux_prepare_atag (void)
|
||||
linux_prepare_atag (void *target_atag)
|
||||
{
|
||||
grub_uint32_t *atag_orig = (grub_uint32_t *) fdt_addr;
|
||||
grub_uint32_t *tmp_atag, *from, *to;
|
||||
const grub_uint32_t *atag_orig = (const grub_uint32_t *) current_fdt;
|
||||
grub_uint32_t *tmp_atag, *to;
|
||||
const grub_uint32_t *from;
|
||||
grub_size_t tmp_size;
|
||||
grub_size_t arg_size = grub_strlen (linux_args);
|
||||
char *cmdline_orig = NULL;
|
||||
@@ -142,7 +143,7 @@ linux_prepare_atag (void)
|
||||
to += 2;
|
||||
|
||||
/* 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_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.
|
||||
*/
|
||||
static grub_err_t
|
||||
linux_prepare_fdt (void)
|
||||
linux_prepare_fdt (void *target_fdt)
|
||||
{
|
||||
int node;
|
||||
int retval;
|
||||
int tmp_size;
|
||||
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);
|
||||
if (!tmp_fdt)
|
||||
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);
|
||||
|
||||
/* Find or create '/chosen' node */
|
||||
@@ -209,7 +210,7 @@ linux_prepare_fdt (void)
|
||||
}
|
||||
|
||||
/* 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_dprintf ("loader", "FDT updated for Linux boot\n");
|
||||
@@ -226,16 +227,17 @@ linux_boot (void)
|
||||
{
|
||||
kernel_entry_t linuxmain;
|
||||
int fdt_valid, atag_valid;
|
||||
void *target_fdt = 0;
|
||||
|
||||
fdt_valid = (fdt_addr && grub_fdt_check_header_nosize (fdt_addr) == 0);
|
||||
atag_valid = ((((grub_uint16_t *) fdt_addr)[3] & ~3) == 0x5440
|
||||
&& *((grub_uint32_t *) fdt_addr));
|
||||
fdt_valid = (current_fdt && grub_fdt_check_header_nosize (current_fdt) == 0);
|
||||
atag_valid = ((((const grub_uint16_t *) current_fdt)[3] & ~3) == 0x5440
|
||||
&& *((const grub_uint32_t *) current_fdt));
|
||||
grub_dprintf ("loader", "atag: %p, %x, %x, %s, %s\n",
|
||||
fdt_addr,
|
||||
((grub_uint16_t *) fdt_addr)[3],
|
||||
*((grub_uint32_t *) fdt_addr),
|
||||
(char *) fdt_addr,
|
||||
(char *) fdt_addr + 1);
|
||||
current_fdt,
|
||||
((const grub_uint16_t *) current_fdt)[3],
|
||||
*((const grub_uint32_t *) current_fdt),
|
||||
(const char *) current_fdt,
|
||||
(const char *) current_fdt + 1);
|
||||
|
||||
if (!fdt_valid && machine_type == GRUB_ARM_MACHINE_TYPE_FDT)
|
||||
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);
|
||||
|
||||
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)
|
||||
{
|
||||
grub_err_t err;
|
||||
|
||||
err = linux_prepare_fdt ();
|
||||
err = linux_prepare_fdt (target_fdt);
|
||||
if (err)
|
||||
return err;
|
||||
grub_dprintf ("loader", "FDT @ 0x%p\n", fdt_addr);
|
||||
grub_dprintf ("loader", "FDT @ %p\n", target_fdt);
|
||||
}
|
||||
else if (atag_valid)
|
||||
{
|
||||
grub_err_t err;
|
||||
|
||||
err = linux_prepare_atag ();
|
||||
err = linux_prepare_atag (target_fdt);
|
||||
if (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");
|
||||
@@ -285,7 +304,7 @@ linux_boot (void)
|
||||
|
||||
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");
|
||||
}
|
||||
@@ -444,11 +463,26 @@ fail:
|
||||
static grub_err_t
|
||||
load_dtb (grub_file_t dtb, int size)
|
||||
{
|
||||
if ((grub_file_read (dtb, fdt_addr, size) != size)
|
||||
|| (grub_fdt_check_header (fdt_addr, size) != 0))
|
||||
return grub_error (GRUB_ERR_BAD_OS, N_("invalid device tree"));
|
||||
void *new_fdt = grub_zalloc (size);
|
||||
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"));
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -464,42 +498,13 @@ grub_cmd_devicetree (grub_command_t cmd __attribute__ ((unused)),
|
||||
|
||||
dtb = grub_file_open (argv[0]);
|
||||
if (!dtb)
|
||||
goto out;
|
||||
return grub_errno;
|
||||
|
||||
size = grub_file_size (dtb);
|
||||
if (size == 0)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_OS, "empty file");
|
||||
goto out;
|
||||
}
|
||||
|
||||
#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);
|
||||
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_error (GRUB_ERR_BAD_OS, "empty file");
|
||||
else
|
||||
load_dtb (dtb, size);
|
||||
grub_file_close (dtb);
|
||||
|
||||
return grub_errno;
|
||||
@@ -517,7 +522,7 @@ GRUB_MOD_INIT (linux)
|
||||
/* TRANSLATORS: DTB stands for device tree blob. */
|
||||
0, N_("Load DTB file."));
|
||||
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 ();
|
||||
}
|
||||
|
||||
|
||||
@@ -37,16 +37,6 @@
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
#define XEN_HYPERVISOR_NAME "xen_hypervisor"
|
||||
|
||||
#define MODULE_DEFAULT_ALIGN (0x0)
|
||||
#define MODULE_IMAGE_MIN_ALIGN MODULE_DEFAULT_ALIGN
|
||||
#define MODULE_INITRD_MIN_ALIGN MODULE_DEFAULT_ALIGN
|
||||
#define MODULE_XSM_MIN_ALIGN MODULE_DEFAULT_ALIGN
|
||||
#define MODULE_CUSTOM_MIN_ALIGN MODULE_DEFAULT_ALIGN
|
||||
|
||||
#define MODULE_IMAGE_COMPATIBLE "multiboot,kernel\0multiboot,module"
|
||||
#define MODULE_INITRD_COMPATIBLE "multiboot,ramdisk\0multiboot,module"
|
||||
#define MODULE_XSM_COMPATIBLE "xen,xsm-policy\0multiboot,module"
|
||||
#define MODULE_CUSTOM_COMPATIBLE "multiboot,module"
|
||||
|
||||
/* This maximum size is defined in Power.org ePAPR V1.1
|
||||
@@ -74,14 +64,6 @@ enum module_type
|
||||
};
|
||||
typedef enum module_type module_type_t;
|
||||
|
||||
struct fdt_node_info
|
||||
{
|
||||
module_type_t type;
|
||||
|
||||
const char *compat_string;
|
||||
grub_size_t compat_string_size;
|
||||
};
|
||||
|
||||
struct xen_hypervisor_header
|
||||
{
|
||||
struct grub_arm64_linux_kernel_header efi_head;
|
||||
@@ -98,7 +80,7 @@ struct xen_boot_binary
|
||||
{
|
||||
struct xen_boot_binary *next;
|
||||
struct xen_boot_binary **prev;
|
||||
const char *name;
|
||||
int is_hypervisor;
|
||||
|
||||
grub_addr_t start;
|
||||
grub_size_t size;
|
||||
@@ -106,8 +88,6 @@ struct xen_boot_binary
|
||||
|
||||
char *cmdline;
|
||||
int cmdline_size;
|
||||
|
||||
struct fdt_node_info node_info;
|
||||
};
|
||||
|
||||
static grub_dl_t my_mod;
|
||||
@@ -116,19 +96,6 @@ static int loaded;
|
||||
|
||||
static struct xen_boot_binary *xen_hypervisor;
|
||||
static struct xen_boot_binary *module_head;
|
||||
static const grub_size_t module_default_align[] = {
|
||||
MODULE_IMAGE_MIN_ALIGN,
|
||||
MODULE_INITRD_MIN_ALIGN,
|
||||
MODULE_XSM_MIN_ALIGN,
|
||||
MODULE_CUSTOM_MIN_ALIGN
|
||||
};
|
||||
|
||||
static const compat_string_struct_t default_compat_string[] = {
|
||||
FDT_COMPATIBLE (MODULE_IMAGE_COMPATIBLE),
|
||||
FDT_COMPATIBLE (MODULE_INITRD_COMPATIBLE),
|
||||
FDT_COMPATIBLE (MODULE_XSM_COMPATIBLE),
|
||||
FDT_COMPATIBLE (MODULE_CUSTOM_COMPATIBLE)
|
||||
};
|
||||
|
||||
static __inline grub_addr_t
|
||||
xen_boot_address_align (grub_addr_t start, grub_size_t align)
|
||||
@@ -136,20 +103,6 @@ xen_boot_address_align (grub_addr_t start, grub_size_t align)
|
||||
return (align ? (ALIGN_UP (start, align)) : start);
|
||||
}
|
||||
|
||||
/* set module type according to command name. */
|
||||
static grub_err_t
|
||||
set_module_type (grub_command_t cmd, struct xen_boot_binary *module)
|
||||
{
|
||||
if (!grub_strcmp (cmd->name, "xen_linux"))
|
||||
module->node_info.type = MODULE_IMAGE;
|
||||
else if (!grub_strcmp (cmd->name, "xen_initrd"))
|
||||
module->node_info.type = MODULE_INITRD;
|
||||
else if (!grub_strcmp (cmd->name, "xen_xsm"))
|
||||
module->node_info.type = MODULE_XSM;
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
prepare_xen_hypervisor_params (void *xen_boot_fdt)
|
||||
{
|
||||
@@ -203,15 +156,11 @@ prepare_xen_module_params (struct xen_boot_binary *module, void *xen_boot_fdt)
|
||||
grub_fdt_add_subnode (xen_boot_fdt, chosen_node, module_name);
|
||||
|
||||
retval = grub_fdt_set_prop (xen_boot_fdt, module_node, "compatible",
|
||||
module->node_info.compat_string,
|
||||
(grub_uint32_t) module->
|
||||
node_info.compat_string_size);
|
||||
MODULE_CUSTOM_COMPATIBLE, sizeof(MODULE_CUSTOM_COMPATIBLE) - 1);
|
||||
if (retval)
|
||||
return grub_error (GRUB_ERR_IO, "failed to update FDT");
|
||||
|
||||
grub_dprintf ("xen_loader", "Module %s compatible = %s size = 0x%lx\n",
|
||||
module->name, module->node_info.compat_string,
|
||||
module->node_info.compat_string_size);
|
||||
grub_dprintf ("xen_loader", "Module\n");
|
||||
|
||||
retval = grub_fdt_set_reg64 (xen_boot_fdt, module_node,
|
||||
xen_boot_address_align (module->start,
|
||||
@@ -223,7 +172,7 @@ prepare_xen_module_params (struct xen_boot_binary *module, void *xen_boot_fdt)
|
||||
if (module->cmdline && module->cmdline_size > 0)
|
||||
{
|
||||
grub_dprintf ("xen_loader",
|
||||
"Module %s cmdline : %s @ %p size:%d\n", module->name,
|
||||
"Module cmdline : %s @ %p size:%d\n",
|
||||
module->cmdline, module->cmdline, module->cmdline_size);
|
||||
|
||||
retval = grub_fdt_set_prop (xen_boot_fdt, module_node, "bootargs",
|
||||
@@ -233,8 +182,7 @@ prepare_xen_module_params (struct xen_boot_binary *module, void *xen_boot_fdt)
|
||||
}
|
||||
else
|
||||
{
|
||||
grub_dprintf ("xen_loader", "Module %s has not bootargs!\n",
|
||||
module->name);
|
||||
grub_dprintf ("xen_loader", "Module has no bootargs!\n");
|
||||
}
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
@@ -251,8 +199,8 @@ finalize_params_xen_boot (void)
|
||||
additional_size += FDT_NODE_NAME_MAX_SIZE + xen_hypervisor->cmdline_size;
|
||||
FOR_LIST_ELEMENTS (module, module_head)
|
||||
{
|
||||
additional_size += 6 * FDT_NODE_NAME_MAX_SIZE + module->
|
||||
node_info.compat_string_size + module->cmdline_size;
|
||||
additional_size += 6 * FDT_NODE_NAME_MAX_SIZE + sizeof(MODULE_CUSTOM_COMPATIBLE) - 1
|
||||
+ module->cmdline_size;
|
||||
}
|
||||
|
||||
xen_boot_fdt = grub_fdt_load (additional_size);
|
||||
@@ -275,8 +223,7 @@ finalize_params_xen_boot (void)
|
||||
{
|
||||
if (module->start && module->size > 0)
|
||||
{
|
||||
grub_dprintf ("xen_loader", "Module %s @ 0x%lx size:0x%lx\n",
|
||||
module->name,
|
||||
grub_dprintf ("xen_loader", "Module @ 0x%lx size:0x%lx\n",
|
||||
xen_boot_address_align (module->start, module->align),
|
||||
module->size);
|
||||
if (prepare_xen_module_params (module, xen_boot_fdt) != GRUB_ERR_NONE)
|
||||
@@ -284,7 +231,7 @@ finalize_params_xen_boot (void)
|
||||
}
|
||||
else
|
||||
{
|
||||
grub_dprintf ("xen_loader", "Module info error: %s!\n", module->name);
|
||||
grub_dprintf ("xen_loader", "Module info error!\n");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
@@ -327,19 +274,16 @@ single_binary_unload (struct xen_boot_binary *binary)
|
||||
{
|
||||
grub_free (binary->cmdline);
|
||||
grub_dprintf ("xen_loader",
|
||||
"Module %s cmdline memory free @ %p size: %d\n",
|
||||
binary->name, binary->cmdline, binary->cmdline_size);
|
||||
"Module cmdline memory free @ %p size: %d\n",
|
||||
binary->cmdline, binary->cmdline_size);
|
||||
}
|
||||
|
||||
if (binary->node_info.type == MODULE_CUSTOM)
|
||||
grub_free ((void *) binary->node_info.compat_string);
|
||||
|
||||
if (grub_strcmp (binary->name, XEN_HYPERVISOR_NAME))
|
||||
if (!binary->is_hypervisor)
|
||||
grub_list_remove (GRUB_AS_LIST (binary));
|
||||
|
||||
grub_dprintf ("xen_loader",
|
||||
"Module %s struct memory free @ %p size: 0x%lx\n",
|
||||
binary->name, binary, sizeof (binary));
|
||||
"Module struct memory free @ %p size: 0x%lx\n",
|
||||
binary, sizeof (binary));
|
||||
grub_free (binary);
|
||||
|
||||
return;
|
||||
@@ -377,8 +321,7 @@ xen_boot_binary_load (struct xen_boot_binary *binary, grub_file_t file,
|
||||
int argc, char *argv[])
|
||||
{
|
||||
binary->size = grub_file_size (file);
|
||||
grub_dprintf ("xen_loader", "Xen_boot %s file size: 0x%lx\n",
|
||||
binary->name, binary->size);
|
||||
grub_dprintf ("xen_loader", "Xen_boot file size: 0x%lx\n", binary->size);
|
||||
|
||||
binary->start
|
||||
= (grub_addr_t) grub_efi_allocate_pages (0,
|
||||
@@ -391,8 +334,8 @@ xen_boot_binary_load (struct xen_boot_binary *binary, grub_file_t file,
|
||||
return;
|
||||
}
|
||||
|
||||
grub_dprintf ("xen_loader", "Xen_boot %s numpages: 0x%lx\n",
|
||||
binary->name, GRUB_EFI_BYTES_TO_PAGES (binary->size + binary->align));
|
||||
grub_dprintf ("xen_loader", "Xen_boot numpages: 0x%lx\n",
|
||||
GRUB_EFI_BYTES_TO_PAGES (binary->size + binary->align));
|
||||
|
||||
if (grub_file_read (file, (void *) xen_boot_address_align (binary->start,
|
||||
binary->align),
|
||||
@@ -416,7 +359,7 @@ xen_boot_binary_load (struct xen_boot_binary *binary, grub_file_t file,
|
||||
grub_create_loader_cmdline (argc - 1, argv + 1, binary->cmdline,
|
||||
binary->cmdline_size);
|
||||
grub_dprintf ("xen_loader",
|
||||
"Xen_boot %s cmdline @ %p %s, size: %d\n", binary->name,
|
||||
"Xen_boot cmdline @ %p %s, size: %d\n",
|
||||
binary->cmdline, binary->cmdline, binary->cmdline_size);
|
||||
}
|
||||
else
|
||||
@@ -430,7 +373,8 @@ xen_boot_binary_load (struct xen_boot_binary *binary, grub_file_t file,
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_xen_module (grub_command_t cmd, int argc, char *argv[])
|
||||
grub_cmd_xen_module (grub_command_t cmd __attribute__((unused)),
|
||||
int argc, char *argv[])
|
||||
{
|
||||
|
||||
struct xen_boot_binary *module = NULL;
|
||||
@@ -454,34 +398,10 @@ grub_cmd_xen_module (grub_command_t cmd, int argc, char *argv[])
|
||||
if (!module)
|
||||
return grub_errno;
|
||||
|
||||
/* process all the options and get module type */
|
||||
if (set_module_type (cmd, module) != GRUB_ERR_NONE)
|
||||
goto fail;
|
||||
switch (module->node_info.type)
|
||||
{
|
||||
case MODULE_IMAGE:
|
||||
case MODULE_INITRD:
|
||||
case MODULE_XSM:
|
||||
module->node_info.compat_string =
|
||||
default_compat_string[module->node_info.type].compat_string;
|
||||
module->node_info.compat_string_size =
|
||||
default_compat_string[module->node_info.type].size;
|
||||
break;
|
||||
module->is_hypervisor = 0;
|
||||
module->align = 4096;
|
||||
|
||||
case MODULE_CUSTOM:
|
||||
/* we have set the node_info in set_module_type */
|
||||
break;
|
||||
|
||||
default:
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid argument"));
|
||||
}
|
||||
module->name = module->node_info.compat_string;
|
||||
module->align = module_default_align[module->node_info.type];
|
||||
|
||||
grub_dprintf ("xen_loader", "Init %s module and node info:\n"
|
||||
"compatible %s\ncompat_string_size 0x%lx\n",
|
||||
module->name, module->node_info.compat_string,
|
||||
module->node_info.compat_string_size);
|
||||
grub_dprintf ("xen_loader", "Init module and node info\n");
|
||||
|
||||
file = grub_file_open (argv[0]);
|
||||
if (!file)
|
||||
@@ -491,7 +411,7 @@ grub_cmd_xen_module (grub_command_t cmd, int argc, char *argv[])
|
||||
if (grub_errno == GRUB_ERR_NONE)
|
||||
grub_list_push (GRUB_AS_LIST_P (&module_head), GRUB_AS_LIST (module));
|
||||
|
||||
fail:
|
||||
fail:
|
||||
if (file)
|
||||
grub_file_close (file);
|
||||
if (grub_errno != GRUB_ERR_NONE)
|
||||
@@ -535,7 +455,7 @@ grub_cmd_xen_hypervisor (grub_command_t cmd __attribute__ ((unused)),
|
||||
if (!xen_hypervisor)
|
||||
return grub_errno;
|
||||
|
||||
xen_hypervisor->name = XEN_HYPERVISOR_NAME;
|
||||
xen_hypervisor->is_hypervisor = 1;
|
||||
xen_hypervisor->align = (grub_size_t) sh.optional_header.section_alignment;
|
||||
|
||||
xen_boot_binary_load (xen_hypervisor, file, argc, argv);
|
||||
@@ -559,29 +479,21 @@ fail:
|
||||
}
|
||||
|
||||
static grub_command_t cmd_xen_hypervisor;
|
||||
static grub_command_t cmd_xen_linux, cmd_xen_initrd, cmd_xen_xsm;
|
||||
static grub_command_t cmd_xen_module;
|
||||
|
||||
GRUB_MOD_INIT (xen_boot)
|
||||
{
|
||||
cmd_xen_hypervisor =
|
||||
grub_register_command ("xen_hypervisor", grub_cmd_xen_hypervisor, 0,
|
||||
N_("Load a xen hypervisor."));
|
||||
cmd_xen_linux =
|
||||
grub_register_command ("xen_linux", grub_cmd_xen_module, 0,
|
||||
N_("Load a xen linux kernel for dom0."));
|
||||
cmd_xen_initrd =
|
||||
grub_register_command ("xen_initrd", grub_cmd_xen_module, 0,
|
||||
N_("Load a xen initrd for dom0."));
|
||||
cmd_xen_xsm =
|
||||
grub_register_command ("xen_xsm", grub_cmd_xen_module, 0,
|
||||
N_("Load a xen security module."));
|
||||
cmd_xen_module =
|
||||
grub_register_command ("xen_module", grub_cmd_xen_module, 0,
|
||||
N_("Load a xen module."));
|
||||
my_mod = mod;
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI (xen_boot)
|
||||
{
|
||||
grub_unregister_command (cmd_xen_hypervisor);
|
||||
grub_unregister_command (cmd_xen_linux);
|
||||
grub_unregister_command (cmd_xen_initrd);
|
||||
grub_unregister_command (cmd_xen_xsm);
|
||||
grub_unregister_command (cmd_xen_module);
|
||||
}
|
||||
|
||||
@@ -48,15 +48,15 @@ read_headers (grub_file_t file, const char *filename, Elf_Ehdr *e, char **shdr)
|
||||
if (e->e_ident[EI_CLASS] != SUFFIX (ELFCLASS))
|
||||
return grub_error (GRUB_ERR_BAD_OS, N_("invalid arch-dependent ELF magic"));
|
||||
|
||||
*shdr = grub_malloc (e->e_shnum * e->e_shentsize);
|
||||
*shdr = grub_malloc ((grub_uint32_t) e->e_shnum * e->e_shentsize);
|
||||
if (! *shdr)
|
||||
return grub_errno;
|
||||
|
||||
if (grub_file_seek (file, e->e_shoff) == (grub_off_t) -1)
|
||||
return grub_errno;
|
||||
|
||||
if (grub_file_read (file, *shdr, e->e_shnum * e->e_shentsize)
|
||||
!= e->e_shnum * e->e_shentsize)
|
||||
if (grub_file_read (file, *shdr, (grub_uint32_t) e->e_shnum * e->e_shentsize)
|
||||
!= (grub_ssize_t) ((grub_uint32_t) e->e_shnum * e->e_shentsize))
|
||||
{
|
||||
if (grub_errno)
|
||||
return grub_errno;
|
||||
@@ -200,8 +200,8 @@ SUFFIX (grub_freebsd_load_elfmodule) (struct grub_relocator *relocator,
|
||||
|
||||
if (chunk_size < sizeof (e))
|
||||
chunk_size = sizeof (e);
|
||||
chunk_size += e.e_phnum * e.e_phentsize;
|
||||
chunk_size += e.e_shnum * e.e_shentsize;
|
||||
chunk_size += (grub_uint32_t) e.e_phnum * e.e_phentsize;
|
||||
chunk_size += (grub_uint32_t) e.e_shnum * e.e_shentsize;
|
||||
|
||||
{
|
||||
grub_relocator_chunk_t ch;
|
||||
@@ -253,14 +253,14 @@ SUFFIX (grub_freebsd_load_elfmodule) (struct grub_relocator *relocator,
|
||||
curload = module + sizeof (e);
|
||||
|
||||
load (file, argv[0], (grub_uint8_t *) chunk_src + curload - *kern_end, e.e_shoff,
|
||||
e.e_shnum * e.e_shentsize);
|
||||
(grub_uint32_t) e.e_shnum * e.e_shentsize);
|
||||
e.e_shoff = curload - module;
|
||||
curload += e.e_shnum * e.e_shentsize;
|
||||
curload += (grub_uint32_t) e.e_shnum * e.e_shentsize;
|
||||
|
||||
load (file, argv[0], (grub_uint8_t *) chunk_src + curload - *kern_end, e.e_phoff,
|
||||
e.e_phnum * e.e_phentsize);
|
||||
(grub_uint32_t) e.e_phnum * e.e_phentsize);
|
||||
e.e_phoff = curload - module;
|
||||
curload += e.e_phnum * e.e_phentsize;
|
||||
curload += (grub_uint32_t) e.e_phnum * e.e_phentsize;
|
||||
|
||||
*kern_end = curload;
|
||||
|
||||
@@ -462,7 +462,7 @@ SUFFIX (grub_netbsd_load_elf_meta) (struct grub_relocator *relocator,
|
||||
|
||||
chunk_size = ALIGN_UP (symsize, sizeof (grub_freebsd_addr_t))
|
||||
+ ALIGN_UP (strsize, sizeof (grub_freebsd_addr_t))
|
||||
+ sizeof (e) + e.e_shnum * e.e_shentsize;
|
||||
+ sizeof (e) + (grub_uint32_t) e.e_shnum * e.e_shentsize;
|
||||
|
||||
symtarget = ALIGN_UP (*kern_end, sizeof (grub_freebsd_addr_t));
|
||||
{
|
||||
@@ -498,10 +498,10 @@ SUFFIX (grub_netbsd_load_elf_meta) (struct grub_relocator *relocator,
|
||||
s2 = (Elf_Shdr *) curload;
|
||||
grub_memcpy (curload, s, e.e_shentsize);
|
||||
if (s == symsh)
|
||||
s2->sh_offset = sizeof (e) + e.e_shnum * e.e_shentsize;
|
||||
s2->sh_offset = sizeof (e) + (grub_uint32_t) e.e_shnum * e.e_shentsize;
|
||||
else if (s == strsh)
|
||||
s2->sh_offset = ALIGN_UP (symsize, sizeof (grub_freebsd_addr_t))
|
||||
+ sizeof (e) + e.e_shnum * e.e_shentsize;
|
||||
+ sizeof (e) + (grub_uint32_t) e.e_shnum * e.e_shentsize;
|
||||
else
|
||||
s2->sh_offset = 0;
|
||||
s2->sh_addr = s2->sh_offset;
|
||||
|
||||
@@ -205,7 +205,7 @@ grub_cmd_truecrypt (grub_command_t cmd __attribute__ ((unused)),
|
||||
fail:
|
||||
|
||||
if (!grub_errno)
|
||||
return grub_error (GRUB_ERR_BAD_OS, "bad truecrypt ISO");
|
||||
grub_error (GRUB_ERR_BAD_OS, "bad truecrypt ISO");
|
||||
|
||||
if (file)
|
||||
grub_file_close (file);
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#include <grub/i18n.h>
|
||||
#include <grub/bitmap_scale.h>
|
||||
#include <grub/cpu/io.h>
|
||||
#include <grub/random.h>
|
||||
|
||||
#define min(a,b) (((a) < (b)) ? (a) : (b))
|
||||
#define max(a,b) (((a) > (b)) ? (a) : (b))
|
||||
@@ -338,7 +339,7 @@ grub_xnu_devprop_add_property_utf16 (struct grub_xnu_devprop_device_descriptor *
|
||||
utf8 = grub_malloc (namelen * 4 + 1);
|
||||
if (!utf8)
|
||||
{
|
||||
grub_free (utf8);
|
||||
grub_free (utf16);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
@@ -577,11 +578,31 @@ static grub_err_t
|
||||
grub_cpu_xnu_fill_devicetree (grub_uint64_t *fsbfreq_out)
|
||||
{
|
||||
struct grub_xnu_devtree_key *efikey;
|
||||
struct grub_xnu_devtree_key *chosenkey;
|
||||
struct grub_xnu_devtree_key *cfgtablekey;
|
||||
struct grub_xnu_devtree_key *curval;
|
||||
struct grub_xnu_devtree_key *runtimesrvkey;
|
||||
struct grub_xnu_devtree_key *platformkey;
|
||||
unsigned i, j;
|
||||
grub_err_t err;
|
||||
|
||||
chosenkey = grub_xnu_create_key (&grub_xnu_devtree_root, "chosen");
|
||||
if (! chosenkey)
|
||||
return grub_errno;
|
||||
|
||||
/* Random seed. */
|
||||
curval = grub_xnu_create_value (&(chosenkey->first_child), "random-seed");
|
||||
if (! curval)
|
||||
return grub_errno;
|
||||
curval->datasize = 64;
|
||||
curval->data = grub_malloc (curval->datasize);
|
||||
if (! curval->data)
|
||||
return grub_errno;
|
||||
/* Our random is not peer-reviewed but xnu uses this seed only for
|
||||
ASLR in kernel. */
|
||||
err = grub_crypto_get_random (curval->data, curval->datasize);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* The value "model". */
|
||||
/* FIXME: may this value be sometimes different? */
|
||||
@@ -897,6 +918,28 @@ grub_xnu_set_video (struct grub_xnu_boot_params_common *params)
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static int
|
||||
total_ram_hook (grub_uint64_t addr __attribute__ ((unused)), grub_uint64_t size,
|
||||
grub_memory_type_t type,
|
||||
void *data)
|
||||
{
|
||||
grub_uint64_t *result = data;
|
||||
|
||||
if (type != GRUB_MEMORY_AVAILABLE)
|
||||
return 0;
|
||||
*result += size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_uint64_t
|
||||
get_total_ram (void)
|
||||
{
|
||||
grub_uint64_t result = 0;
|
||||
|
||||
grub_mmap_iterate (total_ram_hook, &result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Boot xnu. */
|
||||
grub_err_t
|
||||
grub_xnu_boot (void)
|
||||
@@ -973,6 +1016,7 @@ grub_xnu_boot (void)
|
||||
{
|
||||
bootparams_common = &bootparams->v2.common;
|
||||
bootparams->v2.fsbfreq = fsbfreq;
|
||||
bootparams->v2.ram_size = get_total_ram();
|
||||
}
|
||||
else
|
||||
bootparams_common = &bootparams->v1.common;
|
||||
@@ -1080,7 +1124,7 @@ grub_xnu_boot (void)
|
||||
bootparams_common->efi_mmap = memory_map_target;
|
||||
bootparams_common->efi_mmap_size = memory_map_size;
|
||||
bootparams_common->heap_start = grub_xnu_heap_target_start;
|
||||
bootparams_common->heap_size = grub_xnu_heap_size;
|
||||
bootparams_common->heap_size = curruntimepage * GRUB_XNU_PAGESIZE - grub_xnu_heap_target_start;
|
||||
|
||||
/* Parameters for asm helper. */
|
||||
grub_xnu_stack = bootparams_common->heap_start
|
||||
|
||||
@@ -72,7 +72,7 @@ CONCAT(grub_multiboot_load_elf, XX) (grub_file_t file, const char *filename, voi
|
||||
return grub_error (GRUB_ERR_UNKNOWN_OS, N_("this ELF file is not of the right type"));
|
||||
|
||||
/* FIXME: Should we support program headers at strange locations? */
|
||||
if (ehdr->e_phoff + ehdr->e_phnum * ehdr->e_phentsize > MULTIBOOT_SEARCH)
|
||||
if (ehdr->e_phoff + (grub_uint32_t) ehdr->e_phnum * ehdr->e_phentsize > MULTIBOOT_SEARCH)
|
||||
return grub_error (GRUB_ERR_BAD_OS, "program header at a too high offset");
|
||||
|
||||
phdr_base = (char *) buffer + ehdr->e_phoff;
|
||||
@@ -164,7 +164,7 @@ CONCAT(grub_multiboot_load_elf, XX) (grub_file_t file, const char *filename, voi
|
||||
{
|
||||
grub_uint8_t *shdr, *shdrptr;
|
||||
|
||||
shdr = grub_malloc (ehdr->e_shnum * ehdr->e_shentsize);
|
||||
shdr = grub_malloc ((grub_uint32_t) ehdr->e_shnum * ehdr->e_shentsize);
|
||||
if (!shdr)
|
||||
return grub_errno;
|
||||
|
||||
@@ -174,7 +174,7 @@ CONCAT(grub_multiboot_load_elf, XX) (grub_file_t file, const char *filename, voi
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
if (grub_file_read (file, shdr, ehdr->e_shnum * ehdr->e_shentsize)
|
||||
if (grub_file_read (file, shdr, (grub_uint32_t) ehdr->e_shnum * ehdr->e_shentsize)
|
||||
!= (grub_ssize_t) ehdr->e_shnum * ehdr->e_shentsize)
|
||||
{
|
||||
if (!grub_errno)
|
||||
|
||||
@@ -203,20 +203,20 @@ alloc_phys_choose (grub_uint64_t addr, grub_uint64_t len,
|
||||
if (addr + ctx->size >= end)
|
||||
return 0;
|
||||
|
||||
if (addr >= grub_phys_start && addr < grub_phys_end)
|
||||
{
|
||||
addr = ALIGN_UP (grub_phys_end, FOUR_MB);
|
||||
if (addr + ctx->size >= end)
|
||||
return 0;
|
||||
}
|
||||
if ((addr + ctx->size) >= grub_phys_start
|
||||
&& (addr + ctx->size) < grub_phys_end)
|
||||
/* OBP available region contains grub. Start at grub_phys_end. */
|
||||
/* grub_phys_start does not start at the beginning of the memory region */
|
||||
if ((grub_phys_start >= addr && grub_phys_end < end) ||
|
||||
(addr > grub_phys_start && addr < grub_phys_end))
|
||||
{
|
||||
addr = ALIGN_UP (grub_phys_end, FOUR_MB);
|
||||
if (addr + ctx->size >= end)
|
||||
return 0;
|
||||
}
|
||||
|
||||
grub_dprintf("loader",
|
||||
"addr = 0x%lx grub_phys_start = 0x%lx grub_phys_end = 0x%lx\n",
|
||||
addr, grub_phys_start, grub_phys_end);
|
||||
|
||||
if (loaded)
|
||||
{
|
||||
grub_addr_t linux_end = ALIGN_UP (linux_paddr + linux_size, FOUR_MB);
|
||||
|
||||
@@ -299,12 +299,6 @@ grub_net_ipv6_get_link_local (struct grub_net_card *card,
|
||||
char *ptr;
|
||||
grub_net_network_level_address_t addr;
|
||||
|
||||
name = grub_malloc (grub_strlen (card->name)
|
||||
+ GRUB_NET_MAX_STR_HWADDR_LEN
|
||||
+ sizeof (":link"));
|
||||
if (!name)
|
||||
return NULL;
|
||||
|
||||
addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6;
|
||||
addr.ipv6[0] = grub_cpu_to_be64_compile_time (0xfe80ULL << 48);
|
||||
addr.ipv6[1] = grub_net_ipv6_get_id (hwaddr);
|
||||
@@ -317,6 +311,12 @@ grub_net_ipv6_get_link_local (struct grub_net_card *card,
|
||||
return inf;
|
||||
}
|
||||
|
||||
name = grub_malloc (grub_strlen (card->name)
|
||||
+ GRUB_NET_MAX_STR_HWADDR_LEN
|
||||
+ sizeof (":link"));
|
||||
if (!name)
|
||||
return NULL;
|
||||
|
||||
ptr = grub_stpcpy (name, card->name);
|
||||
if (grub_net_hwaddr_cmp (&card->default_address, hwaddr) != 0)
|
||||
{
|
||||
@@ -1322,20 +1322,13 @@ grub_net_open_real (const char *name)
|
||||
if (!ret)
|
||||
return NULL;
|
||||
ret->protocol = proto;
|
||||
if (server)
|
||||
ret->server = grub_strdup (server);
|
||||
if (!ret->server)
|
||||
{
|
||||
ret->server = grub_strdup (server);
|
||||
if (!ret->server)
|
||||
{
|
||||
grub_free (ret);
|
||||
return NULL;
|
||||
}
|
||||
grub_free (ret);
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
ret->server = NULL;
|
||||
ret->fs = &grub_net_fs;
|
||||
ret->offset = 0;
|
||||
ret->eof = 0;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@@ -1428,7 +1421,10 @@ grub_net_fs_open (struct grub_file *file_out, const char *name)
|
||||
file->device->net->packs.last = NULL;
|
||||
file->device->net->name = grub_strdup (name);
|
||||
if (!file->device->net->name)
|
||||
return grub_errno;
|
||||
{
|
||||
grub_free (file);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
err = file->device->net->protocol->open (file, name);
|
||||
if (err)
|
||||
|
||||
@@ -606,10 +606,15 @@ grub_net_tcp_open (char *server,
|
||||
|
||||
nb = grub_netbuff_alloc (sizeof (*tcph) + 128);
|
||||
if (!nb)
|
||||
return NULL;
|
||||
{
|
||||
grub_free (socket);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
err = grub_netbuff_reserve (nb, 128);
|
||||
if (err)
|
||||
{
|
||||
grub_free (socket);
|
||||
grub_netbuff_free (nb);
|
||||
return NULL;
|
||||
}
|
||||
@@ -617,12 +622,14 @@ grub_net_tcp_open (char *server,
|
||||
err = grub_netbuff_put (nb, sizeof (*tcph));
|
||||
if (err)
|
||||
{
|
||||
grub_free (socket);
|
||||
grub_netbuff_free (nb);
|
||||
return NULL;
|
||||
}
|
||||
socket->pq = grub_priority_queue_new (sizeof (struct grub_net_buff *), cmp);
|
||||
if (!socket->pq)
|
||||
{
|
||||
grub_free (socket);
|
||||
grub_netbuff_free (nb);
|
||||
return NULL;
|
||||
}
|
||||
@@ -978,6 +985,7 @@ grub_net_recv_tcp_packet (struct grub_net_buff *nb,
|
||||
cmp);
|
||||
if (!sock->pq)
|
||||
{
|
||||
grub_free (sock);
|
||||
grub_netbuff_free (nb);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
@@ -326,7 +326,10 @@ tftp_open (struct grub_file *file, const char *filename)
|
||||
grub_netbuff_reserve (&nb, 1500);
|
||||
err = grub_netbuff_push (&nb, sizeof (*tftph));
|
||||
if (err)
|
||||
return err;
|
||||
{
|
||||
grub_free (data);
|
||||
return err;
|
||||
}
|
||||
|
||||
tftph = (struct tftphdr *) nb.data;
|
||||
|
||||
@@ -361,19 +364,26 @@ tftp_open (struct grub_file *file, const char *filename)
|
||||
|
||||
err = grub_netbuff_unput (&nb, nb.tail - (nb.data + hdrlen));
|
||||
if (err)
|
||||
return err;
|
||||
{
|
||||
grub_free (data);
|
||||
return err;
|
||||
}
|
||||
|
||||
file->not_easily_seekable = 1;
|
||||
file->data = data;
|
||||
|
||||
data->pq = grub_priority_queue_new (sizeof (struct grub_net_buff *), cmp);
|
||||
if (!data->pq)
|
||||
return grub_errno;
|
||||
{
|
||||
grub_free (data);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
err = grub_net_resolve_address (file->device->net->server, &addr);
|
||||
if (err)
|
||||
{
|
||||
destroy_pq (data);
|
||||
grub_free (data);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -383,6 +393,7 @@ tftp_open (struct grub_file *file, const char *filename)
|
||||
if (!data->sock)
|
||||
{
|
||||
destroy_pq (data);
|
||||
grub_free (data);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
@@ -396,6 +407,7 @@ tftp_open (struct grub_file *file, const char *filename)
|
||||
{
|
||||
grub_net_udp_close (data->sock);
|
||||
destroy_pq (data);
|
||||
grub_free (data);
|
||||
return err;
|
||||
}
|
||||
grub_net_poll_cards (GRUB_NET_INTERVAL + (i * GRUB_NET_INTERVAL_ADDITION),
|
||||
@@ -412,6 +424,7 @@ tftp_open (struct grub_file *file, const char *filename)
|
||||
{
|
||||
grub_net_udp_close (data->sock);
|
||||
destroy_pq (data);
|
||||
grub_free (data);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
|
||||
@@ -476,7 +476,10 @@ insert_string (struct screen *screen, const char *s, int update)
|
||||
(grub_uint8_t *) s, (p - s), 0);
|
||||
|
||||
if (! ensure_space (current_linep, size))
|
||||
return 0;
|
||||
{
|
||||
grub_free (unicode_msg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
grub_memmove (current_linep->buf + screen->column + size,
|
||||
current_linep->buf + screen->column,
|
||||
@@ -1265,6 +1268,7 @@ grub_menu_entry_run (grub_menu_entry_t entry)
|
||||
if (! screen->lines[i].pos)
|
||||
{
|
||||
grub_print_error ();
|
||||
destroy_screen (screen);
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
return;
|
||||
}
|
||||
@@ -1274,6 +1278,7 @@ grub_menu_entry_run (grub_menu_entry_t entry)
|
||||
if (!screen->terms)
|
||||
{
|
||||
grub_print_error ();
|
||||
destroy_screen (screen);
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -77,8 +77,6 @@ print_more (void)
|
||||
grub_term_output_t term;
|
||||
grub_uint32_t *unicode_str, *unicode_last_position;
|
||||
|
||||
pos = grub_term_save_pos ();
|
||||
|
||||
/* TRANSLATORS: This has to fit on one line. It's ok to include few
|
||||
words but don't write poems. */
|
||||
grub_utf8_to_ucs4_alloc (_("--MORE--"), &unicode_str,
|
||||
@@ -90,6 +88,8 @@ print_more (void)
|
||||
return;
|
||||
}
|
||||
|
||||
pos = grub_term_save_pos ();
|
||||
|
||||
grub_setcolorstate (GRUB_TERM_COLOR_HIGHLIGHT);
|
||||
|
||||
FOR_ACTIVE_TERM_OUTPUTS(term)
|
||||
|
||||
@@ -681,18 +681,14 @@ grub_script_arglist_to_argv (struct grub_script_arglist *arglist,
|
||||
}
|
||||
*op = '\0';
|
||||
|
||||
if (grub_script_argv_append (&result, p, op - p))
|
||||
{
|
||||
grub_free (p);
|
||||
need_cleanup = 1;
|
||||
/* Fall through to cleanup */
|
||||
}
|
||||
need_cleanup = grub_script_argv_append (&result, p, op - p);
|
||||
grub_free (p);
|
||||
/* Fall through to cleanup */
|
||||
}
|
||||
else
|
||||
{
|
||||
if (append (&result, values[i], 1))
|
||||
need_cleanup = 1;
|
||||
/* Fall through to cleanup */
|
||||
need_cleanup = append (&result, values[i], 1);
|
||||
/* Fall through to cleanup */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
|
||||
#include "grub_script.tab.h"
|
||||
|
||||
#pragma GCC diagnostic ignored "-Wunreachable-code"
|
||||
#pragma GCC diagnostic ignored "-Wmissing-declarations"
|
||||
|
||||
%}
|
||||
|
||||
@@ -92,7 +92,7 @@ typedef size_t yy_size_t;
|
||||
#define stdout 0
|
||||
|
||||
#define fprintf(...) 0
|
||||
#define exit(...)
|
||||
#define exit(...) grub_fatal("fatal error in lexer")
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
117
grub-core/term/arm/cros.c
Normal file
117
grub-core/term/arm/cros.c
Normal 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
grub-core/term/arm/cros_ec.c
Normal file
270
grub-core/term/arm/cros_ec.c
Normal 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
grub-core/term/arm/pl050.c
Normal file
189
grub-core/term/arm/pl050.c
Normal 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);
|
||||
}
|
||||
@@ -22,212 +22,21 @@
|
||||
#include <grub/cpu/io.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/term.h>
|
||||
#include <grub/keyboard_layouts.h>
|
||||
#include <grub/time.h>
|
||||
#include <grub/loader.h>
|
||||
#include <grub/ps2.h>
|
||||
|
||||
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_orig_set;
|
||||
static grub_uint8_t current_set;
|
||||
struct grub_ps2_state ps2_state;
|
||||
|
||||
static int ping_sent;
|
||||
|
||||
static 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
|
||||
keyboard_controller_wait_until_ready (void)
|
||||
{
|
||||
@@ -350,12 +159,12 @@ set_scancodes (void)
|
||||
if (!grub_keyboard_orig_set)
|
||||
{
|
||||
grub_dprintf ("atkeyb", "No sets support assumed\n");
|
||||
current_set = 1;
|
||||
ps2_state.current_set = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
#if !USE_SCANCODE_SET
|
||||
current_set = 1;
|
||||
ps2_state.current_set = 1;
|
||||
return;
|
||||
#else
|
||||
|
||||
@@ -363,15 +172,15 @@ set_scancodes (void)
|
||||
& ~KEYBOARD_AT_TRANSLATE);
|
||||
|
||||
write_mode (2);
|
||||
current_set = query_mode ();
|
||||
grub_dprintf ("atkeyb", "returned set %d\n", current_set);
|
||||
if (current_set == 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);
|
||||
current_set = query_mode ();
|
||||
grub_dprintf ("atkeyb", "returned set %d\n", current_set);
|
||||
if (current_set == 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");
|
||||
#endif
|
||||
@@ -386,164 +195,10 @@ keyboard_controller_led (grub_uint8_t leds)
|
||||
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
|
||||
grub_at_keyboard_is_alive (void)
|
||||
{
|
||||
if (current_set != 0)
|
||||
if (ps2_state.current_set != 0)
|
||||
return 1;
|
||||
if (ping_sent
|
||||
&& KEYBOARD_COMMAND_ISREADY (grub_inb (KEYBOARD_REG_STATUS))
|
||||
@@ -566,51 +221,28 @@ grub_at_keyboard_is_alive (void)
|
||||
static int
|
||||
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 ())
|
||||
return GRUB_TERM_NO_KEY;
|
||||
|
||||
code = grub_keyboard_getkey ();
|
||||
if (code == -1)
|
||||
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:
|
||||
at_keyboard_status ^= GRUB_TERM_STATUS_CAPS;
|
||||
led_status ^= KEYBOARD_LED_CAPS;
|
||||
keyboard_controller_led (led_status);
|
||||
if (! KEYBOARD_ISREADY (grub_inb (KEYBOARD_REG_STATUS)))
|
||||
return -1;
|
||||
at_key = grub_inb (KEYBOARD_REG_DATA);
|
||||
old_led = ps2_state.led_status;
|
||||
|
||||
#ifdef DEBUG_AT_KEYBOARD
|
||||
grub_dprintf ("atkeyb", "caps_lock = %d\n", !!(at_keyboard_status & GRUB_KEYBOARD_STATUS_CAPS_LOCK));
|
||||
#endif
|
||||
return GRUB_TERM_NO_KEY;
|
||||
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);
|
||||
}
|
||||
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 void
|
||||
grub_keyboard_controller_init (void)
|
||||
{
|
||||
at_keyboard_status = 0;
|
||||
ps2_state.at_keyboard_status = 0;
|
||||
/* Drain input buffer. */
|
||||
while (1)
|
||||
{
|
||||
@@ -632,13 +264,13 @@ grub_keyboard_controller_init (void)
|
||||
grub_keyboard_orig_set = query_mode ();
|
||||
#endif
|
||||
set_scancodes ();
|
||||
keyboard_controller_led (led_status);
|
||||
keyboard_controller_led (ps2_state.led_status);
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
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;
|
||||
if (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
|
||||
grub_at_restore_hw (void)
|
||||
{
|
||||
if (current_set == 0)
|
||||
if (ps2_state.current_set == 0)
|
||||
return GRUB_ERR_NONE;
|
||||
|
||||
/* Drain input buffer. */
|
||||
@@ -668,7 +300,7 @@ grub_at_restore_hw (void)
|
||||
grub_inb (KEYBOARD_REG_DATA);
|
||||
}
|
||||
set_scancodes ();
|
||||
keyboard_controller_led (led_status);
|
||||
keyboard_controller_led (ps2_state.led_status);
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#include <grub/time.h>
|
||||
#include <grub/terminfo.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/i386/coreboot/lbio.h>
|
||||
#include <grub/coreboot/lbio.h>
|
||||
#include <grub/command.h>
|
||||
#include <grub/normal.h>
|
||||
|
||||
|
||||
387
grub-core/term/ps2.c
Normal file
387
grub-core/term/ps2.c
Normal 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);
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,6 @@
|
||||
|
||||
#include <grub/term.h>
|
||||
#include <grub/time.h>
|
||||
#include <grub/cpu/io.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/term.h>
|
||||
#include <grub/usb.h>
|
||||
|
||||
@@ -33,12 +33,19 @@ sleep_test (void)
|
||||
{
|
||||
struct grub_datetime st, en;
|
||||
grub_int32_t stu = 0, enu = 0;
|
||||
int is_delayok;
|
||||
grub_test_assert (!grub_get_datetime (&st), "Couldn't retrieve start time");
|
||||
grub_millisleep (10000);
|
||||
grub_test_assert (!grub_get_datetime (&en), "Couldn't retrieve end time");
|
||||
grub_test_assert (grub_datetime2unixtime (&st, &stu), "Invalid date");
|
||||
grub_test_assert (grub_datetime2unixtime (&en, &enu), "Invalid date");
|
||||
grub_test_assert (enu - stu >= 9 && enu - stu <= 11, "Interval out of range: %d", enu-stu);
|
||||
is_delayok = (enu - stu >= 9 && enu - stu <= 11);
|
||||
#ifdef __arm__
|
||||
/* Ignore QEMU bug */
|
||||
if (enu - stu >= 15 && enu - stu <= 17)
|
||||
is_delayok = 1;
|
||||
#endif
|
||||
grub_test_assert (is_delayok, "Interval out of range: %d", enu-stu);
|
||||
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user