Compare commits

..

164 Commits

Author SHA1 Message Date
Vladimir Serbinenko
21e3cd33b6 Merge branch 'master' into next 2017-05-03 12:00:26 +02:00
Vladimir Serbinenko
db77aa5ad6 Merge branch 'next' of git.sv.gnu.org:/srv/git/grub into next 2017-05-03 11:56:59 +02:00
Vladimir Serbinenko
b0bad6fd94 Bump version to 2.03 2017-05-03 11:55:52 +02:00
Vladimir Serbinenko
e54c99aaff Increase version to 2.02. 2017-04-25 16:23:16 +02:00
Vladimir Serbinenko
d454509bb8 Fix remaining cases of gcc 7 fallthrough warning.
They are all intended, so just add the relevant comment.
2017-04-12 01:42:38 +00:00
Andrei Borzenkov
007f0b407f Add gnulib-fix-gcc7-fallthrough.diff
As long as the code is not upstream, add it as explicit patch for the
case of gnulib refresh.
2017-04-04 19:37:47 +03:00
Andrei Borzenkov
4bd4a88725 i386, x86_64, ppc: fix switch fallthrough cases with GCC7
In util/getroot and efidisk slightly modify exitsing comment to mostly
retain it but still make GCC7 compliant with respect to fall through
annotation.

In grub-core/lib/xzembed/xz_dec_lzma2.c it adds same comments as
upstream.

In grub-core/tests/setjmp_tets.c declare functions as "noreturn" to
suppress GCC7 warning.

In grub-core/gnulib/regexec.c use new __attribute__, because existing
annotation is not recognized by GCC7 parser (which requires that comment
immediately precedes case statement).

Otherwise add FALLTHROUGH comment.

Closes: 50598
2017-04-04 19:23:55 +03:00
Andrei Borzenkov
6cef7f6079 btrfs: avoid "used uninitialized" error with GCC7
sblock was local and so considered new variable on every loop
iteration.

Closes: 50597
2017-04-04 19:22:32 +03:00
Andrei Borzenkov
ec4af117c6 acpi: add missing efi_call wrapper to acpi command
Fixed loading of ACPI tables on EFI (side effect was apparent memory
corruption ranging from unpredictable behavior to system reset).

Reported by Nando Eva <nando4eva@ymail.com>
2017-04-02 14:47:20 +03:00
Vladimir Serbinenko
8014b7b337 Increment version to GRUB 2.02~rc2. 2017-03-15 09:20:29 +01:00
Vladimir Serbinenko
fcea891e17 Use core2duo for bootcheck test on 64-bit EFI.
Obviously pentium2 can't run efi64.
2017-03-15 09:20:14 +01:00
Andrei Borzenkov
c42cb97f08 efi: skip iPXE block device.
iPXE adds Simple File System Protocol to loaded image handle, as side
effect it also adds Block IO protocol (according to comments, to work
around some bugs in EDK2). GRUB assumes that every device with Block IO
is disk and skips network initialization entirely. But iPXE Block IO
implementation is just a stub which always fails for every operation
so cannot be used. Attempt to detect and skip such devices.

We are using media ID which iPXE sets to "iPXE" and block IO size in
hope that no real device would announce 1B block ...

Closes: 50518
2017-03-14 04:14:36 +00:00
phcoder
bcf3c55531 xen: Fix wrong register in relocator.
This fixes chainloading of some GRUB variants.
2017-03-05 10:07:36 +01:00
Vladimir Serbinenko
fb93c75bdd video_fb: Fix blue collor if using unoptimized blitter.
when unmapping the color what matters is the mode of source, not target.
2017-02-27 01:58:50 +00:00
Vladimir Serbinenko
641bb15fa4 legacy_initrd: Strip any additional arguments to initrd. 2017-02-27 00:43:54 +00:00
Andrei Borzenkov
f34ed1f53c grub-fs-tester: improve squash4 tests
1. Make sure files are not multiple of block size. This will ensure tail packing
for squash4 and may also trigger more codes paths in other filesystems.

2. Call mksquashfs with -always-use-fragments to force tail packing.
2017-02-26 14:38:04 +03:00
Andrei Borzenkov
892dfbe113 efi: strip off final NULL from File Path in grub_efi_get_filename
UEFI 2.6 9.3.6.4 File Path Media Device Path says that Path Name is
"A NULL-terminated Path string including directory and file names".

Strip final NULL from Path Name in each File Path node when constructing
full path. To be on safe side, strip all of them.

Fixes failure chainloading grub from grub, when loaded grub truncates
image path and does not find its grub.cfg.

https://bugzilla.opensuse.org/show_bug.cgi?id=1026344

This was triggered by commit ce95549cc54b5d6f494608a7c390dba3aab4fba7;
before it we built Path Name without trailing NULL, and apparently all
other bootloaders use single File Path node, thus not exposing this bug.
2017-02-25 08:39:38 +03:00
Andrei Borzenkov
951306c509 squash4: fix handling of fragments and sparse files
1. Do not assume block list and fragment are mutually exclusive. Squash
can pack file tail as fragment (unless -no-fragments is specified); so
check read offset and read either from block list or from fragments as
appropriate.

2. Support sparse files with zero blocks.

3. Fix fragment read - frag.offset is absolute fragment position,
not offset relative to ino.chunk.

Reported and tested by Carlo Caione <carlo@endlessm.com>
2017-02-24 19:10:43 +03:00
Vladimir Serbinenko
512bb31cbc Whitelist sparc64-ieee1275 as having no video modules.
ieee1275_fb is not built on sparc64 due to virtual address issues.
2017-02-22 09:55:51 +01:00
Andrei Borzenkov
2fb8cd26a9 script: fix double free in lexer
yylex_destroy() already frees scanner.

Found by: Coverity scan.
CID: 176636
2017-02-12 09:23:34 +03:00
Vladimir Serbinenko
529818738f xen: Fix parsing of XZ kernel.
In case of xz, the uncompressed size is appended to xz data which confuses
our xz decompressor. Trim it.
2017-02-07 13:25:38 +01:00
Vladimir Serbinenko
8a96fc4093 xen: Fix handling of GRUB chainloading.
In case of GRUB we put remapper after domain pages and not at 0x0.
In this case we use max_addr to put remapper. Unfortunately we increment
max_addr as well in this case resulting in virt mapping mapping page
at old max_addr and trying to boot using new max_addr.

Closes 46014.
2017-02-07 00:42:43 +01:00
Vladimir Serbinenko
f3df8f961f linguas: Don't skip ko.po.
Translation project doesn't require copyright disclaimers. They're independant
from us. They're responsible for their copyright story.
2017-02-04 00:06:57 +01:00
Vladimir Serbinenko
ec4aca088a Fix truncated checksum.h. 2017-02-03 20:17:48 +01:00
Vladimir Serbinenko
fcb1528d93 Regenerate checksums.h
Screenshots contain version, so we need new checksums.
2017-02-03 13:44:56 +01:00
Vladimir Serbinenko
c36c0e05f1 Release 2.02-rc1. 2017-02-03 13:01:34 +01:00
Vladimir Serbinenko
c96cfac167 Fix mingw compilation. 2017-02-03 13:01:34 +01:00
Daniel Kahn Gillmor
bf94ef7fbd documentation: Clarify documentation for special environment variable "default".
The current documentation for the special environment variable
"default" is confusing and unclear.  This patch attempts to clean it
up.

In particular, the current documentation refers to the "number or
title", but then in the example it gives, the menu entries and
submenus all have numbers *in* their title; furthermore, there is no
example given about how to choose the number, or any indication about
whether counting is zero-indexed or 1-indexed.

Having a cleaner example and presenting all variants (numeric, title,
and id) should make it clearer to the user.

Signed-off-by: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
2017-02-03 12:32:25 +01:00
Vladimir Serbinenko
5412028d19 Avoid causing kernel oops in nilfs2 test.
1024-byte and 2048-byte blocks don't really work with some kernels, skip
them as we don't want any oops'es.
2017-02-03 00:34:07 +01:00
Vladimir Serbinenko
c65d35b08b btrfs: Shorten label by one character.
mkfs.btrfs imposes a slightly lower limit than would be possible in btrfs.
2017-02-03 00:30:29 +01:00
Vladimir Serbinenko
a5bd52990e grub-fs-tester: Fix mkudffs invocation.
With current invocation order of arguments is wrong and path is hardcoded.
2017-02-02 23:32:38 +01:00
Vladimir Serbinenko
1d4e3db907 grub-fs-tester: Fix fat test.
mkfs.vfat ignores -S when invoked on a disk, including loopback device,
so do an mkfs on underlying image.
2017-02-02 23:19:00 +01:00
Daniel Kiper
4e5414b2a1 i386/relocator: Align stack in grub_relocator64_efi relocator
Unified Extensible Firmware Interface Specification, Version 2.6,
section 2.3.4, x64 Platforms, boot services, says among others:
The stack must be 16-byte aligned. So, do it. Otherwise OS may
boot only by chance as it happens right now.

Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
2017-02-02 22:24:47 +01:00
Vladimir Serbinenko
1402cdd96a i386-ieee1275: Add missing bootcheck target. 2017-02-02 21:41:33 +01:00
Vladimir Serbinenko
31932a267c bootcheck-linux-i386: Use -cpu pentium2.
Most modern kernels are compiled for i686, so use -cpu pentium2
to avoid spurious failures.
2017-02-02 21:41:18 +01:00
Vladimir Serbinenko
393cc59195 Use -fPIC with arm64 with clang.
Currently it doesn't work either way but with -fPIC it should work once
clang bug is fixed.
2017-02-02 01:24:11 +01:00
Vladimir Serbinenko
dac87d6032 INSTALL: Fix mention of thumb-clang. 2017-02-02 01:11:52 +01:00
Vladimir Serbinenko
42e24b6006 Fix thumb compilation with clang.
According to EABI only STT_FUNC has convention of lowest bit indicating
execution mode. R_THM_{JUMP,CALL}* relocations are assumed to be pointing
to thumb mode unless they use STT_FUNC.
2017-02-02 00:59:49 +01:00
Vladimir Serbinenko
08438d783f Add missing strtoull_test.c
It was forgotten in my local directory.
2017-02-01 21:50:17 +01:00
Vladimir Serbinenko
34fe0b5901 arm64: Add support for GOT and PCREL32 relocations. 2017-02-01 21:46:19 +01:00
Vladimir Serbinenko
377c121170 mkimage: Fix memory leak. 2017-02-01 21:21:17 +01:00
Vladimir Serbinenko
43b444e593 arm/arm64: Fix improper use of start address.
It was used instead of loading address of current section or of entire buffer.
2017-02-01 20:12:07 +01:00
Vladimir Serbinenko
ea20dd2b22 ia64: Fix iterator for relocation entries.
Don't assume relocation entry size and use sh_entsize properly.
2017-02-01 20:10:26 +01:00
Vladimir Serbinenko
3d173955f0 arm: Fix trampoline generation.
We used the wrong pointer in this case. It worked only by accident.
2017-02-01 15:58:36 +01:00
Vladimir Serbinenko
68c6cec061 Fix bootcheck-related files compilation.
We need -static as otherwise linker will set interpreter field and ld.so
is not available on our initrd's.
Strip all sections we don't need on binary tests.
2017-02-01 15:57:08 +01:00
Vladimir Serbinenko
0704e83a1b Regenerate checksum.h.
Screenshots checked.
Using unifont from http://ftp.us.debian.org/debian/pool/main/u/unifont/xfonts-unifont_7.0.06-1_all.deb.
2017-01-31 22:36:11 +01:00
Vladimir Serbinenko
f14c77f501 grub-mkfont: Remove leftover debug statement. 2017-01-31 22:32:21 +01:00
Vladimir Serbinenko
0fd9fa565b charset: Trim away RLM and LRM.
They are not visible but would otherwise end up as [LRM] or [RLM] squares
with some fonts.
2017-01-31 19:29:31 +01:00
Vladimir Serbinenko
6f5aa28bc2 gfxterm: Fix clearing of cursor.
If ascent is bigger than height - 2, then we draw over character box but then
to clear cursor we only draw over character box. So trim ascent if necessarry.
2017-01-31 18:49:37 +01:00
Vladimir Serbinenko
a134ef1ab9 ia64: Add support for R_IA64_GPREL64I.
Recent GCC generates those relocations, so we need to support them.
2017-01-31 12:39:01 +01:00
Vladimir Serbinenko
255b9e0bea grub-module-verifier: Add mips to all_video whitelist.
On MIPS video is compiled-in. So all_video is empty. Whitelist it.
2017-01-30 19:52:58 +01:00
Vladimir Serbinenko
b53f595b3e Fix -nopie/-nopie check.
We don't use lgcc_s but missing lgcc_s or another library cause test to fail.
So use -nostdlib.
We need to use -Werror to avoid warning-generated case to be accepted.
Clang uses -nopie rather than -no-pie. Check both and use whichever one works.
Additionally android clang passes -pie to the linker even though it doesn't
define __PIE__. So if compilation without no-pie logic fails add -nopie/-no-pie
even if __PIE__ is not defined.
2017-01-30 19:38:55 +01:00
Vladimir Serbinenko
4078fb64c9 Merge branch 'phcoder/termux' of git.sv.gnu.org:/srv/git/grub into next 2017-01-30 14:42:03 +01:00
Vladimir Serbinenko
e1f9050f1a Fix -nopie/-nopie check.
We don't use lgcc_s but missing lgcc_s or another library cause test to fail.
So use -nostdlib.
Clang uses -nopie rather than -no-pie. Check both and use whichever one works.
2017-01-30 14:38:50 +01:00
Vladimir Serbinenko
6371e9c104 grub-module-verifier: Ignore all_video emptiness on xen.
It's intentional that it's empty when no video modules
are available.
2017-01-30 00:13:41 +00:00
Vladimir Serbinenko
d15f17b2a0 Support arm clang 3.8 amd later.
clang 3.8 and later doesn't support -mllvm -use-arm-movt=0
whereas older clang doesn't know -mno-movt. So use
-mno-movt whenever possible and fallback to mllvm variant.
2017-01-28 14:41:23 +00:00
Carlo Caione
a0413e2677 exfat: Support files over 4GiB
file size in grub_fat_data was 32-bit on exfat.
2017-01-27 22:10:21 +00:00
Vladimir Serbinenko
0cb0bdef15 WIP: Disable hardlink test.
It doesn't wotk on termux.
2017-01-27 20:12:03 +00:00
Vladimir Serbinenko
ba8f448172 WIP: disable m4_syscmd check in gnulib.
m4_syscmd uses /bin/sh which isn't available on termux.
2017-01-27 20:12:03 +00:00
Vladimir Serbinenko
6eadd976ea Don't retrieve fstime when it's not useful. 2017-01-27 20:12:02 +00:00
Vladimir Serbinenko
36a4c40abf debashify fixup 2017-01-27 20:12:01 +00:00
Vladimir Serbinenko
55d849f1f7 Support lseek64.
Android doesn't have 64-bit off_t, so use off64_t instead.
2017-01-27 20:12:00 +00:00
Vladimir Serbinenko
f0cdef6ef5 Discover partial linking arguments dynamically.
clang for android doesn't work with -Wl,-r,-d without -static.
2017-01-27 20:12:00 +00:00
Vladimir Serbinenko
69743d7d1b po: Use @SHELL@ rather than /bin/sh.
/bin/sh might not exist.
2017-01-27 20:11:59 +00:00
Vladimir Serbinenko
39bb4f34be Add termux pathto dict. 2017-01-27 20:11:58 +00:00
Vladimir Serbinenko
ea1aab3f2e fs-tester: make sh-compatible 2017-01-27 20:11:57 +00:00
Vladimir Serbinenko
0460bb1e46 support busybox date.
Busybox date doesn't understand weekdays in -d input,
so strip them beforehand.
2017-01-27 20:11:57 +00:00
Vladimir Serbinenko
470511748d Remove bashisms from tests.
Those tests don't actually need bash. Just use common shebang.
2017-01-27 20:11:56 +00:00
Vladimir Serbinenko
eadbf47358 Use $(SHELL) rather than /bin/sh.
/bin/sh doesn't exist under termux.
2017-01-27 20:11:55 +00:00
Vladimir Serbinenko
3568b5bf80 Fix shebang for termux.
Termux doesn't have a /bin/sh. So we needto use $SHELL.
Keep /bin/sh as much as possible.
2017-01-27 20:11:54 +00:00
Vladimir Serbinenko
43dbf83aa2 Ensure that grub_reboot doesn't return on emu.
Use grub_fatal if longjmp fails.

grub_reboot is marked as noreturn so return would cause
a crash.
2017-01-27 20:10:23 +00:00
Vladimir Serbinenko
bec592aa87 grub-shell: skip font copying when no font is available. 2017-01-27 20:09:06 +00:00
Vladimir Serbinenko
79fc008935 Don't use -mlong-calls on arm.
We don't really need it and it's flaky and creates
bogus symbols with clang.
2017-01-27 18:48:25 +00:00
Vladimir Serbinenko
bf9c561670 configure: Disable movw/movt with clang.
Those relocations are not compatible with PE and also
not compatible with custom uboot relocator.
Disable them.
2017-01-27 18:48:23 +00:00
Vladimir Serbinenko
afa9dda37e grub-fs-tester: Delete directory once we're done. 2017-01-27 18:00:40 +00:00
Vladimir Serbinenko
cde63a3bb0 grub-fs-tester: Accomodate for slower systems.
fstime can be more different with xz squashfs.
Allow difference up to 3 seconds.
This code is ugly now but rewriting it now is not on the
table.
2017-01-27 17:58:15 +00:00
Vladimir Serbinenko
bf0e59cebf grub-fs-tester: Accomodate for testing in proot containers.
proot creates hidden files with .proot prefix and name
derived from real file name. So decrease file name length
and path depth. For some reason depth 85 also results in
undeleteable directory, so use 84 instead of 85.
2017-01-27 17:46:47 +00:00
Andrei Borzenkov
a2932fbe8a osdep/linux: handle autofs entries in /proc/self/mountinfo
These entries have placeholder for device name and so are useless for our
purpose. grub failed with something like

grub-install: error: failed to get canonical path of `systemd-1'.

When we see autofs entry, record it (to keep parent-child relationship) but
continue to look for real mount. If it is found, we process it as usual. If
only autofs entry exists, attempt to trigger mount by opening mount point
and retry. Mount point itself is then kept open to avoid timeout.

Recent systemd is by default using automount for /boot/efi so this should
become more popular problem on EFI systems.

Closes: 49942
2017-01-24 20:05:19 +03:00
Andrei Borzenkov
972765fe82 linux: fix "vga=XX deprecated" warning for text mode
Arguments were in reverse order which resulted in

text is deprecated. Use set gfxpayload=vga=0 before linux command instead.
2017-01-08 15:52:49 +03:00
Andrei Borzenkov
07662af7ae configure: fix check for sys/sysmacros.h under glibc 2.25+
glibc 2.25 still includes sys/sysmacros.h in sys/types.h but also emits
deprecation warning. So test for sys/types.h succeeds in configure but later
compilation fails because we use -Werror by default.

While this is fixed in current autoconf GIT, we really cannot force everyone
to use bleeding edge (that is not even released right now). So run test under
-Werror as well to force proper detection.

This should have no impact on autoconf 2.70+ as AC_HEADER_MAJOR in this version
simply checks for header existence.

Reported and tested by Khem Raj <raj.khem@gmail.com>
2016-12-22 22:48:25 +03:00
Michael Chang
562c406763 Fix fwpath in efi netboot
The path returned by grub_efi_net_config has already been stripped for the
directory part extracted from cached bootp packet. We should just return the
result to avoild it be stripped again.

It fixed the problem that grub.efi as NBP image always looking for grub.cfg and
platform directory in upper folder rather than current one it gets loaded while
$prefix is empty. The behavior is inconsistent with other architecture and how
we would expect empty $prefix going to be in general.

The only exception to the general rule of empty $prefix is that when loaded
from platform directory itself, the platform part is stripped thus upper folder
is used for looking up files. It meets the case for how grub-mknetdir lay out
the files under tftp root directory, but also hide away this issue to be
identified as it appears to be just works.

Also fix possible memory leak by moving grub_efi_get_filename() call after
grub_efi_net_config().
2016-12-22 22:37:32 +03:00
Andrei Borzenkov
ce95549cc5 efi: properly terminate filepath with NULL in chainloader
EFI File Path Media Device Path is defined as NULL terminated string;
but chainloader built file paths without final NULL. This caused error
with Secure Boot and Linux Foundation PreLoader on Acer with InsydeH20 BIOS.
Apparently firmware failed verification with EFI_INVALID_PARAMETER which is
considered fatal error by PreLoader.

Reported and tested by Giovanni Santini <itachi.sama.amaterasu@gmail.com>
2016-12-15 16:07:00 +03:00
Magnus Granberg
a3e9da054d configure: add check for -no-pie if the compiler default to -fPIE
When Grub is compile with gcc 6.1 that have --enable-defult-pie set.
It fail with.
-ffreestanding   -m32 -Wl,-melf_i386 -Wl,--build-id=none  -nostdlib -Wl,-N -Wl,-r,-d   -
o trig.module  trig_module-trigtables.o
grep 'MARKER' gcry_whirlpool.marker.new > gcry_whirlpool.marker; rm -f
gcry_whirlpool.marker.new
/usr/lib/gcc/x86_64-pc-linux-gnu/6.1.0/../../../../x86_64-pc-linux-gnu/bin/ld: -r and -
shared may not be used together
collect2: error: ld returned 1 exit status
Makefile:26993: recipe for target 'trig.module' failed

Check that compiler supports -no-pie and add it to linker flags.
2016-12-14 20:44:41 +03:00
Stanislav Kholmanskikh
130234bc78 ofnet: implement the receive buffer
get_card_packet() from ofnet.c allocates a netbuff based on the device's MTU:

 nb = grub_netbuff_alloc (dev->mtu + 64 + 2);

In the case when the MTU is large, and the received packet is
relatively small, this leads to allocation of significantly more memory,
than it's required. An example could be transmission of TFTP packets
with 0x400 blksize via a network card with 0x10000 MTU.

This patch implements a per-card receive buffer in a way similar to efinet.c,
and makes get_card_packet() allocate a netbuff of the received data size.

Signed-off-by: Stanislav Kholmanskikh <stanislav.kholmanskikh@oracle.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2016-12-14 14:13:34 +01:00
Stanislav Kholmanskikh
7b4c54c4ad ofnet: move the allocation of the transmit buffer into a function
In the current code search_net_devices() uses the "alloc-mem" command
from the IEEE1275 User Interface for allocation of the transmit buffer
for the case when GRUB_IEEE1275_FLAG_VIRT_TO_REAL_BROKEN is set.

I don't have hardware where this flag is set to verify if this
workaround is still needed. However, further changes to ofnet will
require to execute this workaround one more time. Therefore, to
avoid possible duplication of code I'm moving this piece of
code into a function.

Signed-off-by: Stanislav Kholmanskikh <stanislav.kholmanskikh@oracle.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2016-12-14 14:13:34 +01:00
Alexander Graf
0d2345774d efi: Move fdt helper into own file
We only support FDT files with EFI on arm and arm64 systems, not
on x86. So move the helper that finds a prepopulated FDT UUID
into its own file and only build it for architectures where it
also gets called.

Signed-off-by: Alexander Graf <agraf@suse.de>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2016-11-24 10:09:24 +01:00
Andrei Borzenkov
c9a8d037a8 NEWS updates 2016-11-22 20:51:54 +03:00
Andrei Borzenkov
f8c3af3b61 bootp: export next server IP as environment variable
Network boot autoconfiguration sets default server to next server IP
(siaddr) from BOOTP/DHCP reply, but manual configuration using net_bootp
exports only server name. Unfortunately semantic of server name is not
clearly defined. BOOTP RFC 951 defines it only for client request, and
DHCP RFC 1541 only mentions it, without any implied usage. It looks like
this field is mostly empty in server replies.

Export next server IP as net_<interface>_next_server variable. This allows
grub configuration script to set $root/$prefix based on information obtained
by net_bootp.

Reported and tested by: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>
Cc: nikunj@linux.vnet.ibm.com

v2: change variable name to net_<interface>_next_server as discussed on the list
2016-11-22 20:43:04 +03:00
Aaro Koskinen
0af7539bd2 configure.ac: don't require build time grub-mkfont on powerpc-ieee1275
Don't require build time grub-mkfont on powerpc-ieee1275.

Signed-off-by: Aaro Koskinen <aaro.koskinen@iki.fi>
2016-11-22 20:41:34 +03:00
Dirk Mueller
0d663b50b9 grub-mknetdir: Add support for ARM64 EFI 2016-11-14 19:27:13 +03:00
Joonas Lahtinen
28511b0da9 .gitignore: Add grub-core/build-grub-module-verifier
Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
2016-11-12 12:07:31 +03:00
Alexander Graf
e1b099fb69 arm efi: Use fdt from firmware when available
If EFI is nice enough to pass us an FDT using configuration tables on 32bit
ARM, we should really try and make use of it.

Signed-off-by: Alexander Graf <agraf@suse.de>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2016-11-10 13:21:00 +01:00
Alexander Graf
fbca374105 arm64: Move firmware fdt search into global function
Searching for a device tree that EFI passes to us via configuration tables
is nothing architecture specific. Move it into generic code.

Signed-off-by: Alexander Graf <agraf@suse.de>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2016-11-10 13:20:56 +01:00
Corey Hickey
5f311e86d2 fix detection of non-LUKS CRYPT
grub_util_get_dm_abstraction() does a string comparison of insufficient
length. When using a UUID such as "CRYPT-PLAIN-sda6_crypt", the function
returns GRUB_DEV_ABSTRACTION_LUKS.

This results in the error:
    ./grub-probe: error: disk `cryptouuid/sda6_crypt' not found.

This appears to be a copy/paste error introduced in:
a10e7a5a89

The bug was (apparently) latent until revealed by:
3bca85b418

Signed-off-by: Corey Hickey <bugfood-c@fatooh.org>
2016-11-05 15:28:50 +03:00
Juergen Gross
0de3eeb623 xen: add capability to load p2m list outside of kernel mapping
Modern pvops linux kernels support a p2m list not covered by the
kernel mapping. This capability is flagged by an elf-note specifying
the virtual address the kernel is expecting the p2m list to be mapped
to.

In case the elf-note is set by the kernel don't place the p2m list
into the kernel mapping, but map it to the given address. This will
allow to support domains with larger memory, as the kernel mapping is
limited to 2GB and a domain with huge memory in the TB range will have
a p2m list larger than this.

Signed-off-by: Juergen Gross <jgross@suse.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2016-10-27 16:22:06 +02:00
Juergen Gross
b67a95ecad xen: modify page table construction
Modify the page table construction to allow multiple virtual regions
to be mapped. This is done as preparation for removing the p2m list
from the initial kernel mapping in order to support huge pv domains.

This allows a cleaner approach for mapping the relocator page by
using this capability.

The interface to the assembler level of the relocator has to be changed
in order to be able to process multiple page table areas.

Signed-off-by: Juergen Gross <jgross@suse.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2016-10-27 16:22:06 +02:00
Juergen Gross
5500cefccd xen: add capability to load initrd outside of initial mapping
Modern pvops linux kernels support an initrd not covered by the initial
mapping. This capability is flagged by an elf-note.

In case the elf-note is set by the kernel don't place the initrd into
the initial mapping. This will allow to load larger initrds and/or
support domains with larger memory, as the initial mapping is limited
to 2GB and it is containing the p2m list.

Signed-off-by: Juergen Gross <jgross@suse.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2016-10-27 16:22:06 +02:00
Juergen Gross
d73976fdff xen: factor out allocation of page tables into separate function
Do the allocation of page tables in a separate function. This will
allow to do the allocation at different times of the boot preparations
depending on the features the kernel is supporting.

Signed-off-by: Juergen Gross <jgross@suse.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2016-10-27 16:22:06 +02:00
Juergen Gross
1fbb2b4b39 xen: factor out allocation of special pages into separate function
Do the allocation of special pages (start info, console and xenbus
ring buffers) in a separate function. This will allow to do the
allocation at different times of the boot preparations depending on
the features the kernel is supporting.

Signed-off-by: Juergen Gross <jgross@suse.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2016-10-27 16:22:06 +02:00
Juergen Gross
c221ea06b5 xen: factor out p2m list allocation into separate function
Do the p2m list allocation of the to be loaded kernel in a separate
function. This will allow doing the p2m list allocation at different
times of the boot preparations depending on the features the kernel
is supporting.

While at this remove superfluous setting of first_p2m_pfn and
nr_p2m_frames as those are needed only in case of the p2m list not
being mapped by the initial kernel mapping.

Signed-off-by: Juergen Gross <jgross@suse.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2016-10-27 16:22:06 +02:00
Juergen Gross
72c28509fa xen: synchronize xen header
Get actual version of include/xen/xen.h from the Xen repository in
order to be able to use constants defined there.

Signed-off-by: Juergen Gross <jgross@suse.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2016-10-27 16:22:06 +02:00
Juergen Gross
7e5fcb0b34 xen: add elfnote.h to avoid using numbers instead of constants
Various features and parameters of a pv-kernel are specified via
elf notes in the kernel image. Those notes are part of the interface
between the Xen hypervisor and the kernel.

Instead of using num,bers in the code when interpreting the elf notes
make use of the header supplied by Xen for that purpose.

Signed-off-by: Juergen Gross <jgross@suse.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2016-10-27 16:21:25 +02:00
Juergen Gross
6ae55ce103 xen: reduce number of global variables in xen loader
The loader for xen paravirtualized environment is using lots of global
variables. Reduce the number by making them either local or by putting
them into a single state structure.

Signed-off-by: Juergen Gross <jgross@suse.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2016-10-27 16:17:15 +02:00
Juergen Gross
c69d1858f1 xen: avoid memleaks on error
When loading a Xen pv-kernel avoid memory leaks in case of errors.

Signed-off-by: Juergen Gross <jgross@suse.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2016-10-27 16:17:15 +02:00
Juergen Gross
4231927e44 xen: make xen loader callable multiple times
The loader for xen paravirtualized environment isn't callable multiple
times as it won't free any memory in case of failure.

Call grub_relocator_unload() as other modules do it before allocating
a new relocator or when unloading the module.

Signed-off-by: Juergen Gross <jgross@suse.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
2016-10-27 16:16:54 +02:00
Daniel Kiper
a620876e3b multiboot2: Add support for relocatable images
Currently multiboot2 protocol loads image exactly at address specified in
ELF or multiboot2 header. This solution works quite well on legacy BIOS
platforms. It is possible because memory regions are placed at predictable
addresses (though I was not able to find any spec which says that it is
strong requirement, so, it looks that it is just a goodwill of hardware
designers). However, EFI platforms are more volatile. Even if required
memory regions live at specific addresses then they are sometimes simply
not free (e.g. used by boot/runtime services on Dell PowerEdge R820 and
OVMF). This means that you are not able to just set up final image
destination on build time. You have to provide method to relocate image
contents to real load address which is usually different than load address
specified in ELF and multiboot2 headers.

This patch provides all needed machinery to do self relocation in image code.
First of all GRUB2 reads min_addr (min. load addr), max_addr (max. load addr),
align (required image alignment), preference (it says which memory regions are
preferred by image, e.g. none, low, high) from multiboot_header_tag_relocatable
header tag contained in binary (at this stage load addresses from multiboot2
and/or ELF headers are ignored). Later loader tries to fulfill request (not only
that one) and if it succeeds then it informs image about real load address via
multiboot_tag_load_base_addr tag. At this stage GRUB2 role is finished. Starting
from now executable must cope with relocations itself using whole static and
dynamic knowledge provided by boot loader.

This patch does not provide functionality which could do relocations using
ELF relocation data. However, I was asked by Konrad Rzeszutek Wilk and Vladimir
'phcoder' Serbinenko to investigate that thing. It looks that relevant machinery
could be added to existing code (including this patch) without huge effort.
Additionally, ELF relocation could live in parallel with self relocation provided
by this patch. However, during research I realized that first of all we should
establish the details how ELF relocatable image should look like and how it should
be build. At least to build proper test/example files.

So, this patch just provides support for self relocatable images. If ELF file
with relocs is loaded then GRUB2 complains loudly and ignores it. Support for
such files will be added later.

This patch was tested with Xen image which uses that functionality. However, this Xen
feature is still under development and new patchset will be released in about 2-3 weeks.

Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
Reviewed-by: Vladimir Serbinenko <phcoder@gmail.com>
2016-10-27 15:55:16 +02:00
Daniel Kiper
f2b6c20a25 multiboot2: Do not pass memory maps to image if EFI boot services are enabled
If image requested EFI boot services then skip multiboot2 memory maps.
Main reason for not providing maps is because they will likely be
invalid. We do a few allocations after filling them, e.g. for relocator
needs. Usually we do not care as we would have finished boot services.
If we keep boot services then it is easier/safer to not provide maps.
However, if image needs memory maps and they are not provided by bootloader
then it should get itself just before ExitBootServices() call.

Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Reviewed-by: Vladimir Serbinenko <phcoder@gmail.com>
2016-10-27 15:55:00 +02:00
Daniel Kiper
ba89c19f49 multiboot2: Add tags used to pass ImageHandle to loaded image
Add tags used to pass ImageHandle to loaded image if requested.
It is used by at least ExitBootServices() function.

Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Reviewed-by: Vladimir Serbinenko <phcoder@gmail.com>
2016-10-27 15:54:46 +02:00
Daniel Kiper
9862b24121 i386/relocator: Add grub_relocator64_efi relocator
Add grub_relocator64_efi relocator. It will be used on EFI 64-bit platforms
when multiboot2 compatible image requests MULTIBOOT_TAG_TYPE_EFI_BS. Relocator
will set lower parts of %rax and %rbx accordingly to multiboot2 specification.
On the other hand processor mode, just before jumping into loaded image, will
be set accordingly to Unified Extensible Firmware Interface Specification,
Version 2.4 Errata B, section 2.3.4, x64 Platforms, boot services. This way
loaded image will be able to use EFI boot services without any issues.

Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Reviewed-by: Vladimir Serbinenko <phcoder@gmail.com>
2016-10-27 15:53:43 +02:00
Sakar Arora
e563928ba4 net/ip: Fix limit_time calculation in freeing old fragments
limit_time underflows when current time is less than 90000ms.
This causes packet fragments received during this time, i.e.,
till 90000ms pass since timer init, to be rejected.

Hence, set it to 0 if its less than 90000.

Signed-off-by: Sakar Arora <Sakar.Arora@nxp.com>
2016-10-18 20:26:42 +03:00
Andrei Borzenkov
a0bf403f66 asm-tests/i386-pc: Check that movl is 5 bytes.
LLVM 3.9 now emits short form of jump instructions, but it is still using
32 bit addresses for some movl instructions. Fortunately it was caught early:

clang ... boot/i386/pc/boot.S
clang -cc1as: fatal error: error in backend: invalid .org offset '440' (at offset '441')

Add additional check to catch it during configure run and force -no-integrated-as.

Closes: 49200

More details in
  https://lists.gnu.org/archive/html/grub-devel/2015-02/msg00099.html
  https://llvm.org/bugs/show_bug.cgi?id=22662
2016-09-28 20:31:04 +03:00
Pete Batard
4e0f8f66e3 Add missing va_end() to xasprintf() in grub-emu. 2016-08-13 16:36:01 +03:00
Vladimir Serbinenko
9ac0dca085 strtoull: Fix behaviour on chars between '9' and 'a'.
Reported by: Aaron Miller <aaronmiller@fb.com>
2016-08-10 17:49:42 +02:00
Andrei Borzenkov
c831d2073b at_keyboard: fix numpad "0" and "." mapping
Reported for set 1 by fgndevelop <fgndevelop@posteo.org>. Apparently
set 2 was reversed too.
2016-07-27 08:33:12 +03:00
Andrei Borzenkov
52408aa946 dns: fix buffer overflow for data->addresses in recv_hook
We may get more than one response before exiting out of loop in
grub_net_dns_lookup, but buffer was allocated for the first response only,
so storing answers from subsequent replies wrote past allocated size.
We never really use more than the very first address during lookup so there
is little point in collecting all of them. Just quit early if we already have
some reply.

Code needs serious redesign to actually collect multiple answers
and select the best fit according to requested type (IPv4 or IPv6).

Reported and tested by Michael Chang <mchang@suse.com>
2016-07-26 20:38:58 +03:00
Andrei Borzenkov
58590cb2ef xfs: accept filesystem with meta_uuid
XFS V5 stores UUID in metadata and compares them with superblock UUID.
To allow changing of user-visible UUID it stores original value in new
superblock field (meta_uuid) and sets incompatible flag to indicate that
new field must be used to verify metadata. Our driver currently does not
check metadata UUID so simply accept such filesystem.

Reported-By: Marcos Mello <marcosfrm@outlook.com>
Reviewd by Jan Kara <jack@suse.cz>
2016-07-26 20:29:26 +03:00
Andrei Borzenkov
b524fa27f5 net: translate pxe prefix to tftp when checking for self-load
Commit ba218c1 missed legacy pxe and pxe: prefixes which are
translated to tftp, so comparison failed.
2016-05-03 19:23:31 +03:00
Andrei Borzenkov
e045af148a net: reset net->stall in grub_net_seek_real
If we open new connection, we need to reset stall indication, otherwise
nothing will ever be polled (low level code rely on this field being
zero when establishing connection).
2016-04-30 09:15:36 +03:00
Stefan Fritsch
13f7ead3a1 http: reset EOF indication in http_seek
Otherwise next read will stop polling too early due to stale EOF
indicator, returning incomplete data to caller.
2016-04-30 09:13:34 +03:00
Mike Gilbert
7a5b301e3a build: Use AC_HEADER_MAJOR to find device macros
Depending on the OS/libc, device macros are defined in different
headers. This change ensures we include the right one.

sys/types.h - BSD
sys/mkdev.h - Sun
sys/sysmacros.h - glibc (Linux)

glibc currently pulls sys/sysmacros.h into sys/types.h, but this may
change in a future release.

https://sourceware.org/ml/libc-alpha/2015-11/msg00253.html
2016-04-24 08:12:42 +03:00
Michael Chang
abf9beb7d6 http: fix superfluous null line in range request header
At least the apache sever is very unhappy with that extra null line and will
take more than ten seconds in responding to each range request, which slows
down a lot the entire http file transfer process or even time out.
2016-04-09 07:08:13 +03:00
Andrei Borzenkov
f4d35d49e3 configure: set -fno-pie together with -fno-PIE
OpenBSD 5.9 apparently defaults to -fpie. We use -fno-PIE when appropriate
already, but that is not enough - it does not turn off -fpie.

Actually check for -fPIE is not precise enough. __PIE__ is set for both
-fpie and -fPIE but with different values. As far as I can tell, both
options were introduced at the same time, so both should always be supported.

This fixes compilation on OpenBSD 5.9 which otherwise created insanely big
lzma_decompress.img.

Reported, suggested and tested by: Jiri B <jirib@devio.us>
2016-03-22 20:12:22 +03:00
Andrei Borzenkov
6714d7ecff bootp: check that interface is not NULL in configure_by_dhcp_ack
grub_net_add_addr may fail with OOM and we use returned interface
later without any checks.
2016-03-20 10:32:33 +03:00
Andrei Borzenkov
5b8ddf6e03 bootp: fix memory leak in grub_cmd_dhcpopt 2016-03-19 09:39:30 +03:00
Aaron Luft
76eac44af3 Remove the variable oldname which is attempting to free stack space.
Historically this variable hold previous value of filename that
had to be freed if allocated previously. Currently this branch
is entered only if filename was not allocated previously so it
became redundant. It did not cause real problems because grub_free
was not called, but code is confusing and causes compilation error
in some cases.
2016-03-15 22:04:38 +03:00
Andrei Borzenkov
ee83919e93 Makefile.util.def: add $LIBINTL to grub-macbless flags
Fixes compilation on OpenBSD 5.9.

Reported by Jiri B <jirib@devio.us>
2016-03-13 08:11:58 +03:00
Robert Marshall
3c3e96d044 Failed config now returns exit code (#1252311)
Grub would notify the user if the new config was invalid, however, it
did not exit properly with exit code 1. Added the proper exit code.

Resolves: rhbz#1252311
2016-03-11 17:24:56 +01:00
Michael Chang
15aee573d2 xen_file: Fix invalid payload size 2016-03-11 10:26:51 +01:00
Vladimir Serbinenko
7f2a856fae multiboot2: Remove useless GRUB_PACKED
Reported by: Daniel Kiper
2016-03-10 21:16:10 +01:00
Andrei Borzenkov
9545a8fd04 20_linux_xen: fix test for GRUB_DEVICE
Same fix as in 082bc9f.
2016-03-06 08:54:19 +03:00
Mike Gilbert
082bc9f77b 10_linux: Fix grouping of tests for GRUB_DEVICE
Commit 7290bb562 causes GRUB_DISABLE_LINUX_UUID to be ignored due to
mixing of || and && operators. Add some parens to help with that.
2016-03-06 08:51:07 +03:00
Andrei Borzenkov
d017ea8ede NEWS update 2016-02-28 21:52:08 +03:00
Vladimir Serbinenko
b4fc7bc2fd Merge branch 'master' into next 2016-02-28 15:22:52 +01:00
Vladimir Serbinenko
8207874e5d Release 2.02~beta3 2016-02-28 03:07:41 +01:00
Vladimir Serbinenko
102e435d81 grub_arch_sync_dma_caches: Accept volatile address 2016-02-28 03:07:27 +01:00
Leif Lindholm
51f375d688 efidisk: Respect block_io_protocol buffer alignment
Returned from the OpenProtocol operation, the grub_efi_block_io_media
structure contains the io_align field, specifying the minimum alignment
required for buffers used in any data transfers with the device.

Make grub_efidisk_readwrite() allocate a temporary buffer, aligned to
this boundary, if the buffer passed to it does not already meet the
requirements.

Also sanity check the io_align field in grub_efidisk_open() for
power-of-two-ness and bail if invalid.
2016-02-27 13:44:59 +01:00
Vladimir Serbinenko
ca028db3d4 usbtrans: Fix memory coherence and use-after-free. 2016-02-27 13:40:52 +01:00
Vladimir Serbinenko
0f076d75d0 ehci: Fix memory coherence
This is a no-op on x86 but necessarry on ARM and may be necessarry on MIPS.
2016-02-27 13:40:52 +01:00
Vladimir Serbinenko
86ef66d977 arm-uboot: Make self-relocatable to allow loading at any address 2016-02-27 13:40:52 +01:00
Vladimir Serbinenko
5bcb7d394c Allow _start == 0 with relocatable images 2016-02-27 13:35:36 +01:00
Vladimir Serbinenko
df21fff504 Provide __bss_start and _end symbols in grub-mkimage.
For this ensure that all bss sections are merged.

We need this to correctly prelink non-PE relocatable images.
2016-02-27 13:35:36 +01:00
Vladimir Serbinenko
73a9c742fe Encapsulate image layout into a separate structure.
Currently we pass around a lot of pointer. Instead put all relevant data
into one structure.
2016-02-27 13:35:36 +01:00
Vladimir Serbinenko
dd3969e7ec mkimagexx: Split PE and generic part for relocations.
As a preparation for U-Boot relocations, split emitting PE-relocations
from parsing source ELF-relocations.
2016-02-27 13:35:36 +01:00
Vladimir Serbinenko
36212460d3 mkimage.c: Split into separate files.
util/grub-mkimagexx.c is included in a special way into mkimage.c.
Interoperation between defines makes this very tricky. Instead
just have a clean interface and compile util/grub-mkimage*.c separately
from mkimage.c
2016-02-27 13:35:36 +01:00
Vladimir Serbinenko
2ebef43cf6 bsd: Ensure that kernel is loaded before loading module.
kernel_type may be set to the type of failed kernel. This patching-up is
easier than to reflow kernel loading routines.
2016-02-27 13:35:36 +01:00
Vladimir Serbinenko
8c26dace6f cat: Don't switch terminal mode when there is nothing to highlight.
This just pollutes serial console.
2016-02-27 13:35:36 +01:00
Vladimir Serbinenko
070e190305 Use console rather than serial_efi0 on arm64-efi in tests 2016-02-27 13:35:36 +01:00
Andrei Borzenkov
109189ce01 efidisk: fix misplaced parenthesis in b00e4c2 2016-02-27 15:16:48 +03:00
Andrei Borzenkov
b00e4c2bd9 efidisk: prevent errors from diskfilter scan of removable drives
Map EFI_NO_MEDIA to GRUB_ERR_OUT_OF_RANGE that is ignored by diskfilter. This
actually matches pretty close (we obviously attempt to read outside of media)
and avoids adding more error codes.

This affects only internally initiated scans. If read/write from removable is
explicitly requested, we still return an error and text explanation is more
clear for user than generic error.

Reported and tested by Andreas Loew <Andreas.Loew@gmx.net>
2016-02-26 21:44:37 +03:00
Vladimir Serbinenko
06a3b0b214 Regenerate checksums 2016-02-26 11:37:47 +01:00
Vladimir Serbinenko
5486a4e12b Makefile: Don't delete default_payload.elf if it doesn't exist. 2016-02-26 11:14:46 +01:00
Josef Bacik
eb9f401fc1 net: fix ipv6 routing
ipv6 routing in grub2 is broken, we cannot talk to anything outside our local
network or anything that doesn't route in our global namespace.  This patch
fixes this by doing a couple of things

1) Read the router information off of the router advertisement.  If we have a
router lifetime we need to take the source address and create a route from it.

2) Changes the routing stuff slightly to allow you to specify a gateway _and_ an
interface.  Since the router advertisements come in on the link local address we
need to associate it with the global address on the card.  So when we are
processing the router advertisement, either use the SLAAC interface we create
and add the route to that interface, or loop through the global addresses we
currently have on our interface and associate it with one of those addresses.
We need to have a special case here for the default route so that it gets used,
we do this by setting the masksize to 0 to mean it encompasses all networks.
The routing code will automatically select the best route so if there is a
closer match we will use that.

With this patch I can now talk to ipv6 addresses outside of my local network.
Thanks,

Signed-off-by: Josef Bacik <jbacik@fb.com>
2016-02-25 22:38:52 +03:00
Vladimir Serbinenko
94c56a4c65 ieee1275: fix signed comparison 2016-02-24 18:37:22 +01:00
Andrei Borzenkov
1b782e902e search: actually skip floppy with --no-floppy
grub_device_iterate() ignores device when iterator returns 1, not 0.

Reported by Carlos E. R. <robin.listas@telefonica.net>
2016-02-23 23:17:24 +03:00
Andrei Borzenkov
15dfea842c multiboot2: zero reserved field in memory map
Documentation says, bootloader should set reserved field to zero.

Reported by Wink Saville <wink@saville.com>
2016-02-23 09:12:14 +03:00
Vladimir Serbinenko
054d1325e9 Improve EHCI logging
Add dprintf's on common error paths and remove some entries which are too
noisy.
2016-02-22 20:07:10 +01:00
Vladimir Serbinenko
0678b5d629 usb_keyboard: Remove useless include
This prevents non-PCI machines from having USB.
2016-02-22 20:05:54 +01:00
Vladimir Serbinenko
be4e9d20a5 Refresh before abort
This ensures that abort message is actually visible to the user.
2016-02-22 19:46:55 +01:00
Eric Snowberg
bc220962e3 ieee1275: prevent buffer over-read
Prevent buffer over-read in grub_machine_mmap_iterate. This was
causing phys_base from being calculated properly. This then
caused the wrong value to be placed in ramdisk_image within
struct linux_hdrs. Which prevented the ramdisk from loading on
boot.

Newer SPARC systems contain more than 8 available memory entries.

For example on a T5-8 with 2TB of memory, the memory layout could
look like this:

T5-8 Memory
reg                      00000000 30000000 0000003f b0000000
                         00000800 00000000 00000040 00000000
                         00001000 00000000 00000040 00000000
                         00001800 00000000 00000040 00000000
                         00002000 00000000 00000040 00000000
                         00002800 00000000 00000040 00000000
                         00003000 00000000 00000040 00000000
                         00003800 00000000 00000040 00000000
available                00003800 00000000 0000003f ffcae000
                         00003000 00000000 00000040 00000000
                         00002800 00000000 00000040 00000000
                         00002000 00000000 00000040 00000000
                         00001800 00000000 00000040 00000000
                         00001000 00000000 00000040 00000000
                         00000800 00000000 00000040 00000000
                         00000000 70000000 0000003f 70000000
                         00000000 6eef8000 00000000 00002000
                         00000000 30400000 00000000 3eaf6000
name                     memory

Signed-off-by: Eric Snowberg <eric.snowberg@oracle.com>
2016-02-22 10:01:31 +03:00
Thomas Huth
625934ec0f menu_entry: Disable cursor during update_screen()
When running grub in a VGA console of a KVM pseries guest on PowerPC,
you can see the cursor sweeping over the whole line when entering a
character in editor mode. This is visible because grub always refreshes
the whole line when entering a character in editor mode, and drawing
characters is quite a slow operation with the firmware used for the
powerpc pseries guests (SLOF).
To avoid this ugliness, the cursor should be disabled when refreshing
the screen contents during update_screen().

Signed-off-by: Thomas Huth <thuth@redhat.com>
2016-02-22 09:59:27 +03:00
Vladimir Serbinenko
c4748ead11 Merge branch 'master' into next
Conflicts:
	ChangeLog-2015
	grub-core/net/drivers/ieee1275/ofnet.c
	include/grub/ieee1275/ieee1275.h
2015-02-27 01:05:08 +01:00
Paulo Flabiano Smorigo
af768f8d41 Add Virtual LAN support.
This patch adds support for virtual LAN (VLAN) tagging. VLAN tagging allows
multiple VLANs in a bridged network to share the same physical network link
but maintain isolation:

http://en.wikipedia.org/wiki/IEEE_802.1Q

* grub-core/net/ethernet.c: Add check, get, and set vlan tag id.
* grub-core/net/drivers/ieee1275/ofnet.c: Get vlan tag id from bootargs.
* grub-core/net/arp.c: Add check.
* grub-core/net/ip.c: Likewise.
* include/grub/net/arp.h: Add vlantag attribute.
* include/grub/net/ip.h: Likewise.
2013-12-23 12:32:47 -02:00
Paulo Flabiano Smorigo
8ff3c31f6d Add bootargs parser for open firmware.
It enables net boot even when there is no bootp/dhcp server.

* grub-core/net/drivers/ieee1275/ofnet.c: Add grub_ieee1275_parse_bootargs and
call it at grub_ieee1275_net_config_real.
2013-12-23 12:13:48 -02:00
Paulo Flabiano Smorigo
11454e94ea Add grub_env_set_net_property function.
* grub-core/net/bootp.c: Remove set_env_limn_ro.
* grub-core/net/net.c: Add grub_env_set_net_property.
2013-12-23 12:07:31 -02:00
239 changed files with 4355 additions and 6072 deletions

1
.gitignore vendored
View File

@@ -246,3 +246,4 @@ build-aux/test-driver
/garbage-gen
/garbage-gen.exe
/grub-fs-tester
grub-core/build-grub-module-verifier

View File

@@ -15,15 +15,14 @@ configuring the GRUB.
Note: older versions may work but support is limited
Experimental support for clang 3.3 or later (results in much bigger binaries)
for i386, x86_64, arm (except thumb), arm64, mips(el), powerpc, sparc64
for i386, x86_64, arm (including thumb), arm64, mips(el), powerpc, sparc64
Note: clang 3.2 or later works for i386 and x86_64 targets but results in
much bigger binaries.
earlier versions not tested
Note: clang 3.2 or later works for arm
None of tested clang versions generated usable thumb code
earlier versions not tested
Note: clang 3.3 or later works for arm64
earlier versions have no arm64 support
Note: clang on arm64 is not supported due to
https://llvm.org/bugs/show_bug.cgi?id=26030
Note: clang 3.3 or later works for mips(el)
earlier versions fail to generate .reginfo and hence gprel relocations
fail.

View File

@@ -145,109 +145,116 @@ if COND_real_platform
if COND_i386_coreboot
QEMU32=qemu-system-i386
MINIMUM_CPU_LINUX=pentium2
endif
if COND_i386_multiboot
QEMU32=qemu-system-i386
MINIMUM_CPU_LINUX=pentium2
endif
if COND_i386_ieee1275
QEMU32=qemu-system-i386
MINIMUM_CPU_LINUX=pentium2
endif
if COND_i386_qemu
QEMU32=qemu-system-i386
MINIMUM_CPU_LINUX=pentium2
endif
if COND_i386_pc
QEMU32=qemu-system-i386
MINIMUM_CPU_LINUX=pentium2
endif
if COND_i386_efi
QEMU32=qemu-system-i386
MINIMUM_CPU_LINUX=pentium2
endif
if COND_x86_64_efi
QEMU32=qemu-system-x86_64
MINIMUM_CPU_LINUX=core2duo
endif
linux.init.x86_64: $(srcdir)/grub-core/tests/boot/linux.init-x86_64.S $(srcdir)/grub-core/tests/boot/qemu-shutdown-x86.S
$(TARGET_CC) -o $@ $< -m64 -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\"
$(TARGET_CC) -o $@ $< -static -m64 -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\"
linux.init.i386: $(srcdir)/grub-core/tests/boot/linux.init-i386.S $(srcdir)/grub-core/tests/boot/qemu-shutdown-x86.S
$(TARGET_CC) -o $@ $< -m32 -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\"
$(TARGET_CC) -o $@ $< -static -m32 -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\"
linux.init.mips: $(srcdir)/grub-core/tests/boot/linux.init-mips.S
$(TARGET_CC) -o $@ $< -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\"
$(TARGET_CC) -o $@ $< -static -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\"
linux.init.ppc: $(srcdir)/grub-core/tests/boot/linux.init-ppc.S
$(TARGET_CC) -o $@ $< -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\"
$(TARGET_CC) -o $@ $< -static -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\"
linux.init.mipsel: $(srcdir)/grub-core/tests/boot/linux.init-mips.S
$(TARGET_CC) -o $@ $< -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\"
$(TARGET_CC) -o $@ $< -static -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\"
linux.init.loongson: $(srcdir)/grub-core/tests/boot/linux.init-mips.S
$(TARGET_CC) -o $@ $< -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" -DREBOOT=1
$(TARGET_CC) -o $@ $< -static -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" -DREBOOT=1
multiboot.elf: $(srcdir)/grub-core/tests/boot/kernel-i386.S $(srcdir)/grub-core/tests/boot/qemu-shutdown-x86.S
$(TARGET_CC) -o $@ $< -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" -ffreestanding -nostdlib -nostdinc -DTARGET_MULTIBOOT=1 -Wl,--build-id=none -Wl,-N -Wl,-Ttext,0x100000 -m32 -I$(srcdir)/include
$(TARGET_CC) -o $@ $< -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" -static -ffreestanding -nostdlib -nostdinc -DTARGET_MULTIBOOT=1 -Wl,--build-id=none -Wl,-N -Wl,-Ttext,0x100000 -m32 -I$(srcdir)/include
kfreebsd.elf: $(srcdir)/grub-core/tests/boot/kernel-i386.S $(srcdir)/grub-core/tests/boot/qemu-shutdown-x86.S
$(TARGET_CC) -o $@ $< -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" -ffreestanding -nostdlib -nostdinc -Wl,--build-id=none -Wl,-N -Wl,-Ttext,0x100000 -m32 -I$(srcdir)/include
$(TARGET_CC) -o $@ $< -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" -static -ffreestanding -nostdlib -nostdinc -Wl,--build-id=none -Wl,-N -Wl,-Ttext,0x100000 -m32 -I$(srcdir)/include
kfreebsd.aout: kfreebsd.elf
$(TARGET_OBJCOPY) -O a.out-i386-linux $< $@ -R .note.gnu.build-id -R .note.gnu.gold-version
$(TARGET_OBJCOPY) -O a.out-i386-linux $< $@ -j .text
pc-chainloader.elf: $(srcdir)/grub-core/tests/boot/kernel-8086.S $(srcdir)/grub-core/tests/boot/qemu-shutdown-x86.S
$(TARGET_CC) -o $@ $< -DTARGET_CHAINLOADER=1 -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" -ffreestanding -nostdlib -nostdinc -Wl,--build-id=none -Wl,-N -Wl,-Ttext,0x7c00 -m32
$(TARGET_CC) -o $@ $< -static -DTARGET_CHAINLOADER=1 -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" -ffreestanding -nostdlib -nostdinc -Wl,--build-id=none -Wl,-N -Wl,-Ttext,0x7c00 -m32
pc-chainloader.bin: pc-chainloader.elf
$(TARGET_OBJCOPY) -O binary --strip-unneeded -R .note -R .comment -R .note.gnu.build-id -R .reginfo -R .rel.dyn -R .note.gnu.gold-version $< $@;
ntldr.elf: $(srcdir)/grub-core/tests/boot/kernel-8086.S $(srcdir)/grub-core/tests/boot/qemu-shutdown-x86.S
$(TARGET_CC) -o $@ $< -DTARGET_NTLDR=1 -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" -ffreestanding -nostdlib -nostdinc -Wl,--build-id=none -Wl,-N -Wl,-Ttext,0 -m32
$(TARGET_CC) -o $@ $< -DTARGET_NTLDR=1 -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" -static -ffreestanding -nostdlib -nostdinc -Wl,--build-id=none -Wl,-N -Wl,-Ttext,0 -m32
ntldr.bin: ntldr.elf
$(TARGET_OBJCOPY) -O binary --strip-unneeded -R .note -R .comment -R .note.gnu.build-id -R .reginfo -R .rel.dyn -R .note.gnu.gold-version $< $@;
$(TARGET_OBJCOPY) -O binary --strip-unneeded -j .text $< $@;
multiboot2.elf: $(srcdir)/grub-core/tests/boot/kernel-i386.S $(srcdir)/grub-core/tests/boot/qemu-shutdown-x86.S
$(TARGET_CC) -o $@ $< -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" -ffreestanding -nostdlib -nostdinc -Wl,--build-id=none -Wl,-N -Wl,-Ttext,0x100000 -m32 -I$(srcdir)/include -DTARGET_MULTIBOOT2=1
$(TARGET_CC) -static -o $@ $< -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" -ffreestanding -nostdlib -nostdinc -Wl,--build-id=none -Wl,-N -Wl,-Ttext,0x100000 -m32 -I$(srcdir)/include -DTARGET_MULTIBOOT2=1
kfreebsd.init.x86_64: $(srcdir)/grub-core/tests/boot/kfreebsd.init-x86_64.S $(srcdir)/grub-core/tests/boot/qemu-shutdown-x86.S
$(TARGET_CC) -o $@ $< -m64 -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" && freebsd-brandelf -t FreeBSD $@
$(TARGET_CC) -o $@ $< -m64 -static -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" && freebsd-brandelf -t FreeBSD $@
kfreebsd.init.i386: $(srcdir)/grub-core/tests/boot/kfreebsd.init-i386.S $(srcdir)/grub-core/tests/boot/qemu-shutdown-x86.S
$(TARGET_CC) -o $@ $< -m32 -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" && freebsd-brandelf -t FreeBSD $@
$(TARGET_CC) -o $@ $< -m32 -static -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" && freebsd-brandelf -t FreeBSD $@
knetbsd.init.i386: $(srcdir)/grub-core/tests/boot/kbsd.init-i386.S $(srcdir)/grub-core/tests/boot/qemu-shutdown-x86.S
$(TARGET_CC) -o $@ $< -m32 -nostdlib -nostdinc -DTARGET_NETBSD=1 -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\"
$(TARGET_CC) -o $@ $< -m32 -static -nostdlib -nostdinc -DTARGET_NETBSD=1 -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\"
kopenbsd.init.i386: $(srcdir)/grub-core/tests/boot/kbsd.init-i386.S $(srcdir)/grub-core/tests/boot/qemu-shutdown-x86.S
$(TARGET_CC) -o $@ $< -m32 -nostdlib -nostdinc -DTARGET_OPENBSD=1 -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\"
$(TARGET_CC) -o $@ $< -m32 -static -nostdlib -nostdinc -DTARGET_OPENBSD=1 -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\"
knetbsd.init.x86_64: $(srcdir)/grub-core/tests/boot/kbsd.init-x86_64.S $(srcdir)/grub-core/tests/boot/qemu-shutdown-x86.S
$(TARGET_CC) -o $@ $< -m64 -DTARGET_NETBSD=1 -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\"
$(TARGET_CC) -o $@ $< -m64 -DTARGET_NETBSD=1 -static -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\"
kopenbsd.init.x86_64: $(srcdir)/grub-core/tests/boot/kbsd.init-x86_64.S $(srcdir)/grub-core/tests/boot/qemu-shutdown-x86.S
$(TARGET_CC) -o $@ $< -m64 -DTARGET_OPENBSD=1 -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\"
$(TARGET_CC) -o $@ $< -m64 -DTARGET_OPENBSD=1 -static -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\"
linux-initramfs.mips: linux.init.mips Makefile
TDIR=`mktemp -d "$${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` && cp $< $$TDIR/init && (cd $$TDIR && echo ./init | cpio --quiet --dereference -o -H newc) | gzip > $@ && rm -rf $$TDIR
TDIR=`mktemp -d "$${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` && cp $< $$TDIR/init && (cd $$TDIR && echo ./init | cpio -R 0:0 --quiet --dereference -o -H newc) | gzip > $@ && rm -rf $$TDIR
linux-initramfs.ppc: linux.init.ppc Makefile
TDIR=`mktemp -d "$${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` && cp $< $$TDIR/init && (cd $$TDIR && echo ./init | cpio --quiet --dereference -o -H newc) | gzip > $@ && rm -rf $$TDIR
TDIR=`mktemp -d "$${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` && cp $< $$TDIR/init && (cd $$TDIR && echo ./init | cpio -R 0:0 --quiet --dereference -o -H newc) | gzip > $@ && rm -rf $$TDIR
linux-initramfs.mipsel: linux.init.mipsel Makefile
TDIR=`mktemp -d "$${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` && cp $< $$TDIR/init && (cd $$TDIR && echo ./init | cpio --quiet --dereference -o -H newc) | gzip > $@ && rm -rf $$TDIR
TDIR=`mktemp -d "$${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` && cp $< $$TDIR/init && (cd $$TDIR && echo ./init | cpio -R 0:0 --quiet --dereference -o -H newc) | gzip > $@ && rm -rf $$TDIR
linux-initramfs.loongson: linux.init.loongson Makefile
TDIR=`mktemp -d "$${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` && cp $< $$TDIR/init && (cd $$TDIR && echo ./init | cpio --quiet --dereference -o -H newc) | gzip > $@ && rm -rf $$TDIR
TDIR=`mktemp -d "$${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` && cp $< $$TDIR/init && (cd $$TDIR && echo ./init | cpio -R 0:0 --quiet --dereference -o -H newc) | gzip > $@ && rm -rf $$TDIR
linux-initramfs.i386: linux.init.i386 Makefile
TDIR=`mktemp -d "$${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` && cp $< $$TDIR/init && (cd $$TDIR && echo ./init | cpio --quiet --dereference -o -H newc) | gzip > $@ && rm -rf $$TDIR
TDIR=`mktemp -d "$${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` && cp $< $$TDIR/init && (cd $$TDIR && echo ./init | cpio -R 0:0 --quiet --dereference -o -H newc) | gzip > $@ && rm -rf $$TDIR
linux-initramfs.x86_64: linux.init.x86_64 Makefile
TDIR=`mktemp -d "$${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` && cp $< $$TDIR/init && (cd $$TDIR && echo ./init | cpio --quiet --dereference -o -H newc) | gzip > $@ && rm -rf $$TDIR
TDIR=`mktemp -d "$${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` && cp $< $$TDIR/init && (cd $$TDIR && echo ./init | cpio -R 0:0 --quiet --dereference -o -H newc) | gzip > $@ && rm -rf $$TDIR
kfreebsd-mfsroot.i386.img: kfreebsd.init.i386 Makefile
TDIR=`mktemp -d "$${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` && mkdir $$TDIR/dev && mkdir $$TDIR/sbin && cp $< $$TDIR/sbin/init && makefs -t ffs -s 30m -f 1000 -o minfree=0,version=1 $@ $$TDIR && rm -rf $$TDIR
@@ -306,7 +313,7 @@ bootcheck-knetbsd-x86_64: knetbsd.miniroot-image.x86_64.gz $(GRUB_PAYLOADS_DIR)/
./grub-shell --timeout=$(BOOTCHECK_TIMEOUT) --qemu=qemu-system-x86_64 --files=/miniroot.gz=knetbsd.miniroot-image.x86_64.gz --files=/knetbsd=$(GRUB_PAYLOADS_DIR)/knetbsd.x86_64 $(srcdir)/grub-core/tests/boot/knetbsd.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null
bootcheck-linux-i386: linux-initramfs.i386 $(GRUB_PAYLOADS_DIR)/linux.i386 $(srcdir)/grub-core/tests/boot/linux.cfg grub-shell
./grub-shell --timeout=$(BOOTCHECK_TIMEOUT) --qemu=$(QEMU32) --files=/initrd=linux-initramfs.i386 --files=/linux=$(GRUB_PAYLOADS_DIR)/linux.i386 $(srcdir)/grub-core/tests/boot/linux.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null
./grub-shell --timeout=$(BOOTCHECK_TIMEOUT) --qemu=$(QEMU32) --files=/initrd=linux-initramfs.i386 --files=/linux=$(GRUB_PAYLOADS_DIR)/linux.i386 $(srcdir)/grub-core/tests/boot/linux.cfg --qemu-opts="-cpu $(MINIMUM_CPU_LINUX)" | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null
bootcheck-linux-x86_64: linux-initramfs.x86_64 $(GRUB_PAYLOADS_DIR)/linux.x86_64 $(srcdir)/grub-core/tests/boot/linux.cfg grub-shell
./grub-shell --timeout=$(BOOTCHECK_TIMEOUT) --qemu=qemu-system-x86_64 --files=/initrd=linux-initramfs.x86_64 --files=/linux=$(GRUB_PAYLOADS_DIR)/linux.x86_64 $(srcdir)/grub-core/tests/boot/linux.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null
@@ -369,6 +376,12 @@ if COND_i386_coreboot
BOOTCHECKS = bootcheck-kfreebsd-aout bootcheck-kopenbsd-i386 bootcheck-kopenbsd-x86_64 bootcheck-multiboot bootcheck-multiboot2 bootcheck-linux-i386 bootcheck-linux-x86_64 bootcheck-knetbsd-x86_64 bootcheck-kfreebsd-x86_64 bootcheck-kfreebsd-i386
endif
if COND_i386_ieee1275
# *BSD requires ACPI
#legacy protocol (linux16) makes early BIOS calls.
BOOTCHECKS = bootcheck-kfreebsd-aout bootcheck-multiboot bootcheck-multiboot2 bootcheck-linux-i386 bootcheck-linux-x86_64
endif
if COND_i386_pc
#pc chainloader by definition is only for i386-pc
#ntldr and bootmgr require BIOS.
@@ -410,7 +423,7 @@ bootcheck: $(BOOTCHECKS)
if COND_i386_coreboot
default_payload.elf: grub-mkstandalone grub-mkimage FORCE
rm $@
test -f $@ && rm $@ || true
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

View File

@@ -416,7 +416,7 @@ program = {
ldadd = libgrubgcry.a;
ldadd = libgrubkern.a;
ldadd = grub-core/gnulib/libgnu.a;
ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
};
data = {

14
NEWS
View File

@@ -18,6 +18,7 @@ New in 2.02:
* ZFS features support.
* ZFS LZ4 support.
* XFS V5 format support.
* LVM RAID1 support.
* New/improved terminal and video support:
* Monochrome text (matching `hercules' in GRUB Legacy).
@@ -49,6 +50,9 @@ New in 2.02:
* Improve TFTP robustness.
* Parse `nd' disk names in GRUB Legacy configuration files.
* Issue separate DNS queries for IPv4 and IPv6.
* Support IPv6 Router Advertisement to configure default router.
* New variable net_<interface>_next_server containing next server
from BOOTP reply.
* Coreboot improvements:
* CBFS support both in on-disk images (loopback) and flash.
@@ -96,6 +100,8 @@ New in 2.02:
EFI Stall. If everything fails, use hardcoded frequency 800MHz.
* Support Hyper-V Gen2 platforms which lack PIT for TSC calibration.
* Map UEFI Persistent Memory to E820 persistent memory.
* New Xen loader on ARM64.
* Respect alignment requirement for block device IO buffers on EFI.
* Security:
* Add optional facility to enforce that all files read by the core image
@@ -134,6 +140,11 @@ New in 2.02:
menu entry immediately.
* New `file' command and grub-file utility to check file types.
* New syslinux configuration file parser.
* Set menu entry class to primary OS name returned by os-prober to display
OS specific icon.
* On Linux x86 detect EFI word size in grub-install and automatically select
correct platform (x86_64-efi or i386-efi) to install. Requires Linux kernel
4.0 or higher.
* Build system:
* Remove all uses of nested functions; GRUB no longer requires an
@@ -160,6 +171,9 @@ New in 2.02:
* emu libusb support removed (was broken and unmaintained).
* powerpc64le compile support.
* Use fixed timestamp when generating GRUB image for reproducible builds.
* Verify at build time that modules contain only supported relocations and their
structure matches what boot-time module loader expects.
* Do not require fonts on powerpc-ieee1275.
* Revision control moved to git.

View File

@@ -390,6 +390,58 @@ else
[fi]
])
AC_DEFUN([grub_CHECK_LINK_PIE],[
[# Position independent executable.
link_nopie_needed=no]
AC_MSG_CHECKING([whether linker needs disabling of PIE to work])
AC_LANG_CONFTEST([AC_LANG_SOURCE([[]])])
[if eval "$ac_compile -Wl,-r,-d -nostdlib -Werror -o conftest.o" 2> /dev/null; then]
AC_MSG_RESULT([no])
[# Should we clear up other files as well, having called `AC_LANG_CONFTEST'?
rm -f conftest.o
else
link_nopie_needed=yes]
AC_MSG_RESULT([yes])
[fi]
])
dnl Check if the Linker supports `-no-pie'.
AC_DEFUN([grub_CHECK_NO_PIE],
[AC_MSG_CHECKING([whether linker accepts -no-pie])
AC_CACHE_VAL(grub_cv_cc_ld_no_pie,
[save_LDFLAGS="$LDFLAGS"
LDFLAGS="$LDFLAGS -no-pie -nostdlib -Werror"
AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[]])],
[grub_cv_cc_ld_no_pie=yes],
[grub_cv_cc_ld_no_pie=no])
LDFLAGS="$save_LDFLAGS"
])
AC_MSG_RESULT([$grub_cv_cc_ld_no_pie])
nopie_possible=no
if test "x$grub_cv_cc_ld_no_pie" = xyes ; then
nopie_possible=yes
fi
])
AC_DEFUN([grub_CHECK_NO_PIE_ONEWORD],
[AC_MSG_CHECKING([whether linker accepts -nopie])
AC_CACHE_VAL(grub_cv_cc_ld_no_pie_oneword,
[save_LDFLAGS="$LDFLAGS"
LDFLAGS="$LDFLAGS -nopie -nostdlib -Werror"
AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[]])],
[grub_cv_cc_ld_no_pie_oneword=yes],
[grub_cv_cc_ld_no_pie_oneword=no])
LDFLAGS="$save_LDFLAGS"
])
AC_MSG_RESULT([$grub_cv_cc_ld_no_pie_oneword])
nopie_oneword_possible=no
if test "x$grub_cv_cc_ld_no_pie_oneword" = xyes ; then
nopie_oneword_possible=yes
fi
])
dnl Check if the C compiler supports `-fPIC'.
AC_DEFUN([grub_CHECK_PIC],[
[# Position independent executable.

View File

@@ -1,12 +1,16 @@
/* on x86 old clang doesn't support .code16
newer clang supports it but creates 6-byte jumps instead of 3-byte ones
which makes us go over boot sector size. */
which makes us go over boot sector size.
Starting with 3.9 clang emits 3-byte jumps but still creates 8-bytes movl
instead of 5-bytes, so code overflows into data. */
.code16
jmp far
.org 4
jmp nearer
.org 6
movl nearer, %ebx
.org 11
.space 100
nearer:
.space 200

View File

@@ -41,7 +41,7 @@ CCASFLAGS_KERNEL = $(CCASFLAGS_CPU) $(CCASFLAGS_PLATFORM)
STRIPFLAGS_KERNEL = -R .rel.dyn -R .reginfo -R .note -R .comment -R .drectve -R .note.gnu.gold-version -R .MIPS.abiflags -R .ARM.exidx
CFLAGS_MODULE = $(CFLAGS_PLATFORM) -ffreestanding
LDFLAGS_MODULE = $(LDFLAGS_PLATFORM) -nostdlib $(TARGET_LDFLAGS_OLDMAGIC) -Wl,-r,-d
LDFLAGS_MODULE = $(LDFLAGS_PLATFORM) -nostdlib $(TARGET_LDFLAGS_OLDMAGIC) $(TARGET_INCREMENTAL_LINK)
CPPFLAGS_MODULE = $(CPPFLAGS_CPU) $(CPPFLAGS_PLATFORM)
CCASFLAGS_MODULE = $(CCASFLAGS_CPU) $(CCASFLAGS_PLATFORM)
@@ -86,11 +86,9 @@ 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_FDT_LIST)
$(CPPFLAGS_TERMINAL_LIST) $(CPPFLAGS_COMMAND_LIST)
# Define these variables to calm down automake

View File

@@ -31,7 +31,7 @@ dnl (such as BUILD_CC, BUILD_CFLAGS, etc.) for the build type and variables
dnl with the prefix "TARGET_" (such as TARGET_CC, TARGET_CFLAGS, etc.) are
dnl used for the target type. See INSTALL for full list of variables.
AC_INIT([GRUB],[2.02~beta2],[bug-grub@gnu.org])
AC_INIT([GRUB],[2.03],[bug-grub@gnu.org])
AC_CONFIG_AUX_DIR([build-aux])
@@ -167,7 +167,6 @@ case "$target_cpu"-"$platform" in
mipsel-fuloong) platform=loongson ;;
mipsel-loongson) ;;
arm-uboot) ;;
arm-coreboot) ;;
arm-efi) ;;
arm64-efi) ;;
*-emu) ;;
@@ -374,7 +373,10 @@ case "$host_os" in
;;
*)
AC_CHECK_SIZEOF(off_t)
test x"$ac_cv_sizeof_off_t" = x8 || AC_MSG_ERROR([Large file support is required]);;
if test x"$ac_cv_sizeof_off_t" != x8 ; then
AC_CHECK_SIZEOF(off64_t)
test x"$ac_cv_sizeof_off64_t" = x8 || AC_MSG_ERROR([Large file support is required])
fi;;
esac
if test x$USE_NLS = xno; then
@@ -389,7 +391,15 @@ fi
# Check for functions and headers.
AC_CHECK_FUNCS(posix_memalign memalign getextmntent)
AC_CHECK_HEADERS(sys/param.h sys/mount.h sys/mnttab.h sys/mkdev.h limits.h)
AC_CHECK_HEADERS(sys/param.h sys/mount.h sys/mnttab.h limits.h)
# glibc 2.25 still includes sys/sysmacros.h in sys/types.h but emits deprecation
# warning which causes compilation failure later with -Werror. So use -Werror here
# as well to force proper sys/sysmacros.h detection.
SAVED_CFLAGS="$CFLAGS"
CFLAGS="$HOST_CFLAGS -Werror"
AC_HEADER_MAJOR
CFLAGS="$SAVED_CFLAGS"
AC_CHECK_MEMBERS([struct statfs.f_fstypename],,,[$ac_includes_default
#include <sys/param.h>
@@ -449,6 +459,16 @@ case "$build_os" in
esac
AC_SUBST(BUILD_EXEEXT)
# In some build environments like termux /bin/sh is not a valid
# shebang. Use $SHELL instead if it's executable and /bin/sh isn't
BUILD_SHEBANG=/bin/sh
for she in /bin/sh "$SHELL"; do
if test -x "$she" ; then
BUILD_SHEBANG="$she"
fi
done
AC_SUBST(BUILD_SHEBANG)
# For gnulib.
gl_INIT
@@ -883,6 +903,25 @@ if test x"$target_cpu" = xsparc64 ; then
TARGET_LDFLAGS="$TARGET_LDFLAGS $grub_cv_target_cc_mno_relax"
fi
AC_CACHE_CHECK([for incremental link options], grub_cv_target_cc_incremental_link, [
grub_cv_target_cc_incremental_link=no
for cand in "-Wl,-r,-d" "-static -Wl,-r,-d"; do
#AC_LINK_IFELSE doesn't handle non-executable output correctly
echo > conftest_inclink.c
if $TARGET_CC -o /dev/null $TARGET_CFLAGS $TARGET_CPPFLAGS $TARGET_LDFLAGS -nostdlib -Werror $cand conftest_inclink.c >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD; then
grub_cv_target_cc_incremental_link="$cand"
break
fi
done
])
if test x"$grub_cv_target_cc_incremental_link" = xno ; then
AC_MSG_ERROR([could not find incremental link options])
fi
TARGET_INCREMENTAL_LINK="$grub_cv_target_cc_incremental_link"
AC_SUBST(TARGET_INCREMENTAL_LINK)
# By default, GCC 4.4 generates .eh_frame sections containing unwind
# information in some cases where it previously did not. GRUB doesn't need
# these and they just use up vital space. Restore the old compiler
@@ -1145,14 +1184,23 @@ if test "$target_cpu"-"$platform" = x86_64-efi; then
fi
if test "x$target_cpu" = xarm; then
AC_CACHE_CHECK([whether option -mlong-calls works], grub_cv_cc_mlong_calls, [
CFLAGS="$TARGET_CFLAGS -mlong-calls -Werror"
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])],
[grub_cv_cc_mlong_calls=yes],
[grub_cv_cc_mlong_calls=no])
AC_CACHE_CHECK([for options to disable movt and movw], grub_cv_target_cc_mno_movt, [
grub_cv_target_cc_mno_movt=no
for cand in "-mno-movt" \
"-mllvm -arm-use-movt=0"; do
if test x"$grub_cv_target_cc_mno_movt" != xno ; then
break
fi
CFLAGS="$TARGET_CFLAGS $cand -Werror"
CPPFLAGS="$TARGET_CPPFLAGS"
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])],
[grub_cv_target_cc_mno_movt="$cand"], [])
done
])
if test "x$grub_cv_cc_mlong_calls" = xyes; then
TARGET_CFLAGS="$TARGET_CFLAGS -mlong-calls"
if test x"$grub_cv_target_cc_mno_movt" != xno ; then
# A trick so that clang doesn't see it on link stage
TARGET_CPPFLAGS="$TARGET_CPPFLAGS $grub_cv_target_cc_mno_movt"
fi
AC_CACHE_CHECK([whether option -mthumb-interwork works], grub_cv_cc_mthumb_interwork, [
CFLAGS="$TARGET_CFLAGS -mthumb-interwork -Werror"
@@ -1185,13 +1233,25 @@ CFLAGS="$TARGET_CFLAGS"
# Position independent executable.
grub_CHECK_PIE
grub_CHECK_NO_PIE
grub_CHECK_NO_PIE_ONEWORD
[# Need that, because some distributions ship compilers that include
# `-fPIE' in the default specs.
# `-fPIE' or '-fpie' and '-pie' in the default specs.
if [ x"$pie_possible" = xyes ]; then
TARGET_CFLAGS="$TARGET_CFLAGS -fno-PIE"
TARGET_CFLAGS="$TARGET_CFLAGS -fno-PIE -fno-pie"
fi
if [ x"$link_nopie_needed" = xyes ] || [ x"$pie_possible" = xyes ]; then
if [ x"$nopie_possible" = xyes ]; then
TARGET_LDFLAGS="$TARGET_LDFLAGS -no-pie"
fi
if [ x"$nopie_oneword_possible" = xyes ]; then
TARGET_LDFLAGS="$TARGET_LDFLAGS -nopie"
fi
fi]
CFLAGS="$TARGET_CFLAGS"
LDFLAGS="$TARGET_LDFLAGS"
# Position independent executable.
grub_CHECK_PIC
@@ -1200,9 +1260,12 @@ grub_CHECK_PIC
# and reload $gp in every function.
# GCC implements it using symbol __gnu_local_gp in non-PIC as well.
# However with clang we need PIC for this reloading to happen.
# With arm64 we need relocations that are in some way representable in
# PE as we need to support arm64-efi. Without -fPIC clang generates
# movk's which aren't representable.
# Since default varies across dictributions use either -fPIC or -fno-PIC
# explicitly.
if ( test x$target_cpu = xmips || test x$target_cpu = xmipsel ) && test "x$grub_cv_cc_target_clang" = xyes ; then
if ( test x$target_cpu = xmips || test x$target_cpu = xmipsel || test x$target_cpu = xarm64 ) && test "x$grub_cv_cc_target_clang" = xyes ; then
TARGET_CFLAGS="$TARGET_CFLAGS -fPIC"
elif [ x"$pic_possible" = xyes ]; then
TARGET_CFLAGS="$TARGET_CFLAGS -fno-PIC"
@@ -1555,11 +1618,11 @@ if test x"$grub_build_mkfont_excuse" = x ; then
else
enable_build_grub_mkfont=no
fi
if test x"$enable_build_grub_mkfont" = xno && ( test "x$platform" = xqemu || test "x$platform" = xloongson || test "x$platform" = xqemu_mips || test "x$target_cpu"-"$platform" = xpowerpc-ieee1275 || test "x$platform" = xcoreboot ); then
if test x"$enable_build_grub_mkfont" = xno && ( test "x$platform" = xqemu || test "x$platform" = xloongson || test "x$platform" = xqemu_mips || test "x$platform" = xcoreboot ); then
if test x"$grub_build_mkfont_excuse" = x ; then
AC_MSG_ERROR([qemu, powerpc-ieee1275, coreboot and loongson ports needs build-time grub-mkfont])
AC_MSG_ERROR([qemu, coreboot and loongson ports need build-time grub-mkfont])
else
AC_MSG_ERROR([qemu, powerpc-ieee1275, coreboot and loongson ports needs build-time grub-mkfont ($grub_build_mkfont_excuse)])
AC_MSG_ERROR([qemu, coreboot and loongson ports need build-time grub-mkfont ($grub_build_mkfont_excuse)])
fi
fi
@@ -1629,11 +1692,11 @@ if test x"$enable_build_grub_mkfont" = xno ; then
FONT_SOURCE=
fi
if test "x$FONT_SOURCE" = x && ( test "x$platform" = xqemu || test "x$platform" = xloongson || test "x$platform" = xqemu_mips || test "x$target_cpu"-"$platform" = xpowerpc-ieee1275 || test "x$platform" = xcoreboot ); then
if test "x$FONT_SOURCE" = x && ( test "x$platform" = xqemu || test "x$platform" = xloongson || test "x$platform" = xqemu_mips || test "x$platform" = xcoreboot ); then
if test x"$grub_build_mkfont_excuse" = x ; then
AC_MSG_ERROR([qemu, powerpc-ieee1275, coreboot and loongson ports need unifont])
AC_MSG_ERROR([qemu, coreboot and loongson ports need unifont])
else
AC_MSG_ERROR([qemu, powerpc-ieee1275, coreboot and loongson ports need unifont ($grub_build_mkfont_excuse)])
AC_MSG_ERROR([qemu, coreboot and loongson ports need unifont ($grub_build_mkfont_excuse)])
fi
fi
@@ -1873,7 +1936,6 @@ 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

@@ -2446,6 +2446,10 @@ The boot file name provided by DHCP. Read-only.
The name of the DHCP server responsible for these boot parameters.
Read-only.
@item net_@var{<interface>}_next_server
The IP address of the next (usually, TFTP) server provided by DHCP.
Read-only.
@item net_default_interface
Initially set to name of network interface that was used to load grub.
Read-write, although setting it affects only interpretation of
@@ -3062,6 +3066,7 @@ These variables have special meaning to GRUB.
* net_@var{<interface>}_hostname::
* net_@var{<interface>}_ip::
* net_@var{<interface>}_mac::
* net_@var{<interface>}_next_server::
* net_@var{<interface>}_rootpath::
* net_default_interface::
* net_default_ip::
@@ -3213,9 +3218,10 @@ source for more details.
@node default
@subsection default
If this variable is set, it identifies a menu entry that should be selected
by default, possibly after a timeout (@pxref{timeout}). The entry may be
identified by number or by id.
If this variable is set, it identifies a menu entry that should be
selected by default, possibly after a timeout (@pxref{timeout}). The
entry may be identified by number (starting from 0 at each level of
the hierarchy), by title, or by id.
For example, if you have:
@@ -3231,24 +3237,26 @@ then you can make this the default using:
default=example-gnu-linux
@end example
If the entry is in a submenu, then it must be identified using the titles of
each of the submenus starting from the top level followed by the number or
title of the menu entry itself, separated by @samp{>}. For example, take
the following menu structure:
If the entry is in a submenu, then it must be identified using the
number, title, or id of each of the submenus starting from the top
level, followed by the number, title, or id of the menu entry itself,
with each element separated by @samp{>}. For example, take the
following menu structure:
@example
Submenu 1
Menu Entry 1
Menu Entry 2
Submenu 2
Submenu 3
Menu Entry 3
Menu Entry 4
Menu Entry 5
GNU/Hurd --id gnu-hurd
Standard Boot --id=gnu-hurd-std
Rescue shell --id=gnu-hurd-rescue
Other platforms --id=other
Minix --id=minix
Version 3.4.0 --id=minix-3.4.0
Version 3.3.0 --id=minix-3.3.0
GRUB Invaders --id=grub-invaders
@end example
``Menu Entry 3'' would then be identified as
@samp{Submenu 2>Submenu 3>Menu Entry 3}.
The more recent release of Minix would then be identified as
@samp{Other platforms>Minix>Version 3.4.0}, or as @samp{1>0>0}, or as
@samp{other>minix>minix-3.4.0}.
This variable is often set by @samp{GRUB_DEFAULT} (@pxref{Simple
configuration}), @command{grub-set-default}, or @command{grub-reboot}.
@@ -3422,6 +3430,12 @@ The default is the value of @samp{color_normal} (@pxref{color_normal}).
@xref{Network}.
@node net_@var{<interface>}_next_server
@subsection net_@var{<interface>}_next_server
@xref{Network}.
@node net_@var{<interface>}_rootpath
@subsection net_@var{<interface>}_rootpath

View File

@@ -31,8 +31,7 @@ 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",
"arm_coreboot"]
"mips_qemu_mips", "arm_uboot", "arm_efi", "arm64_efi" ]
GROUPS = {}
@@ -45,7 +44,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", "arm_coreboot" ]
GROUPS["arm"] = [ "arm_uboot", "arm_efi" ]
GROUPS["arm64"] = [ "arm64_efi" ]
# Groups based on firmware
@@ -53,7 +52,6 @@ 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")
@@ -63,10 +61,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"] + ["arm_coreboot"]
GROUPS["usb"] = GROUPS["pci"]
# If gfxterm is main output console integrate it into kernel
GROUPS["videoinkernel"] = ["mips_loongson", "i386_coreboot", "arm_coreboot" ]
GROUPS["videoinkernel"] = ["mips_loongson", "i386_coreboot" ]
GROUPS["videomodules"] = GRUB_PLATFORMS[:];
for i in GROUPS["videoinkernel"]: GROUPS["videomodules"].remove(i)

View File

@@ -112,7 +112,7 @@ endif
if COND_i386_coreboot
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/tsc.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/coreboot/lbio.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/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
@@ -239,20 +239,6 @@ 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
@@ -292,7 +278,7 @@ BUILT_SOURCES += symlist.h
symlist.c: symlist.h gensymlist.sh
$(TARGET_CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS_KERNEL) $(CPPFLAGS) -DGRUB_SYMBOL_GENERATOR=1 symlist.h > symlist.p || (rm -f symlist.p; exit 1)
cat symlist.p | /bin/sh $(srcdir)/gensymlist.sh $(top_builddir)/config.h $(KERNEL_HEADER_FILES) >$@ || (rm -f $@; exit 1)
cat symlist.p | $(SHELL) $(srcdir)/gensymlist.sh $(top_builddir)/config.h $(KERNEL_HEADER_FILES) >$@ || (rm -f $@; exit 1)
rm -f symlist.p
CLEANFILES += symlist.c
BUILT_SOURCES += symlist.c
@@ -372,16 +358,6 @@ 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

@@ -49,20 +49,20 @@ kernel = {
nostrip = emu;
emu_ldflags = '-Wl,-r,-d';
i386_efi_ldflags = '-Wl,-r,-d';
emu_ldflags = '$(TARGET_INCREMENTAL_LINK)';
i386_efi_ldflags = '$(TARGET_INCREMENTAL_LINK)';
i386_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version';
x86_64_efi_ldflags = '-Wl,-r,-d';
x86_64_efi_ldflags = '$(TARGET_INCREMENTAL_LINK)';
x86_64_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version';
ia64_efi_cflags = '-fno-builtin -fpic -minline-int-divide-max-throughput';
ia64_efi_ldflags = '-Wl,-r,-d';
ia64_efi_ldflags = '$(TARGET_INCREMENTAL_LINK)';
ia64_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version';
arm_efi_ldflags = '-Wl,-r,-d';
arm_efi_ldflags = '$(TARGET_INCREMENTAL_LINK)';
arm_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version';
arm64_efi_ldflags = '-Wl,-r,-d';
arm64_efi_ldflags = '$(TARGET_INCREMENTAL_LINK)';
arm64_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version -R .eh_frame';
i386_pc_ldflags = '$(TARGET_IMG_LDFLAGS)';
@@ -90,10 +90,8 @@ 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,-r,-d';
arm_uboot_ldflags = '$(TARGET_INCREMENTAL_LINK)';
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;
@@ -107,8 +105,7 @@ 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/startup.S;
arm_coreboot_startup = kern/arm/startup.S;
arm_uboot_startup = kern/arm/uboot/startup.S;
arm_efi_startup = kern/arm/efi/startup.S;
arm64_efi_startup = kern/arm64/efi/startup.S;
@@ -152,20 +149,6 @@ 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;
@@ -181,7 +164,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;
coreboot = video/coreboot/cbfb.c;
i386_coreboot = video/i386/coreboot/cbfb.c;
efi = disk/efi/efidisk.c;
efi = kern/efi/efi.c;
@@ -229,8 +212,10 @@ kernel = {
arm_efi = kern/arm/efi/init.c;
arm_efi = kern/arm/efi/misc.c;
arm_efi = kern/efi/fdt.c;
arm64_efi = kern/arm64/efi/init.c;
arm64_efi = kern/efi/fdt.c;
i386_pc = kern/i386/pc/init.c;
i386_pc = kern/i386/pc/mmap.c;
@@ -240,9 +225,8 @@ kernel = {
i386_qemu = kern/vga_init.c;
i386_qemu = kern/i386/qemu/mmap.c;
coreboot = kern/coreboot/mmap.c;
i386_coreboot = kern/i386/coreboot/mmap.c;
i386_coreboot = kern/i386/coreboot/cbtable.c;
arm_coreboot = kern/arm/coreboot/cbtable.c;
i386_multiboot = kern/i386/multiboot_mmap.c;
@@ -254,7 +238,6 @@ 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;
@@ -270,7 +253,6 @@ 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;
@@ -592,17 +574,7 @@ 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 = {
@@ -782,7 +754,6 @@ module = {
enable = arm_efi;
enable = arm64_efi;
enable = arm_uboot;
enable = arm_coreboot;
};
module = {
@@ -850,7 +821,7 @@ module = {
common = commands/gptsync.c;
};
/*module = {
module = {
name = halt;
nopc = commands/halt.c;
i386_pc = commands/i386/pc/halt.c;
@@ -885,7 +856,7 @@ module = {
xen = lib/xen/reboot.c;
uboot = lib/uboot/reboot.c;
common = commands/reboot.c;
};*/
};
module = {
name = hashsum;
@@ -1562,6 +1533,7 @@ module = {
i386_xen = lib/i386/xen/relocator.S;
x86_64_xen = lib/x86_64/xen/relocator.S;
xen = lib/i386/relocator_common_c.c;
x86_64_efi = lib/x86_64/efi/relocator.c;
extra_dist = lib/i386/relocator_common.S;
extra_dist = kern/powerpc/cache_flush.S;
@@ -1577,7 +1549,6 @@ 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;
@@ -1898,7 +1869,6 @@ module = {
module = {
name = at_keyboard;
common = term/at_keyboard.c;
common = term/ps2.c;
enable = x86;
};
@@ -1991,6 +1961,11 @@ module = {
common = tests/example_functional_test.c;
};
module = {
name = strtoull_test;
common = tests/strtoull_test.c;
};
module = {
name = setjmp_test;
common = tests/setjmp_test.c;

View File

@@ -1,255 +0,0 @@
/*
* 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

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

File diff suppressed because it is too large Load Diff

View File

@@ -1,45 +0,0 @@
/* 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

@@ -1,208 +0,0 @@
/* 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,10 +22,13 @@
#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+");
@@ -36,6 +39,8 @@ GRUB_MOD_LICENSE ("GPLv3+");
* - is not supporting interrupt transfers
*/
#define GRUB_EHCI_PCI_SBRN_REG 0x60
/* Capability registers offsets */
enum
{
@@ -49,6 +54,7 @@ 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 */
@@ -79,6 +85,13 @@ 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
{
@@ -442,10 +455,9 @@ grub_ehci_reset (struct grub_ehci *e)
sync_all_caches (e);
grub_dprintf ("ehci", "reset\n");
grub_ehci_oper_write32 (e, GRUB_EHCI_COMMAND,
GRUB_EHCI_CMD_HC_RESET);
GRUB_EHCI_CMD_HC_RESET
| grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND));
/* Ensure command is written */
grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND);
/* XXX: How long time could take reset of HC ? */
@@ -461,24 +473,116 @@ grub_ehci_reset (struct grub_ehci *e)
}
/* PCI iteration function... */
void
grub_ehci_init_device (volatile void *regs)
static int
grub_ehci_pci_iter (grub_pci_device_t dev, grub_pci_id_t pciid,
void *data __attribute__ ((unused)))
{
grub_uint8_t release;
grub_uint32_t class_code;
grub_uint32_t interf;
grub_uint32_t subclass;
grub_uint32_t class;
grub_uint32_t base, base_h;
struct grub_ehci *e;
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;
return 1;
e->framelist_chunk = NULL;
e->td_chunk = NULL;
e->qh_chunk = NULL;
e->iobase_ehcc = regs;
e->iobase_ehcc = grub_pci_device_map_range (dev,
(base & GRUB_EHCI_ADDR_MEM_MASK),
0x100);
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: iobase of EHCC: %08x\n",
(base & GRUB_EHCI_ADDR_MEM_MASK));
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: CAPLEN: %02x\n",
grub_ehci_ehcc_read8 (e, GRUB_EHCI_EHCC_CAPLEN));
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: VERSION: %04x\n",
@@ -494,7 +598,7 @@ grub_ehci_init_device (volatile void *regs)
if (caplen & (sizeof (grub_uint32_t) - 1))
{
grub_dprintf ("ehci", "Unaligned caplen\n");
return;
return 0;
}
e->iobase = ((volatile grub_uint32_t *) e->iobase_ehcc
+ (caplen / sizeof (grub_uint32_t)));
@@ -505,7 +609,7 @@ grub_ehci_init_device (volatile void *regs)
grub_dprintf ("ehci",
"EHCI grub_ehci_pci_iter: iobase of oper. regs: %08x\n",
(grub_addr_t) e->iobase_ehcc + caplen);
(base & GRUB_EHCI_ADDR_MEM_MASK) + 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",
@@ -521,6 +625,10 @@ grub_ehci_init_device (volatile void *regs)
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 */
@@ -624,6 +732,65 @@ grub_ehci_init_device (volatile void *regs)
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 */
@@ -697,7 +864,7 @@ grub_ehci_init_device (volatile void *regs)
grub_dprintf ("ehci",
"EHCI grub_ehci_pci_iter: iobase of oper. regs: %08x\n",
(grub_addr_t) regs);
(base & GRUB_EHCI_ADDR_MEM_MASK));
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",
@@ -713,7 +880,7 @@ grub_ehci_init_device (volatile void *regs)
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: CONFIG_FLAG: %08x\n",
grub_ehci_oper_read32 (e, GRUB_EHCI_CONFIG_FLAG));
return;
return 0;
fail:
if (e)
@@ -727,7 +894,7 @@ fail:
}
grub_free (e);
return;
return 0;
}
static int
@@ -1579,8 +1746,8 @@ grub_ehci_hubports (grub_usb_controller_t dev)
}
static grub_usb_err_t
grub_ehci_reset_port (grub_usb_controller_t dev,
unsigned int port)
grub_ehci_portstatus (grub_usb_controller_t dev,
unsigned int port, unsigned int enable)
{
struct grub_ehci *e = (struct grub_ehci *) dev->data;
grub_uint64_t endtime;
@@ -1602,6 +1769,14 @@ grub_ehci_reset_port (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);
@@ -1716,6 +1891,12 @@ 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)
{
@@ -1802,7 +1983,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,
.reset_port = grub_ehci_reset_port,
.portstatus = grub_ehci_portstatus,
.detect_dev = grub_ehci_detect_dev,
/* estimated max. count of TDs for one bulk transfer */
.max_bulk_tds = GRUB_EHCI_N_TD * 3 / 4
@@ -1816,7 +1997,7 @@ GRUB_MOD_INIT (ehci)
grub_stop_disk_firmware ();
grub_boot_time ("Initing EHCI hardware");
grub_ehci_pci_scan ();
grub_ehci_inithw ();
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_rest_port (grub_usb_controller_t dev,
unsigned int port)
grub_ohci_portstatus (grub_usb_controller_t dev,
unsigned int port, unsigned int enable)
{
struct grub_ohci *o = (struct grub_ohci *) dev->data;
grub_uint64_t endtime;
@@ -1233,6 +1233,22 @@ grub_ohci_rest_port (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).
@@ -1422,7 +1438,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,
.reset_port = grub_ohci_reset_port,
.portstatus = grub_ohci_portstatus,
.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_reset_port (grub_usb_controller_t dev,
unsigned int port)
grub_uhci_portstatus (grub_usb_controller_t dev,
unsigned int port, unsigned int enable)
{
struct grub_uhci *u = (struct grub_uhci *) dev->data;
int reg;
@@ -731,6 +731,21 @@ grub_uhci_reset_port (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;
@@ -828,7 +843,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,
.reset_port = grub_uhci_reset_port,
.portstatus = grub_uhci_portstatus,
.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");
/* Reset port. */
err = hub->controller->dev->reset_port (hub->controller, portno);
/* Enable the port. */
err = hub->controller->dev->portstatus (hub->controller, portno, 1);
if (err)
return;
hub->controller->dev->pending_reset = grub_get_time_ms () + 5000;

View File

@@ -18,7 +18,7 @@
*/
#include <grub/dl.h>
#include <grub/dma.h>
#include <grub/pci.h>
#include <grub/mm.h>
#include <grub/misc.h>
#include <grub/usb.h>

View File

@@ -761,10 +761,10 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args)
struct grub_efi_guid acpi = GRUB_EFI_ACPI_TABLE_GUID;
struct grub_efi_guid acpi20 = GRUB_EFI_ACPI_20_TABLE_GUID;
grub_efi_system_table->boot_services->install_configuration_table
(&acpi20, grub_acpi_get_rsdpv2 ());
grub_efi_system_table->boot_services->install_configuration_table
(&acpi, grub_acpi_get_rsdpv1 ());
efi_call_2 (grub_efi_system_table->boot_services->install_configuration_table,
&acpi20, grub_acpi_get_rsdpv2 ());
efi_call_2 (grub_efi_system_table->boot_services->install_configuration_table,
&acpi, grub_acpi_get_rsdpv1 ());
}
#endif

View File

@@ -140,10 +140,13 @@ grub_cmd_cat (grub_extcmd_context_t ctxt, int argc, char **args)
grub_setcolorstate (GRUB_TERM_COLOR_STANDARD);
}
grub_setcolorstate (GRUB_TERM_COLOR_HIGHLIGHT);
for (j = 0; j < utcount; j++)
grub_printf ("<%x>", (unsigned int) utbuf[j]);
grub_setcolorstate (GRUB_TERM_COLOR_STANDARD);
if (utcount)
{
grub_setcolorstate (GRUB_TERM_COLOR_HIGHLIGHT);
for (j = 0; j < utcount; j++)
grub_printf ("<%x>", (unsigned int) utbuf[j]);
grub_setcolorstate (GRUB_TERM_COLOR_STANDARD);
}
grub_xputs ("\n");
grub_refresh ();

View File

@@ -328,6 +328,7 @@ grub_cmd_hdparm (grub_extcmd_context_t ctxt, int argc, char **args)
ata = ((struct grub_scsi *) disk->data)->data;
break;
}
/* FALLTHROUGH */
default:
grub_disk_close (disk);
return grub_error (GRUB_ERR_IO, "not an ATA device");

View File

@@ -20,7 +20,7 @@
#include <grub/misc.h>
#include <grub/command.h>
#include <grub/i18n.h>
#include <grub/coreboot/lbio.h>
#include <grub/i386/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/coreboot/lbio.h>
#include <grub/i386/coreboot/lbio.h>
#include <grub/i386/tsc.h>
GRUB_MOD_LICENSE ("GPLv3+");

View File

@@ -517,7 +517,7 @@ grub_cmd_legacy_initrd (struct grub_command *mycmd __attribute__ ((unused)),
#endif
);
return cmd->func (cmd, argc, args);
return cmd->func (cmd, argc ? 1 : 0, args);
}
if (kernel_type == MULTIBOOT)
{

View File

@@ -79,6 +79,7 @@ get_uuid (const char *name, char **uuid, int getnative)
case GRUB_DISK_DEVICE_XEN:
if (getnative)
break;
/* FALLTHROUGH */
/* Virtual disks. */
/* GRUB dynamically generated files. */

View File

@@ -64,7 +64,7 @@ iterate_device (const char *name, void *data)
/* Skip floppy drives when requested. */
if (ctx->no_floppy &&
name[0] == 'f' && name[1] == 'd' && name[2] >= '0' && name[2] <= '9')
return 0;
return 1;
#ifdef DO_SEARCH_FS_UUID
#define compare_fn grub_strcasecmp

View File

@@ -282,6 +282,7 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
break;
case GRUB_CRYPTODISK_MODE_IV_PLAIN64:
iv[1] = grub_cpu_to_le32 (sector >> 32);
/* FALLTHROUGH */
case GRUB_CRYPTODISK_MODE_IV_PLAIN:
iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF);
break;

View File

@@ -80,6 +80,15 @@ make_devices (void)
/* This should not happen... Why? */
continue;
/* iPXE adds stub Block IO protocol to loaded image device handle. It is
completely non-functional and simply returns an error for every method.
So attempt to detect and skip it. Magic number is literal "iPXE" and
check block size as well */
/* FIXME: shoud we close it? We do not do it elsewhere */
if (bio->media && bio->media->media_id == 0x69505845U &&
bio->media->block_size == 1)
continue;
d = grub_malloc (sizeof (*d));
if (! d)
{
@@ -215,7 +224,7 @@ name_devices (struct grub_efidisk_data *devices)
{
case GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE:
is_hard_drive = 1;
/* Fall through by intention. */
/* Intentionally fall through. */
case GRUB_EFI_CDROM_DEVICE_PATH_SUBTYPE:
{
struct grub_efidisk_data *parent, *parent2;
@@ -493,8 +502,15 @@ grub_efidisk_open (const char *name, struct grub_disk *disk)
m = d->block_io->media;
/* FIXME: Probably it is better to store the block size in the disk,
and total sectors should be replaced with total blocks. */
grub_dprintf ("efidisk", "m = %p, last block = %llx, block size = %x\n",
m, (unsigned long long) m->last_block, m->block_size);
grub_dprintf ("efidisk",
"m = %p, last block = %llx, block size = %x, io align = %x\n",
m, (unsigned long long) m->last_block, m->block_size,
m->io_align);
/* Ensure required buffer alignment is a power of two (or is zero). */
if (m->io_align & (m->io_align - 1))
return grub_error (GRUB_ERR_IO, "invalid buffer alignment %d", m->io_align);
disk->total_sectors = m->last_block + 1;
/* Don't increase this value due to bug in some EFI. */
disk->max_agglomerate = 0xa0000 >> (GRUB_DISK_CACHE_BITS + GRUB_DISK_SECTOR_BITS);
@@ -524,15 +540,42 @@ grub_efidisk_readwrite (struct grub_disk *disk, grub_disk_addr_t sector,
{
struct grub_efidisk_data *d;
grub_efi_block_io_t *bio;
grub_efi_status_t status;
grub_size_t io_align, num_bytes;
char *aligned_buf;
d = disk->data;
bio = d->block_io;
return efi_call_5 ((wr ? bio->write_blocks : bio->read_blocks), bio,
bio->media->media_id,
(grub_efi_uint64_t) sector,
(grub_efi_uintn_t) size << disk->log_sector_size,
buf);
/* Set alignment to 1 if 0 specified */
io_align = bio->media->io_align ? bio->media->io_align : 1;
num_bytes = size << disk->log_sector_size;
if ((grub_addr_t) buf & (io_align - 1))
{
aligned_buf = grub_memalign (io_align, num_bytes);
if (! aligned_buf)
return GRUB_EFI_OUT_OF_RESOURCES;
if (wr)
grub_memcpy (aligned_buf, buf, num_bytes);
}
else
{
aligned_buf = buf;
}
status = efi_call_5 ((wr ? bio->write_blocks : bio->read_blocks), bio,
bio->media->media_id, (grub_efi_uint64_t) sector,
(grub_efi_uintn_t) num_bytes, aligned_buf);
if ((grub_addr_t) buf & (io_align - 1))
{
if (!wr)
grub_memcpy (buf, aligned_buf, num_bytes);
grub_free (aligned_buf);
}
return status;
}
static grub_err_t
@@ -547,7 +590,9 @@ grub_efidisk_read (struct grub_disk *disk, grub_disk_addr_t sector,
status = grub_efidisk_readwrite (disk, sector, size, buf, 0);
if (status != GRUB_EFI_SUCCESS)
if (status == GRUB_EFI_NO_MEDIA)
return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("no media in `%s'"), disk->name);
else if (status != GRUB_EFI_SUCCESS)
return grub_error (GRUB_ERR_READ_ERROR,
N_("failure reading sector 0x%llx from `%s'"),
(unsigned long long) sector,
@@ -568,7 +613,9 @@ grub_efidisk_write (struct grub_disk *disk, grub_disk_addr_t sector,
status = grub_efidisk_readwrite (disk, sector, size, (char *) buf, 1);
if (status != GRUB_EFI_SUCCESS)
if (status == GRUB_EFI_NO_MEDIA)
return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("no media in `%s'"), disk->name);
else if (status != GRUB_EFI_SUCCESS)
return grub_error (GRUB_ERR_WRITE_ERROR,
N_("failure writing sector 0x%llx to `%s'"),
(unsigned long long) sector, disk->name);

View File

@@ -417,6 +417,7 @@ fill_hook (grub_uint64_t addr, grub_uint64_t size, grub_memory_type_t type,
default:
grub_dprintf ("efiemu",
"Unknown memory type %d. Assuming unusable\n", type);
/* FALLTHROUGH */
case GRUB_MEMORY_RESERVED:
return grub_efiemu_add_to_mmap (addr, size,
GRUB_EFI_UNUSABLE_MEMORY);

View File

@@ -227,11 +227,11 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data,
static grub_err_t
read_sblock (grub_disk_t disk, struct grub_btrfs_superblock *sb)
{
struct grub_btrfs_superblock sblock;
unsigned i;
grub_err_t err = GRUB_ERR_NONE;
for (i = 0; i < ARRAY_SIZE (superblock_sectors); i++)
{
struct grub_btrfs_superblock sblock;
/* Don't try additional superblocks beyond device size. */
if (i && (grub_le_to_cpu64 (sblock.this_device.size)
>> GRUB_DISK_SECTOR_BITS) <= superblock_sectors[i])

View File

@@ -189,7 +189,11 @@ struct grub_fshelp_node {
struct grub_fat_data *data;
grub_uint8_t attr;
grub_ssize_t file_size;
#ifndef MODE_EXFAT
grub_uint32_t file_size;
#else
grub_uint64_t file_size;
#endif
grub_uint32_t file_cluster;
grub_uint32_t cur_cluster_num;
grub_uint32_t cur_cluster;

View File

@@ -750,19 +750,15 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir,
if (dir->data->joliet && !ctx.filename)
{
char *oldname, *semicolon;
char *semicolon;
oldname = name;
ctx.filename = grub_iso9660_convert_string
((grub_uint8_t *) oldname, dirent.namelen >> 1);
((grub_uint8_t *) name, dirent.namelen >> 1);
semicolon = grub_strrchr (ctx.filename, ';');
if (semicolon)
*semicolon = '\0';
if (ctx.filename_alloc)
grub_free (oldname);
ctx.filename_alloc = 1;
}

View File

@@ -823,7 +823,12 @@ direct_read (struct grub_squash_data *data,
curread = data->blksz - boff;
if (curread > len)
curread = len;
if (!(ino->block_sizes[i]
if (!ino->block_sizes[i])
{
/* Sparse block */
grub_memset (buf, '\0', curread);
}
else if (!(ino->block_sizes[i]
& grub_cpu_to_le32_compile_time (SQUASH_BLOCK_UNCOMPRESSED)))
{
char *block;
@@ -873,36 +878,57 @@ direct_read (struct grub_squash_data *data,
static grub_ssize_t
grub_squash_read_data (struct grub_squash_data *data,
struct grub_squash_cache_inode *ino,
grub_off_t off, char *buf, grub_size_t len)
grub_squash_read (grub_file_t file, char *buf, grub_size_t len)
{
struct grub_squash_data *data = file->data;
struct grub_squash_cache_inode *ino = &data->ino;
grub_off_t off = file->offset;
grub_err_t err;
grub_uint64_t a = 0, b;
grub_uint64_t a, b;
grub_uint32_t fragment = 0;
int compressed = 0;
struct grub_squash_frag_desc frag;
grub_off_t direct_len;
grub_uint64_t mask = grub_le_to_cpu32 (data->sb.block_size) - 1;
grub_size_t orig_len = len;
switch (ino->ino.type)
{
case grub_cpu_to_le16_compile_time (SQUASH_TYPE_LONG_REGULAR):
a = grub_le_to_cpu64 (ino->ino.long_file.chunk);
fragment = grub_le_to_cpu32 (ino->ino.long_file.fragment);
break;
case grub_cpu_to_le16_compile_time (SQUASH_TYPE_REGULAR):
a = grub_le_to_cpu32 (ino->ino.file.chunk);
fragment = grub_le_to_cpu32 (ino->ino.file.fragment);
break;
}
if (fragment == 0xffffffff)
return direct_read (data, ino, off, buf, len);
/* Squash may pack file tail as fragment. So read initial part directly and
get tail from fragments */
direct_len = fragment == 0xffffffff ? file->size : file->size & ~mask;
if (off < direct_len)
{
grub_size_t read_len = direct_len - off;
grub_ssize_t res;
if (read_len > len)
read_len = len;
res = direct_read (data, ino, off, buf, read_len);
if ((grub_size_t) res != read_len)
return -1; /* FIXME: is short read possible here? */
len -= read_len;
if (!len)
return read_len;
buf += read_len;
off = 0;
}
else
off -= direct_len;
err = read_chunk (data, &frag, sizeof (frag),
data->fragments, sizeof (frag) * fragment);
if (err)
return -1;
a += grub_le_to_cpu64 (frag.offset);
a = grub_le_to_cpu64 (frag.offset);
compressed = !(frag.size & grub_cpu_to_le32_compile_time (SQUASH_BLOCK_UNCOMPRESSED));
if (ino->ino.type == grub_cpu_to_le16_compile_time (SQUASH_TYPE_LONG_REGULAR))
b = grub_le_to_cpu32 (ino->ino.long_file.offset) + off;
@@ -943,16 +969,7 @@ grub_squash_read_data (struct grub_squash_data *data,
if (err)
return -1;
}
return len;
}
static grub_ssize_t
grub_squash_read (grub_file_t file, char *buf, grub_size_t len)
{
struct grub_squash_data *data = file->data;
return grub_squash_read_data (data, &data->ino,
file->offset, buf, len);
return orig_len;
}
static grub_err_t

View File

@@ -76,8 +76,13 @@ GRUB_MOD_LICENSE ("GPLv3+");
/* incompat feature flags */
#define XFS_SB_FEAT_INCOMPAT_FTYPE (1 << 0) /* filetype in dirent */
#define XFS_SB_FEAT_INCOMPAT_SPINODES (1 << 1) /* sparse inode chunks */
#define XFS_SB_FEAT_INCOMPAT_META_UUID (1 << 2) /* metadata UUID */
/* We do not currently verify metadata UUID so it is safe to read such filesystem */
#define XFS_SB_FEAT_INCOMPAT_SUPPORTED \
(XFS_SB_FEAT_INCOMPAT_FTYPE)
(XFS_SB_FEAT_INCOMPAT_FTYPE | \
XFS_SB_FEAT_INCOMPAT_META_UUID)
struct grub_xfs_sblock
{

View File

@@ -336,6 +336,7 @@ grub_gdb_trap (int trap_no)
/* sAA..AA: Step one instruction from AA..AA(optional). */
case 's':
stepping = 1;
/* FALLTHROUGH */
/* cAA..AA: Continue at address AA..AA(optional). */
case 'c':

View File

@@ -1,4 +1,4 @@
#! /bin/sh
#! @BUILD_SHEBANG@
set -e
# Copyright (C) 2010 Free Software Foundation, Inc.
@@ -79,9 +79,9 @@ else
for dep in $deps; do echo "char moddep_$dep[] __attribute__ ((section(\"_moddeps, _moddeps\"))) = \"$dep\";" >>$t2; done
if test -n "$deps"; then
@TARGET_CC@ @TARGET_LDFLAGS@ -ffreestanding -nostdlib -o $tmpfile2 $t1 $t2 $tmpfile -Wl,-r,-d
@TARGET_CC@ @TARGET_LDFLAGS@ @TARGET_INCREMENTAL_LINK@ -ffreestanding -nostdlib -o $tmpfile2 $t1 $t2 $tmpfile
else
@TARGET_CC@ @TARGET_LDFLAGS@ -ffreestanding -nostdlib -o $tmpfile2 $t1 $tmpfile -Wl,-r,-d
@TARGET_CC@ @TARGET_LDFLAGS@ @TARGET_INCREMENTAL_LINK@ -ffreestanding -nostdlib -o $tmpfile2 $t1 $tmpfile
fi
rm -f $t1 $t2 $tmpfile
mv $tmpfile2 $tmpfile
@@ -94,6 +94,6 @@ else
rm -f $tmpfile.bin
fi
if test x@platform@ != xemu; then
./build-grub-module-verifier@BUILD_EXEEXT@ $tmpfile @target_cpu@
./build-grub-module-verifier@BUILD_EXEEXT@ $tmpfile @target_cpu@ @platform@
fi
mv $tmpfile $outfile

View File

@@ -1,4 +1,4 @@
#! /bin/sh
#! @BUILD_SHEBANG@
set -e
# Copyright (C) 2010 Free Software Foundation, Inc.

View File

@@ -0,0 +1,14 @@
diff --git grub-core/gnulib/regexec.c grub-core/gnulib/regexec.c
index f632cd4..a7776f0 100644
--- grub-core/gnulib/regexec.c
+++ grub-core/gnulib/regexec.c
@@ -4099,6 +4099,9 @@ check_node_accept (const re_match_context_t *mctx, const re_token_t *node,
case OP_UTF8_PERIOD:
if (ch >= ASCII_CHARS)
return false;
+#if defined __GNUC__ && __GNUC__ >= 7
+ __attribute__ ((fallthrough));
+#endif
/* FALLTHROUGH */
#endif
case OP_PERIOD:

View File

@@ -4099,6 +4099,9 @@ check_node_accept (const re_match_context_t *mctx, const re_token_t *node,
case OP_UTF8_PERIOD:
if (ch >= ASCII_CHARS)
return false;
#if defined __GNUC__ && __GNUC__ >= 7
__attribute__ ((fallthrough));
#endif
/* FALLTHROUGH */
#endif
case OP_PERIOD:

View File

@@ -29,8 +29,6 @@ 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,
@@ -254,38 +252,6 @@ 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,18 +33,6 @@
# 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
@@ -135,4 +123,4 @@ clean_invalidate_dcache:
pop {r4-r12, lr}
bx lr
#include "cache.S"
#include "cache.S"

View File

@@ -1,74 +0,0 @@
/*
* 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

@@ -1,44 +0,0 @@
/*
* 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

@@ -1,59 +0,0 @@
/*
* 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

@@ -1,169 +0,0 @@
/*
* 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

@@ -1,101 +0,0 @@
/*
* 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

@@ -173,6 +173,8 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr,
sym_addr += grub_arm_thm_call_get_offset ((grub_uint16_t *) target);
grub_dprintf ("dl", " sym_addr = 0x%08x\n", sym_addr);
if (ELF_ST_TYPE (sym->st_info) != STT_FUNC)
sym_addr |= 1;
offset = sym_addr - (grub_uint32_t) target;
@@ -227,13 +229,16 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr,
sym_addr += grub_arm_thm_jump19_get_offset ((grub_uint16_t *) target);
if (ELF_ST_TYPE (sym->st_info) != STT_FUNC)
sym_addr |= 1;
offset = sym_addr - (grub_uint32_t) target;
if (!grub_arm_thm_jump19_check_offset (offset)
|| !(sym_addr & 1))
{
struct trampoline_thumb *tp = mod->gotptr;
mod->gotptr = tp + 1;
struct trampoline_thumb *tp = mod->trampptr;
mod->trampptr = tp + 1;
grub_memcpy (tp->template, thumb_template, sizeof (tp->template));
tp->neg_addr = -sym_addr - 4;
offset = ((grub_uint8_t *) tp - (grub_uint8_t *) target - 4) | 1;

View File

@@ -1,70 +0,0 @@
/* 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

@@ -24,7 +24,6 @@
* 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:
*
@@ -87,7 +86,7 @@ FUNCTION(codestart)
@ Stack pointer used as start address for signature probing
mov r12, sp
adr sp, entry_state
push {r0-r12,lr} @ store U-Boot context (sp in r12)
push {r1-r12,lr} @ store U-Boot context (sp in r12)
adr r1, _start
ldr r0, bss_start_ptr @ src
@@ -128,8 +127,6 @@ reloc_done:
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
@@ -139,7 +136,6 @@ reloc_done:
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
@@ -157,21 +153,69 @@ reloc_done:
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/coreboot context stack space
VARIABLE(grub_arm_saved_registers)
.long 0 @ r0
@ U-boot context stack space
entry_state_end:
VARIABLE(grub_uboot_machine_type)
.long 0 @ r1
VARIABLE(grub_uboot_boot_data)
.long 0 @ r2
.long 0 @ r3
.long 0 @ r4
.long 0 @ r5
.long 0 @ r6
.long 0 @ r7
.long 0 @ r8
.long 0 @ r9
.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 @ r10
.long 0 @ r11
.long 0 @ sp
VARIABLE(grub_uboot_search_hint)@ U-Boot stack pointer -
.long 0 @ also API signature address hint.
.long 0 @ lr
entry_state:
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

View File

@@ -1,73 +0,0 @@
/*
* 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

@@ -25,14 +25,9 @@
#include <grub/i18n.h>
#include <grub/cpu/reloc.h>
struct trampoline
{
#define LDR 0x58000050
#define BR 0xd61f0200
grub_uint32_t ldr; /* ldr x16, 8 */
grub_uint32_t br; /* br x16 */
grub_uint64_t addr;
};
/*
* Check if EHDR is a valid ELF header.
@@ -53,42 +48,6 @@ grub_arch_dl_check_header (void *ehdr)
#pragma GCC diagnostic ignored "-Wcast-align"
grub_err_t
grub_arch_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp,
grub_size_t *got)
{
const Elf_Ehdr *e = ehdr;
const Elf_Shdr *s;
unsigned i;
*tramp = 0;
*got = 0;
for (i = 0, s = (const Elf_Shdr *) ((grub_addr_t) e + e->e_shoff);
i < e->e_shnum;
i++, s = (const Elf_Shdr *) ((grub_addr_t) s + e->e_shentsize))
if (s->sh_type == SHT_REL || s->sh_type == SHT_RELA)
{
const Elf_Rel *rel, *max;
for (rel = (const Elf_Rel *) ((grub_addr_t) e + s->sh_offset),
max = rel + s->sh_size / s->sh_entsize;
rel < max;
rel = (const Elf_Rel *) ((grub_addr_t) rel + s->sh_entsize))
switch (ELF_R_TYPE (rel->r_info))
{
case R_AARCH64_CALL26:
case R_AARCH64_JUMP26:
{
*tramp += sizeof (struct trampoline);
break;
}
}
}
return GRUB_ERR_NONE;
}
/*
* Unified function for both REL and RELA
*/
@@ -97,6 +56,7 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr,
Elf_Shdr *s, grub_dl_segment_t seg)
{
Elf_Rel *rel, *max;
unsigned unmatched_adr_got_page = 0;
for (rel = (Elf_Rel *) ((char *) ehdr + s->sh_offset),
max = (Elf_Rel *) ((char *) rel + s->sh_size);
@@ -145,7 +105,7 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr,
if (!grub_arm_64_check_xxxx26_offset (offset))
{
struct trampoline *tp = mod->trampptr;
struct grub_arm64_trampoline *tp = mod->trampptr;
mod->trampptr = tp + 1;
tp->ldr = LDR;
tp->br = BR;
@@ -160,6 +120,56 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr,
grub_arm64_set_xxxx26_offset (place, offset);
}
break;
case R_AARCH64_PREL32:
{
grub_int64_t value;
Elf64_Word *addr32 = place;
value = ((grub_int32_t) *addr32) + sym_addr -
(Elf64_Xword) (grub_addr_t) seg->addr - rel->r_offset;
if (value != (grub_int32_t) value)
return grub_error (GRUB_ERR_BAD_MODULE, "relocation out of range");
grub_dprintf("dl", " reloc_prel32 %p => 0x%016llx\n",
place, (unsigned long long) sym_addr);
*addr32 = value;
}
break;
case R_AARCH64_ADR_GOT_PAGE:
{
grub_uint64_t *gp = mod->gotptr;
Elf_Rela *rel2;
grub_int64_t gpoffset = ((grub_uint64_t) gp & ~0xfffULL) - (((grub_uint64_t) place) & ~0xfffULL);
*gp = (grub_uint64_t) sym_addr;
mod->gotptr = gp + 1;
unmatched_adr_got_page++;
grub_dprintf("dl", " reloc_got %p => 0x%016llx (0x%016llx)\n",
place, (unsigned long long) sym_addr, (unsigned long long) gp);
if (!grub_arm64_check_hi21_signed (gpoffset))
return grub_error (GRUB_ERR_BAD_MODULE,
"HI21 out of range");
grub_arm64_set_hi21(place, gpoffset);
for (rel2 = (Elf_Rela *) ((char *) rel + s->sh_entsize);
rel2 < (Elf_Rela *) max;
rel2 = (Elf_Rela *) ((char *) rel2 + s->sh_entsize))
if (ELF_R_SYM (rel2->r_info)
== ELF_R_SYM (rel->r_info)
&& ((Elf_Rela *) rel)->r_addend == rel2->r_addend
&& ELF_R_TYPE (rel2->r_info) == R_AARCH64_LD64_GOT_LO12_NC)
{
grub_arm64_set_abs_lo12_ldst64 ((void *) ((grub_addr_t) seg->addr + rel2->r_offset),
(grub_uint64_t)gp);
break;
}
if (rel2 >= (Elf_Rela *) max)
return grub_error (GRUB_ERR_BAD_MODULE,
"ADR_GOT_PAGE without matching LD64_GOT_LO12_NC");
}
break;
case R_AARCH64_LD64_GOT_LO12_NC:
if (unmatched_adr_got_page == 0)
return grub_error (GRUB_ERR_BAD_MODULE,
"LD64_GOT_LO12_NC without matching ADR_GOT_PAGE");
unmatched_adr_got_page--;
break;
case R_AARCH64_ADR_PREL_PG_HI21:
{
grub_int64_t offset = (sym_addr & ~0xfffULL) - (((grub_uint64_t) place) & ~0xfffULL);

View File

@@ -93,3 +93,42 @@ grub_arm64_set_abs_lo12_ldst64 (grub_uint32_t *place, grub_int64_t target)
*place &= insmask;
*place |= grub_cpu_to_le32 (target << 7) & ~insmask;
}
#pragma GCC diagnostic ignored "-Wcast-align"
grub_err_t
grub_arm64_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp,
grub_size_t *got)
{
const Elf64_Ehdr *e = ehdr;
const Elf64_Shdr *s;
unsigned i;
*tramp = 0;
*got = 0;
for (i = 0, s = (Elf64_Shdr *) ((char *) e + grub_le_to_cpu64 (e->e_shoff));
i < grub_le_to_cpu16 (e->e_shnum);
i++, s = (Elf64_Shdr *) ((char *) s + grub_le_to_cpu16 (e->e_shentsize)))
if (s->sh_type == grub_cpu_to_le32_compile_time (SHT_REL)
|| s->sh_type == grub_cpu_to_le32_compile_time (SHT_RELA))
{
const Elf64_Rela *rel, *max;
for (rel = (Elf64_Rela *) ((char *) e + grub_le_to_cpu64 (s->sh_offset)),
max = (const Elf64_Rela *) ((char *) rel + grub_le_to_cpu64 (s->sh_size));
rel < max; rel = (const Elf64_Rela *) ((char *) rel + grub_le_to_cpu64 (s->sh_entsize)))
switch (ELF64_R_TYPE (rel->r_info))
{
case R_AARCH64_CALL26:
case R_AARCH64_JUMP26:
*tramp += sizeof (struct grub_arm64_trampoline);
break;
case R_AARCH64_ADR_GOT_PAGE:
*got += 8;
break;
}
}
return GRUB_ERR_NONE;
}

View File

@@ -366,6 +366,9 @@ grub_efi_get_filename (grub_efi_device_path_t *dp0)
len = ((GRUB_EFI_DEVICE_PATH_LENGTH (dp) - 4)
/ sizeof (grub_efi_char16_t));
fp = (grub_efi_file_path_device_path_t *) dp;
/* According to EFI spec Path Name is NULL terminated */
while (len > 0 && fp->path_name[len - 1] == 0)
len--;
p = (char *) grub_utf16_to_utf8 ((unsigned char *) p, fp->path_name, len);
}

43
grub-core/kern/efi/fdt.c Normal file
View File

@@ -0,0 +1,43 @@
/* fdt.c - EFI Flattened Device Tree interaction */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2006,2007 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/efi/efi.h>
#include <grub/mm.h>
void *
grub_efi_get_firmware_fdt (void)
{
grub_efi_configuration_table_t *tables;
grub_efi_guid_t fdt_guid = GRUB_EFI_DEVICE_TREE_GUID;
void *firmware_fdt = NULL;
unsigned int i;
/* Look for FDT in UEFI config tables. */
tables = grub_efi_system_table->configuration_table;
for (i = 0; i < grub_efi_system_table->num_table_entries; i++)
if (grub_memcmp (&tables[i].vendor_guid, &fdt_guid, sizeof (fdt_guid)) == 0)
{
firmware_fdt = tables[i].vendor_table;
grub_dprintf ("linux", "found registered FDT @ %p\n", firmware_fdt);
break;
}
return firmware_fdt;
}

View File

@@ -59,10 +59,13 @@ grub_machine_get_bootlocation (char **device, char **path)
if (!image)
return;
*device = grub_efidisk_get_device_name (image->device_handle);
*path = grub_efi_get_filename (image->file_path);
if (!*device && grub_efi_net_config)
grub_efi_net_config (image->device_handle, device, path);
{
grub_efi_net_config (image->device_handle, device, path);
return;
}
*path = grub_efi_get_filename (image->file_path);
if (*path)
{
/* Get the directory. */

View File

@@ -63,6 +63,7 @@ void
grub_reboot (void)
{
longjmp (main_env, 1);
grub_fatal ("longjmp failed");
}
void

View File

@@ -127,6 +127,7 @@ xasprintf (const char *fmt, ...)
va_start (ap, fmt);
result = grub_xvasprintf (fmt, ap);
va_end (ap);
if (!result)
grub_util_error ("%s", _("out of memory"));

View File

@@ -17,7 +17,7 @@
*/
#include <grub/i386/coreboot/memory.h>
#include <grub/coreboot/lbio.h>
#include <grub/i386/coreboot/lbio.h>
#include <grub/types.h>
#include <grub/err.h>
#include <grub/misc.h>

View File

@@ -16,8 +16,8 @@
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/memory.h>
#include <grub/coreboot/lbio.h>
#include <grub/machine/memory.h>
#include <grub/machine/lbio.h>
#include <grub/types.h>
#include <grub/err.h>
#include <grub/misc.h>
@@ -49,7 +49,6 @@ 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)
@@ -76,7 +75,6 @@ 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

@@ -104,6 +104,9 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr,
case R_IA64_PCREL64LSB:
*(grub_uint64_t *) addr += value - addr;
break;
case R_IA64_GPREL64I:
grub_ia64_set_immu64 (addr, value - (grub_addr_t) mod->base);
break;
case R_IA64_GPREL22:
if ((value - (grub_addr_t) mod->base) & ~MASK20)
return grub_error (GRUB_ERR_BAD_MODULE,
@@ -116,6 +119,7 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr,
case R_IA64_LTOFF22:
if (ELF_ST_TYPE (sym->st_info) == STT_FUNC)
value = *(grub_uint64_t *) sym->st_value + rel->r_addend;
/* Fallthrough. */
case R_IA64_LTOFF_FPTR22:
{
grub_uint64_t *gpptr = mod->gotptr;

View File

@@ -30,6 +30,40 @@
#define MASK20 ((1 << 20) - 1)
#define MASK3 (~(grub_addr_t) 3)
void
grub_ia64_set_immu64 (grub_addr_t addr, grub_uint64_t val)
{
/* Copied from binutils. */
grub_uint64_t *ptr = ((grub_uint64_t *) (addr & MASK3));
grub_uint64_t t0, t1;
t0 = grub_le_to_cpu64 (ptr[0]);
t1 = grub_le_to_cpu64 (ptr[1]);
/* tmpl/s: bits 0.. 5 in t0
slot 0: bits 5..45 in t0
slot 1: bits 46..63 in t0, bits 0..22 in t1
slot 2: bits 23..63 in t1 */
/* First, clear the bits that form the 64 bit constant. */
t0 &= ~(0x3ffffLL << 46);
t1 &= ~(0x7fffffLL
| (( (0x07fLL << 13) | (0x1ffLL << 27)
| (0x01fLL << 22) | (0x001LL << 21)
| (0x001LL << 36)) << 23));
t0 |= ((val >> 22) & 0x03ffffLL) << 46; /* 18 lsbs of imm41 */
t1 |= ((val >> 40) & 0x7fffffLL) << 0; /* 23 msbs of imm41 */
t1 |= ( (((val >> 0) & 0x07f) << 13) /* imm7b */
| (((val >> 7) & 0x1ff) << 27) /* imm9d */
| (((val >> 16) & 0x01f) << 22) /* imm5c */
| (((val >> 21) & 0x001) << 21) /* ic */
| (((val >> 63) & 0x001) << 36)) << 23; /* i */
ptr[0] = t0;
ptr[1] = t1;
}
void
grub_ia64_add_value_to_slot_20b (grub_addr_t addr, grub_uint32_t value)
{
@@ -182,11 +216,11 @@ grub_ia64_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp,
i++, s = (Elf64_Shdr *) ((char *) s + grub_le_to_cpu16 (e->e_shentsize)))
if (s->sh_type == grub_cpu_to_le32_compile_time (SHT_RELA))
{
Elf64_Rela *rel, *max;
const Elf64_Rela *rel, *max;
for (rel = (Elf64_Rela *) ((char *) e + grub_le_to_cpu64 (s->sh_offset)),
max = rel + grub_le_to_cpu64 (s->sh_size) / grub_le_to_cpu64 (s->sh_entsize);
rel < max; rel++)
max = (const Elf64_Rela *) ((char *) rel + grub_le_to_cpu64 (s->sh_size));
rel < max; rel = (const Elf64_Rela *) ((char *) rel + grub_le_to_cpu64 (s->sh_entsize)))
switch (ELF64_R_TYPE (grub_le_to_cpu64 (rel->r_info)))
{
case R_IA64_PCREL21B:

View File

@@ -25,7 +25,7 @@ grub_machine_mmap_iterate (grub_memory_hook_t hook, void *hook_data)
{
grub_ieee1275_phandle_t root;
grub_ieee1275_phandle_t memory;
grub_uint32_t available[32];
grub_uint32_t available[128];
grub_ssize_t available_size;
grub_uint32_t address_cells = 1;
grub_uint32_t size_cells = 1;
@@ -49,6 +49,9 @@ grub_machine_mmap_iterate (grub_memory_hook_t hook, void *hook_data)
sizeof available, &available_size))
return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
"couldn't examine /memory/available property");
if (available_size < 0 || (grub_size_t) available_size > sizeof (available))
return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
"/memory response buffer exceeded");
if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_BROKEN_ADDRESS_CELLS))
{

View File

@@ -236,6 +236,7 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr,
sym_value &= 0xffff0000;
*(grub_uint16_t *) addr = 0;
}
/* Fallthrough. */
case R_MIPS_CALL16:
{
grub_uint32_t *gpptr = mod->gotptr;

View File

@@ -391,12 +391,13 @@ grub_strtoull (const char *str, char **end, int base)
unsigned long digit;
digit = grub_tolower (*str) - '0';
if (digit > 9)
{
digit += '0' - 'a' + 10;
if (digit >= (unsigned long) base)
break;
}
if (digit >= 'a' - '0')
digit += '0' - 'a' + 10;
else if (digit > 9)
break;
if (digit >= (unsigned long) base)
break;
found = 1;

View File

@@ -159,6 +159,7 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr,
if (value >> 32)
return grub_error (GRUB_ERR_BAD_MODULE,
"address out of 32 bits range");
/* Fallthrough. */
case R_SPARC_LM22:
*addr = (*addr & 0xFFC00000) | ((value >> 10) & 0x3FFFFF);
break;

View File

@@ -36,14 +36,30 @@
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,13 +39,48 @@
* 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_unaligned_uint64_t *ptr = (void *) ((grub_addr_t) fdt
+ grub_fdt_get_off_mem_rsvmap (fdt));
grub_uint64_t *ptr = (void *) ((grub_addr_t) fdt
+ grub_fdt_get_off_mem_rsvmap (fdt));
do
{
size += 2 * sizeof(*ptr);
if (!ptr[0].val && !ptr[1].val)
if (!*ptr && !*(ptr + 1))
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 (const void *fdt, unsigned int nodeoffset,
static grub_uint32_t *find_prop (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 (const 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 (const void *fdt)
int grub_fdt_check_header_nosize (void *fdt)
{
if (((grub_addr_t) fdt & 0x3) || (grub_fdt_get_magic (fdt) != FDT_MAGIC)
if (((grub_addr_t) fdt & 0x7) || (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 (const void *fdt)
return 0;
}
int grub_fdt_check_header (const void *fdt, unsigned int size)
int grub_fdt_check_header (void *fdt, unsigned int size)
{
if (size < sizeof (grub_fdt_header_t)
|| (grub_fdt_get_totalsize (fdt) > size)
@@ -295,29 +295,41 @@ int grub_fdt_check_header (const void *fdt, unsigned int size)
return 0;
}
static const grub_uint32_t *
advance_token (const void *fdt, const grub_uint32_t *token, const grub_uint32_t *end, int skip_current)
/* Find a direct sub-node of a given parent node. */
int grub_fdt_find_subnode (const void *fdt, unsigned int parentoffset,
const char *name)
{
for (; token < end; skip_current = 0)
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)
{
switch (grub_be_to_cpu32 (*token))
switch (grub_be_to_cpu32(*token))
{
case FDT_BEGIN_NODE:
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;
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;
case FDT_PROP:
/* Skip property token and following data (len, nameoff and property
value). */
if (token >= end - 1)
return 0;
return -1;
token += prop_entry_size(grub_be_to_cpu32(*(token + 1)))
/ sizeof(*token);
break;
@@ -325,74 +337,10 @@ advance_token (const void *fdt, const grub_uint32_t *token, const grub_uint32_t
token++;
break;
default:
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;
return -1;
}
int grub_fdt_add_subnode (void *fdt, unsigned int parentoffset,
@@ -411,24 +359,6 @@ 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)
{

View File

@@ -73,6 +73,22 @@ VARIABLE(grub_relocator64_rsp)
movq %rax, %rsp
#ifdef GRUB_MACHINE_EFI
jmp LOCAL(skip_efi_stack_align)
/*
* Here is grub_relocator64_efi_start() entry point. Most of the
* code below is shared between grub_relocator64_efi_start()
* and grub_relocator64_start().
*
* Think twice before changing anything there!!!
*/
VARIABLE(grub_relocator64_efi_start)
/* Align the stack as UEFI spec requires. */
andq $~15, %rsp
LOCAL(skip_efi_stack_align):
#endif
/* mov imm64, %rax */
.byte 0x48
.byte 0xb8
@@ -120,6 +136,11 @@ LOCAL(jump_addr):
VARIABLE(grub_relocator64_rip)
.quad 0
#ifdef GRUB_MACHINE_EFI
/* Here grub_relocator64_efi_start() ends. Ufff... */
VARIABLE(grub_relocator64_efi_end)
#endif
#ifndef __x86_64__
.p2align 4
LOCAL(gdt):

View File

@@ -16,6 +16,8 @@
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/i386/memory.h>
#include <grub/i386/types.h>
#include <grub/symbol.h>
#include <grub/xen.h>
@@ -23,78 +25,86 @@
VARIABLE(grub_relocator_xen_remap_start)
LOCAL(base):
/* mov imm32, %ebx */
/* Remap the remapper to it's new address. */
/* mov imm32, %ebx - %ebx: new virtual address of remapper */
.byte 0xbb
VARIABLE(grub_relocator_xen_remapper_virt)
.long 0
/* mov imm32, %ecx */
/* mov imm32, %ecx - %ecx: low part of page table entry */
.byte 0xb9
VARIABLE(grub_relocator_xen_remapper_map)
.long 0
/* mov imm32, %edx */
/* mov imm32, %edx - %edx: high part of page table entry */
.byte 0xba
VARIABLE(grub_relocator_xen_remapper_map_high)
.long 0
movl %ebx, %ebp
movl %ebx, %ebp /* %ebx is clobbered by hypercall */
movl $2, %esi
movl $UVMF_INVLPG, %esi /* esi: flags (inv. single entry) */
movl $__HYPERVISOR_update_va_mapping, %eax
int $0x82
movl %ebp, %ebx
addl $(LOCAL(cont) - LOCAL(base)), %ebx
jmp *%ebx
jmp *%ebx /* Continue with new virtual address */
LOCAL(cont):
xorl %eax, %eax
movl %eax, %ebp
/* Modify mappings of new page tables to be read-only. */
/* mov imm32, %eax */
.byte 0xb8
VARIABLE(grub_relocator_xen_paging_areas_addr)
.long 0
movl %eax, %ebx
1:
movl 0(%ebx), %ebp /* Get start pfn of the current area */
movl GRUB_TARGET_SIZEOF_LONG(%ebx), %ecx /* Get # of pg tables */
testl %ecx, %ecx /* 0 -> last area reached */
jz 3f
addl $(2 * GRUB_TARGET_SIZEOF_LONG), %ebx
movl %ebx, %esp /* Save current area pointer */
2:
movl %ecx, %edi
/* mov imm32, %eax */
.byte 0xb8
VARIABLE(grub_relocator_xen_mfn_list)
.long 0
movl %eax, %edi
movl %ebp, %eax
movl 0(%edi, %eax, 4), %ecx
/* mov imm32, %ebx */
.byte 0xbb
VARIABLE(grub_relocator_xen_paging_start)
.long 0
shll $12, %eax
addl %eax, %ebx
movl 0(%eax, %ebp, 4), %ecx /* mfn */
movl %ebp, %ebx
shll $PAGE_SHIFT, %ebx /* virtual address (1:1 mapping) */
movl %ecx, %edx
shll $12, %ecx
shrl $20, %edx
orl $5, %ecx
movl $2, %esi
shll $PAGE_SHIFT, %ecx /* prepare pte low part */
shrl $(32 - PAGE_SHIFT), %edx /* pte high part */
orl $(GRUB_PAGE_PRESENT | GRUB_PAGE_USER), %ecx /* pte low */
movl $UVMF_INVLPG, %esi
movl $__HYPERVISOR_update_va_mapping, %eax
int $0x82
int $0x82 /* parameters: eax, ebx, ecx, edx, esi */
incl %ebp
/* mov imm32, %ecx */
.byte 0xb9
VARIABLE(grub_relocator_xen_paging_size)
.long 0
cmpl %ebp, %ecx
incl %ebp /* next pfn */
movl %edi, %ecx
ja 1b
loop 2b
mov %esp, %ebx /* restore area poniter */
jmp 1b
3:
/* Switch page tables: pin new L3 pt, load cr3, unpin old L3. */
/* mov imm32, %ebx */
.byte 0xbb
VARIABLE(grub_relocator_xen_mmu_op_addr)
.long 0
movl $3, %ecx
movl $0, %edx
movl $0x7FF0, %esi
movl $3, %ecx /* 3 mmu ops */
movl $0, %edx /* pdone (not used) */
movl $DOMID_SELF, %esi
movl $__HYPERVISOR_mmuext_op, %eax
int $0x82
/* Continue in virtual kernel mapping. */
/* mov imm32, %eax */
.byte 0xb8
VARIABLE(grub_relocator_xen_remap_continue)
@@ -102,6 +112,9 @@ VARIABLE(grub_relocator_xen_remap_continue)
jmp *%eax
VARIABLE(grub_relocator_xen_paging_areas)
.long 0, 0, 0, 0, 0, 0, 0, 0
VARIABLE(grub_relocator_xen_mmu_op)
.space 256
@@ -109,21 +122,22 @@ VARIABLE(grub_relocator_xen_remap_end)
VARIABLE(grub_relocator_xen_start)
/* Unmap old remapper area. */
/* mov imm32, %eax */
.byte 0xb8
VARIABLE(grub_relocator_xen_remapper_virt2)
.long 0
movl %eax, %edi
movl %eax, %ebx
xorl %ecx, %ecx
xorl %ecx, %ecx /* Invalid pte */
xorl %edx, %edx
movl $2, %esi
movl $UVMF_INVLPG, %esi
movl $__HYPERVISOR_update_va_mapping, %eax
int $0x82
/* Prepare registers for starting kernel. */
/* mov imm32, %eax */
.byte 0xb8
VARIABLE(grub_relocator_xen_stack)
@@ -145,6 +159,7 @@ VARIABLE(grub_relocator_xen_start_info)
VARIABLE(grub_relocator_xen_entry_point)
.long 0
/* Now start the new kernel. */
jmp *%eax
VARIABLE(grub_relocator_xen_end)

View File

@@ -0,0 +1,80 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2009 Free Software Foundation, Inc.
* Copyright (C) 2016 Oracle and/or its affiliates. All rights reserved.
*
* 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/misc.h>
#include <grub/types.h>
#include <grub/err.h>
#include <grub/i386/relocator.h>
#include <grub/relocator_private.h>
extern grub_uint64_t grub_relocator64_rax;
extern grub_uint64_t grub_relocator64_rbx;
extern grub_uint64_t grub_relocator64_rcx;
extern grub_uint64_t grub_relocator64_rdx;
extern grub_uint64_t grub_relocator64_rip;
extern grub_uint64_t grub_relocator64_rsi;
extern grub_uint8_t grub_relocator64_efi_start;
extern grub_uint8_t grub_relocator64_efi_end;
#define RELOCATOR_SIZEOF(x) (&grub_relocator##x##_end - &grub_relocator##x##_start)
grub_err_t
grub_relocator64_efi_boot (struct grub_relocator *rel,
struct grub_relocator64_efi_state state)
{
grub_err_t err;
void *relst;
grub_relocator_chunk_t ch;
/*
* 64-bit relocator code may live above 4 GiB quite well.
* However, I do not want ask for problems. Just in case.
*/
err = grub_relocator_alloc_chunk_align (rel, &ch, 0,
0x100000000 - RELOCATOR_SIZEOF (64_efi),
RELOCATOR_SIZEOF (64_efi), 16,
GRUB_RELOCATOR_PREFERENCE_NONE, 1);
if (err)
return err;
/* Do not touch %rsp! It points to EFI created stack. */
grub_relocator64_rax = state.rax;
grub_relocator64_rbx = state.rbx;
grub_relocator64_rcx = state.rcx;
grub_relocator64_rdx = state.rdx;
grub_relocator64_rip = state.rip;
grub_relocator64_rsi = state.rsi;
grub_memmove (get_virtual_current_address (ch), &grub_relocator64_efi_start,
RELOCATOR_SIZEOF (64_efi));
err = grub_relocator_prepare_relocs (rel, get_physical_target_address (ch),
&relst, NULL);
if (err)
return err;
((void (*) (void)) relst) ();
/* Not reached. */
return GRUB_ERR_NONE;
}

View File

@@ -16,95 +16,85 @@
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/x86_64/memory.h>
#include <grub/x86_64/types.h>
#include <grub/symbol.h>
#include <grub/xen.h>
/* Macro to load an imm64 value stored by the C-part into %rax: */
#define MOV_IMM64_RAX(var) .byte 0x48, 0xb8; VARIABLE(var); .quad 0
.p2align 4 /* force 16-byte alignment */
VARIABLE(grub_relocator_xen_remap_start)
LOCAL(base):
/* mov imm64, %rax */
.byte 0x48
.byte 0xb8
VARIABLE(grub_relocator_xen_remapper_virt)
.quad 0
/* Remap the remapper to it's new address. */
MOV_IMM64_RAX(grub_relocator_xen_remapper_virt)
movq %rax, %rdi
movq %rax, %rbx
movq %rax, %rdi /* %rdi: new virtual address of remapper */
movq %rax, %rbx /* Remember new virtual address */
/* mov imm64, %rax */
.byte 0x48
.byte 0xb8
VARIABLE(grub_relocator_xen_remapper_map)
.quad 0
MOV_IMM64_RAX(grub_relocator_xen_remapper_map)
movq %rax, %rsi
movq %rax, %rsi /* %rsi: page table entry */
movq $2, %rdx
movq $UVMF_INVLPG, %rdx /* %rdx: flags (inv. single entry) */
movq $__HYPERVISOR_update_va_mapping, %rax
syscall
syscall /* Do the remap operation */
addq $(LOCAL(cont) - LOCAL(base)), %rbx
jmp *%rbx
jmp *%rbx /* Continue with new virtual address */
LOCAL(cont):
/* mov imm64, %rcx */
.byte 0x48
.byte 0xb9
VARIABLE(grub_relocator_xen_paging_size)
.quad 0
/* Modify mappings of new page tables to be read-only. */
MOV_IMM64_RAX(grub_relocator_xen_mfn_list)
/* mov imm64, %rax */
.byte 0x48
.byte 0xb8
VARIABLE(grub_relocator_xen_paging_start)
.quad 0
movq %rax, %rbx /* %rbx is the base of the p2m list */
leaq EXT_C(grub_relocator_xen_paging_areas) (%rip), %r8
movq %rax, %r12
/* mov imm64, %rax */
.byte 0x48
.byte 0xb8
VARIABLE(grub_relocator_xen_mfn_list)
.quad 0
movq %rax, %rsi
1:
movq 0(%r8), %r12 /* Get start pfn of the current area */
movq GRUB_TARGET_SIZEOF_LONG(%r8), %rcx /* Get # of pg tables */
testq %rcx, %rcx /* 0 -> last area reached */
jz 3f
2:
movq %r12, %rdi
movq %rsi, %rbx
movq 0(%rsi), %rsi
shlq $12, %rsi
orq $5, %rsi
movq $2, %rdx
movq %rcx, %r9
shlq $PAGE_SHIFT, %rdi /* virtual address (1:1 mapping) */
movq (%rbx, %r12, 8), %rsi /* mfn */
shlq $PAGE_SHIFT, %rsi
orq $(GRUB_PAGE_PRESENT | GRUB_PAGE_USER), %rsi /* Build pte */
movq $UVMF_INVLPG, %rdx
movq %rcx, %r9 /* %rcx clobbered by hypercall */
movq $__HYPERVISOR_update_va_mapping, %rax
syscall
movq %r9, %rcx
addq $8, %rbx
addq $4096, %r12
movq %rbx, %rsi
incq %r12 /* next pfn */
loop 1b
loop 2b
leaq LOCAL(mmu_op) (%rip), %rdi
movq $3, %rsi
movq $0, %rdx
movq $0x7FF0, %r10
addq $(2 * GRUB_TARGET_SIZEOF_LONG), %r8 /* next pg table area */
jmp 1b
3:
/* Switch page tables: pin new L4 pt, load cr3, unpin old L4. */
leaq EXT_C(grub_relocator_xen_mmu_op) (%rip), %rdi
movq $3, %rsi /* 3 mmu ops */
movq $0, %rdx /* pdone (not used) */
movq $DOMID_SELF, %r10
movq $__HYPERVISOR_mmuext_op, %rax
syscall
/* mov imm64, %rax */
.byte 0x48
.byte 0xb8
VARIABLE(grub_relocator_xen_remap_continue)
.quad 0
/* Continue in virtual kernel mapping. */
MOV_IMM64_RAX(grub_relocator_xen_remap_continue)
jmp *%rax
LOCAL(mmu_op):
VARIABLE(grub_relocator_xen_paging_areas)
/* array of start, size pairs, size 0 is end marker */
.quad 0, 0, 0, 0, 0, 0, 0, 0
VARIABLE(grub_relocator_xen_mmu_op)
.space 256
@@ -112,46 +102,32 @@ VARIABLE(grub_relocator_xen_remap_end)
VARIABLE(grub_relocator_xen_start)
/* mov imm64, %rax */
.byte 0x48
.byte 0xb8
VARIABLE(grub_relocator_xen_remapper_virt2)
.quad 0
/* Unmap old remapper area. */
MOV_IMM64_RAX(grub_relocator_xen_remapper_virt2)
movq %rax, %rdi
xorq %rax, %rax
xorq %rax, %rax /* Invalid pte */
movq %rax, %rsi
movq $2, %rdx
movq $UVMF_INVLPG, %rdx
movq $__HYPERVISOR_update_va_mapping, %rax
syscall
/* mov imm64, %rax */
.byte 0x48
.byte 0xb8
VARIABLE(grub_relocator_xen_stack)
.quad 0
/* Prepare registers for starting kernel. */
MOV_IMM64_RAX(grub_relocator_xen_stack)
movq %rax, %rsp
/* mov imm64, %rax */
.byte 0x48
.byte 0xb8
VARIABLE(grub_relocator_xen_start_info)
.quad 0
MOV_IMM64_RAX(grub_relocator_xen_start_info)
movq %rax, %rsi
cld
/* mov imm64, %rax */
.byte 0x48
.byte 0xb8
VARIABLE(grub_relocator_xen_entry_point)
.quad 0
MOV_IMM64_RAX(grub_relocator_xen_entry_point)
/* Now start the new kernel. */
jmp *%rax
VARIABLE(grub_relocator_xen_end)

View File

@@ -29,6 +29,11 @@
typedef grub_addr_t grub_xen_reg_t;
struct grub_relocator_xen_paging_area {
grub_xen_reg_t start;
grub_xen_reg_t size;
} GRUB_PACKED;
extern grub_uint8_t grub_relocator_xen_start;
extern grub_uint8_t grub_relocator_xen_end;
extern grub_uint8_t grub_relocator_xen_remap_start;
@@ -36,15 +41,16 @@ extern grub_uint8_t grub_relocator_xen_remap_end;
extern grub_xen_reg_t grub_relocator_xen_stack;
extern grub_xen_reg_t grub_relocator_xen_start_info;
extern grub_xen_reg_t grub_relocator_xen_entry_point;
extern grub_xen_reg_t grub_relocator_xen_paging_start;
extern grub_xen_reg_t grub_relocator_xen_paging_size;
extern grub_xen_reg_t grub_relocator_xen_remapper_virt;
extern grub_xen_reg_t grub_relocator_xen_remapper_virt2;
extern grub_xen_reg_t grub_relocator_xen_remapper_map;
extern grub_xen_reg_t grub_relocator_xen_mfn_list;
extern struct grub_relocator_xen_paging_area
grub_relocator_xen_paging_areas[XEN_MAX_MAPPINGS];
extern grub_xen_reg_t grub_relocator_xen_remap_continue;
#ifdef __i386__
extern grub_xen_reg_t grub_relocator_xen_mmu_op_addr;
extern grub_xen_reg_t grub_relocator_xen_paging_areas_addr;
extern grub_xen_reg_t grub_relocator_xen_remapper_map_high;
#endif
extern mmuext_op_t grub_relocator_xen_mmu_op[3];
@@ -61,6 +67,7 @@ grub_relocator_xen_boot (struct grub_relocator *rel,
{
grub_err_t err;
void *relst;
int i;
grub_relocator_chunk_t ch, ch_tramp;
grub_xen_mfn_t *mfn_list =
(grub_xen_mfn_t *) grub_xen_start_page_addr->mfn_list;
@@ -77,8 +84,11 @@ grub_relocator_xen_boot (struct grub_relocator *rel,
grub_relocator_xen_stack = state.stack;
grub_relocator_xen_start_info = state.start_info;
grub_relocator_xen_entry_point = state.entry_point;
grub_relocator_xen_paging_start = state.paging_start << 12;
grub_relocator_xen_paging_size = state.paging_size;
for (i = 0; i < XEN_MAX_MAPPINGS; i++)
{
grub_relocator_xen_paging_areas[i].start = state.paging_start[i];
grub_relocator_xen_paging_areas[i].size = state.paging_size[i];
}
grub_relocator_xen_remapper_virt = remapper_virt;
grub_relocator_xen_remapper_virt2 = remapper_virt;
grub_relocator_xen_remap_continue = trampoline_virt;
@@ -88,10 +98,12 @@ grub_relocator_xen_boot (struct grub_relocator *rel,
grub_relocator_xen_remapper_map_high = (mfn_list[remapper_pfn] >> 20);
grub_relocator_xen_mmu_op_addr = (char *) &grub_relocator_xen_mmu_op
- (char *) &grub_relocator_xen_remap_start + remapper_virt;
grub_relocator_xen_paging_areas_addr =
(char *) &grub_relocator_xen_paging_areas
- (char *) &grub_relocator_xen_remap_start + remapper_virt;
#endif
grub_relocator_xen_mfn_list = state.mfn_list
+ state.paging_start * sizeof (grub_addr_t);
grub_relocator_xen_mfn_list = state.mfn_list;
grub_memset (grub_relocator_xen_mmu_op, 0,
sizeof (grub_relocator_xen_mmu_op));
@@ -100,9 +112,9 @@ grub_relocator_xen_boot (struct grub_relocator *rel,
#else
grub_relocator_xen_mmu_op[0].cmd = MMUEXT_PIN_L4_TABLE;
#endif
grub_relocator_xen_mmu_op[0].arg1.mfn = mfn_list[state.paging_start];
grub_relocator_xen_mmu_op[0].arg1.mfn = mfn_list[state.paging_start[0]];
grub_relocator_xen_mmu_op[1].cmd = MMUEXT_NEW_BASEPTR;
grub_relocator_xen_mmu_op[1].arg1.mfn = mfn_list[state.paging_start];
grub_relocator_xen_mmu_op[1].arg1.mfn = mfn_list[state.paging_start[0]];
grub_relocator_xen_mmu_op[2].cmd = MMUEXT_UNPIN_TABLE;
grub_relocator_xen_mmu_op[2].arg1.mfn =
mfn_list[grub_xen_start_page_addr->pt_base >> 12];

View File

@@ -1044,6 +1044,8 @@ enum xz_ret xz_dec_lzma2_run(
s->lzma2.sequence = SEQ_LZMA_PREPARE;
/* Fall through */
case SEQ_LZMA_PREPARE:
if (s->lzma2.compressed < RC_INIT_BYTES)
return XZ_DATA_ERROR;
@@ -1054,6 +1056,8 @@ enum xz_ret xz_dec_lzma2_run(
s->lzma2.compressed -= RC_INIT_BYTES;
s->lzma2.sequence = SEQ_LZMA_RUN;
/* Fall through */
case SEQ_LZMA_RUN:
/*
* Set dictionary limit to indicate how much we want

View File

@@ -750,6 +750,7 @@ static enum xz_ret dec_main(struct xz_dec *s, struct xz_buf *b)
s->sequence = SEQ_BLOCK_START;
/* FALLTHROUGH */
case SEQ_BLOCK_START:
/* We need one byte of input to continue. */
if (b->in_pos == b->in_size)
@@ -773,6 +774,7 @@ static enum xz_ret dec_main(struct xz_dec *s, struct xz_buf *b)
s->temp.pos = 0;
s->sequence = SEQ_BLOCK_HEADER;
/* FALLTHROUGH */
case SEQ_BLOCK_HEADER:
if (!fill_temp(s, b))
return XZ_OK;
@@ -783,6 +785,7 @@ static enum xz_ret dec_main(struct xz_dec *s, struct xz_buf *b)
s->sequence = SEQ_BLOCK_UNCOMPRESS;
/* FALLTHROUGH */
case SEQ_BLOCK_UNCOMPRESS:
ret = dec_block(s, b);
if (ret != XZ_STREAM_END)
@@ -810,6 +813,7 @@ static enum xz_ret dec_main(struct xz_dec *s, struct xz_buf *b)
s->sequence = SEQ_BLOCK_CHECK;
/* FALLTHROUGH */
case SEQ_BLOCK_CHECK:
ret = hash_validate(s, b, 0);
if (ret != XZ_STREAM_END)
@@ -858,6 +862,7 @@ static enum xz_ret dec_main(struct xz_dec *s, struct xz_buf *b)
s->sequence = SEQ_INDEX_CRC32;
/* FALLTHROUGH */
case SEQ_INDEX_CRC32:
ret = hash_validate(s, b, 1);
if (ret != XZ_STREAM_END)
@@ -866,6 +871,7 @@ static enum xz_ret dec_main(struct xz_dec *s, struct xz_buf *b)
s->temp.size = STREAM_HEADER_SIZE;
s->sequence = SEQ_STREAM_FOOTER;
/* FALLTHROUGH */
case SEQ_STREAM_FOOTER:
if (!fill_temp(s, b))
return XZ_OK;

View File

@@ -42,7 +42,7 @@ static grub_size_t linux_size;
static char *linux_args;
static grub_uint32_t machine_type;
static const void *current_fdt;
static void *fdt_addr;
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 (const grub_uint32_t *atag)
get_atag_size (grub_uint32_t *atag)
{
const grub_uint32_t *atag0 = atag;
grub_uint32_t *atag0 = atag;
while (atag[0] && atag[1])
atag += atag[0];
return atag - atag0;
@@ -68,11 +68,10 @@ get_atag_size (const grub_uint32_t *atag)
* Merges in command line parameters and sets up initrd addresses.
*/
static grub_err_t
linux_prepare_atag (void *target_atag)
linux_prepare_atag (void)
{
const grub_uint32_t *atag_orig = (const grub_uint32_t *) current_fdt;
grub_uint32_t *tmp_atag, *to;
const grub_uint32_t *from;
grub_uint32_t *atag_orig = (grub_uint32_t *) fdt_addr;
grub_uint32_t *tmp_atag, *from, *to;
grub_size_t tmp_size;
grub_size_t arg_size = grub_strlen (linux_args);
char *cmdline_orig = NULL;
@@ -143,7 +142,7 @@ linux_prepare_atag (void *target_atag)
to += 2;
/* Copy updated FDT to its launch location */
grub_memcpy (target_atag, tmp_atag, sizeof (grub_uint32_t) * (to - tmp_atag));
grub_memcpy (atag_orig, tmp_atag, sizeof (grub_uint32_t) * (to - tmp_atag));
grub_free (tmp_atag);
grub_dprintf ("loader", "ATAG updated for Linux boot\n");
@@ -157,19 +156,19 @@ linux_prepare_atag (void *target_atag)
* Merges in command line parameters and sets up initrd addresses.
*/
static grub_err_t
linux_prepare_fdt (void *target_fdt)
linux_prepare_fdt (void)
{
int node;
int retval;
int tmp_size;
void *tmp_fdt;
tmp_size = grub_fdt_get_totalsize (current_fdt) + 0x100 + grub_strlen (linux_args);
tmp_size = grub_fdt_get_totalsize (fdt_addr) + 0x100 + grub_strlen (linux_args);
tmp_fdt = grub_malloc (tmp_size);
if (!tmp_fdt)
return grub_errno;
grub_memcpy (tmp_fdt, current_fdt, grub_fdt_get_totalsize (current_fdt));
grub_memcpy (tmp_fdt, fdt_addr, grub_fdt_get_totalsize (fdt_addr));
grub_fdt_set_totalsize (tmp_fdt, tmp_size);
/* Find or create '/chosen' node */
@@ -210,7 +209,7 @@ linux_prepare_fdt (void *target_fdt)
}
/* Copy updated FDT to its launch location */
grub_memcpy (target_fdt, tmp_fdt, tmp_size);
grub_memcpy (fdt_addr, tmp_fdt, tmp_size);
grub_free (tmp_fdt);
grub_dprintf ("loader", "FDT updated for Linux boot\n");
@@ -227,17 +226,16 @@ linux_boot (void)
{
kernel_entry_t linuxmain;
int fdt_valid, atag_valid;
void *target_fdt = 0;
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));
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));
grub_dprintf ("loader", "atag: %p, %x, %x, %s, %s\n",
current_fdt,
((const grub_uint16_t *) current_fdt)[3],
*((const grub_uint32_t *) current_fdt),
(const char *) current_fdt,
(const char *) current_fdt + 1);
fdt_addr,
((grub_uint16_t *) fdt_addr)[3],
*((grub_uint32_t *) fdt_addr),
(char *) fdt_addr,
(char *) fdt_addr + 1);
if (!fdt_valid && machine_type == GRUB_ARM_MACHINE_TYPE_FDT)
return grub_error (GRUB_ERR_FILE_NOT_FOUND,
@@ -247,40 +245,23 @@ 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 (target_fdt);
err = linux_prepare_fdt ();
if (err)
return err;
grub_dprintf ("loader", "FDT @ %p\n", target_fdt);
grub_dprintf ("loader", "FDT @ 0x%p\n", fdt_addr);
}
else if (atag_valid)
{
grub_err_t err;
err = linux_prepare_atag (target_fdt);
err = linux_prepare_atag ();
if (err)
return err;
grub_dprintf ("loader", "ATAG @ %p\n", target_fdt);
grub_dprintf ("loader", "ATAG @ 0x%p\n", fdt_addr);
}
grub_dprintf ("loader", "Jumping to Linux...\n");
@@ -304,7 +285,7 @@ linux_boot (void)
grub_arm_disable_caches_mmu ();
linuxmain (0, machine_type, target_fdt);
linuxmain (0, machine_type, fdt_addr);
return grub_error (GRUB_ERR_BAD_OS, "Linux call returned");
}
@@ -463,26 +444,11 @@ fail:
static grub_err_t
load_dtb (grub_file_t dtb, int size)
{
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;
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"));
grub_fdt_set_totalsize (fdt_addr, size);
return GRUB_ERR_NONE;
}
@@ -498,13 +464,42 @@ grub_cmd_devicetree (grub_command_t cmd __attribute__ ((unused)),
dtb = grub_file_open (argv[0]);
if (!dtb)
return grub_errno;
goto out;
size = grub_file_size (dtb);
if (size == 0)
grub_error (GRUB_ERR_BAD_OS, "empty file");
else
load_dtb (dtb, size);
{
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_file_close (dtb);
return grub_errno;
@@ -522,7 +517,7 @@ GRUB_MOD_INIT (linux)
/* TRANSLATORS: DTB stands for device tree blob. */
0, N_("Load DTB file."));
my_mod = mod;
current_fdt = grub_arm_firmware_get_boot_data ();
fdt_addr = (void *) grub_arm_firmware_get_boot_data ();
machine_type = grub_arm_firmware_get_machine_type ();
}

View File

@@ -28,28 +28,6 @@
static void *loaded_fdt;
static void *fdt;
static void *
get_firmware_fdt (void)
{
grub_efi_configuration_table_t *tables;
grub_efi_guid_t fdt_guid = GRUB_EFI_DEVICE_TREE_GUID;
void *firmware_fdt = NULL;
unsigned int i;
/* Look for FDT in UEFI config tables. */
tables = grub_efi_system_table->configuration_table;
for (i = 0; i < grub_efi_system_table->num_table_entries; i++)
if (grub_memcmp (&tables[i].vendor_guid, &fdt_guid, sizeof (fdt_guid)) == 0)
{
firmware_fdt = tables[i].vendor_table;
grub_dprintf ("linux", "found registered FDT @ %p\n", firmware_fdt);
break;
}
return firmware_fdt;
}
void *
grub_fdt_load (grub_size_t additional_size)
{
@@ -65,7 +43,7 @@ grub_fdt_load (grub_size_t additional_size)
if (loaded_fdt)
raw_fdt = loaded_fdt;
else
raw_fdt = get_firmware_fdt();
raw_fdt = grub_efi_get_firmware_fdt();
size =
raw_fdt ? grub_fdt_get_totalsize (raw_fdt) : GRUB_FDT_EMPTY_TREE_SZ;

View File

@@ -122,6 +122,8 @@ copy_file_path (grub_efi_file_path_device_path_t *fp,
if (*p == '/')
*p = '\\';
/* File Path is NULL terminated */
fp->path_name[size++] = '\0';
fp->header.length = size * sizeof (grub_efi_char16_t) + sizeof (*fp);
}
@@ -156,8 +158,10 @@ make_file_path (grub_efi_device_path_t *dp, const char *filename)
d = GRUB_EFI_NEXT_DEVICE_PATH (d);
}
/* File Path is NULL terminated. Allocate space for 2 extra characters */
/* FIXME why we split path in two components? */
file_path = grub_malloc (size
+ ((grub_strlen (dir_start) + 1)
+ ((grub_strlen (dir_start) + 2)
* GRUB_MAX_UTF16_PER_UTF8
* sizeof (grub_efi_char16_t))
+ sizeof (grub_efi_file_path_device_path_t) * 2);

View File

@@ -1889,6 +1889,10 @@ grub_cmd_freebsd_module (grub_command_t cmd __attribute__ ((unused)),
grub_err_t err;
void *src;
if (! grub_loader_is_loaded ())
return grub_error (GRUB_ERR_BAD_ARGUMENT,
N_("you need to load the kernel first"));
if (kernel_type != KERNEL_TYPE_FREEBSD)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no FreeBSD loaded");
@@ -1992,6 +1996,10 @@ grub_cmd_netbsd_module (grub_command_t cmd,
{
grub_uint32_t type;
if (! grub_loader_is_loaded ())
return grub_error (GRUB_ERR_BAD_ARGUMENT,
N_("you need to load the kernel first"));
if (kernel_type != KERNEL_TYPE_NETBSD)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no NetBSD loaded");
@@ -2070,6 +2078,10 @@ grub_cmd_openbsd_ramdisk (grub_command_t cmd __attribute__ ((unused)),
if (argc != 1)
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
if (! grub_loader_is_loaded ())
return grub_error (GRUB_ERR_BAD_ARGUMENT,
N_("you need to load the kernel first"));
if (kernel_type != KERNEL_TYPE_OPENBSD)
return grub_error (GRUB_ERR_BAD_OS, "no kOpenBSD loaded");

View File

@@ -384,6 +384,7 @@ load_chewed (grub_file_t file, const char *filename)
segment.len = 0;
segment.offset = 0;
segment.len = 0;
/* Fallthrough. */
case PAYLOAD_SEGMENT_CODE:
case PAYLOAD_SEGMENT_DATA:
{

View File

@@ -915,8 +915,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
grub_env_set ("gfxpayload", "text");
grub_printf_ (N_("%s is deprecated. "
"Use set gfxpayload=%s before "
"linux command instead.\n"), "text",
argv[i]);
"linux command instead.\n"),
argv[i], "text");
break;
case 1:
@@ -925,8 +925,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
grub_env_set ("gfxpayload", "text");
grub_printf_ (N_("%s is deprecated. "
"Use set gfxpayload=%s before "
"linux command instead.\n"), "text",
argv[i]);
"linux command instead.\n"),
argv[i], "text");
break;
default:
/* Ignore invalid values. */
@@ -984,10 +984,13 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
{
case 'g':
shift += 10;
/* FALLTHROUGH */
case 'm':
shift += 10;
/* FALLTHROUGH */
case 'k':
shift += 10;
/* FALLTHROUGH */
default:
break;
}

View File

@@ -70,9 +70,18 @@ load_kernel (grub_file_t file, const char *filename,
char *buffer, struct multiboot_header *header)
{
grub_err_t err;
mbi_load_data_t mld;
mld.file = file;
mld.filename = filename;
mld.buffer = buffer;
mld.mbi_ver = 1;
mld.relocatable = 0;
mld.avoid_efi_boot_services = 0;
if (grub_multiboot_quirks & GRUB_MULTIBOOT_QUIRK_BAD_KLUDGE)
{
err = grub_multiboot_load_elf (file, filename, buffer);
err = grub_multiboot_load_elf (&mld);
if (err == GRUB_ERR_NONE) {
return GRUB_ERR_NONE;
}
@@ -121,7 +130,7 @@ load_kernel (grub_file_t file, const char *filename,
return GRUB_ERR_NONE;
}
return grub_multiboot_load_elf (file, filename, buffer);
return grub_multiboot_load_elf (&mld);
}
static struct multiboot_header *

File diff suppressed because it is too large Load Diff

View File

@@ -20,12 +20,16 @@
#include <grub/i386/linux.h>
#include <grub/misc.h>
#define XZ_MAGIC "\3757zXZ\0"
grub_elf_t
grub_xen_file (grub_file_t file)
{
grub_elf_t elf;
struct linux_kernel_header lh;
grub_file_t off_file;
grub_uint32_t payload_offset, payload_length;
grub_uint8_t magic[6];
elf = grub_elf_file (file, file->name);
if (elf)
@@ -46,20 +50,36 @@ grub_xen_file (grub_file_t file)
return NULL;
}
if (lh.payload_length < 4)
payload_length = lh.payload_length;
payload_offset = (lh.setup_sects + 1) * 512
+ lh.payload_offset;
if (payload_length < sizeof (magic))
{
grub_error (GRUB_ERR_BAD_OS, "payload too short");
return NULL;
}
grub_dprintf ("xen", "found bzimage payload 0x%llx-0x%llx\n",
(unsigned long long) (lh.setup_sects + 1) * 512
+ lh.payload_offset,
(unsigned long long) lh.payload_length - 4);
(unsigned long long) payload_offset,
(unsigned long long) lh.payload_length);
off_file = grub_file_offset_open (file, (lh.setup_sects + 1) * 512
+ lh.payload_offset,
lh.payload_length - 4);
grub_file_seek (file, payload_offset);
if (grub_file_read (file, &magic, sizeof (magic)) != sizeof (magic))
{
if (!grub_errno)
grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
file->name);
goto fail;
}
/* Kernel suffixes xz payload with their uncompressed size.
Trim it. */
if (grub_memcmp (magic, XZ_MAGIC, sizeof (XZ_MAGIC) - 1) == 0)
payload_length -= 4;
off_file = grub_file_offset_open (file, payload_offset,
payload_length);
if (!off_file)
goto fail;

View File

@@ -18,6 +18,7 @@
#include <grub/xen_file.h>
#include <grub/misc.h>
#include <xen/elfnote.h>
static grub_err_t
parse_xen_guest (grub_elf_t elf, struct grub_xen_file_info *xi,
@@ -26,6 +27,8 @@ parse_xen_guest (grub_elf_t elf, struct grub_xen_file_info *xi,
char *buf;
char *ptr;
int has_paddr = 0;
grub_errno = GRUB_ERR_NONE;
if (grub_file_seek (elf->file, off) == (grub_off_t) -1)
return grub_errno;
buf = grub_malloc (sz);
@@ -35,7 +38,8 @@ parse_xen_guest (grub_elf_t elf, struct grub_xen_file_info *xi,
if (grub_file_read (elf->file, buf, sz) != (grub_ssize_t) sz)
{
if (grub_errno)
return grub_errno;
goto out;
grub_free (buf);
return grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
elf->file->name);
}
@@ -123,14 +127,14 @@ parse_xen_guest (grub_elf_t elf, struct grub_xen_file_info *xi,
{
xi->virt_base = grub_strtoull (ptr + sizeof ("VIRT_BASE=") - 1, &ptr, 16);
if (grub_errno)
return grub_errno;
goto out;
continue;
}
if (grub_strncmp (ptr, "VIRT_ENTRY=", sizeof ("VIRT_ENTRY=") - 1) == 0)
{
xi->entry_point = grub_strtoull (ptr + sizeof ("VIRT_ENTRY=") - 1, &ptr, 16);
if (grub_errno)
return grub_errno;
goto out;
continue;
}
if (grub_strncmp (ptr, "HYPERCALL_PAGE=", sizeof ("HYPERCALL_PAGE=") - 1) == 0)
@@ -138,7 +142,7 @@ parse_xen_guest (grub_elf_t elf, struct grub_xen_file_info *xi,
xi->hypercall_page = grub_strtoull (ptr + sizeof ("HYPERCALL_PAGE=") - 1, &ptr, 16);
xi->has_hypercall_page = 1;
if (grub_errno)
return grub_errno;
goto out;
continue;
}
if (grub_strncmp (ptr, "ELF_PADDR_OFFSET=", sizeof ("ELF_PADDR_OFFSET=") - 1) == 0)
@@ -146,7 +150,7 @@ parse_xen_guest (grub_elf_t elf, struct grub_xen_file_info *xi,
xi->paddr_offset = grub_strtoull (ptr + sizeof ("ELF_PADDR_OFFSET=") - 1, &ptr, 16);
has_paddr = 1;
if (grub_errno)
return grub_errno;
goto out;
continue;
}
}
@@ -154,7 +158,11 @@ parse_xen_guest (grub_elf_t elf, struct grub_xen_file_info *xi,
xi->hypercall_page = (xi->hypercall_page << 12) + xi->virt_base;
if (!has_paddr)
xi->paddr_offset = xi->virt_base;
return GRUB_ERR_NONE;
out:
grub_free (buf);
return grub_errno;
}
#pragma GCC diagnostic ignored "-Wcast-align"
@@ -196,35 +204,35 @@ parse_note (grub_elf_t elf, struct grub_xen_file_info *xi,
xi->has_note = 1;
switch (nh->n_type)
{
case 1:
case XEN_ELFNOTE_ENTRY:
xi->entry_point = grub_le_to_cpu_addr (*(Elf_Addr *) desc);
break;
case 2:
case XEN_ELFNOTE_HYPERCALL_PAGE:
xi->hypercall_page = grub_le_to_cpu_addr (*(Elf_Addr *) desc);
xi->has_hypercall_page = 1;
break;
case 3:
case XEN_ELFNOTE_VIRT_BASE:
xi->virt_base = grub_le_to_cpu_addr (*(Elf_Addr *) desc);
break;
case 4:
case XEN_ELFNOTE_PADDR_OFFSET:
xi->paddr_offset = grub_le_to_cpu_addr (*(Elf_Addr *) desc);
break;
case 5:
case XEN_ELFNOTE_XEN_VERSION:
grub_dprintf ("xen", "xenversion = `%s'\n", (char *) desc);
break;
case 6:
case XEN_ELFNOTE_GUEST_OS:
grub_dprintf ("xen", "name = `%s'\n", (char *) desc);
break;
case 7:
case XEN_ELFNOTE_GUEST_VERSION:
grub_dprintf ("xen", "version = `%s'\n", (char *) desc);
break;
case 8:
case XEN_ELFNOTE_LOADER:
if (descsz < 7
|| grub_memcmp (desc, "generic", descsz == 7 ? 7 : 8) != 0)
return grub_error (GRUB_ERR_BAD_OS, "invalid loader");
break;
/* PAE */
case 9:
case XEN_ELFNOTE_PAE_MODE:
grub_dprintf ("xen", "pae = `%s', %d, %d\n", (char *) desc,
xi->arch, descsz);
if (xi->arch != GRUB_XEN_FILE_I386
@@ -253,6 +261,13 @@ parse_note (grub_elf_t elf, struct grub_xen_file_info *xi,
descsz == 2 ? 2 : 3) == 0)
xi->arch = GRUB_XEN_FILE_I386;
break;
case XEN_ELFNOTE_INIT_P2M:
xi->p2m_base = grub_le_to_cpu_addr (*(Elf_Addr *) desc);
xi->has_p2m_base = 1;
break;
case XEN_ELFNOTE_MOD_START_PFN:
xi->unmapped_initrd = !!grub_le_to_cpu32(*(grub_uint32_t *) desc);
break;
default:
grub_dprintf ("xen", "unknown note type %d\n", nh->n_type);
break;

View File

@@ -118,6 +118,48 @@ grub_multiboot_set_video_mode (void)
return err;
}
#ifdef GRUB_MACHINE_EFI
#ifdef __x86_64__
#define grub_relocator_efi_boot grub_relocator64_efi_boot
#define grub_relocator_efi_state grub_relocator64_efi_state
#endif
#endif
#ifdef grub_relocator_efi_boot
static void
efi_boot (struct grub_relocator *rel,
grub_uint32_t target)
{
struct grub_relocator_efi_state state_efi = MULTIBOOT_EFI_INITIAL_STATE;
state_efi.MULTIBOOT_EFI_ENTRY_REGISTER = grub_multiboot_payload_eip;
state_efi.MULTIBOOT_EFI_MBI_REGISTER = target;
grub_relocator_efi_boot (rel, state_efi);
}
#else
#define grub_efi_is_finished 1
static void
efi_boot (struct grub_relocator *rel __attribute__ ((unused)),
grub_uint32_t target __attribute__ ((unused)))
{
}
#endif
#if defined (__i386__) || defined (__x86_64__)
static void
normal_boot (struct grub_relocator *rel, struct grub_relocator32_state state)
{
grub_relocator32_boot (rel, state, 0);
}
#else
static void
normal_boot (struct grub_relocator *rel, struct grub_relocator32_state state)
{
grub_relocator32_boot (rel, state);
}
#endif
static grub_err_t
grub_multiboot_boot (void)
{
@@ -131,11 +173,10 @@ grub_multiboot_boot (void)
if (err)
return err;
#if defined (__i386__) || defined (__x86_64__)
grub_relocator32_boot (grub_multiboot_relocator, state, 0);
#else
grub_relocator32_boot (grub_multiboot_relocator, state);
#endif
if (grub_efi_is_finished)
normal_boot (grub_multiboot_relocator, state);
else
efi_boot (grub_multiboot_relocator, state.MULTIBOOT_MBI_REGISTER);
/* Not reached. */
return GRUB_ERR_NONE;
@@ -166,13 +207,12 @@ static grub_uint64_t highest_load;
/* Load ELF32 or ELF64. */
grub_err_t
grub_multiboot_load_elf (grub_file_t file, const char *filename,
void *buffer)
grub_multiboot_load_elf (mbi_load_data_t *mld)
{
if (grub_multiboot_is_elf32 (buffer))
return grub_multiboot_load_elf32 (file, filename, buffer);
else if (grub_multiboot_is_elf64 (buffer))
return grub_multiboot_load_elf64 (file, filename, buffer);
if (grub_multiboot_is_elf32 (mld->buffer))
return grub_multiboot_load_elf32 (mld);
else if (grub_multiboot_is_elf64 (mld->buffer))
return grub_multiboot_load_elf64 (mld);
return grub_error (GRUB_ERR_UNKNOWN_OS, N_("invalid arch-dependent ELF magic"));
}

View File

@@ -51,11 +51,15 @@ CONCAT(grub_multiboot_is_elf, XX) (void *buffer)
}
static grub_err_t
CONCAT(grub_multiboot_load_elf, XX) (grub_file_t file, const char *filename, void *buffer)
CONCAT(grub_multiboot_load_elf, XX) (mbi_load_data_t *mld)
{
Elf_Ehdr *ehdr = (Elf_Ehdr *) buffer;
Elf_Ehdr *ehdr = (Elf_Ehdr *) mld->buffer;
char *phdr_base;
grub_err_t err;
grub_relocator_chunk_t ch;
grub_uint32_t load_offset, load_size;
int i;
void *source;
if (ehdr->e_ident[EI_MAG0] != ELFMAG0
|| ehdr->e_ident[EI_MAG1] != ELFMAG1
@@ -75,54 +79,86 @@ CONCAT(grub_multiboot_load_elf, XX) (grub_file_t file, const char *filename, voi
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;
phdr_base = (char *) mld->buffer + ehdr->e_phoff;
#define phdr(i) ((Elf_Phdr *) (phdr_base + (i) * ehdr->e_phentsize))
mld->link_base_addr = ~0;
/* Calculate lowest and highest load address. */
for (i = 0; i < ehdr->e_phnum; i++)
if (phdr(i)->p_type == PT_LOAD)
{
mld->link_base_addr = grub_min (mld->link_base_addr, phdr(i)->p_paddr);
highest_load = grub_max (highest_load, phdr(i)->p_paddr + phdr(i)->p_memsz);
}
#ifdef MULTIBOOT_LOAD_ELF64
if (highest_load >= 0x100000000)
return grub_error (GRUB_ERR_BAD_OS, "segment crosses 4 GiB border");
#endif
load_size = highest_load - mld->link_base_addr;
if (mld->relocatable)
{
if (load_size > mld->max_addr || mld->min_addr > mld->max_addr - load_size)
return grub_error (GRUB_ERR_BAD_OS, "invalid min/max address and/or load size");
err = grub_relocator_alloc_chunk_align (grub_multiboot_relocator, &ch,
mld->min_addr, mld->max_addr - load_size,
load_size, mld->align ? mld->align : 1,
mld->preference, mld->avoid_efi_boot_services);
}
else
err = grub_relocator_alloc_chunk_addr (grub_multiboot_relocator, &ch,
mld->link_base_addr, load_size);
if (err)
{
grub_dprintf ("multiboot_loader", "Cannot allocate memory for OS image\n");
return err;
}
mld->load_base_addr = get_physical_target_address (ch);
source = get_virtual_current_address (ch);
grub_dprintf ("multiboot_loader", "link_base_addr=0x%x, load_base_addr=0x%x, "
"load_size=0x%x, relocatable=%d\n", mld->link_base_addr,
mld->load_base_addr, load_size, mld->relocatable);
if (mld->relocatable)
grub_dprintf ("multiboot_loader", "align=0x%lx, preference=0x%x, avoid_efi_boot_services=%d\n",
(long) mld->align, mld->preference, mld->avoid_efi_boot_services);
/* Load every loadable segment in memory. */
for (i = 0; i < ehdr->e_phnum; i++)
{
if (phdr(i)->p_type == PT_LOAD)
{
grub_err_t err;
void *source;
if (phdr(i)->p_paddr + phdr(i)->p_memsz > highest_load)
highest_load = phdr(i)->p_paddr + phdr(i)->p_memsz;
grub_dprintf ("multiboot_loader", "segment %d: paddr=0x%lx, memsz=0x%lx, vaddr=0x%lx\n",
i, (long) phdr(i)->p_paddr, (long) phdr(i)->p_memsz, (long) phdr(i)->p_vaddr);
{
grub_relocator_chunk_t ch;
err = grub_relocator_alloc_chunk_addr (grub_multiboot_relocator,
&ch, phdr(i)->p_paddr,
phdr(i)->p_memsz);
if (err)
{
grub_dprintf ("multiboot_loader", "Error loading phdr %d\n", i);
return err;
}
source = get_virtual_current_address (ch);
}
load_offset = phdr(i)->p_paddr - mld->link_base_addr;
if (phdr(i)->p_filesz != 0)
{
if (grub_file_seek (file, (grub_off_t) phdr(i)->p_offset)
if (grub_file_seek (mld->file, (grub_off_t) phdr(i)->p_offset)
== (grub_off_t) -1)
return grub_errno;
if (grub_file_read (file, source, phdr(i)->p_filesz)
if (grub_file_read (mld->file, (grub_uint8_t *) source + load_offset, phdr(i)->p_filesz)
!= (grub_ssize_t) phdr(i)->p_filesz)
{
if (!grub_errno)
grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"),
filename);
mld->filename);
return grub_errno;
}
}
if (phdr(i)->p_filesz < phdr(i)->p_memsz)
grub_memset ((grub_uint8_t *) source + phdr(i)->p_filesz, 0,
grub_memset ((grub_uint8_t *) source + load_offset + phdr(i)->p_filesz, 0,
phdr(i)->p_memsz - phdr(i)->p_filesz);
}
}
@@ -168,18 +204,18 @@ CONCAT(grub_multiboot_load_elf, XX) (grub_file_t file, const char *filename, voi
if (!shdr)
return grub_errno;
if (grub_file_seek (file, ehdr->e_shoff) == (grub_off_t) -1)
if (grub_file_seek (mld->file, ehdr->e_shoff) == (grub_off_t) -1)
{
grub_free (shdr);
return grub_errno;
}
if (grub_file_read (file, shdr, (grub_uint32_t) ehdr->e_shnum * ehdr->e_shentsize)
if (grub_file_read (mld->file, shdr, (grub_uint32_t) ehdr->e_shnum * ehdr->e_shentsize)
!= (grub_ssize_t) ehdr->e_shnum * ehdr->e_shentsize)
{
if (!grub_errno)
grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"),
filename);
mld->filename);
return grub_errno;
}
@@ -189,7 +225,9 @@ CONCAT(grub_multiboot_load_elf, XX) (grub_file_t file, const char *filename, voi
Elf_Shdr *sh = (Elf_Shdr *) shdrptr;
void *src;
grub_addr_t target;
grub_err_t err;
if (mld->mbi_ver >= 2 && (sh->sh_type == SHT_REL || sh->sh_type == SHT_RELA))
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "ELF files with relocs are not supported yet");
/* This section is a loaded section,
so we don't care. */
@@ -200,33 +238,28 @@ CONCAT(grub_multiboot_load_elf, XX) (grub_file_t file, const char *filename, voi
if (sh->sh_size == 0)
continue;
{
grub_relocator_chunk_t ch;
err = grub_relocator_alloc_chunk_align (grub_multiboot_relocator,
&ch, 0,
(0xffffffff - sh->sh_size)
+ 1, sh->sh_size,
sh->sh_addralign,
GRUB_RELOCATOR_PREFERENCE_NONE,
0);
if (err)
{
grub_dprintf ("multiboot_loader", "Error loading shdr %d\n", i);
return err;
}
src = get_virtual_current_address (ch);
target = get_physical_target_address (ch);
}
err = grub_relocator_alloc_chunk_align (grub_multiboot_relocator, &ch, 0,
(0xffffffff - sh->sh_size) + 1,
sh->sh_size, sh->sh_addralign,
GRUB_RELOCATOR_PREFERENCE_NONE,
mld->avoid_efi_boot_services);
if (err)
{
grub_dprintf ("multiboot_loader", "Error loading shdr %d\n", i);
return err;
}
src = get_virtual_current_address (ch);
target = get_physical_target_address (ch);
if (grub_file_seek (file, sh->sh_offset) == (grub_off_t) -1)
if (grub_file_seek (mld->file, sh->sh_offset) == (grub_off_t) -1)
return grub_errno;
if (grub_file_read (file, src, sh->sh_size)
if (grub_file_read (mld->file, src, sh->sh_size)
!= (grub_ssize_t) sh->sh_size)
{
if (!grub_errno)
grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"),
filename);
mld->filename);
return grub_errno;
}
sh->sh_addr = target;

View File

@@ -68,6 +68,7 @@ static grub_size_t elf_sec_num, elf_sec_entsize;
static unsigned elf_sec_shstrndx;
static void *elf_sections;
static int keep_bs = 0;
static grub_uint32_t load_base_addr;
void
grub_multiboot_add_elfsyms (grub_size_t num, grub_size_t entsize,
@@ -101,36 +102,40 @@ find_header (grub_properly_aligned_t *buffer, grub_ssize_t len)
grub_err_t
grub_multiboot_load (grub_file_t file, const char *filename)
{
grub_properly_aligned_t *buffer;
grub_ssize_t len;
struct multiboot_header *header;
grub_err_t err;
struct multiboot_header_tag *tag;
struct multiboot_header_tag_address *addr_tag = NULL;
int entry_specified = 0;
grub_addr_t entry = 0;
struct multiboot_header_tag_relocatable *rel_tag;
int entry_specified = 0, efi_entry_specified = 0;
grub_addr_t entry = 0, efi_entry = 0;
grub_uint32_t console_required = 0;
struct multiboot_header_tag_framebuffer *fbtag = NULL;
int accepted_consoles = GRUB_MULTIBOOT_CONSOLE_EGA_TEXT;
mbi_load_data_t mld;
buffer = grub_malloc (MULTIBOOT_SEARCH);
if (!buffer)
mld.mbi_ver = 2;
mld.relocatable = 0;
mld.buffer = grub_malloc (MULTIBOOT_SEARCH);
if (!mld.buffer)
return grub_errno;
len = grub_file_read (file, buffer, MULTIBOOT_SEARCH);
len = grub_file_read (file, mld.buffer, MULTIBOOT_SEARCH);
if (len < 32)
{
grub_free (buffer);
grub_free (mld.buffer);
return grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), filename);
}
COMPILE_TIME_ASSERT (MULTIBOOT_HEADER_ALIGN % 4 == 0);
header = find_header (buffer, len);
header = find_header (mld.buffer, len);
if (header == 0)
{
grub_free (buffer);
grub_free (mld.buffer);
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no multiboot header found");
}
@@ -172,10 +177,13 @@ grub_multiboot_load (grub_file_t file, const char *filename)
case MULTIBOOT_TAG_TYPE_NETWORK:
case MULTIBOOT_TAG_TYPE_EFI_MMAP:
case MULTIBOOT_TAG_TYPE_EFI_BS:
case MULTIBOOT_TAG_TYPE_EFI32_IH:
case MULTIBOOT_TAG_TYPE_EFI64_IH:
case MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR:
break;
default:
grub_free (buffer);
grub_free (mld.buffer);
return grub_error (GRUB_ERR_UNKNOWN_OS,
"unsupported information tag: 0x%x",
request_tag->requests[i]);
@@ -192,6 +200,13 @@ grub_multiboot_load (grub_file_t file, const char *filename)
entry = ((struct multiboot_header_tag_entry_address *) tag)->entry_addr;
break;
case MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI64:
#if defined (GRUB_MACHINE_EFI) && defined (__x86_64__)
efi_entry_specified = 1;
efi_entry = ((struct multiboot_header_tag_entry_address *) tag)->entry_addr;
#endif
break;
case MULTIBOOT_HEADER_TAG_CONSOLE_FLAGS:
if (!(((struct multiboot_header_tag_console_flags *) tag)->console_flags
& MULTIBOOT_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED))
@@ -206,27 +221,50 @@ grub_multiboot_load (grub_file_t file, const char *filename)
accepted_consoles |= GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER;
break;
case MULTIBOOT_HEADER_TAG_RELOCATABLE:
mld.relocatable = 1;
rel_tag = (struct multiboot_header_tag_relocatable *) tag;
mld.min_addr = rel_tag->min_addr;
mld.max_addr = rel_tag->max_addr;
mld.align = rel_tag->align;
switch (rel_tag->preference)
{
case MULTIBOOT_LOAD_PREFERENCE_LOW:
mld.preference = GRUB_RELOCATOR_PREFERENCE_LOW;
break;
case MULTIBOOT_LOAD_PREFERENCE_HIGH:
mld.preference = GRUB_RELOCATOR_PREFERENCE_HIGH;
break;
default:
mld.preference = GRUB_RELOCATOR_PREFERENCE_NONE;
}
break;
/* GRUB always page-aligns modules. */
case MULTIBOOT_HEADER_TAG_MODULE_ALIGN:
break;
case MULTIBOOT_HEADER_TAG_EFI_BS:
#ifdef GRUB_MACHINE_EFI
keep_bs = 1;
#endif
break;
default:
if (! (tag->flags & MULTIBOOT_HEADER_TAG_OPTIONAL))
{
grub_free (buffer);
grub_free (mld.buffer);
return grub_error (GRUB_ERR_UNKNOWN_OS,
"unsupported tag: 0x%x", tag->type);
}
break;
}
if (addr_tag && !entry_specified)
if (addr_tag && !entry_specified && !(keep_bs && efi_entry_specified))
{
grub_free (buffer);
grub_free (mld.buffer);
return grub_error (GRUB_ERR_UNKNOWN_OS,
"load address tag without entry address tag");
}
@@ -235,8 +273,8 @@ grub_multiboot_load (grub_file_t file, const char *filename)
{
grub_uint64_t load_addr = (addr_tag->load_addr + 1)
? addr_tag->load_addr : (addr_tag->header_addr
- ((char *) header - (char *) buffer));
int offset = ((char *) header - (char *) buffer -
- ((char *) header - (char *) mld.buffer));
int offset = ((char *) header - (char *) mld.buffer -
(addr_tag->header_addr - load_addr));
int load_size = ((addr_tag->load_end_addr == 0) ? file->size - offset :
addr_tag->load_end_addr - addr_tag->load_addr);
@@ -249,27 +287,50 @@ grub_multiboot_load (grub_file_t file, const char *filename)
else
code_size = load_size;
err = grub_relocator_alloc_chunk_addr (grub_multiboot_relocator,
&ch, load_addr,
code_size);
if (mld.relocatable)
{
if (code_size > mld.max_addr || mld.min_addr > mld.max_addr - code_size)
{
grub_free (mld.buffer);
return grub_error (GRUB_ERR_BAD_OS, "invalid min/max address and/or load size");
}
err = grub_relocator_alloc_chunk_align (grub_multiboot_relocator, &ch,
mld.min_addr, mld.max_addr - code_size,
code_size, mld.align ? mld.align : 1,
mld.preference, keep_bs);
}
else
err = grub_relocator_alloc_chunk_addr (grub_multiboot_relocator,
&ch, load_addr, code_size);
if (err)
{
grub_dprintf ("multiboot_loader", "Error loading aout kludge\n");
grub_free (buffer);
grub_free (mld.buffer);
return err;
}
mld.link_base_addr = load_addr;
mld.load_base_addr = get_physical_target_address (ch);
source = get_virtual_current_address (ch);
grub_dprintf ("multiboot_loader", "link_base_addr=0x%x, load_base_addr=0x%x, "
"load_size=0x%lx, relocatable=%d\n", mld.link_base_addr,
mld.load_base_addr, (long) code_size, mld.relocatable);
if (mld.relocatable)
grub_dprintf ("multiboot_loader", "align=0x%lx, preference=0x%x, avoid_efi_boot_services=%d\n",
(long) mld.align, mld.preference, keep_bs);
if ((grub_file_seek (file, offset)) == (grub_off_t) -1)
{
grub_free (buffer);
grub_free (mld.buffer);
return grub_errno;
}
grub_file_read (file, source, load_size);
if (grub_errno)
{
grub_free (buffer);
grub_free (mld.buffer);
return grub_errno;
}
@@ -279,17 +340,41 @@ grub_multiboot_load (grub_file_t file, const char *filename)
}
else
{
err = grub_multiboot_load_elf (file, filename, buffer);
mld.file = file;
mld.filename = filename;
mld.avoid_efi_boot_services = keep_bs;
err = grub_multiboot_load_elf (&mld);
if (err)
{
grub_free (buffer);
grub_free (mld.buffer);
return err;
}
}
if (entry_specified)
load_base_addr = mld.load_base_addr;
if (keep_bs && efi_entry_specified)
grub_multiboot_payload_eip = efi_entry;
else if (entry_specified)
grub_multiboot_payload_eip = entry;
if (mld.relocatable)
{
/*
* Both branches are mathematically equivalent. However, it looks
* that real life (C?) is more complicated. I am trying to avoid
* wrap around here if mld.load_base_addr < mld.link_base_addr.
* If you look at C operator precedence then everything should work.
* However, I am not 100% sure that a given compiler will not
* optimize/break this stuff. So, maybe we should use signed
* 64-bit int here.
*/
if (mld.load_base_addr >= mld.link_base_addr)
grub_multiboot_payload_eip += mld.load_base_addr - mld.link_base_addr;
else
grub_multiboot_payload_eip -= mld.link_base_addr - mld.load_base_addr;
}
if (fbtag)
err = grub_multiboot_set_console (GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER,
accepted_consoles,
@@ -377,7 +462,7 @@ static grub_size_t
grub_multiboot_get_mbi_size (void)
{
#ifdef GRUB_MACHINE_EFI
if (!efi_mmap_size)
if (!keep_bs && !efi_mmap_size)
find_efi_mmap_size ();
#endif
return 2 * sizeof (grub_uint32_t) + sizeof (struct multiboot_tag)
@@ -396,13 +481,16 @@ grub_multiboot_get_mbi_size (void)
+ grub_get_multiboot_mmap_count ()
* sizeof (struct multiboot_mmap_entry)), MULTIBOOT_TAG_ALIGN)
+ ALIGN_UP (sizeof (struct multiboot_tag_framebuffer), MULTIBOOT_TAG_ALIGN)
+ ALIGN_UP (sizeof (struct multiboot_tag_efi32), MULTIBOOT_TAG_ALIGN)
+ ALIGN_UP (sizeof (struct multiboot_tag_efi64), MULTIBOOT_TAG_ALIGN)
+ ALIGN_UP (sizeof (struct multiboot_tag_old_acpi)
+ sizeof (struct grub_acpi_rsdp_v10), MULTIBOOT_TAG_ALIGN)
+ ALIGN_UP (sizeof (struct multiboot_tag_load_base_addr), MULTIBOOT_TAG_ALIGN)
+ acpiv2_size ()
+ net_size ()
#ifdef GRUB_MACHINE_EFI
+ ALIGN_UP (sizeof (struct multiboot_tag_efi32), MULTIBOOT_TAG_ALIGN)
+ ALIGN_UP (sizeof (struct multiboot_tag_efi32_ih), MULTIBOOT_TAG_ALIGN)
+ ALIGN_UP (sizeof (struct multiboot_tag_efi64), MULTIBOOT_TAG_ALIGN)
+ ALIGN_UP (sizeof (struct multiboot_tag_efi64_ih), MULTIBOOT_TAG_ALIGN)
+ ALIGN_UP (sizeof (struct multiboot_tag_efi_mmap)
+ efi_mmap_size, MULTIBOOT_TAG_ALIGN)
#endif
@@ -420,6 +508,7 @@ grub_fill_multiboot_mmap_iter (grub_uint64_t addr, grub_uint64_t size,
(*mmap_entry)->addr = addr;
(*mmap_entry)->len = size;
(*mmap_entry)->type = type;
(*mmap_entry)->zero = 0;
(*mmap_entry)++;
return 0;
@@ -677,6 +766,15 @@ grub_multiboot_make_mbi (grub_uint32_t *target)
% sizeof (grub_properly_aligned_t) == 0);
ptrorig += (2 * sizeof (grub_uint32_t)) / sizeof (grub_properly_aligned_t);
{
struct multiboot_tag_load_base_addr *tag = (struct multiboot_tag_load_base_addr *) ptrorig;
tag->type = MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR;
tag->size = sizeof (struct multiboot_tag_load_base_addr);
tag->load_base_addr = load_base_addr;
ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
/ sizeof (grub_properly_aligned_t);
}
{
struct multiboot_tag_string *tag = (struct multiboot_tag_string *) ptrorig;
tag->type = MULTIBOOT_TAG_TYPE_CMDLINE;
@@ -739,12 +837,13 @@ grub_multiboot_make_mbi (grub_uint32_t *target)
}
}
{
struct multiboot_tag_mmap *tag = (struct multiboot_tag_mmap *) ptrorig;
grub_fill_multiboot_mmap (tag);
ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
/ sizeof (grub_properly_aligned_t);
}
if (!keep_bs)
{
struct multiboot_tag_mmap *tag = (struct multiboot_tag_mmap *) ptrorig;
grub_fill_multiboot_mmap (tag);
ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
/ sizeof (grub_properly_aligned_t);
}
{
struct multiboot_tag_elf_sections *tag
@@ -760,18 +859,19 @@ grub_multiboot_make_mbi (grub_uint32_t *target)
/ sizeof (grub_properly_aligned_t);
}
{
struct multiboot_tag_basic_meminfo *tag
= (struct multiboot_tag_basic_meminfo *) ptrorig;
tag->type = MULTIBOOT_TAG_TYPE_BASIC_MEMINFO;
tag->size = sizeof (struct multiboot_tag_basic_meminfo);
if (!keep_bs)
{
struct multiboot_tag_basic_meminfo *tag
= (struct multiboot_tag_basic_meminfo *) ptrorig;
tag->type = MULTIBOOT_TAG_TYPE_BASIC_MEMINFO;
tag->size = sizeof (struct multiboot_tag_basic_meminfo);
/* Convert from bytes to kilobytes. */
tag->mem_lower = grub_mmap_get_lower () / 1024;
tag->mem_upper = grub_mmap_get_upper () / 1024;
ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
/ sizeof (grub_properly_aligned_t);
}
/* Convert from bytes to kilobytes. */
tag->mem_lower = grub_mmap_get_lower () / 1024;
tag->mem_upper = grub_mmap_get_upper () / 1024;
ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
/ sizeof (grub_properly_aligned_t);
}
{
struct grub_net_network_level_interface *net;
@@ -870,36 +970,57 @@ grub_multiboot_make_mbi (grub_uint32_t *target)
grub_efi_uintn_t efi_desc_size;
grub_efi_uint32_t efi_desc_version;
tag->type = MULTIBOOT_TAG_TYPE_EFI_MMAP;
tag->size = sizeof (*tag) + efi_mmap_size;
if (!keep_bs)
err = grub_efi_finish_boot_services (&efi_mmap_size, tag->efi_mmap, NULL,
&efi_desc_size, &efi_desc_version);
else
{
if (grub_efi_get_memory_map (&efi_mmap_size, (void *) tag->efi_mmap,
NULL,
&efi_desc_size, &efi_desc_version) <= 0)
err = grub_error (GRUB_ERR_IO, "couldn't retrieve memory map");
}
if (err)
return err;
tag->descr_size = efi_desc_size;
tag->descr_vers = efi_desc_version;
tag->size = sizeof (*tag) + efi_mmap_size;
tag->type = MULTIBOOT_TAG_TYPE_EFI_MMAP;
tag->size = sizeof (*tag) + efi_mmap_size;
ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
/ sizeof (grub_properly_aligned_t);
err = grub_efi_finish_boot_services (&efi_mmap_size, tag->efi_mmap, NULL,
&efi_desc_size, &efi_desc_version);
if (err)
return err;
tag->descr_size = efi_desc_size;
tag->descr_vers = efi_desc_version;
tag->size = sizeof (*tag) + efi_mmap_size;
ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
/ sizeof (grub_properly_aligned_t);
}
}
if (keep_bs)
{
struct multiboot_tag *tag = (struct multiboot_tag *) ptrorig;
tag->type = MULTIBOOT_TAG_TYPE_EFI_BS;
tag->size = sizeof (struct multiboot_tag);
ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
/ sizeof (grub_properly_aligned_t);
{
struct multiboot_tag *tag = (struct multiboot_tag *) ptrorig;
tag->type = MULTIBOOT_TAG_TYPE_EFI_BS;
tag->size = sizeof (struct multiboot_tag);
ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
/ sizeof (grub_properly_aligned_t);
}
#ifdef __i386__
{
struct multiboot_tag_efi32_ih *tag = (struct multiboot_tag_efi32_ih *) ptrorig;
tag->type = MULTIBOOT_TAG_TYPE_EFI32_IH;
tag->size = sizeof (struct multiboot_tag_efi32_ih);
tag->pointer = (grub_addr_t) grub_efi_image_handle;
ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
/ sizeof (grub_properly_aligned_t);
}
#endif
#ifdef __x86_64__
{
struct multiboot_tag_efi64_ih *tag = (struct multiboot_tag_efi64_ih *) ptrorig;
tag->type = MULTIBOOT_TAG_TYPE_EFI64_IH;
tag->size = sizeof (struct multiboot_tag_efi64_ih);
tag->pointer = (grub_addr_t) grub_efi_image_handle;
ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
/ sizeof (grub_properly_aligned_t);
}
#endif
}
#endif

View File

@@ -1,4 +1,4 @@
#!/bin/sh
#!@BUILD_SHEBANG@
# User-controllable options
grub_modinfo_target_cpu=@target_cpu@
@@ -19,6 +19,7 @@ grub_target_cflags='@TARGET_CFLAGS@'
grub_target_cppflags='@TARGET_CPPFLAGS@'
grub_target_ccasflags='@TARGET_CCASFLAGS@'
grub_target_ldflags='@TARGET_LDFLAGS@'
grub_target_incremental_ldflags='@TARGET_INCREMENTAL_LINK@'
grub_cflags='@CFLAGS@'
grub_cppflags='@CPPFLAGS@'
grub_ccasflags='@CCASFLAGS@'

View File

@@ -111,8 +111,8 @@ grub_net_arp_send_request (struct grub_net_network_level_interface *inf,
}
grub_err_t
grub_net_arp_receive (struct grub_net_buff *nb,
struct grub_net_card *card)
grub_net_arp_receive (struct grub_net_buff *nb, struct grub_net_card *card,
grub_uint16_t *vlantag)
{
struct arppkt *arp_packet = (struct arppkt *) nb->data;
grub_net_network_level_address_t sender_addr, target_addr;
@@ -138,6 +138,14 @@ grub_net_arp_receive (struct grub_net_buff *nb,
FOR_NET_NETWORK_LEVEL_INTERFACES (inf)
{
/* Verify vlantag id */
if (inf->card == card && inf->vlantag != *vlantag)
{
grub_dprintf ("net", "invalid vlantag! %x != %x\n",
inf->vlantag, *vlantag);
break;
}
/* Am I the protocol address target? */
if (grub_net_addr_cmp (&inf->address, &target_addr) == 0
&& arp_packet->op == grub_cpu_to_be16_compile_time (ARP_REQUEST))

View File

@@ -82,7 +82,7 @@ parse_dhcp_vendor (const char *name, const void *vend, int limit, int *mask)
grub_memcpy (&gw.ipv4, ptr, sizeof (gw.ipv4));
rname = grub_xasprintf ("%s:default", name);
if (rname)
grub_net_add_route_gw (rname, target, gw);
grub_net_add_route_gw (rname, target, gw, NULL);
grub_free (rname);
}
break;
@@ -142,6 +142,7 @@ grub_net_configure_by_dhcp_ack (const char *name,
grub_net_link_level_address_t hwaddr;
struct grub_net_network_level_interface *inter;
int mask = -1;
char server_ip[sizeof ("xxx.xxx.xxx.xxx")];
addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4;
addr.ipv4 = bp->your_ip;
@@ -157,6 +158,9 @@ grub_net_configure_by_dhcp_ack (const char *name,
hwaddr.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
inter = grub_net_add_addr (name, card, &addr, &hwaddr, flags);
if (!inter)
return 0;
#if 0
/* This is likely based on misunderstanding. gateway_ip refers to
address of BOOTP relay and should not be used after BOOTP transaction
@@ -189,15 +193,22 @@ grub_net_configure_by_dhcp_ack (const char *name,
if (size > OFFSET_OF (boot_file, bp))
grub_env_set_net_property (name, "boot_file", bp->boot_file,
sizeof (bp->boot_file));
if (bp->server_ip)
{
grub_snprintf (server_ip, sizeof (server_ip), "%d.%d.%d.%d",
((grub_uint8_t *) &bp->server_ip)[0],
((grub_uint8_t *) &bp->server_ip)[1],
((grub_uint8_t *) &bp->server_ip)[2],
((grub_uint8_t *) &bp->server_ip)[3]);
grub_env_set_net_property (name, "next_server", server_ip, sizeof (server_ip));
grub_print_error ();
}
if (is_def)
grub_net_default_server = 0;
if (is_def && !grub_net_default_server && bp->server_ip)
{
grub_net_default_server = grub_xasprintf ("%d.%d.%d.%d",
((grub_uint8_t *) &bp->server_ip)[0],
((grub_uint8_t *) &bp->server_ip)[1],
((grub_uint8_t *) &bp->server_ip)[2],
((grub_uint8_t *) &bp->server_ip)[3]);
grub_net_default_server = grub_strdup (server_ip);
grub_print_error ();
}
@@ -209,11 +220,7 @@ grub_net_configure_by_dhcp_ack (const char *name,
if (device && !*device && bp->server_ip)
{
*device = grub_xasprintf ("tftp,%d.%d.%d.%d",
((grub_uint8_t *) &bp->server_ip)[0],
((grub_uint8_t *) &bp->server_ip)[1],
((grub_uint8_t *) &bp->server_ip)[2],
((grub_uint8_t *) &bp->server_ip)[3]);
*device = grub_xasprintf ("tftp,%s", server_ip);
grub_print_error ();
}
if (size > OFFSET_OF (server_name, bp)
@@ -368,6 +375,7 @@ grub_cmd_dhcpopt (struct grub_command *cmd __attribute__ ((unused)),
if (grub_strcmp (args[3], "string") == 0)
{
grub_err_t err = GRUB_ERR_NONE;
char *val = grub_malloc (taglength + 1);
if (!val)
return grub_errno;
@@ -376,8 +384,9 @@ grub_cmd_dhcpopt (struct grub_command *cmd __attribute__ ((unused)),
if (args[0][0] == '-' && args[0][1] == 0)
grub_printf ("%s\n", val);
else
return grub_env_set (args[0], val);
return GRUB_ERR_NONE;
err = grub_env_set (args[0], val);
grub_free (val);
return err;
}
if (grub_strcmp (args[3], "number") == 0)
@@ -399,6 +408,7 @@ grub_cmd_dhcpopt (struct grub_command *cmd __attribute__ ((unused)),
if (grub_strcmp (args[3], "hex") == 0)
{
grub_err_t err = GRUB_ERR_NONE;
char *val = grub_malloc (2 * taglength + 1);
int i;
if (!val)
@@ -412,8 +422,9 @@ grub_cmd_dhcpopt (struct grub_command *cmd __attribute__ ((unused)),
if (args[0][0] == '-' && args[0][1] == 0)
grub_printf ("%s\n", val);
else
return grub_env_set (args[0], val);
return GRUB_ERR_NONE;
err = grub_env_set (args[0], val);
grub_free (val);
return err;
}
return grub_error (GRUB_ERR_BAD_ARGUMENT,

View File

@@ -238,6 +238,15 @@ recv_hook (grub_net_udp_socket_t sock __attribute__ ((unused)),
char *redirect_save = NULL;
grub_uint32_t ttl_all = ~0U;
/* Code apparently assumed that only one packet is received as response.
We may get multiple responses due to network condition, so check here
and quit early. */
if (*data->addresses)
{
grub_netbuff_free (nb);
return GRUB_ERR_NONE;
}
head = (struct dns_header *) nb->data;
ptr = (grub_uint8_t *) (head + 1);
if (ptr >= nb->tail)

View File

@@ -85,24 +85,30 @@ get_card_packet (struct grub_net_card *dev)
grub_uint64_t start_time;
struct grub_net_buff *nb;
nb = grub_netbuff_alloc (dev->mtu + 64 + 2);
start_time = grub_get_time_ms ();
do
rc = grub_ieee1275_read (data->handle, dev->rcvbuf, dev->rcvbufsize, &actual);
while ((actual <= 0 || rc < 0) && (grub_get_time_ms () - start_time < 200));
if (actual <= 0)
return NULL;
nb = grub_netbuff_alloc (actual + 2);
if (!nb)
return NULL;
/* Reserve 2 bytes so that 2 + 14/18 bytes of ethernet header is divisible
by 4. So that IP header is aligned on 4 bytes. */
grub_netbuff_reserve (nb, 2);
start_time = grub_get_time_ms ();
do
rc = grub_ieee1275_read (data->handle, nb->data, dev->mtu + 64, &actual);
while ((actual <= 0 || rc < 0) && (grub_get_time_ms () - start_time < 200));
if (actual > 0)
grub_memcpy (nb->data, dev->rcvbuf, actual);
if (grub_netbuff_put (nb, actual))
{
grub_netbuff_put (nb, actual);
return nb;
grub_netbuff_free (nb);
return NULL;
}
grub_netbuff_free (nb);
return NULL;
return nb;
}
static struct grub_net_card_driver ofdriver =
@@ -140,18 +146,18 @@ enum
};
static int
grub_ieee1275_parse_bootpath (const char *devpath, char *bootpath,
grub_ieee1275_parse_bootargs (const char *devpath, char *bootpath,
char **device, struct grub_net_card **card)
{
char *args;
char *comma_char = 0;
char *equal_char = 0;
grub_size_t field_counter = 0;
grub_net_network_level_address_t client_addr, gateway_addr, subnet_mask;
grub_net_link_level_address_t hw_addr;
grub_net_interface_flags_t flags = 0;
struct grub_net_network_level_interface *inter;
struct grub_net_network_level_interface *inter = NULL;
grub_uint16_t vlantag = 0;
hw_addr.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
@@ -169,6 +175,11 @@ grub_ieee1275_parse_bootpath (const char *devpath, char *bootpath,
*equal_char = 0;
grub_env_set_net_property ((*card)->name, args, equal_char + 1,
grub_strlen(equal_char + 1));
if ((grub_strcmp (args, "vtag") == 0) &&
(grub_strlen (equal_char + 1) == 8))
vlantag = grub_strtoul (equal_char + 1 + 4, 0, 16);
*equal_char = '=';
}
else
@@ -207,8 +218,10 @@ grub_ieee1275_parse_bootpath (const char *devpath, char *bootpath,
hw_addr.mac, sizeof(hw_addr.mac), 0);
inter = grub_net_add_addr ((*card)->name, *card, &client_addr, &hw_addr,
flags);
inter->vlantag = vlantag;
grub_net_add_ipv4_local (inter,
__builtin_ctz (~grub_le_to_cpu32 (subnet_mask.ipv4)));
}
if (gateway_addr.ipv4 != 0)
@@ -221,7 +234,7 @@ grub_ieee1275_parse_bootpath (const char *devpath, char *bootpath,
target.ipv4.masksize = 0;
rname = grub_xasprintf ("%s:default", ((*card)->name));
if (rname)
grub_net_add_route_gw (rname, target, gateway_addr);
grub_net_add_route_gw (rname, target, gateway_addr, inter);
else
return grub_errno;
}
@@ -261,7 +274,7 @@ grub_ieee1275_net_config_real (const char *devpath, char **device, char **path,
}
grub_free (canon);
grub_ieee1275_parse_bootpath (devpath, bootpath, device, &card);
grub_ieee1275_parse_bootargs (devpath, bootpath, device, &card);
for (i = 0; i < ARRAY_SIZE (bootp_response_properties); i++)
if (grub_ieee1275_get_property_length (grub_ieee1275_chosen,
@@ -294,6 +307,91 @@ grub_ieee1275_net_config_real (const char *devpath, char **device, char **path,
}
}
/* Allocate memory with alloc-mem */
static void *
grub_ieee1275_alloc_mem (grub_size_t len)
{
struct alloc_args
{
struct grub_ieee1275_common_hdr common;
grub_ieee1275_cell_t method;
grub_ieee1275_cell_t len;
grub_ieee1275_cell_t catch;
grub_ieee1275_cell_t result;
}
args;
if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_CANNOT_INTERPRET))
{
grub_error (GRUB_ERR_UNKNOWN_COMMAND, N_("interpret is not supported"));
return NULL;
}
INIT_IEEE1275_COMMON (&args.common, "interpret", 2, 2);
args.len = len;
args.method = (grub_ieee1275_cell_t) "alloc-mem";
if (IEEE1275_CALL_ENTRY_FN (&args) == -1 || args.catch)
{
grub_error (GRUB_ERR_INVALID_COMMAND, N_("alloc-mem failed"));
return NULL;
}
else
return (void *)args.result;
}
/* Free memory allocated by alloc-mem */
static grub_err_t
grub_ieee1275_free_mem (void *addr, grub_size_t len)
{
struct free_args
{
struct grub_ieee1275_common_hdr common;
grub_ieee1275_cell_t method;
grub_ieee1275_cell_t len;
grub_ieee1275_cell_t addr;
grub_ieee1275_cell_t catch;
}
args;
if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_CANNOT_INTERPRET))
{
grub_error (GRUB_ERR_UNKNOWN_COMMAND, N_("interpret is not supported"));
return grub_errno;
}
INIT_IEEE1275_COMMON (&args.common, "interpret", 3, 1);
args.addr = (grub_ieee1275_cell_t)addr;
args.len = len;
args.method = (grub_ieee1275_cell_t) "free-mem";
if (IEEE1275_CALL_ENTRY_FN(&args) == -1 || args.catch)
{
grub_error (GRUB_ERR_INVALID_COMMAND, N_("free-mem failed"));
return grub_errno;
}
return GRUB_ERR_NONE;
}
static void *
ofnet_alloc_netbuf (grub_size_t len)
{
if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_VIRT_TO_REAL_BROKEN))
return grub_ieee1275_alloc_mem (len);
else
return grub_zalloc (len);
}
static void
ofnet_free_netbuf (void *addr, grub_size_t len)
{
if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_VIRT_TO_REAL_BROKEN))
grub_ieee1275_free_mem (addr, len);
else
grub_free (addr);
}
static int
search_net_devices (struct grub_ieee1275_devalias *alias)
{
@@ -409,40 +507,19 @@ search_net_devices (struct grub_ieee1275_devalias *alias)
card->default_address = lla;
card->txbufsize = ALIGN_UP (card->mtu, 64) + 256;
card->rcvbufsize = ALIGN_UP (card->mtu, 64) + 256;
if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_VIRT_TO_REAL_BROKEN))
{
struct alloc_args
{
struct grub_ieee1275_common_hdr common;
grub_ieee1275_cell_t method;
grub_ieee1275_cell_t len;
grub_ieee1275_cell_t catch;
grub_ieee1275_cell_t result;
}
args;
INIT_IEEE1275_COMMON (&args.common, "interpret", 2, 2);
args.len = card->txbufsize;
args.method = (grub_ieee1275_cell_t) "alloc-mem";
if (IEEE1275_CALL_ENTRY_FN (&args) == -1
|| args.catch)
{
card->txbuf = 0;
grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
}
else
card->txbuf = (void *) args.result;
}
else
card->txbuf = grub_zalloc (card->txbufsize);
card->txbuf = ofnet_alloc_netbuf (card->txbufsize);
if (!card->txbuf)
goto fail_netbuf;
card->rcvbuf = ofnet_alloc_netbuf (card->rcvbufsize);
if (!card->rcvbuf)
{
grub_free (ofdata->path);
grub_free (ofdata);
grub_free (card);
grub_print_error ();
return 0;
grub_error_push ();
ofnet_free_netbuf (card->txbuf, card->txbufsize);
grub_error_pop ();
goto fail_netbuf;
}
card->driver = NULL;
card->data = ofdata;
@@ -455,6 +532,13 @@ search_net_devices (struct grub_ieee1275_devalias *alias)
card->driver = &ofdriver;
grub_net_card_register (card);
return 0;
fail_netbuf:
grub_free (ofdata->path);
grub_free (ofdata);
grub_free (card);
grub_print_error ();
return 0;
}
static void

View File

@@ -18,6 +18,7 @@
#include <grub/misc.h>
#include <grub/mm.h>
#include <grub/env.h>
#include <grub/net/ethernet.h>
#include <grub/net/ip.h>
#include <grub/net/arp.h>
@@ -56,10 +57,17 @@ send_ethernet_packet (struct grub_net_network_level_interface *inf,
{
struct etherhdr *eth;
grub_err_t err;
grub_uint8_t etherhdr_size;
grub_uint16_t vlantag_id = VLANTAG_IDENTIFIER;
COMPILE_TIME_ASSERT (sizeof (*eth) < GRUB_NET_MAX_LINK_HEADER_SIZE);
etherhdr_size = sizeof (*eth);
COMPILE_TIME_ASSERT (sizeof (*eth) + 4 < GRUB_NET_MAX_LINK_HEADER_SIZE);
err = grub_netbuff_push (nb, sizeof (*eth));
/* Increase ethernet header in case of vlantag */
if (inf->vlantag != 0)
etherhdr_size += 4;
err = grub_netbuff_push (nb, etherhdr_size);
if (err)
return err;
eth = (struct etherhdr *) nb->data;
@@ -76,6 +84,19 @@ send_ethernet_packet (struct grub_net_network_level_interface *inf,
return err;
inf->card->opened = 1;
}
/* Check and add a vlan-tag if needed. */
if (inf->vlantag != 0)
{
/* Move eth type to the right */
grub_memcpy ((char *) nb->data + etherhdr_size - 2,
(char *) nb->data + etherhdr_size - 6, 2);
/* Add the tag in the middle */
grub_memcpy ((char *) nb->data + etherhdr_size - 6, &vlantag_id, 2);
grub_memcpy ((char *) nb->data + etherhdr_size - 4, (char *) &(inf->vlantag), 2);
}
return inf->card->driver->send (inf->card, nb);
}
@@ -90,10 +111,25 @@ grub_net_recv_ethernet_packet (struct grub_net_buff *nb,
grub_net_link_level_address_t hwaddress;
grub_net_link_level_address_t src_hwaddress;
grub_err_t err;
grub_uint8_t etherhdr_size = sizeof (*eth);
grub_uint16_t vlantag = 0;
/* Check if a vlan-tag is present. If so, the ethernet header is 4 bytes */
/* longer than the original one. The vlantag id is extracted and the header */
/* is reseted to the original size. */
if (grub_get_unaligned16 (nb->data + etherhdr_size - 2) == VLANTAG_IDENTIFIER)
{
vlantag = grub_get_unaligned16 (nb->data + etherhdr_size);
etherhdr_size += 4;
/* Move eth type to the original position */
grub_memcpy((char *) nb->data + etherhdr_size - 6,
(char *) nb->data + etherhdr_size - 2, 2);
}
eth = (struct etherhdr *) nb->data;
type = grub_be_to_cpu16 (eth->type);
err = grub_netbuff_pull (nb, sizeof (*eth));
err = grub_netbuff_pull (nb, etherhdr_size);
if (err)
return err;
@@ -121,13 +157,14 @@ grub_net_recv_ethernet_packet (struct grub_net_buff *nb,
{
/* ARP packet. */
case GRUB_NET_ETHERTYPE_ARP:
grub_net_arp_receive (nb, card);
grub_net_arp_receive (nb, card, &vlantag);
grub_netbuff_free (nb);
return GRUB_ERR_NONE;
/* IP packet. */
case GRUB_NET_ETHERTYPE_IP:
case GRUB_NET_ETHERTYPE_IP6:
return grub_net_recv_ip_packets (nb, card, &hwaddress, &src_hwaddress);
return grub_net_recv_ip_packets (nb, card, &hwaddress, &src_hwaddress,
&vlantag);
}
grub_netbuff_free (nb);
return GRUB_ERR_NONE;

View File

@@ -381,9 +381,8 @@ http_establish (struct grub_file *file, grub_off_t offset, int initial)
ptr = nb->tail;
grub_snprintf ((char *) ptr,
sizeof ("Range: bytes=XXXXXXXXXXXXXXXXXXXX-"
"\r\n"
"\r\n"),
"Range: bytes=%" PRIuGRUB_UINT64_T "-\r\n\r\n",
"Range: bytes=%" PRIuGRUB_UINT64_T "-\r\n",
offset);
grub_netbuff_put (nb, grub_strlen ((char *) ptr));
}
@@ -450,6 +449,7 @@ http_seek (struct grub_file *file, grub_off_t off)
}
file->device->net->stall = 0;
file->device->net->eof = 0;
file->device->net->offset = off;
data = grub_zalloc (sizeof (*data));

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