Compare commits

..

168 Commits

Author SHA1 Message Date
Vladimir Serbinenko
6e4e4ee33f dwc2 counterpart of previous patch 2016-03-01 20:09:54 +01:00
Vladimir Serbinenko
e1444e5399 Rename portstatus to reset_port.
The way we currently use portstatus always uses
enable=1 and we use it for its reset side effect.
Change confusing name and remove unused parameter.
2016-03-01 20:09:47 +01:00
Vladimir Serbinenko
ef57ad6164 detect_dev 2016-03-01 19:59:52 +01:00
Vladimir Serbinenko
72bd5756af dwc2 skeleton 2016-02-27 16:15:43 +01:00
Vladimir Serbinenko
295e041189 clone ehci to dwc1 2016-02-25 19:55:39 +01:00
Vladimir Serbinenko
3f6f84f9e0 fix mkimage.c split 2016-02-25 19:52:46 +01:00
Vladimir Serbinenko
9f8f747605 usbtrans: Fix memory coherence 2016-02-23 12:07:01 +01:00
Vladimir Serbinenko
102016960d ehci: Fix memory coherence 2016-02-23 12:06:48 +01:00
Vladimir Serbinenko
07cd46627b arm: implement grub_arch_sync_dma_caches 2016-02-23 12:06:00 +01:00
Vladimir Serbinenko
9e161d1302 Make dma_caches accept volatile 2016-02-23 11:45:29 +01:00
Vladimir Serbinenko
06c92907c1 cros fix 2016-02-23 11:26:35 +01:00
Vladimir Serbinenko
74cef4ab78 cleaner 2016-02-23 10:19:26 +01:00
Vladimir Serbinenko
f4116c3a42 Decrease frame timeout 2016-02-23 10:15:05 +01:00
Vladimir Serbinenko
2d56c1b117 cleaner 2016-02-23 09:52:08 +01:00
Vladimir Serbinenko
1f72ca020d cleaner 2016-02-23 09:50:43 +01:00
Vladimir Serbinenko
3d300d7247 cleaner 2016-02-23 09:43:57 +01:00
Vladimir Serbinenko
03104c2d98 always use older cros protocol. We don't realy need new one 2016-02-23 09:42:09 +01:00
Vladimir Serbinenko
40562ddf1e cros e0 fix 2016-02-22 21:12:50 +01:00
Vladimir Serbinenko
1ea06af1ae EHCI FDT missing file 2016-02-22 20:40:16 +01:00
Vladimir Serbinenko
df21b9363d cleaner 2016-02-22 19:44:39 +01:00
Vladimir Serbinenko
8efde40d0c cleaner 2016-02-22 19:44:09 +01:00
Vladimir Serbinenko
d624e04af1 cleaner 2016-02-22 19:39:30 +01:00
Vladimir Serbinenko
bbd85a0292 cleaner 2016-02-22 19:38:26 +01:00
Vladimir Serbinenko
4f06545767 cleaner 2016-02-22 19:37:37 +01:00
Vladimir Serbinenko
66d0e16425 cleaner 2016-02-22 19:35:46 +01:00
Vladimir Serbinenko
a98c706755 cleaner 2016-02-22 19:35:16 +01:00
Vladimir Serbinenko
95f663ec1d cleaner 2016-02-22 19:34:30 +01:00
Vladimir Serbinenko
2b2a338ad6 cleaner 2016-02-22 19:33:34 +01:00
Vladimir Serbinenko
6c9512b610 cleaner 2016-02-22 19:33:13 +01:00
Vladimir Serbinenko
f447b3d2bb Dirty cros keyboard import 2016-02-22 19:29:47 +01:00
Vladimir Serbinenko
295fe6c548 Dirty cros keyboard 2016-02-22 19:29:08 +01:00
Vladimir Serbinenko
9cd85f276f frequency 2016-02-22 03:34:35 +01:00
Vladimir Serbinenko
502a7c48e9 ARM caches 2016-02-22 03:34:16 +01:00
Vladimir Serbinenko
418b32f8e9 EHCI reset fix 2016-02-22 03:33:59 +01:00
Vladimir Serbinenko
98490fc328 DMA split 2016-02-22 03:33:18 +01:00
Vladimir Serbinenko
3625fdc0b9 Improve EHCI logging 2016-02-22 03:32:50 +01:00
Vladimir Serbinenko
1ec2b7758b ehci split fixup 2016-02-22 03:28:10 +01:00
Vladimir Serbinenko
f51e8d0dda coreboot 2016-02-22 03:27:39 +01:00
Vladimir Serbinenko
ee52ea80d6 Remove useless include 2016-02-22 03:25:50 +01:00
Vladimir Serbinenko
c55f74a5c5 ehci split 2016-02-22 01:08:27 +01:00
Vladimir Serbinenko
3b1bb7f3eb DTB overrides 2016-02-22 00:05:40 +01:00
Vladimir Serbinenko
0b71582111 coreboot 2016-02-21 20:28:10 +01:00
Vladimir Serbinenko
dc491ff04a fdtbus 2016-02-21 20:27:50 +01:00
Vladimir Serbinenko
192243b13e Out-of-place FDT handling 2016-02-21 20:27:28 +01:00
Vladimir Serbinenko
0f3ae7324a fdt 2016-02-21 19:48:57 +01:00
Vladimir Serbinenko
ab8770a314 pre-located image for veyron 2016-02-21 19:28:56 +01:00
Vladimir Serbinenko
f2df41cffa coreboot 2016-02-21 19:28:40 +01:00
Vladimir Serbinenko
b0227ce4b9 fdt: relax align requirement 2016-02-21 19:28:23 +01:00
Vladimir Serbinenko
f900bea454 coreboot 2016-02-21 18:59:14 +01:00
Vladimir Serbinenko
dc51ac70ee switch to layout 2016-02-21 18:47:29 +01:00
Vladimir Serbinenko
869a0bc476 coreboot 2016-02-21 18:44:55 +01:00
Vladimir Serbinenko
f9ee0c3e5d Simplify reloc 2016-02-21 18:44:18 +01:00
Vladimir Serbinenko
8af26e386c coreboot reloc 2016-02-21 18:42:35 +01:00
Vladimir Serbinenko
78e9b82d2c coreboot memory before _start 2016-02-21 18:41:39 +01:00
Vladimir Serbinenko
86139504b7 pl050 2016-02-21 01:53:44 +01:00
Vladimir Serbinenko
35c1d629f9 fdtbus 2016-02-21 01:53:07 +01:00
Vladimir Serbinenko
bacb8f911f coreboot 2016-02-21 00:05:38 +01:00
Vladimir Serbinenko
fbda565356 fdt 2016-02-21 00:05:21 +01:00
Vladimir Serbinenko
598185f806 fdtbus 2016-02-21 00:04:18 +01:00
Vladimir Serbinenko
ca2fd6c93f ps2 split 2016-02-20 18:45:42 +01:00
Vladimir Serbinenko
a29fb4722c coreboot 2016-02-20 16:26:23 +01:00
Vladimir Serbinenko
7562f4ab53 bus fdt improvements 2016-02-20 16:25:39 +01:00
Vladimir Serbinenko
c7d0aa5450 fdtbus 2016-02-20 14:30:43 +01:00
Vladimir Serbinenko
ceb68c6648 missing files 2016-02-20 14:29:01 +01:00
Vladimir Serbinenko
99291427d2 fdtlib 2016-02-20 14:28:37 +01:00
Vladimir Serbinenko
6ffee98e1b Useless fdt.lst 2016-02-20 14:22:34 +01:00
Vladimir Serbinenko
a6649f5b8e FDT lib improvements 2016-02-20 12:30:06 +01:00
Vladimir Serbinenko
c3c14cffef refresh before abort 2016-02-20 09:12:15 +01:00
Vladimir Serbinenko
84939af253 generic timer safeguard 2016-02-20 09:12:02 +01:00
Vladimir Serbinenko
ba6d40e8bb WIP2 2016-02-19 16:47:36 +01:00
Vladimir Serbinenko
2c3a054f4f WIP 2016-02-19 12:41:50 +01:00
Vladimir Serbinenko
b8eda96422 rename 2016-02-19 12:17:56 +01:00
Vladimir Serbinenko
ca3962ca7b fix relocate 2016-02-19 12:17:20 +01:00
Vladimir Serbinenko
a4f7d77f7d fs 2016-02-19 04:48:50 +01:00
Vladimir Serbinenko
5099975ace fd 2016-02-19 04:48:17 +01:00
Vladimir Serbinenko
2f98d7648e Move cbfb 2016-02-19 04:47:02 +01:00
Vladimir Serbinenko
018e382144 decouple 2016-02-19 04:31:59 +01:00
Vladimir Serbinenko
f5cba79512 Declare arm-coreboot 2016-02-19 03:24:49 +01:00
Vladimir Serbinenko
46569db585 arm-uboot: Make self-relocatable to allow loading at any address 2016-02-19 03:22:10 +01:00
Vladimir Serbinenko
575c7a6e3c Allow _start == 0 with relocatable images 2016-02-19 02:03:28 +01:00
Vladimir Serbinenko
fc489a889d Provide __bss_start and _end symbols in grub-mkimage.
For this ensure that all bss sections are merged.
2016-02-19 02:02:50 +01:00
Vladimir Serbinenko
bfb517bc3b encapsulate 2016-02-19 01:58:11 +01:00
Vladimir Serbinenko
437dba573f Remove useless ifdef 2016-02-19 01:28:16 +01:00
Vladimir Serbinenko
974ba94330 mkimagexx: Split PE and generic part. 2016-02-19 01:14:12 +01:00
Vladimir Serbinenko
963d21b76c file split 2016-02-19 01:14:12 +01:00
Vladimir Serbinenko
e3745f9087 default_payload.elf: Always rebuild and remove before build.
It's difficult to know all dependencies. Since it's manual and cheap
target anyway, simply always rebuild it.
2016-02-17 18:19:18 +01:00
Vladimir Serbinenko
01d50c2539 default_payload.elf: Include password_pbkdf2.
Withoout this module we may end up in a system where no password is
accepted.
2016-02-17 18:11:51 +01:00
Vladimir Serbinenko
8d69065f52 default_payload.elf: Add modules from $(EXTRA_PAYLOAD_MODULES).
This allows coreboot building system to add extra modules depending
on user config.
2016-02-17 18:10:31 +01:00
Vladimir Serbinenko
59ec05bcf8 mm: Avoid integer overflow. 2016-02-17 18:09:44 +01:00
Vladimir Serbinenko
fabde8324d Remove -Wno-maybe-uninitialized as it may not be present. 2016-02-17 17:58:05 +01:00
Vladimir Serbinenko
5cae910665 Fix warnings when compiling with -O3 2016-02-17 17:56:41 +01:00
Vladimir Serbinenko
25492a0f04 Add wbinvd around bios call.
Via C3 has problems with cache coherency when transitioning between the modes,
so flush it around bios calls.
2016-02-14 08:34:10 +01:00
Eric Snowberg
080a20861c OBP available region contains grub. Start at grub_phys_end.
This prevents a problem where grub was being overwritten since
grub_phys_start does not start at a zero offset within the memory
map.
2016-02-12 23:16:03 +01:00
Andreas Freimuth
f96b34224e Add Thinkpad T410s button cmos address. 2016-02-12 19:19:11 +01:00
Vladimir Serbinenko
a2ab8c2172 TODO: Remove obsolete link 2016-02-12 17:51:52 +01:00
Toomas Soome
ce01054ec3 lz4: Fix pointer overflow 2016-02-12 17:26:32 +01:00
Vladimir Serbinenko
feef882f98 grub-shell: Update 32-bit OVMF binary name. 2016-02-12 16:08:04 +01:00
Daniel Kiper
eba6db6323 relocator: Fix integer underflow. 2016-02-12 16:07:57 +01:00
Vladimir Serbinenko
6e1ace590a Change -v to -V for version of shell utils. 2016-02-12 15:46:05 +01:00
Vladimir Serbinenko
7c35f65aac xnu: Add new kernel path to autoconfig. 2016-02-12 15:42:26 +01:00
Vladimir Serbinenko
4598cafa7d arm64: Use cpu timer for timekeeping. 2016-02-12 12:43:02 +01:00
Vladimir Serbinenko
6f4189ffc1 powerpc: Trim header in tests. 2016-02-12 12:42:04 +01:00
Vladimir Serbinenko
127cfea8be default_payload: Include syslinuxcfg, all filesystems and xnu. 2016-02-12 12:41:28 +01:00
Vladimir Serbinenko
22aa31bcc3 xnu: Supply random seed.
Now we're able to load kernels up to El Capitan.
2016-02-12 12:40:10 +01:00
Vladimir Serbinenko
e72de13b9e Add RNG module. 2016-02-12 12:39:38 +01:00
Vladimir Serbinenko
342d6edb97 yylex: use grub_fatal for exit.
lexer calls yylex_fatal on fatal internal errors. yylex_fatal itself is
declared as noreturn and calls exit. Returning from noreturn function has
unpredictable consequences.
2016-02-12 12:34:54 +01:00
Vladimir Serbinenko
e5c9300191 printf: Fix and test %% behaviour in presence of subsequenbt args. 2016-02-12 12:33:41 +01:00
Vladimir Serbinenko
d9a3bfead8 Split pmtimer wait and tsc measurement from pmtimer tsc calibration. 2016-02-12 11:40:51 +01:00
Vladimir Serbinenko
1933d37371 Make grub_cpu_is_tsc_supported generally available. 2016-02-12 11:38:51 +01:00
Vladimir Serbinenko
b29638222e Make grub_acpi_find_fadt accessible generically 2016-02-12 11:35:48 +01:00
Vladimir Serbinenko
8ad190cac2 Make unaligned types public.
This simplifies code which has to handle those types.
2016-02-12 09:11:06 +01:00
Vladimir Serbinenko
281baeecd3 Fix emu compilation error on arm. 2016-02-12 09:10:08 +01:00
Vladimir Serbinenko
df4df4d887 xnu: Include relocated EFI in heap size. 2016-02-11 12:30:45 +01:00
Vladimir Serbinenko
2d425ffdd5 xnu: supply ramsize to the kernel.
Without this info recent kernels crash as they allocate no heap.
2016-02-11 11:58:28 +01:00
Andrei Borzenkov
67dba97e45 support modules without symbol table
all_video module does not have any code or data and exists solely for
.moddeps section to pull in dependencies. This makes all symbols unneeded.

While in current binutils (last released version as of this commit is 2.26)
``strip --strip-unneeded'' unintentionally adds section symbols for each
existing section, this behavior was considered a bug and changed in commit
14f2c699ddca1e2f706342dffc59a6c7e23e844c to completely strip symbol table
in this case.

Older binutils (verified with 2.17) and some other toolchains (at least
elftoolchain r3223M), both used in FreeBSD, remove symbol table in all_video
as well.

Relax run-time check and do not return error for modules without symbol table.
Add additional checks to module verifier to make sure such modules

a) have non-empty .moddeps section. Without either externally visible symbols
or .moddeps modules are completely useless and should not be built.

b) do not have any relocations.

Closes: 46986

v2: add run-time check for empty symbol table if relocations are present as
    suggested by Vladimir.
2016-02-03 20:34:55 +03:00
Andrei Borzenkov
7290bb5623 10_linux: avoid multi-device root= kernel argument
If root filesystem is multidev btrfs, do not attempt to pass all devices as
kernel root= argument. This results in splitting command line in GRUB due to
embedded newline and even if we managed to quote it, kernel does not know how
to interpret it anyway. Multidev btrfs requires user space device scanning,
so passing single device would not work too.

This still respects user settings GRUB_DISABLE_LINUX_UUID. Not sure what we
should do in this case.

Closes: 45709
2016-02-01 20:13:48 +03:00
Vladimir Serbinenko
ff84a9b868 Error out if mtools invocation fails. 2016-01-22 19:28:08 +01:00
Vladimir Serbinenko
605eecc985 arm64: Add support for relocations needed for linaro gcc 2016-01-22 19:09:37 +01:00
Vladimir Serbinenko
b6a03dfd32 efiemu: Fix compilation failure 2016-01-22 14:10:30 +01:00
Vladimir Serbinenko
5f2b285bf8 Document cpuid -p 2016-01-22 13:50:53 +01:00
Robert Elliott
ae3b83a4d4 efiemu: Handle persistent RAM and unknown possible future additions. 2016-01-22 13:32:30 +01:00
Vladimir Serbinenko
dab148891e Document expr1 expr2 syntax for test command 2016-01-22 13:27:36 +01:00
Michael Chang
64e2d139fe Restore terminal settings on grub-emu exit. 2016-01-22 11:05:32 +01:00
Vladimir Serbinenko
0edd750e50 xen_boot: Remove obsolete module type distinctions. 2016-01-22 10:18:47 +01:00
Vladimir Serbinenko
cc2ed41039 arm: Ignore qemu clock bug 2016-01-22 10:12:43 +01:00
Vladimir Serbinenko
7c6c2ad42c i386-ieee1275: Increase maximum heap size to accomodate highres graphi tests 2016-01-22 10:12:43 +01:00
Colin Watson
47e67d809c Remove pragmas related to -Wunreachable-code
-Wunreachable-code has been a no-op since GCC 4.5; GRUB hasn't been
compiled with it since 2012; and GCC 6 produces "error:
'-Wunreachable-code' is not an option that controls warnings" for these.

Fixes Debian bug #812047.
2016-01-20 15:56:55 +00:00
Colin Watson
92bbf25714 loader/bsd: Fix signed/unsigned comparison 2016-01-16 20:40:55 +00:00
Colin Watson
95440b41d3 ahci, ehci: Fix typos 2016-01-16 20:37:15 +00:00
Andrei Borzenkov
f826d914e2 grub-probe: fix memory leak
Found by: Coverity scan.
CID: 73783
2016-01-16 21:47:28 +03:00
Andrei Borzenkov
77002c65d3 tftp: fix memory leaks in open
If protocol open fails, file is immediately freed, so data was leaked.

Found by: Coverity scan.
CID: 96659
2016-01-16 21:27:57 +03:00
Andrei Borzenkov
d4561cd080 tcp: fix memory leaks
Found by: Coverity scan.
CID: 96639, 96647
2016-01-16 20:59:50 +03:00
Andrei Borzenkov
9b4256bf05 net: fix memory leaks
Found by: Coverity scan.
CID: 96638, 96648
2016-01-16 20:48:33 +03:00
Andrei Borzenkov
eefa3239c2 legacycfg: fix memory leaks and add NULL check
Memory leaks found by Coverity scan.
CID: 96642, 96645
2016-01-16 20:34:02 +03:00
Andrei Borzenkov
4f8fe948b9 loader: Unintended sign extension
CID: 96707, 96699, 96693, 96691, 96711, 96709, 96708, 96703, 96702,
96700, 96698, 96696, 96695, 96692, 96710, 96705
2016-01-15 19:18:05 +03:00
Andrei Borzenkov
b95e926788 script: fix memory leak
Found by: Coverity scan.
CID: 96637
2016-01-12 22:50:30 +03:00
Andrei Borzenkov
26533fe6bc normal: fix memory leak
Found by: Coverity scan.
CID: 96641, 96670, 96667
2016-01-12 22:40:03 +03:00
Andrei Borzenkov
29862fdc3a xnu: fix memory leak
Found by: Coverity scan.
CID: 96663
2016-01-12 21:52:51 +03:00
Andrei Borzenkov
9daf7aae8b truecrypt: fix memory leak
Found by: Coverity scan.
CID: 156611
2016-01-12 21:52:51 +03:00
Andrei Borzenkov
a4b1326f0d gfxmenu: fix memory leak
Found by: Coverity scan.
CID: 96657
2016-01-12 21:52:50 +03:00
Andrei Borzenkov
dbb0f9fa4f efiemu: fix memory leak
Found by: Coverity scan.
CID: 156610
2016-01-12 21:52:50 +03:00
Andrei Borzenkov
e9d71db53a efidisk: fix memory leak
Found by: Coverity scan.
CID: 96644
2016-01-12 21:52:50 +03:00
Andrei Borzenkov
6c35ce72ba verify: fix memory leak
Found by: Coverity scan.
CID: 96643
2016-01-12 21:52:42 +03:00
Andrei Borzenkov
f3c84fa798 password_pbkdf2: fix memory leak
Found by: Coverity scan.
CID: 96656
2016-01-12 20:53:26 +03:00
Andrei Borzenkov
5db2190f2c parttool: fix memory leak
Found by: Coverity scan.
CID: 96652
2016-01-12 20:41:44 +03:00
Andrei Borzenkov
1bff60e5aa nativedisk: fix memory leak
Based on Coverity scan.
CID: 96660

Extended to also cover other error return places.
2016-01-12 20:37:43 +03:00
Andrei Borzenkov
8fe17d91af acpi: fix memory leak
Found by: Coverity scan.
CID: 96673
2016-01-12 20:26:30 +03:00
Andrei Borzenkov
66768b99f1 grub-install: include ehci in list of native modules
This matches behavior of "nativedisk" command.

Reported and tested by Smith Henry <sh37092@gmail.com>
2016-01-10 16:08:06 +03:00
Andrei Borzenkov
962b69d950 grub-mkimage: remove redundant NULL check
Found by: Coverity scan.
CID: 73737
2016-01-10 11:51:34 +03:00
Andrei Borzenkov
528256932b net: remove dead and redundant code
server cannot be NULL at this point (we return error earlier if it is).
Also structure is zalloc'ed, so no need to explicitly initialize
members to 0.

Found by: Coverity scan.
CID: 73837
2016-01-10 11:33:13 +03:00
Andrei Borzenkov
269a522c7d hostdisk: fix device detection
Condition was apparently reversed so GRUB assumed all devices were
files. This later made it skip BLKFLSBUF ioctl on Linux which caused
various page cache coherency issues. Observed were

- failure to validate blocklist install (read content did not match
  just written)

- failure to detect Linux MD on disk after online hot addition
  (GRUB got stale superblock)

Closes: 46691
2016-01-10 10:41:04 +03:00
Andrei Borzenkov
5a5a3c6963 setup: fix NULL pointer dereference
Check return value of grub_guess_root_devices

Found by: Coverity scan.
CID: 73638, 73751
2016-01-09 21:25:22 +03:00
Andrei Borzenkov
670c43af27 mkimage: fix unintended sign extension
Found by: Coverity scan.
CID: 73691, 73717
2016-01-09 21:05:44 +03:00
Andrei Borzenkov
dc27d254f2 util/getroot: delete dead code
is_part cannot be non-zero at this point.

Found by: Coveruty scan.
CID: 73838
2016-01-09 20:54:54 +03:00
Andrei Borzenkov
31f6506c57 loader/multiboot: fix unintended sign extension
Found by: Coveruty scan.
CID: 73700, 73763
2016-01-09 19:58:51 +03:00
Andrei Borzenkov
9fecb0588e kern/elf: fix unintended sign extension
Found by: Coverity scan.
CID: 73729, 73735, 73758, 73760
2016-01-09 19:41:26 +03:00
Andrei Borzenkov
aafd205c92 xfs: fix possible inode corruption in directory scan
grub_xfs_iterate_dir did not restore first character after inline
name when match was found. Dependning on XFS format this character
could be inode number and we could return to the same node later in
find_file if processing cycled symlinks.

CID: 86724
2016-01-09 18:55:55 +03:00
Andrei Borzenkov
bd60f5a207 rescue_parser: restructure code to avoid Coverity false positive
If line contains single word, line and argv[0] are aliases, so
no NULL dereference is possible, but Coverity does not know it.
Change code to avoid ambiguity and also remove redundant call to
grub_strchr.

CID: 86725
2016-01-09 18:15:27 +03:00
Andrei Borzenkov
725548a285 grub-mklayout: check subscript bounds
Found by: Coverity scan.
CID: 73686
2016-01-09 14:13:36 +03:00
Andrei Borzenkov
d5cc487d39 grub-probe: fix memory leak
Found by: Coverity scan.
CID: 73783
2016-01-09 13:55:28 +03:00
Andrei Borzenkov
fa2af21ec8 gfxmenu: fix memory leak
Found by: Coverity scan.
CID: 73766
2016-01-09 13:55:28 +03:00
Andrei Borzenkov
0e075ac385 util/setup: fix grub_util_path_list leak
Add helper grub_util_free_path_list and use it where appropriate.

Found by: Coverity scan.
CID: 73727
2016-01-09 13:55:18 +03:00
Andrei Borzenkov
57e7f1b775 setup: fix memory leak
Found by: Coverity scan.
CID: 73680, 73715
2016-01-09 13:10:10 +03:00
Andrei Borzenkov
67d9ce82ac efiemu: check return value of grub_efiemu_write_value
Found by: Coverity scan.
CID: 73590
2016-01-09 11:36:42 +03:00
Andrei Borzenkov
12bf87466f efiemu: change code to avoid Coverity false positive
CID: 73623
2016-01-09 11:36:42 +03:00
Andrei Borzenkov
97c41e1216 efiemu: fix unintended sign extension
Found by: Coverity scan.
CID: 73883, 73637
2016-01-09 11:36:42 +03:00
Andrei Borzenkov
8ab2675ede hfs: fix memory leak
Found by: Coverity scan.
CID: 156531
2016-01-09 11:36:42 +03:00
Andrei Borzenkov
efc04d65c7 grub-module-verifier: fix unintended sign extension
Found by: Coverity scan.
CID: 156533, 156532
2016-01-09 11:36:42 +03:00
152 changed files with 7056 additions and 2147 deletions

View File

@@ -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

View File

@@ -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
View File

@@ -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/

View File

@@ -86,9 +86,11 @@ CPPFLAGS_TERMINAL_LIST += '-Dgrub_term_register_output(...)=OUTPUT_TERMINAL_LIST
CPPFLAGS_COMMAND_LIST = '-Dgrub_register_command(...)=COMMAND_LIST_MARKER(__VA_ARGS__)'
CPPFLAGS_COMMAND_LIST += '-Dgrub_register_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

View File

@@ -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])

View File

@@ -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

View File

@@ -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)

View File

@@ -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`; \

View File

@@ -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
View File

@@ -0,0 +1,255 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2016 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/fdtbus.h>
#include <grub/fdt.h>
#include <grub/term.h>
static const void *dtb;
static grub_size_t root_address_cells, root_size_cells;
/* Pointer to this symbol signals invalid mapping. */
char grub_fdtbus_invalid_mapping[1];
struct grub_fdtbus_dev
{
struct grub_fdtbus_dev *next;
struct grub_fdtbus_dev *parent;
int node;
struct grub_fdtbus_driver *driver;
};
struct grub_fdtbus_dev *devs;
struct grub_fdtbus_driver *drivers;
static int
is_compatible (struct grub_fdtbus_driver *driver,
int node)
{
grub_size_t compatible_size;
const char *compatible = grub_fdt_get_prop (dtb, node, "compatible",
&compatible_size);
const char *compatible_end = compatible + compatible_size;
while (compatible < compatible_end)
{
if (grub_strcmp (driver->compatible, compatible) == 0)
return 1;
compatible += grub_strlen (compatible) + 1;
}
return 0;
}
static void
fdtbus_scan (struct grub_fdtbus_dev *parent)
{
int node;
for (node = grub_fdt_first_node (dtb, parent ? parent->node : 0); node >= 0;
node = grub_fdt_next_node (dtb, node))
{
struct grub_fdtbus_dev *dev;
struct grub_fdtbus_driver *driver;
dev = grub_zalloc (sizeof (*dev));
if (!dev)
{
grub_print_error ();
return;
}
dev->node = node;
dev->next = devs;
dev->parent = parent;
devs = dev;
FOR_LIST_ELEMENTS(driver, drivers)
if (!dev->driver && is_compatible (driver, node))
{
if (driver->attach(dev) == GRUB_ERR_NONE)
{
dev->driver = driver;
break;
}
grub_print_error ();
}
fdtbus_scan (dev);
}
}
void
grub_fdtbus_register (struct grub_fdtbus_driver *driver)
{
struct grub_fdtbus_dev *dev;
grub_list_push (GRUB_AS_LIST_P (&drivers),
GRUB_AS_LIST (driver));
for (dev = devs; dev; dev = dev->next)
if (!dev->driver && is_compatible (driver, dev->node))
{
if (driver->attach(dev) == GRUB_ERR_NONE)
dev->driver = driver;
grub_print_error ();
}
}
void
grub_fdtbus_unregister (struct grub_fdtbus_driver *driver)
{
grub_list_remove (GRUB_AS_LIST (driver));
struct grub_fdtbus_dev *dev;
for (dev = devs; dev; dev = dev->next)
if (dev->driver == driver)
{
if (driver->detach)
driver->detach(dev);
dev->driver = 0;
}
}
void
grub_fdtbus_init (const void *dtb_in, grub_size_t size)
{
if (!dtb_in || grub_fdt_check_header (dtb_in, size) < 0)
grub_fatal ("invalid FDT");
dtb = dtb_in;
const grub_uint32_t *prop = grub_fdt_get_prop (dtb, 0, "#address-cells", 0);
if (prop)
root_address_cells = grub_be_to_cpu32 (*prop);
else
root_address_cells = 1;
prop = grub_fdt_get_prop (dtb, 0, "#size-cells", 0);
if (prop)
root_size_cells = grub_be_to_cpu32 (*prop);
else
root_size_cells = 1;
fdtbus_scan (0);
}
static int
get_address_cells (const struct grub_fdtbus_dev *dev)
{
const grub_uint32_t *prop;
if (!dev)
return root_address_cells;
prop = grub_fdt_get_prop (dtb, dev->node, "#address-cells", 0);
if (prop)
return grub_be_to_cpu32 (*prop);
return 1;
}
static int
get_size_cells (const struct grub_fdtbus_dev *dev)
{
const grub_uint32_t *prop;
if (!dev)
return root_size_cells;
prop = grub_fdt_get_prop (dtb, dev->node, "#size-cells", 0);
if (prop)
return grub_be_to_cpu32 (*prop);
return 1;
}
static grub_uint64_t
get64 (const grub_uint32_t *reg, grub_size_t cells)
{
grub_uint64_t val = 0;
if (cells >= 1)
val = grub_be_to_cpu32 (reg[cells - 1]);
if (cells >= 2)
val |= ((grub_uint64_t) grub_be_to_cpu32 (reg[cells - 2])) << 32;
return val;
}
static volatile void *
translate (const struct grub_fdtbus_dev *dev, const grub_uint32_t *reg)
{
volatile void *ret;
const grub_uint32_t *ranges;
grub_size_t ranges_size, cells_per_mapping;
grub_size_t parent_address_cells, child_address_cells, child_size_cells;
grub_size_t nmappings, i;
if (dev == 0)
{
grub_uint64_t val;
val = get64 (reg, root_address_cells);
if (sizeof (void *) == 4 && (val >> 32))
return grub_fdtbus_invalid_mapping;
return (void *) (grub_addr_t) val;
}
ranges = grub_fdt_get_prop (dtb, dev->node, "ranges", &ranges_size);
if (!ranges)
return grub_fdtbus_invalid_mapping;
if (ranges_size == 0)
return translate (dev->parent, reg);
parent_address_cells = get_address_cells (dev->parent);
child_address_cells = get_address_cells (dev);
child_size_cells = get_size_cells (dev);
cells_per_mapping = parent_address_cells + child_address_cells + child_size_cells;
nmappings = ranges_size / 4 / cells_per_mapping;
for (i = 0; i < nmappings; i++)
{
const grub_uint32_t *child_addr = &ranges[i * cells_per_mapping];
const grub_uint32_t *parent_addr = child_addr + child_address_cells;
grub_uint64_t child_size = get64 (parent_addr + parent_address_cells, child_size_cells);
if (child_address_cells > 2 && grub_memcmp (reg, child_addr, (child_address_cells - 2) * 4) != 0)
continue;
if (get64 (reg, child_address_cells) < get64 (child_addr, child_address_cells))
continue;
grub_uint64_t offset = get64 (reg, child_address_cells) - get64 (child_addr, child_address_cells);
if (offset >= child_size)
continue;
ret = translate (dev->parent, parent_addr);
if (grub_fdtbus_is_mapping_valid (ret))
ret = (volatile char *) ret + offset;
return ret;
}
return grub_fdtbus_invalid_mapping;
}
volatile void *
grub_fdtbus_map_reg (const struct grub_fdtbus_dev *dev, int regno, grub_size_t *size)
{
grub_size_t address_cells, size_cells;
address_cells = get_address_cells (dev->parent);
size_cells = get_size_cells (dev->parent);
const grub_uint32_t *reg = grub_fdt_get_prop (dtb, dev->node, "reg", 0);
if (size && size_cells)
*size = reg[(address_cells + size_cells) * regno + address_cells];
if (size && !size_cells)
*size = 0;
return translate (dev->parent, reg + (address_cells + size_cells) * regno);
}
const char *
grub_fdtbus_get_name (const struct grub_fdtbus_dev *dev)
{
return grub_fdt_get_nodename (dtb, dev->node);
}
const void *
grub_fdtbus_get_prop (const struct grub_fdtbus_dev *dev,
const char *name,
grub_uint32_t *len)
{
return grub_fdt_get_prop (dtb, dev->node, name, len);
}
const void *
grub_fdtbus_get_fdt (void)
{
return dtb;
}

View File

@@ -0,0 +1,45 @@
/* ehci.c - EHCI Support. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2011 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/misc.h>
#include <grub/mm.h>
#include <grub/time.h>
#include <grub/usb.h>
#include <grub/fdtbus.h>
static grub_err_t
dwc2_attach(const struct grub_fdtbus_dev *dev)
{
grub_dprintf ("dwc2", "Found snps-dwc2\n");
grub_dwc2_init_device (grub_fdtbus_map_reg (dev, 0, 0));
return 0;
}
struct grub_fdtbus_driver dwc2 =
{
.compatible = "snps,dwc2",
.attach = dwc2_attach
};
void
grub_dwc2_pci_scan (void)
{
grub_fdtbus_register (&dwc2);
}

1791
grub-core/bus/usb/dwc2.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,45 @@
/* ehci.c - EHCI Support. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2011 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/misc.h>
#include <grub/mm.h>
#include <grub/time.h>
#include <grub/usb.h>
#include <grub/fdtbus.h>
static grub_err_t
ehci_attach(const struct grub_fdtbus_dev *dev)
{
grub_dprintf ("ehci", "Found generic-ehci\n");
grub_ehci_init_device (grub_fdtbus_map_reg (dev, 0, 0));
return 0;
}
struct grub_fdtbus_driver ehci =
{
.compatible = "generic-ehci",
.attach = ehci_attach
};
void
grub_ehci_pci_scan (void)
{
grub_fdtbus_register (&ehci);
}

View File

@@ -0,0 +1,208 @@
/* ehci.c - EHCI Support. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2011 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/pci.h>
#include <grub/cpu/pci.h>
#include <grub/cs5536.h>
#include <grub/misc.h>
#include <grub/mm.h>
#include <grub/time.h>
#include <grub/usb.h>
#define GRUB_EHCI_PCI_SBRN_REG 0x60
#define GRUB_EHCI_ADDR_MEM_MASK (~0xff)
/* USBLEGSUP bits and related OS OWNED byte offset */
enum
{
GRUB_EHCI_BIOS_OWNED = (1 << 16),
GRUB_EHCI_OS_OWNED = (1 << 24)
};
/* PCI iteration function... */
static int
grub_ehci_pci_iter (grub_pci_device_t dev, grub_pci_id_t pciid,
void *data __attribute__ ((unused)))
{
volatile grub_uint32_t *regs;
grub_uint32_t base, base_h;
grub_uint32_t eecp_offset;
grub_uint32_t usblegsup = 0;
grub_uint64_t maxtime;
grub_uint32_t interf;
grub_uint32_t subclass;
grub_uint32_t class;
grub_uint8_t release;
grub_uint32_t class_code;
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: begin\n");
if (pciid == GRUB_CS5536_PCIID)
{
grub_uint64_t basereg;
basereg = grub_cs5536_read_msr (dev, GRUB_CS5536_MSR_USB_EHCI_BASE);
if (!(basereg & GRUB_CS5536_MSR_USB_BASE_MEMORY_ENABLE))
{
/* Shouldn't happen. */
grub_dprintf ("ehci", "No EHCI address is assigned\n");
return 0;
}
base = (basereg & GRUB_CS5536_MSR_USB_BASE_ADDR_MASK);
basereg |= GRUB_CS5536_MSR_USB_BASE_BUS_MASTER;
basereg &= ~GRUB_CS5536_MSR_USB_BASE_PME_ENABLED;
basereg &= ~GRUB_CS5536_MSR_USB_BASE_PME_STATUS;
basereg &= ~GRUB_CS5536_MSR_USB_BASE_SMI_ENABLE;
grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_USB_EHCI_BASE, basereg);
}
else
{
grub_pci_address_t addr;
addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS);
class_code = grub_pci_read (addr) >> 8;
interf = class_code & 0xFF;
subclass = (class_code >> 8) & 0xFF;
class = class_code >> 16;
/* If this is not an EHCI controller, just return. */
if (class != 0x0c || subclass != 0x03 || interf != 0x20)
return 0;
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: class OK\n");
/* Check Serial Bus Release Number */
addr = grub_pci_make_address (dev, GRUB_EHCI_PCI_SBRN_REG);
release = grub_pci_read_byte (addr);
if (release != 0x20)
{
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: Wrong SBRN: %0x\n",
release);
return 0;
}
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: bus rev. num. OK\n");
/* Determine EHCI EHCC registers base address. */
addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0);
base = grub_pci_read (addr);
addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG1);
base_h = grub_pci_read (addr);
/* Stop if registers are mapped above 4G - GRUB does not currently
* work with registers mapped above 4G */
if (((base & GRUB_PCI_ADDR_MEM_TYPE_MASK) != GRUB_PCI_ADDR_MEM_TYPE_32)
&& (base_h != 0))
{
grub_dprintf ("ehci",
"EHCI grub_ehci_pci_iter: registers above 4G are not supported\n");
return 0;
}
base &= GRUB_PCI_ADDR_MEM_MASK;
if (!base)
{
grub_dprintf ("ehci",
"EHCI: EHCI is not mapped\n");
return 0;
}
/* Set bus master - needed for coreboot, VMware, broken BIOSes etc. */
addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND);
grub_pci_write_word(addr,
GRUB_PCI_COMMAND_MEM_ENABLED
| GRUB_PCI_COMMAND_BUS_MASTER
| grub_pci_read_word(addr));
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: 32-bit EHCI OK\n");
}
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: iobase of EHCC: %08x\n",
(base & GRUB_EHCI_ADDR_MEM_MASK));
regs = grub_pci_device_map_range (dev,
(base & GRUB_EHCI_ADDR_MEM_MASK),
0x100);
/* Is there EECP ? */
eecp_offset = (grub_le_to_cpu32 (regs[2]) >> 8) & 0xff;
/* Determine and change ownership. */
/* EECP offset valid in HCCPARAMS */
/* Ownership can be changed via EECP only */
if (pciid != GRUB_CS5536_PCIID && eecp_offset >= 0x40)
{
grub_pci_address_t pciaddr_eecp;
pciaddr_eecp = grub_pci_make_address (dev, eecp_offset);
usblegsup = grub_pci_read (pciaddr_eecp);
if (usblegsup & GRUB_EHCI_BIOS_OWNED)
{
grub_boot_time ("Taking ownership of EHCI controller");
grub_dprintf ("ehci",
"EHCI grub_ehci_pci_iter: EHCI owned by: BIOS\n");
/* Ownership change - set OS_OWNED bit */
grub_pci_write (pciaddr_eecp, usblegsup | GRUB_EHCI_OS_OWNED);
/* Ensure PCI register is written */
grub_pci_read (pciaddr_eecp);
/* Wait for finish of ownership change, EHCI specification
* doesn't say how long it can take... */
maxtime = grub_get_time_ms () + 1000;
while ((grub_pci_read (pciaddr_eecp) & GRUB_EHCI_BIOS_OWNED)
&& (grub_get_time_ms () < maxtime));
if (grub_pci_read (pciaddr_eecp) & GRUB_EHCI_BIOS_OWNED)
{
grub_dprintf ("ehci",
"EHCI grub_ehci_pci_iter: EHCI change ownership timeout");
/* Change ownership in "hard way" - reset BIOS ownership */
grub_pci_write (pciaddr_eecp, GRUB_EHCI_OS_OWNED);
/* Ensure PCI register is written */
grub_pci_read (pciaddr_eecp);
}
}
else if (usblegsup & GRUB_EHCI_OS_OWNED)
/* XXX: What to do in this case - nothing ? Can it happen ? */
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: EHCI owned by: OS\n");
else
{
grub_dprintf ("ehci",
"EHCI grub_ehci_pci_iter: EHCI owned by: NONE\n");
/* XXX: What to do in this case ? Can it happen ?
* Is code below correct ? */
/* Ownership change - set OS_OWNED bit */
grub_pci_write (pciaddr_eecp, GRUB_EHCI_OS_OWNED);
/* Ensure PCI register is written */
grub_pci_read (pciaddr_eecp);
}
/* Disable SMI, just to be sure. */
pciaddr_eecp = grub_pci_make_address (dev, eecp_offset + 4);
grub_pci_write (pciaddr_eecp, 0);
/* Ensure PCI register is written */
grub_pci_read (pciaddr_eecp);
}
grub_dprintf ("ehci", "inithw: EHCI grub_ehci_pci_iter: ownership OK\n");
grub_ehci_init_device (regs);
return 0;
}
void
grub_ehci_pci_scan (void)
{
grub_pci_iterate (grub_ehci_pci_iter, NULL);
}

View File

@@ -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");

View File

@@ -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

View File

@@ -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

View File

@@ -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;

View File

@@ -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);

View File

@@ -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;

View File

@@ -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;

View File

@@ -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+");

View File

@@ -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+");

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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]);

View File

@@ -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

View File

@@ -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);

View File

@@ -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]);

View File

@@ -85,6 +85,12 @@ make_devices (void)
{
/* Uggh. */
grub_free (handles);
while (devices)
{
d = devices->next;
grub_free (devices);
devices = d;
}
return 0;
}

View File

@@ -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);

View File

@@ -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");

View File

@@ -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;

View File

@@ -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 */

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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);

View File

@@ -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);

View File

@@ -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)) {

View File

@@ -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

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -29,6 +29,8 @@ void grub_arm_clean_dcache_range_armv6 (grub_addr_t start, grub_addr_t end,
grub_addr_t dlinesz);
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)
{

View File

@@ -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"

View File

@@ -0,0 +1,74 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2007,2008,2013 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/coreboot/lbio.h>
#include <grub/types.h>
#include <grub/err.h>
#include <grub/misc.h>
#include <grub/dl.h>
#include <grub/arm/startup.h>
GRUB_MOD_LICENSE ("GPLv3+");
#pragma GCC diagnostic ignored "-Wcast-align"
/* Helper for grub_linuxbios_table_iterate. */
static int
check_signature (grub_linuxbios_table_header_t tbl_header)
{
if (! grub_memcmp (tbl_header->signature, "LBIO", 4))
return 1;
return 0;
}
grub_err_t
grub_linuxbios_table_iterate (int (*hook) (grub_linuxbios_table_item_t,
void *),
void *hook_data)
{
grub_linuxbios_table_header_t table_header
= (grub_linuxbios_table_header_t) grub_arm_saved_registers.r[0];
grub_linuxbios_table_item_t table_item;
if (!check_signature (table_header))
return 0;
signature_found:
table_item =
(grub_linuxbios_table_item_t) ((char *) table_header +
table_header->header_size);
for (; table_item < (grub_linuxbios_table_item_t) ((char *) table_header
+ table_header->header_size
+ table_header->table_size);
table_item = (grub_linuxbios_table_item_t) ((char *) table_item + table_item->size))
{
if (table_item->tag == GRUB_LINUXBIOS_MEMBER_LINK
&& check_signature ((grub_linuxbios_table_header_t) (grub_addr_t)
*(grub_uint64_t *) (table_item + 1)))
{
table_header = (grub_linuxbios_table_header_t) (grub_addr_t)
*(grub_uint64_t *) (table_item + 1);
goto signature_found;
}
if (hook (table_item, hook_data))
return 1;
}
return 0;
}

View File

@@ -0,0 +1,44 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2016 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/symbol.h>
.file "coreboot.S"
.text
.syntax unified
#if !defined (__thumb2__)
.arch armv7a
.arm
#else
.arch armv7
.thumb
#endif
FUNCTION(grub_arm_pfr1)
mrc p15, 0, r0, c0, c1, 1
bx lr
FUNCTION(grub_armv7_get_timer_value)
isb
mrrc p15, 1, r0, r1, c14
bx lr
FUNCTION(grub_armv7_get_timer_frequency)
mrc p15, 0, r0, c14, c0, 0
bx lr

View File

@@ -0,0 +1,59 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2007,2009 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/dl.h>
#include <grub/dma.h>
#include <grub/mm.h>
#include <grub/misc.h>
#include <grub/mm_private.h>
#include <grub/cache.h>
struct grub_pci_dma_chunk *
grub_memalign_dma32 (grub_size_t align, grub_size_t size)
{
void *ret;
if (align < 64)
align = 64;
size = ALIGN_UP (size, align);
ret = grub_memalign (align, size);
if (!ret)
return 0;
grub_arch_sync_dma_caches (ret, size);
return ret;
}
void
grub_dma_free (struct grub_pci_dma_chunk *ch)
{
grub_size_t size = (((struct grub_mm_header *) ch) - 1)->size * GRUB_MM_ALIGN;
grub_arch_sync_dma_caches (ch, size);
grub_free (ch);
}
volatile void *
grub_dma_get_virt (struct grub_pci_dma_chunk *ch)
{
return (void *) ch;
}
grub_uint32_t
grub_dma_get_phys (struct grub_pci_dma_chunk *ch)
{
return (grub_uint32_t) (grub_addr_t) ch;
}

View File

@@ -0,0 +1,169 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2009,2013 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/kernel.h>
#include <grub/mm.h>
#include <grub/memory.h>
#include <grub/machine/console.h>
#include <grub/machine/kernel.h>
#include <grub/offsets.h>
#include <grub/types.h>
#include <grub/err.h>
#include <grub/dl.h>
#include <grub/misc.h>
#include <grub/loader.h>
#include <grub/env.h>
#include <grub/cache.h>
#include <grub/time.h>
#include <grub/symbol.h>
#include <grub/video.h>
#include <grub/coreboot/lbio.h>
#include <grub/fdtbus.h>
extern grub_uint8_t _start[];
extern grub_uint8_t _end[];
extern grub_uint8_t _edata[];
grub_addr_t start_of_ram = ~(grub_addr_t)0;
void __attribute__ ((noreturn))
grub_exit (void)
{
/* We can't use grub_fatal() in this function. This would create an infinite
loop, since grub_fatal() calls grub_abort() which in turn calls grub_exit(). */
while (1)
grub_cpu_idle ();
}
static grub_uint64_t modend;
static int have_memory = 0;
/* Helper for grub_machine_init. */
static int
heap_init (grub_uint64_t addr, grub_uint64_t size, grub_memory_type_t type,
void *data __attribute__ ((unused)))
{
grub_uint64_t begin = addr, end = addr + size;
#if GRUB_CPU_SIZEOF_VOID_P == 4
/* Restrict ourselves to 32-bit memory space. */
if (begin > GRUB_ULONG_MAX)
return 0;
if (end > GRUB_ULONG_MAX)
end = GRUB_ULONG_MAX;
#endif
if (start_of_ram > begin)
start_of_ram = begin;
if (type != GRUB_MEMORY_AVAILABLE)
return 0;
if (modend && begin < modend)
{
if (begin < (grub_addr_t)_start)
{
grub_mm_init_region ((void *) (grub_addr_t) begin, (grub_size_t) ((grub_addr_t)_start - begin));
have_memory = 1;
}
begin = modend;
}
/* Avoid DMA problems. */
if (end >= 0xfe000000)
end = 0xfe000000;
if (end <= begin)
return 0;
grub_mm_init_region ((void *) (grub_addr_t) begin, (grub_size_t) (end - begin));
have_memory = 1;
return 0;
}
static const void *dtb;
static grub_size_t dtb_size;
static int
iterate_linuxbios_table (grub_linuxbios_table_item_t table_item, void *data __attribute__ ((unused)))
{
if (table_item->tag != GRUB_LINUXBIOS_MEMBER_DTB)
return 0;
if (grub_fdt_check_header (table_item + 1, table_item->size) >= 0)
{
dtb = table_item + 1;
dtb_size = table_item->size;
}
else
grub_printf ("Invalid DTB supplied by coreboot\n");
return 0;
}
void
grub_machine_init (void)
{
struct grub_module_header *header;
modend = grub_modules_get_end ();
grub_video_coreboot_fb_early_init ();
grub_machine_mmap_iterate (heap_init, NULL);
if (!have_memory)
grub_fatal ("No memory found");
grub_video_coreboot_fb_late_init ();
grub_font_init ();
grub_gfxterm_init ();
FOR_MODULES (header)
if (header->type == OBJ_TYPE_DTB)
{
char *dtb_orig_addr, *dtb_copy;
dtb_orig_addr = (char *) header + sizeof (struct grub_module_header);
dtb_size = header->size - sizeof (struct grub_module_header);
dtb = dtb_copy = grub_malloc (dtb_size);
grub_memmove (dtb_copy, dtb_orig_addr, dtb_size);
break;
}
if (!dtb)
grub_linuxbios_table_iterate (iterate_linuxbios_table, 0);
if (!dtb)
grub_fatal ("No DTB found");
grub_fdtbus_init (dtb, dtb_size);
grub_machine_timer_init ();
grub_cros_init ();
grub_pl050_init ();
}
void
grub_machine_get_bootlocation (char **device __attribute__ ((unused)),
char **path __attribute__ ((unused)))
{
}
void
grub_machine_fini (int flags __attribute__ ((unused)))
{
}

View File

@@ -0,0 +1,101 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2016 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/mm.h>
#include <grub/machine/kernel.h>
#include <grub/types.h>
#include <grub/err.h>
#include <grub/time.h>
#include <grub/fdtbus.h>
#include <grub/misc.h>
grub_uint64_t
grub_armv7_get_timer_value(void);
grub_uint32_t
grub_armv7_get_timer_frequency(void);
grub_uint32_t
grub_arm_pfr1(void);
static int have_timer = 0;
static volatile grub_uint32_t *sp804_regs;
static grub_uint64_t
sp804_get_time_ms (void)
{
static grub_uint32_t high, last_low;
grub_uint32_t low = ~sp804_regs[1];
if (last_low > low)
high++;
last_low = low;
return grub_divmod64 ((((grub_uint64_t) high) << 32) | low,
1000, 0);
}
static grub_err_t
sp804_attach(const struct grub_fdtbus_dev *dev)
{
if (have_timer)
return GRUB_ERR_NONE;
sp804_regs = grub_fdtbus_map_reg (dev, 0, 0);
if (!grub_fdtbus_is_mapping_valid (sp804_regs))
return grub_error (GRUB_ERR_IO, "could not map sp804: %p", sp804_regs);
grub_install_get_time_ms (sp804_get_time_ms);
have_timer = 1;
return GRUB_ERR_NONE;
}
struct grub_fdtbus_driver sp804 =
{
.compatible = "arm,sp804",
.attach = sp804_attach
};
static grub_uint32_t timer_frequency_in_khz;
static grub_uint64_t
generic_get_time_ms (void)
{
return grub_divmod64 (grub_armv7_get_timer_value(), timer_frequency_in_khz, 0);
}
static int
try_generic_timer (void)
{
if (((grub_arm_pfr1 () >> 16) & 0xf) != 1)
return 0;
grub_printf ("freq = %x\n", grub_armv7_get_timer_frequency());
timer_frequency_in_khz = 0x016e3600 / 1000; //grub_armv7_get_timer_frequency() / 1000;
if (timer_frequency_in_khz == 0)
return 0;
grub_install_get_time_ms (generic_get_time_ms);
have_timer = 1;
return 1;
}
void
grub_machine_timer_init (void)
{
grub_fdtbus_register (&sp804);
if (!have_timer)
try_generic_timer ();
if (!have_timer)
grub_fatal ("No timer found");
}

View File

@@ -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:

View File

@@ -0,0 +1,70 @@
/* init.c - generic U-Boot initialization and finalization */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2016 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/uboot/uboot.h>
#include <grub/arm/startup.h>
#include <grub/uboot/api_public.h>
extern int (*grub_uboot_syscall_ptr) (int, int *, ...);
grub_uint32_t
grub_uboot_get_machine_type (void)
{
return grub_arm_saved_registers.r[1];
}
const void *
grub_uboot_get_boot_data (void)
{
return (const void *) grub_arm_saved_registers.r[2];
}
int
grub_uboot_api_init (void)
{
struct api_signature *start, *end;
struct api_signature *p;
grub_addr_t grub_uboot_search_hint = grub_arm_saved_registers.sp;
if (grub_uboot_search_hint)
{
/* Extended search range to work around Trim Slice U-Boot issue */
start = (struct api_signature *) ((grub_uboot_search_hint & ~0x000fffff)
- 0x00500000);
end =
(struct api_signature *) ((grub_addr_t) start + UBOOT_API_SEARCH_LEN -
API_SIG_MAGLEN + 0x00500000);
}
else
{
start = 0;
end = (struct api_signature *) (256 * 1024 * 1024);
}
/* Structure alignment is (at least) 8 bytes */
for (p = start; p < end; p = (void *) ((grub_addr_t) p + 8))
{
if (grub_memcmp (&(p->magic), API_SIG_MAGIC, API_SIG_MAGLEN) == 0)
{
grub_uboot_syscall_ptr = p->syscall;
return p->version;
}
}
return 0;
}

View File

@@ -0,0 +1,73 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2013 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/offsets.h>
#include <grub/symbol.h>
#include <grub/machine/kernel.h>
/*
* uboot_syscall():
* This function is effectively a veneer, so it cannot
* modify the stack or corrupt any registers other than
* r12 (ip). Furthermore it needs to restore r8 for
* U-Boot (Global Data Pointer) and preserve it for Grub.
*/
FUNCTION(grub_uboot_syscall)
str r8, transition_space
str lr, transition_space + 4
str r9, transition_space + 8
ldr ip, saved_registers_ptr
ldr r8, [ip, #4 * 8]
ldr r9, [ip, #4 * 9]
bl do_syscall
ldr r8, transition_space
ldr lr, transition_space + 4
ldr r9, transition_space + 8
bx lr
do_syscall:
ldr ip, grub_uboot_syscall_ptr
bx ip
FUNCTION(grub_uboot_return)
ldr ip, saved_registers_ptr
ldr sp, [ip, #4 * 4]
pop {r4-r12, lr}
mov sp, r12
bx lr
.align 3
@ GRUB context stack space
transition_space:
.long 0 @ r8
.long 0 @ lr
.long 0 @ r9
saved_registers_ptr:
.long EXT_C(grub_arm_saved_registers)
VARIABLE(grub_uboot_syscall_ptr)
.long 0 @
END

View File

@@ -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"),

View File

@@ -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;
}

View 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 ();
}

View File

@@ -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

View File

@@ -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;

View File

@@ -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,

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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)

View File

@@ -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>

View File

@@ -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)
{

View File

@@ -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;
}

View File

@@ -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 ();
}

View File

@@ -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;

View File

@@ -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);

View File

@@ -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)
{

View File

@@ -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

View File

@@ -102,13 +102,13 @@ static grub_uint32_t *get_next_node (const void *fdt, char *node_name)
static int get_mem_rsvmap_size (const void *fdt)
{
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
View 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);
}

View File

@@ -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
View 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);
}

View File

@@ -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;
}
}
}
}

View File

@@ -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 ();
}

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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);

View 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

View File

@@ -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)

View File

@@ -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);

View File

@@ -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)

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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)

View File

@@ -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 */
}
}

View File

@@ -30,7 +30,6 @@
#include "grub_script.tab.h"
#pragma GCC diagnostic ignored "-Wunreachable-code"
#pragma GCC diagnostic ignored "-Wmissing-declarations"
%}

View File

@@ -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
View File

@@ -0,0 +1,117 @@
/*
* GRUB -- GRand Unified Bootloader
*
* Copyright (C) 2012 Google Inc.
* Copyright (C) 2016 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/ps2.h>
#include <grub/fdtbus.h>
#include <grub/err.h>
#include <grub/machine/kernel.h>
#include <grub/misc.h>
#include <grub/term.h>
#include <grub/time.h>
#include <grub/fdtbus.h>
#include <grub/arm/cros_ec.h>
struct grub_ps2_state ps2_state;
struct grub_cros_ec_keyscan old_scan;
static grub_uint8_t map_code[GRUB_CROS_EC_KEYSCAN_COLS][GRUB_CROS_EC_KEYSCAN_ROWS];
static grub_uint8_t e0_translate[16] =
{
0x1c, 0x1d, 0x35, 0x00,
0x38, 0x00, 0x47, 0x48,
0x49, 0x4b, 0x4d, 0x4f,
0x50, 0x51, 0x52, 0x53,
};
/* If there is a character pending, return it;
otherwise return GRUB_TERM_NO_KEY. */
static int
grub_cros_keyboard_getkey (struct grub_term_input *term __attribute__ ((unused)))
{
struct grub_cros_ec_keyscan scan;
int i, j;
if (grub_cros_ec_scan_keyboard(&scan) < 0)
return GRUB_TERM_NO_KEY;
for (i = 0; i < GRUB_CROS_EC_KEYSCAN_COLS; i++)
if (scan.data[i] ^ old_scan.data[i])
for (j = 0; j < GRUB_CROS_EC_KEYSCAN_ROWS; j++)
if ((scan.data[i] ^ old_scan.data[i]) & (1 << j))
{
grub_uint8_t code = map_code[i][j];
int ret;
grub_uint8_t brk = 0;
if (!(scan.data[i] & (1 << j)))
brk = 0x80;
grub_dprintf ("cros_keyboard", "key <%d, %d> code %x\n", i, j, code);
if (code < 0x60)
ret = grub_ps2_process_incoming_byte (&ps2_state, code | brk);
else if (code >= 0x60 && code < 0x70 && e0_translate[code - 0x60])
{
grub_ps2_process_incoming_byte (&ps2_state, 0xe0);
ret = grub_ps2_process_incoming_byte (&ps2_state, e0_translate[code - 0x60] | brk);
}
else
ret = GRUB_TERM_NO_KEY;
old_scan.data[i] ^= (1 << j);
if (ret != GRUB_TERM_NO_KEY)
return ret;
}
return GRUB_TERM_NO_KEY;
}
static struct grub_term_input grub_cros_keyboard_term =
{
.name = "cros_keyboard",
.getkey = grub_cros_keyboard_getkey
};
static grub_err_t
cros_attach(const struct grub_fdtbus_dev *dev __attribute__ ((unused)))
{
grub_size_t keymap_size, i;
const grub_uint8_t *keymap = grub_fdtbus_get_prop (dev, "linux,keymap", &keymap_size);
if (keymap)
{
for (i = 0; i + 3 < keymap_size; i += 4)
if (keymap[i+1] < GRUB_CROS_EC_KEYSCAN_COLS && keymap[i] < GRUB_CROS_EC_KEYSCAN_ROWS
&& keymap[i+2] == 0 && keymap[i+3] < 0x80)
map_code[keymap[i+1]][keymap[i]] = keymap[i+3];
}
ps2_state.current_set = 1;
ps2_state.at_keyboard_status = 0;
grub_term_register_input ("cros_keyboard", &grub_cros_keyboard_term);
return GRUB_ERR_NONE;
}
struct grub_fdtbus_driver cros =
{
.compatible = "google,cros-ec-keyb",
.attach = cros_attach
};
void
grub_cros_init (void)
{
grub_fdtbus_register (&cros);
}

View File

@@ -0,0 +1,270 @@
/*
* GRUB -- GRand Unified Bootloader
*
* Copyright (C) 2012 Google Inc.
* Copyright (C) 2016 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/mm.h>
#include <grub/time.h>
#include <grub/misc.h>
#include <grub/arm/cros_ec.h>
static grub_uint64_t
grub_get_time_us (void)
{
return 1000 * grub_get_time_ms();
}
static void
grub_microsleep (grub_uint64_t len)
{
grub_uint64_t end_time = grub_get_time_us () + len;
while (grub_get_time_us () < end_time)
grub_cpu_idle ();
}
volatile grub_uint32_t *spi = (volatile grub_uint32_t *) 0xff110000;
static int
spi_send (const void *data, grub_size_t sz)
{
const grub_uint8_t *ptr = data, *end = ptr + sz;
spi[2] = 0;
spi[1] = sz - 1;
spi[0] = ((1 << 18) | spi[0]) & ~(1 << 19);
spi[2] = 1;
while (ptr < end)
{
while (spi[9] & 2);
spi[256] = *ptr++;
}
while (spi[9] & 1);
return 0;
}
static int
spi_read (void *data, grub_size_t sz)
{
grub_uint8_t *ptr = data, *end = ptr + sz;
spi[2] = 0;
spi[1] = sz - 1;
spi[0] = ((1 << 19) | spi[0]) & ~(1 << 18);
spi[2] = 1;
while (ptr < end)
{
while (spi[9] & 8);
*ptr++ = spi[512];
}
while (spi[9] & 1);
return 0;
}
static int
spi_start (void)
{
spi[3] = 1;
return 0;
}
static void
spi_stop (void)
{
spi[3] = 0;
}
#define uint8_t grub_uint8_t
#define uint16_t grub_uint16_t
#define uint32_t grub_uint32_t
#define uint64_t grub_uint64_t
#define mdelay grub_millisleep
#define memcpy grub_memcpy
static const uint64_t FramingTimeoutUs = 300 * 1000;
static const uint8_t EcFramingByte = 0xec;
#define EC_CMD_MKBP_STATE 0x60
#define EC_CMD_VERSION0 0xdc
static uint64_t last_transfer;
static void stop_bus(void)
{
spi_stop();
last_transfer = grub_get_time_us();
}
static int wait_for_frame(void)
{
uint64_t start = grub_get_time_us();
uint8_t byte;
do {
if (spi_read(&byte, 1))
return -1;
if (byte != EcFramingByte &&
grub_get_time_us() - start > FramingTimeoutUs) {
grub_dprintf("cros", "Timeout waiting for framing byte.\n");
return -1;
}
} while (byte != EcFramingByte);
return 0;
}
/*
* Calculate a simple 8-bit checksum of a data block
*
* @param data Data block to checksum
* @param size Size of data block in bytes
* @return checksum value (0 to 255)
*/
static uint8_t cros_ec_calc_checksum(const void *data, int size)
{
uint8_t csum;
const uint8_t *bytes = data;
int i;
for (i = csum = 0; i < size; i++)
csum += bytes[i];
return csum & 0xff;
}
enum {
// response, arglen
CROS_EC_SPI_IN_HDR_SIZE = 2,
// version, cmd, arglen
CROS_EC_SPI_OUT_HDR_SIZE = 3
};
static grub_uint8_t busbuf[256];
#define MSG_BYTES ((int)sizeof (busbuf))
static int ec_command(int cmd, int cmd_version,
const void *dout, int dout_len,
void *din, int din_len)
{
uint8_t *bytes;
// Header + data + checksum.
uint32_t out_bytes = CROS_EC_SPI_OUT_HDR_SIZE + dout_len + 1;
uint32_t in_bytes = CROS_EC_SPI_IN_HDR_SIZE + din_len + 1;
/*
* Sanity-check I/O sizes given transaction overhead in internal
* buffers.
*/
if (out_bytes > MSG_BYTES) {
grub_dprintf("cros", "Cannot send %d bytes\n", dout_len);
return -1;
}
if (in_bytes > MSG_BYTES) {
grub_dprintf("cros", "Cannot receive %d bytes\n", din_len);
return -1;
}
// Prepare the output.
bytes = busbuf;
*bytes++ = EC_CMD_VERSION0 + cmd_version;
*bytes++ = cmd;
*bytes++ = dout_len;
memcpy(bytes, dout, dout_len);
bytes += dout_len;
*bytes++ = cros_ec_calc_checksum(busbuf,
CROS_EC_SPI_OUT_HDR_SIZE + dout_len);
while (grub_get_time_us() - last_transfer < 200)
;
if (spi_start())
return -1;
// Allow EC to ramp up clock after being awoken.
// See chrome-os-partner:32223 for more details.
grub_microsleep (100);
if (spi_send(busbuf, out_bytes)) {
stop_bus();
return -1;
}
// Wait until the EC is ready.
if (wait_for_frame()) {
stop_bus();
return -1;
}
// Read the response code and the data length.
bytes = busbuf;
if (spi_read(bytes, 2)) {
stop_bus();
return -1;
}
uint8_t result = *bytes++;
uint8_t length = *bytes++;
// Make sure there's enough room for the data.
if (CROS_EC_SPI_IN_HDR_SIZE + length + 1 > MSG_BYTES) {
grub_dprintf("cros", "Received length %#02x too large\n",
length);
stop_bus();
return -1;
}
// Read the data and the checksum, and finish up.
if (spi_read(bytes, length + 1)) {
stop_bus();
return -1;
}
bytes += length;
int expected = *bytes++;
stop_bus();
// Check the integrity of the response.
if (result != 0) {
grub_dprintf("cros", "Received bad result code %d\n", result);
return -result;
}
int csum = cros_ec_calc_checksum(busbuf,
CROS_EC_SPI_IN_HDR_SIZE + length);
if (csum != expected) {
grub_dprintf("cros", "Invalid checksum rx %#02x, calced %#02x\n",
expected, csum);
return -1;
}
// If the caller wants the response, copy it out for them.
if (length < din_len)
din_len = length;
if (din) {
memcpy(din, (uint8_t *)busbuf + CROS_EC_SPI_IN_HDR_SIZE,
din_len);
}
return din_len;
}
int
grub_cros_ec_scan_keyboard(struct grub_cros_ec_keyscan *scan)
{
if (ec_command(EC_CMD_MKBP_STATE, 0, NULL, 0, scan,
sizeof(*scan)) < (int)sizeof(*scan))
return -1;
return 0;
}

189
grub-core/term/arm/pl050.c Normal file
View File

@@ -0,0 +1,189 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2007,2008,2009 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/ps2.h>
#include <grub/fdtbus.h>
#include <grub/err.h>
#include <grub/machine/kernel.h>
#include <grub/at_keyboard.h>
#include <grub/misc.h>
#include <grub/term.h>
#include <grub/time.h>
#include <grub/ps2.h>
#include <grub/fdtbus.h>
static volatile grub_uint32_t *pl050_regs;
struct grub_ps2_state ps2_state;
static void
keyboard_controller_wait_until_ready (void)
{
while (! (pl050_regs[1] & 0x40));
}
static grub_uint8_t
wait_ack (void)
{
grub_uint64_t endtime;
grub_uint8_t ack;
endtime = grub_get_time_ms () + 20;
do
ack = pl050_regs[2];
while (ack != GRUB_AT_ACK && ack != GRUB_AT_NACK
&& grub_get_time_ms () < endtime);
return ack;
}
static int
write_mode (int mode)
{
unsigned i;
for (i = 0; i < GRUB_AT_TRIES; i++)
{
grub_uint8_t ack;
keyboard_controller_wait_until_ready ();
pl050_regs[2] = 0xf0;
keyboard_controller_wait_until_ready ();
pl050_regs[2] = mode;
keyboard_controller_wait_until_ready ();
ack = wait_ack ();
if (ack == GRUB_AT_NACK)
continue;
if (ack == GRUB_AT_ACK)
break;
return 0;
}
return (i != GRUB_AT_TRIES);
}
static int
query_mode (void)
{
grub_uint8_t ret;
int e;
e = write_mode (0);
if (!e)
return 0;
keyboard_controller_wait_until_ready ();
do
ret = pl050_regs[2];
while (ret == GRUB_AT_ACK);
/* QEMU translates the set even in no-translate mode. */
if (ret == 0x43 || ret == 1)
return 1;
if (ret == 0x41 || ret == 2)
return 2;
if (ret == 0x3f || ret == 3)
return 3;
return 0;
}
static void
set_scancodes (void)
{
write_mode (2);
ps2_state.current_set = query_mode ();
grub_dprintf ("atkeyb", "returned set %d\n", ps2_state.current_set);
if (ps2_state.current_set == 2)
return;
write_mode (1);
ps2_state.current_set = query_mode ();
grub_dprintf ("atkeyb", "returned set %d\n", ps2_state.current_set);
if (ps2_state.current_set == 1)
return;
grub_dprintf ("atkeyb", "no supported scancode set found\n");
}
static void
keyboard_controller_led (grub_uint8_t leds)
{
keyboard_controller_wait_until_ready ();
pl050_regs[2] = 0xed;
keyboard_controller_wait_until_ready ();
pl050_regs[2] = leds & 0x7;
}
/* If there is a character pending, return it;
otherwise return GRUB_TERM_NO_KEY. */
static int
grub_pl050_keyboard_getkey (struct grub_term_input *term __attribute__ ((unused)))
{
grub_uint8_t at_key;
int ret;
grub_uint8_t old_led;
if (!(pl050_regs[1] & 0x10))
return -1;
at_key = pl050_regs[2];
old_led = ps2_state.led_status;
ret = grub_ps2_process_incoming_byte (&ps2_state, at_key);
if (old_led != ps2_state.led_status)
keyboard_controller_led (ps2_state.led_status);
return ret;
}
static struct grub_term_input grub_pl050_keyboard_term =
{
.name = "pl050_keyboard",
.getkey = grub_pl050_keyboard_getkey
};
static grub_err_t
pl050_attach(const struct grub_fdtbus_dev *dev)
{
const grub_uint32_t *reg;
reg = grub_fdtbus_get_prop (dev, "reg", 0);
/* Mouse. Nothing to do. */
if (grub_be_to_cpu32 (*reg) == 0x7000)
return 0;
pl050_regs = grub_fdtbus_map_reg (dev, 0, 0);
if (!grub_fdtbus_is_mapping_valid (pl050_regs))
return grub_error (GRUB_ERR_IO, "could not map pl050");
ps2_state.at_keyboard_status = 0;
set_scancodes ();
keyboard_controller_led (ps2_state.led_status);
grub_term_register_input ("pl050_keyboard", &grub_pl050_keyboard_term);
return GRUB_ERR_NONE;
}
struct grub_fdtbus_driver pl050 =
{
.compatible = "arm,pl050",
.attach = pl050_attach
};
void
grub_pl050_init (void)
{
grub_fdtbus_register (&pl050);
}

View File

@@ -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;
}

View File

@@ -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
View File

@@ -0,0 +1,387 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2007,2008,2009 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/dl.h>
#include <grub/misc.h>
#include <grub/term.h>
#include <grub/keyboard_layouts.h>
#include <grub/ps2.h>
#define KEYBOARD_LED_SCROLL (1 << 0)
#define KEYBOARD_LED_NUM (1 << 1)
#define KEYBOARD_LED_CAPS (1 << 2)
static const grub_uint8_t set1_mapping[128] =
{
/* 0x00 */ 0 /* Unused */, GRUB_KEYBOARD_KEY_ESCAPE,
/* 0x02 */ GRUB_KEYBOARD_KEY_1, GRUB_KEYBOARD_KEY_2,
/* 0x04 */ GRUB_KEYBOARD_KEY_3, GRUB_KEYBOARD_KEY_4,
/* 0x06 */ GRUB_KEYBOARD_KEY_5, GRUB_KEYBOARD_KEY_6,
/* 0x08 */ GRUB_KEYBOARD_KEY_7, GRUB_KEYBOARD_KEY_8,
/* 0x0a */ GRUB_KEYBOARD_KEY_9, GRUB_KEYBOARD_KEY_0,
/* 0x0c */ GRUB_KEYBOARD_KEY_DASH, GRUB_KEYBOARD_KEY_EQUAL,
/* 0x0e */ GRUB_KEYBOARD_KEY_BACKSPACE, GRUB_KEYBOARD_KEY_TAB,
/* 0x10 */ GRUB_KEYBOARD_KEY_Q, GRUB_KEYBOARD_KEY_W,
/* 0x12 */ GRUB_KEYBOARD_KEY_E, GRUB_KEYBOARD_KEY_R,
/* 0x14 */ GRUB_KEYBOARD_KEY_T, GRUB_KEYBOARD_KEY_Y,
/* 0x16 */ GRUB_KEYBOARD_KEY_U, GRUB_KEYBOARD_KEY_I,
/* 0x18 */ GRUB_KEYBOARD_KEY_O, GRUB_KEYBOARD_KEY_P,
/* 0x1a */ GRUB_KEYBOARD_KEY_LBRACKET, GRUB_KEYBOARD_KEY_RBRACKET,
/* 0x1c */ GRUB_KEYBOARD_KEY_ENTER, GRUB_KEYBOARD_KEY_LEFT_CTRL,
/* 0x1e */ GRUB_KEYBOARD_KEY_A, GRUB_KEYBOARD_KEY_S,
/* 0x20 */ GRUB_KEYBOARD_KEY_D, GRUB_KEYBOARD_KEY_F,
/* 0x22 */ GRUB_KEYBOARD_KEY_G, GRUB_KEYBOARD_KEY_H,
/* 0x24 */ GRUB_KEYBOARD_KEY_J, GRUB_KEYBOARD_KEY_K,
/* 0x26 */ GRUB_KEYBOARD_KEY_L, GRUB_KEYBOARD_KEY_SEMICOLON,
/* 0x28 */ GRUB_KEYBOARD_KEY_DQUOTE, GRUB_KEYBOARD_KEY_RQUOTE,
/* 0x2a */ GRUB_KEYBOARD_KEY_LEFT_SHIFT, GRUB_KEYBOARD_KEY_BACKSLASH,
/* 0x2c */ GRUB_KEYBOARD_KEY_Z, GRUB_KEYBOARD_KEY_X,
/* 0x2e */ GRUB_KEYBOARD_KEY_C, GRUB_KEYBOARD_KEY_V,
/* 0x30 */ GRUB_KEYBOARD_KEY_B, GRUB_KEYBOARD_KEY_N,
/* 0x32 */ GRUB_KEYBOARD_KEY_M, GRUB_KEYBOARD_KEY_COMMA,
/* 0x34 */ GRUB_KEYBOARD_KEY_DOT, GRUB_KEYBOARD_KEY_SLASH,
/* 0x36 */ GRUB_KEYBOARD_KEY_RIGHT_SHIFT, GRUB_KEYBOARD_KEY_NUMMUL,
/* 0x38 */ GRUB_KEYBOARD_KEY_LEFT_ALT, GRUB_KEYBOARD_KEY_SPACE,
/* 0x3a */ GRUB_KEYBOARD_KEY_CAPS_LOCK, GRUB_KEYBOARD_KEY_F1,
/* 0x3c */ GRUB_KEYBOARD_KEY_F2, GRUB_KEYBOARD_KEY_F3,
/* 0x3e */ GRUB_KEYBOARD_KEY_F4, GRUB_KEYBOARD_KEY_F5,
/* 0x40 */ GRUB_KEYBOARD_KEY_F6, GRUB_KEYBOARD_KEY_F7,
/* 0x42 */ GRUB_KEYBOARD_KEY_F8, GRUB_KEYBOARD_KEY_F9,
/* 0x44 */ GRUB_KEYBOARD_KEY_F10, GRUB_KEYBOARD_KEY_NUM_LOCK,
/* 0x46 */ GRUB_KEYBOARD_KEY_SCROLL_LOCK, GRUB_KEYBOARD_KEY_NUM7,
/* 0x48 */ GRUB_KEYBOARD_KEY_NUM8, GRUB_KEYBOARD_KEY_NUM9,
/* 0x4a */ GRUB_KEYBOARD_KEY_NUMMINUS, GRUB_KEYBOARD_KEY_NUM4,
/* 0x4c */ GRUB_KEYBOARD_KEY_NUM5, GRUB_KEYBOARD_KEY_NUM6,
/* 0x4e */ GRUB_KEYBOARD_KEY_NUMPLUS, GRUB_KEYBOARD_KEY_NUM1,
/* 0x50 */ GRUB_KEYBOARD_KEY_NUM2, GRUB_KEYBOARD_KEY_NUM3,
/* 0x52 */ GRUB_KEYBOARD_KEY_NUMDOT, GRUB_KEYBOARD_KEY_NUMDOT,
/* 0x54 */ 0, 0,
/* 0x56 */ GRUB_KEYBOARD_KEY_102ND, GRUB_KEYBOARD_KEY_F11,
/* 0x58 */ GRUB_KEYBOARD_KEY_F12, 0,
/* 0x5a */ 0, 0,
/* 0x5c */ 0, 0,
/* 0x5e */ 0, 0,
/* 0x60 */ 0, 0,
/* 0x62 */ 0, 0,
/* OLPC keys. Just mapped to normal keys. */
/* 0x64 */ 0, GRUB_KEYBOARD_KEY_UP,
/* 0x66 */ GRUB_KEYBOARD_KEY_DOWN, GRUB_KEYBOARD_KEY_LEFT,
/* 0x68 */ GRUB_KEYBOARD_KEY_RIGHT, 0,
/* 0x6a */ 0, 0,
/* 0x6c */ 0, 0,
/* 0x6e */ 0, 0,
/* 0x70 */ 0, 0,
/* 0x72 */ 0, GRUB_KEYBOARD_KEY_JP_RO,
/* 0x74 */ 0, 0,
/* 0x76 */ 0, 0,
/* 0x78 */ 0, 0,
/* 0x7a */ 0, 0,
/* 0x7c */ 0, GRUB_KEYBOARD_KEY_JP_YEN,
/* 0x7e */ GRUB_KEYBOARD_KEY_KPCOMMA
};
static const struct
{
grub_uint8_t from, to;
} set1_e0_mapping[] =
{
{0x1c, GRUB_KEYBOARD_KEY_NUMENTER},
{0x1d, GRUB_KEYBOARD_KEY_RIGHT_CTRL},
{0x35, GRUB_KEYBOARD_KEY_NUMSLASH },
{0x38, GRUB_KEYBOARD_KEY_RIGHT_ALT},
{0x47, GRUB_KEYBOARD_KEY_HOME},
{0x48, GRUB_KEYBOARD_KEY_UP},
{0x49, GRUB_KEYBOARD_KEY_PPAGE},
{0x4b, GRUB_KEYBOARD_KEY_LEFT},
{0x4d, GRUB_KEYBOARD_KEY_RIGHT},
{0x4f, GRUB_KEYBOARD_KEY_END},
{0x50, GRUB_KEYBOARD_KEY_DOWN},
{0x51, GRUB_KEYBOARD_KEY_NPAGE},
{0x52, GRUB_KEYBOARD_KEY_INSERT},
{0x53, GRUB_KEYBOARD_KEY_DELETE},
};
static const grub_uint8_t set2_mapping[256] =
{
/* 0x00 */ 0, GRUB_KEYBOARD_KEY_F9,
/* 0x02 */ 0, GRUB_KEYBOARD_KEY_F5,
/* 0x04 */ GRUB_KEYBOARD_KEY_F3, GRUB_KEYBOARD_KEY_F1,
/* 0x06 */ GRUB_KEYBOARD_KEY_F2, GRUB_KEYBOARD_KEY_F12,
/* 0x08 */ 0, GRUB_KEYBOARD_KEY_F10,
/* 0x0a */ GRUB_KEYBOARD_KEY_F8, GRUB_KEYBOARD_KEY_F6,
/* 0x0c */ GRUB_KEYBOARD_KEY_F4, GRUB_KEYBOARD_KEY_TAB,
/* 0x0e */ GRUB_KEYBOARD_KEY_RQUOTE, 0,
/* 0x10 */ 0, GRUB_KEYBOARD_KEY_LEFT_ALT,
/* 0x12 */ GRUB_KEYBOARD_KEY_LEFT_SHIFT, 0,
/* 0x14 */ GRUB_KEYBOARD_KEY_LEFT_CTRL, GRUB_KEYBOARD_KEY_Q,
/* 0x16 */ GRUB_KEYBOARD_KEY_1, 0,
/* 0x18 */ 0, 0,
/* 0x1a */ GRUB_KEYBOARD_KEY_Z, GRUB_KEYBOARD_KEY_S,
/* 0x1c */ GRUB_KEYBOARD_KEY_A, GRUB_KEYBOARD_KEY_W,
/* 0x1e */ GRUB_KEYBOARD_KEY_2, 0,
/* 0x20 */ 0, GRUB_KEYBOARD_KEY_C,
/* 0x22 */ GRUB_KEYBOARD_KEY_X, GRUB_KEYBOARD_KEY_D,
/* 0x24 */ GRUB_KEYBOARD_KEY_E, GRUB_KEYBOARD_KEY_4,
/* 0x26 */ GRUB_KEYBOARD_KEY_3, 0,
/* 0x28 */ 0, GRUB_KEYBOARD_KEY_SPACE,
/* 0x2a */ GRUB_KEYBOARD_KEY_V, GRUB_KEYBOARD_KEY_F,
/* 0x2c */ GRUB_KEYBOARD_KEY_T, GRUB_KEYBOARD_KEY_R,
/* 0x2e */ GRUB_KEYBOARD_KEY_5, 0,
/* 0x30 */ 0, GRUB_KEYBOARD_KEY_N,
/* 0x32 */ GRUB_KEYBOARD_KEY_B, GRUB_KEYBOARD_KEY_H,
/* 0x34 */ GRUB_KEYBOARD_KEY_G, GRUB_KEYBOARD_KEY_Y,
/* 0x36 */ GRUB_KEYBOARD_KEY_6, 0,
/* 0x38 */ 0, 0,
/* 0x3a */ GRUB_KEYBOARD_KEY_M, GRUB_KEYBOARD_KEY_J,
/* 0x3c */ GRUB_KEYBOARD_KEY_U, GRUB_KEYBOARD_KEY_7,
/* 0x3e */ GRUB_KEYBOARD_KEY_8, 0,
/* 0x40 */ 0, GRUB_KEYBOARD_KEY_COMMA,
/* 0x42 */ GRUB_KEYBOARD_KEY_K, GRUB_KEYBOARD_KEY_I,
/* 0x44 */ GRUB_KEYBOARD_KEY_O, GRUB_KEYBOARD_KEY_0,
/* 0x46 */ GRUB_KEYBOARD_KEY_9, 0,
/* 0x48 */ 0, GRUB_KEYBOARD_KEY_DOT,
/* 0x4a */ GRUB_KEYBOARD_KEY_SLASH, GRUB_KEYBOARD_KEY_L,
/* 0x4c */ GRUB_KEYBOARD_KEY_SEMICOLON, GRUB_KEYBOARD_KEY_P,
/* 0x4e */ GRUB_KEYBOARD_KEY_DASH, 0,
/* 0x50 */ 0, GRUB_KEYBOARD_KEY_JP_RO,
/* 0x52 */ GRUB_KEYBOARD_KEY_DQUOTE, 0,
/* 0x54 */ GRUB_KEYBOARD_KEY_LBRACKET, GRUB_KEYBOARD_KEY_EQUAL,
/* 0x56 */ 0, 0,
/* 0x58 */ GRUB_KEYBOARD_KEY_CAPS_LOCK, GRUB_KEYBOARD_KEY_RIGHT_SHIFT,
/* 0x5a */ GRUB_KEYBOARD_KEY_ENTER, GRUB_KEYBOARD_KEY_RBRACKET,
/* 0x5c */ 0, GRUB_KEYBOARD_KEY_BACKSLASH,
/* 0x5e */ 0, 0,
/* 0x60 */ 0, GRUB_KEYBOARD_KEY_102ND,
/* 0x62 */ 0, 0,
/* 0x64 */ 0, 0,
/* 0x66 */ GRUB_KEYBOARD_KEY_BACKSPACE, 0,
/* 0x68 */ 0, GRUB_KEYBOARD_KEY_NUM1,
/* 0x6a */ GRUB_KEYBOARD_KEY_JP_YEN, GRUB_KEYBOARD_KEY_NUM4,
/* 0x6c */ GRUB_KEYBOARD_KEY_NUM7, GRUB_KEYBOARD_KEY_KPCOMMA,
/* 0x6e */ 0, 0,
/* 0x70 */ GRUB_KEYBOARD_KEY_NUMDOT, GRUB_KEYBOARD_KEY_NUM0,
/* 0x72 */ GRUB_KEYBOARD_KEY_NUM2, GRUB_KEYBOARD_KEY_NUM5,
/* 0x74 */ GRUB_KEYBOARD_KEY_NUM6, GRUB_KEYBOARD_KEY_NUM8,
/* 0x76 */ GRUB_KEYBOARD_KEY_ESCAPE, GRUB_KEYBOARD_KEY_NUM_LOCK,
/* 0x78 */ GRUB_KEYBOARD_KEY_F11, GRUB_KEYBOARD_KEY_NUMPLUS,
/* 0x7a */ GRUB_KEYBOARD_KEY_NUM3, GRUB_KEYBOARD_KEY_NUMMINUS,
/* 0x7c */ GRUB_KEYBOARD_KEY_NUMMUL, GRUB_KEYBOARD_KEY_NUM9,
/* 0x7e */ GRUB_KEYBOARD_KEY_SCROLL_LOCK, 0,
/* 0x80 */ 0, 0,
/* 0x82 */ 0, GRUB_KEYBOARD_KEY_F7,
};
static const struct
{
grub_uint8_t from, to;
} set2_e0_mapping[] =
{
{0x11, GRUB_KEYBOARD_KEY_RIGHT_ALT},
{0x14, GRUB_KEYBOARD_KEY_RIGHT_CTRL},
{0x4a, GRUB_KEYBOARD_KEY_NUMSLASH},
{0x5a, GRUB_KEYBOARD_KEY_NUMENTER},
{0x69, GRUB_KEYBOARD_KEY_END},
{0x6b, GRUB_KEYBOARD_KEY_LEFT},
{0x6c, GRUB_KEYBOARD_KEY_HOME},
{0x70, GRUB_KEYBOARD_KEY_INSERT},
{0x71, GRUB_KEYBOARD_KEY_DELETE},
{0x72, GRUB_KEYBOARD_KEY_DOWN},
{0x74, GRUB_KEYBOARD_KEY_RIGHT},
{0x75, GRUB_KEYBOARD_KEY_UP},
{0x7a, GRUB_KEYBOARD_KEY_NPAGE},
{0x7d, GRUB_KEYBOARD_KEY_PPAGE},
};
static int
fetch_key (struct grub_ps2_state *ps2_state, grub_uint8_t at_key, int *is_break)
{
int was_ext = 0;
int ret = 0;
/* May happen if no keyboard is connected. Just ignore this. */
if (at_key == 0xff)
return -1;
if (at_key == 0xe0)
{
ps2_state->e0_received = 1;
return -1;
}
if ((ps2_state->current_set == 2 || ps2_state->current_set == 3) && at_key == 0xf0)
{
ps2_state->f0_received = 1;
return -1;
}
/* Setting LEDs may generate ACKs. */
if (at_key == GRUB_AT_ACK)
return -1;
was_ext = ps2_state->e0_received;
ps2_state->e0_received = 0;
switch (ps2_state->current_set)
{
case 1:
*is_break = !!(at_key & 0x80);
if (!was_ext)
ret = set1_mapping[at_key & 0x7f];
else
{
unsigned i;
for (i = 0; i < ARRAY_SIZE (set1_e0_mapping); i++)
if (set1_e0_mapping[i].from == (at_key & 0x7f))
{
ret = set1_e0_mapping[i].to;
break;
}
}
break;
case 2:
*is_break = ps2_state->f0_received;
ps2_state->f0_received = 0;
if (!was_ext)
ret = set2_mapping[at_key];
else
{
unsigned i;
for (i = 0; i < ARRAY_SIZE (set2_e0_mapping); i++)
if (set2_e0_mapping[i].from == at_key)
{
ret = set2_e0_mapping[i].to;
break;
}
}
break;
default:
return -1;
}
if (!ret)
{
if (was_ext)
grub_dprintf ("atkeyb", "Unknown key 0xe0+0x%02x from set %d\n",
at_key, ps2_state->current_set);
else
grub_dprintf ("atkeyb", "Unknown key 0x%02x from set %d\n",
at_key, ps2_state->current_set);
return -1;
}
return ret;
}
/* FIXME: This should become an interrupt service routine. For now
it's just used to catch events from control keys. */
static int
grub_keyboard_isr (struct grub_ps2_state *ps2_state,
grub_keyboard_key_t key, int is_break)
{
if (!is_break)
switch (key)
{
case GRUB_KEYBOARD_KEY_LEFT_SHIFT:
ps2_state->at_keyboard_status |= GRUB_TERM_STATUS_LSHIFT;
return 1;
case GRUB_KEYBOARD_KEY_RIGHT_SHIFT:
ps2_state->at_keyboard_status |= GRUB_TERM_STATUS_RSHIFT;
return 1;
case GRUB_KEYBOARD_KEY_LEFT_CTRL:
ps2_state->at_keyboard_status |= GRUB_TERM_STATUS_LCTRL;
return 1;
case GRUB_KEYBOARD_KEY_RIGHT_CTRL:
ps2_state->at_keyboard_status |= GRUB_TERM_STATUS_RCTRL;
return 1;
case GRUB_KEYBOARD_KEY_RIGHT_ALT:
ps2_state->at_keyboard_status |= GRUB_TERM_STATUS_RALT;
return 1;
case GRUB_KEYBOARD_KEY_LEFT_ALT:
ps2_state->at_keyboard_status |= GRUB_TERM_STATUS_LALT;
return 1;
default:
return 0;
}
else
switch (key)
{
case GRUB_KEYBOARD_KEY_LEFT_SHIFT:
ps2_state->at_keyboard_status &= ~GRUB_TERM_STATUS_LSHIFT;
return 1;
case GRUB_KEYBOARD_KEY_RIGHT_SHIFT:
ps2_state->at_keyboard_status &= ~GRUB_TERM_STATUS_RSHIFT;
return 1;
case GRUB_KEYBOARD_KEY_LEFT_CTRL:
ps2_state->at_keyboard_status &= ~GRUB_TERM_STATUS_LCTRL;
return 1;
case GRUB_KEYBOARD_KEY_RIGHT_CTRL:
ps2_state->at_keyboard_status &= ~GRUB_TERM_STATUS_RCTRL;
return 1;
case GRUB_KEYBOARD_KEY_RIGHT_ALT:
ps2_state->at_keyboard_status &= ~GRUB_TERM_STATUS_RALT;
return 1;
case GRUB_KEYBOARD_KEY_LEFT_ALT:
ps2_state->at_keyboard_status &= ~GRUB_TERM_STATUS_LALT;
return 1;
default:
return 0;
}
}
/* If there is a key pending, return it; otherwise return GRUB_TERM_NO_KEY. */
int
grub_ps2_process_incoming_byte (struct grub_ps2_state *ps2_state,
grub_uint8_t at_key)
{
int code;
int is_break = 0;
code = fetch_key (ps2_state, at_key, &is_break);
if (code == -1)
return GRUB_TERM_NO_KEY;
if (grub_keyboard_isr (ps2_state, code, is_break))
return GRUB_TERM_NO_KEY;
if (is_break)
return GRUB_TERM_NO_KEY;
#ifdef DEBUG_AT_KEYBOARD
grub_dprintf ("atkeyb", "Detected key 0x%x\n", code);
#endif
switch (code)
{
case GRUB_KEYBOARD_KEY_CAPS_LOCK:
ps2_state->at_keyboard_status ^= GRUB_TERM_STATUS_CAPS;
ps2_state->led_status ^= KEYBOARD_LED_CAPS;
#ifdef DEBUG_AT_KEYBOARD
grub_dprintf ("atkeyb", "caps_lock = %d\n", !!(ps2_state->at_keyboard_status & GRUB_KEYBOARD_STATUS_CAPS_LOCK));
#endif
return GRUB_TERM_NO_KEY;
case GRUB_KEYBOARD_KEY_NUM_LOCK:
ps2_state->at_keyboard_status ^= GRUB_TERM_STATUS_NUM;
ps2_state->led_status ^= KEYBOARD_LED_NUM;
#ifdef DEBUG_AT_KEYBOARD
grub_dprintf ("atkeyb", "num_lock = %d\n", !!(ps2_state->at_keyboard_status & GRUB_KEYBOARD_STATUS_NUM_LOCK));
#endif
return GRUB_TERM_NO_KEY;
case GRUB_KEYBOARD_KEY_SCROLL_LOCK:
ps2_state->at_keyboard_status ^= GRUB_TERM_STATUS_SCROLL;
ps2_state->led_status ^= KEYBOARD_LED_SCROLL;
return GRUB_TERM_NO_KEY;
default:
return grub_term_map_key (code, ps2_state->at_keyboard_status);
}
}

View File

@@ -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>

View File

@@ -25,7 +25,7 @@
#include <grub/mm.h>
#include <grub/video.h>
#include <grub/video_fb.h>
#include <grub/machine/lbio.h>
#include <grub/coreboot/lbio.h>
#include <grub/machine/console.h>
struct grub_linuxbios_table_framebuffer *grub_video_coreboot_fbtable;

View File

@@ -242,6 +242,6 @@ enum
};
struct grub_acpi_fadt *
grub_acpi_find_fadt (void);
EXPORT_FUNC(grub_acpi_find_fadt) (void);
#endif /* ! GRUB_ACPI_HEADER */

View File

@@ -0,0 +1,29 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2009 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef GRUB_MACHINE_CONSOLE_HEADER
#define GRUB_MACHINE_CONSOLE_HEADER 1
void grub_video_coreboot_fb_init (void);
void grub_video_coreboot_fb_early_init (void);
void grub_video_coreboot_fb_late_init (void);
void grub_video_coreboot_fb_fini (void);
extern struct grub_linuxbios_table_framebuffer *grub_video_coreboot_fbtable;
#endif /* ! GRUB_MACHINE_CONSOLE_HEADER */

View File

@@ -0,0 +1,44 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2013 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef GRUB_KERNEL_MACHINE_HEADER
#define GRUB_KERNEL_MACHINE_HEADER 1
#ifndef ASM_FILE
#include <grub/symbol.h>
#include <grub/types.h>
struct grub_fdt_board
{
const char *vendor, *part;
const grub_uint8_t *dtb;
grub_size_t dtb_size;
};
extern struct grub_fdt_board grub_fdt_boards[];
void grub_machine_timer_init (void);
void grub_pl050_init (void);
void
grub_cros_init (void);
extern grub_addr_t EXPORT_VAR (start_of_ram);
#endif /* ! ASM_FILE */
#define GRUB_KERNEL_MACHINE_STACK_SIZE GRUB_KERNEL_ARM_STACK_SIZE
#endif /* ! GRUB_KERNEL_MACHINE_HEADER */

Some files were not shown because too many files have changed in this diff Show More