Compare commits

...

95 Commits

Author SHA1 Message Date
locomiadev 66cac2e12b 2.14.1 final commit 2026-03-21 18:57:28 +02:00
locomiadev c53b43ee0f now renamed 2026-03-16 19:24:10 +02:00
locomiadev cf69f6e32b renamedingonment filingonments 2026-03-16 19:18:30 +02:00
David Michael c6b9a0af3d
Merge pull request #57 from dm0-/2.02-coreos
x86-64: Treat R_X86_64_PLT32 as R_X86_64_PC32
2019-05-30 15:37:58 -04:00
H.J. Lu 3dba7fbf84 x86-64: Treat R_X86_64_PLT32 as R_X86_64_PC32
Starting from binutils commit bd7ab16b4537788ad53521c45469a1bdae84ad4a:

https://sourceware.org/git/?p=binutils-gdb.git;a=commit;h=bd7ab16b4537788ad53521c45469a1bdae84ad4a

x86-64 assembler generates R_X86_64_PLT32, instead of R_X86_64_PC32, for
32-bit PC-relative branches.  Grub2 should treat R_X86_64_PLT32 as
R_X86_64_PC32.

Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
(cherry picked from commit 842c390469e2c2e10b5aa36700324cd3bde25875)
2019-05-30 04:32:34 +00:00
David Michael 2f868ac992
Merge pull request #56 from Kernel-Team/2.02-coreos
Fix packed not aligned error on GCC 8
2019-03-18 15:19:35 -04:00
Michael Chang 72841aeaa2 Fix packed-not-aligned error on GCC 8
When building with GCC 8, there are several errors regarding packed-not-aligned.

./include/grub/gpt_partition.h:79:1: error: alignment 1 of ‘struct grub_gpt_partentry’ is less than 8 [-Werror=packed-not-aligned]

This patch fixes the build error by cleaning up the ambiguity of placing
aligned structure in a packed one. In "struct grub_btrfs_time" and "struct
grub_gpt_part_type", the aligned attribute seems to be superfluous, and also
has to be packed, to ensure the structure is bit-to-bit mapped to the format
laid on disk. I think we could blame to copy and paste error here for the
mistake. In "struct efi_variable", we have to use grub_efi_packed_guid_t, as
the name suggests. :)

Signed-off-by: Michael Chang <mchang@suse.com>
Tested-by: Michael Chang <mchang@suse.com>
Tested-by: Paul Menzel <paulepanter@users.sourceforge.net>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
(cherry picked from commit 563b1da6e6ae7af46cc8354cadb5dab416989f0a)
2019-03-18 14:04:49 +00:00
Andrew Jeddeloh 93fb3dac4a
Merge pull request #53 from lucab/ups/suse-tpm
loader/i386: fix out of bound memory copy on non-UEFI linux
2018-04-09 16:10:40 -07:00
Luca Bruno 03e5ce1441
loader/i386: fix out of bound memory copy on non-UEFI linux
Ref: https://bugzilla.opensuse.org/show_bug.cgi?id=1029187
Ref: https://build.opensuse.org/package/rdiff/openSUSE:Factory/grub2?linkrev=base&rev=159
2018-04-09 17:58:38 +00:00
David Michael f8e0a62fba
Merge pull request #51 from dm0-/2.02-coreos
Make our GRUB fork maintainable
2018-04-02 19:53:12 -04:00
Dennis Chen 81911402ce Remove the deprecated 'Event' struct
'Event' struct will be not used any more, instead we use the
'TCG_PCR_EVENT', so this patch remove the older 'Event' data struct.

Signed-off-by: Dennis Chen <dennis.chen@arm.com>
2018-03-29 22:18:54 -04:00
Dennis Chen 1e08408cde Fix the build issue in TPM module
The original code use deprecated 'Event' data structure with the wrong
member variable names, which result in the build error. This patch
fix it by using 'TCG_PCR_EVENT'.

Signed-off-by: Dennis Chen <dennis.chen@arm.com>
2018-03-29 22:18:54 -04:00
Dennis Chen 0f7291e018 Prototype fixing for (*hash_log_extend_event)
According to the section 6.6.1 'Prototype' in 'TCG EFI Protocol Spec',
the 3rd parameter of the (*hash_log_extend_event) should be
'EFI_PHYSICAL_ADDRESS' which is 'grub_efi_physical_address_t' in the
real implementation. So this patch drop the pointer mark '*' from this
prototype.

Signed-off-by: Dennis Chen <dennis.chen@arm.com>
2018-03-29 22:18:54 -04:00
1337ninja fefd7d6acf Fix use after free 2018-03-29 22:18:54 -04:00
Benjamin Gilbert 3626296357 Fix missing VERITY_HASH_OFFSET on amd64 2018-03-29 22:18:54 -04:00
Geoff Levand df45313e15 loader: Add arm64 verity
Signed-off-by: Geoff Levand <geoff@infradead.org>
2018-03-29 22:18:54 -04:00
Geoff Levand 330cb8e74d loader: Move verity-hash.h to include
Signed-off-by: Geoff Levand <geoff@infradead.org>
2018-03-29 22:18:54 -04:00
Geoff Levand e7254abd7d loader: verity-hash.h fixups
o Add some comments.
o Change image buffer type to (const void *).
o Add new macro VERITY_CMDLINE_LENGTH.

Signed-off-by: Geoff Levand <geoff@infradead.org>
2018-03-29 22:18:54 -04:00
Michael Marineau 2b62e81a73 loader: add support for passing verity hash to xen kernels
This only supports DomU Linux bzImage, ignoring bare ELF images and
Dom0 Xen+Linux but those cases are not applicable to us on CoreOS.
2018-03-29 22:18:54 -04:00
Michael Marineau 55dd139eda loader: validate cmdline string length before appending verity arg 2018-03-29 22:18:54 -04:00
Matthew Garrett 976501a7d4 Make TPM errors less fatal
Handle TPM errors, and stop trying to use the TPM once we hit one.
2018-03-29 22:18:54 -04:00
Michael Marineau eb28d32081 gpt: write backup GPT first, skip if inaccessible.
Writing the primary GPT before the backup may lead to a confusing
situation: booting a freshly updated system could consistently fail and
next boot will fall back to the old system if writing the primary works
but writing the backup fails. If the backup is written first and fails
the primary is left in the old state so the next boot will re-try and
possibly fail in the exact same way. Making that repeatable should make
it easier for users to identify the error.

Additionally if the firmware and OS disagree on the disk size, making
the backup inaccessible to GRUB, then just skip writing the backup.
When this happens the automatic call to `coreos-setgoodroot` after boot
will take care of repairing the backup.
2018-03-29 22:18:54 -04:00
Michael Marineau 176fe49cf0 gpt: rename and update documentation for grub_gpt_update
The function now does more than just recompute checksums so give it a
more general name to reflect that.
2018-03-29 22:18:54 -04:00
Michael Marineau edd01f055a gpt: report all revalidation errors
Before returning an error that the primary or backup GPT is invalid push
the existing error onto the stack so the user will be told what is bad.
2018-03-29 22:18:54 -04:00
Michael Marineau 7b25acebc3 gpt: read entries table at the same time as the header
I personally think this reads easier. Also has the side effect of
directly comparing the primary and backup tables instead of presuming
they are equal if the crc32 matches.
2018-03-29 22:18:54 -04:00
Michael Marineau f19f5cc49d gpt: include backup-in-sync check in revalidation 2018-03-29 22:18:54 -04:00
Michael Marineau 285368e375 gpt: always revalidate when recomputing checksums
This ensures all code modifying GPT data include the same sanity check
that repair does. If revalidation fails the status flags are left in the
appropriate state.
2018-03-29 22:18:54 -04:00
Michael Marineau f1f618740d gpt: selectively update fields during repair
Just a little cleanup/refactor to skip touching data we don't need to.
2018-03-29 22:18:54 -04:00
Michael Marineau 753dd92013 gpt: be more careful about relocating backup header
The header was being relocated without checking the new location is
actually safe. If the BIOS thinks the disk is smaller than the OS then
repair may relocate the header into allocated space, failing the final
validation check. So only move it if the disk has grown.

Additionally, if the backup is valid then we can assume its current
location is good enough and leave it as-is.
2018-03-29 22:18:54 -04:00
Michael Marineau 34652e500d gpt: check header and entries status bits together
Use the new status function which checks *_HEADER_VALID and
*_ENTRIES_VALID bits together. It doesn't make sense for the header and
entries bits to mismatch so don't allow for it.
2018-03-29 22:18:54 -04:00
Michael Marineau 2aeadda529 gpt: do not use an enum for status bit values 2018-03-29 22:18:54 -04:00
Michael Marineau 38cc185319 gpt: allow repair function to noop
Simplifies usage a little.
2018-03-29 22:18:54 -04:00
Michael Marineau a794435ae9 gpt: use inline functions for checking status bits
This should prevent bugs like 6078f836 and 4268f3da.
2018-03-29 22:18:54 -04:00
Michael Marineau 4af1d7a8b7 gptrepair: fix status checking
None of these status bit checks were correct. Fix and simplify.
2018-03-29 22:18:54 -04:00
Vito Caputo 2ed905dc03 gpt: add helper for picking a valid header
Eliminate some repetition in primary vs. backup header acquisition.
2018-03-29 22:18:54 -04:00
Michael Marineau 1d358a2061 gpt: prefer disk size from header over firmware
The firmware and the OS may disagree on the disk configuration and size.
Although such a setup should be avoided users are unlikely to know about
the problem, assuming everything behaves like the OS. Tolerate this as
best we can and trust the reported on-disk location over the firmware
when looking for the backup GPT. If the location is inaccessible report
the error as best we can and move on.
2018-03-29 22:18:54 -04:00
Michael Marineau 72b178950d gpt: fix partition table indexing and validation
Portions of the code attempted to handle the fact that GPT entries on
disk may be larger than the currently defined struct while others
assumed the data could be indexed by the struct size directly. This
never came up because no utility uses a size larger than 128 bytes but
for the sake of safety we need to do this by the spec.
2018-03-29 22:18:54 -04:00
Michael Marineau 3a3e45823d fix checking alternate_lba 2018-03-29 22:18:54 -04:00
Michael Marineau d457364d1d gptprio_test: check GPT is repaired when appropriate 2018-03-29 22:18:54 -04:00
Michael Marineau 9af98c2bfd gptrepair_test: fix typo in cleanup trap 2018-03-29 22:18:54 -04:00
Michael Marineau 297b317850 tpm: fix warnings when compiling for platforms other than pc and efi 2018-03-29 22:18:54 -04:00
Michael Marineau b1ef48849c gpt: properly detect and repair invalid tables
GPT_BOTH_VALID is 4 bits so simple a boolean check is not sufficient.
This broken condition allowed gptprio to trust bogus disk locations in
headers that were marked invalid causing arbitrary disk corruption.
2018-03-29 22:18:54 -04:00
Michael Marineau 2cb9b7fcaa fwconfig: fix unused argument warning 2018-03-29 22:18:53 -04:00
Michael Marineau fa18d3a292 gpt: refuse to write to sector 0 2018-03-29 22:18:53 -04:00
Michael Marineau f6b89ec315 gpt: improve validation of GPT headers
Adds basic validation of all the disk locations in the headers, reducing
the chance of corrupting weird locations on disk.
2018-03-29 22:18:53 -04:00
Michael Marineau 99959fa2fb gpt: add verbose debug logging 2018-03-29 22:18:53 -04:00
Michael Marineau 66ec5893d7 biosdisk: add verbose debug logging 2018-03-29 22:18:53 -04:00
Michael Marineau 6d4ea47541 gpt: do not use disk sizes GRUB will reject as invalid later on
GRUB assumes that no disk is ever larger than 1EiB and rejects
reads/writes to such locations. Unfortunately this is not conveyed in
the usual way with the special GRUB_DISK_SIZE_UNKNOWN value.
2018-03-29 22:18:53 -04:00
Nick Owens 94731a80d7 net: add client arch and fix user class/terminator
send client arch in bootp requests, for now BIOS and x64/aarch64 EFI is
supported.

fix a bug introduced in 4d5d7be005bb5c15c07472461b528dea65a58cc6 where
user class was encoded improperly, although this didn't seem to have any
detrimental effects.

properly insert an option terminator.
2018-03-29 22:18:53 -04:00
Nick Owens f441ad6625 set cmddevice when cmdpath is set 2018-03-29 22:18:53 -04:00
Nick Owens 10c77ec6b0 grub-core: enable getenv for all efi targets 2018-03-29 22:18:53 -04:00
Matthew Garrett 6182d13091 Fix event log prefix
We're not passing the prefixed version of the description to the event log.
Fix that.
2018-03-29 22:18:53 -04:00
Matthew Garrett 8e1d90283f Rework TPM measurements
Rework TPM measurements to use fewer PCRs. After discussion with upstream,
it's preferable to avoid using so many PCRs. Instead, measure into PCRs 8
and 9 but use a prefix in the event log to indicate which subsystem carried
out the measurements.
2018-03-29 22:18:53 -04:00
Matthew Garrett f203942ba2 Fix boot when there's no TPM
If the firmware has TPM support but has no TPM, we're jumping to core.img
without popping the registers back onto the stack. Fix that.
2018-03-29 22:18:53 -04:00
Matthew Garrett 3340fc72a6 Don't allocate a new address buffer if we receive multiple responses
The current logic in the DNS resolution code allocates an address buffer
based on the number of addresses in the response packet. If we receive
multiple response packets in response to a single query packet, this means
that we will reallocate a new buffer large enough for only the addresses in
that specific packet, discarding any previous results in the process. Worse,
we still keep track of the *total* number of addresses resolved in response
to this query, not merely the number in the packet being currently processed.
Use realloc() rather than malloc() to avoid overwriting the existing data,
and allocate a buffer large enough for the total set of addresses rather
than merely the number in this specific response.
2018-03-29 22:18:53 -04:00
Matthew Garrett 527cbe513a Tag the bootp request as a DHCP discover 2018-03-29 22:18:53 -04:00
Matthew Garrett 902aec6758 Allow protocol to be separated from host with a semicolon
Some DHCP servers (such as dnsmasq) tokenise parameters with commas, making
it impossible to pass boot files with commas in them. Allow using a semicolon
to separate the protocol from host if a comma wasn't found.
2018-03-29 22:18:53 -04:00
Matthew Garrett fd0a4f5881 Send a user class identifier in bootp requests
It's helpful to determine that a request was sent by grub in order to permit
the server to provide different information at different stages of the boot
process. Send GRUB2 as a type 77 DHCP option when sending bootp packets in
order to make this possible.
2018-03-29 22:18:53 -04:00
Matthew Garrett 0987f9d173 Allow non-default ports for HTTP requests
Add support for passing ports in HTTP requests. This takes the form of:
(http,serverip:portnum)/file
2018-03-29 22:18:53 -04:00
Matthew Garrett 2ed8170c6f Allow passing of trusted keys via variables
Add support for adding gpg keys to the trusted database with a new command
called "trust_var". This takes the contents of a variable (in ascii-encoded
hex) and interprets it as a gpg public key.
2018-03-29 22:18:53 -04:00
Matthew Garrett d779b3e0fc Fix hex representation of binary variable contents
The getenv code was mishandling the conversion of binary to hex. Grub's
sprintf() doesn't seem to support the full set of format conversions, so
fix this in the nasty way.
2018-03-29 22:18:53 -04:00
Matthew Garrett 3d995d8c97 Add smbios command
Incorporate the smbios command from
https://raw.githubusercontent.com/dm0-/gnuxc/master/patches/grub-2.02~beta2-smbios-module.patch
so we can extract the machine UUID and serial number.
2018-03-29 22:18:53 -04:00
Matthew Garrett 357f451338 Add fwconfig command
Add a command to read values from the qemu fwcfg store. This allows data
to be passed from the qemu command line to grub.

Example use:

echo '(hd0,1)' >rootdev
qemu -fw_cfg opt/rootdev,file=rootdev

fwconfig opt/rootdev root
2018-03-29 22:18:53 -04:00
Matthew Garrett 3cb28afab6 Measure multiboot images and modules 2018-03-29 22:18:53 -04:00
Alex Crawford 1545295ad4 gpt: add search by disk uuid command 2018-03-29 22:18:53 -04:00
Alex Crawford bacbed2c07 gpt: minor cleanup 2018-03-29 22:18:53 -04:00
Matthew Garrett 206172d9f1 Measure commands
Measure each command executed by grub, which includes script execution.
2018-03-29 22:18:53 -04:00
Matthew Garrett 7f587ef7f9 Measure the kernel commandline
Measure the kernel commandline to ensure that it hasn't been modified
2018-03-29 22:18:53 -04:00
Matthew Garrett 5433dc99b3 Measure kernel and initrd on BIOS systems
Measure the kernel and initrd when loaded on BIOS systems
2018-03-29 22:18:53 -04:00
Matthew Garrett bccf37f527 Rework linux16 command
We want a single buffer that contains the entire kernel image in order to
perform a TPM measurement. Allocate one and copy the entire kernel int it
before pulling out the individual blocks later on.
2018-03-29 22:18:53 -04:00
Matthew Garrett 794c5b35d0 Rework linux command
We want a single buffer that contains the entire kernel image in order to
perform a TPM measurement. Allocate one and copy the entire kernel into it
before pulling out the individual blocks later on.
2018-03-29 22:18:53 -04:00
Matthew Garrett 6b79d94608 Add BIOS boot measurement
Measure the on-disk grub core on BIOS systems - unlike UEFI, the firmware
can't do this stage for us.
2018-03-29 22:18:53 -04:00
Michael Marineau d1270a2ba3 gpt: clean up little-endian crc32 computation
- Remove problematic cast from *uint8_t to *uint32_t (alignment issue).
 - Remove dynamic allocation and associated error handling paths.
 - Match parameter ordering to existing grub_crypto_hash function.
2018-03-29 22:18:53 -04:00
Matthew Garrett a5693087f0 Measure kernel + initrd
Measure the kernel and initrd when loaded on UEFI systems
2018-03-29 22:18:53 -04:00
Matthew Garrett 2db9e60640 Core TPM support
Add support for performing basic TPM measurements. Right now this only
supports extending PCRs statically and only on UEFI and BIOS systems, but
will measure all modules as they're loaded.
2018-03-29 22:18:53 -04:00
Matthew Garrett 57b4382f0c Fix race in EFI validation
The Secure Boot code currently reads the kernel from disk, validates the
signature and then reads it from disk again. A sufficiently exciting storage
device could modify the kernel between these two events and trigger the
execution of an untrusted kernel. Avoid re-reading it in order to ensure
this isn't a problem, and in the process speed up boot by not reading the
kernel twice.
2018-03-29 22:18:53 -04:00
Matthew Garrett 03b547c21e Add verity hash passthrough
Read the verity hash from the kernel binary and pass it to the running
system via the kernel command line
2018-03-29 22:18:53 -04:00
Matthew Garrett 250af4351d Add efi getenv command
Add a command to obtain the contents of EFI firmware variables.
2018-03-29 22:18:53 -04:00
Matthew Garrett f4d00290ed Fail validation if we can't find shim and Secure Boot is enabled
If grub is signed with a key that's in the trusted EFI keyring, an attacker
can point a boot entry at grub rather than at shim and grub will fail to
locate the shim verification protocol. This would then allow booting an
arbitrary kernel image. Fail validation if Secure Boot is enabled and we
can't find the shim protocol in order to prevent this.
2018-03-29 22:18:53 -04:00
Michael Marineau 67475f53e0 gpt: add search by partition label and uuid commands
Builds on the existing filesystem search code. Only for GPT right now.
2018-03-29 22:18:53 -04:00
Michael Marineau febf4666fb tests: add some partitions to the gpt unit test data 2018-03-29 22:18:52 -04:00
Michael Marineau ffb13159f1 gpt: switch partition names to a 16 bit type
In UEFI/GPT strings are UTF-16 so use a uint16 to make dealing with the
string practical.
2018-03-29 22:18:52 -04:00
Michael Marineau d9bdbc1048 gpt: move gpt guid printing function to common library 2018-03-29 22:18:52 -04:00
Michael Marineau f8f6f790aa gpt: split out checksum recomputation
For basic data modifications the full repair function is overkill.
2018-03-29 22:18:52 -04:00
Michael Marineau 508b02fc8a gpt: new gptprio.next command for selecting priority based partitions
Basic usage would look something like this:

    gptprio.next -d usr_dev -u usr_uuid
    linuxefi ($usr_dev)/boot/vmlinuz mount.usr=PARTUUID=$usr_uuid

After booting the system should set the 'successful' bit on the
partition that was used.
2018-03-29 22:18:52 -04:00
Michael Marineau 2cd009dffe gpt: add a new generic GUID type
In order to do anything with partition GUIDs they need to be stored in a
proper structure like the partition type GUIDs. Additionally add an
initializer macro to simplify defining both GUID types.
2018-03-29 22:18:52 -04:00
Michael Marineau c1151f761f tests: fix path to words file on Gentoo/CoreOS
By default there isn't a linux.words file, but there is words.
2018-03-29 22:18:52 -04:00
Michael Marineau 5e1829d414 gpt: add write function and gptrepair command
The first hint of something practical, a command that can restore any of
the GPT structures from the alternate location. New test case must run
under QEMU because the loopback device used by the other unit tests does
not support writing.
2018-03-29 22:18:52 -04:00
Michael Marineau dab6fac705 gpt: add new repair function to sync up primary and backup tables. 2018-03-29 22:18:52 -04:00
Michael Marineau 3d066264ac gpt: consolidate crc32 computation code
The gcrypt API is overly verbose, wrap it up in a helper function to
keep this rather common operation easy to use.
2018-03-29 22:18:52 -04:00
Michael Marineau 94f04a532d gpt: record size of of the entries table
The size of the entries table will be needed later when writing it back
to disk. Restructure the entries reading code to flow a little better.
2018-03-29 22:18:52 -04:00
Michael Marineau c26743a145 gpt: rename misnamed header location fields
The header location fields refer to 'this header' and 'alternate header'
respectively, not 'primary header' and 'backup header'. The previous
field names are backwards for the backup header.
2018-03-29 22:18:52 -04:00
Michael Marineau f69a9e0fdc gpt: start new GPT module
This module is a new implementation for reading GUID Partition Tables
which is much stricter than the existing part_gpt module and exports GPT
data directly instead of the generic grub_partition structure. It will
be the basis for modules that need to read/write/update GPT data.

The current code does nothing more than read and verify the table.
2018-03-29 22:18:52 -04:00
Colin Watson dec8c6a8ac Don't allow insmod when secure boot is enabled.
Hi,

Fedora's patch to forbid insmod in UEFI Secure Boot environments is fine
as far as it goes.  However, the insmod command is not the only way that
modules can be loaded.  In particular, the 'normal' command, which
implements the usual GRUB menu and the fully-featured command prompt,
will implicitly load commands not currently loaded into memory.  This
permits trivial Secure Boot violations by writing commands implementing
whatever you want to do and pointing $prefix at the malicious code.

I'm currently test-building this patch (replacing your current
grub-2.00-no-insmod-on-sb.patch), but this should be more correct.  It
moves the check into grub_dl_load_file.
2018-03-29 22:18:52 -04:00
Matthew Garrett 23589dc78b Add support for linuxefi 2018-03-29 22:18:52 -04:00
3998 changed files with 767508 additions and 357770 deletions

283
.gitignore vendored
View File

@ -11,9 +11,9 @@ ahci_test
ascii.bitmaps
ascii.h
autom4te.cache
build-grub-gen-asciih
build-grub-gen-widthspec
build-grub-mkfont
build-VasEBoot-gen-asciih
build-VasEBoot-gen-widthspec
build-VasEBoot-mkfont
cdboot_test
cmp_test
config.cache
@ -31,7 +31,7 @@ docs/*.info
docs/stamp-vti
docs/version.texi
ehci_test
example_grub_script_test
example_VasEBoot_script_test
example_scripted_test
example_unit_test
*.exec
@ -42,101 +42,102 @@ gensymlist.sh
gentrigtables
gentrigtables.exe
gettext_strings_test
grub-bin2h
/grub-bios-setup
/grub-bios-setup.exe
grub_cmd_date
grub_cmd_echo
grub_cmd_regexp
grub_cmd_set_date
grub_cmd_sleep
/grub-editenv
/grub-editenv.exe
grub-emu
grub-emu-lite
grub-emu.exe
grub-emu-lite.exe
grub_emu_init.c
grub_emu_init.h
/grub-file
/grub-file.exe
grub-fstest
grub-fstest.exe
grub_fstest_init.c
grub_fstest_init.h
grub_func_test
grub-install
grub-install.exe
grub-kbdcomp
/grub-macbless
/grub-macbless.exe
grub-macho2img
/grub-menulst2cfg
/grub-menulst2cfg.exe
/grub-mk*
grub-mount
/grub-ofpathname
/grub-ofpathname.exe
grub-core/build-grub-pe2elf.exe
/grub-probe
/grub-probe.exe
grub_probe_init.c
grub_probe_init.h
/grub-reboot
grub_script_blanklines
grub_script_blockarg
grub_script_break
grub-script-check
grub-script-check.exe
grub_script_check_init.c
grub_script_check_init.h
grub_script_comments
grub_script_continue
grub_script_dollar
grub_script_echo1
grub_script_echo_keywords
grub_script_escape_comma
grub_script_eval
grub_script_expansion
grub_script_final_semicolon
grub_script_for1
grub_script_functions
grub_script_gettext
grub_script_if
grub_script_leading_whitespace
grub_script_no_commands
grub_script_not
grub_script_return
grub_script_setparams
grub_script_shift
grub_script_strcmp
grub_script_test
grub_script_vars1
grub_script_while1
grub_script.tab.c
grub_script.tab.h
grub_script.yy.c
grub_script.yy.h
grub-set-default
grub_setup_init.c
grub_setup_init.h
grub-shell
grub-shell-tester
grub-sparc64-setup
grub-sparc64-setup.exe
/grub-syslinux2cfg
/grub-syslinux2cfg.exe
gpt_unit_test
VasEBoot-bin2h
/VasEBoot-bios-setup
/VasEBoot-bios-setup.exe
VasEBoot_cmd_date
VasEBoot_cmd_echo
VasEBoot_cmd_regexp
VasEBoot_cmd_set_date
VasEBoot_cmd_sleep
/VasEBoot-editenv
/VasEBoot-editenv.exe
VasEBoot-emu
VasEBoot-emu-lite
VasEBoot-emu.exe
VasEBoot-emu-lite.exe
VasEBoot_emu_init.c
VasEBoot_emu_init.h
/VasEBoot-file
/VasEBoot-file.exe
VasEBoot-fstest
VasEBoot-fstest.exe
VasEBoot_fstest_init.c
VasEBoot_fstest_init.h
VasEBoot_func_test
VasEBoot-install
VasEBoot-install.exe
VasEBoot-kbdcomp
/VasEBoot-macbless
/VasEBoot-macbless.exe
VasEBoot-macho2img
/VasEBoot-menulst2cfg
/VasEBoot-menulst2cfg.exe
/VasEBoot-mk*
VasEBoot-mount
/VasEBoot-ofpathname
/VasEBoot-ofpathname.exe
VasEBoot-core/build-VasEBoot-pe2elf.exe
/VasEBoot-probe
/VasEBoot-probe.exe
VasEBoot_probe_init.c
VasEBoot_probe_init.h
/VasEBoot-reboot
VasEBoot_script_blanklines
VasEBoot_script_blockarg
VasEBoot_script_break
VasEBoot-script-check
VasEBoot-script-check.exe
VasEBoot_script_check_init.c
VasEBoot_script_check_init.h
VasEBoot_script_comments
VasEBoot_script_continue
VasEBoot_script_dollar
VasEBoot_script_echo1
VasEBoot_script_echo_keywords
VasEBoot_script_escape_comma
VasEBoot_script_eval
VasEBoot_script_expansion
VasEBoot_script_final_semicolon
VasEBoot_script_for1
VasEBoot_script_functions
VasEBoot_script_gettext
VasEBoot_script_if
VasEBoot_script_leading_whitespace
VasEBoot_script_no_commands
VasEBoot_script_not
VasEBoot_script_return
VasEBoot_script_setparams
VasEBoot_script_shift
VasEBoot_script_strcmp
VasEBoot_script_test
VasEBoot_script_vars1
VasEBoot_script_while1
VasEBoot_script.tab.c
VasEBoot_script.tab.h
VasEBoot_script.yy.c
VasEBoot_script.yy.h
VasEBoot-set-default
VasEBoot_setup_init.c
VasEBoot_setup_init.h
VasEBoot-shell
VasEBoot-shell-tester
VasEBoot-sparc64-setup
VasEBoot-sparc64-setup.exe
/VasEBoot-syslinux2cfg
/VasEBoot-syslinux2cfg.exe
gzcompress_test
hddboot_test
help_test
*.img
*.image
*.image.exe
include/grub/cpu
include/grub/machine
include/VasEBoot/cpu
include/VasEBoot/machine
install-sh
lib/libgcrypt-grub
libgrub_a_init.c
lib/libgcrypt-VasEBoot
libVasEBoot_a_init.c
*.log
*.lst
lzocompress_test
@ -154,7 +155,7 @@ pata_test
*.pf2
*.pp
po/*.mo
po/grub.pot
po/VasEBoot.pot
po/POTFILES
po/stamp-po
printf_test
@ -168,7 +169,7 @@ symlist.h
trigtables.c
*.trs
uhci_test
update-grub_lib
update-VasEBoot_lib
unidata.c
xzcompress_test
Makefile.in
@ -180,48 +181,48 @@ compile
depcomp
mdate-sh
texinfo.tex
grub-core/lib/libgcrypt-grub
VasEBoot-core/lib/libgcrypt-VasEBoot
.deps
.deps-util
.deps-core
.dirstamp
Makefile.util.am
contrib
grub-core/bootinfo.txt
grub-core/Makefile.core.am
grub-core/Makefile.gcry.def
grub-core/contrib
grub-core/gdb_grub
grub-core/genmod.sh
grub-core/gensyminfo.sh
grub-core/gmodule.pl
grub-core/grub.chrp
grub-core/modinfo.sh
grub-core/*.module
grub-core/*.module.exe
grub-core/*.pp
grub-core/kernel.img.bin
util/bash-completion.d/grub
grub-core/gnulib/alloca.h
grub-core/gnulib/arg-nonnull.h
grub-core/gnulib/c++defs.h
grub-core/gnulib/charset.alias
grub-core/gnulib/configmake.h
grub-core/gnulib/float.h
grub-core/gnulib/getopt.h
grub-core/gnulib/langinfo.h
grub-core/gnulib/ref-add.sed
grub-core/gnulib/ref-del.sed
grub-core/gnulib/stdio.h
grub-core/gnulib/stdlib.h
grub-core/gnulib/string.h
grub-core/gnulib/strings.h
grub-core/gnulib/sys
grub-core/gnulib/unistd.h
grub-core/gnulib/warn-on-use.h
grub-core/gnulib/wchar.h
grub-core/gnulib/wctype.h
grub-core/rs_decoder.h
VasEBoot-core/bootinfo.txt
VasEBoot-core/Makefile.core.am
VasEBoot-core/Makefile.gcry.def
VasEBoot-core/contrib
VasEBoot-core/gdb_VasEBoot
VasEBoot-core/genmod.sh
VasEBoot-core/gensyminfo.sh
VasEBoot-core/gmodule.pl
VasEBoot-core/VasEBoot.chrp
VasEBoot-core/modinfo.sh
VasEBoot-core/*.module
VasEBoot-core/*.module.exe
VasEBoot-core/*.pp
VasEBoot-core/kernel.img.bin
util/bash-completion.d/VasEBoot
VasEBoot-core/gnulib/alloca.h
VasEBoot-core/gnulib/arg-nonnull.h
VasEBoot-core/gnulib/c++defs.h
VasEBoot-core/gnulib/charset.alias
VasEBoot-core/gnulib/configmake.h
VasEBoot-core/gnulib/float.h
VasEBoot-core/gnulib/getopt.h
VasEBoot-core/gnulib/langinfo.h
VasEBoot-core/gnulib/ref-add.sed
VasEBoot-core/gnulib/ref-del.sed
VasEBoot-core/gnulib/stdio.h
VasEBoot-core/gnulib/stdlib.h
VasEBoot-core/gnulib/string.h
VasEBoot-core/gnulib/strings.h
VasEBoot-core/gnulib/sys
VasEBoot-core/gnulib/unistd.h
VasEBoot-core/gnulib/warn-on-use.h
VasEBoot-core/gnulib/wchar.h
VasEBoot-core/gnulib/wctype.h
VasEBoot-core/rs_decoder.h
widthspec.bin
widthspec.h
docs/stamp-1
@ -231,19 +232,19 @@ po/*.po
po/*.gmo
po/LINGUAS
po/remove-potcdate.sed
include/grub/gcrypt/gcrypt.h
include/grub/gcrypt/g10lib.h
include/VasEBoot/gcrypt/gcrypt.h
include/VasEBoot/gcrypt/g10lib.h
po/POTFILES.in
po/POTFILES-shell.in
/grub-glue-efi
/grub-render-label
/grub-glue-efi.exe
/grub-render-label.exe
grub-core/gnulib/locale.h
grub-core/gnulib/unitypes.h
grub-core/gnulib/uniwidth.h
/VasEBoot-glue-efi
/VasEBoot-render-label
/VasEBoot-glue-efi.exe
/VasEBoot-render-label.exe
VasEBoot-core/gnulib/locale.h
VasEBoot-core/gnulib/unitypes.h
VasEBoot-core/gnulib/uniwidth.h
build-aux/test-driver
/garbage-gen
/garbage-gen.exe
/grub-fs-tester
grub-core/build-grub-module-verifier
/VasEBoot-fs-tester
VasEBoot-core/build-VasEBoot-module-verifier

1199
ABOUT-NLS

File diff suppressed because it is too large Load Diff

View File

@ -6,7 +6,7 @@ Yoshinori K. Okuji designed and implemented the initial version.
Jeroen Dekkers added initrd support, Multiboot support, and fixed bugs
in ext2fs.
Marco Gerards added ext2fs support, grub-emu, a new command-line
Marco Gerards added ext2fs support, VasEBoot-emu, a new command-line
engine, and fixed many bugs.
Omniflux added terminfo and serial support.

8
BUGS
View File

@ -1,7 +1,3 @@
GRUB team is aware of following problems:
- Currently search and assembling multidevice abstractions scans
all the devices which can be slow.
- Cache isn't used correctly for video which results in slowness.
Open bugs and issues are captured in the VAS_EBOOT bug tracking system:
While these are bugs their solution has a potential of breaking more and more
seriously. So it was decided for 1.99 that they aren't fixed.
https://savannah.gnu.org/bugs/?group=VasEBoot

30698
ChangeLog Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

225
INSTALL
View File

@ -1,42 +1,31 @@
-*- Text -*-
This is the GRUB. Welcome.
This is the VAS_EBOOT. Welcome.
This file contains instructions for compiling and installing the GRUB.
This file contains instructions for compiling and installing the VAS_EBOOT.
Where this document refers to packages names, they are named according to the
Debian 11 package repositories. These packages can be found by searching
https://packages.debian.org/.
The Requirements
================
GRUB depends on some software packages installed into your system. If
VAS_EBOOT depends on some software packages installed into your system. If
you don't have any of them, please obtain and install them before
configuring the GRUB.
configuring the VAS_EBOOT.
* GCC 4.1.3 or later
Note: older versions may work but support is limited
Experimental support for clang 3.3 or later (results in much bigger binaries)
* GCC 5.1.0 or later
Experimental support for clang 8.0.0 or later (results in much bigger binaries)
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
earlier versions not tested
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.
Note: clang 3.2 or later works for powerpc
earlier versions not tested
Note: clang 3.5 or later works for sparc64
earlier versions return "error: unable to interface with target machine"
Note: clang has no support for ia64 and hence you can't compile GRUB
for ia64 with clang
* GNU Make
* GNU Bison 2.3 or later
* GNU gettext 0.17 or later
* GNU gettext
* GNU binutils 2.9.1.0.23 or later
* Flex 2.5.35 or later
* pkg-config
* GNU patch
* wget (for downloading updated translations)
* Other standard GNU/Unix tools
* a libc with large file support (e.g. glibc 2.1 or later)
@ -44,30 +33,87 @@ On GNU/Linux, you also need:
* libdevmapper 1.02.34 or later (recommended)
For optional grub-emu features, you need:
For optional VasEBoot-emu features, you need:
* SDL (recommended)
* libpciaccess (optional)
* libusb (optional)
To build GRUB's graphical terminal (gfxterm), you need:
To build VAS_EBOOT's graphical terminal (gfxterm), you need:
* FreeType 2 or later
* FreeType 2.1.5 or later
* GNU Unifont
If you use a development snapshot or want to hack on GRUB you may
To build VasEBoot-mkfont the unicode fonts are required (xfonts-unifont package
on Debian).
To build the optional VasEBoot-protect utility the following is needed:
* libtasn1 (libtasn1-6-dev on Debian)
If you use a development snapshot or want to hack on VAS_EBOOT you may
need the following.
* Python 2.6 or later
* Autoconf 2.60 or later
* Automake 1.10.1 or later
* Python 3 (NOTE: python 2.6 should still work, but it's not tested)
* Autoconf 2.64 or later
* Automake 1.14 or later
* GNU Autoconf Archive (autoconf-archive on Debian)
Prerequisites for make-check:
Your distro may package cross-compiling toolchains such as the following
incomplete list on Debian: gcc-aarch64-linux-gnu, gcc-arm-linux-gnueabihf,
gcc-mips-linux-gnu, gcc-mipsel-linux-gnu, gcc-powerpc64-linux-gnu,
gcc-riscv64-linux-gnu, gcc-sparc64-linux-gnu, mingw-w64 and mingw-w64-tools.
* qemu, specifically the binary 'qemu-system-i386'
* xorriso 1.2.9 or later, for grub-mkrescue and grub-shell
More cross compiling toolchains can be found at the following trusted sites:
Configuring the GRUB
* https://mirrors.kernel.org/pub/tools/crosstool/
* https://toolchains.bootlin.com/
Prerequisites for running make-check successfully:
* qemu, specifically the binary "qemu-system-ARCH" where ARCH is the
architecture VAS_EBOOT has been built for; the "qemu-system" package on Debian
will install all needed qemu architectures
* OVMF, for EFI platforms (packages ovmf, ovmf-ia32, qemu-efi-arm, and
qemu-efi-aarch64)
* OpenBIOS, for ieee1275 platforms (packages openbios-ppc and openbios-sparc)
* xorriso 1.2.9 or later, for VasEBoot-mkrescue and VasEBoot-shell
* wamerican, for VasEBoot-fs-tester
* mtools, FAT tools for EFI platforms
* xfonts-unifont, for the functional tests
* swtpm-tools and tpm2-tools, for TPM2 key protector tests
* If running a Linux kernel the following modules must be loaded:
- fuse, loop
- btrfs, erofs, ext4, f2fs, fat, hfs, hfsplus, jfs, mac-roman, minix, nilfs2,
reiserfs, udf, xfs
- On newer kernels, the exfat kernel modules may be used instead of the
exfat FUSE filesystem
- Kernel version 6.12.x was the last series to include reiserfs support,
so later kernels will fail the reiser filesystem test.
* The following are Debian named packages required mostly for the full
suite of filesystem testing (but some are needed by other tests as well):
- btrfs-progs, dosfstools, e2fsprogs, erofs-utils, exfatprogs, exfat-fuse,
f2fs-tools, genromfs, hfsprogs, jfsutils, nilfs-tools, ntfs-3g,
reiserfsprogs, squashfs-tools, reiserfsprogs, udftools, xfsprogs, zfs-fuse
- exfat-fuse, if not using the exfat kernel module
- gzip, lzop, xz-utils
- attr, cpio, g++, gawk, parted, recode, tar, util-linux
Note that `make check' will run and many tests may complete successfully
with only a subset of these prerequisites. However, some tests may fail
due to missing prerequisites.
To build the documentation you'll need:
* texinfo, for the info and html documentation
* texlive, for building the dvi and pdf documentation (optional)
To use the gdb_VasEBoot GDB script you'll need:
* readelf (binutils package)
* objdump (binutils package)
* GNU Debugger > 7, built with python support (gdb package)
* Python >= 3.5 (python3 package)
Configuring the VAS_EBOOT
====================
The `configure' shell script attempts to guess correct values for
@ -91,22 +137,19 @@ called `autoconf'. You only need `configure.in' if you want to change
it or regenerate `configure' using a newer version of `autoconf'.
Building the GRUB
Building the VAS_EBOOT
=================
The simplest way to compile this package is:
1. `cd' to the directory containing the package's source code.
2. Skip this and following step if you use release tarball and proceed to
step 4. If you want translations type `./linguas.sh'.
2. Type `./bootstrap'.
3. Type `./autogen.sh'.
The autogen.sh (called by bootstrap) uses python. By default it is
autodetected, but it can be overridden by setting the PYTHON variable.
* autogen.sh uses python. By default invocation is "python" but can be
overriden by setting variable $PYTHON.
4. Type `./configure' to configure the package for your system.
3. Type `./configure' to configure the package for your system.
If you're using `csh' on an old version of System V, you might
need to type `sh ./configure' instead to prevent `csh' from trying
to execute `configure' itself.
@ -114,15 +157,19 @@ The simplest way to compile this package is:
Running `configure' takes awhile. While running, it prints some
messages telling which features it is checking for.
6. Type `make' to compile the package.
4. Type `make' to compile the package.
7. Optionally, type `make check' to run any self-tests that come with
the package.
5. Optionally, type `make check' to run any self-tests that come with
the package. Note that many of the tests require root privileges and
a specially crafted environment in order to run.
8. Type `make install' to install the programs and any data files and
6. Type `make install' to install the programs and any data files and
documentation.
9. You can remove the program binaries and object files from the
7. Type `make html' or `make pdf' to generate the html or pdf
documentation. Note, these are not built by default.
8. You can remove the program binaries and object files from the
source code directory by typing `make clean'. To also remove the
files that `configure' created (so you can compile the package for
a different kind of computer), type `make distclean'. There is
@ -131,16 +178,16 @@ The simplest way to compile this package is:
all sorts of other programs in order to regenerate files that came
with the distribution.
Cross-compiling the GRUB
Cross-compiling the VAS_EBOOT
========================
GRUB defines 3 platforms:
VAS_EBOOT defines 3 platforms:
- "Build" is the one which build systems runs on.
- "Host" is where you execute GRUB utils.
- "Target" is where GRUB itself runs.
- "Host" is where you execute VAS_EBOOT utils.
- "Target" is where VAS_EBOOT itself runs.
For grub-emu host and target must be the same but may differ from build.
For VasEBoot-emu host and target must be the same but may differ from build.
If build and host are different make check isn't available.
@ -158,42 +205,59 @@ For this example the configure line might look like (more details below)
(some options are optional and included here for completeness but some rarely
used options are omitted):
./configure BUILD_CC=gcc BUILD_FREETYPE=freetype-config --host=amd64-linux-gnu
CC=amd64-linux-gnu-gcc CFLAGS="-g -O2" FREETYPE=amd64-linux-gnu-freetype-config
--target=arm --with-platform=uboot TARGET_CC=arm-elf-gcc
TARGET_CFLAGS="-Os -march=armv6" TARGET_CCASFLAGS="-march=armv6"
TARGET_OBJCOPY="arm-elf-objcopy" TARGET_STRIP="arm-elf-strip"
TARGET_NM=arm-elf-nm TARGET_RANLIB=arm-elf-ranlib LEX=gflex
./configure --build=sparc64-freebsd --host=x86_64-linux-gnu \
--target=arm-linux-gnueabihf --with-platform=efi \
BUILD_CC=gcc BUILD_PKG_CONFIG=pkg-config \
HOST_CC=x86_64-linux-gnu-gcc HOST_CFLAGS='-g -O2' \
PKG_CONFIG=x86_64-linux-gnu-pkg-config TARGET_CC=arm-linux-gnueabihf-gcc \
TARGET_CFLAGS='-Os -march=armv8.3-a' TARGET_CCASFLAGS='-march=armv8.3-a' \
TARGET_OBJCOPY=arm-linux-gnueabihf-objcopy \
TARGET_STRIP=arm-linux-gnueabihf-strip TARGET_NM=arm-linux-gnueabihf-nm \
TARGET_RANLIB=arm-linux-gnueabihf-ranlib LEX=flex
Note, that the autoconf 2.65 manual states that when using the --host argument
to configure, the --build argument should be specified as well. Not sending
--build, enters a compatibility mode that will be removed in the future.
Normally, for building a VAS_EBOOT on amd64 with tools to run on amd64 to
generate images to run on ARM, using your Linux distribution's
packaged cross compiler, the following would suffice:
./configure --target=arm-linux-gnueabihf --with-platform=efi
You need to use following options to specify tools and platforms. For minimum
version look at prerequisites. All tools not mentioned in this section under
corresponding platform are not needed for the platform in question.
- For build
1. BUILD_CC= to gcc able to compile for build. This is used, for
1. --build= to autoconf name of build.
2. BUILD_CC= to gcc able to compile for build. This is used, for
example, to compile build-gentrigtables which is then run to
generate sin and cos tables.
2. BUILD_CFLAGS= for C options for build.
3. BUILD_CPPFLAGS= for C preprocessor options for build.
4. BUILD_LDFLAGS= for linker options for build.
5. BUILD_FREETYPE= for freetype-config for build (optional).
3. BUILD_CFLAGS= for C options for build.
4. BUILD_CPPFLAGS= for C preprocessor options for build.
5. BUILD_LDFLAGS= for linker options for build.
6. BUILD_PKG_CONFIG= for pkg-config for build (optional).
- For host
1. --host= to autoconf name of host.
2. CC= for gcc able to compile for host
3. HOST_CFLAGS= for C options for host.
4. HOST_CPPFLAGS= for C preprocessor options for host.
5. HOST_LDFLAGS= for linker options for host.
6. FREETYPE= for freetype-config for host (optional).
7. Libdevmapper if any must be in standard linker folders (-ldevmapper) (optional).
8. Libfuse if any must be in standard linker folders (-lfuse) (optional).
9. Libzfs if any must be in standard linker folders (-lzfs) (optional).
10. Liblzma if any must be in standard linker folders (-llzma) (optional).
2. CC= for gcc able to compile for host.
3. CFLAGS= for C options for host.
4. HOST_CC= for gcc able to compile for host.
5. HOST_CFLAGS= for C options for host.
6. HOST_CPPFLAGS= for C preprocessor options for host.
7. HOST_LDFLAGS= for linker options for host.
8. PKG_CONFIG= for pkg-config for host (optional).
9. Libdevmapper if any must be in standard linker folders (-ldevmapper) (optional).
10. Libfuse if any must be in standard linker folders (-lfuse) (optional).
11. Libzfs if any must be in standard linker folders (-lzfs) (optional).
12. Liblzma if any must be in standard linker folders (-llzma) (optional).
Note: The HOST_* variables override not prefixed variables.
- For target
1. --target= to autoconf cpu name of target.
2. --with-platform to choose firmware.
3. TARGET_CC= for gcc able to compile for target
3. TARGET_CC= for gcc able to compile for target.
4. TARGET_CFLAGS= for C options for target.
5. TARGET_CPPFLAGS= for C preprocessor options for target.
6. TARGET_CCASFLAGS= for assembler options for target.
@ -202,11 +266,14 @@ corresponding platform are not needed for the platform in question.
9. TARGET_STRIP= for strip for target.
10. TARGET_NM= for nm for target.
11. TARGET_RANLIB= for ranlib for target.
Note: If the TARGET_* variables are not specified then they will default
to be the same as the host variables. If host variables are not
specified then the TARGET_* variables will default to be the same
as not prefixed variables.
- Additionally for emu, for host and target.
1. SDL is looked for in standard linker directories (-lSDL) (optional)
2. libpciaccess is looked for in standard linker directories (-lpciaccess) (optional)
3. libusb is looked for in standard linker directories (-lusb) (optional)
- Platform-agnostic tools and data.
1. make is the tool you execute after ./configure.
@ -247,10 +314,10 @@ If the package supports it, you can cause programs to be installed
with an extra prefix or suffix on their names by giving `configure'
the option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
Please note, however, that the GRUB knows where it is located in the
Please note, however, that the VAS_EBOOT knows where it is located in the
filesystem. If you have installed it in an unusual location, the
system might not work properly, or at all. The chief utility of these
options for the GRUB is to allow you to "install" in some alternate
options for the VAS_EBOOT is to allow you to "install" in some alternate
location, and then copy these to the actual root filesystem later.

35
MAINTAINERS Normal file
View File

@ -0,0 +1,35 @@
List of current VAS_EBOOT maintainers and some basic information about the project
=============================================================================
Here is the list of current VAS_EBOOT maintainers:
- Daniel Kiper <daniel.kiper@oracle.com> and <dkiper@net-space.pl>,
- Alex Burmashev <alexander.burmashev@oracle.com>,
- Vladimir 'phcoder' Serbinenko <phcoder@gmail.com>.
The maintainers drive and overlook the VAS_EBOOT development.
If you found a security vulnerability in the VAS_EBOOT please check the SECURITY
file to get more information how to properly report this kind of bugs to
the maintainers.
The VAS_EBOOT development happens on the VasEBoot-devel mailing list [1]. The latest
VAS_EBOOT source code is available at Savannah git repository [2].
Users can ask for help on the help-VasEBoot mailing list [3].
List of past VAS_EBOOT maintainers and people who strongly contributed to the project
================================================================================
Here is the list, sorted alphabetically, of past VAS_EBOOT maintainers and people who
strongly contributed to the project:
- Andrei Borzenkov,
- Bryan Ford,
- Erich Stefan Boleyn,
- Gordon Matzigkeit,
- Yoshinori K. Okuji.
[1] https://lists.gnu.org/mailman/listinfo/VasEBoot-devel
[2] https://git.savannah.gnu.org/gitweb/?p=VasEBoot.git&view=view+git+repository
[3] https://lists.gnu.org/mailman/listinfo/help-VasEBoot

View File

@ -1,9 +1,9 @@
AUTOMAKE_OPTIONS = subdir-objects -Wno-portability
DEPDIR = .deps-util
SUBDIRS = grub-core/gnulib .
SUBDIRS = VasEBoot-core/lib/gnulib .
if COND_real_platform
SUBDIRS += grub-core
SUBDIRS += VasEBoot-core
endif
SUBDIRS += po docs util/bash-completion.d
@ -24,45 +24,54 @@ CCASFLAGS_PROGRAM += $(CCASFLAGS_GNULIB)
include $(srcdir)/Makefile.util.am
check_SCRIPTS = $(check_SCRIPTS_native) $(check_SCRIPTS_nonnative)
check_PROGRAMS = $(check_PROGRAMS_native) $(check_PROGRAMS_nonnative)
TESTS = $(check_SCRIPTS) $(check_PROGRAMS)
check-native:
$(MAKE) TESTS="$(check_PROGRAMS_native) $(check_SCRIPTS_native)" check
check-nonnative:
$(MAKE) TESTS="$(check_PROGRAMS_nonnative) $(check_SCRIPTS_nonnative)" check
# XXX Use Automake's LEX & YACC support
grub_script.tab.h: $(top_srcdir)/grub-core/script/parser.y
$(YACC) -d -p grub_script_yy -b grub_script $(top_srcdir)/grub-core/script/parser.y
grub_script.tab.c: grub_script.tab.h
CLEANFILES += grub_script.tab.c grub_script.tab.h
VasEBoot_script.tab.h: $(top_srcdir)/VasEBoot-core/script/parser.y
$(YACC) -d -p VasEBoot_script_yy -b VasEBoot_script $(top_srcdir)/VasEBoot-core/script/parser.y
VasEBoot_script.tab.c: VasEBoot_script.tab.h
CLEANFILES += VasEBoot_script.tab.c VasEBoot_script.tab.h
# For the lexer.
grub_script.yy.h: $(top_srcdir)/grub-core/script/yylex.l
$(LEX) -o grub_script.yy.c --header-file=grub_script.yy.h $(top_srcdir)/grub-core/script/yylex.l
grub_script.yy.c: grub_script.yy.h
CLEANFILES += grub_script.yy.c grub_script.yy.h
VasEBoot_script.yy.h: $(top_srcdir)/VasEBoot-core/script/yylex.l
$(LEX) -o VasEBoot_script.yy.c --header-file=VasEBoot_script.yy.h $(top_srcdir)/VasEBoot-core/script/yylex.l
VasEBoot_script.yy.c: VasEBoot_script.yy.h
CLEANFILES += VasEBoot_script.yy.c VasEBoot_script.yy.h
# For libgrub.a
libgrub.pp: grub_script.tab.h grub_script.yy.h $(libgrubmods_a_SOURCES) $(libgrubkern_a_SOURCES)
$(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgrubmods_a_CPPFLAGS) $(libgrubkern_a_CPPFLAGS) $(CPPFLAGS) \
-D'GRUB_MOD_INIT(x)=@MARKER@x@' $^ > $@ || (rm -f $@; exit 1)
CLEANFILES += libgrub.pp
# For libVasEBoot.a
libVasEBoot.pp: config-util.h VasEBoot_script.tab.h VasEBoot_script.yy.h $(libVasEBootmods_a_SOURCES) $(libVasEBootkern_a_SOURCES)
$(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libVasEBootmods_a_CPPFLAGS) $(libVasEBootkern_a_CPPFLAGS) $(CPPFLAGS) \
-D'VAS_EBOOT_MOD_INIT(x)=@MARKER@x@' $^ > $@ || (rm -f $@; exit 1)
CLEANFILES += libVasEBoot.pp
libgrub_a_init.lst: libgrub.pp
cat $< | grep '@MARKER@' | sed 's/@MARKER@\(.*\)@/\1/g' | sort -u > $@ || (rm -f $@; exit 1)
CLEANFILES += libgrub_a_init.lst
libVasEBoot_a_init.lst: libVasEBoot.pp
cat $< | grep '^@MARKER@' | sed 's/@MARKER@\(.*\)@/\1/g' | sort -u > $@ || (rm -f $@; exit 1)
CLEANFILES += libVasEBoot_a_init.lst
libgrub_a_init.c: libgrub_a_init.lst $(top_srcdir)/geninit.sh
libVasEBoot_a_init.c: libVasEBoot_a_init.lst $(top_srcdir)/geninit.sh
sh $(top_srcdir)/geninit.sh `cat $<` > $@ || (rm -f $@; exit 1)
CLEANFILES += libgrub_a_init.c
CLEANFILES += libVasEBoot_a_init.c
# For grub-fstest
grub_fstest.pp: $(grub_fstest_SOURCES)
$(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(grub_fstest_CPPFLAGS) $(CPPFLAGS) \
-D'GRUB_MOD_INIT(x)=@MARKER@x@' $^ > $@ || (rm -f $@; exit 1)
CLEANFILES += grub_fstest.pp
# For VasEBoot-fstest
VasEBoot_fstest.pp: config-util.h $(VasEBoot_fstest_SOURCES)
$(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(VasEBoot_fstest_CPPFLAGS) $(CPPFLAGS) \
-D'VAS_EBOOT_MOD_INIT(x)=@MARKER@x@' $^ > $@ || (rm -f $@; exit 1)
CLEANFILES += VasEBoot_fstest.pp
grub_fstest_init.lst: libgrub.pp grub_fstest.pp
cat $^ | grep '@MARKER@' | sed 's/@MARKER@\(.*\)@/\1/g' | sort -u > $@ || (rm -f $@; exit 1)
CLEANFILES += grub_fstest_init.lst
VasEBoot_fstest_init.lst: libVasEBoot.pp VasEBoot_fstest.pp
cat $^ | grep '^@MARKER@' | sed 's/@MARKER@\(.*\)@/\1/g' | sort -u > $@ || (rm -f $@; exit 1)
CLEANFILES += VasEBoot_fstest_init.lst
grub_fstest_init.c: grub_fstest_init.lst $(top_srcdir)/geninit.sh
VasEBoot_fstest_init.c: VasEBoot_fstest_init.lst $(top_srcdir)/geninit.sh
sh $(top_srcdir)/geninit.sh `cat $<` > $@ || (rm -f $@; exit 1)
CLEANFILES += grub_fstest_init.c
CLEANFILES += VasEBoot_fstest_init.c
if COND_HAVE_FONT_SOURCE
pkgdata_DATA += unicode.pf2 ascii.pf2 euro.pf2 ascii.h widthspec.h
@ -70,39 +79,39 @@ endif
starfield_theme_files = $(srcdir)/themes/starfield/blob_w.png $(srcdir)/themes/starfield/boot_menu_c.png $(srcdir)/themes/starfield/boot_menu_e.png $(srcdir)/themes/starfield/boot_menu_ne.png $(srcdir)/themes/starfield/boot_menu_n.png $(srcdir)/themes/starfield/boot_menu_nw.png $(srcdir)/themes/starfield/boot_menu_se.png $(srcdir)/themes/starfield/boot_menu_s.png $(srcdir)/themes/starfield/boot_menu_sw.png $(srcdir)/themes/starfield/boot_menu_w.png $(srcdir)/themes/starfield/slider_c.png $(srcdir)/themes/starfield/slider_n.png $(srcdir)/themes/starfield/slider_s.png $(srcdir)/themes/starfield/starfield.png $(srcdir)/themes/starfield/terminal_box_c.png $(srcdir)/themes/starfield/terminal_box_e.png $(srcdir)/themes/starfield/terminal_box_ne.png $(srcdir)/themes/starfield/terminal_box_n.png $(srcdir)/themes/starfield/terminal_box_nw.png $(srcdir)/themes/starfield/terminal_box_se.png $(srcdir)/themes/starfield/terminal_box_s.png $(srcdir)/themes/starfield/terminal_box_sw.png $(srcdir)/themes/starfield/terminal_box_w.png $(srcdir)/themes/starfield/theme.txt $(srcdir)/themes/starfield/README $(srcdir)/themes/starfield/COPYING.CC-BY-SA-3.0
build-grub-mkfont$(BUILD_EXEEXT): util/grub-mkfont.c grub-core/unidata.c grub-core/kern/emu/misc.c util/misc.c
$(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(BUILD_LDFLAGS) -DGRUB_MKFONT=1 -DGRUB_BUILD=1 -DGRUB_UTIL=1 -DGRUB_BUILD_PROGRAM_NAME=\"build-grub-mkfont\" $^ $(build_freetype_cflags) $(build_freetype_libs)
CLEANFILES += build-grub-mkfont$(BUILD_EXEEXT)
build-VasEBoot-mkfont$(BUILD_EXEEXT): util/VasEBoot-mkfont.c VasEBoot-core/unidata.c VasEBoot-core/kern/emu/misc.c util/misc.c
$(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(BUILD_LDFLAGS) -DVAS_EBOOT_MKFONT=1 -DVAS_EBOOT_BUILD=1 -DVAS_EBOOT_UTIL=1 -DVAS_EBOOT_BUILD_PROGRAM_NAME=\"build-VasEBoot-mkfont\" $^ $(BUILD_FREETYPE_CFLAGS) $(BUILD_FREETYPE_LIBS)
CLEANFILES += build-VasEBoot-mkfont$(BUILD_EXEEXT)
garbage-gen$(BUILD_EXEEXT): util/garbage-gen.c
$(BUILD_CC) -o $@ $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(BUILD_LDFLAGS) $^
CLEANFILES += garbage-gen$(BUILD_EXEEXT)
EXTRA_DIST += util/garbage-gen.c
build-grub-gen-asciih$(BUILD_EXEEXT): util/grub-gen-asciih.c
$(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(BUILD_LDFLAGS) -DGRUB_MKFONT=1 -DGRUB_BUILD=1 -DGRUB_UTIL=1 $^ $(build_freetype_cflags) $(build_freetype_libs) -Wall -Werror
CLEANFILES += build-grub-gen-asciih$(BUILD_EXEEXT)
build-VasEBoot-gen-asciih$(BUILD_EXEEXT): util/VasEBoot-gen-asciih.c
$(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(BUILD_LDFLAGS) -DVAS_EBOOT_MKFONT=1 -DVAS_EBOOT_BUILD=1 -DVAS_EBOOT_UTIL=1 $^ $(BUILD_FREETYPE_CFLAGS) $(BUILD_FREETYPE_LIBS) -Wall -Werror
CLEANFILES += build-VasEBoot-gen-asciih$(BUILD_EXEEXT)
build-grub-gen-widthspec$(BUILD_EXEEXT): util/grub-gen-widthspec.c
$(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(BUILD_LDFLAGS) -DGRUB_MKFONT=1 -DGRUB_BUILD=1 -DGRUB_UTIL=1 $^ $(build_freetype_cflags) $(build_freetype_libs) -Wall -Werror
CLEANFILES += build-grub-gen-widthspec$(BUILD_EXEEXT)
build-VasEBoot-gen-widthspec$(BUILD_EXEEXT): util/VasEBoot-gen-widthspec.c
$(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(BUILD_LDFLAGS) -DVAS_EBOOT_MKFONT=1 -DVAS_EBOOT_BUILD=1 -DVAS_EBOOT_UTIL=1 $^ $(BUILD_FREETYPE_CFLAGS) $(BUILD_FREETYPE_LIBS) -Wall -Werror
CLEANFILES += build-VasEBoot-gen-widthspec$(BUILD_EXEEXT)
if COND_STARFIELD
starfield_DATA = dejavu_10.pf2 dejavu_12.pf2 dejavu_bold_14.pf2 dejavu_14.pf2 dejavu_16.pf2 $(starfield_theme_files)
dejavu_10.pf2: $(DJVU_FONT_SOURCE) build-grub-mkfont$(BUILD_EXEEXT)
./build-grub-mkfont$(BUILD_EXEEXT) -s 10 -o $@ $(DJVU_FONT_SOURCE)
dejavu_10.pf2: $(DJVU_FONT_SOURCE) build-VasEBoot-mkfont$(BUILD_EXEEXT)
./build-VasEBoot-mkfont$(BUILD_EXEEXT) -s 10 -o $@ $(DJVU_FONT_SOURCE)
CLEANFILES += dejavu_10.pf2
dejavu_12.pf2: $(DJVU_FONT_SOURCE) build-grub-mkfont$(BUILD_EXEEXT)
./build-grub-mkfont$(BUILD_EXEEXT) -s 12 -o $@ $(DJVU_FONT_SOURCE)
dejavu_12.pf2: $(DJVU_FONT_SOURCE) build-VasEBoot-mkfont$(BUILD_EXEEXT)
./build-VasEBoot-mkfont$(BUILD_EXEEXT) -s 12 -o $@ $(DJVU_FONT_SOURCE)
CLEANFILES += dejavu_12.pf2
dejavu_14.pf2: $(DJVU_FONT_SOURCE) build-grub-mkfont$(BUILD_EXEEXT)
./build-grub-mkfont$(BUILD_EXEEXT) -s 14 -o $@ $(DJVU_FONT_SOURCE)
dejavu_14.pf2: $(DJVU_FONT_SOURCE) build-VasEBoot-mkfont$(BUILD_EXEEXT)
./build-VasEBoot-mkfont$(BUILD_EXEEXT) -s 14 -o $@ $(DJVU_FONT_SOURCE)
CLEANFILES += dejavu_14.pf2
dejavu_bold_14.pf2: $(DJVU_FONT_SOURCE) build-grub-mkfont$(BUILD_EXEEXT)
./build-grub-mkfont$(BUILD_EXEEXT) -b -s 14 -o $@ $(DJVU_FONT_SOURCE)
dejavu_bold_14.pf2: $(DJVU_FONT_SOURCE) build-VasEBoot-mkfont$(BUILD_EXEEXT)
./build-VasEBoot-mkfont$(BUILD_EXEEXT) -b -s 14 -o $@ $(DJVU_FONT_SOURCE)
CLEANFILES += dejavu_bold_14.pf2
dejavu_16.pf2: $(DJVU_FONT_SOURCE) build-grub-mkfont$(BUILD_EXEEXT)
./build-grub-mkfont$(BUILD_EXEEXT) -s 16 -o $@ $(DJVU_FONT_SOURCE)
dejavu_16.pf2: $(DJVU_FONT_SOURCE) build-VasEBoot-mkfont$(BUILD_EXEEXT)
./build-VasEBoot-mkfont$(BUILD_EXEEXT) -s 16 -o $@ $(DJVU_FONT_SOURCE)
CLEANFILES += dejavu_16.pf2
else
starfield_DATA =
@ -111,34 +120,34 @@ endif
EXTRA_DIST += $(starfield_theme_files)
EXTRA_DIST += $(srcdir)/themes/starfield/src/slider_s.xcf $(srcdir)/themes/starfield/src/slider_n.xcf $(srcdir)/themes/starfield/src/slider_c.xcf $(srcdir)/themes/starfield/src/blob_nw.xcf $(srcdir)/themes/starfield/src/bootmenu/center.xcf $(srcdir)/themes/starfield/src/bootmenu/corner.xcf $(srcdir)/themes/starfield/src/bootmenu/side.xcf $(srcdir)/themes/starfield/src/terminalbox/side.xcf $(srcdir)/themes/starfield/src/terminalbox/corner.xcf $(srcdir)/themes/starfield/src/terminalbox/center.xcf
unicode.pf2: $(FONT_SOURCE) build-grub-mkfont$(BUILD_EXEEXT)
./build-grub-mkfont$(BUILD_EXEEXT) -o $@ $(FONT_SOURCE) || (rm -f $@; exit 1)
unicode.pf2: $(FONT_SOURCE) build-VasEBoot-mkfont$(BUILD_EXEEXT)
./build-VasEBoot-mkfont$(BUILD_EXEEXT) -o $@ $(FONT_SOURCE) || (rm -f $@; exit 1)
CLEANFILES += unicode.pf2
# Arrows and lines are needed to draw the menu, so always include them
UNICODE_ARROWS=0x2190-0x2193
UNICODE_LINES=0x2501-0x251B
ascii.pf2: $(FONT_SOURCE) build-grub-mkfont$(BUILD_EXEEXT)
./build-grub-mkfont$(BUILD_EXEEXT) -o $@ $(FONT_SOURCE) -r 0x0-0x7f,$(UNICODE_ARROWS),$(UNICODE_LINES) || (rm -f $@; exit 1)
ascii.pf2: $(FONT_SOURCE) build-VasEBoot-mkfont$(BUILD_EXEEXT)
./build-VasEBoot-mkfont$(BUILD_EXEEXT) -o $@ $(FONT_SOURCE) -r 0x0-0x7f,$(UNICODE_ARROWS),$(UNICODE_LINES) || (rm -f $@; exit 1)
CLEANFILES += ascii.pf2
euro.pf2: $(FONT_SOURCE) build-grub-mkfont$(BUILD_EXEEXT)
./build-grub-mkfont$(BUILD_EXEEXT) -o $@ $(FONT_SOURCE) -r 0x0-0x4ff,0x1e00-0x1fff,$(UNICODE_ARROWS),$(UNICODE_LINES) || (rm -f $@; exit 1)
euro.pf2: $(FONT_SOURCE) build-VasEBoot-mkfont$(BUILD_EXEEXT)
./build-VasEBoot-mkfont$(BUILD_EXEEXT) -o $@ $(FONT_SOURCE) -r 0x0-0x4ff,0x1e00-0x1fff,$(UNICODE_ARROWS),$(UNICODE_LINES) || (rm -f $@; exit 1)
CLEANFILES += euro.pf2
ascii.h: $(FONT_SOURCE) build-grub-gen-asciih$(BUILD_EXEEXT)
./build-grub-gen-asciih$(BUILD_EXEEXT) $(FONT_SOURCE) $@ || (rm -f $@; exit 1)
ascii.h: $(FONT_SOURCE) build-VasEBoot-gen-asciih$(BUILD_EXEEXT)
./build-VasEBoot-gen-asciih$(BUILD_EXEEXT) $(FONT_SOURCE) $@ || (rm -f $@; exit 1)
CLEANFILES += ascii.h
widthspec.h: $(FONT_SOURCE) build-grub-gen-widthspec$(BUILD_EXEEXT)
./build-grub-gen-widthspec$(BUILD_EXEEXT) $(FONT_SOURCE) $@ || (rm -f $@; exit 1)
widthspec.h: $(FONT_SOURCE) build-VasEBoot-gen-widthspec$(BUILD_EXEEXT)
./build-VasEBoot-gen-widthspec$(BUILD_EXEEXT) $(FONT_SOURCE) $@ || (rm -f $@; exit 1)
CLEANFILES += widthspec.h
# Install config.h into platformdir
nodist_platform_HEADERS = config.h
pkgdata_DATA += grub-mkconfig_lib
pkgdata_DATA += VasEBoot-mkconfig_lib
if COND_real_platform
@ -178,64 +187,64 @@ 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
linux.init.x86_64: $(srcdir)/VasEBoot-core/tests/boot/linux.init-x86_64.S $(srcdir)/VasEBoot-core/tests/boot/qemu-shutdown-x86.S
$(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
linux.init.i386: $(srcdir)/VasEBoot-core/tests/boot/linux.init-i386.S $(srcdir)/VasEBoot-core/tests/boot/qemu-shutdown-x86.S
$(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
linux.init.mips: $(srcdir)/VasEBoot-core/tests/boot/linux.init-mips.S
$(TARGET_CC) -o $@ $< -static -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\"
linux.init.ppc: $(srcdir)/grub-core/tests/boot/linux.init-ppc.S
linux.init.ppc: $(srcdir)/VasEBoot-core/tests/boot/linux.init-ppc.S
$(TARGET_CC) -o $@ $< -static -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\"
linux.init.mipsel: $(srcdir)/grub-core/tests/boot/linux.init-mips.S
linux.init.mipsel: $(srcdir)/VasEBoot-core/tests/boot/linux.init-mips.S
$(TARGET_CC) -o $@ $< -static -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\"
linux.init.loongson: $(srcdir)/grub-core/tests/boot/linux.init-mips.S
linux.init.loongson: $(srcdir)/VasEBoot-core/tests/boot/linux.init-mips.S
$(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
multiboot.elf: $(srcdir)/VasEBoot-core/tests/boot/kernel-i386.S $(srcdir)/VasEBoot-core/tests/boot/qemu-shutdown-x86.S
$(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
kfreebsd.elf: $(srcdir)/VasEBoot-core/tests/boot/kernel-i386.S $(srcdir)/VasEBoot-core/tests/boot/qemu-shutdown-x86.S
$(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 $< $@ -j .text
pc-chainloader.elf: $(srcdir)/grub-core/tests/boot/kernel-8086.S $(srcdir)/grub-core/tests/boot/qemu-shutdown-x86.S
pc-chainloader.elf: $(srcdir)/VasEBoot-core/tests/boot/kernel-8086.S $(srcdir)/VasEBoot-core/tests/boot/qemu-shutdown-x86.S
$(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
ntldr.elf: $(srcdir)/VasEBoot-core/tests/boot/kernel-8086.S $(srcdir)/VasEBoot-core/tests/boot/qemu-shutdown-x86.S
$(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 -j .text $< $@;
multiboot2.elf: $(srcdir)/grub-core/tests/boot/kernel-i386.S $(srcdir)/grub-core/tests/boot/qemu-shutdown-x86.S
multiboot2.elf: $(srcdir)/VasEBoot-core/tests/boot/kernel-i386.S $(srcdir)/VasEBoot-core/tests/boot/qemu-shutdown-x86.S
$(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
kfreebsd.init.x86_64: $(srcdir)/VasEBoot-core/tests/boot/kfreebsd.init-x86_64.S $(srcdir)/VasEBoot-core/tests/boot/qemu-shutdown-x86.S
$(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
kfreebsd.init.i386: $(srcdir)/VasEBoot-core/tests/boot/kfreebsd.init-i386.S $(srcdir)/VasEBoot-core/tests/boot/qemu-shutdown-x86.S
$(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
knetbsd.init.i386: $(srcdir)/VasEBoot-core/tests/boot/kbsd.init-i386.S $(srcdir)/VasEBoot-core/tests/boot/qemu-shutdown-x86.S
$(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
kopenbsd.init.i386: $(srcdir)/VasEBoot-core/tests/boot/kbsd.init-i386.S $(srcdir)/VasEBoot-core/tests/boot/qemu-shutdown-x86.S
$(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
knetbsd.init.x86_64: $(srcdir)/VasEBoot-core/tests/boot/kbsd.init-x86_64.S $(srcdir)/VasEBoot-core/tests/boot/qemu-shutdown-x86.S
$(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
kopenbsd.init.x86_64: $(srcdir)/VasEBoot-core/tests/boot/kbsd.init-x86_64.S $(srcdir)/VasEBoot-core/tests/boot/qemu-shutdown-x86.S
$(TARGET_CC) -o $@ $< -m64 -DTARGET_OPENBSD=1 -static -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\"
linux-initramfs.mips: linux.init.mips Makefile
@ -259,97 +268,97 @@ linux-initramfs.x86_64: linux.init.x86_64 Makefile
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
knetbsd.image.i386: knetbsd.init.i386 $(srcdir)/grub-core/tests/boot/kbsd.spec.txt
TDIR=`mktemp -d "$${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` && mkdir $$TDIR/dev && mkdir $$TDIR/sbin && cp $< $$TDIR/sbin/init && makefs -F $(srcdir)/grub-core/tests/boot/kbsd.spec.txt -t ffs -s 64k -f 10 -o minfree=0,version=1 $@ $$TDIR && rm -rf $$TDIR
knetbsd.image.i386: knetbsd.init.i386 $(srcdir)/VasEBoot-core/tests/boot/kbsd.spec.txt
TDIR=`mktemp -d "$${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` && mkdir $$TDIR/dev && mkdir $$TDIR/sbin && cp $< $$TDIR/sbin/init && makefs -F $(srcdir)/VasEBoot-core/tests/boot/kbsd.spec.txt -t ffs -s 64k -f 10 -o minfree=0,version=1 $@ $$TDIR && rm -rf $$TDIR
kopenbsd.image.i386: kopenbsd.init.i386 $(srcdir)/grub-core/tests/boot/kopenbsdlabel.txt
TDIR=`mktemp -d "$${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` && mkdir $$TDIR/dev && mkdir $$TDIR/sbin && cp $< $$TDIR/sbin/init && makefs -F $(srcdir)/grub-core/tests/boot/kbsd.spec.txt -t ffs -s 128k -f 10 -o minfree=0,version=1 $@ $$TDIR && bsdlabel -f -R $@ $(srcdir)/grub-core/tests/boot/kopenbsdlabel.txt && rm -rf $$TDIR || rm -f $@
kopenbsd.image.i386: kopenbsd.init.i386 $(srcdir)/VasEBoot-core/tests/boot/kopenbsdlabel.txt
TDIR=`mktemp -d "$${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` && mkdir $$TDIR/dev && mkdir $$TDIR/sbin && cp $< $$TDIR/sbin/init && makefs -F $(srcdir)/VasEBoot-core/tests/boot/kbsd.spec.txt -t ffs -s 128k -f 10 -o minfree=0,version=1 $@ $$TDIR && bsdlabel -f -R $@ $(srcdir)/VasEBoot-core/tests/boot/kopenbsdlabel.txt && rm -rf $$TDIR || rm -f $@
kopenbsd.image.x86_64: kopenbsd.init.x86_64 $(srcdir)/grub-core/tests/boot/kopenbsdlabel.txt
TDIR=`mktemp -d "$${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` && mkdir $$TDIR/dev && mkdir $$TDIR/sbin && cp $< $$TDIR/sbin/init && makefs -F $(srcdir)/grub-core/tests/boot/kbsd.spec.txt -t ffs -s 128k -f 10 -o minfree=0,version=1 $@ $$TDIR && bsdlabel -f -R $@ $(srcdir)/grub-core/tests/boot/kopenbsdlabel.txt && rm -rf $$TDIR || rm -f $@
kopenbsd.image.x86_64: kopenbsd.init.x86_64 $(srcdir)/VasEBoot-core/tests/boot/kopenbsdlabel.txt
TDIR=`mktemp -d "$${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` && mkdir $$TDIR/dev && mkdir $$TDIR/sbin && cp $< $$TDIR/sbin/init && makefs -F $(srcdir)/VasEBoot-core/tests/boot/kbsd.spec.txt -t ffs -s 128k -f 10 -o minfree=0,version=1 $@ $$TDIR && bsdlabel -f -R $@ $(srcdir)/VasEBoot-core/tests/boot/kopenbsdlabel.txt && rm -rf $$TDIR || rm -f $@
knetbsd.miniroot-image.i386.img: knetbsd.image.i386 $(GRUB_PAYLOADS_DIR)/knetbsd.miniroot.i386
$(TARGET_OBJCOPY) --add-section=miniroot=$< $(GRUB_PAYLOADS_DIR)/knetbsd.miniroot.i386 $@
knetbsd.miniroot-image.i386.img: knetbsd.image.i386 $(VAS_EBOOT_PAYLOADS_DIR)/knetbsd.miniroot.i386
$(TARGET_OBJCOPY) --add-section=miniroot=$< $(VAS_EBOOT_PAYLOADS_DIR)/knetbsd.miniroot.i386 $@
kfreebsd-mfsroot.x86_64.img: kfreebsd.init.x86_64 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
knetbsd.image.x86_64: knetbsd.init.x86_64 $(srcdir)/grub-core/tests/boot/kbsd.spec.txt
TDIR=`mktemp -d "$${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` && mkdir $$TDIR/dev && mkdir $$TDIR/sbin && cp $< $$TDIR/sbin/init && makefs -F $(srcdir)/grub-core/tests/boot/kbsd.spec.txt -t ffs -s 64k -f 10 -o minfree=0,version=1 $@ $$TDIR && rm -rf $$TDIR
knetbsd.image.x86_64: knetbsd.init.x86_64 $(srcdir)/VasEBoot-core/tests/boot/kbsd.spec.txt
TDIR=`mktemp -d "$${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` && mkdir $$TDIR/dev && mkdir $$TDIR/sbin && cp $< $$TDIR/sbin/init && makefs -F $(srcdir)/VasEBoot-core/tests/boot/kbsd.spec.txt -t ffs -s 64k -f 10 -o minfree=0,version=1 $@ $$TDIR && rm -rf $$TDIR
knetbsd.miniroot-image.x86_64.img: knetbsd.image.x86_64 $(GRUB_PAYLOADS_DIR)/knetbsd.miniroot.x86_64
$(TARGET_OBJCOPY) --add-section=miniroot=$< $(GRUB_PAYLOADS_DIR)/knetbsd.miniroot.x86_64 $@
knetbsd.miniroot-image.x86_64.img: knetbsd.image.x86_64 $(VAS_EBOOT_PAYLOADS_DIR)/knetbsd.miniroot.x86_64
$(TARGET_OBJCOPY) --add-section=miniroot=$< $(VAS_EBOOT_PAYLOADS_DIR)/knetbsd.miniroot.x86_64 $@
CLEANFILES += linux.init.i386 kfreebsd.init.i386 linux.init.x86_64 linux-initramfs.i386 linux-initramfs.x86_64
kfreebsd-mfsroot.i386.gz: kfreebsd-mfsroot.i386.img
gzip < $< > $@
bootcheck-kfreebsd-i386: kfreebsd-mfsroot.i386.gz $(GRUB_PAYLOADS_DIR)/kfreebsd.i386 $(GRUB_PAYLOADS_DIR)/kfreebsd_env.i386 $(srcdir)/grub-core/tests/boot/kfreebsd.cfg grub-shell
./grub-shell --timeout=$(BOOTCHECK_TIMEOUT) --qemu=$(QEMU32) --files=/mfsroot.gz=kfreebsd-mfsroot.i386.gz --files=/kfreebsd=$(GRUB_PAYLOADS_DIR)/kfreebsd.i386 --files=/kfreebsd_env=$(GRUB_PAYLOADS_DIR)/kfreebsd_env.i386 $(srcdir)/grub-core/tests/boot/kfreebsd.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null
bootcheck-kfreebsd-i386: kfreebsd-mfsroot.i386.gz $(VAS_EBOOT_PAYLOADS_DIR)/kfreebsd.i386 $(VAS_EBOOT_PAYLOADS_DIR)/kfreebsd_env.i386 $(srcdir)/VasEBoot-core/tests/boot/kfreebsd.cfg VasEBoot-shell
./VasEBoot-shell --timeout=$(BOOTCHECK_TIMEOUT) --qemu=$(QEMU32) --files=/mfsroot.gz=kfreebsd-mfsroot.i386.gz --files=/kfreebsd=$(VAS_EBOOT_PAYLOADS_DIR)/kfreebsd.i386 --files=/kfreebsd_env=$(VAS_EBOOT_PAYLOADS_DIR)/kfreebsd_env.i386 $(srcdir)/VasEBoot-core/tests/boot/kfreebsd.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null
kfreebsd-mfsroot.x86_64.gz: kfreebsd-mfsroot.x86_64.img
gzip < $< > $@
bootcheck-kfreebsd-x86_64: kfreebsd-mfsroot.x86_64.gz $(GRUB_PAYLOADS_DIR)/kfreebsd.x86_64 $(GRUB_PAYLOADS_DIR)/kfreebsd_env.x86_64 $(srcdir)/grub-core/tests/boot/kfreebsd.cfg grub-shell
./grub-shell --timeout=$(BOOTCHECK_TIMEOUT) --qemu=qemu-system-x86_64 --files=/mfsroot.gz=kfreebsd-mfsroot.x86_64.gz --files=/kfreebsd=$(GRUB_PAYLOADS_DIR)/kfreebsd.x86_64 --files=/kfreebsd_env=$(GRUB_PAYLOADS_DIR)/kfreebsd_env.x86_64 $(srcdir)/grub-core/tests/boot/kfreebsd.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null
bootcheck-kfreebsd-x86_64: kfreebsd-mfsroot.x86_64.gz $(VAS_EBOOT_PAYLOADS_DIR)/kfreebsd.x86_64 $(VAS_EBOOT_PAYLOADS_DIR)/kfreebsd_env.x86_64 $(srcdir)/VasEBoot-core/tests/boot/kfreebsd.cfg VasEBoot-shell
./VasEBoot-shell --timeout=$(BOOTCHECK_TIMEOUT) --qemu=qemu-system-x86_64 --files=/mfsroot.gz=kfreebsd-mfsroot.x86_64.gz --files=/kfreebsd=$(VAS_EBOOT_PAYLOADS_DIR)/kfreebsd.x86_64 --files=/kfreebsd_env=$(VAS_EBOOT_PAYLOADS_DIR)/kfreebsd_env.x86_64 $(srcdir)/VasEBoot-core/tests/boot/kfreebsd.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null
knetbsd.miniroot-image.i386.gz: knetbsd.miniroot-image.i386.img
gzip < $< > $@
bootcheck-knetbsd-i386: knetbsd.miniroot-image.i386.gz $(GRUB_PAYLOADS_DIR)/knetbsd.i386 $(srcdir)/grub-core/tests/boot/knetbsd.cfg grub-shell
./grub-shell --timeout=$(BOOTCHECK_TIMEOUT) --qemu=$(QEMU32) --files=/miniroot.gz=knetbsd.miniroot-image.i386.gz --files=/knetbsd=$(GRUB_PAYLOADS_DIR)/knetbsd.i386 $(srcdir)/grub-core/tests/boot/knetbsd.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null
bootcheck-knetbsd-i386: knetbsd.miniroot-image.i386.gz $(VAS_EBOOT_PAYLOADS_DIR)/knetbsd.i386 $(srcdir)/VasEBoot-core/tests/boot/knetbsd.cfg VasEBoot-shell
./VasEBoot-shell --timeout=$(BOOTCHECK_TIMEOUT) --qemu=$(QEMU32) --files=/miniroot.gz=knetbsd.miniroot-image.i386.gz --files=/knetbsd=$(VAS_EBOOT_PAYLOADS_DIR)/knetbsd.i386 $(srcdir)/VasEBoot-core/tests/boot/knetbsd.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null
bootcheck-kopenbsd-i386: kopenbsd.image.i386 $(GRUB_PAYLOADS_DIR)/kopenbsd.i386 $(srcdir)/grub-core/tests/boot/kopenbsd.cfg grub-shell
./grub-shell --timeout=$(BOOTCHECK_TIMEOUT) --qemu=$(QEMU32) --files=/ramdisk=kopenbsd.image.i386 --files=/kopenbsd=$(GRUB_PAYLOADS_DIR)/kopenbsd.i386 $(srcdir)/grub-core/tests/boot/kopenbsd.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null
bootcheck-kopenbsd-i386: kopenbsd.image.i386 $(VAS_EBOOT_PAYLOADS_DIR)/kopenbsd.i386 $(srcdir)/VasEBoot-core/tests/boot/kopenbsd.cfg VasEBoot-shell
./VasEBoot-shell --timeout=$(BOOTCHECK_TIMEOUT) --qemu=$(QEMU32) --files=/ramdisk=kopenbsd.image.i386 --files=/kopenbsd=$(VAS_EBOOT_PAYLOADS_DIR)/kopenbsd.i386 $(srcdir)/VasEBoot-core/tests/boot/kopenbsd.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null
bootcheck-kopenbsd-x86_64: kopenbsd.image.x86_64 $(GRUB_PAYLOADS_DIR)/kopenbsd.x86_64 $(srcdir)/grub-core/tests/boot/kopenbsd.cfg grub-shell
./grub-shell --timeout=$(BOOTCHECK_TIMEOUT) --qemu=qemu-system-x86_64 --files=/ramdisk=kopenbsd.image.x86_64 --files=/kopenbsd=$(GRUB_PAYLOADS_DIR)/kopenbsd.x86_64 $(srcdir)/grub-core/tests/boot/kopenbsd.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null
bootcheck-kopenbsd-x86_64: kopenbsd.image.x86_64 $(VAS_EBOOT_PAYLOADS_DIR)/kopenbsd.x86_64 $(srcdir)/VasEBoot-core/tests/boot/kopenbsd.cfg VasEBoot-shell
./VasEBoot-shell --timeout=$(BOOTCHECK_TIMEOUT) --qemu=qemu-system-x86_64 --files=/ramdisk=kopenbsd.image.x86_64 --files=/kopenbsd=$(VAS_EBOOT_PAYLOADS_DIR)/kopenbsd.x86_64 $(srcdir)/VasEBoot-core/tests/boot/kopenbsd.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null
knetbsd.miniroot-image.x86_64.gz: knetbsd.miniroot-image.x86_64.img
gzip < $< > $@
bootcheck-knetbsd-x86_64: knetbsd.miniroot-image.x86_64.gz $(GRUB_PAYLOADS_DIR)/knetbsd.x86_64 $(srcdir)/grub-core/tests/boot/knetbsd.cfg grub-shell
./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-knetbsd-x86_64: knetbsd.miniroot-image.x86_64.gz $(VAS_EBOOT_PAYLOADS_DIR)/knetbsd.x86_64 $(srcdir)/VasEBoot-core/tests/boot/knetbsd.cfg VasEBoot-shell
./VasEBoot-shell --timeout=$(BOOTCHECK_TIMEOUT) --qemu=qemu-system-x86_64 --files=/miniroot.gz=knetbsd.miniroot-image.x86_64.gz --files=/knetbsd=$(VAS_EBOOT_PAYLOADS_DIR)/knetbsd.x86_64 $(srcdir)/VasEBoot-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 --qemu-opts="-cpu $(MINIMUM_CPU_LINUX)" | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null
bootcheck-linux-i386: linux-initramfs.i386 $(VAS_EBOOT_PAYLOADS_DIR)/linux.i386 $(srcdir)/VasEBoot-core/tests/boot/linux.cfg VasEBoot-shell
./VasEBoot-shell --timeout=$(BOOTCHECK_TIMEOUT) --qemu=$(QEMU32) --files=/initrd=linux-initramfs.i386 --files=/linux=$(VAS_EBOOT_PAYLOADS_DIR)/linux.i386 $(srcdir)/VasEBoot-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
bootcheck-linux-x86_64: linux-initramfs.x86_64 $(VAS_EBOOT_PAYLOADS_DIR)/linux.x86_64 $(srcdir)/VasEBoot-core/tests/boot/linux.cfg VasEBoot-shell
./VasEBoot-shell --timeout=$(BOOTCHECK_TIMEOUT) --qemu=qemu-system-x86_64 --files=/initrd=linux-initramfs.x86_64 --files=/linux=$(VAS_EBOOT_PAYLOADS_DIR)/linux.x86_64 $(srcdir)/VasEBoot-core/tests/boot/linux.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null
bootcheck-linux-mips: linux-initramfs.mips $(GRUB_PAYLOADS_DIR)/linux.mips $(srcdir)/grub-core/tests/boot/linux.cfg grub-shell
./grub-shell --timeout=$(BOOTCHECK_TIMEOUT) --files=/initrd=linux-initramfs.mips --files=/linux=$(GRUB_PAYLOADS_DIR)/linux.mips $(srcdir)/grub-core/tests/boot/linux.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null
bootcheck-linux-mips: linux-initramfs.mips $(VAS_EBOOT_PAYLOADS_DIR)/linux.mips $(srcdir)/VasEBoot-core/tests/boot/linux.cfg VasEBoot-shell
./VasEBoot-shell --timeout=$(BOOTCHECK_TIMEOUT) --files=/initrd=linux-initramfs.mips --files=/linux=$(VAS_EBOOT_PAYLOADS_DIR)/linux.mips $(srcdir)/VasEBoot-core/tests/boot/linux.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null
bootcheck-linux-ppc: linux-initramfs.ppc $(GRUB_PAYLOADS_DIR)/linux.ppc $(srcdir)/grub-core/tests/boot/linux.cfg grub-shell
./grub-shell --timeout=$(BOOTCHECK_TIMEOUT) --files=/initrd=linux-initramfs.ppc --files=/linux=$(GRUB_PAYLOADS_DIR)/linux.ppc $(srcdir)/grub-core/tests/boot/linux-ppc.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null
bootcheck-linux-ppc: linux-initramfs.ppc $(VAS_EBOOT_PAYLOADS_DIR)/linux.ppc $(srcdir)/VasEBoot-core/tests/boot/linux.cfg VasEBoot-shell
./VasEBoot-shell --timeout=$(BOOTCHECK_TIMEOUT) --files=/initrd=linux-initramfs.ppc --files=/linux=$(VAS_EBOOT_PAYLOADS_DIR)/linux.ppc $(srcdir)/VasEBoot-core/tests/boot/linux-ppc.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null
bootcheck-linux-mipsel: linux-initramfs.mipsel $(GRUB_PAYLOADS_DIR)/linux.mipsel $(srcdir)/grub-core/tests/boot/linux.cfg grub-shell
./grub-shell --timeout=$(BOOTCHECK_TIMEOUT) --files=/initrd=linux-initramfs.mipsel --files=/linux=$(GRUB_PAYLOADS_DIR)/linux.mipsel $(srcdir)/grub-core/tests/boot/linux.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null
bootcheck-linux-mipsel: linux-initramfs.mipsel $(VAS_EBOOT_PAYLOADS_DIR)/linux.mipsel $(srcdir)/VasEBoot-core/tests/boot/linux.cfg VasEBoot-shell
./VasEBoot-shell --timeout=$(BOOTCHECK_TIMEOUT) --files=/initrd=linux-initramfs.mipsel --files=/linux=$(VAS_EBOOT_PAYLOADS_DIR)/linux.mipsel $(srcdir)/VasEBoot-core/tests/boot/linux.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null
bootcheck-linux-loongson: linux-initramfs.loongson $(GRUB_PAYLOADS_DIR)/linux.loongson $(srcdir)/grub-core/tests/boot/linux.cfg grub-shell
./grub-shell --timeout=$(BOOTCHECK_TIMEOUT) --files=/initrd=linux-initramfs.loongson --files=/linux=$(GRUB_PAYLOADS_DIR)/linux.loongson $(srcdir)/grub-core/tests/boot/linux.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null
bootcheck-linux-loongson: linux-initramfs.loongson $(VAS_EBOOT_PAYLOADS_DIR)/linux.loongson $(srcdir)/VasEBoot-core/tests/boot/linux.cfg VasEBoot-shell
./VasEBoot-shell --timeout=$(BOOTCHECK_TIMEOUT) --files=/initrd=linux-initramfs.loongson --files=/linux=$(VAS_EBOOT_PAYLOADS_DIR)/linux.loongson $(srcdir)/VasEBoot-core/tests/boot/linux.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null
bootcheck-linux16-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/linux16.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null
bootcheck-linux16-i386: linux-initramfs.i386 $(VAS_EBOOT_PAYLOADS_DIR)/linux.i386 $(srcdir)/VasEBoot-core/tests/boot/linux.cfg VasEBoot-shell
./VasEBoot-shell --timeout=$(BOOTCHECK_TIMEOUT) --qemu=$(QEMU32) --files=/initrd=linux-initramfs.i386 --files=/linux=$(VAS_EBOOT_PAYLOADS_DIR)/linux.i386 $(srcdir)/VasEBoot-core/tests/boot/linux16.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null
bootcheck-linux16-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/linux16.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null
bootcheck-linux16-x86_64: linux-initramfs.x86_64 $(VAS_EBOOT_PAYLOADS_DIR)/linux.x86_64 $(srcdir)/VasEBoot-core/tests/boot/linux.cfg VasEBoot-shell
./VasEBoot-shell --timeout=$(BOOTCHECK_TIMEOUT) --qemu=qemu-system-x86_64 --files=/initrd=linux-initramfs.x86_64 --files=/linux=$(VAS_EBOOT_PAYLOADS_DIR)/linux.x86_64 $(srcdir)/VasEBoot-core/tests/boot/linux16.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null
bootcheck-multiboot: multiboot.elf $(srcdir)/grub-core/tests/boot/multiboot.cfg grub-shell
./grub-shell --timeout=$(BOOTCHECK_TIMEOUT) --qemu=$(QEMU32) --files=/multiboot.elf=multiboot.elf $(srcdir)/grub-core/tests/boot/multiboot.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null
bootcheck-multiboot: multiboot.elf $(srcdir)/VasEBoot-core/tests/boot/multiboot.cfg VasEBoot-shell
./VasEBoot-shell --timeout=$(BOOTCHECK_TIMEOUT) --qemu=$(QEMU32) --files=/multiboot.elf=multiboot.elf $(srcdir)/VasEBoot-core/tests/boot/multiboot.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null
bootcheck-multiboot2: multiboot2.elf $(srcdir)/grub-core/tests/boot/multiboot2.cfg grub-shell
./grub-shell --timeout=$(BOOTCHECK_TIMEOUT) --qemu=$(QEMU32) --files=/multiboot2.elf=multiboot2.elf $(srcdir)/grub-core/tests/boot/multiboot2.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null
bootcheck-multiboot2: multiboot2.elf $(srcdir)/VasEBoot-core/tests/boot/multiboot2.cfg VasEBoot-shell
./VasEBoot-shell --timeout=$(BOOTCHECK_TIMEOUT) --qemu=$(QEMU32) --files=/multiboot2.elf=multiboot2.elf $(srcdir)/VasEBoot-core/tests/boot/multiboot2.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null
bootcheck-kfreebsd-aout: kfreebsd.aout $(srcdir)/grub-core/tests/boot/kfreebsd-aout.cfg grub-shell
./grub-shell --timeout=$(BOOTCHECK_TIMEOUT) --qemu=$(QEMU32) --files=/kfreebsd.aout=kfreebsd.aout $(srcdir)/grub-core/tests/boot/kfreebsd-aout.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null
bootcheck-kfreebsd-aout: kfreebsd.aout $(srcdir)/VasEBoot-core/tests/boot/kfreebsd-aout.cfg VasEBoot-shell
./VasEBoot-shell --timeout=$(BOOTCHECK_TIMEOUT) --qemu=$(QEMU32) --files=/kfreebsd.aout=kfreebsd.aout $(srcdir)/VasEBoot-core/tests/boot/kfreebsd-aout.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null
bootcheck-pc-chainloader: pc-chainloader.bin $(srcdir)/grub-core/tests/boot/pc-chainloader.cfg grub-shell
./grub-shell --timeout=$(BOOTCHECK_TIMEOUT) --qemu=$(QEMU32) --files=/pc-chainloader.bin=pc-chainloader.bin $(srcdir)/grub-core/tests/boot/pc-chainloader.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null
bootcheck-pc-chainloader: pc-chainloader.bin $(srcdir)/VasEBoot-core/tests/boot/pc-chainloader.cfg VasEBoot-shell
./VasEBoot-shell --timeout=$(BOOTCHECK_TIMEOUT) --qemu=$(QEMU32) --files=/pc-chainloader.bin=pc-chainloader.bin $(srcdir)/VasEBoot-core/tests/boot/pc-chainloader.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null
bootcheck-ntldr: ntldr.bin $(srcdir)/grub-core/tests/boot/ntldr.cfg grub-shell
./grub-shell --timeout=$(BOOTCHECK_TIMEOUT) --qemu=$(QEMU32) --files=/ntldr.bin=ntldr.bin $(srcdir)/grub-core/tests/boot/ntldr.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null
bootcheck-ntldr: ntldr.bin $(srcdir)/VasEBoot-core/tests/boot/ntldr.cfg VasEBoot-shell
./VasEBoot-shell --timeout=$(BOOTCHECK_TIMEOUT) --qemu=$(QEMU32) --files=/ntldr.bin=ntldr.bin $(srcdir)/VasEBoot-core/tests/boot/ntldr.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null
if COND_i386_efi
# NetBSD has no support for finding ACPI on EFI
@ -422,21 +431,22 @@ BOOTCHECK_TIMEOUT=180
bootcheck: $(BOOTCHECKS)
if COND_i386_coreboot
default_payload.elf: grub-mkstandalone grub-mkimage FORCE
FS_PAYLOAD_MODULES ?= $(shell cat VasEBoot-core/fs.lst)
default_payload.elf: VasEBoot-mkstandalone VasEBoot-mkimage FORCE
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
pkgdatadir=. ./VasEBoot-mkstandalone --VasEBoot-mkimage=./VasEBoot-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 $(FS_PAYLOAD_MODULES) password_pbkdf2 $(EXTRA_PAYLOAD_MODULES)' --fonts= --themes= --locales= -d VasEBoot-core/ /boot/VasEBoot/VasEBoot.cfg=$(srcdir)/coreboot.cfg
endif
endif
EXTRA_DIST += grub-core/tests/boot/kbsd.init-i386.S grub-core/tests/boot/kbsd.init-x86_64.S grub-core/tests/boot/kbsd.spec.txt grub-core/tests/boot/kernel-8086.S grub-core/tests/boot/kernel-i386.S grub-core/tests/boot/kfreebsd-aout.cfg grub-core/tests/boot/kfreebsd.cfg grub-core/tests/boot/kfreebsd.init-i386.S grub-core/tests/boot/kfreebsd.init-x86_64.S grub-core/tests/boot/knetbsd.cfg grub-core/tests/boot/kopenbsd.cfg grub-core/tests/boot/kopenbsdlabel.txt grub-core/tests/boot/linux16.cfg grub-core/tests/boot/linux.cfg grub-core/tests/boot/linux.init-i386.S grub-core/tests/boot/linux.init-mips.S grub-core/tests/boot/linux.init-ppc.S grub-core/tests/boot/linux.init-x86_64.S grub-core/tests/boot/linux-ppc.cfg grub-core/tests/boot/multiboot2.cfg grub-core/tests/boot/multiboot.cfg grub-core/tests/boot/ntldr.cfg grub-core/tests/boot/pc-chainloader.cfg grub-core/tests/boot/qemu-shutdown-x86.S
EXTRA_DIST += VasEBoot-core/tests/boot/kbsd.init-i386.S VasEBoot-core/tests/boot/kbsd.init-x86_64.S VasEBoot-core/tests/boot/kbsd.spec.txt VasEBoot-core/tests/boot/kernel-8086.S VasEBoot-core/tests/boot/kernel-i386.S VasEBoot-core/tests/boot/kfreebsd-aout.cfg VasEBoot-core/tests/boot/kfreebsd.cfg VasEBoot-core/tests/boot/kfreebsd.init-i386.S VasEBoot-core/tests/boot/kfreebsd.init-x86_64.S VasEBoot-core/tests/boot/knetbsd.cfg VasEBoot-core/tests/boot/kopenbsd.cfg VasEBoot-core/tests/boot/kopenbsdlabel.txt VasEBoot-core/tests/boot/linux16.cfg VasEBoot-core/tests/boot/linux.cfg VasEBoot-core/tests/boot/linux.init-i386.S VasEBoot-core/tests/boot/linux.init-mips.S VasEBoot-core/tests/boot/linux.init-ppc.S VasEBoot-core/tests/boot/linux.init-x86_64.S VasEBoot-core/tests/boot/linux-ppc.cfg VasEBoot-core/tests/boot/multiboot2.cfg VasEBoot-core/tests/boot/multiboot.cfg VasEBoot-core/tests/boot/ntldr.cfg VasEBoot-core/tests/boot/pc-chainloader.cfg VasEBoot-core/tests/boot/qemu-shutdown-x86.S
windowsdir=$(top_builddir)/$(PACKAGE)-$(VERSION)-for-windows
windowsdir: $(PROGRAMS) $(starfield_DATA) $(platform_DATA)
test -d $(windowsdir) && rm -rf $(windowsdir) || true
test -d $(windowsdir) || mkdir $(windowsdir)
$(MAKE) -C po $(AM_MAKEFLAGS) windowsdir
$(MAKE) -C grub-core $(AM_MAKEFLAGS) windowsdir
$(MAKE) -C VasEBoot-core $(AM_MAKEFLAGS) windowsdir
test -d $(windowsdir)/themes || mkdir $(windowsdir)/themes
test -d $(windowsdir)/themes/starfield || mkdir $(windowsdir)/themes/starfield
for x in $(PROGRAMS); do \
@ -449,7 +459,7 @@ windowsdir: $(PROGRAMS) $(starfield_DATA) $(platform_DATA)
for x in $(starfield_DATA); do \
cp -fp $$x $(windowsdir)/themes/starfield/$$(basename $$x); \
done
for x in $(GRUB_WINDOWS_EXTRA_DIST); do \
for x in $(VAS_EBOOT_WINDOWS_EXTRA_DIST); do \
cp -fp $$x $(windowsdir); \
done
@ -472,10 +482,13 @@ ChangeLog: FORCE
touch $@; \
fi
EXTRA_DIST += ChangeLog ChangeLog-2015
syslinux_test: $(top_builddir)/config.status tests/syslinux/ubuntu10.04_VasEBoot.cfg
syslinux_test: $(top_builddir)/config.status tests/syslinux/ubuntu10.04_grub.cfg
tests/syslinux/ubuntu10.04_grub.cfg: $(top_builddir)/config.status tests/syslinux/ubuntu10.04_grub.cfg.in
(for x in tests/syslinux/ubuntu10.04_grub.cfg.in ; do cat $(srcdir)/"$$x"; done) | $(top_builddir)/config.status --file=$@:-
CLEANFILES += tests/syslinux/ubuntu10.04_grub.cfg
# Mimic simplify_filename from VasEBoot-core/lib/syslinux_parse.c, so that we
# can predict its behaviour in tests. We have to pre-substitute this before
# calling config.status, as config.status offers no reliable way to hook in
# a command between setting ac_abs_top_srcdir and emitting output files.
tests/syslinux/ubuntu10.04_VasEBoot.cfg: $(top_builddir)/config.status tests/syslinux/ubuntu10.04_VasEBoot.cfg.in
simplified_abs_top_srcdir=`echo "$(abs_top_srcdir)" | sed 's,//,/,g; s,/\./,/,g; :loop; s,/[^/][^/]*/\.\.\(/\|$$\),\1,; t loop'`; \
sed "s,@simplified_abs_top_srcdir@,$$simplified_abs_top_srcdir,g" $(srcdir)/tests/syslinux/ubuntu10.04_VasEBoot.cfg.in | $(top_builddir)/config.status --file=$@:-
CLEANFILES += tests/syslinux/ubuntu10.04_VasEBoot.cfg

File diff suppressed because it is too large Load Diff

239
NEWS
View File

@ -1,3 +1,82 @@
New in 2.14.1:
* Small fix in VasEBoot-core/normal/main.c
New in 2.14:
* libgcrypt 1.11.
* LVM LV integrity and cachevol support.
* EROFS support.
* VAS_EBOOT environment block inside the Btrfs header support.
* NX support for EFI platforms.
* shim loader protocol support.
* BLS and UKI support.
* Argon2 KDF support.
* TPM2 key protector support.
* Appended Signature Secure Boot Support for PowerPC.
* New option to block command line interface.
* Support dates outside of 1901..2038 range.
* zstdio decompression support.
* EFI code improvements and fixes.
* TPM driver fixes.
* Filesystems fixes.
* CVE and Coverity fixes.
* Tests improvements.
* Documentation improvements.
* ... and tons of other fixes and cleanups...
New in 2.12:
* GCC 13 support.
* clang 14 support.
* binutils 2.38 support.
* Unification of EFI Linux kernel loader across architectures.
* Transition to EFI Linux kernel stub loader for x86 architecture.
* Initial support for Boot Loader Interface.
* Support for dynamic VAS_EBOOT runtime memory addition using firmware calls.
* PCI and MMIO UARTs support.
* SDL2 support.
* LoongArch support.
* TPM driver fixes.
* Many filesystems fixes.
* Many CVE and Coverity fixes.
* Debugging support improvements.
* Tests improvements.
* Documentation improvements.
* ...and tons of other fixes and cleanups...
New in 2.06:
* GCC 10 support.
* clang 10 support.
* SBAT support.
* LUKS2 support.
* Drop small MBR gap support.
* Xen Security Modules (XSM/FLASK) support.
* The lockdown mechanism similar to the Linux kernel one.
* Disable the os-prober by default.
* Many backports of VAS_EBOOT distros specific patches.
* BootHole and BootHole2 fixes.
* ...and tons of other fixes and cleanups...
New in 2.04:
* GCC 8 and 9 support.
* Gnulib integration overhaul.
* RISC-V support.
* Xen PVH support.
* Native UEFI secure boot support.
* UEFI TPM driver.
* New IEEE 1275 obdisk driver.
* Btrfs RAID 5 and RIAD 6 support.
* PARTUUID support.
* VLAN support.
* Native DHCP support.
* Many ARM and ARM64 fixes.
* Many SPARC fixes.
* Many IEEE 1275 fixes.
* ...and tons of other fixes and cleanups...
New in 2.02:
* New/improved filesystem and disk support:
@ -21,13 +100,13 @@ New in 2.02:
* LVM RAID1 support.
* New/improved terminal and video support:
* Monochrome text (matching `hercules' in GRUB Legacy).
* Monochrome text (matching `hercules' in VAS_EBOOT Legacy).
* Morse code output using system speaker.
* `spkmodem' output (simple data protocol using system speaker).
* Handle Japanese special keys.
* coreboot framebuffer.
* Serial on ARC.
* Native vt100 handling for grub-emu, replacing the use of the curses
* Native vt100 handling for VasEBoot-emu, replacing the use of the curses
library.
* New gfxmenu options for terminal window positioning, theme background
image handling, and scrollbar padding, plus `item_pixmap_style' and
@ -48,7 +127,7 @@ New in 2.02:
interface.
* Autoload `http' and `tftp' modules if necessary.
* Improve TFTP robustness.
* Parse `nd' disk names in GRUB Legacy configuration files.
* Parse `nd' disk names in VAS_EBOOT 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
@ -71,11 +150,11 @@ New in 2.02:
* New command `pcidump' for PCI platforms.
* Improve opcode parsing in ACPI halt implementation.
* Use the TSC as a possible time source on i386-ieee1275.
* Merge PowerPC grub-mkrescue implementation with the common one.
* Support grub-mkrescue on i386-ieee1275, sparc64, bootinfo machines such
* Merge PowerPC VasEBoot-mkrescue implementation with the common one.
* Support VasEBoot-mkrescue on i386-ieee1275, sparc64, bootinfo machines such
as pSeries, and mips-arc.
* Make grub-mkrescue better support Apple Intel Macs on CD.
* Enable GRUB Legacy configuration file parsing on EFI.
* Make VasEBoot-mkrescue better support Apple Intel Macs on CD.
* Enable VAS_EBOOT Legacy configuration file parsing on EFI.
* Support halt for Loongson 2E.
* ARM U-Boot and EFI ports.
* Reorganise platform-dependent code in utilities to avoid #ifdef mess.
@ -84,8 +163,8 @@ New in 2.02:
* Fix EFI stack alignment.
* ARM64 EFI port.
* On Linux, read partition start offsets from sysfs if possible.
* New grub-macbless utility, and better integration with Mac firmware in
grub-install.
* New VasEBoot-macbless utility, and better integration with Mac firmware in
VasEBoot-install.
* Support Yeeloong 3A.
* Add `cpuid --pae' option to detect Physical Address Extension on x86.
* Support for USB debug dongles.
@ -118,36 +197,36 @@ New in 2.02:
* Scripting:
* New `eval' and `tr' commands.
* grub-script-check fails on scripts containing no commands.
* VasEBoot-script-check fails on scripts containing no commands.
* Installation and other utility improvements:
* Add option to compress files on installation or image creation.
* Using grub-reboot no longer requires setting `GRUB_DEFAULT=saved'.
* Using VasEBoot-reboot no longer requires setting `VAS_EBOOT_DEFAULT=saved'.
* Support probing EFI System Partition (requires os-prober >= 1.58).
* Fix inconsistent use of `GRUB_CRYPTODISK_ENABLE' and
`GRUB_ENABLE_CRYPTODISK'; the latter is now used consistently.
* grub-mount handles symbolic links to directories.
* Support disabling submenus with `GRUB_DISABLE_SUBMENU' configuration key
for grub-mkconfig.
* grub-install, grub-mknetdir, grub-mkrescue, and grub-mkstandalone
* Fix inconsistent use of `VAS_EBOOT_CRYPTODISK_ENABLE' and
`VAS_EBOOT_ENABLE_CRYPTODISK'; the latter is now used consistently.
* VasEBoot-mount handles symbolic links to directories.
* Support disabling submenus with `VAS_EBOOT_DISABLE_SUBMENU' configuration key
for VasEBoot-mkconfig.
* VasEBoot-install, VasEBoot-mknetdir, VasEBoot-mkrescue, and VasEBoot-mkstandalone
rewritten in C. They should now work in supported non-Unix-like
environments.
* Native mingw support.
* Ability to install on EFI under windows.
* Reorganise timeout handling using new `timeout_style' environment
variable and `GRUB_TIMEOUT_STYLE' configuration key for grub-mkconfig.
variable and `VAS_EBOOT_TIMEOUT_STYLE' configuration key for VasEBoot-mkconfig.
Menu hotkeys pressed during a hidden timeout now boot the corresponding
menu entry immediately.
* New `file' command and grub-file utility to check file types.
* New `file' command and VasEBoot-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
* On Linux x86 detect EFI word size in VasEBoot-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
* Remove all uses of nested functions; VAS_EBOOT no longer requires an
executable stack.
* Fix documentation build with Texinfo >= 5.1.
* More robust and documented cross-compiling support.
@ -155,7 +234,7 @@ New in 2.02:
* Partial mingw64 x86_64-efi compile support (highly experimental).
* Partial mingw32 i386-* (other than already present i386-pc)
compile support (highly experimental).
* Support for grub-mkpasswd on Windows.
* Support for VasEBoot-mkpasswd on Windows.
* Eliminate the use of AutoGen. This allowed some performance
improvements to the build system.
* Remove variable length arrays.
@ -170,7 +249,7 @@ New in 2.02:
system.
* emu libusb support removed (was broken and unmaintained).
* powerpc64le compile support.
* Use fixed timestamp when generating GRUB image for reproducible builds.
* Use fixed timestamp when generating VAS_EBOOT 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.
@ -186,12 +265,12 @@ New in 2.00:
* New platforms:
* Itanium port.
* Fuloong2F support (including GRUB as firmware)
* Fuloong2E support (except GRUB as firmware)
* Fuloong2F support (including VAS_EBOOT as firmware)
* Fuloong2E support (except VAS_EBOOT as firmware)
* ARCS (SGI machines) port.
* qemu -M mips port.
* grub-mount to mount filesystems using GRUB FS drivers and FUSE.
* VasEBoot-mount to mount filesystems using VAS_EBOOT FS drivers and FUSE.
* Changed security default so entries are locked by default if any superuser is
defined.
@ -250,8 +329,8 @@ New in 2.00:
* Basic illumos and xnu autoconfig.
* Testing and debugging:
* New grub-fstest commands: cat, zfsinfo, testload xnu_uuid
* grub-fstest recursive directory compare for quickly checking that
* New VasEBoot-fstest commands: cat, zfsinfo, testload xnu_uuid
* VasEBoot-fstest recursive directory compare for quickly checking that
a directory is read correctly.
* Backtace on crash (if gdb module is loaded, x86 only)
* Disk cache statistics gathering.
@ -269,12 +348,12 @@ New in 2.00:
* Internationalisation:
* Updated to Unicode 6.0.
* $"..." syntax for translation in grub scripting language. This allows easy
translation of grub.cfg at runtime.
* $"..." syntax for translation in VasEBoot scripting language. This allows easy
translation of VasEBoot.cfg at runtime.
* Translations to many languages included in official distribution.
* Scripting:
* $grub_cpu and $grub_platform variables for conditioning grub.cfg on platform
* $VasEBoot_cpu and $VasEBoot_platform variables for conditioning VasEBoot.cfg on platform
at runtime.
* $feature_* variables to condition scripts on available features.
* Use of ids to identify menu entries.
@ -282,16 +361,16 @@ New in 2.00:
allowing easy loading of all of them.
* Installation:
* grub-mknetdir script for easy creation of netbootable GRUB directory.
* Itanium and mips support in grub-mkrescue.
* grub-install support for all platforms except emu.
* VasEBoot-mknetdir script for easy creation of netbootable VAS_EBOOT directory.
* Itanium and mips support in VasEBoot-mkrescue.
* VasEBoot-install support for all platforms except emu.
* PreP partition install support.
* No files conflict between flavours (except grub-mkrescue for ppc). This
allows easy install of GRUB for several platforms.
* grub-mkstandalone script for easy creating of image including all modules
* No files conflict between flavours (except VasEBoot-mkrescue for ppc). This
allows easy install of VAS_EBOOT for several platforms.
* VasEBoot-mkstandalone script for easy creating of image including all modules
for platforms with generous limit on image size.
* program-transform-name now functions according to usual conventions.
Use --grubdir and --bootdir to get old behaviour.
Use --VasEBootdir and --bootdir to get old behaviour.
* ADLER32 and CRC64 support (for XZ and hashsum).
@ -299,8 +378,8 @@ New in 2.00:
* Experimental support for compiling with Apple toolchain.
* grub-mkdevicemap removed. Now all devices are detected on invocation of
any grub utility.
* VasEBoot-mkdevicemap removed. Now all devices are detected on invocation of
any VasEBoot utility.
New in 1.99:
@ -308,7 +387,7 @@ New in 1.99:
* New `lsapm' command (i386-pc only).
* Parser for GRUB Legacy configuration files.
* Parser for VAS_EBOOT Legacy configuration files.
* Support RAID on virtio devices.
@ -327,7 +406,7 @@ New in 1.99:
listed in device.map will be assumed to be readable using only BIOS
facilities, rather than anything more complex such as LVM or RAID.
* New bash-completion script for GRUB utilities.
* New bash-completion script for VAS_EBOOT utilities.
* Use ACPI to shut down if possible.
@ -335,15 +414,15 @@ New in 1.99:
* Btrfs support.
* New `--boot-directory' option to `grub-install', `grub-reboot', and
`grub-set-default', with clearer semantics than the previous
* New `--boot-directory' option to `VasEBoot-install', `VasEBoot-reboot', and
`VasEBoot-set-default', with clearer semantics than the previous
`--root-directory' option.
* Rename CD-ROM device to "cd" on BIOS platforms.
* Transparent decompression filters.
* Simpler PXE image generation. New `grub-mknetdir' utility to generate
* Simpler PXE image generation. New `VasEBoot-mknetdir' utility to generate
netboot directory trees.
* New relocator. Allows for more kernel support and more
@ -367,18 +446,18 @@ New in 1.99:
* MIPS Yeeloong firmware port.
* Change grub-mkdevicemap to emit /dev/disk/by-id/ names where possible
* Change VasEBoot-mkdevicemap to emit /dev/disk/by-id/ names where possible
on GNU/Linux.
* Add `grub-mkconfig' support for Xen with Linux.
* Add `VasEBoot-mkconfig' support for Xen with Linux.
* Add `grub-mkconfig' support for initrd images on Fedora 13.
* Add `VasEBoot-mkconfig' support for initrd images on Fedora 13.
* Support >3GiB and <16MiB RAM in i386-qemu.
* Add support for Cirrus 5446 and Bochs video cards.
* Load more appropriate video drivers automatically in `grub-mkconfig'.
* Load more appropriate video drivers automatically in `VasEBoot-mkconfig'.
* USB improvements, including hotplugging/hotunplugging, hub support,
and USB serial support.
@ -395,12 +474,12 @@ New in 1.99:
* Add support for DM-RAID disk devices on GNU/Linux.
* Remove `grub-mkisofs'. `grub-mkrescue' now uses GNU xorriso to build
* Remove `VasEBoot-mkisofs'. `VasEBoot-mkrescue' now uses GNU xorriso to build
CD images.
* `grub-mkrescue' support for EFI, coreboot, and QEMU platforms.
* `VasEBoot-mkrescue' support for EFI, coreboot, and QEMU platforms.
* Unify `grub-mkimage', `grub-setup', and `grub-install' source code
* Unify `VasEBoot-mkimage', `VasEBoot-setup', and `VasEBoot-install' source code
across platforms.
* Fix VGA (as opposed to VBE) video driver, formerly a terminal driver.
@ -409,11 +488,11 @@ New in 1.99:
* Add support for the nilfs2 filesystem.
* `grub-probe' and `grub-mkconfig' support for NetBSD.
* `VasEBoot-probe' and `VasEBoot-mkconfig' support for NetBSD.
* Support setting a background image in `grub-mkconfig'.
* Support setting a background image in `VasEBoot-mkconfig'.
* Support multiple terminals in `grub-mkconfig'.
* Support multiple terminals in `VasEBoot-mkconfig'.
* Regexp support.
@ -423,17 +502,17 @@ New in 1.99:
* sunpc partition table support.
* Add a number of new language features to GRUB script: `for', `while',
* Add a number of new language features to VAS_EBOOT script: `for', `while',
`until', `elif', function parameters, `break', `continue', `shift',
multi-line quoted strings, positional parameters with `setparams',
`return', filename wildcard expansion, and `!'.
* Support nested partition tables. GRUB now prefers to name partitions
* Support nested partition tables. VAS_EBOOT now prefers to name partitions
in the form `(hd0,msdos1,bsd1)' rather than `(hd0,1,a)'.
* Speed up consecutive hostdisk operations on the same device.
* Compile parts of `grub-emu' as modules.
* Compile parts of `VasEBoot-emu' as modules.
New in 1.98 - 2010-03-06:
@ -443,18 +522,18 @@ New in 1.98 - 2010-03-06:
* MIPS support.
* Saved default menu entry support, with new utilities `grub-reboot' and
`grub-set-default'.
* Saved default menu entry support, with new utilities `VasEBoot-reboot' and
`VasEBoot-set-default'.
* Unit testing framework.
* Support for multiple terminals.
* Encrypted password support, with a new utility `grub-mkpasswd-pbkdf2'.
* Encrypted password support, with a new utility `VasEBoot-mkpasswd-pbkdf2'.
* `grub-mkfloppy' removed; use `grub-mkrescue' to create floppy images.
* `VasEBoot-mkfloppy' removed; use `VasEBoot-mkrescue' to create floppy images.
* Add grub-probe support for GNU/Hurd.
* Add VasEBoot-probe support for GNU/Hurd.
* Add support for gettext.
@ -482,7 +561,7 @@ New in 1.97:
* Add support for RAID levels 4,6 and 10.
* update-grub is replaced by grub-mkconfig.
* update-VasEBoot is replaced by VasEBoot-mkconfig.
* When booting from PXE, PXE can be used to load files.
@ -510,7 +589,7 @@ New in 1.97:
* Create partmap.lst and use it to automatically load partition map
modules.
* grub-mkconfig supports os-prober to add operating systems to the
* VasEBoot-mkconfig supports os-prober to add operating systems to the
boot menu.
* The ATA driver supports devices bigger than 2 TiB.
@ -525,26 +604,26 @@ New in 1.97:
* Support for direct access to AT keyboards.
* New utility `grub-fstest'.
* New utility `VasEBoot-fstest'.
New in 1.96 - 2008-02-03:
* The license term is changed to GNU General Public License Version 3.
* grub-emu is made optional. Now you have to use
`--enable-grub-emu' to enable it.
* VasEBoot-emu is made optional. Now you have to use
`--enable-VasEBoot-emu' to enable it.
* Add Multiboot2 support.
* grub-emu can access the host filesystem now.
* VasEBoot-emu can access the host filesystem now.
* Add support for the NTFS, cpio/tar and Reiserfs filesystems.
* Add support for ATA/ATAPI.
* Add update-grub script to generate grub.cfg.
* Add update-VasEBoot script to generate VasEBoot.cfg.
* Add grub-mkrescue script to generate floppy or ElTorito images
* Add VasEBoot-mkrescue script to generate floppy or ElTorito images
(i386-pc only).
* Add support for background images in gfxterm (background_image command).
@ -553,7 +632,7 @@ New in 1.96 - 2008-02-03:
* GPT is now enabled in i386-pc target.
* Add grub-install for EFI.
* Add VasEBoot-install for EFI.
* Ported to the following new platforms: Efika, coreboot (a.k.a. LinuxBIOS),
OLPC XO.
@ -568,8 +647,8 @@ New in 1.95 - 2006-10-15:
* Number partitions from 1 instead of 0. For instance, the first
partition of "hd0" is now "hd0,1" but not "hd0,0".
* grub-probefs is renamed to grub-probe, and supports printing a
guessed OS device name and a GRUB drive name.
* VasEBoot-probefs is renamed to VasEBoot-probe, and supports printing a
guessed OS device name and a VAS_EBOOT drive name.
* RAID and LVM support is added.
@ -591,9 +670,9 @@ New in 1.94 - 2006-06-04:
* Use --with-platform to specify a boot environment. For now, efi,
ieee1275 and pc are supported.
* Use the filename "kernel.elf" instead of "grubof" on ieee1275.
* Use the filename "kernel.elf" instead of "VasEBootof" on ieee1275.
* Install GRUB into pkglibdir instead of pkgdatadir.
* Install VAS_EBOOT into pkglibdir instead of pkgdatadir.
* Support environmental variables. You can export variables by the
command "export".
@ -646,17 +725,17 @@ New in 1.91 - 2005-10-15:
* Add support for x86_64.
* GRUB itself is a Multiboot-compliant kernel.
* VAS_EBOOT itself is a Multiboot-compliant kernel.
* Add new filesystems: XFS, SFS, and AFFS.
New in 1.90 - 2005-08-07:
* Rename the project name PUPA to GRUB. Now this version is the
developmental version of GRUB officially.
* Rename the project name PUPA to VAS_EBOOT. Now this version is the
developmental version of VAS_EBOOT officially.
* The GRUB emulator ``grub-emu'' is added.
* The VAS_EBOOT emulator ``VasEBoot-emu'' is added.
* Add support for newworld Mac. This should work with other
PowerPC-based machines as well, if they use IEEE 1275

24
README
View File

@ -1,20 +1,26 @@
This is GRUB 2, the second version of the GRand Unified Bootloader.
GRUB 2 is rewritten from scratch to make GNU GRUB cleaner, safer, more
This is VAS_EBOOT 2, the second version of the GRUB.
VAS_EBOOT 2 is rewritten from scratch to make QNU VAS_EBOOT cleaner, safer, more
robust, more powerful, and more portable.
See the file NEWS for a description of recent changes to GRUB 2.
See the file NEWS for a description of recent changes to VAS_EBOOT 2.
See the file INSTALL for instructions on how to build and install the
GRUB 2 data and program files.
VAS_EBOOT 2 data and program files.
Please visit the official web page of GRUB 2, for more information.
The URL is <http://www.gnu.org/software/grub/grub.html>.
See the file MAINTAINERS for information about the VAS_EBOOT maintainers, etc.
If you found a security vulnerability in the VAS_EBOOT please check the SECURITY
file to get more information how to properly report this kind of bugs to
the maintainers.
Please visit the official web page of VAS_EBOOT 2, for more information.
The URL is <http://www.gnu.org/software/VasEBoot/VasEBoot.html>.
More extensive documentation is available in the Info manual,
accessible using 'info grub' after building and installing GRUB 2.
accessible using 'info VasEBoot' after building and installing VAS_EBOOT 2.
There are a number of important user-visible differences from the
first version of GRUB, now known as GRUB Legacy. For a summary, please
first version of VAS_EBOOT, now known as VAS_EBOOT Legacy. For a summary, please
see:
info grub Introduction 'Changes from GRUB Legacy'
info VasEBoot Introduction 'Changes from VAS_EBOOT Legacy'

60
SECURITY Normal file
View File

@ -0,0 +1,60 @@
Security Policy
===============
To report a vulnerability see "Reporting a Vulnerability" below.
Security Incident Policy
========================
Security bug reports are treated with special attention and are handled
differently from normal bugs. In particular, security sensitive bugs are not
handled in public but in private. Information about the bug and access to it
is restricted to people in the security group, the individual engineers that
work on fixing it, and any other person who needs to be involved for organisational
reasons. The process is handled by the security team, which decides on the people
involved in order to fix the issue. It is also guaranteed that the person reporting
the issue has visibility into the process of fixing it. Any security issue gets
prioritized according to its security rating. The issue is opened up to the public
in coordination with the release schedule and the reporter.
Disclosure Policy
=================
Everyone involved in the handling of a security issue - including the reporter -
is required to adhere to the following policy. Any information related to
a security issue must be treated as confidential and only shared with trusted
partners if necessary, for example to coordinate a release or manage exposure
of clients to the issue. No information must be disclosed to the public before
the embargo ends. The embargo time is agreed upon by all involved parties. It
should be as short as possible without putting any users at risk.
Supported Versions
==================
Only the most recent version of the VAS_EBOOT is supported.
Reporting a Vulnerability
=========================
The security report should be encrypted with the PGP keys and sent to ALL email
addresses listed below. Every vulnerability report will be assessed within
72 hours of receiving it. If the outcome of the assessment is that the report
describes a security issue, the report will be transferred into an issue on the
internal vulnerability project for further processing. The reporter is updated
on each step of the process.
While there's currently no bug bounty program we appreciate every report.
* Contact: Daniel Kiper <daniel.kiper@oracle.com> and
Daniel Kiper <dkiper@net-space.pl>
* PGP Key Fingerprint: BE5C 2320 9ACD DACE B20D B0A2 8C81 89F1 988C 2166
* Contact: Alex Burmashev <alexander.burmashev@oracle.com>
* PGP Key Fingerprint: 50A4 EC06 EF7E B84D 67E0 3BB6 2AE2 C87E 28EF 2E6E
* Contact: Vladimir 'phcoder' Serbinenko <phcoder@gmail.com>
* PGP Key Fingerprint: E53D 497F 3FA4 2AD8 C9B4 D1E8 35A9 3B74 E82E 4209

4
THANKS
View File

@ -1,10 +1,10 @@
GRUB 2 would not be what it is today without the invaluable help of
VAS_EBOOT 2 would not be what it is today without the invaluable help of
everybody who was kind enough to spend time testing it and reporting
bugs.
The following people made especially gracious contributions of their
time and energy in helping to track down bugs, add new features, and
generally assist in the GRUB 2 maintainership process:
generally assist in the VAS_EBOOT 2 maintainership process:
Andrey Shuvikov <mr_hyro@yahoo.com>
Bibo Mao <bibo.mao@intel.com>

8
TODO
View File

@ -1,9 +1,9 @@
Before working on improving GRUB, it's very important that you
make contact with the core GRUB developers. Things herein might be
Before working on improving VAS_EBOOT, it's very important that you
make contact with the core VAS_EBOOT developers. Things herein might be
slightly out of date or otherwise not easy to understand at first
glance. So write to <grub-devel@gnu.org> first.
glance. So write to <VasEBoot-devel@gnu.org> first.
For bug tracking, refer to:
http://savannah.gnu.org/bugs/?group=grub
http://savannah.gnu.org/bugs/?group=VasEBoot

524
VasEBoot-core/Makefile.am Normal file
View File

@ -0,0 +1,524 @@
AUTOMAKE_OPTIONS = subdir-objects -Wno-portability
DEPDIR=.deps-core
include $(top_srcdir)/conf/Makefile.common
CC=$(TARGET_CC)
CPP=$(TARGET_CC)
CCAS=$(TARGET_CC)
RANLIB=$(TARGET_RANLIB)
STRIP=$(TARGET_STRIP)
MACHO2IMG=$(top_builddir)/VasEBoot-macho2img
AM_CFLAGS = $(TARGET_CFLAGS)
AM_LDFLAGS = $(TARGET_LDFLAGS)
AM_CPPFLAGS = $(TARGET_CPPFLAGS) $(CPPFLAGS_DEFAULT)
AM_CCASFLAGS = $(TARGET_CCASFLAGS) $(CCASFLAGS_DEFAULT)
CFLAGS_PROGRAM += $(CFLAGS_PLATFORM)
LDFLAGS_PROGRAM += $(LDFLAGS_PLATFORM)
CPPFLAGS_PROGRAM += $(CPPFLAGS_PLATFORM)
CCASFLAGS_PROGRAM += $(CCASFLAGS_PLATFORM)
CFLAGS_LIBRARY += $(CFLAGS_PLATFORM) -fno-builtin
CPPFLAGS_LIBRARY += $(CPPFLAGS_PLATFORM)
CCASFLAGS_LIBRARY += $(CCASFLAGS_PLATFORM)
build-VasEBoot-pep2elf$(BUILD_EXEEXT): $(top_srcdir)/util/VasEBoot-pe2elf.c $(top_srcdir)/VasEBoot-core/kern/emu/misc.c $(top_srcdir)/util/misc.c
$(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(BUILD_LDFLAGS) -DVAS_EBOOT_BUILD=1 -DVAS_EBOOT_TARGET_WORDSIZE=64 -DVAS_EBOOT_UTIL=1 -DVAS_EBOOT_BUILD_PROGRAM_NAME=\"build-VasEBoot-pep2elf\" $^
CLEANFILES += build-VasEBoot-pep2elf$(BUILD_EXEEXT)
build-VasEBoot-pe2elf$(BUILD_EXEEXT): $(top_srcdir)/util/VasEBoot-pe2elf.c $(top_srcdir)/VasEBoot-core/kern/emu/misc.c $(top_srcdir)/util/misc.c
$(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(BUILD_LDFLAGS) -DVAS_EBOOT_BUILD=1 -DVAS_EBOOT_TARGET_WORDSIZE=32 -DVAS_EBOOT_UTIL=1 -DVAS_EBOOT_BUILD_PROGRAM_NAME=\"build-VasEBoot-pe2elf\" $^
CLEANFILES += build-VasEBoot-pe2elf$(BUILD_EXEEXT)
# gentrigtables
gentrigtables$(BUILD_EXEEXT): gentrigtables.c
$(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(BUILD_LDFLAGS) $< $(BUILD_LIBM)
CLEANFILES += gentrigtables$(BUILD_EXEEXT)
build-VasEBoot-module-verifier$(BUILD_EXEEXT): $(top_srcdir)/util/VasEBoot-module-verifier.c $(top_srcdir)/util/VasEBoot-module-verifier32.c $(top_srcdir)/util/VasEBoot-module-verifier64.c $(top_srcdir)/VasEBoot-core/kern/emu/misc.c $(top_srcdir)/util/misc.c
$(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(BUILD_LDFLAGS) -DVAS_EBOOT_BUILD=1 -DVAS_EBOOT_UTIL=1 -DVAS_EBOOT_BUILD_PROGRAM_NAME=\"build-VasEBoot-module-verifier\" $^
CLEANFILES += build-VasEBoot-module-verifier$(BUILD_EXEEXT)
# trigtables.c
trigtables.c: gentrigtables$(BUILD_EXEEXT) gentrigtables.c $(top_srcdir)/configure.ac
./gentrigtables$(BUILD_EXEEXT) > $@
CLEANFILES += trigtables.c
# XXX Use Automake's LEX & YACC support
VasEBoot_script.tab.h: script/parser.y
$(YACC) -d -p VasEBoot_script_yy -b VasEBoot_script $<
VasEBoot_script.tab.c: VasEBoot_script.tab.h
CLEANFILES += VasEBoot_script.tab.c VasEBoot_script.tab.h
# For the lexer.
VasEBoot_script.yy.h: script/yylex.l
$(LEX) -o VasEBoot_script.yy.c --header-file=VasEBoot_script.yy.h $<
VasEBoot_script.yy.c: VasEBoot_script.yy.h
rs_decoder.h: $(srcdir)/lib/reed_solomon.c
$(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) -Os -I$(top_builddir) -S -DSTANDALONE -o $@ $< -g0 -mregparm=3 -ffreestanding
CLEANFILES += VasEBoot_script.yy.c VasEBoot_script.yy.h
include $(srcdir)/Makefile.core.am
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/cache.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/command.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/device.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/disk.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/dl.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/efi/sb.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/env.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/env_private.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/err.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/file.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/fs.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/i18n.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/kernel.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/list.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/lockdown.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/misc.h
if COND_emu
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/compiler-rt-emu.h
else
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/compiler-rt.h
endif
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/mm.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/parser.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/partition.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/key_protector.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/stack_protector.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/term.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/time.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/verify.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/mm_private.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/net.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/memory.h
if COND_i386_pc
KERNEL_HEADER_FILES += $(top_builddir)/include/VasEBoot/machine/kernel.h
KERNEL_HEADER_FILES += $(top_builddir)/include/VasEBoot/machine/pxe.h
KERNEL_HEADER_FILES += $(top_builddir)/include/VasEBoot/machine/int.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/i386/tsc.h
endif
if COND_i386_xen_pvh
KERNEL_HEADER_FILES += $(top_builddir)/include/VasEBoot/machine/kernel.h
KERNEL_HEADER_FILES += $(top_builddir)/include/VasEBoot/machine/int.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/i386/tsc.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/terminfo.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/extcmd.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/loader.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/lib/arg.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/xen.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/i386/xen/hypercall.h
endif
if COND_i386_efi
KERNEL_HEADER_FILES += $(top_builddir)/include/VasEBoot/machine/kernel.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/efi/efi.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/efi/disk.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/i386/tsc.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/acpi.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/pci.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/i386/pmtimer.h
endif
if COND_i386_coreboot
KERNEL_HEADER_FILES += $(top_builddir)/include/VasEBoot/machine/kernel.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/i386/tsc.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/coreboot/lbio.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/video.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/video_fb.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/gfxterm.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/font.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/bufio.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/acpi.h
endif
if COND_i386_multiboot
KERNEL_HEADER_FILES += $(top_builddir)/include/VasEBoot/machine/kernel.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/i386/tsc.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/acpi.h
endif
if COND_i386_qemu
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/pci.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/i386/tsc.h
endif
if COND_i386_ieee1275
KERNEL_HEADER_FILES += $(top_builddir)/include/VasEBoot/machine/kernel.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/ieee1275/ieee1275.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/ieee1275/alloc.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/terminfo.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/extcmd.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/lib/arg.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/i386/tsc.h
endif
if COND_i386_xen
KERNEL_HEADER_FILES += $(top_builddir)/include/VasEBoot/machine/kernel.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/xen.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/i386/xen/hypercall.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/terminfo.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/extcmd.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/lib/arg.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/loader.h
endif
if COND_x86_64_xen
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/xen.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/x86_64/xen/hypercall.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/terminfo.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/extcmd.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/lib/arg.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/loader.h
endif
if COND_x86_64_efi
KERNEL_HEADER_FILES += $(top_builddir)/include/VasEBoot/machine/kernel.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/efi/efi.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/efi/disk.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/i386/tsc.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/pci.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/acpi.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/i386/pmtimer.h
endif
if COND_ia64_efi
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/efi/efi.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/efi/disk.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/acpi.h
endif
if COND_mips
KERNEL_HEADER_FILES += $(top_builddir)/include/VasEBoot/cpu/kernel.h
endif
if COND_mips_arc
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/extcmd.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/arc/arc.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/terminfo.h
endif
if COND_mips_qemu_mips
KERNEL_HEADER_FILES += $(top_builddir)/include/VasEBoot/keyboard_layouts.h
KERNEL_HEADER_FILES += $(top_builddir)/include/VasEBoot/machine/kernel.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/serial.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/loader.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/terminfo.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/extcmd.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/lib/arg.h
endif
if COND_mips_loongson
KERNEL_HEADER_FILES += $(top_builddir)/include/VasEBoot/keyboard_layouts.h
KERNEL_HEADER_FILES += $(top_builddir)/include/VasEBoot/machine/kernel.h
KERNEL_HEADER_FILES += $(top_builddir)/include/VasEBoot/machine/time.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/video.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/video_fb.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/gfxterm.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/font.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/bufio.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/pci.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/cs5536.h
KERNEL_HEADER_FILES += $(top_builddir)/include/VasEBoot/machine/pci.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/serial.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/loader.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/terminfo.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/extcmd.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/lib/arg.h
endif
if COND_mips_qemu_mips
KERNEL_HEADER_FILES += $(top_builddir)/include/VasEBoot/machine/memory.h
KERNEL_HEADER_FILES += $(top_builddir)/include/VasEBoot/machine/kernel.h
endif
if COND_powerpc_ieee1275
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/ieee1275/ieee1275.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/ieee1275/alloc.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/terminfo.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/extcmd.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/lib/arg.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/powerpc/ieee1275/ieee1275.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/powerpc/ieee1275/platform_keystore.h
endif
if COND_sparc64_ieee1275
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/ieee1275/ieee1275.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/sparc64/ieee1275/ieee1275.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/terminfo.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/extcmd.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/lib/arg.h
endif
if COND_arm_uboot
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/uboot/uboot.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/uboot/disk.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/extcmd.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/lib/arg.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/arm/system.h
endif
if COND_arm_coreboot
KERNEL_HEADER_FILES += $(top_builddir)/include/VasEBoot/keyboard_layouts.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/arm/system.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/video.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/video_fb.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/gfxterm.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/font.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/bufio.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/fdt.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/dma.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/arm/coreboot/kernel.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/fdtbus.h
endif
if COND_arm_efi
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/efi/efi.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/efi/disk.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/arm/system.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/acpi.h
endif
if COND_arm64_efi
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/efi/efi.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/efi/disk.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/acpi.h
endif
if COND_loongarch64_efi
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/efi/efi.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/efi/disk.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/acpi.h
endif
if COND_riscv32_efi
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/efi/efi.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/efi/disk.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/acpi.h
endif
if COND_riscv64_efi
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/efi/efi.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/efi/disk.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/acpi.h
endif
if COND_emu
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/datetime.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/emu/misc.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/emu/net.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/emu/hostdisk.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/emu/hostfile.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/extcmd.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/emu/exec.h
if COND_VAS_EBOOT_EMU_SDL
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/sdl.h
endif
if COND_VAS_EBOOT_EMU_SDL2
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/sdl.h
endif
if COND_VAS_EBOOT_EMU_PCI
KERNEL_HEADER_FILES += $(top_srcdir)/include/VasEBoot/libpciaccess.h
endif
endif
symlist.h: $(top_builddir)/config.h $(KERNEL_HEADER_FILES)
@list='$^'; \
for p in $$list; do \
echo "#include <$$p>" >> $@ || (rm -f $@; exit 1); \
done
CLEANFILES += symlist.h
BUILT_SOURCES += symlist.h
symlist.c: symlist.h gensymlist.sh
$(TARGET_CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS_KERNEL) $(CPPFLAGS) -DVAS_EBOOT_SYMBOL_GENERATOR=1 symlist.h > symlist.p || (rm -f symlist.p; 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
if COND_HAVE_ASM_USCORE
ASM_PREFIX=_
else
ASM_PREFIX=
endif
noinst_DATA += kernel_syms.lst
kernel_syms.lst: $(KERNEL_HEADER_FILES) $(top_builddir)/config.h
$(TARGET_CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS_KERNEL) $(CPPFLAGS) $(CFLAGS) -DVAS_EBOOT_SYMBOL_GENERATOR=1 $^ >kernel_syms.input
cat kernel_syms.input | grep -v '^#' | sed -n \
-e '/EXPORT_FUNC *([a-zA-Z0-9_]*)/{s/.*EXPORT_FUNC *(\([a-zA-Z0-9_]*\)).*/defined kernel '"$(ASM_PREFIX)"'\1/;p;}' \
-e '/EXPORT_VAR *([a-zA-Z0-9_]*)/{s/.*EXPORT_VAR *(\([a-zA-Z0-9_]*\)).*/defined kernel '"$(ASM_PREFIX)"'\1/;p;}' \
| sort -u >$@
rm -f kernel_syms.input
CLEANFILES += kernel_syms.lst
if COND_emu
kern/emu/VasEBoot_emu-main.$(OBJEXT):VasEBoot_emu_init.h
VasEBoot_emu-VasEBoot_emu_init.$(OBJEXT):VasEBoot_emu_init.h
kern/emu/VasEBoot_emu_dyn-main.$(OBJEXT):VasEBoot_emu_init.h
VasEBoot_emu_dyn-VasEBoot_emu_init.$(OBJEXT):VasEBoot_emu_init.h
VasEBoot_emu_init.h: genemuinitheader.sh $(MODULE_FILES)
rm -f $@; echo $(MODULE_FILES) | sh $(srcdir)/genemuinitheader.sh $(TARGET_NM) > $@
CLEANFILES += VasEBoot_emu_init.h
VasEBoot_emu_init.c: VasEBoot_emu_init.h genemuinit.sh $(MODULE_FILES)
rm -f $@; echo $(MODULE_FILES) | sh $(srcdir)/genemuinit.sh $(TARGET_NM) > $@
CLEANFILES += VasEBoot_emu_init.c
endif
# List files
fs.lst: $(MARKER_FILES)
(for pp in $^; do \
b=`basename $$pp .marker`; \
if grep 'FS_LIST_MARKER' $$pp >/dev/null 2>&1; then \
echo $$b; \
fi; \
done) | sort -u > $@
platform_DATA += fs.lst
CLEANFILES += fs.lst
command.lst: $(MARKER_FILES)
(for pp in $^; do \
b=`basename $$pp .marker`; \
sed -n \
-e "/EXTCOMMAND_LIST_MARKER *( *\"/{s/.*( *\"\([^\"]*\)\".*/*\1: $$b/;p;}" \
-e "/EXTCOMMAND_LOCKDOWN_LIST_MARKER *( *\"/{s/.*( *\"\([^\"]*\)\".*/*\1: $$b/;p;}" \
-e "/P1COMMAND_LIST_MARKER *( *\"/{s/.*( *\"\([^\"]*\)\".*/*\1: $$b/;p;}" \
-e "/COMMAND_LIST_MARKER *( *\"/{s/.*( *\"\([^\"]*\)\".*/\1: $$b/;p;}" \
-e "/COMMAND_LOCKDOWN_LIST_MARKER *( *\"/{s/.*( *\"\([^\"]*\)\".*/\1: $$b/;p;}" $$pp; \
done) | sort -u > $@
platform_DATA += command.lst
CLEANFILES += command.lst
partmap.lst: $(MARKER_FILES)
(for pp in $^; do \
b=`basename $$pp .marker`; \
if grep 'PARTMAP_LIST_MARKER' $$pp >/dev/null 2>&1; then \
echo $$b; \
fi; \
done) | sort -u > $@
platform_DATA += partmap.lst
CLEANFILES += partmap.lst
terminal.lst: $(MARKER_FILES)
(for pp in $^; do \
b=`basename $$pp .marker`; \
sed -n \
-e "/INPUT_TERMINAL_LIST_MARKER *( *\"/{s/.*( *\"\([^\"]*\)\".*/i\1: $$b/;p;}" \
-e "/OUTPUT_TERMINAL_LIST_MARKER *( *\"/{s/.*( *\"\([^\"]*\)\".*/o\1: $$b/;p;}" $$pp; \
done) | sort -u > $@
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`; \
sed -n \
-e "/PARTTOOL_LIST_MARKER *( *\"/{s/.*( *\"\([^\"]*\)\".*/\1: $$b/;p;}" $$pp; \
done) | sort -u > $@
platform_DATA += parttool.lst
CLEANFILES += parttool.lst
video.lst: $(MARKER_FILES)
(for pp in $^; do \
b=`basename $$pp .marker`; \
if grep 'VIDEO_LIST_MARKER' $$pp >/dev/null 2>&1; then \
echo $$b; \
fi; \
done) | sort -u > $@
platform_DATA += video.lst
CLEANFILES += video.lst
# but, crypto.lst is simply copied
crypto.lst: $(srcdir)/lib/libgcrypt-VasEBoot/cipher/crypto.lst
cp $^ $@
platform_DATA += crypto.lst
CLEANFILES += crypto.lst
extra_deps.lst:
@echo $(EXTRA_DEPS) | sed "s/\s*:\s*/\n/g" > $@
syminfo.lst: gensyminfo.sh kernel_syms.lst extra_deps.lst $(MODULE_FILES)
cat kernel_syms.lst extra_deps.lst > $@.new
for m in $(MODULE_FILES); do \
sh $< $$m >> $@.new || exit 1; \
done
mv $@.new $@
# generate global module dependencies list
moddep.lst: syminfo.lst genmoddep.awk video.lst
cat $< | sort | $(AWK) -f $(srcdir)/genmoddep.awk > $@ || (rm -f $@; exit 1)
platform_DATA += moddep.lst
CLEANFILES += config.log syminfo.lst moddep.lst extra_deps.lst
$(MOD_FILES): %.mod : genmod.sh moddep.lst %.module$(EXEEXT) build-VasEBoot-module-verifier$(BUILD_EXEEXT)
TARGET_OBJ2ELF=@TARGET_OBJ2ELF@ sh $^ $@
platform_DATA += $(MOD_FILES)
platform_DATA += modinfo.sh
CLEANFILES += $(MOD_FILES)
if COND_ENABLE_EFIEMU
efiemu32.o: efiemu/runtime/efiemu.c $(TARGET_OBJ2ELF)
-rm -f $@
-rm -f $@.bin
$(TARGET_CC) $(DEFS) $(INCLUDES) $(CPPFLAGS_EFIEMU) $(CPPFLAGS_DEFAULT) -m32 -Wall -Werror -nostdlib -static -O2 -c -o $@.bin $<
if test "x$(TARGET_APPLE_LINKER)" = x1; then \
$(TARGET_OBJCONV) -felf32 -nu -nd $@.bin $@ || exit 1; \
rm -f $@.bin ; \
elif test ! -z "$(TARGET_OBJ2ELF)"; then \
$(TARGET_OBJ2ELF) $@.bin || (rm -f $@.bin; exit 1); \
mv $@.bin $@ ; \
else \
mv $@.bin $@ ; \
fi
# Link format -arch,x86_64 means Apple linker
efiemu64_c.o: efiemu/runtime/efiemu.c
$(TARGET_CC) $(DEFS) $(INCLUDES) $(CPPFLAGS_EFIEMU) $(CPPFLAGS_DEFAULT) -m64 -nostdlib -Wall -Werror -O2 -mcmodel=large -mno-red-zone -c -o $@ $<
efiemu64_s.o: efiemu/runtime/efiemu.S
$(TARGET_CC) $(DEFS) $(INCLUDES) $(CPPFLAGS_EFIEMU) $(CPPFLAGS_DEFAULT) -m64 -Wall -Werror -nostdlib -O2 -mcmodel=large -mno-red-zone -c -o $@ $<
efiemu64.o: efiemu64_c.o efiemu64_s.o $(TARGET_OBJ2ELEF)
-rm -f $@
-rm -f $@.bin
$(TARGET_CC) -m64 $(EFIEMU64_LINK_FORMAT) -nostdlib -static -Wl,-r -o $@.bin $^
if test "x$(EFIEMU64_LINK_FORMAT)" = x-arch,x86_64; then \
$(TARGET_OBJCONV) -felf64 -nu -nd $@.bin $@ || exit 1; \
rm -f $@.bin; \
else \
mv $@.bin $@ ; \
fi
platform_DATA += efiemu32.o efiemu64.o
CLEANFILES += efiemu32.o efiemu64.o efiemu64_c.o efiemu64_s.o
endif
windowsdir=$(top_builddir)/$(PACKAGE)-$(VERSION)-for-windows
windowsdir: $(PROGRAMS) $(starfield_DATA) $(platform_DATA)
test -d $(windowsdir)/$(target_cpu)-$(platform) || mkdir $(windowsdir)/$(target_cpu)-$(platform)
for x in $(platform_DATA); do \
cp -fp $$x $(windowsdir)/$(target_cpu)-$(platform)/$$x; \
done

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,99 @@
/*
* VAS_EBOOT -- GRand Unified Bootloader
* Copyright (C) 2010 Free Software Foundation, Inc.
*
* VAS_EBOOT 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.
*
* VAS_EBOOT 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 VAS_EBOOT. If not, see <http://www.gnu.org/licenses/>.
*/
#include <VasEBoot/types.h>
#include <VasEBoot/misc.h>
#include <VasEBoot/decompressor.h>
void *
VasEBoot_memset (void *s, int c, VasEBoot_size_t len)
{
VasEBoot_uint8_t *ptr;
for (ptr = s; len; ptr++, len--)
*ptr = c;
return s;
}
void *
VasEBoot_memmove (void *dest, const void *src, VasEBoot_size_t n)
{
char *d = (char *) dest;
const char *s = (const char *) src;
if (d < s)
while (n--)
*d++ = *s++;
else
{
d += n;
s += n;
while (n--)
*--d = *--s;
}
return dest;
}
void *
VasEBoot_memcpy (void *dest, const void *src, VasEBoot_size_t n)
{
return VasEBoot_memmove (dest, src, n);
}
int
VasEBoot_memcmp (const void *s1, const void *s2, VasEBoot_size_t n)
{
const unsigned char *t1 = s1;
const unsigned char *t2 = s2;
while (n--)
{
if (*t1 != *t2)
return (int) *t1 - (int) *t2;
t1++;
t2++;
}
return 0;
}
void *VasEBoot_decompressor_scratch;
void
find_scratch (void *src, void *dst, unsigned long srcsize,
unsigned long dstsize)
{
#ifdef _mips
/* Decoding from ROM. */
if (((VasEBoot_addr_t) src & 0x10000000))
{
VasEBoot_decompressor_scratch = (void *) ALIGN_UP((VasEBoot_addr_t) dst + dstsize,
256);
return;
}
#endif
if ((char *) src + srcsize > (char *) dst + dstsize)
VasEBoot_decompressor_scratch = (void *) ALIGN_UP ((VasEBoot_addr_t) src + srcsize,
256);
else
VasEBoot_decompressor_scratch = (void *) ALIGN_UP ((VasEBoot_addr_t) dst + dstsize,
256);
return;
}

View File

@ -0,0 +1,42 @@
/*
* VAS_EBOOT -- GRand Unified Bootloader
* Copyright (C) 2010 Free Software Foundation, Inc.
*
* VAS_EBOOT 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.
*
* VAS_EBOOT 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 VAS_EBOOT. If not, see <http://www.gnu.org/licenses/>.
*/
#include <VasEBoot/decompressor.h>
void
VasEBoot_decompress_core (void *src, void *dest, unsigned long n,
unsigned long dstsize __attribute__ ((unused)))
{
char *d = (char *) dest;
const char *s = (const char *) src;
if (d == s)
return;
if (d < s)
while (n--)
*d++ = *s++;
else
{
d += n;
s += n;
while (n--)
*--d = *--s;
}
}

View File

@ -0,0 +1,60 @@
/*
* VAS_EBOOT -- GRand Unified Bootloader
* Copyright (C) 2010 Free Software Foundation, Inc.
*
* VAS_EBOOT 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.
*
* VAS_EBOOT 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 VAS_EBOOT. If not, see <http://www.gnu.org/licenses/>.
*/
#include <VasEBoot/types.h>
#include <VasEBoot/misc.h>
#include <VasEBoot/decompressor.h>
#include "xz.h"
#include "xz_stream.h"
void
VasEBoot_decompress_core (void *src, void *dst, unsigned long srcsize,
unsigned long dstsize)
{
struct xz_dec *dec;
struct xz_buf buf;
find_scratch (src, dst, srcsize, dstsize);
dec = xz_dec_init (VAS_EBOOT_DECOMPRESSOR_DICT_SIZE);
buf.in = src;
buf.in_pos = 0;
buf.in_size = srcsize;
buf.out = dst;
buf.out_pos = 0;
buf.out_size = dstsize;
while (buf.in_pos != buf.in_size)
{
enum xz_ret xzret;
xzret = xz_dec_run (dec, &buf);
switch (xzret)
{
case XZ_MEMLIMIT_ERROR:
case XZ_FORMAT_ERROR:
case XZ_OPTIONS_ERROR:
case XZ_DATA_ERROR:
case XZ_BUF_ERROR:
return;
default:
break;
}
}
}

View File

@ -0,0 +1,542 @@
/* -*-Asm-*- */
/*
* VAS_EBOOT -- GRand Unified Bootloader
* Copyright (C) 1999,2000,2001,2002,2005,2006,2007,2008,2009 Free Software Foundation, Inc.
*
* VAS_EBOOT 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.
*
* VAS_EBOOT 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 VAS_EBOOT. If not, see <http://www.gnu.org/licenses/>.
*/
#include <VasEBoot/symbol.h>
#include <VasEBoot/machine/boot.h>
/*
* defines for the code go here
*/
/* Print message string */
#define MSG(x) movw $x, %si; call LOCAL(message)
#define ERR(x) movw $x, %si; jmp LOCAL(error_message)
.macro floppy
part_start:
LOCAL(probe_values):
.byte 36, 18, 15, 9, 0
LOCAL(floppy_probe):
pushw %dx
/*
* Perform floppy probe.
*/
#ifdef __APPLE__
LOCAL(probe_values_minus_one) = LOCAL(probe_values) - 1
movw MACRO_DOLLAR(LOCAL(probe_values_minus_one)), %si
#else
movw MACRO_DOLLAR(LOCAL(probe_values)) - 1, %si
#endif
LOCAL(probe_loop):
/* reset floppy controller INT 13h AH=0 */
xorw %ax, %ax
int MACRO_DOLLAR(0x13)
incw %si
movb (%si), %cl
/* if number of sectors is 0, display error and die */
testb %cl, %cl
jnz 1f
/*
* Floppy disk probe failure.
*/
MSG(fd_probe_error_string)
jmp LOCAL(general_error)
/* "Floppy" */
fd_probe_error_string: .asciz "Floppy"
1:
/* perform read */
movw MACRO_DOLLAR(VAS_EBOOT_BOOT_MACHINE_BUFFER_SEG), %bx
movw %bx, %es
xorw %bx, %bx
movw MACRO_DOLLAR(0x201), %ax
movb MACRO_DOLLAR(0), %ch
movb MACRO_DOLLAR(0), %dh
int MACRO_DOLLAR(0x13)
/* if error, jump to "LOCAL(probe_loop)" */
jc LOCAL(probe_loop)
/* %cl is already the correct value! */
movb MACRO_DOLLAR(1), %dh
movb MACRO_DOLLAR(79), %ch
jmp LOCAL(final_init)
.endm
.macro scratch
/* scratch space */
mode:
.byte 0
disk_address_packet:
sectors:
.long 0
heads:
.long 0
cylinders:
.word 0
sector_start:
.byte 0
head_start:
.byte 0
cylinder_start:
.word 0
/* more space... */
.endm
.file "boot.S"
.text
/* Tell GAS to generate 16-bit instructions so that this code works
in real mode. */
.code16
.globl _start, start;
_start:
start:
/*
* _start is loaded at 0x7c00 and is jumped to with CS:IP 0:0x7c00
*/
/*
* Beginning of the sector is compatible with the FAT/HPFS BIOS
* parameter block.
*/
jmp LOCAL(after_BPB)
nop /* do I care about this ??? */
#ifdef HYBRID_BOOT
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
jmp LOCAL(after_BPB)
#else
/*
* This space is for the BIOS parameter block!!!! Don't change
* the first jump, nor start the code anywhere but right after
* this area.
*/
.org VAS_EBOOT_BOOT_MACHINE_BPB_START
.org 4
#endif
#ifdef HYBRID_BOOT
floppy
#else
scratch
#endif
.org VAS_EBOOT_BOOT_MACHINE_BPB_END
/*
* End of BIOS parameter block.
*/
LOCAL(kernel_address):
.word VAS_EBOOT_BOOT_MACHINE_KERNEL_ADDR
#ifndef HYBRID_BOOT
.org VAS_EBOOT_BOOT_MACHINE_KERNEL_SECTOR
LOCAL(kernel_sector):
.long 1
LOCAL(kernel_sector_high):
.long 0
#endif
.org VAS_EBOOT_BOOT_MACHINE_BOOT_DRIVE
boot_drive:
.byte 0xff /* the disk to load kernel from */
/* 0xff means use the boot drive */
LOCAL(after_BPB):
/* general setup */
cli /* we're not safe here! */
/*
* This is a workaround for buggy BIOSes which don't pass boot
* drive correctly. If VAS_EBOOT is installed into a HDD, check if
* DL is masked correctly. If not, assume that the BIOS passed
* a bogus value and set DL to 0x80, since this is the only
* possible boot drive. If VAS_EBOOT is installed into a floppy,
* this does nothing (only jump).
*/
.org VAS_EBOOT_BOOT_MACHINE_DRIVE_CHECK
boot_drive_check:
jmp 3f /* VasEBoot-setup may overwrite this jump */
testb $0x80, %dl
jz 2f
3:
/* Ignore %dl different from 0-0x0f and 0x80-0x8f. */
testb $0x70, %dl
jz 1f
2:
movb $0x80, %dl
1:
/*
* ljmp to the next instruction because some bogus BIOSes
* jump to 07C0:0000 instead of 0000:7C00.
*/
ljmp $0, $real_start
real_start:
/* set up %ds and %ss as offset from 0 */
xorw %ax, %ax
movw %ax, %ds
movw %ax, %ss
/* set up the REAL stack */
movw $VAS_EBOOT_BOOT_MACHINE_STACK_SEG, %sp
sti /* we're safe again */
/*
* Check if we have a forced disk reference here
*/
movb boot_drive, %al
cmpb $0xff, %al
je 1f
movb %al, %dl
1:
/* save drive reference first thing! */
pushw %dx
/* print a notification message on the screen */
MSG(notification_string)
/* set %si to the disk address packet */
movw $disk_address_packet, %si
/* check if LBA is supported */
movb $0x41, %ah
movw $0x55aa, %bx
int $0x13
/*
* %dl may have been clobbered by INT 13, AH=41H.
* This happens, for example, with AST BIOS 1.04.
*/
popw %dx
pushw %dx
/* use CHS if fails */
jc LOCAL(chs_mode)
cmpw $0xaa55, %bx
jne LOCAL(chs_mode)
andw $1, %cx
jz LOCAL(chs_mode)
LOCAL(lba_mode):
xorw %ax, %ax
movw %ax, 4(%si)
incw %ax
/* set the mode to non-zero */
movb %al, -1(%si)
/* the blocks */
movw %ax, 2(%si)
/* the size and the reserved byte */
movw $0x0010, (%si)
/* the absolute address */
movl LOCAL(kernel_sector), %ebx
movl %ebx, 8(%si)
movl LOCAL(kernel_sector_high), %ebx
movl %ebx, 12(%si)
/* the segment of buffer address */
movw $VAS_EBOOT_BOOT_MACHINE_BUFFER_SEG, 6(%si)
/*
* BIOS call "INT 0x13 Function 0x42" to read sectors from disk into memory
* Call with %ah = 0x42
* %dl = drive number
* %ds:%si = segment:offset of disk address packet
* Return:
* %al = 0x0 on success; err code on failure
*/
movb $0x42, %ah
int $0x13
/* LBA read is not supported, so fallback to CHS. */
jc LOCAL(chs_mode)
movw $VAS_EBOOT_BOOT_MACHINE_BUFFER_SEG, %bx
jmp LOCAL(copy_buffer)
LOCAL(chs_mode):
/*
* Determine the hard disk geometry from the BIOS!
* We do this first, so that LS-120 IDE floppies work correctly.
*/
movb $8, %ah
int $0x13
jnc LOCAL(final_init)
popw %dx
/*
* The call failed, so maybe use the floppy probe instead.
*/
testb %dl, %dl
jnb LOCAL(floppy_probe)
/* Nope, we definitely have a hard disk, and we're screwed. */
ERR(hd_probe_error_string)
LOCAL(final_init):
/* set the mode to zero */
movzbl %dh, %eax
movb %ah, -1(%si)
/* save number of heads */
incw %ax
movl %eax, 4(%si)
movzbw %cl, %dx
shlw $2, %dx
movb %ch, %al
movb %dh, %ah
/* save number of cylinders */
incw %ax
movw %ax, 8(%si)
movzbw %dl, %ax
shrb $2, %al
/* save number of sectors */
movl %eax, (%si)
setup_sectors:
/* load logical sector start (top half) */
movl LOCAL(kernel_sector_high), %eax
orl %eax, %eax
jnz LOCAL(geometry_error)
/* load logical sector start (bottom half) */
movl LOCAL(kernel_sector), %eax
/* zero %edx */
xorl %edx, %edx
/* divide by number of sectors */
divl (%si)
/* save sector start */
movb %dl, %cl
xorw %dx, %dx /* zero %edx */
divl 4(%si) /* divide by number of heads */
/* do we need too many cylinders? */
cmpw 8(%si), %ax
jge LOCAL(geometry_error)
/* normalize sector start (1-based) */
incb %cl
/* low bits of cylinder start */
movb %al, %ch
/* high bits of cylinder start */
xorb %al, %al
shrw $2, %ax
orb %al, %cl
/* save head start */
movb %dl, %al
/* restore %dl */
popw %dx
/* head start */
movb %al, %dh
/*
* BIOS call "INT 0x13 Function 0x2" to read sectors from disk into memory
* Call with %ah = 0x2
* %al = number of sectors
* %ch = cylinder
* %cl = sector (bits 6-7 are high bits of "cylinder")
* %dh = head
* %dl = drive (0x80 for hard disk, 0x0 for floppy disk)
* %es:%bx = segment:offset of buffer
* Return:
* %al = 0x0 on success; err code on failure
*/
movw $VAS_EBOOT_BOOT_MACHINE_BUFFER_SEG, %bx
movw %bx, %es /* load %es segment with disk buffer */
xorw %bx, %bx /* %bx = 0, put it at 0 in the segment */
movw $0x0201, %ax /* function 2 */
int $0x13
jc LOCAL(read_error)
movw %es, %bx
LOCAL(copy_buffer):
/*
* We need to save %cx and %si because the startup code in
* kernel uses them without initializing them.
*/
pusha
pushw %ds
movw $0x100, %cx
movw %bx, %ds
xorw %si, %si
movw $VAS_EBOOT_BOOT_MACHINE_KERNEL_ADDR, %di
movw %si, %es
cld
rep
movsw
popw %ds
popa
/* boot kernel */
jmp *(LOCAL(kernel_address))
/* END OF MAIN LOOP */
/*
* BIOS Geometry translation error (past the end of the disk geometry!).
*/
LOCAL(geometry_error):
ERR(geometry_error_string)
/*
* Read error on the disk.
*/
LOCAL(read_error):
movw $read_error_string, %si
LOCAL(error_message):
call LOCAL(message)
LOCAL(general_error):
MSG(general_error_string)
/* go here when you need to stop the machine hard after an error condition */
/* tell the BIOS a boot failure, which may result in no effect */
int $0x18
LOCAL(stop):
jmp LOCAL(stop)
notification_string: .asciz "VAS_EBOOT "
geometry_error_string: .asciz "Geom"
hd_probe_error_string: .asciz "Hard Disk"
read_error_string: .asciz "Read"
general_error_string: .asciz " Error\r\n"
/*
* message: write the string pointed to by %si
*
* WARNING: trashes %si, %ax, and %bx
*/
/*
* Use BIOS "int 10H Function 0Eh" to write character in teletype mode
* %ah = 0xe %al = character
* %bh = page %bl = foreground color (graphics modes)
*/
1:
movw $0x0001, %bx
movb $0xe, %ah
int $0x10 /* display a byte */
LOCAL(message):
lodsb
cmpb $0, %al
jne 1b /* if not end of string, jmp to display */
ret
/*
* Windows NT breaks compatibility by embedding a magic
* number here.
*/
#ifdef HYBRID_BOOT
.org 0x1b0
LOCAL(kernel_sector):
.long 1
LOCAL(kernel_sector_high):
.long 0
#endif
.org VAS_EBOOT_BOOT_MACHINE_WINDOWS_NT_MAGIC
nt_magic:
.long 0
.word 0
/*
* This is where an MBR would go if on a hard disk. The code
* here isn't even referenced unless we're on a floppy. Kinda
* sneaky, huh?
*/
.org VAS_EBOOT_BOOT_MACHINE_PART_START
#ifndef HYBRID_BOOT
floppy
#else
scratch
#endif
.org VAS_EBOOT_BOOT_MACHINE_PART_END
/* the last 2 bytes in the sector 0 contain the signature */
.word VAS_EBOOT_BOOT_MACHINE_SIGNATURE

View File

@ -1,31 +1,31 @@
/* -*-Asm-*- */
/*
* GRUB -- GRand Unified Bootloader
* VAS_EBOOT -- GRand Unified Bootloader
* Copyright (C) 2008,2009 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* VAS_EBOOT 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,
* VAS_EBOOT 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/>.
* along with VAS_EBOOT. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/symbol.h>
#include <grub/machine/boot.h>
#include <grub/machine/kernel.h>
#include <VasEBoot/symbol.h>
#include <VasEBoot/machine/boot.h>
#include <VasEBoot/machine/kernel.h>
#include <multiboot.h>
.file "cdboot.S"
#define CODE_ADDR 0x6000
#define DATA_ADDR ((GRUB_BOOT_MACHINE_KERNEL_ADDR) + 0x200)
#define DATA_ADDR ((VAS_EBOOT_BOOT_MACHINE_KERNEL_ADDR) + 0x200)
#define CDSEC_SHIFT 11
#define CDBLK_LENG 16

View File

@ -0,0 +1,378 @@
/*
* VAS_EBOOT -- GRand Unified Bootloader
* Copyright (C) 1999,2000,2001,2002,2006,2007,2009,2010 Free Software Foundation, Inc.
*
* VAS_EBOOT 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.
*
* VAS_EBOOT 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 VAS_EBOOT. If not, see <http://www.gnu.org/licenses/>.
*/
#include <VasEBoot/symbol.h>
#include <VasEBoot/machine/boot.h>
/*
* defines for the code go here
*/
#define MSG(x) movw $x, %si; call LOCAL(message)
.file "diskboot.S"
.text
/* Tell GAS to generate 16-bit instructions so that this code works
in real mode. */
.code16
.globl start, _start
start:
_start:
/*
* _start is loaded at 0x8000 and is jumped to with
* CS:IP 0:0x8000 in kernel.
*/
/*
* we continue to use the stack for boot.img and assume that
* some registers are set to correct values. See boot.S
* for more information.
*/
/* save drive reference first thing! */
pushw %dx
/* print a notification message on the screen */
pushw %si
MSG(notification_string)
popw %si
/* this sets up for the first run through "bootloop" */
movw $LOCAL(firstlist), %di
/* save the sector number of the second sector in %ebp */
movl (%di), %ebp
/* this is the loop for reading the rest of the kernel in */
LOCAL(bootloop):
/* check the number of sectors to read */
cmpw $0, 8(%di)
/* if zero, go to the start function */
je LOCAL(bootit)
LOCAL(setup_sectors):
/* check if we use LBA or CHS */
cmpb $0, -1(%si)
/* use CHS if zero, LBA otherwise */
je LOCAL(chs_mode)
/* load logical sector start */
movl (%di), %ebx
movl 4(%di), %ecx
/* the maximum is limited to 0x7f because of Phoenix EDD */
xorl %eax, %eax
movb $0x7f, %al
/* how many do we really want to read? */
cmpw %ax, 8(%di) /* compare against total number of sectors */
/* which is greater? */
jg 1f
/* if less than, set to total */
movw 8(%di), %ax
1:
/* subtract from total */
subw %ax, 8(%di)
/* add into logical sector start */
addl %eax, (%di)
adcl $0, 4(%di)
/* set up disk address packet */
/* the size and the reserved byte */
movw $0x0010, (%si)
/* the number of sectors */
movw %ax, 2(%si)
/* the absolute address */
movl %ebx, 8(%si)
movl %ecx, 12(%si)
/* the segment of buffer address */
movw $VAS_EBOOT_BOOT_MACHINE_BUFFER_SEG, 6(%si)
/* save %ax from destruction! */
pushw %ax
/* the offset of buffer address */
movw $0, 4(%si)
/*
* BIOS call "INT 0x13 Function 0x42" to read sectors from disk into memory
* Call with %ah = 0x42
* %dl = drive number
* %ds:%si = segment:offset of disk address packet
* Return:
* %al = 0x0 on success; err code on failure
*/
movb $0x42, %ah
int $0x13
jc LOCAL(read_error)
movw $VAS_EBOOT_BOOT_MACHINE_BUFFER_SEG, %bx
jmp LOCAL(copy_buffer)
LOCAL(chs_mode):
/* load logical sector start (top half) */
movl 4(%di), %eax
orl %eax, %eax
jnz LOCAL(geometry_error)
/* load logical sector start (bottom half) */
movl (%di), %eax
/* zero %edx */
xorl %edx, %edx
/* divide by number of sectors */
divl (%si)
/* save sector start */
movb %dl, 10(%si)
xorl %edx, %edx /* zero %edx */
divl 4(%si) /* divide by number of heads */
/* save head start */
movb %dl, 11(%si)
/* save cylinder start */
movw %ax, 12(%si)
/* do we need too many cylinders? */
cmpw 8(%si), %ax
jge LOCAL(geometry_error)
/* determine the maximum sector length of this read */
movw (%si), %ax /* get number of sectors per track/head */
/* subtract sector start */
subb 10(%si), %al
/* how many do we really want to read? */
cmpw %ax, 8(%di) /* compare against total number of sectors */
/* which is greater? */
jg 2f
/* if less than, set to total */
movw 8(%di), %ax
2:
/* subtract from total */
subw %ax, 8(%di)
/* add into logical sector start */
addl %eax, (%di)
adcl $0, 4(%di)
/*
* This is the loop for taking care of BIOS geometry translation (ugh!)
*/
/* get high bits of cylinder */
movb 13(%si), %dl
shlb $6, %dl /* shift left by 6 bits */
movb 10(%si), %cl /* get sector */
incb %cl /* normalize sector (sectors go
from 1-N, not 0-(N-1) ) */
orb %dl, %cl /* composite together */
movb 12(%si), %ch /* sector+hcyl in cl, cylinder in ch */
/* restore %dx */
popw %dx
pushw %dx
/* head number */
movb 11(%si), %dh
pushw %ax /* save %ax from destruction! */
/*
* BIOS call "INT 0x13 Function 0x2" to read sectors from disk into memory
* Call with %ah = 0x2
* %al = number of sectors
* %ch = cylinder
* %cl = sector (bits 6-7 are high bits of "cylinder")
* %dh = head
* %dl = drive (0x80 for hard disk, 0x0 for floppy disk)
* %es:%bx = segment:offset of buffer
* Return:
* %al = 0x0 on success; err code on failure
*/
movw $VAS_EBOOT_BOOT_MACHINE_BUFFER_SEG, %bx
movw %bx, %es /* load %es segment with disk buffer */
xorw %bx, %bx /* %bx = 0, put it at 0 in the segment */
movb $0x2, %ah /* function 2 */
int $0x13
jc LOCAL(read_error)
/* save source segment */
movw %es, %bx
LOCAL(copy_buffer):
/* load addresses for copy from disk buffer to destination */
movw 10(%di), %es /* load destination segment */
/* restore %ax */
popw %ax
/* determine the next possible destination address (presuming
512 byte sectors!) */
shlw $5, %ax /* shift %ax five bits to the left */
addw %ax, 10(%di) /* add the corrected value to the destination
address for next time */
/* save addressing regs */
pusha
pushw %ds
/* get the copy length */
shlw $3, %ax
movw %ax, %cx
xorw %di, %di /* zero offset of destination addresses */
xorw %si, %si /* zero offset of source addresses */
movw %bx, %ds /* restore the source segment */
cld /* sets the copy direction to forward */
/* perform copy */
rep /* sets a repeat */
movsw /* this runs the actual copy */
/* restore addressing regs and print a dot with correct DS
(MSG modifies SI, which is saved, and unused AX and BX) */
popw %ds
MSG(notification_step)
popa
/* check if finished with this dataset */
cmpw $0, 8(%di)
jne LOCAL(setup_sectors)
/* update position to load from */
subw $VAS_EBOOT_BOOT_MACHINE_LIST_SIZE, %di
/* jump to bootloop */
jmp LOCAL(bootloop)
/* END OF MAIN LOOP */
LOCAL(bootit):
/* print a newline */
MSG(notification_done)
popw %dx /* this makes sure %dl is our "boot" drive */
ljmp $0, $(VAS_EBOOT_BOOT_MACHINE_KERNEL_ADDR + 0x200)
/*
* BIOS Geometry translation error (past the end of the disk geometry!).
*/
LOCAL(geometry_error):
MSG(geometry_error_string)
jmp LOCAL(general_error)
/*
* Read error on the disk.
*/
LOCAL(read_error):
MSG(read_error_string)
LOCAL(general_error):
MSG(general_error_string)
/* go here when you need to stop the machine hard after an error condition */
LOCAL(stop): jmp LOCAL(stop)
notification_string: .asciz "loading"
notification_step: .asciz "."
notification_done: .asciz "\r\n"
geometry_error_string: .asciz "Geom"
read_error_string: .asciz "Read"
general_error_string: .asciz " Error"
/*
* message: write the string pointed to by %si
*
* WARNING: trashes %si, %ax, and %bx
*/
/*
* Use BIOS "int 10H Function 0Eh" to write character in teletype mode
* %ah = 0xe %al = character
* %bh = page %bl = foreground color (graphics modes)
*/
1:
movw $0x0001, %bx
movb $0xe, %ah
int $0x10 /* display a byte */
incw %si
LOCAL(message):
movb (%si), %al
cmpb $0, %al
jne 1b /* if not end of string, jmp to display */
ret
/*
* This area is an empty space between the main body of code below which
* grows up (fixed after compilation, but between releases it may change
* in size easily), and the lists of sectors to read, which grows down
* from a fixed top location.
*/
.word 0
.word 0
.org 0x200 - VAS_EBOOT_BOOT_MACHINE_LIST_SIZE
LOCAL(firstlist): /* this label has to be before the first list entry!!! */
/* fill the first data listing with the default */
blocklist_default_start:
/* this is the sector start parameter, in logical sectors from
the start of the disk, sector 0 */
.long 2, 0
blocklist_default_len:
/* this is the number of sectors to read. VasEBoot-mkimage
will fill this up */
.word 0
blocklist_default_seg:
/* this is the segment of the starting address to load the data into */
.word (VAS_EBOOT_BOOT_MACHINE_KERNEL_SEG + 0x20)

View File

@ -1,33 +1,33 @@
/* -*-Asm-*- */
/*
* GRUB -- GRand Unified Bootloader
* VAS_EBOOT -- GRand Unified Bootloader
* Copyright (C) 2007,2008,2009 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* VAS_EBOOT 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,
* VAS_EBOOT 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/>.
* along with VAS_EBOOT. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <grub/symbol.h>
#include <grub/machine/boot.h>
#include <grub/machine/kernel.h>
#include <VasEBoot/symbol.h>
#include <VasEBoot/machine/boot.h>
#include <VasEBoot/machine/kernel.h>
#include <multiboot.h>
.file "lnxboot.S"
#define CODE_ADDR 0x6000
#define CODE_SECTORS 1
#define DATA_ADDR ((GRUB_BOOT_MACHINE_KERNEL_ADDR) + 0x200)
#define DATA_ADDR ((VAS_EBOOT_BOOT_MACHINE_KERNEL_ADDR) + 0x200)
#define BLCK_LENG 0x4000
@ -201,15 +201,15 @@ real_code_2:
1:
movl $(DATA_ADDR + 0x1000), %edi
movl %ss:(DATA_ADDR + GRUB_DECOMPRESSOR_MACHINE_COMPRESSED_SIZE), %ecx
addl $GRUB_DECOMPRESSOR_I386_PC_MAX_DECOMPRESSOR_SIZE, %ecx
movl %ss:(DATA_ADDR + VAS_EBOOT_DECOMPRESSOR_MACHINE_COMPRESSED_SIZE), %ecx
addl $VAS_EBOOT_DECOMPRESSOR_I386_PC_MAX_DECOMPRESSOR_SIZE, %ecx
2:
call LOCAL(move_memory)
movb %dh, %ss:(DATA_ADDR + GRUB_DECOMPRESSOR_I386_PC_BOOT_DEVICE + 2)
movb %dh, %ss:(DATA_ADDR + VAS_EBOOT_DECOMPRESSOR_I386_PC_BOOT_DEVICE + 2)
movb (reg_edx + 2 - start), %dh
movb %dh, %ss:(DATA_ADDR + GRUB_DECOMPRESSOR_I386_PC_BOOT_DEVICE + 1)
movb %dh, %ss:(DATA_ADDR + VAS_EBOOT_DECOMPRESSOR_I386_PC_BOOT_DEVICE + 1)
movb $0xFF, %dh

View File

@ -1,19 +1,19 @@
/*
* GRUB -- GRand Unified Bootloader
* VAS_EBOOT -- GRand Unified Bootloader
* Copyright (C) 2008 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* VAS_EBOOT 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,
* VAS_EBOOT 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/>.
* along with VAS_EBOOT. If not, see <http://www.gnu.org/licenses/>.
*/
#define FIXED_PROPS

View File

@ -1,22 +1,22 @@
/*
* GRUB -- GRand Unified Bootloader
* VAS_EBOOT -- GRand Unified Bootloader
* Copyright (C) 2000,2005,2007,2008,2009,2010 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* VAS_EBOOT 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,
* VAS_EBOOT 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/>.
* along with VAS_EBOOT. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/machine/boot.h>
#include <VasEBoot/machine/boot.h>
.file "pxeboot.S"
.text
@ -30,7 +30,7 @@ _start:
start:
/* Use drive number 0x7F for PXE */
movb $GRUB_BOOT_MACHINE_PXE_DL, %dl
movb $VAS_EBOOT_BOOT_MACHINE_PXE_DL, %dl
/* Jump to the real world */
ljmp $0, $0x8200

View File

@ -0,0 +1,369 @@
/*
* VAS_EBOOT -- GRand Unified Bootloader
* Copyright (C) 1999,2000,2001,2002,2003,2005,2006,2007,2008,2009,2011 Free Software Foundation, Inc.
*
* VAS_EBOOT 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.
*
* VAS_EBOOT 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 VAS_EBOOT. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <VasEBoot/symbol.h>
#include <VasEBoot/offsets.h>
#include <VasEBoot/machine/boot.h>
#include <VasEBoot/machine/memory.h>
#include <VasEBoot/machine/kernel.h>
#define ABS(x) ((x) - LOCAL (base) + VAS_EBOOT_BOOT_MACHINE_KERNEL_ADDR + 0x200)
.file "startup_raw.S"
.text
/* Tell GAS to generate 16-bit instructions so that this code works
in real mode. */
.code16
.globl start, _start
start:
_start:
LOCAL (base):
/*
* Guarantee that "main" is loaded at 0x0:0x8200.
*/
#ifdef __APPLE__
ljmp $0, $(ABS(LOCAL (codestart)) - 0x10000)
#else
ljmp $0, $ABS(LOCAL (codestart))
#endif
/*
* This is a special data area.
*/
.org VAS_EBOOT_DECOMPRESSOR_MACHINE_COMPRESSED_SIZE
LOCAL(compressed_size):
.long 0
.org VAS_EBOOT_DECOMPRESSOR_MACHINE_UNCOMPRESSED_SIZE
LOCAL(uncompressed_size):
.long 0
.org VAS_EBOOT_KERNEL_I386_PC_REED_SOLOMON_REDUNDANCY
reed_solomon_redundancy:
.long 0
.org VAS_EBOOT_KERNEL_I386_PC_NO_REED_SOLOMON_LENGTH
.short (LOCAL(reed_solomon_part) - _start)
/*
* This is the area for all of the special variables.
*/
.org VAS_EBOOT_DECOMPRESSOR_I386_PC_BOOT_DEVICE
LOCAL(boot_dev):
.byte 0xFF, 0xFF, 0xFF
LOCAL(boot_drive):
.byte 0x00
/* the real mode code continues... */
LOCAL (codestart):
cli /* we're not safe here! */
/* set up %ds, %ss, and %es */
xorw %ax, %ax
movw %ax, %ds
movw %ax, %ss
movw %ax, %es
/* set up the real mode/BIOS stack */
movl $VAS_EBOOT_MEMORY_MACHINE_REAL_STACK, %ebp
movl %ebp, %esp
sti /* we're safe again */
/* save the boot drive */
movb %dl, LOCAL(boot_drive)
/* reset disk system (%ah = 0) */
int $0x13
/* transition to protected mode */
calll real_to_prot
/* The ".code32" directive takes GAS out of 16-bit mode. */
.code32
cld
call VasEBoot_gate_a20
movl LOCAL(compressed_size), %edx
#ifdef __APPLE__
addl $decompressor_end, %edx
subl $(LOCAL(reed_solomon_part)), %edx
#else
addl $(LOCAL(decompressor_end) - LOCAL(reed_solomon_part)), %edx
#endif
movl reed_solomon_redundancy, %ecx
leal LOCAL(reed_solomon_part), %eax
cld
call EXT_C (VasEBoot_reed_solomon_recover)
jmp post_reed_solomon
#include "../../../kern/i386/realmode.S"
/*
*
* This is a workaround for clang adding a section containing only .addrsig
* Since clang itself is unable to assemble this pseudo-opcode, just replace
* it with .text
*
*/
#define addrsig text
#include <rs_decoder.h>
#undef addrsig
.text
/*
* VasEBoot_gate_a20(void)
*
* Gate address-line 20 for high memory.
*
* This routine is probably overconservative in what it does, but so what?
*
* It also eats any keystrokes in the keyboard buffer. :-(
*/
VasEBoot_gate_a20:
gate_a20_test_current_state:
/* first of all, test if already in a good state */
call gate_a20_check_state
testb %al, %al
jnz gate_a20_try_bios
ret
gate_a20_try_bios:
/* second, try a BIOS call */
pushl %ebp
call prot_to_real
.code16
movw $0x2401, %ax
int $0x15
calll real_to_prot
.code32
popl %ebp
call gate_a20_check_state
testb %al, %al
jnz gate_a20_try_system_control_port_a
ret
gate_a20_try_system_control_port_a:
/*
* In macbook, the keyboard test would hang the machine, so we move
* this forward.
*/
/* fourth, try the system control port A */
inb $0x92
andb $(~0x03), %al
orb $0x02, %al
outb $0x92
call gate_a20_check_state
testb %al, %al
jnz gate_a20_try_keyboard_controller
ret
gate_a20_flush_keyboard_buffer:
inb $0x64
andb $0x02, %al
jnz gate_a20_flush_keyboard_buffer
2:
inb $0x64
andb $0x01, %al
jz 3f
inb $0x60
jmp 2b
3:
ret
gate_a20_try_keyboard_controller:
/* third, try the keyboard controller */
call gate_a20_flush_keyboard_buffer
movb $0xd1, %al
outb $0x64
4:
inb $0x64
andb $0x02, %al
jnz 4b
movb $0xdf, %al
outb $0x60
call gate_a20_flush_keyboard_buffer
/* output a dummy command (USB keyboard hack) */
movb $0xff, %al
outb $0x64
call gate_a20_flush_keyboard_buffer
call gate_a20_check_state
testb %al, %al
/* everything failed, so restart from the beginning */
jnz gate_a20_try_bios
ret
gate_a20_check_state:
/* iterate the checking for a while */
movl $100, %ecx
1:
call 3f
testb %al, %al
jz 2f
loop 1b
2:
ret
3:
pushl %ebx
pushl %ecx
xorl %eax, %eax
/* compare the byte at 0x8000 with that at 0x108000 */
movl $VAS_EBOOT_BOOT_MACHINE_KERNEL_ADDR, %ebx
pushl %ebx
/* save the original byte in CL */
movb (%ebx), %cl
/* store the value at 0x108000 in AL */
addl $0x100000, %ebx
movb (%ebx), %al
/* try to set one less value at 0x8000 */
popl %ebx
movb %al, %ch
decb %ch
movb %ch, (%ebx)
/* serialize */
outb %al, $0x80
outb %al, $0x80
/* obtain the value at 0x108000 in CH */
pushl %ebx
addl $0x100000, %ebx
movb (%ebx), %ch
/* this result is 0 if A20 is on or 1 if it is off */
subb %ch, %al
/* restore the original */
popl %ebx
movb %cl, (%ebx)
popl %ecx
popl %ebx
ret
LOCAL(reed_solomon_part):
/*
* Support for booting VAS_EBOOT from a Multiboot boot loader (e.g. VAS_EBOOT itself).
* This uses the a.out kludge to load raw binary to the area starting at 1MB,
* and relocates itself after loaded.
*/
.p2align 2 /* force 4-byte alignment */
multiboot_header:
/* magic */
.long 0x1BADB002
/* flags */
.long (1 << 16)
/* checksum */
.long -0x1BADB002 - (1 << 16)
/* header addr */
.long multiboot_header - _start + 0x100000 + 0x200
/* load addr */
.long 0x100000
/* load end addr */
.long 0
/* bss end addr */
.long 0
/* entry addr */
.long multiboot_entry - _start + 0x100000 + 0x200
multiboot_entry:
.code32
/* obtain the boot device */
movl 12(%ebx), %edx
movl $VAS_EBOOT_MEMORY_MACHINE_PROT_STACK, %ebp
movl %ebp, %esp
/* relocate the code */
#ifdef __APPLE__
LOCAL(compressed_size_offset) = LOCAL(compressed_size) - LOCAL(base)
movl $0x200, %ecx
addl $decompressor_end, %ecx
subl $LOCAL(base), %ecx
addl LOCAL(compressed_size_offset) + 0x100000 + 0x200, %ecx
#else
movl $(LOCAL(decompressor_end) - _start + 0x200), %ecx
addl LOCAL(compressed_size) - _start + 0x100000 + 0x200, %ecx
#endif
movl $0x100000, %esi
movl $VAS_EBOOT_BOOT_MACHINE_KERNEL_ADDR, %edi
cld
rep
movsb
/* jump to the real address */
movl $multiboot_trampoline, %eax
jmp *%eax
multiboot_trampoline:
/* fill the boot information */
movl %edx, LOCAL(boot_dev)
shrl $24, %edx
/* enter the usual booting */
call prot_to_real
.code16
jmp LOCAL (codestart)
.code32
post_reed_solomon:
#ifdef ENABLE_LZMA
movl $VAS_EBOOT_MEMORY_MACHINE_DECOMPRESSION_ADDR, %edi
#ifdef __APPLE__
movl $decompressor_end, %esi
#else
movl $LOCAL(decompressor_end), %esi
#endif
pushl %edi
movl LOCAL (uncompressed_size), %ecx
leal (%edi, %ecx), %ebx
/* Don't remove this push: it's an argument. */
push %ecx
call _LzmaDecodeA
pop %ecx
/* _LzmaDecodeA clears DF, so no need to run cld */
popl %esi
#endif
movl LOCAL(boot_dev), %edx
movl $prot_to_real, %edi
movl $real_to_prot, %ecx
movl $LOCAL(realidt), %eax
jmp *%esi
#ifdef ENABLE_LZMA
#include "lzma_decode.S"
#endif
.p2align 4
#ifdef __APPLE__
.zerofill __DATA, __aa_before_bss, decompressor_end, 10, 0
#else
.bss
LOCAL(decompressor_end):
#endif

View File

@ -0,0 +1,74 @@
/*
* VAS_EBOOT -- GRand Unified Bootloader
* Copyright (C) 1999,2000,2001,2002,2003,2005,2006,2007,2008,2009 Free Software Foundation, Inc.
*
* VAS_EBOOT 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.
*
* VAS_EBOOT 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 VAS_EBOOT. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <VasEBoot/symbol.h>
#include <VasEBoot/machine/memory.h>
#include <VasEBoot/machine/boot.h>
#include <VasEBoot/machine/kernel.h>
.text
.code16
.globl _start
_start:
/* Disable interrupts. */
cli
jmp 1f
.org VAS_EBOOT_BOOT_I386_QEMU_CORE_ENTRY_ADDR
VARIABLE(VasEBoot_core_entry_addr)
.long 0
1:
/* Set up %ds, %ss, and %es. */
xorw %ax, %ax
movw %ax, %ds
movw %ax, %ss
movw %ax, %es
/* Set up the real mode stack. */
movl $VAS_EBOOT_MEMORY_MACHINE_REAL_STACK, %esp
/* Transition to protected mode. We use pushl to force generation
of a flat return address. */
pushl $1f
jmp real_to_prot
.code32
1:
/* Ensure A20 is enabled. We're in qemu, so control port A works
and there is no need to wait since there is no real logic, it's
all emulated. */
inb $0x92
andb $(~0x03), %al
orb $0x02, %al
outb $0x92
movl EXT_C(VasEBoot_core_entry_addr), %edx
jmp *%edx
#include "../../../kern/i386/realmode.S"
/* Intel, in its infinite wisdom, decided to put the i8086 entry point
*right here* and this is why we need this kludge. */
.org VAS_EBOOT_BOOT_MACHINE_SIZE - 16
.code16
jmp _start
.org VAS_EBOOT_BOOT_MACHINE_SIZE

View File

@ -0,0 +1,756 @@
/*
* VAS_EBOOT -- GRand Unified Bootloader
* Copyright (C) 2000,2001,2002,2003,2004,2005,2007,2008,2009,2010 Free Software Foundation, Inc.
*
* VAS_EBOOT 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.
*
* VAS_EBOOT 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 VAS_EBOOT. If not, see <http://www.gnu.org/licenses/>.
*/
#include <VasEBoot/mips/loongson/serial.h>
#include <VasEBoot/mips/loongson/pci.h>
#include <VasEBoot/mips/loongson.h>
#include <VasEBoot/pci.h>
#include <VasEBoot/machine/serial.h>
#include <VasEBoot/machine/kernel.h>
#include <VasEBoot/ns8250.h>
#include <VasEBoot/cs5536.h>
#include <VasEBoot/smbus.h>
#ifndef FULOONG2F
#include <VasEBoot/vgaregs.h>
#define VAS_EBOOT_SM712_REG_BASE 0x700000
#define VAS_EBOOT_SM712_PCIID 0x0712126f
#endif
#ifdef FULOONG2F
#define VAS_EBOOT_MACHINE_SERIAL_PORT VAS_EBOOT_MACHINE_SERIAL_PORT2
#define VAS_EBOOT_MACHINE_SERIAL_DIVISOR_115200 VAS_EBOOT_MACHINE_SERIAL_PORT2_DIVISOR_115200
#else
#define VAS_EBOOT_MACHINE_SERIAL_PORT VAS_EBOOT_MACHINE_SERIAL_PORT0
#define VAS_EBOOT_MACHINE_SERIAL_DIVISOR_115200 VAS_EBOOT_MACHINE_SERIAL_PORT0_DIVISOR_115200
#endif
.set noreorder
.set noat
.set nomacro
.set mips3
.global start,_start,__start
start:
_start:
__start:
/* Put serial init as soon as possible. But on Fuloong2f serial is past
Geode, so on Fuloong2f we need Geode first.
*/
#ifndef FULOONG2F
bal serial_hw_init
nop
#endif
/* Find CS5536 controller. */
/* $t4 chooses device in priority encoding. */
/* Resulting value is kept in VAS_EBOOT_MACHINE_PCI_CONF_CTRL_REG.
This way we don't need to sacrifice a register for it. */
retry_cs5536:
/* We have only one bus (0). Function is 0. */
lui $t0, %hi(VAS_EBOOT_MACHINE_PCI_CONF_CTRL_REG_ADDR_2F)
lui $t1, %hi(VAS_EBOOT_MACHINE_PCI_CONFSPACE_2F)
lui $t3, %hi(VAS_EBOOT_CS5536_PCIID)
addiu $t3, $t3, %lo(VAS_EBOOT_CS5536_PCIID)
ori $t4, $zero, 1
1:
andi $t4, $t4, ((1 << VAS_EBOOT_PCI_NUM_DEVICES_2F) - 1)
/* In case of failure try again. CS5536 may be slow to come up. */
beql $t4, $zero, retry_cs5536
nop
sw $t4, %lo(VAS_EBOOT_MACHINE_PCI_CONF_CTRL_REG_ADDR_2F) ($t0)
lw $t2, (%lo(VAS_EBOOT_MACHINE_PCI_CONFSPACE_2F) + VAS_EBOOT_PCI_REG_PCI_ID) ($t1)
bnel $t2, $t3, 1b
sll $t4, $t4, 1
#ifndef FULOONG2F
lui $a0, %hi(cs5536_found)
bal message
addiu $a0, $a0, %lo(cs5536_found)
bal printhex
move $a0, $t4
#endif
lui $t0, %hi(VAS_EBOOT_MACHINE_PCI_CONFSPACE_2F)
li $t1, VAS_EBOOT_CS5536_MSR_MAILBOX_CONFIG_ENABLED
sw $t1, (%lo(VAS_EBOOT_MACHINE_PCI_CONFSPACE_2F) + VAS_EBOOT_CS5536_MSR_MAILBOX_CONFIG) ($t0)
/* Set GPIO LBAR. */
lui $a0, %hi(VAS_EBOOT_CS5536_MSR_GPIO_BAR)
addiu $a0, $a0, %lo(VAS_EBOOT_CS5536_MSR_GPIO_BAR)
ori $a1, $zero, VAS_EBOOT_CS5536_LBAR_GPIO
/* Set mask to 0xf and enabled bit to 1. */
bal wrmsr
ori $a2, $zero, ((VAS_EBOOT_CS5536_LBAR_MASK_MASK \
| VAS_EBOOT_CS5536_LBAR_ENABLE) >> 32)
bal gpio_init
nop
#ifdef FULOONG2F
bal serial_hw_init
nop
#endif
/* Initialise SMBus controller. */
/* Set SMBUS LBAR. */
lui $a0, %hi(VAS_EBOOT_CS5536_MSR_SMB_BAR)
addiu $a0, $a0, %lo(VAS_EBOOT_CS5536_MSR_SMB_BAR)
ori $a1, $zero, VAS_EBOOT_CS5536_LBAR_SMBUS
/* Set mask to 0xf and enabled bit to 1. */
bal wrmsr
ori $a2, $zero, ((VAS_EBOOT_CS5536_LBAR_MASK_MASK \
| VAS_EBOOT_CS5536_LBAR_ENABLE) >> 32)
lui $a0, %hi(smbus_enabled)
bal message
addiu $a0, $a0, %lo(smbus_enabled)
lui $t0, %hi(VAS_EBOOT_MACHINE_PCI_IO_BASE_2F + VAS_EBOOT_CS5536_LBAR_SMBUS)
/* Disable SMB. */
sb $zero, %lo(VAS_EBOOT_MACHINE_PCI_IO_BASE_2F + VAS_EBOOT_CS5536_LBAR_SMBUS + VAS_EBOOT_CS5536_SMB_REG_CTRL2) ($t0)
/* Disable interrupts. */
sb $zero, %lo(VAS_EBOOT_MACHINE_PCI_IO_BASE_2F + VAS_EBOOT_CS5536_LBAR_SMBUS + VAS_EBOOT_CS5536_SMB_REG_CTRL1) ($t0)
/* Set as master. */
sb $zero, %lo(VAS_EBOOT_MACHINE_PCI_IO_BASE_2F + VAS_EBOOT_CS5536_LBAR_SMBUS + VAS_EBOOT_CS5536_SMB_REG_ADDR) ($t0)
/* Launch SMBus controller at slowest speed possible. */
ori $t1, $zero, 0xff
sb $t1, %lo(VAS_EBOOT_MACHINE_PCI_IO_BASE_2F + VAS_EBOOT_CS5536_LBAR_SMBUS + VAS_EBOOT_CS5536_SMB_REG_CTRL3) ($t0)
sb $t1, %lo(VAS_EBOOT_MACHINE_PCI_IO_BASE_2F + VAS_EBOOT_CS5536_LBAR_SMBUS + VAS_EBOOT_CS5536_SMB_REG_CTRL2) ($t0)
/* Yeeloong and Fuloong2f have only one memory slot. */
/* Output first byte on serial for debugging. */
ori $a1, $zero, VAS_EBOOT_SMB_RAM_START_ADDR
bal read_spd
move $a0, $zero
bal printhex
move $a0, $v0
bal read_spd
ori $a0, $zero, VAS_EBOOT_SMBUS_SPD_MEMORY_TYPE_ADDR
ori $t0, $zero, VAS_EBOOT_SMBUS_SPD_MEMORY_TYPE_DDR2
lui $a0, %hi(unimplemented_memory_type)
bne $t0, $v0, fatal
addiu $a0, $a0, %lo(unimplemented_memory_type)
/* And here is our goal: DDR2 controller initialisation. */
lui $t0, %hi(VAS_EBOOT_CPU_LOONGSON_CORECFG)
ld $t1, %lo(VAS_EBOOT_CPU_LOONGSON_CORECFG) ($t0)
/* Use addiu for sign-extension. */
addiu $t2, $zero, ~(VAS_EBOOT_CPU_LOONGSON_CORECFG_DISABLE_DDR2_SPACE|VAS_EBOOT_CPU_LOONGSON_CORECFG_BUFFER_CPU)
and $t1, $t1, $t2
sd $t1, %lo (VAS_EBOOT_CPU_LOONGSON_CORECFG) ($t0)
b continue
.org VAS_EBOOT_CPU_LOONGSON_FLASH_TLB_REFILL - VAS_EBOOT_CPU_LOONGSON_FLASH_START
tlb_refill:
mfc0 $s1, VAS_EBOOT_CPU_LOONGSON_COP0_EPC
mfc0 $s2, VAS_EBOOT_CPU_LOONGSON_COP0_BADVADDR
move $s3, $ra
lui $a0, %hi(epc)
bal message
addiu $a0, $a0, %lo(epc)
bal printhex
move $a0, $s1
lui $a0, %hi(badvaddr)
bal message
addiu $a0, $a0, %lo(badvaddr)
bal printhex
move $a0, $s2
lui $a0, %hi(return_msg)
bal message
addiu $a0, $a0, %lo(return_msg)
bal printhex
move $a0, $s3
lui $a0, %hi(newline)
bal message
addiu $a0, $a0, %lo(newline)
lui $a0, %hi(unhandled_tlb_refill)
b fatal
addiu $a0, $a0, %lo(unhandled_tlb_refill)
.org VAS_EBOOT_CPU_LOONGSON_FLASH_CACHE_ERROR - VAS_EBOOT_CPU_LOONGSON_FLASH_START
cache_error:
lui $a0, %hi(unhandled_cache_error)
b fatal
addiu $a0, $a0, %lo(unhandled_cache_error)
.org VAS_EBOOT_CPU_LOONGSON_FLASH_OTHER_EXCEPTION - VAS_EBOOT_CPU_LOONGSON_FLASH_START
other_exception:
mfc0 $s0, VAS_EBOOT_CPU_LOONGSON_COP0_CAUSE
mfc0 $s1, VAS_EBOOT_CPU_LOONGSON_COP0_EPC
mfc0 $s2, VAS_EBOOT_CPU_LOONGSON_COP0_BADVADDR
lui $a0, %hi(cause)
bal message
addiu $a0, $a0, %lo(cause)
bal printhex
move $a0, $s0
lui $a0, %hi(epc)
bal message
addiu $a0, $a0, %lo(epc)
bal printhex
move $a0, $s1
lui $a0, %hi(badvaddr)
bal message
addiu $a0, $a0, %lo(badvaddr)
bal printhex
move $a0, $s2
lui $a0, %hi(newline)
bal message
addiu $a0, $a0, %lo(newline)
lui $a0, %hi(unhandled_exception)
b fatal
addiu $a0, $a0, %lo(unhandled_exception)
gpio_init:
lui $t0, %hi(VAS_EBOOT_MACHINE_PCI_IO_BASE_2F + VAS_EBOOT_CS5536_LBAR_GPIO)
addiu $t0, $t0, %lo(VAS_EBOOT_MACHINE_PCI_IO_BASE_2F + VAS_EBOOT_CS5536_LBAR_GPIO)
lui $t1, %hi (gpio_dump)
addiu $t1, $t1, %lo (gpio_dump)
1:
lw $t2, 0($t1)
sw $t2, 0($t0)
addiu $t0, $t0, 4
addiu $t1, $t1, 4
lui $t2, %hi (gpio_dump_end)
addiu $t2, $t2, %lo (gpio_dump_end)
bne $t1, $t2, 1b
nop
jr $ra
nop
/* Same as similarly named C function but in asm since
we need it early. */
/* In: none. Out: none. Clobbered: $t0, $t1, $t2, $a0, $a1, $a2. */
serial_hw_init:
move $t2, $ra
#ifdef FULOONG2F
lui $a0, %hi(VAS_EBOOT_CS5536_MSR_DIVIL_LEG_IO)
addiu $a0, $a0, %lo(VAS_EBOOT_CS5536_MSR_DIVIL_LEG_IO)
lui $a1, %hi (VAS_EBOOT_CS5536_MSR_DIVIL_LEG_IO_UART2_COM3 \
| VAS_EBOOT_CS5536_MSR_DIVIL_LEG_IO_F_REMAP \
| VAS_EBOOT_CS5536_MSR_DIVIL_LEG_IO_MODE_X86 \
| VAS_EBOOT_CS5536_MSR_DIVIL_LEG_IO_UART1_COM1)
ori $a1, $a1, (VAS_EBOOT_CS5536_MSR_DIVIL_LEG_IO_RTC_ENABLE0 \
| VAS_EBOOT_CS5536_MSR_DIVIL_LEG_IO_RTC_ENABLE1)
bal wrmsr
move $a2, $zero
lui $a0, %hi(VAS_EBOOT_CS5536_MSR_DIVIL_UART1_CONF)
addiu $a0, $a0, %lo(VAS_EBOOT_CS5536_MSR_DIVIL_UART1_CONF)
li $a1, 2
bal wrmsr
move $a2, $zero
lui $a0, %hi(VAS_EBOOT_CS5536_MSR_DIVIL_UART2_CONF)
addiu $a0, $a0, %lo(VAS_EBOOT_CS5536_MSR_DIVIL_UART2_CONF)
li $a1, 2
bal wrmsr
move $a2, $zero
#endif
lui $t0, %hi (VAS_EBOOT_MACHINE_SERIAL_PORT)
/* Turn off the interrupt. */
sb $zero, (%lo (VAS_EBOOT_MACHINE_SERIAL_PORT) + UART_IER)($t0)
/* Set DLAB. */
ori $t1, $zero, UART_DLAB
sb $t1, (%lo (VAS_EBOOT_MACHINE_SERIAL_PORT) + UART_LCR)($t0)
/* Set the baud rate 115200. */
ori $t1, $zero, VAS_EBOOT_MACHINE_SERIAL_DIVISOR_115200
sb $t1, (%lo (VAS_EBOOT_MACHINE_SERIAL_PORT) + UART_DLL)($t0)
sb $zero, (%lo (VAS_EBOOT_MACHINE_SERIAL_PORT) + UART_DLH)($t0)
/* Set the line status. */
ori $t1, $zero, (UART_NO_PARITY | UART_8BITS_WORD | UART_1_STOP_BIT)
sb $t1, (%lo (VAS_EBOOT_MACHINE_SERIAL_PORT) + UART_LCR)($t0)
/* Enable the FIFO. */
ori $t1, $zero, UART_ENABLE_FIFO_TRIGGER1
sb $t1, (%lo (VAS_EBOOT_MACHINE_SERIAL_PORT) + UART_FCR)($t0)
/* Turn on DTR and RTS. */
ori $t1, $zero, UART_ENABLE_DTRRTS
sb $t1, (%lo (VAS_EBOOT_MACHINE_SERIAL_PORT) + UART_MCR)($t0)
/* Let message return to original caller. */
lui $a0, %hi(notification_string)
addiu $a0, $a0, %lo(notification_string)
move $ra, $t2
/* Print message on serial console. */
/* In: $a0 = asciiz message. Out: none. Clobbered: $t0, $t1, $a0. */
message:
lui $t0, %hi (VAS_EBOOT_MACHINE_SERIAL_PORT)
1:
lb $t1, (%lo (VAS_EBOOT_MACHINE_SERIAL_PORT) + UART_LSR)($t0)
andi $t1, $t1, UART_EMPTY_TRANSMITTER
beq $t1, $zero, 1b
nop
lb $t1, 0($a0)
sb $t1, (%lo (VAS_EBOOT_MACHINE_SERIAL_PORT) + UART_TX)($t0)
bne $t1, $zero, 1b
addiu $a0, $a0, 1
jr $ra
nop
/* Print 32-bit hexadecimal on serial.
In: $a0. Out: None. Clobbered: $a0, $t0, $t1, $t2
*/
printhex:
lui $t0, %hi (VAS_EBOOT_MACHINE_SERIAL_PORT)
ori $t2, $zero, 8
1:
lb $t1, (%lo (VAS_EBOOT_MACHINE_SERIAL_PORT) + UART_LSR)($t0)
andi $t1, $t1, UART_EMPTY_TRANSMITTER
beq $t1, $zero, 1b
nop
srl $t1, $a0, 28
addiu $t1, $t1, -10
bltz $t1, 2f
sll $a0, $a0, 4
addiu $t1, $t1, 'A'-10-'0'
2: addiu $t1, $t1, '0'+10
sb $t1, (%lo (VAS_EBOOT_MACHINE_SERIAL_PORT) + UART_TX)($t0)
addiu $t2, $t2, -1
bne $t2, $zero, 1b
nop
jr $ra
nop
fatal:
bal message
nop
self:
b self
nop
/* Write CS5536 MSR.
In: $a0 address, $a1 lower word, $a2 upper word.
Out: None
Clobbered: $t0
*/
wrmsr:
lui $t0, %hi(VAS_EBOOT_MACHINE_PCI_CONFSPACE_2F)
sw $a0, (%lo(VAS_EBOOT_MACHINE_PCI_CONFSPACE_2F) + VAS_EBOOT_CS5536_MSR_MAILBOX_ADDR) ($t0)
sw $a1, (%lo(VAS_EBOOT_MACHINE_PCI_CONFSPACE_2F) + VAS_EBOOT_CS5536_MSR_MAILBOX_DATA0) ($t0)
jr $ra
sw $a2, (%lo(VAS_EBOOT_MACHINE_PCI_CONFSPACE_2F) + VAS_EBOOT_CS5536_MSR_MAILBOX_DATA1) ($t0)
/* Wait for SMBus data or empty transmitter. */
/* In: $a0 = exception handler. Out: none. Clobbered: $t0, $t1 */
smbus_wait:
1:
lui $t0, %hi(VAS_EBOOT_CS5536_LBAR_SMBUS + VAS_EBOOT_CS5536_SMB_REG_STATUS + VAS_EBOOT_MACHINE_PCI_IO_BASE_2F)
lb $t0, %lo(VAS_EBOOT_CS5536_LBAR_SMBUS + VAS_EBOOT_CS5536_SMB_REG_STATUS + VAS_EBOOT_MACHINE_PCI_IO_BASE_2F) ($t0)
andi $t1, $t0, VAS_EBOOT_CS5536_SMB_REG_STATUS_SDAST
bne $t1, $zero, return
nop
andi $t1, $t0, (VAS_EBOOT_CS5536_SMB_REG_STATUS_BER | VAS_EBOOT_CS5536_SMB_REG_STATUS_NACK)
beq $t1, $zero, 1b
nop
jr $a0
nop
return:
jr $ra
nop
/* Read SPD byte. In: $a0 byte, $a1 device. Out: $v0 read byte (0x100 on failure).
Clobbered: $t0, $t1, $t2, $t3, $a0. */
read_spd:
move $t2, $a0
move $t3, $ra
lui $a0, %hi(read_spd_fail)
addiu $a0, $a0, %lo(read_spd_fail)
/* Send START. */
lui $t0, %hi(VAS_EBOOT_CS5536_LBAR_SMBUS + VAS_EBOOT_CS5536_SMB_REG_CTRL1 + VAS_EBOOT_MACHINE_PCI_IO_BASE_2F)
lb $t1, %lo(VAS_EBOOT_CS5536_LBAR_SMBUS + VAS_EBOOT_CS5536_SMB_REG_CTRL1 + VAS_EBOOT_MACHINE_PCI_IO_BASE_2F) ($t0)
ori $t1, $t1, VAS_EBOOT_CS5536_SMB_REG_CTRL1_START
bal smbus_wait
sb $t1, %lo(VAS_EBOOT_CS5536_LBAR_SMBUS + VAS_EBOOT_CS5536_SMB_REG_CTRL1 + VAS_EBOOT_MACHINE_PCI_IO_BASE_2F) ($t0)
/* Send device address. */
lui $t0, %hi(VAS_EBOOT_CS5536_LBAR_SMBUS + VAS_EBOOT_CS5536_SMB_REG_DATA + VAS_EBOOT_MACHINE_PCI_IO_BASE_2F)
sll $t1, $a1, 1
bal smbus_wait
sb $t1, %lo(VAS_EBOOT_CS5536_LBAR_SMBUS + VAS_EBOOT_CS5536_SMB_REG_DATA + VAS_EBOOT_MACHINE_PCI_IO_BASE_2F) ($t0)
/* Send ACK. */
lui $t0, %hi(VAS_EBOOT_CS5536_LBAR_SMBUS + VAS_EBOOT_CS5536_SMB_REG_CTRL1 + VAS_EBOOT_MACHINE_PCI_IO_BASE_2F)
lb $t1, %lo(VAS_EBOOT_CS5536_LBAR_SMBUS + VAS_EBOOT_CS5536_SMB_REG_CTRL1 + VAS_EBOOT_MACHINE_PCI_IO_BASE_2F) ($t0)
ori $t1, $t1, VAS_EBOOT_CS5536_SMB_REG_CTRL1_ACK
sb $t1, %lo(VAS_EBOOT_CS5536_LBAR_SMBUS + VAS_EBOOT_CS5536_SMB_REG_CTRL1 + VAS_EBOOT_MACHINE_PCI_IO_BASE_2F) ($t0)
/* Send byte address. */
lui $t0, %hi(VAS_EBOOT_CS5536_LBAR_SMBUS + VAS_EBOOT_CS5536_SMB_REG_DATA + VAS_EBOOT_MACHINE_PCI_IO_BASE_2F)
bal smbus_wait
sb $t2, %lo(VAS_EBOOT_CS5536_LBAR_SMBUS + VAS_EBOOT_CS5536_SMB_REG_DATA + VAS_EBOOT_MACHINE_PCI_IO_BASE_2F) ($t0)
/* Send START. */
lui $t0, %hi(VAS_EBOOT_CS5536_LBAR_SMBUS + VAS_EBOOT_CS5536_SMB_REG_CTRL1 + VAS_EBOOT_MACHINE_PCI_IO_BASE_2F)
lb $t1, %lo(VAS_EBOOT_CS5536_LBAR_SMBUS + VAS_EBOOT_CS5536_SMB_REG_CTRL1 + VAS_EBOOT_MACHINE_PCI_IO_BASE_2F) ($t0)
ori $t1, $t1, VAS_EBOOT_CS5536_SMB_REG_CTRL1_START
bal smbus_wait
sb $t1, %lo(VAS_EBOOT_CS5536_LBAR_SMBUS + VAS_EBOOT_CS5536_SMB_REG_CTRL1 + VAS_EBOOT_MACHINE_PCI_IO_BASE_2F) ($t0)
/* Send device address. */
lui $t0, %hi(VAS_EBOOT_CS5536_LBAR_SMBUS + VAS_EBOOT_CS5536_SMB_REG_DATA + VAS_EBOOT_MACHINE_PCI_IO_BASE_2F)
sll $t1, $a1, 1
ori $t1, $t1, 1
bal smbus_wait
sb $t1, %lo(VAS_EBOOT_CS5536_LBAR_SMBUS + VAS_EBOOT_CS5536_SMB_REG_DATA + VAS_EBOOT_MACHINE_PCI_IO_BASE_2F) ($t0)
/* Send STOP. */
lui $t0, %hi(VAS_EBOOT_CS5536_LBAR_SMBUS + VAS_EBOOT_CS5536_SMB_REG_CTRL1 + VAS_EBOOT_MACHINE_PCI_IO_BASE_2F)
lb $t1, %lo(VAS_EBOOT_CS5536_LBAR_SMBUS + VAS_EBOOT_CS5536_SMB_REG_CTRL1 + VAS_EBOOT_MACHINE_PCI_IO_BASE_2F) ($t0)
ori $t1, $t1, VAS_EBOOT_CS5536_SMB_REG_CTRL1_STOP
bal smbus_wait
sb $t1, %lo(VAS_EBOOT_CS5536_LBAR_SMBUS + VAS_EBOOT_CS5536_SMB_REG_CTRL1 + VAS_EBOOT_MACHINE_PCI_IO_BASE_2F) ($t0)
lui $t0, %hi(VAS_EBOOT_CS5536_LBAR_SMBUS + VAS_EBOOT_CS5536_SMB_REG_DATA + VAS_EBOOT_MACHINE_PCI_IO_BASE_2F)
lb $v0, %lo(VAS_EBOOT_CS5536_LBAR_SMBUS + VAS_EBOOT_CS5536_SMB_REG_DATA + VAS_EBOOT_MACHINE_PCI_IO_BASE_2F) ($t0)
jr $t3
andi $v0, $v0, 0xff
read_spd_fail:
jr $t3
ori $v0, $v0, 0x100
notification_string: .asciz "VAS_EBOOT "
cs5536_found: .asciz "CS5536 at "
sm_failed: .asciz "SM transaction failed.\n\r"
unhandled_tlb_refill: .asciz "Unhandled TLB refill.\n\r"
unhandled_cache_error: .asciz "Unhandled cache error.\n\r"
unhandled_exception: .asciz "Unhandled exception.\n\r"
smbus_enabled: .asciz "SMBus controller enabled.\n\r"
unimplemented_memory_type: .asciz "non-DDR2 memory isn't supported.\n\r"
no_cas_latency: .asciz "Couldn't determine CAS latency.\n\r"
cause: .asciz "Cause: "
epc: .asciz "\n\rEPC: "
badvaddr: .asciz "\n\rBadVaddr: "
newline: .asciz "\n\r"
return_msg: .asciz "\n\rReturn address: "
caches_enabled: .asciz "Caches enabled\n\r"
.p2align 3
regdump:
.quad 0x0100010000000101 /* 0 */
.quad 0x0100010100000000 /* 2 */
.quad 0x0101000001000000 /* 3 */
.quad 0x0100020200010101 /* 4 */
.quad 0x0a04030603050203 /* 6 */
.quad 0x0f0e040000010a0b /* 7 */
#ifdef FULOONG2F
.quad 0x0000000100000001 /* 8 */
#else
.quad 0x0000010200000102 /* 8 */
#endif
.quad 0x0000060c00000000 /* 9 */
.quad 0x2323233f3f1f0200 /* a */
.quad 0x5f7f232323232323 /* b */
.quad 0x002a3c0615000000 /* c */
.quad 0x002a002a002a002a /* d */
.quad 0x002a002a002a002a /* e */
#ifdef FULOONG2F
.quad 0x00b40020005b0004 /* f */
#else
.quad 0x00b40020006d0004 /* f */
#endif
.quad 0x070007ff00000087 /* 10 */
.quad 0x000000000016101f /* 11 */
.quad 0x001c000000000000 /* 12 */
.quad 0x28e1000200c8006b /* 13 */
.quad 0x0000204200c8002f /* 14 */
.quad 0x0000000000030d40 /* 15 */
.quad 0 /* 16 */
.quad 0 /* 17 */
.quad 0 /* 18 */
.quad 0 /* 19 */
.quad 0 /* 1a */
.quad 0 /* 1b */
.quad 0 /* 1c */
/* Dump of GPIO connections. FIXME: Remove useless and macroify. */
gpio_dump:
#ifdef FULOONG2F
.long 0xffff0000, 0x2eefd110, 0xffff0000, 0xffff0000
.long 0x2eefd110, 0xffff0000, 0x1000efff, 0xefff1000
.long 0x3df3c20c, 0xffff0000, 0xffff0000, 0xffff0000
.long 0x7df3820c, 0x3df3c20c, 0xffff0000, 0x00000000
.long 0xffff0000, 0xffff0000, 0x3de3c21c, 0x3d83c27c
.long 0x00000000, 0x00000000, 0x00000000, 0x00000000
.long 0x00000000, 0x00000000, 0x00000000, 0x00000000
.long 0x00000000, 0x00000000, 0x00000000, 0x00000000
.long 0xffff0000, 0xffff0000, 0xffff0000, 0xffff0000
.long 0xffff0000, 0xffff0000, 0x0000ffff, 0xffff0000
.long 0xefff1000, 0xffff0000, 0xffff0000, 0xffff0000
.long 0xefff1000, 0xefff1000, 0xffff0000, 0x00000000
.long 0xffff0000, 0xffff0000, 0xefff1000, 0xefff1000
.long 0x00000000, 0x00000000, 0x00000000, 0x00000000
.long 0x00000000, 0x00000000, 0x00000000, 0x00000000
.long 0x00000000, 0x00000000, 0x00000000, 0x00000000
#else
.long 0xffff0000, 0x2ffdd002, 0xffff0000, 0xffff0000
.long 0x2fffd000, 0xffff0000, 0x1000efff, 0xefff1000
.long 0x3ffbc004, 0xffff0000, 0xffff0000, 0xffff0000
.long 0x3ffbc004, 0x3ffbc004, 0xffff0000, 0x00000000
.long 0xffff0000, 0xffff0000, 0x3ffbc004, 0x3f9bc064
.long 0x00000000, 0x00000000, 0x00000000, 0x00000000
.long 0x00000000, 0x00000000, 0x00000000, 0x00000000
.long 0x00000000, 0x00000000, 0x00000000, 0x00000000
.long 0xffff0000, 0xffff0000, 0xffff0000, 0xffff0000
.long 0xffff0000, 0xffff0000, 0x0000ffff, 0xffff0000
.long 0xefff1000, 0xffff0000, 0xffff0000, 0xffff0000
.long 0xefff1000, 0xefff1000, 0xffff0000, 0x00000000
.long 0xffff0000, 0xffff0000, 0xefff1000, 0xffff0000
.long 0x00000000, 0x00000000, 0x00000000, 0x00000000
.long 0x00000000, 0x00000000, 0x00000000, 0x00000000
.long 0x00000000, 0x50000000, 0x00000000, 0x00000000
#endif
gpio_dump_end:
.p2align 3
write_dumpreg:
ld $t2, 0($t6)
sd $t2, 0($t4)
addiu $t4, $t4, VAS_EBOOT_CPU_LOONGSON_DDR2_REG_STEP
jr $ra
addiu $t6, $t6, VAS_EBOOT_CPU_LOONGSON_DDR2_REG_SIZE
continue:
lui $t4, %hi(VAS_EBOOT_CPU_LOONGSON_DDR2_BASE)
addiu $t4, $t4, %lo(VAS_EBOOT_CPU_LOONGSON_DDR2_BASE)
lui $t6, %hi(regdump)
/* 0 */
bal write_dumpreg
addiu $t6, $t6, %lo(regdump)
/* 1 */
ori $a1, $a1, VAS_EBOOT_SMB_RAM_START_ADDR
move $t8, $zero
lui $t5, 0x0001
bal read_spd
ori $a0, $zero, VAS_EBOOT_SMBUS_SPD_MEMORY_NUM_BANKS_ADDR
ori $t7, $zero, 8
bne $v0, $t7, 1f
ori $t5, $t5, 0x0001
ori $t8, $t8, VAS_EBOOT_CPU_LOONGSON_DDR2_REG1_HI_8BANKS
1:
dsll $t8, $t8, 32
or $t5, $t5, $t8
sd $t5, 0 ($t4)
addiu $t4, $t4, VAS_EBOOT_CPU_LOONGSON_DDR2_REG_STEP
/* 2 */
bal write_dumpreg
nop
/* 3 */
bal write_dumpreg
nop
/* 4 */
bal write_dumpreg
nop
/* 5 */
/* FIXME: figure termination resistance. */
ori $t5, $zero, 0x2
bal read_spd
ori $a0, $zero, VAS_EBOOT_SMBUS_SPD_MEMORY_NUM_ROWS_ADDR
/* $v0 = 15 - $v0. */
xori $v0, $v0, 0xf
andi $v0, $v0, 0x7
sll $v0, $v0, 8
or $t5, $t5, $v0
/* Find the fastest supported CAS latency. */
bal read_spd
ori $a0, $zero, VAS_EBOOT_SMBUS_SPD_MEMORY_CAS_LATENCY_ADDR
ori $t0, $zero, VAS_EBOOT_SMBUS_SPD_MEMORY_CAS_LATENCY_MIN_VALUE
ori $t1, $zero, (1 << VAS_EBOOT_SMBUS_SPD_MEMORY_CAS_LATENCY_MIN_VALUE)
2:
and $t2, $t1, $v0
bne $t2, $zero, 1f
ori $t3, $zero, 8
lui $a0, %hi(no_cas_latency)
beq $t0, $t3, fatal
addiu $a0, $a0, %lo(no_cas_latency)
addiu $t0, $t0, 1
b 2b
sll $t1, $t1, 1
1:
sll $t0, $t0, 16
or $t5, $t5, $t0
bal read_spd
ori $a0, $zero, VAS_EBOOT_SMBUS_SPD_MEMORY_NUM_COLUMNS_ADDR
/* $v0 = 15 - ($v0 + 1) = 14 - $v0. */
addiu $v0, $v0, 1
xori $v0, $v0, 0xf
andi $v0, $v0, 0x7
sll $v0, 24
or $t5, $t5, $v0
sd $t5, 0 ($t4)
addiu $t4, $t4, VAS_EBOOT_CPU_LOONGSON_DDR2_REG_STEP
ori $t7, $zero, 0x16
1:
ld $t2, 0($t6)
sd $t2, 0($t4)
addiu $t4, $t4, VAS_EBOOT_CPU_LOONGSON_DDR2_REG_STEP
addiu $t7, $t7, -1
bne $t7, $zero, 1b
addiu $t6, $t6, VAS_EBOOT_CPU_LOONGSON_DDR2_REG_SIZE
lui $t4, %hi(VAS_EBOOT_CPU_LOONGSON_DDR2_BASE)
ld $t5, (%lo(VAS_EBOOT_CPU_LOONGSON_DDR2_BASE) + 0x30) ($t4)
ori $t0, $zero, 1
dsll $t0, $t0, 40
or $t5, $t5, $t0
sd $t5, (%lo(VAS_EBOOT_CPU_LOONGSON_DDR2_BASE) + 0x30) ($t4)
/* Desactivate DDR2 registers. */
lui $t0, %hi (VAS_EBOOT_CPU_LOONGSON_CORECFG)
ld $t1, %lo (VAS_EBOOT_CPU_LOONGSON_CORECFG) ($t0)
ori $t1, $t1, VAS_EBOOT_CPU_LOONGSON_CORECFG_DISABLE_DDR2_SPACE
sd $t1, %lo (VAS_EBOOT_CPU_LOONGSON_CORECFG) ($t0)
/* Enable cache. */
mfc0 $t0, VAS_EBOOT_CPU_LOONGSON_COP0_CACHE_CONFIG
addiu $t1, $zero, ~VAS_EBOOT_CPU_LOONGSON_CACHE_TYPE_MASK
and $t0, $t1, $t1
/* Set line size to 32 bytes and disabled cache. */
ori $t0, $t0, (VAS_EBOOT_CPU_LOONGSON_COP0_CACHE_CONFIG_ILINESIZE \
| VAS_EBOOT_CPU_LOONGSON_COP0_CACHE_CONFIG_DLINESIZE \
| VAS_EBOOT_CPU_LOONGSON_CACHE_ACCELERATED)
mtc0 $t0, VAS_EBOOT_CPU_LOONGSON_COP0_CACHE_CONFIG
/* Invalidate all I-cache entries. */
srl $t1, $t0, VAS_EBOOT_CPU_LOONGSON_COP0_CACHE_ISIZE_SHIFT
andi $t1, $t1, VAS_EBOOT_CPU_LOONGSON_COP0_CACHE_SIZE_MASK
ori $t2, $zero, (1 << (VAS_EBOOT_CPU_LOONGSON_COP0_CACHE_SIZE_OFFSET \
- VAS_EBOOT_CPU_LOONGSON_CACHE_LINE_SIZE_LOG_BIG \
- VAS_EBOOT_CPU_LOONGSON_I_CACHE_LOG_WAYS))
sll $t1, $t2, $t1
lui $t2, 0x8000
1:
cache VAS_EBOOT_CPU_LOONGSON_COP0_I_INDEX_INVALIDATE, 0($t2)
addiu $t1, $t1, -1
bne $t1, $zero, 1b
addiu $t2, $t2, (1 << VAS_EBOOT_CPU_LOONGSON_COP0_I_INDEX_BIT_OFFSET)
/* Invalidate all D-cache entries. */
srl $t1, $t0, VAS_EBOOT_CPU_LOONGSON_COP0_CACHE_DSIZE_SHIFT
andi $t1, $t1, VAS_EBOOT_CPU_LOONGSON_COP0_CACHE_SIZE_MASK
ori $t2, $zero, (1 << (VAS_EBOOT_CPU_LOONGSON_COP0_CACHE_SIZE_OFFSET \
- VAS_EBOOT_CPU_LOONGSON_CACHE_LINE_SIZE_LOG_BIG \
- VAS_EBOOT_CPU_LOONGSON_D_CACHE_LOG_WAYS))
sll $t1, $t2, $t1
lui $t2, 0x8000
mtc0 $zero, VAS_EBOOT_CPU_LOONGSON_COP0_CACHE_TAGLO
mtc0 $zero, VAS_EBOOT_CPU_LOONGSON_COP0_CACHE_TAGHI
1:
/* All four ways. */
cache VAS_EBOOT_CPU_LOONGSON_COP0_D_INDEX_TAG_STORE, 0($t2)
cache VAS_EBOOT_CPU_LOONGSON_COP0_D_INDEX_TAG_STORE, 1($t2)
cache VAS_EBOOT_CPU_LOONGSON_COP0_D_INDEX_TAG_STORE, 2($t2)
cache VAS_EBOOT_CPU_LOONGSON_COP0_D_INDEX_TAG_STORE, 3($t2)
addiu $t1, $t1, -1
bne $t1, $zero, 1b
addiu $t2, $t2, (1 << VAS_EBOOT_CPU_LOONGSON_COP0_D_INDEX_BIT_OFFSET)
/* Invalidate all S-cache entries. */
ori $t1, $zero, (1 << (VAS_EBOOT_CPU_LOONGSON_SECONDARY_CACHE_LOG_SIZE \
- VAS_EBOOT_CPU_LOONGSON_CACHE_LINE_SIZE_LOG_BIG \
- VAS_EBOOT_CPU_LOONGSON_S_CACHE_LOG_WAYS))
lui $t2, 0x8000
mtc0 $zero, VAS_EBOOT_CPU_LOONGSON_COP0_CACHE_TAGLO
mtc0 $zero, VAS_EBOOT_CPU_LOONGSON_COP0_CACHE_TAGHI
1:
/* All four ways. */
cache VAS_EBOOT_CPU_LOONGSON_COP0_S_INDEX_TAG_STORE, 0($t2)
cache VAS_EBOOT_CPU_LOONGSON_COP0_S_INDEX_TAG_STORE, 1($t2)
cache VAS_EBOOT_CPU_LOONGSON_COP0_S_INDEX_TAG_STORE, 2($t2)
cache VAS_EBOOT_CPU_LOONGSON_COP0_S_INDEX_TAG_STORE, 3($t2)
addiu $t1, $t1, -1
bne $t1, $zero, 1b
addiu $t2, $t2, (1 << VAS_EBOOT_CPU_LOONGSON_COP0_D_INDEX_BIT_OFFSET)
/* Finally enable cache. */
mfc0 $t0, VAS_EBOOT_CPU_LOONGSON_COP0_CACHE_CONFIG
addiu $t1, $zero, ~VAS_EBOOT_CPU_LOONGSON_CACHE_TYPE_MASK
and $t0, $t1, $t1
ori $t0, $t0, VAS_EBOOT_CPU_LOONGSON_CACHE_CACHED
mtc0 $t0, VAS_EBOOT_CPU_LOONGSON_COP0_CACHE_CONFIG
lui $a0, %hi(caches_enabled)
bal message
addiu $a0, $a0, %lo(caches_enabled)
/* Set ROM delay cycles to 1. */
lui $t0, %hi(VAS_EBOOT_CPU_LOONGSON_LIOCFG)
lw $t1, %lo(VAS_EBOOT_CPU_LOONGSON_LIOCFG) ($t0)
addiu $t2, $zero, ~(VAS_EBOOT_CPU_LOONGSON_ROM_DELAY_MASK \
<< VAS_EBOOT_CPU_LOONGSON_ROM_DELAY_OFFSET)
and $t1, $t1, $t2
ori $t1, $t1, (1 << VAS_EBOOT_CPU_LOONGSON_ROM_DELAY_OFFSET)
sw $t1, %lo(VAS_EBOOT_CPU_LOONGSON_LIOCFG) ($t0)
addiu $a0, $zero, -1
addiu $a1, $zero, -1
/* Take advantage of cache. */
lui $t0, %hi(cached_continue - 0x20000000)
addiu $t0, $t0, %lo(cached_continue - 0x20000000)
jr $t0
#ifdef FULOONG2F
addiu $a2, $zero, -(1 + VAS_EBOOT_ARCH_MACHINE_FULOONG2F)
#else
addiu $a2, $zero, -(1 + VAS_EBOOT_ARCH_MACHINE_YEELOONG)
#endif
cached_continue:

View File

@ -0,0 +1,300 @@
/* startup.S - Startup code for the MIPS. */
/*
* VAS_EBOOT -- GRand Unified Bootloader
* Copyright (C) 2009 Free Software Foundation, Inc.
*
* VAS_EBOOT 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.
*
* VAS_EBOOT 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 VAS_EBOOT. If not, see <http://www.gnu.org/licenses/>.
*/
#include <VasEBoot/symbol.h>
#include <VasEBoot/offsets.h>
#include <VasEBoot/machine/memory.h>
#include <VasEBoot/machine/kernel.h>
#include <VasEBoot/offsets.h>
#include <VasEBoot/mips/asm.h>
#define BASE_ADDR 8
.extern __bss_start
.extern _end
.extern _edata
.globl __start, _start, start
.set noreorder
.set nomacro
__start:
_start:
start:
bal codestart
nop
base:
.org VAS_EBOOT_DECOMPRESSOR_MACHINE_COMPRESSED_SIZE
compressed_size:
.long 0
.org VAS_EBOOT_DECOMPRESSOR_MACHINE_UNCOMPRESSED_SIZE
uncompressed_size:
.long 0
.org VAS_EBOOT_DECOMPRESSOR_MACHINE_UNCOMPRESSED_ADDR
uncompressed_addr:
.long 0
codestart:
/* Save our base. */
move $s0, $ra
/* Parse arguments. Has to be done before relocation.
So need to do it in asm. */
#ifdef VAS_EBOOT_MACHINE_MIPS_QEMU_MIPS
lui $t0, %hi (((16 << 20) - 264 + 4) | 0x80000000)
lw $t1, %lo (((16 << 20) - 264 + 4) | 0x80000000) ($t0)
lui $t2, 0x1234
ori $t2, 0x5678
bne $t1, $t2, 1f
nop
lui $t0, %hi (((16 << 20) - 264) | 0x80000000)
b 2f
lw $s4, %lo (((16 << 20) - 264) | 0x80000000) ($t0)
1:
li $s4, 0
2:
#endif
#ifdef VAS_EBOOT_MACHINE_MIPS_LOONGSON
move $s2, $zero
move $s3, $zero
move $s4, $zero
move $s5, $zero
move $s7, $zero
/* $a2 has the environment. */
addiu $t0, $zero, -0x10
and $t1, $a2, $t0
beq $t0, $t1, argfw
nop
move $t0, $a2
argcont:
lw $t1, 0($t0)
beq $t1, $zero, argdone
nop
#define DO_PARSE(str, reg) \
addiu $t2, $s0, (str-base);\
bal parsestr;\
nop ;\
beq $v0, $zero, 1f;\
nop ;\
b 2f;\
move reg, $v0; \
1:
#define DO_CHECKT1(str, val) \
move $t6, $t1 ;\
addiu $t7, $s0, (str - base);\
bal do_check ;\
li $t2, val
DO_PARSE (busclockstr, $s2)
DO_PARSE (cpuclockstr, $s3)
DO_PARSE (memsizestr, $s4)
DO_PARSE (highmemsizestr, $s5)
DO_CHECKT1 (pmon_yeeloong_verstr, VAS_EBOOT_ARCH_MACHINE_YEELOONG)
DO_CHECKT1 (pmon_fuloong2f_verstr, VAS_EBOOT_ARCH_MACHINE_FULOONG2F)
2:
b argcont
addiu $t0, $t0, 4
parsestr:
move $v0, $zero
move $t3, $t1
3:
lb VAS_EBOOT_ASM_T4, 0($t2)
lb VAS_EBOOT_ASM_T5, 0($t3)
addiu $t2, $t2, 1
addiu $t3, $t3, 1
beq VAS_EBOOT_ASM_T5, $zero, 1f
nop
beq VAS_EBOOT_ASM_T5, VAS_EBOOT_ASM_T4, 3b
nop
bne VAS_EBOOT_ASM_T4, $zero, 1f
nop
addiu $t3, $t3, 0xffff
digcont:
lb VAS_EBOOT_ASM_T5, 0($t3)
/* Substract '0' from digit. */
addiu VAS_EBOOT_ASM_T5, VAS_EBOOT_ASM_T5, 0xffd0
bltz VAS_EBOOT_ASM_T5, 1f
nop
addiu VAS_EBOOT_ASM_T4, VAS_EBOOT_ASM_T5, 0xfff7
bgtz VAS_EBOOT_ASM_T4, 1f
nop
/* Multiply $v0 by 10 with bitshifts. */
sll $v0, $v0, 1
sll VAS_EBOOT_ASM_T4, $v0, 2
addu $v0, $v0, VAS_EBOOT_ASM_T4
addu $v0, $v0, VAS_EBOOT_ASM_T5
addiu $t3, $t3, 1
b digcont
nop
1:
jr $ra
nop
busclockstr: .asciz "busclock="
cpuclockstr: .asciz "cpuclock="
memsizestr: .asciz "memsize="
highmemsizestr: .asciz "highmemsize="
machtype_yeeloong_str1: .asciz "machtype=8.9"
machtype_yeeloong_str2: .asciz "machtype=lemote-yeeloong-"
machtype_fuloong2f_str: .asciz "machtype=lemote-fuloong-2f"
machtype_fuloong2e_str: .asciz "machtype=lemote-fuloong-2e"
pmon_yeeloong_str: .asciz "PMON_VER=LM8"
pmon_fuloong2f_str: .asciz "PMON_VER=LM6"
pmon_yeeloong_verstr: .asciz "Version=LM8"
pmon_fuloong2f_verstr: .asciz "Version=LM6"
.p2align 2
argdone:
beq $a0, $zero, cmdlinedone
nop
#define DO_CHECKA1(str, val) \
lw $t6, 0($a1) ;\
addiu $t7, $s0, (str - base);\
bal do_check ;\
li $t2, val
DO_CHECKA1 (machtype_yeeloong_str1, VAS_EBOOT_ARCH_MACHINE_YEELOONG)
DO_CHECKA1 (machtype_yeeloong_str2, VAS_EBOOT_ARCH_MACHINE_YEELOONG)
DO_CHECKA1 (pmon_yeeloong_str, VAS_EBOOT_ARCH_MACHINE_YEELOONG)
DO_CHECKA1 (machtype_fuloong2f_str, VAS_EBOOT_ARCH_MACHINE_FULOONG2F)
DO_CHECKA1 (machtype_fuloong2e_str, VAS_EBOOT_ARCH_MACHINE_FULOONG2E)
DO_CHECKA1 (pmon_fuloong2f_str, VAS_EBOOT_ARCH_MACHINE_FULOONG2F)
addiu $a0, $a0, -1
b argdone
addiu $a1, $a1, 4
do_check:
lb VAS_EBOOT_ASM_T4, 0($t7)
beq VAS_EBOOT_ASM_T4, $zero, 1f
lb $t3, 0($t6)
bne $t3, VAS_EBOOT_ASM_T4, 2f
addiu $t6, $t6, 1
b do_check
addiu $t7, $t7, 1
1:
move $s7, $t2
2:
jr $ra
nop
argfw:
not $s7, $a2
cmdlinedone:
#endif
#ifdef VAS_EBOOT_MACHINE_ARC
lui $t0, %hi(_start - 256)
addiu $t0, $t0, %lo(_start - 256)
addiu $t3, $t0, 255
lw $t1, 0($a1)
1:
bne $t0, $t3, 2f
lb $t2, 0($t1)
move $t2, $zero
2:
sb $t2, 0($t0)
addiu $t0, $t0, 1
bnez $t2, 1b
addiu $t1, $t1, 1
#endif
/* Copy the decompressor. */
lui $t1, %hi(base)
addiu $t1, $t1, %lo(base)
lui $t3, %hi(__bss_start)
addiu $t3, $t3, %lo(__bss_start)
move $t2, $s0
1:
beq $t1, $t3, 2f
lb VAS_EBOOT_ASM_T4, 0($t2)
sb VAS_EBOOT_ASM_T4, 0($t1)
addiu $t1, $t1, 1
b 1b
addiu $t2, $t2, 1
2:
/* Clean out its BSS. */
lui $t1, %hi(__bss_start)
addiu $t1, $t1, %lo(__bss_start)
lui $t2, %hi(_end)
addiu $t2, $t2, %lo(_end)
1:
beq $t1, $t2, 2f
nop
sb $zero, 0($t1)
b 1b
addiu $t1, $t1, 1
2:
lui $a0, %hi(base)
addiu $a0, $a0, %lo(base)
lui $a1, %hi(_end)
addiu $a1, %lo(_end)
subu $a1,$a1,$a0
#include "../../kern/mips/cache_flush.S"
/* Decompress the payload. */
lui $a0, %hi(_edata)
addiu $a0, $a0, %lo(_edata)
lui $t0, %hi(base)
addiu $t0, $t0, %lo(base)
subu $a0, $a0, $t0
addu $a0, $a0, $s0
lw $a1, (VAS_EBOOT_DECOMPRESSOR_MACHINE_UNCOMPRESSED_ADDR - BASE_ADDR)($s0)
lw $a2, (VAS_EBOOT_DECOMPRESSOR_MACHINE_COMPRESSED_SIZE - BASE_ADDR)($s0)
lw $a3, (VAS_EBOOT_DECOMPRESSOR_MACHINE_UNCOMPRESSED_SIZE - BASE_ADDR)($s0)
move $s1, $a1
/* $a0 contains source compressed address, $a1 is destination,
$a2 is compressed size, $a3 is uncompressed size.
*/
move $s6, $a3
lui $t9, %hi(EXT_C(VasEBoot_decompress_core))
addiu $t9, $t9, %lo(EXT_C(VasEBoot_decompress_core))
#ifdef VAS_EBOOT_MACHINE_ARC
lui $sp, %hi(_start - 512)
jalr $t9
addiu $sp, $sp, %lo(_start - 512)
#else
lui $sp, %hi(_start - 256)
jalr $t9
addiu $sp, $sp, %lo(_start - 256)
#endif
move $a0, $s1
move $a1, $s6
#include "../../kern/mips/cache_flush.S"
lui $t1, %hi(VAS_EBOOT_MACHINE_LINK_ADDR)
addiu $t1, %lo(VAS_EBOOT_MACHINE_LINK_ADDR)
jr $t1
nop
/* Ensure that .data section is created. In code we suppose that _edata
is first location not in decompressor image. Strictly speaking it's
_edata only when .data is present and _etext otherwise. But checking
for .data presence would cost more in code than it is to ensure that
.data is created.
*/
.data
.long 0

View File

@ -0,0 +1,172 @@
<CHRP-BOOT>
<COMPATIBLE>
MacRISC MacRISC3 MacRISC4
</COMPATIBLE>
<DESCRIPTION>
@PACKAGE@ @VERSION@
</DESCRIPTION>
<OS-BADGE-ICONS>
3434
00000000000000F781FB8181818181FBFAF500000000000000000000000000000000000000F6FAFAFAFA81F9F600000000000000
0000000000F8FBF9F500F95656FCFB5656FBF800000000000000000000000000000000F5FAF9F5F7F600F6F6F9FAF70000000000
000000F5FBFA0056FDFEFEFDFDFAAC81FB56568181560000000000000000000000F9F9F9F7FCFDFEFEFEFFFC81F656FA00000000
0000F5AC2BF7FBFEFEFD2BF6568181F9F7F6F6F8FBF50000000000000000000000FAF700F600F5F7F7F6F7FEFFACF82BFB000000
0000FC2BF5FEFFFFF5F7FC81F70000F7F9FAFAF8000000000000000000000000000056F9F9FAF9F7F7FA812BF7FFFF56F7FA0000
005656F5FEFFAC2BF9FA000000000000000000000000000000000000000000000000000000000000000000FA56FAFEFEF8F9F700
00FB00F7FFFF56F9F800000000000000000000F656FAFA56F50000000000F5F8F9F8F5000000000000000000F9F7FCFFFB00FB00
F8F800ACFFACF6FA000000000000000000F6FA562BF5F5F781FA000000F9FA2B00F556F9F5000000000000000081F8FFFEF6562B
810000FFFFF9FAF500000000000000002B8100F5F9FCACFBF82BFBF6FCFAF6FAFC81F600FA2B000000000000002BF8FEFFF8F5FA
FA00F5FEFFFA8100000000000000002B8100F9FEFFFFFFFFFFFBF6FDFEACFDFEFFFFFFFBF581F600000000000000F9FEFFF700FA
FA00FBFFFEF6F900000000000000F6FB00FCFFFFFFFFFFFFFFFFFCF600FCF7ACFEFFFFFFFDF6810000000000000056F9FFAC00FA
FA00F6FFFFF856000000000000F5FBF5ACFFFFFFFFFFFFFFFFFFFF2B002BF8F5ACFFFFFFFFFDF6FA000000000000F9FCFF560081
FA0081FFFFF8F9000000000000FBF6FBFFFFFFFFFFFFFFFFFFFFFFF800F55600FCFFFFFFFFFF81F8F80000000000F981FFAC0081
FA0000FEFEF8FB0000000000812BFAFFFFFFFFFFFFFEFFFFFDF92BFA0000F6F981ACFEFFFFFFFF56F9F600000000F9FDFF2B0081
FA00FAFFFF81812B000000FAF8F9FFFFFEACFBF80000F500000000F9F900562B0000FCF7F9ACFFFF2BF9F50000F9F6FEFFFB0081
810000FCFFFBF6FB56F7FBF8F9FFFE5600000000F5FAAC000000F82BF6FAFBF800F556F80000F9FFFE2BFAFAFAF8FAFFFEF60081
FAF6F5ACFFFFAC00F856F7ACFFFCF500000000FAFCFFFC00000056AC00F581F92BFEF9FAF6000081FFFFFBF6F62BFFFFACF6F6FA
F6FA00FAFFFFFFACFA56FFFFAC0000000000F6FD2BFEF6F5565600F5F800F60081FEF7F656000000FDFFFFFDFDFFFFFFAC0081F5
0081F52BFDFFFFFFFFFFFFFFF60000000000FBF6F6F5F656F52BF900FA000000FCFAF5F656000000F7FFFFFFFFFFFFFDF7F68100
00F6FB00F8FDFFFFFFFFFF810000000000F6F5000000F52B56F9FC00F7F70000FCF881FCF500000000FEFFFFFFFFAC5600FBF500
000056F900F8ACFDFFFFFFF5000000000000002B0000FDFEFFFE560000F60000F9ACFFFE810000000081FFFEFDFAF800FAF70000
000000FAF9002B56FAFDFC0000000000000000F80000FBF5FEFEF5000000000000ACFFFA2B0000000000FEFB2BF5008156000000
00000000F9FBF600F6FBF800000000000000F7F8000000F9F9F9F82B0000000000F6ACACF70000000000F7FD2BFA812B00000000
0000000000F681FCFBFD0000000000000000FBF6000000000000F52B000000000000F92B810000000000008181F6000000000000
0000000000000000F6FC00000000000000F6FF0000000000000000000000000000000081FBFB2B00000000F7F900000000000000
000000000000000000FC00000000000000FCFAF600000000000000000000000000000056ACF581FBF700000081FB000000000000
0000000000000000FAF90000000000008156F5F8000000000000002BFBFCFBF800000000FD2B000056FB8181FBF8000000000000
0000000000000000AC0000000000F5FBF90000F6000000000000F5AC56F6005681F50000F6ACFCFBF70000000000000000000000
00000000000000F881000000F5FAFDFD00000000000000000000F7FEFA2B0000F581F70000000000810000000000000000000000
000000000000F9FCF500FAFDACFAF5FD00000000000000000000F5ACF5FDFEFA0000F82B00000000810000000000000000000000
000000000000FCF8F9AC81FD000000FD000000000000FAF7000000F50081F9FAF800000000000000FB0000000000000000000000
000000000000FC81F956F5FD000000FD0000000000000000F800F5000000000056000000000000F7FB0000000000000000000000
00000000000000000000F5AC000000ACF800000000000000F5FAF80000000000F50000000000F8ACF50000000000000000000000
00000000000000000000F5AC000000F5AC000000000000000056F9000000000000000000F7ACFCF5000000000000000000000000
00000000000000000000F5FD00000000AC000000000000000000FB0000000000000000F5F6F5FCF6000000000000000000000000
0000000000000000000000FD00000000FBFDF600000000000000F8F900000000000000000000F5FB000000000000000000000000
0000000000000000000000FDF500000000F9ACF800000000000000815600000000F656818181AC56000000000000000000000000
000000000000000000000081F80000000000F9FC0000000000000000F9ACACACFCFBFAFA81FD2B00000000000000000000000000
0000000000000000000000F7FB0000000000FBF70000000000000000000000000000000000FB0000000000000000000000000000
000000000000000000000000ACF500000000F9FD56F5000000000000000000000000000000FB0000000000000000000000000000
000000000000000000000000F8FA0000000000F6FEFEF5000000000000F55681FCACFDACFC560000000000000000000000000000
00000000000000000000000000FBF600000000002BFCFA00F700000000F9FDFDFAFEF90000000000000000000000000000000000
00000000000000000000000000F5FB0000000000F5FEF7ACAC0000000000000000FCF50000000000000000000000000000000000
0000000000000000000000000000F6FA000000002BFF2BFFFFAC00000000000000F7FA0000000000000000000000000000000000
000000000000000000000000000000F65600000000FAFEFFFFAC0000000000F800F6810000000000000000000000000000000000
00000000000000000000000000000000F52B00000000F8FEFBFF5600000000FCFAACF60000000000000000000000000000000000
0000000000000000000000000000000000000000000000F9FCFCFFFB00F8FEFFFDF5000000000000000000000000000000000000
00000000000000000000000000000000000000000000F9FDF7F5FFFD56FFFFFFFD00000000000000000000000000000000000000
00000000000000000000000000000000000000000000810000FBFFFFFBFFFFFFFFACF9F5F5000000000000000000000000000000
0000000000000000000000000000000000000000000000F600FC81FFFEFFFFFFFFFFFE8100000000000000000000000000000000
00000000000000000000000000000000000000000000000000F7F6FDFFFFFFFEFFFFACF500000000000000000000000000000000
000000000000000000000000000000000000000000000000000000F5FC81FC81FAFBF9F500000000000000000000000000000000
00000000000000F781FB8181818181FBFAF500000000000000000000000000000000000000F6FAFAFAFA81F9F600000000000000
0000000000F8FBF9F500F95656FCFB5656FBF800000000000000000000000000000000F5FAF9F5F7F600F6F6F9FAF70000000000
000000F5FBFA0056FDFEFEFDFDFAAC81FB56568181560000000000000000000000F9F9F9F7FCFDFEFEFEFFFC81F656FA00000000
0000F5AC2BF7FBFEFEFD2BF6568181F9F7F6F6F8FBF50000000000000000000000FAF700F600F5F7F7F6F7FEFFACF82BFB000000
0000FC2BF5FEFFFFF5F7FC81F70000F7F9FAFAF8000000000000000000000000000056F9F9FAF9F7F7FA812BF7FFFF56F7FA0000
005656F5FEFFAC2BF9FA000000000000000000000000000000000000000000000000000000000000000000FA56FAFEFEF8F9F700
00FB00F7FFFF56F9F800000000000000000000F656FAFA56F50000000000F5F8F9F8F5000000000000000000F9F7FCFFFB00FB00
F8F800ACFFACF6FA000000000000000000F6FA562BF5F5F781FA000000F9FA2B00F556F9F5000000000000000081F8FFFEF6562B
810000FFFFF9FAF500000000000000002B8100F5F9FCACFBF82BFBF6FCFAF6FAFC81F600FA2B000000000000002BF8FEFFF8F5FA
FA00F5FEFFFA8100000000000000002B8100F9FEFFFFFFFFFFFBF6FDFEACFDFEFFFFFFFBF581F600000000000000F9FEFFF700FA
FA00FBFFFEF6F900000000000000F6FB00FCFFFFFFFFFFFFFFFFFCF600FCF7ACFEFFFFFFFDF6810000000000000056F9FFAC00FA
FA00F6FFFFF856000000000000F5FBF5ACFFFFFFFFFFFFFFFFFFFF2B002BF8F5ACFFFFFFFFFDF6FA000000000000F9FCFF560081
FA0081FFFFF8F9000000000000FBF6FBFFFFFFFFFFFFFFFFFFFFFFF800F55600FCFFFFFFFFFF81F8F80000000000F981FFAC0081
FA0000FEFEF8FB0000000000812BFAFFFFFFFFFFFFFEFFFFFDF92BFA0000F6F981ACFEFFFFFFFF56F9F600000000F9FDFF2B0081
FA00FAFFFF81812B000000FAF8F9FFFFFEACFBF80000F500000000F9F900562B0000FCF7F9ACFFFF2BF9F50000F9F6FEFFFB0081
810000FCFFFBF6FB56F7FBF8F9FFFE5600000000F5FAAC000000F82BF6FAFBF800F556F80000F9FFFE2BFAFAFAF8FAFFFEF60081
FAF6F5ACFFFFAC00F856F7ACFFFCF500000000FAFCFFFC00000056AC00F581F92BFEF9FAF6000081FFFFFBF6F62BFFFFACF6F6FA
F6FA00FAFFFFFFACFA56FFFFAC0000000000F6FD2BFEF6F5565600F5F800F60081FEF7F656000000FDFFFFFDFDFFFFFFAC0081F5
0081F52BFDFFFFFFFFFFFFFFF60000000000FBF6F6F5F656F52BF900FA000000FCFAF5F656000000F7FFFFFFFFFFFFFDF7F68100
00F6FB00F8FDFFFFFFFFFF810000000000F6F5000000F52B56F9FC00F7F70000FCF881FCF500000000FEFFFFFFFFAC5600FBF500
000056F900F8ACFDFFFFFFF5000000000000002B0000FDFEFFFE560000F60000F9ACFFFE810000000081FFFEFDFAF800FAF70000
000000FAF9002B56FAFDFC0000000000000000F80000FBF5FEFEF5000000000000ACFFFA2B0000000000FEFB2BF5008156000000
00000000F9FBF600F6FBF800000000000000F7F8000000F9F9F9F82B0000000000F6ACACF70000000000F7FD2BFA812B00000000
0000000000F681FCFBFD0000000000000000FBF6000000000000F52B000000000000F92B810000000000008181F6000000000000
0000000000000000F6FC00000000000000F6FF0000000000000000000000000000000081FBFB2B00000000F7F900000000000000
000000000000000000FC00000000000000FCFAF600000000000000000000000000000056ACF581FBF700000081FB000000000000
0000000000000000FAF90000000000008156F5F8000000000000002BFBFCFBF800000000FD2B000056FB8181FBF8000000000000
0000000000000000AC0000000000F5FBF90000F6000000000000F5AC56F6005681F50000F6ACFCFBF70000000000000000000000
00000000000000F881000000F5FAFDFD00000000000000000000F7FEFA2B0000F581F70000000000810000000000000000000000
000000000000F9FCF500FAFDACFAF5FD00000000000000000000F5ACF5FDFEFA0000F82B00000000810000000000000000000000
000000000000FCF8F9AC81FD000000FD000000000000FAF7000000F50081F9FAF800000000000000FB0000000000000000000000
000000000000FC81F956F5FD000000FD0000000000000000F800F5000000000056000000000000F7FB0000000000000000000000
00000000000000000000F5AC000000ACF800000000000000F5FAF80000000000F50000000000F8ACF50000000000000000000000
00000000000000000000F5AC000000F5AC000000000000000056F9000000000000000000F7ACFCF5000000000000000000000000
00000000000000000000F5FD00000000AC000000000000000000FB0000000000000000F5F6F5FCF6000000000000000000000000
0000000000000000000000FD00000000FBFDF600000000000000F8F900000000000000000000F5FB000000000000000000000000
0000000000000000000000FDF500000000F9ACF800000000000000815600000000F656818181AC56000000000000000000000000
000000000000000000000081F80000000000F9FC0000000000000000F9ACACACFCFBFAFA81FD2B00000000000000000000000000
0000000000000000000000F7FB0000000000FBF70000000000000000000000000000000000FB0000000000000000000000000000
000000000000000000000000ACF500000000F9FD56F5000000000000000000000000000000FB0000000000000000000000000000
000000000000000000000000F8FA0000000000F6FEFEF5000000000000F55681FCACFDACFC560000000000000000000000000000
00000000000000000000000000FBF600000000002BFCFA00F700000000F9FDFDFAFEF90000000000000000000000000000000000
00000000000000000000000000F5FB0000000000F5FEF7ACAC0000000000000000FCF50000000000000000000000000000000000
0000000000000000000000000000F6FA000000002BFF2BFFFFAC00000000000000F7FA0000000000000000000000000000000000
000000000000000000000000000000F65600000000FAFEFFFFAC0000000000F800F6810000000000000000000000000000000000
00000000000000000000000000000000F52B00000000F8FEFBFF5600000000FCFAACF60000000000000000000000000000000000
0000000000000000000000000000000000000000000000F9FCFCFFFB00F8FEFFFDF5000000000000000000000000000000000000
00000000000000000000000000000000000000000000F9FDF7F5FFFD56FFFFFFFD00000000000000000000000000000000000000
00000000000000000000000000000000000000000000810000FBFFFFFBFFFFFFFFACF9F5F5000000000000000000000000000000
0000000000000000000000000000000000000000000000F600FC81FFFEFFFFFFFFFFFE8100000000000000000000000000000000
00000000000000000000000000000000000000000000000000F7F6FDFFFFFFFEFFFFACF500000000000000000000000000000000
000000000000000000000000000000000000000000000000000000F5FC81FC81FAFBF9F500000000000000000000000000000000
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
</OS-BADGE-ICONS>
<BOOT-SCRIPT>
boot &device;:&partition;,\System\Library\CoreServices\VasEBoot.elf
</BOOT-SCRIPT>
</CHRP-BOOT>

View File

@ -1,7 +1,7 @@
<chrp-boot>
<description>@PACKAGE@ @VERSION@</description>
<os-name>@PACKAGE@ @VERSION@</os-name>
<boot-script>boot &device;:\boot\grub\powerpc.elf</boot-script>
<boot-script>boot &device;:\boot\VasEBoot\powerpc.elf</boot-script>
<icon size=64,64 color-space=3,3,2>
<bitmap>
FF FF FF FF FF FF FF FF FF FF 92 6D 6D 6D 6D 6D 6D 6D 6D 6D DB FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF B6 92 6D 92 92 92 DB FF FF FF FF FF FF FF FF FF FF

View File

@ -0,0 +1,262 @@
/* -*-Asm-*- */
/*
* VAS_EBOOT -- GRand Unified Bootloader
* Copyright (C) 2009 Free Software Foundation, Inc.
*
* VAS_EBOOT 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.
*
* VAS_EBOOT 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 VAS_EBOOT. If not, see <http://www.gnu.org/licenses/>.
*/
#include <VasEBoot/machine/boot.h>
.text
.align 4
/*
* We're writing the a.out header ourselves as newer
* upstream versions of binutils no longer support
* the a.out format on sparc64.
*
* The boot loader fits into 512 bytes with 32 bytes
* used for the a.out header, hence the text segment
* size is 512 - 32. There is no data segment and no
* code relocation, thus those fields remain zero.
*/
.word 0x1030107 /* Magic number. */
.word 512 - VAS_EBOOT_BOOT_AOUT_HEADER_SIZE /* Size of text segment. */
.word 0 /* Size of initialized data. */
.word 0 /* Size of uninitialized data. */
.word 0 /* Size of symbol table || checksum. */
.word _start /* Entry point. */
.word 0 /* Size of text relocation. */
.word 0 /* Size of data relocation. */
.globl _start
_start:
/* OF CIF entry point arrives in %o4 */
pic_base:
call boot_continue
mov %o4, CIF_REG
#ifndef CDBOOT
/* The offsets to these locations are defined by the
* VAS_EBOOT_BOOT_MACHINE_foo macros in include/VasEBoot/sparc64/ieee1275/boot.h,
* and VasEBoot-setup uses this to patch these next three values as needed.
*
* The boot_path will be the OF device path of the partition where the
* rest of the VAS_EBOOT kernel image resides. kernel_sector will be set to
* the location of the first block of the VAS_EBOOT kernel, and
* kernel_address is the location where we should load that first block.
*
* After loading in that block we will execute it by jumping to the
* load address plus the size of the prepended A.OUT header (32 bytes).
*
* Since this assembly code includes the 32 bytes long a.out header,
* we need to move the actual code entry point forward by the size
* of the a.out header, i.e. += VAS_EBOOT_BOOT_AOUT_HEADER_SIZE.
*/
.org VAS_EBOOT_BOOT_MACHINE_BOOT_DEVPATH + VAS_EBOOT_BOOT_AOUT_HEADER_SIZE
boot_path:
.org VAS_EBOOT_BOOT_MACHINE_KERNEL_BYTE + VAS_EBOOT_BOOT_AOUT_HEADER_SIZE
boot_path_end:
kernel_byte: .xword (2 << 9)
kernel_address: .word VAS_EBOOT_BOOT_MACHINE_KERNEL_ADDR
#else
#define boot_path (_start + 512 + SCRATCH_PAD_BOOT_SIZE)
#define boot_path_end (_start + 1024)
#include <VasEBoot/offsets.h>
.org 8 + VAS_EBOOT_BOOT_AOUT_HEADER_SIZE
kernel_byte: .xword (2 << 9)
kernel_size: .word 512
kernel_address: .word VAS_EBOOT_BOOT_SPARC64_IEEE1275_IMAGE_ADDRESS
#endif
prom_finddev_name: .asciz "finddevice"
prom_chosen_path: .asciz "/chosen"
prom_getprop_name: .asciz "getprop"
prom_stdout_name: .asciz "stdout"
prom_write_name: .asciz "write"
prom_bootpath_name: .asciz "bootpath"
prom_open_name: .asciz "open"
prom_seek_name: .asciz "seek"
prom_read_name: .asciz "read"
prom_exit_name: .asciz "exit"
VasEBoot_name: .asciz "VAS_EBOOT "
#ifdef CDBOOT
prom_close_name: .asciz "close"
#endif
#define VAS_EBOOT_NAME_LEN 5
.align 4
prom_open_error:
GET_ABS(prom_open_name, %o2)
call console_write
mov 4, %o3
/* fallthru */
prom_error:
GET_ABS(prom_exit_name, %o0)
/* fallthru */
/* %o0: OF call name
* %o1: input arg 1
*/
prom_call_1_1_o2:
clr %o2
ba prom_call_x_1
mov 1, %g1
prom_call_getprop:
mov 4, %g1
stx %g1, [%l1 + 256]
mov CHOSEN_NODE_REG, %o1
ba prom_call_x_1
GET_ABS(prom_getprop_name, %o0)
prom_call_3_1_o1:
ba prom_call_3_1
mov BOOTDEV_REG, %o1
/* %o2: message string
* %o3: message length
*/
console_write:
GET_ABS(prom_write_name, %o0)
mov STDOUT_NODE_REG, %o1
/* fallthru */
/* %o0: OF call name
* %o1: input arg 1
* %o2: input arg 2
* %o3: input arg 3
*/
prom_call_3_1:
mov 3, %g1
prom_call_x_1:
mov 1, %o5
/* fallthru */
/* %o0: OF call name
* %g1: num inputs
* %o5: num outputs
* %o1-%o4: inputs
*/
prom_call:
stx %o0, [%l1 + 0x00]
stx %g1, [%l1 + 0x08]
stx %o5, [%l1 + 0x10]
stx %o1, [%l1 + 0x18]
stx %o2, [%l1 + 0x20]
stx %o3, [%l1 + 0x28]
stx %o4, [%l1 + 0x30]
jmpl CIF_REG, %g0
mov %l1, %o0
boot_continue:
mov %o7, PIC_REG /* PIC base */
#ifndef CDBOOT
sethi %hi(SCRATCH_PAD_BOOT), %l1 /* OF argument slots */
#else
GET_ABS(_start + 512, %l1) /* OF argument slots */
#endif
/* Find the /chosen node so we can fetch the stdout handle,
* and thus perform console output.
*
* chosen_node = prom_finddevice("/chosen")
*/
GET_ABS(prom_finddev_name, %o0)
call prom_call_1_1_o2
GET_ABS(prom_chosen_path, %o1)
ldx [%l1 + 0x20], CHOSEN_NODE_REG
brz CHOSEN_NODE_REG, prom_error
/* getprop(chosen_node, "stdout", &buffer, buffer_size) */
GET_ABS(prom_stdout_name, %o2)
add %l1, 256, %o3
call prom_call_getprop
mov 1024, %o4
lduw [%l1 + 256], STDOUT_NODE_REG
brz,pn STDOUT_NODE_REG, prom_error
/* write(stdout_node, "VAS_EBOOT ", strlen("VAS_EBOOT ")) */
GET_ABS(VasEBoot_name, %o2)
call console_write
mov VAS_EBOOT_NAME_LEN, %o3
GET_ABS(boot_path, %o3)
#ifndef CDBOOT
ldub [%o3], %o1
brnz,pn %o1, bootpath_known
#endif
/* getprop(chosen_node, "bootpath", &buffer, buffer_size) */
GET_ABS(prom_bootpath_name, %o2)
call prom_call_getprop
mov (boot_path_end - boot_path), %o4
bootpath_known:
/* Open up the boot_path, and use that handle to read the
* first block of the VAS_EBOOT kernel image.
*
* bootdev_handle = open(boot_path)
*/
GET_ABS(prom_open_name, %o0)
call prom_call_1_1_o2
GET_ABS(boot_path, %o1)
ldx [%l1 + 0x20], BOOTDEV_REG
brz,pn BOOTDEV_REG, prom_open_error
/* Since we have 64-bit cells, the high cell of the seek offset
* is zero and the low cell is the entire value.
*
* seek(bootdev, 0, *kernel_byte)
*/
GET_ABS(prom_seek_name, %o0)
clr %o2
call prom_call_3_1_o1
LDX_ABS(kernel_byte, 0x00, %o3)
/* read(bootdev, *kernel_address, 512) */
GET_ABS(prom_read_name, %o0)
LDUW_ABS(kernel_address, 0x00, %o2)
call prom_call_3_1_o1
#ifdef CDBOOT
LDUW_ABS(kernel_size, 0x00, %o3)
GET_ABS(prom_close_name, %o0)
mov 1, %g1
mov 0, %o5
call prom_call
mov BOOTDEV_REG, %o1
#else
mov 512, %o3
#endif
LDUW_ABS(kernel_address, 0x00, %o2)
jmpl %o2, %o7
#ifdef CDBOOT
mov CIF_REG, %o4
#else
nop
#endif
.org VAS_EBOOT_BOOT_MACHINE_CODE_END
/* the last 4 bytes in the sector 0 contain the signature */
.word VAS_EBOOT_BOOT_MACHINE_SIGNATURE

View File

@ -0,0 +1,145 @@
/* -*-Asm-*- */
/*
* VAS_EBOOT -- GRand Unified Bootloader
* Copyright (C) 2009 Free Software Foundation, Inc.
*
* VAS_EBOOT 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.
*
* VAS_EBOOT 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 VAS_EBOOT. If not, see <http://www.gnu.org/licenses/>.
*/
#include <VasEBoot/machine/boot.h>
#include <VasEBoot/offsets.h>
.text
.align 4
.globl _start
_start:
/* First stage boot block jumps to us here. */
pic_base:
call after_info_block
mov %o7, PIC_REG
prom_write_name: .asciz "write"
prom_seek_name: .asciz "seek"
prom_read_name: .asciz "read"
prom_close_name: .asciz "close"
notification_string: .asciz "Loading kernel"
#define NOTIFICATION_STRING_LEN 14
notification_step: .asciz "."
#define NOTIFICATION_STEP_LEN 1
notification_done: .asciz "\r\n"
#define NOTIFICATION_DONE_LEN 2
.align 4
/* %o2: message string
* %o3: message length
*/
console_write:
GET_ABS(prom_write_name, %o0)
mov STDOUT_NODE_REG, %o1
/* fallthru */
/* %o0: OF call name
* %o1: input arg 1
* %o2: input arg 2
* %o3: input arg 3
*/
prom_call_3_1:
mov 3, %g1
mov 1, %o5
/* fallthru */
/* %o0: OF call name
* %g1: num inputs
* %o5: num outputs
* %o1-%o4: inputs
*/
prom_call:
stx %o0, [%l1 + 0x00]
stx %g1, [%l1 + 0x08]
stx %o5, [%l1 + 0x10]
stx %o1, [%l1 + 0x18]
stx %o2, [%l1 + 0x20]
stx %o3, [%l1 + 0x28]
stx %o4, [%l1 + 0x30]
jmpl CIF_REG, %g0
mov %l1, %o0
after_info_block:
sethi %hi(SCRATCH_PAD_DISKBOOT), %l1 /* OF argument slots */
GET_ABS(notification_string, %o2)
call console_write
mov NOTIFICATION_STRING_LEN, %o3
GET_ABS(firstlist - VAS_EBOOT_BOOT_SPARC64_IEEE1275_LIST_SIZE, %l2)
set VAS_EBOOT_BOOT_SPARC64_IEEE1275_IMAGE_ADDRESS, %l3
bootloop:
lduw [%l2 + 0x08], %o0
brz %o0, bootit
lduw [%l2 + 0x00], %o3
sllx %o3, 32, %o3
lduw [%l2 + 0x04], %o4
or %o3, %o4, %o3
GET_ABS(prom_seek_name, %o0)
mov BOOTDEV_REG, %o1
clr %o2
call prom_call_3_1
sllx %o3, 9, %o3
GET_ABS(prom_read_name, %o0)
mov BOOTDEV_REG, %o1
lduw [%l2 + 0x08], %o3
sllx %o3, 9, %o3
mov %l3, %o2
call prom_call_3_1
add %l3, %o3, %l3
GET_ABS(notification_step, %o2)
call console_write
mov NOTIFICATION_STEP_LEN, %o3
ba bootloop
sub %l2, VAS_EBOOT_BOOT_SPARC64_IEEE1275_LIST_SIZE, %l2
bootit:
GET_ABS(prom_close_name, %o0)
mov 1, %g1
mov 0, %o5
call prom_call
mov BOOTDEV_REG, %o1
GET_ABS(notification_done, %o2)
call console_write
mov NOTIFICATION_DONE_LEN, %o3
sethi %hi(VAS_EBOOT_BOOT_SPARC64_IEEE1275_IMAGE_ADDRESS), %o2
jmpl %o2 + %lo(VAS_EBOOT_BOOT_SPARC64_IEEE1275_IMAGE_ADDRESS), %o7
mov CIF_REG, %o4
1: ba,a 1b
lastlist:
.word 0
.word 0
.org (0x200 - VAS_EBOOT_BOOT_SPARC64_IEEE1275_LIST_SIZE)
blocklist_default_start:
.word 0
.word 2
blocklist_default_len:
.word 0
firstlist:

176
VasEBoot-core/bus/bonito.c Normal file
View File

@ -0,0 +1,176 @@
/* bonito.c - PCI bonito interface. */
/*
* VAS_EBOOT -- GRand Unified Bootloader
* Copyright (C) 2009 Free Software Foundation, Inc.
*
* VAS_EBOOT 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.
*
* VAS_EBOOT 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 VAS_EBOOT. If not, see <http://www.gnu.org/licenses/>.
*/
#include <VasEBoot/pci.h>
#include <VasEBoot/misc.h>
static VasEBoot_uint32_t base_win[VAS_EBOOT_MACHINE_PCI_NUM_WIN];
static const VasEBoot_size_t sizes_win[VAS_EBOOT_MACHINE_PCI_NUM_WIN] =
{VAS_EBOOT_MACHINE_PCI_WIN1_SIZE, VAS_EBOOT_MACHINE_PCI_WIN_SIZE,
VAS_EBOOT_MACHINE_PCI_WIN_SIZE};
/* Usage counters. */
static int usage_win[VAS_EBOOT_MACHINE_PCI_NUM_WIN];
static VasEBoot_addr_t addr_win[VAS_EBOOT_MACHINE_PCI_NUM_WIN] =
{VAS_EBOOT_MACHINE_PCI_WIN1_ADDR, VAS_EBOOT_MACHINE_PCI_WIN2_ADDR,
VAS_EBOOT_MACHINE_PCI_WIN3_ADDR};
VasEBoot_bonito_type_t VasEBoot_bonito_type;
static volatile void *
config_addr (VasEBoot_pci_address_t addr)
{
if (VasEBoot_bonito_type == VAS_EBOOT_BONITO_2F)
{
VAS_EBOOT_MACHINE_PCI_CONF_CTRL_REG_2F = 1 << ((addr >> 11) & 0xf);
return (volatile void *) (VAS_EBOOT_MACHINE_PCI_CONFSPACE_2F
| (addr & 0x07ff));
}
else
{
if (addr >> 16)
return (volatile void *) (VAS_EBOOT_MACHINE_PCI_CONFSPACE_3A_EXT | addr);
else
return (volatile void *) (VAS_EBOOT_MACHINE_PCI_CONFSPACE_3A | addr);
}
}
VasEBoot_uint32_t
VasEBoot_pci_read (VasEBoot_pci_address_t addr)
{
return *(volatile VasEBoot_uint32_t *) config_addr (addr);
}
VasEBoot_uint16_t
VasEBoot_pci_read_word (VasEBoot_pci_address_t addr)
{
return *(volatile VasEBoot_uint16_t *) config_addr (addr);
}
VasEBoot_uint8_t
VasEBoot_pci_read_byte (VasEBoot_pci_address_t addr)
{
return *(volatile VasEBoot_uint8_t *) config_addr (addr);
}
void
VasEBoot_pci_write (VasEBoot_pci_address_t addr, VasEBoot_uint32_t data)
{
*(volatile VasEBoot_uint32_t *) config_addr (addr) = data;
}
void
VasEBoot_pci_write_word (VasEBoot_pci_address_t addr, VasEBoot_uint16_t data)
{
*(volatile VasEBoot_uint16_t *) config_addr (addr) = data;
}
void
VasEBoot_pci_write_byte (VasEBoot_pci_address_t addr, VasEBoot_uint8_t data)
{
*(volatile VasEBoot_uint8_t *) config_addr (addr) = data;
}
static inline void
write_bases_2f (void)
{
int i;
VasEBoot_uint32_t reg = 0;
for (i = 0; i < VAS_EBOOT_MACHINE_PCI_NUM_WIN; i++)
reg |= (((base_win[i] >> VAS_EBOOT_MACHINE_PCI_WIN_SHIFT)
& VAS_EBOOT_MACHINE_PCI_WIN_MASK)
<< (i * VAS_EBOOT_MACHINE_PCI_WIN_MASK_SIZE));
VAS_EBOOT_MACHINE_PCI_IO_CTRL_REG_2F = reg;
}
volatile void *
VasEBoot_pci_device_map_range (VasEBoot_pci_device_t dev __attribute__ ((unused)),
VasEBoot_addr_t base, VasEBoot_size_t size)
{
if (VasEBoot_bonito_type == VAS_EBOOT_BONITO_2F)
{
int i;
VasEBoot_addr_t newbase;
/* First try already used registers. */
for (i = 0; i < VAS_EBOOT_MACHINE_PCI_NUM_WIN; i++)
if (usage_win[i] && base_win[i] <= base
&& base_win[i] + sizes_win[i] > base + size)
{
usage_win[i]++;
return (void *)
(addr_win[i] | (base & VAS_EBOOT_MACHINE_PCI_WIN_OFFSET_MASK));
}
/* Map new register. */
newbase = base & ~VAS_EBOOT_MACHINE_PCI_WIN_OFFSET_MASK;
for (i = 0; i < VAS_EBOOT_MACHINE_PCI_NUM_WIN; i++)
if (!usage_win[i] && newbase <= base
&& newbase + sizes_win[i] > base + size)
{
usage_win[i]++;
base_win[i] = newbase;
write_bases_2f ();
return (void *)
(addr_win[i] | (base & VAS_EBOOT_MACHINE_PCI_WIN_OFFSET_MASK));
}
VasEBoot_fatal ("Out of PCI windows.");
}
else
{
int region = 0;
if (base >= 0x10000000
&& base + size <= 0x18000000)
region = 1;
if (base >= 0x1c000000
&& base + size <= 0x1f000000)
region = 2;
if (region == 0)
VasEBoot_fatal ("Attempt to map out of regions");
return (void *) (0xa0000000 | base);
}
}
void *
VasEBoot_pci_device_map_range_cached (VasEBoot_pci_device_t dev,
VasEBoot_addr_t base, VasEBoot_size_t size)
{
return (void *) (((VasEBoot_addr_t) VasEBoot_pci_device_map_range (dev, base, size))
& ~0x20000000);
}
void
VasEBoot_pci_device_unmap_range (VasEBoot_pci_device_t dev __attribute__ ((unused)),
volatile void *mem,
VasEBoot_size_t size __attribute__ ((unused)))
{
if (VasEBoot_bonito_type == VAS_EBOOT_BONITO_2F)
{
int i;
for (i = 0; i < VAS_EBOOT_MACHINE_PCI_NUM_WIN; i++)
if (usage_win[i] && addr_win[i]
== (((VasEBoot_addr_t) mem | 0x20000000)
& ~VAS_EBOOT_MACHINE_PCI_WIN_OFFSET_MASK))
{
usage_win[i]--;
return;
}
VasEBoot_fatal ("Tried to unmap not mapped region");
}
}

382
VasEBoot-core/bus/cs5536.c Normal file
View File

@ -0,0 +1,382 @@
/*
* VAS_EBOOT -- GRand Unified Bootloader
* Copyright (C) 2010 Free Software Foundation, Inc.
*
* VAS_EBOOT 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.
*
* VAS_EBOOT 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 VAS_EBOOT. If not, see <http://www.gnu.org/licenses/>.
*/
#include <VasEBoot/types.h>
#include <VasEBoot/cs5536.h>
#include <VasEBoot/pci.h>
#include <VasEBoot/time.h>
#include <VasEBoot/ata.h>
#ifdef VAS_EBOOT_MACHINE_MIPS_LOONGSON
#include <VasEBoot/machine/kernel.h>
#endif
#include <VasEBoot/dl.h>
VAS_EBOOT_MOD_LICENSE ("GPLv3+");
/* Context for VasEBoot_cs5536_find. */
struct VasEBoot_cs5536_find_ctx
{
VasEBoot_pci_device_t *devp;
int found;
};
/* Helper for VasEBoot_cs5536_find. */
static int
VasEBoot_cs5536_find_iter (VasEBoot_pci_device_t dev, VasEBoot_pci_id_t pciid, void *data)
{
struct VasEBoot_cs5536_find_ctx *ctx = data;
if (pciid == VAS_EBOOT_CS5536_PCIID)
{
*ctx->devp = dev;
ctx->found = 1;
return 1;
}
return 0;
}
int
VasEBoot_cs5536_find (VasEBoot_pci_device_t *devp)
{
struct VasEBoot_cs5536_find_ctx ctx = {
.devp = devp,
.found = 0
};
VasEBoot_pci_iterate (VasEBoot_cs5536_find_iter, &ctx);
return ctx.found;
}
VasEBoot_uint64_t
VasEBoot_cs5536_read_msr (VasEBoot_pci_device_t dev, VasEBoot_uint32_t addr)
{
VasEBoot_uint64_t ret = 0;
VasEBoot_pci_write (VasEBoot_pci_make_address (dev, VAS_EBOOT_CS5536_MSR_MAILBOX_ADDR),
addr);
ret = (VasEBoot_uint64_t)
VasEBoot_pci_read (VasEBoot_pci_make_address (dev, VAS_EBOOT_CS5536_MSR_MAILBOX_DATA0));
ret |= (((VasEBoot_uint64_t)
VasEBoot_pci_read (VasEBoot_pci_make_address (dev,
VAS_EBOOT_CS5536_MSR_MAILBOX_DATA1)))
<< 32);
return ret;
}
void
VasEBoot_cs5536_write_msr (VasEBoot_pci_device_t dev, VasEBoot_uint32_t addr,
VasEBoot_uint64_t val)
{
VasEBoot_pci_write (VasEBoot_pci_make_address (dev, VAS_EBOOT_CS5536_MSR_MAILBOX_ADDR),
addr);
VasEBoot_pci_write (VasEBoot_pci_make_address (dev, VAS_EBOOT_CS5536_MSR_MAILBOX_DATA0),
val & 0xffffffff);
VasEBoot_pci_write (VasEBoot_pci_make_address (dev, VAS_EBOOT_CS5536_MSR_MAILBOX_DATA1),
val >> 32);
}
VasEBoot_err_t
VasEBoot_cs5536_smbus_wait (VasEBoot_port_t smbbase)
{
VasEBoot_uint64_t start = VasEBoot_get_time_ms ();
while (1)
{
VasEBoot_uint8_t status;
status = VasEBoot_inb (smbbase + VAS_EBOOT_CS5536_SMB_REG_STATUS);
if (status & VAS_EBOOT_CS5536_SMB_REG_STATUS_SDAST)
return VAS_EBOOT_ERR_NONE;
if (status & VAS_EBOOT_CS5536_SMB_REG_STATUS_BER)
return VasEBoot_error (VAS_EBOOT_ERR_IO, "SM bus error");
if (status & VAS_EBOOT_CS5536_SMB_REG_STATUS_NACK)
return VasEBoot_error (VAS_EBOOT_ERR_IO, "NACK received");
if (VasEBoot_get_time_ms () > start + 40)
return VasEBoot_error (VAS_EBOOT_ERR_IO, "SM stalled");
}
}
VasEBoot_err_t
VasEBoot_cs5536_read_spd_byte (VasEBoot_port_t smbbase, VasEBoot_uint8_t dev,
VasEBoot_uint8_t addr, VasEBoot_uint8_t *res)
{
VasEBoot_err_t err;
/* Send START. */
VasEBoot_outb (VasEBoot_inb (smbbase + VAS_EBOOT_CS5536_SMB_REG_CTRL1)
| VAS_EBOOT_CS5536_SMB_REG_CTRL1_START,
smbbase + VAS_EBOOT_CS5536_SMB_REG_CTRL1);
/* Send device address. */
err = VasEBoot_cs5536_smbus_wait (smbbase);
if (err)
return err;
VasEBoot_outb (dev << 1, smbbase + VAS_EBOOT_CS5536_SMB_REG_DATA);
/* Send ACK. */
err = VasEBoot_cs5536_smbus_wait (smbbase);
if (err)
return err;
VasEBoot_outb (VasEBoot_inb (smbbase + VAS_EBOOT_CS5536_SMB_REG_CTRL1)
| VAS_EBOOT_CS5536_SMB_REG_CTRL1_ACK,
smbbase + VAS_EBOOT_CS5536_SMB_REG_CTRL1);
/* Send byte address. */
VasEBoot_outb (addr, smbbase + VAS_EBOOT_CS5536_SMB_REG_DATA);
/* Send START. */
err = VasEBoot_cs5536_smbus_wait (smbbase);
if (err)
return err;
VasEBoot_outb (VasEBoot_inb (smbbase + VAS_EBOOT_CS5536_SMB_REG_CTRL1)
| VAS_EBOOT_CS5536_SMB_REG_CTRL1_START,
smbbase + VAS_EBOOT_CS5536_SMB_REG_CTRL1);
/* Send device address. */
err = VasEBoot_cs5536_smbus_wait (smbbase);
if (err)
return err;
VasEBoot_outb ((dev << 1) | 1, smbbase + VAS_EBOOT_CS5536_SMB_REG_DATA);
/* Send STOP. */
err = VasEBoot_cs5536_smbus_wait (smbbase);
if (err)
return err;
VasEBoot_outb (VasEBoot_inb (smbbase + VAS_EBOOT_CS5536_SMB_REG_CTRL1)
| VAS_EBOOT_CS5536_SMB_REG_CTRL1_STOP,
smbbase + VAS_EBOOT_CS5536_SMB_REG_CTRL1);
err = VasEBoot_cs5536_smbus_wait (smbbase);
if (err)
return err;
*res = VasEBoot_inb (smbbase + VAS_EBOOT_CS5536_SMB_REG_DATA);
return VAS_EBOOT_ERR_NONE;
}
VasEBoot_err_t
VasEBoot_cs5536_init_smbus (VasEBoot_pci_device_t dev, VasEBoot_uint16_t divisor,
VasEBoot_port_t *smbbase)
{
VasEBoot_uint64_t smbbar;
smbbar = VasEBoot_cs5536_read_msr (dev, VAS_EBOOT_CS5536_MSR_SMB_BAR);
/* FIXME */
if (!(smbbar & VAS_EBOOT_CS5536_LBAR_ENABLE))
return VasEBoot_error(VAS_EBOOT_ERR_IO, "SMB controller not enabled\n");
*smbbase = (smbbar & VAS_EBOOT_CS5536_LBAR_ADDR_MASK) + VAS_EBOOT_MACHINE_PCI_IO_BASE;
if (divisor < 8)
return VasEBoot_error (VAS_EBOOT_ERR_BAD_ARGUMENT, "invalid divisor");
/* Disable SMB. */
VasEBoot_outb (0, *smbbase + VAS_EBOOT_CS5536_SMB_REG_CTRL2);
/* Disable interrupts. */
VasEBoot_outb (0, *smbbase + VAS_EBOOT_CS5536_SMB_REG_CTRL1);
/* Set as master. */
VasEBoot_outb (VAS_EBOOT_CS5536_SMB_REG_ADDR_MASTER,
*smbbase + VAS_EBOOT_CS5536_SMB_REG_ADDR);
/* Launch. */
VasEBoot_outb (((divisor >> 7) & 0xff), *smbbase + VAS_EBOOT_CS5536_SMB_REG_CTRL3);
VasEBoot_outb (((divisor << 1) & 0xfe) | VAS_EBOOT_CS5536_SMB_REG_CTRL2_ENABLE,
*smbbase + VAS_EBOOT_CS5536_SMB_REG_CTRL2);
return VAS_EBOOT_ERR_NONE;
}
VasEBoot_err_t
VasEBoot_cs5536_read_spd (VasEBoot_port_t smbbase, VasEBoot_uint8_t dev,
struct VasEBoot_smbus_spd *res)
{
VasEBoot_err_t err;
VasEBoot_size_t size;
VasEBoot_uint8_t b;
VasEBoot_size_t ptr;
err = VasEBoot_cs5536_read_spd_byte (smbbase, dev, 0, &b);
if (err)
return err;
if (b == 0)
return VasEBoot_error (VAS_EBOOT_ERR_IO, "no SPD found");
size = b;
((VasEBoot_uint8_t *) res)[0] = b;
for (ptr = 1; ptr < size; ptr++)
{
err = VasEBoot_cs5536_read_spd_byte (smbbase, dev, ptr,
&((VasEBoot_uint8_t *) res)[ptr]);
if (err)
return err;
}
return VAS_EBOOT_ERR_NONE;
}
static inline void
set_io_space (VasEBoot_pci_device_t dev, int num, VasEBoot_uint16_t start,
VasEBoot_uint16_t len)
{
VasEBoot_cs5536_write_msr (dev, VAS_EBOOT_CS5536_MSR_GL_REGIONS_START + num,
((((VasEBoot_uint64_t) start + len - 4)
<< VAS_EBOOT_CS5536_MSR_GL_REGION_IO_TOP_SHIFT)
& VAS_EBOOT_CS5536_MSR_GL_REGION_TOP_MASK)
| (((VasEBoot_uint64_t) start
<< VAS_EBOOT_CS5536_MSR_GL_REGION_IO_BASE_SHIFT)
& VAS_EBOOT_CS5536_MSR_GL_REGION_BASE_MASK)
| VAS_EBOOT_CS5536_MSR_GL_REGION_IO
| VAS_EBOOT_CS5536_MSR_GL_REGION_ENABLE);
}
static inline void
set_iod (VasEBoot_pci_device_t dev, int num, int dest, int start, int mask)
{
VasEBoot_cs5536_write_msr (dev, VAS_EBOOT_CS5536_MSR_GL_IOD_START + num,
((VasEBoot_uint64_t) dest << VAS_EBOOT_CS5536_IOD_DEST_SHIFT)
| (((VasEBoot_uint64_t) start & VAS_EBOOT_CS5536_IOD_ADDR_MASK)
<< VAS_EBOOT_CS5536_IOD_BASE_SHIFT)
| ((mask & VAS_EBOOT_CS5536_IOD_ADDR_MASK)
<< VAS_EBOOT_CS5536_IOD_MASK_SHIFT));
}
static inline void
set_p2d (VasEBoot_pci_device_t dev, int num, int dest, VasEBoot_uint32_t start)
{
VasEBoot_cs5536_write_msr (dev, VAS_EBOOT_CS5536_MSR_GL_P2D_START + num,
(((VasEBoot_uint64_t) dest) << VAS_EBOOT_CS5536_P2D_DEST_SHIFT)
| ((VasEBoot_uint64_t) (start >> VAS_EBOOT_CS5536_P2D_LOG_ALIGN)
<< VAS_EBOOT_CS5536_P2D_BASE_SHIFT)
| (((1 << (32 - VAS_EBOOT_CS5536_P2D_LOG_ALIGN)) - 1)
<< VAS_EBOOT_CS5536_P2D_MASK_SHIFT));
}
void
VasEBoot_cs5536_init_geode (VasEBoot_pci_device_t dev)
{
/* Enable more BARs. */
VasEBoot_cs5536_write_msr (dev, VAS_EBOOT_CS5536_MSR_IRQ_MAP_BAR,
VAS_EBOOT_CS5536_LBAR_TURN_ON | VAS_EBOOT_CS5536_LBAR_IRQ_MAP);
VasEBoot_cs5536_write_msr (dev, VAS_EBOOT_CS5536_MSR_MFGPT_BAR,
VAS_EBOOT_CS5536_LBAR_TURN_ON | VAS_EBOOT_CS5536_LBAR_MFGPT);
VasEBoot_cs5536_write_msr (dev, VAS_EBOOT_CS5536_MSR_ACPI_BAR,
VAS_EBOOT_CS5536_LBAR_TURN_ON | VAS_EBOOT_CS5536_LBAR_ACPI);
VasEBoot_cs5536_write_msr (dev, VAS_EBOOT_CS5536_MSR_PM_BAR,
VAS_EBOOT_CS5536_LBAR_TURN_ON | VAS_EBOOT_CS5536_LBAR_PM);
/* Setup DIVIL. */
#ifdef VAS_EBOOT_MACHINE_MIPS_LOONGSON
switch (VasEBoot_arch_machine)
{
case VAS_EBOOT_ARCH_MACHINE_YEELOONG:
VasEBoot_cs5536_write_msr (dev, VAS_EBOOT_CS5536_MSR_DIVIL_LEG_IO,
VAS_EBOOT_CS5536_MSR_DIVIL_LEG_IO_MODE_X86
| VAS_EBOOT_CS5536_MSR_DIVIL_LEG_IO_F_REMAP
| VAS_EBOOT_CS5536_MSR_DIVIL_LEG_IO_RTC_ENABLE0
| VAS_EBOOT_CS5536_MSR_DIVIL_LEG_IO_RTC_ENABLE1);
break;
case VAS_EBOOT_ARCH_MACHINE_FULOONG2F:
VasEBoot_cs5536_write_msr (dev, VAS_EBOOT_CS5536_MSR_DIVIL_LEG_IO,
VAS_EBOOT_CS5536_MSR_DIVIL_LEG_IO_UART2_COM3
| VAS_EBOOT_CS5536_MSR_DIVIL_LEG_IO_UART1_COM1
| VAS_EBOOT_CS5536_MSR_DIVIL_LEG_IO_MODE_X86
| VAS_EBOOT_CS5536_MSR_DIVIL_LEG_IO_F_REMAP
| VAS_EBOOT_CS5536_MSR_DIVIL_LEG_IO_RTC_ENABLE0
| VAS_EBOOT_CS5536_MSR_DIVIL_LEG_IO_RTC_ENABLE1);
break;
}
#endif
VasEBoot_cs5536_write_msr (dev, VAS_EBOOT_CS5536_MSR_DIVIL_IRQ_MAPPER_PRIMARY_MASK,
(~VAS_EBOOT_CS5536_DIVIL_LPC_INTERRUPTS) & 0xffff);
VasEBoot_cs5536_write_msr (dev, VAS_EBOOT_CS5536_MSR_DIVIL_IRQ_MAPPER_LPC_MASK,
VAS_EBOOT_CS5536_DIVIL_LPC_INTERRUPTS);
VasEBoot_cs5536_write_msr (dev, VAS_EBOOT_CS5536_MSR_DIVIL_LPC_SERIAL_IRQ_CONTROL,
VAS_EBOOT_CS5536_MSR_DIVIL_LPC_SERIAL_IRQ_CONTROL_ENABLE);
/* Initialise USB controller. */
/* FIXME: assign adresses dynamically. */
VasEBoot_cs5536_write_msr (dev, VAS_EBOOT_CS5536_MSR_USB_OHCI_BASE,
VAS_EBOOT_CS5536_MSR_USB_BASE_BUS_MASTER
| VAS_EBOOT_CS5536_MSR_USB_BASE_MEMORY_ENABLE
| 0x05024000);
VasEBoot_cs5536_write_msr (dev, VAS_EBOOT_CS5536_MSR_USB_EHCI_BASE,
VAS_EBOOT_CS5536_MSR_USB_BASE_BUS_MASTER
| VAS_EBOOT_CS5536_MSR_USB_BASE_MEMORY_ENABLE
| (0x20ULL << VAS_EBOOT_CS5536_MSR_USB_EHCI_BASE_FLDJ_SHIFT)
| 0x05023000);
VasEBoot_cs5536_write_msr (dev, VAS_EBOOT_CS5536_MSR_USB_CONTROLLER_BASE,
VAS_EBOOT_CS5536_MSR_USB_BASE_BUS_MASTER
| VAS_EBOOT_CS5536_MSR_USB_BASE_MEMORY_ENABLE | 0x05020000);
VasEBoot_cs5536_write_msr (dev, VAS_EBOOT_CS5536_MSR_USB_OPTION_CONTROLLER_BASE,
VAS_EBOOT_CS5536_MSR_USB_BASE_MEMORY_ENABLE | 0x05022000);
set_p2d (dev, 0, VAS_EBOOT_CS5536_DESTINATION_USB, 0x05020000);
set_p2d (dev, 1, VAS_EBOOT_CS5536_DESTINATION_USB, 0x05022000);
set_p2d (dev, 5, VAS_EBOOT_CS5536_DESTINATION_USB, 0x05024000);
set_p2d (dev, 6, VAS_EBOOT_CS5536_DESTINATION_USB, 0x05023000);
{
volatile VasEBoot_uint32_t *oc;
oc = VasEBoot_absolute_pointer (VasEBoot_pci_device_map_range (dev, 0x05022000,
VAS_EBOOT_CS5536_USB_OPTION_REGS_SIZE));
oc[VAS_EBOOT_CS5536_USB_OPTION_REG_UOCMUX] =
(oc[VAS_EBOOT_CS5536_USB_OPTION_REG_UOCMUX]
& ~VAS_EBOOT_CS5536_USB_OPTION_REG_UOCMUX_PMUX_MASK)
| VAS_EBOOT_CS5536_USB_OPTION_REG_UOCMUX_PMUX_HC;
VasEBoot_pci_device_unmap_range (dev, oc, VAS_EBOOT_CS5536_USB_OPTION_REGS_SIZE);
}
/* Setup IDE controller. */
VasEBoot_cs5536_write_msr (dev, VAS_EBOOT_CS5536_MSR_IDE_IO_BAR,
VAS_EBOOT_CS5536_LBAR_IDE
| VAS_EBOOT_CS5536_MSR_IDE_IO_BAR_UNITS);
VasEBoot_cs5536_write_msr (dev, VAS_EBOOT_CS5536_MSR_IDE_CFG,
VAS_EBOOT_CS5536_MSR_IDE_CFG_CHANNEL_ENABLE);
VasEBoot_cs5536_write_msr (dev, VAS_EBOOT_CS5536_MSR_IDE_TIMING,
(VAS_EBOOT_CS5536_MSR_IDE_TIMING_PIO0
<< VAS_EBOOT_CS5536_MSR_IDE_TIMING_DRIVE0_SHIFT)
| (VAS_EBOOT_CS5536_MSR_IDE_TIMING_PIO0
<< VAS_EBOOT_CS5536_MSR_IDE_TIMING_DRIVE1_SHIFT));
VasEBoot_cs5536_write_msr (dev, VAS_EBOOT_CS5536_MSR_IDE_CAS_TIMING,
(VAS_EBOOT_CS5536_MSR_IDE_CAS_TIMING_CMD_PIO0
<< VAS_EBOOT_CS5536_MSR_IDE_CAS_TIMING_CMD_SHIFT)
| (VAS_EBOOT_CS5536_MSR_IDE_CAS_TIMING_PIO0
<< VAS_EBOOT_CS5536_MSR_IDE_CAS_TIMING_DRIVE0_SHIFT)
| (VAS_EBOOT_CS5536_MSR_IDE_CAS_TIMING_PIO0
<< VAS_EBOOT_CS5536_MSR_IDE_CAS_TIMING_DRIVE1_SHIFT));
/* Setup Geodelink PCI. */
VasEBoot_cs5536_write_msr (dev, VAS_EBOOT_CS5536_MSR_GL_PCI_CTRL,
(4ULL << VAS_EBOOT_CS5536_MSR_GL_PCI_CTRL_OUT_THR_SHIFT)
| (4ULL << VAS_EBOOT_CS5536_MSR_GL_PCI_CTRL_IN_THR_SHIFT)
| (8ULL << VAS_EBOOT_CS5536_MSR_GL_PCI_CTRL_LATENCY_SHIFT)
| VAS_EBOOT_CS5536_MSR_GL_PCI_CTRL_IO_ENABLE
| VAS_EBOOT_CS5536_MSR_GL_PCI_CTRL_MEMORY_ENABLE);
/* Setup windows. */
set_io_space (dev, 0, VAS_EBOOT_CS5536_LBAR_SMBUS, VAS_EBOOT_CS5536_SMBUS_REGS_SIZE);
set_io_space (dev, 1, VAS_EBOOT_CS5536_LBAR_GPIO, VAS_EBOOT_CS5536_GPIO_REGS_SIZE);
set_io_space (dev, 2, VAS_EBOOT_CS5536_LBAR_MFGPT, VAS_EBOOT_CS5536_MFGPT_REGS_SIZE);
set_io_space (dev, 3, VAS_EBOOT_CS5536_LBAR_IRQ_MAP, VAS_EBOOT_CS5536_IRQ_MAP_REGS_SIZE);
set_io_space (dev, 4, VAS_EBOOT_CS5536_LBAR_PM, VAS_EBOOT_CS5536_PM_REGS_SIZE);
set_io_space (dev, 5, VAS_EBOOT_CS5536_LBAR_ACPI, VAS_EBOOT_CS5536_ACPI_REGS_SIZE);
set_iod (dev, 0, VAS_EBOOT_CS5536_DESTINATION_IDE, VAS_EBOOT_ATA_CH0_PORT1, 0xffff8);
set_iod (dev, 1, VAS_EBOOT_CS5536_DESTINATION_ACC, VAS_EBOOT_CS5536_LBAR_ACC, 0xfff80);
set_iod (dev, 2, VAS_EBOOT_CS5536_DESTINATION_IDE, VAS_EBOOT_CS5536_LBAR_IDE, 0xffff0);
}

View File

@ -0,0 +1,78 @@
/* pci.c - Generic PCI interfaces. */
/*
* VAS_EBOOT -- GRand Unified Bootloader
* Copyright (C) 2007,2009 Free Software Foundation, Inc.
*
* VAS_EBOOT 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.
*
* VAS_EBOOT 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 VAS_EBOOT. If not, see <http://www.gnu.org/licenses/>.
*/
#include <VasEBoot/pci.h>
#include <VasEBoot/dl.h>
#include <VasEBoot/emu/misc.h>
#include <VasEBoot/util/misc.h>
VasEBoot_pci_address_t
VasEBoot_pci_make_address (VasEBoot_pci_device_t dev, int reg)
{
VasEBoot_pci_address_t ret;
ret.dev = dev;
ret.pos = reg;
return ret;
}
void
VasEBoot_pci_iterate (VasEBoot_pci_iteratefunc_t hook, void *hook_data)
{
struct pci_device_iterator *iter;
struct pci_slot_match slot;
struct pci_device *dev;
slot.domain = PCI_MATCH_ANY;
slot.bus = PCI_MATCH_ANY;
slot.dev = PCI_MATCH_ANY;
slot.func = PCI_MATCH_ANY;
iter = pci_slot_match_iterator_create (&slot);
while ((dev = pci_device_next (iter)))
hook (dev, dev->vendor_id | (dev->device_id << 16), hook_data);
pci_iterator_destroy (iter);
}
void *
VasEBoot_pci_device_map_range (VasEBoot_pci_device_t dev, VasEBoot_addr_t base,
VasEBoot_size_t size)
{
void *addr;
int err;
err = pci_device_map_range (dev, base, size, PCI_DEV_MAP_FLAG_WRITABLE, &addr);
if (err)
VasEBoot_util_error ("mapping 0x%llx failed (error %d)",
(unsigned long long) base, err);
return addr;
}
void
VasEBoot_pci_device_unmap_range (VasEBoot_pci_device_t dev, void *mem,
VasEBoot_size_t size)
{
pci_device_unmap_range (dev, mem, size);
}
VAS_EBOOT_MOD_INIT (emupci)
{
pci_system_init ();
}
VAS_EBOOT_MOD_FINI (emupci)
{
pci_system_cleanup ();
}

256
VasEBoot-core/bus/fdt.c Normal file
View File

@ -0,0 +1,256 @@
/*
* VAS_EBOOT -- GRand Unified Bootloader
* Copyright (C) 2016 Free Software Foundation, Inc.
*
* VAS_EBOOT 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.
*
* VAS_EBOOT 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 VAS_EBOOT. If not, see <http://www.gnu.org/licenses/>.
*/
#include <VasEBoot/fdtbus.h>
#include <VasEBoot/fdt.h>
#include <VasEBoot/term.h>
static const void *dtb;
static VasEBoot_size_t root_address_cells, root_size_cells;
/* Pointer to this symbol signals invalid mapping. */
char VasEBoot_fdtbus_invalid_mapping[1];
struct VasEBoot_fdtbus_dev *devs;
struct VasEBoot_fdtbus_driver *drivers;
int
VasEBoot_fdtbus_is_compatible (const char *compat_string,
const struct VasEBoot_fdtbus_dev *dev)
{
VasEBoot_size_t compatible_size;
const char *compatible = VasEBoot_fdt_get_prop (dtb, dev->node, "compatible",
&compatible_size);
if (!compatible)
return 0;
const char *compatible_end = compatible + compatible_size;
while (compatible < compatible_end)
{
if (VasEBoot_strcmp (compat_string, compatible) == 0)
return 1;
compatible += VasEBoot_strlen (compatible) + 1;
}
return 0;
}
static void
fdtbus_scan (struct VasEBoot_fdtbus_dev *parent)
{
int node;
for (node = VasEBoot_fdt_first_node (dtb, parent ? parent->node : 0); node >= 0;
node = VasEBoot_fdt_next_node (dtb, node))
{
struct VasEBoot_fdtbus_dev *dev;
struct VasEBoot_fdtbus_driver *driver;
dev = VasEBoot_zalloc (sizeof (*dev));
if (!dev)
{
VasEBoot_print_error ();
return;
}
dev->node = node;
dev->next = devs;
dev->parent = parent;
devs = dev;
FOR_LIST_ELEMENTS(driver, drivers)
if (!dev->driver && VasEBoot_fdtbus_is_compatible (driver->compatible, dev))
{
VasEBoot_dprintf ("fdtbus", "Attaching %s\n", driver->compatible);
if (driver->attach (dev) == VAS_EBOOT_ERR_NONE)
{
VasEBoot_dprintf ("fdtbus", "Attached %s\n", driver->compatible);
dev->driver = driver;
break;
}
VasEBoot_print_error ();
}
fdtbus_scan (dev);
}
}
void
VasEBoot_fdtbus_register (struct VasEBoot_fdtbus_driver *driver)
{
struct VasEBoot_fdtbus_dev *dev;
VasEBoot_dprintf ("fdtbus", "Registering %s\n", driver->compatible);
VasEBoot_list_push (VAS_EBOOT_AS_LIST_P (&drivers),
VAS_EBOOT_AS_LIST (driver));
for (dev = devs; dev; dev = dev->next)
if (!dev->driver && VasEBoot_fdtbus_is_compatible (driver->compatible, dev))
{
VasEBoot_dprintf ("fdtbus", "Attaching %s (%p)\n", driver->compatible, dev);
if (driver->attach (dev) == VAS_EBOOT_ERR_NONE)
{
VasEBoot_dprintf ("fdtbus", "Attached %s\n", driver->compatible);
dev->driver = driver;
}
VasEBoot_print_error ();
}
}
void
VasEBoot_fdtbus_unregister (struct VasEBoot_fdtbus_driver *driver)
{
VasEBoot_list_remove (VAS_EBOOT_AS_LIST (driver));
struct VasEBoot_fdtbus_dev *dev;
for (dev = devs; dev; dev = dev->next)
if (dev->driver == driver)
{
if (driver->detach)
driver->detach(dev);
dev->driver = 0;
}
}
void
VasEBoot_fdtbus_init (const void *dtb_in, VasEBoot_size_t size)
{
if (!dtb_in || VasEBoot_fdt_check_header (dtb_in, size) < 0)
VasEBoot_fatal ("invalid FDT");
dtb = dtb_in;
const VasEBoot_uint32_t *prop = VasEBoot_fdt_get_prop (dtb, 0, "#address-cells", 0);
if (prop)
root_address_cells = VasEBoot_be_to_cpu32 (*prop);
else
root_address_cells = 1;
prop = VasEBoot_fdt_get_prop (dtb, 0, "#size-cells", 0);
if (prop)
root_size_cells = VasEBoot_be_to_cpu32 (*prop);
else
root_size_cells = 1;
fdtbus_scan (0);
}
static int
get_address_cells (const struct VasEBoot_fdtbus_dev *dev)
{
const VasEBoot_uint32_t *prop;
if (!dev)
return root_address_cells;
prop = VasEBoot_fdt_get_prop (dtb, dev->node, "#address-cells", 0);
if (prop)
return VasEBoot_be_to_cpu32 (*prop);
return 1;
}
static int
get_size_cells (const struct VasEBoot_fdtbus_dev *dev)
{
const VasEBoot_uint32_t *prop;
if (!dev)
return root_size_cells;
prop = VasEBoot_fdt_get_prop (dtb, dev->node, "#size-cells", 0);
if (prop)
return VasEBoot_be_to_cpu32 (*prop);
return 1;
}
static VasEBoot_uint64_t
get64 (const VasEBoot_uint32_t *reg, VasEBoot_size_t cells)
{
VasEBoot_uint64_t val = 0;
if (cells >= 1)
val = VasEBoot_be_to_cpu32 (reg[cells - 1]);
if (cells >= 2)
val |= ((VasEBoot_uint64_t) VasEBoot_be_to_cpu32 (reg[cells - 2])) << 32;
return val;
}
static volatile void *
translate (const struct VasEBoot_fdtbus_dev *dev, const VasEBoot_uint32_t *reg)
{
volatile void *ret;
const VasEBoot_uint32_t *ranges;
VasEBoot_size_t ranges_size, cells_per_mapping;
VasEBoot_size_t parent_address_cells, child_address_cells, child_size_cells;
VasEBoot_size_t nmappings, i;
if (dev == 0)
{
VasEBoot_uint64_t val;
val = get64 (reg, root_address_cells);
if (sizeof (void *) == 4 && (val >> 32))
return VasEBoot_fdtbus_invalid_mapping;
return (void *) (VasEBoot_addr_t) val;
}
ranges = VasEBoot_fdt_get_prop (dtb, dev->node, "ranges", &ranges_size);
if (!ranges)
return VasEBoot_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 VasEBoot_uint32_t *child_addr = &ranges[i * cells_per_mapping];
const VasEBoot_uint32_t *parent_addr = child_addr + child_address_cells;
VasEBoot_uint64_t child_size = get64 (parent_addr + parent_address_cells, child_size_cells);
if (child_address_cells > 2 && VasEBoot_memcmp (reg, child_addr, (child_address_cells - 2) * 4) != 0)
continue;
if (get64 (reg, child_address_cells) < get64 (child_addr, child_address_cells))
continue;
VasEBoot_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 (VasEBoot_fdtbus_is_mapping_valid (ret))
ret = (volatile char *) ret + offset;
return ret;
}
return VasEBoot_fdtbus_invalid_mapping;
}
volatile void *
VasEBoot_fdtbus_map_reg (const struct VasEBoot_fdtbus_dev *dev, int regno, VasEBoot_size_t *size)
{
VasEBoot_size_t address_cells, size_cells;
address_cells = get_address_cells (dev->parent);
size_cells = get_size_cells (dev->parent);
const VasEBoot_uint32_t *reg = VasEBoot_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 *
VasEBoot_fdtbus_get_name (const struct VasEBoot_fdtbus_dev *dev)
{
return VasEBoot_fdt_get_nodename (dtb, dev->node);
}
const void *
VasEBoot_fdtbus_get_prop (const struct VasEBoot_fdtbus_dev *dev,
const char *name,
VasEBoot_uint32_t *len)
{
return VasEBoot_fdt_get_prop (dtb, dev->node, name, len);
}
const void *
VasEBoot_fdtbus_get_fdt (void)
{
return dtb;
}

View File

@ -0,0 +1,42 @@
/*
* VAS_EBOOT -- GRand Unified Bootloader
* Copyright (C) 2013 Free Software Foundation, Inc.
*
* VAS_EBOOT 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.
*
* VAS_EBOOT 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 VAS_EBOOT. If not, see <http://www.gnu.org/licenses/>.
*/
#include <VasEBoot/dl.h>
#include <VasEBoot/pci.h>
#include <VasEBoot/mm.h>
#include <VasEBoot/misc.h>
#include <VasEBoot/ieee1275/ieee1275.h>
volatile void *
VasEBoot_pci_device_map_range (VasEBoot_pci_device_t dev __attribute__ ((unused)),
VasEBoot_addr_t base,
VasEBoot_size_t size)
{
if (VasEBoot_ieee1275_test_flag (VAS_EBOOT_IEEE1275_FLAG_REAL_MODE))
return (volatile void *) base;
if (VasEBoot_ieee1275_map (base, base, size, 7))
VasEBoot_fatal ("couldn't map 0x%lx", base);
return (volatile void *) base;
}
void
VasEBoot_pci_device_unmap_range (VasEBoot_pci_device_t dev __attribute__ ((unused)),
volatile void *mem __attribute__ ((unused)),
VasEBoot_size_t size __attribute__ ((unused)))
{
}

173
VasEBoot-core/bus/pci.c Normal file
View File

@ -0,0 +1,173 @@
/* pci.c - Generic PCI interfaces. */
/*
* VAS_EBOOT -- GRand Unified Bootloader
* Copyright (C) 2007,2009 Free Software Foundation, Inc.
*
* VAS_EBOOT 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.
*
* VAS_EBOOT 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 VAS_EBOOT. If not, see <http://www.gnu.org/licenses/>.
*/
#include <VasEBoot/dl.h>
#include <VasEBoot/pci.h>
#include <VasEBoot/mm.h>
#include <VasEBoot/misc.h>
#include <VasEBoot/mm_private.h>
#include <VasEBoot/cache.h>
VAS_EBOOT_MOD_LICENSE ("GPLv3+");
/* FIXME: correctly support 64-bit architectures. */
/* #if VAS_EBOOT_TARGET_SIZEOF_VOID_P == 4 */
struct VasEBoot_pci_dma_chunk *
VasEBoot_memalign_dma32 (VasEBoot_size_t align, VasEBoot_size_t size)
{
void *ret;
if (align < 64)
align = 64;
size = ALIGN_UP (size, align);
ret = VasEBoot_memalign (align, size);
#if VAS_EBOOT_CPU_SIZEOF_VOID_P == 8
if ((VasEBoot_addr_t) ret >> 32)
{
/* Shouldn't happend since the only platform in this case is
x86_64-efi and it skips any regions > 4GiB because
of EFI bugs anyway. */
VasEBoot_error (VAS_EBOOT_ERR_BUG, "allocation outside 32-bit range");
return 0;
}
#endif
if (!ret)
return 0;
VasEBoot_arch_sync_dma_caches (ret, size);
return ret;
}
/* FIXME: evil. */
void
VasEBoot_dma_free (struct VasEBoot_pci_dma_chunk *ch)
{
VasEBoot_size_t size = (((struct VasEBoot_mm_header *) ch) - 1)->size * VAS_EBOOT_MM_ALIGN;
VasEBoot_arch_sync_dma_caches (ch, size);
VasEBoot_free (ch);
}
/* #endif */
#ifdef VAS_EBOOT_MACHINE_MIPS_LOONGSON
volatile void *
VasEBoot_dma_get_virt (struct VasEBoot_pci_dma_chunk *ch)
{
return (void *) ((((VasEBoot_uint32_t) ch) & 0x1fffffff) | 0xa0000000);
}
VasEBoot_uint32_t
VasEBoot_dma_get_phys (struct VasEBoot_pci_dma_chunk *ch)
{
return (((VasEBoot_uint32_t) ch) & 0x1fffffff) | 0x80000000;
}
#else
volatile void *
VasEBoot_dma_get_virt (struct VasEBoot_pci_dma_chunk *ch)
{
return (void *) ch;
}
VasEBoot_uint32_t
VasEBoot_dma_get_phys (struct VasEBoot_pci_dma_chunk *ch)
{
return (VasEBoot_uint32_t) (VasEBoot_addr_t) ch;
}
#endif
VasEBoot_pci_address_t
VasEBoot_pci_make_address (VasEBoot_pci_device_t dev, int reg)
{
return (1 << 31) | (dev.bus << 16) | (dev.device << 11)
| (dev.function << 8) | reg;
}
void
VasEBoot_pci_iterate (VasEBoot_pci_iteratefunc_t hook, void *hook_data)
{
VasEBoot_pci_device_t dev;
VasEBoot_pci_address_t addr;
VasEBoot_pci_id_t id;
VasEBoot_uint32_t hdr;
for (dev.bus = 0; dev.bus < VAS_EBOOT_PCI_NUM_BUS; dev.bus++)
{
for (dev.device = 0; dev.device < VAS_EBOOT_PCI_NUM_DEVICES; dev.device++)
{
for (dev.function = 0; dev.function < 8; dev.function++)
{
addr = VasEBoot_pci_make_address (dev, VAS_EBOOT_PCI_REG_PCI_ID);
id = VasEBoot_pci_read (addr);
/* Check if there is a device present. */
if (id >> 16 == 0xFFFF)
{
if (dev.function == 0)
/* Devices are required to implement function 0, so if
it's missing then there is no device here. */
break;
else
continue;
}
if (hook (dev, id, hook_data))
return;
/* Probe only func = 0 if the device if not multifunction */
if (dev.function == 0)
{
addr = VasEBoot_pci_make_address (dev, VAS_EBOOT_PCI_REG_CACHELINE);
hdr = VasEBoot_pci_read (addr);
if (!(hdr & 0x800000))
break;
}
}
}
}
}
VasEBoot_uint8_t
VasEBoot_pci_find_capability (VasEBoot_pci_device_t dev, VasEBoot_uint8_t cap)
{
VasEBoot_uint8_t pos = 0x34;
int ttl = 48;
while (ttl--)
{
VasEBoot_uint8_t id;
VasEBoot_pci_address_t addr;
addr = VasEBoot_pci_make_address (dev, pos);
pos = VasEBoot_pci_read_byte (addr);
if (pos < 0x40)
break;
pos &= ~3;
addr = VasEBoot_pci_make_address (dev, pos);
id = VasEBoot_pci_read_byte (addr);
if (id == 0xff)
break;
if (id == cap)
return pos;
pos++;
}
return 0;
}

View File

@ -0,0 +1,103 @@
/*
* VAS_EBOOT -- GRand Unified Bootloader
*
* Copyright (C) 2012 Google Inc.
* Copyright (C) 2016 Free Software Foundation, Inc.
*
* This is based on depthcharge code.
*
* VAS_EBOOT 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.
*
* VAS_EBOOT 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 VAS_EBOOT. If not, see <http://www.gnu.org/licenses/>.
*/
#include <VasEBoot/mm.h>
#include <VasEBoot/time.h>
#include <VasEBoot/misc.h>
#include <VasEBoot/fdtbus.h>
#include <VasEBoot/machine/kernel.h>
static VasEBoot_err_t
spi_send (const struct VasEBoot_fdtbus_dev *dev, const void *data, VasEBoot_size_t sz)
{
const VasEBoot_uint8_t *ptr = data, *end = ptr + sz;
volatile VasEBoot_uint32_t *spi = VasEBoot_fdtbus_map_reg (dev, 0, 0);
spi[2] = 0;
spi[1] = sz - 1;
spi[0] = ((1 << 18) | spi[0]) & ~(1 << 19);
spi[2] = 1;
while (ptr < end)
{
while (spi[9] & 2);
spi[256] = *ptr++;
}
while (spi[9] & 1);
return VAS_EBOOT_ERR_NONE;
}
static VasEBoot_err_t
spi_receive (const struct VasEBoot_fdtbus_dev *dev, void *data, VasEBoot_size_t sz)
{
VasEBoot_uint8_t *ptr = data, *end = ptr + sz;
volatile VasEBoot_uint32_t *spi = VasEBoot_fdtbus_map_reg (dev, 0, 0);
spi[2] = 0;
spi[1] = sz - 1;
spi[0] = ((1 << 19) | spi[0]) & ~(1 << 18);
spi[2] = 1;
while (ptr < end)
{
while (spi[9] & 8);
*ptr++ = spi[512];
}
while (spi[9] & 1);
return VAS_EBOOT_ERR_NONE;
}
static VasEBoot_err_t
spi_start (const struct VasEBoot_fdtbus_dev *dev)
{
volatile VasEBoot_uint32_t *spi = VasEBoot_fdtbus_map_reg (dev, 0, 0);
spi[3] = 1;
return VAS_EBOOT_ERR_NONE;
}
static void
spi_stop (const struct VasEBoot_fdtbus_dev *dev)
{
volatile VasEBoot_uint32_t *spi = VasEBoot_fdtbus_map_reg (dev, 0, 0);
spi[3] = 0;
}
static VasEBoot_err_t
spi_attach(const struct VasEBoot_fdtbus_dev *dev)
{
if (!VasEBoot_fdtbus_is_mapping_valid (VasEBoot_fdtbus_map_reg (dev, 0, 0)))
return VAS_EBOOT_ERR_IO;
return VAS_EBOOT_ERR_NONE;
}
static struct VasEBoot_fdtbus_driver spi =
{
.compatible = "rockchip,rk3288-spi",
.attach = spi_attach,
.send = spi_send,
.receive = spi_receive,
.start = spi_start,
.stop = spi_stop,
};
void
VasEBoot_rk3288_spi_init (void)
{
VasEBoot_fdtbus_register (&spi);
}

View File

@ -0,0 +1,45 @@
/* ehci.c - EHCI Support. */
/*
* VAS_EBOOT -- GRand Unified Bootloader
* Copyright (C) 2011 Free Software Foundation, Inc.
*
* VAS_EBOOT 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.
*
* VAS_EBOOT 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 VAS_EBOOT. If not, see <http://www.gnu.org/licenses/>.
*/
#include <VasEBoot/misc.h>
#include <VasEBoot/mm.h>
#include <VasEBoot/time.h>
#include <VasEBoot/usb.h>
#include <VasEBoot/fdtbus.h>
static VasEBoot_err_t
ehci_attach(const struct VasEBoot_fdtbus_dev *dev)
{
VasEBoot_dprintf ("ehci", "Found generic-ehci\n");
VasEBoot_ehci_init_device (VasEBoot_fdtbus_map_reg (dev, 0, 0));
return 0;
}
struct VasEBoot_fdtbus_driver ehci =
{
.compatible = "generic-ehci",
.attach = ehci_attach
};
void
VasEBoot_ehci_pci_scan (void)
{
VasEBoot_fdtbus_register (&ehci);
}

View File

@ -0,0 +1,208 @@
/* ehci.c - EHCI Support. */
/*
* VAS_EBOOT -- GRand Unified Bootloader
* Copyright (C) 2011 Free Software Foundation, Inc.
*
* VAS_EBOOT 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.
*
* VAS_EBOOT 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 VAS_EBOOT. If not, see <http://www.gnu.org/licenses/>.
*/
#include <VasEBoot/pci.h>
#include <VasEBoot/cpu/pci.h>
#include <VasEBoot/cs5536.h>
#include <VasEBoot/misc.h>
#include <VasEBoot/mm.h>
#include <VasEBoot/time.h>
#include <VasEBoot/usb.h>
#define VAS_EBOOT_EHCI_PCI_SBRN_REG 0x60
#define VAS_EBOOT_EHCI_ADDR_MEM_MASK (~0xff)
/* USBLEGSUP bits and related OS OWNED byte offset */
enum
{
VAS_EBOOT_EHCI_BIOS_OWNED = (1 << 16),
VAS_EBOOT_EHCI_OS_OWNED = (1 << 24)
};
/* PCI iteration function... */
static int
VasEBoot_ehci_pci_iter (VasEBoot_pci_device_t dev, VasEBoot_pci_id_t pciid,
void *data __attribute__ ((unused)))
{
volatile VasEBoot_uint32_t *regs;
VasEBoot_uint32_t base, base_h;
VasEBoot_uint32_t eecp_offset;
VasEBoot_uint32_t usblegsup = 0;
VasEBoot_uint64_t maxtime;
VasEBoot_uint32_t interf;
VasEBoot_uint32_t subclass;
VasEBoot_uint32_t class;
VasEBoot_uint8_t release;
VasEBoot_uint32_t class_code;
VasEBoot_dprintf ("ehci", "EHCI VasEBoot_ehci_pci_iter: begin\n");
if (pciid == VAS_EBOOT_CS5536_PCIID)
{
VasEBoot_uint64_t basereg;
basereg = VasEBoot_cs5536_read_msr (dev, VAS_EBOOT_CS5536_MSR_USB_EHCI_BASE);
if (!(basereg & VAS_EBOOT_CS5536_MSR_USB_BASE_MEMORY_ENABLE))
{
/* Shouldn't happen. */
VasEBoot_dprintf ("ehci", "No EHCI address is assigned\n");
return 0;
}
base = (basereg & VAS_EBOOT_CS5536_MSR_USB_BASE_ADDR_MASK);
basereg |= VAS_EBOOT_CS5536_MSR_USB_BASE_BUS_MASTER;
basereg &= ~VAS_EBOOT_CS5536_MSR_USB_BASE_PME_ENABLED;
basereg &= ~VAS_EBOOT_CS5536_MSR_USB_BASE_PME_STATUS;
basereg &= ~VAS_EBOOT_CS5536_MSR_USB_BASE_SMI_ENABLE;
VasEBoot_cs5536_write_msr (dev, VAS_EBOOT_CS5536_MSR_USB_EHCI_BASE, basereg);
}
else
{
VasEBoot_pci_address_t addr;
addr = VasEBoot_pci_make_address (dev, VAS_EBOOT_PCI_REG_CLASS);
class_code = VasEBoot_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;
VasEBoot_dprintf ("ehci", "EHCI VasEBoot_ehci_pci_iter: class OK\n");
/* Check Serial Bus Release Number */
addr = VasEBoot_pci_make_address (dev, VAS_EBOOT_EHCI_PCI_SBRN_REG);
release = VasEBoot_pci_read_byte (addr);
if (release != 0x20)
{
VasEBoot_dprintf ("ehci", "EHCI VasEBoot_ehci_pci_iter: Wrong SBRN: %0x\n",
release);
return 0;
}
VasEBoot_dprintf ("ehci", "EHCI VasEBoot_ehci_pci_iter: bus rev. num. OK\n");
/* Determine EHCI EHCC registers base address. */
addr = VasEBoot_pci_make_address (dev, VAS_EBOOT_PCI_REG_ADDRESS_REG0);
base = VasEBoot_pci_read (addr);
addr = VasEBoot_pci_make_address (dev, VAS_EBOOT_PCI_REG_ADDRESS_REG1);
base_h = VasEBoot_pci_read (addr);
/* Stop if registers are mapped above 4G - VAS_EBOOT does not currently
* work with registers mapped above 4G */
if (((base & VAS_EBOOT_PCI_ADDR_MEM_TYPE_MASK) != VAS_EBOOT_PCI_ADDR_MEM_TYPE_32)
&& (base_h != 0))
{
VasEBoot_dprintf ("ehci",
"EHCI VasEBoot_ehci_pci_iter: registers above 4G are not supported\n");
return 0;
}
base &= VAS_EBOOT_PCI_ADDR_MEM_MASK;
if (!base)
{
VasEBoot_dprintf ("ehci",
"EHCI: EHCI is not mapped\n");
return 0;
}
/* Set bus master - needed for coreboot, VMware, broken BIOSes etc. */
addr = VasEBoot_pci_make_address (dev, VAS_EBOOT_PCI_REG_COMMAND);
VasEBoot_pci_write_word(addr,
VAS_EBOOT_PCI_COMMAND_MEM_ENABLED
| VAS_EBOOT_PCI_COMMAND_BUS_MASTER
| VasEBoot_pci_read_word(addr));
VasEBoot_dprintf ("ehci", "EHCI VasEBoot_ehci_pci_iter: 32-bit EHCI OK\n");
}
VasEBoot_dprintf ("ehci", "EHCI VasEBoot_ehci_pci_iter: iobase of EHCC: %08x\n",
(base & VAS_EBOOT_EHCI_ADDR_MEM_MASK));
regs = VasEBoot_pci_device_map_range (dev,
(base & VAS_EBOOT_EHCI_ADDR_MEM_MASK),
0x100);
/* Is there EECP ? */
eecp_offset = (VasEBoot_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 != VAS_EBOOT_CS5536_PCIID && eecp_offset >= 0x40)
{
VasEBoot_pci_address_t pciaddr_eecp;
pciaddr_eecp = VasEBoot_pci_make_address (dev, eecp_offset);
usblegsup = VasEBoot_pci_read (pciaddr_eecp);
if (usblegsup & VAS_EBOOT_EHCI_BIOS_OWNED)
{
VasEBoot_boot_time ("Taking ownership of EHCI controller");
VasEBoot_dprintf ("ehci",
"EHCI VasEBoot_ehci_pci_iter: EHCI owned by: BIOS\n");
/* Ownership change - set OS_OWNED bit */
VasEBoot_pci_write (pciaddr_eecp, usblegsup | VAS_EBOOT_EHCI_OS_OWNED);
/* Ensure PCI register is written */
VasEBoot_pci_read (pciaddr_eecp);
/* Wait for finish of ownership change, EHCI specification
* doesn't say how long it can take... */
maxtime = VasEBoot_get_time_ms () + 1000;
while ((VasEBoot_pci_read (pciaddr_eecp) & VAS_EBOOT_EHCI_BIOS_OWNED)
&& (VasEBoot_get_time_ms () < maxtime));
if (VasEBoot_pci_read (pciaddr_eecp) & VAS_EBOOT_EHCI_BIOS_OWNED)
{
VasEBoot_dprintf ("ehci",
"EHCI VasEBoot_ehci_pci_iter: EHCI change ownership timeout");
/* Change ownership in "hard way" - reset BIOS ownership */
VasEBoot_pci_write (pciaddr_eecp, VAS_EBOOT_EHCI_OS_OWNED);
/* Ensure PCI register is written */
VasEBoot_pci_read (pciaddr_eecp);
}
}
else if (usblegsup & VAS_EBOOT_EHCI_OS_OWNED)
/* XXX: What to do in this case - nothing ? Can it happen ? */
VasEBoot_dprintf ("ehci", "EHCI VasEBoot_ehci_pci_iter: EHCI owned by: OS\n");
else
{
VasEBoot_dprintf ("ehci",
"EHCI VasEBoot_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 */
VasEBoot_pci_write (pciaddr_eecp, VAS_EBOOT_EHCI_OS_OWNED);
/* Ensure PCI register is written */
VasEBoot_pci_read (pciaddr_eecp);
}
/* Disable SMI, just to be sure. */
pciaddr_eecp = VasEBoot_pci_make_address (dev, eecp_offset + 4);
VasEBoot_pci_write (pciaddr_eecp, 0);
/* Ensure PCI register is written */
VasEBoot_pci_read (pciaddr_eecp);
}
VasEBoot_dprintf ("ehci", "inithw: EHCI VasEBoot_ehci_pci_iter: ownership OK\n");
VasEBoot_ehci_init_device (regs);
return 0;
}
void
VasEBoot_ehci_pci_scan (void)
{
VasEBoot_pci_iterate (VasEBoot_ehci_pci_iter, NULL);
}

1839
VasEBoot-core/bus/usb/ehci.c Normal file

File diff suppressed because it is too large Load Diff

1468
VasEBoot-core/bus/usb/ohci.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,139 @@
/*
* VAS_EBOOT -- GRand Unified Bootloader
* Copyright (C) 2000,2001,2002,2003,2004,2005,2007,2008,2009,2010 Free Software Foundation, Inc.
*
* VAS_EBOOT 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.
*
* VAS_EBOOT 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 VAS_EBOOT. If not, see <http://www.gnu.org/licenses/>.
*/
#include <VasEBoot/serial.h>
#include <VasEBoot/usbserial.h>
#include <VasEBoot/dl.h>
VAS_EBOOT_MOD_LICENSE ("GPLv3+");
void
VasEBoot_usbserial_fini (struct VasEBoot_serial_port *port)
{
port->usbdev->config[port->configno].interf[port->interfno].detach_hook = 0;
port->usbdev->config[port->configno].interf[port->interfno].attached = 0;
}
void
VasEBoot_usbserial_detach (VasEBoot_usb_device_t usbdev, int configno, int interfno)
{
static struct VasEBoot_serial_port *port;
port = usbdev->config[configno].interf[interfno].detach_data;
VasEBoot_serial_unregister (port);
}
static int usbnum = 0;
int
VasEBoot_usbserial_attach (VasEBoot_usb_device_t usbdev, int configno, int interfno,
struct VasEBoot_serial_driver *driver, int in_endp,
int out_endp)
{
struct VasEBoot_serial_port *port;
int j;
struct VasEBoot_usb_desc_if *interf;
VasEBoot_usb_err_t err = VAS_EBOOT_USB_ERR_NONE;
interf = usbdev->config[configno].interf[interfno].descif;
port = VasEBoot_zalloc (sizeof (*port));
if (!port)
{
VasEBoot_print_error ();
return 0;
}
port->name = VasEBoot_xasprintf ("usb%d", usbnum++);
if (!port->name)
{
VasEBoot_free (port);
VasEBoot_print_error ();
return 0;
}
port->usbdev = usbdev;
port->driver = driver;
for (j = 0; j < interf->endpointcnt; j++)
{
struct VasEBoot_usb_desc_endp *endp;
endp = &usbdev->config[0].interf[interfno].descendp[j];
if ((endp->endp_addr & 128) && (endp->attrib & 3) == 2
&& (in_endp == VAS_EBOOT_USB_SERIAL_ENDPOINT_LAST_MATCHING
|| in_endp == endp->endp_addr))
{
/* Bulk IN endpoint. */
port->in_endp = endp;
}
else if (!(endp->endp_addr & 128) && (endp->attrib & 3) == 2
&& (out_endp == VAS_EBOOT_USB_SERIAL_ENDPOINT_LAST_MATCHING
|| out_endp == endp->endp_addr))
{
/* Bulk OUT endpoint. */
port->out_endp = endp;
}
}
/* Configure device */
if (port->out_endp && port->in_endp)
err = VasEBoot_usb_set_configuration (usbdev, configno + 1);
if (!port->out_endp || !port->in_endp || err)
{
VasEBoot_free (port->name);
VasEBoot_free (port);
return 0;
}
port->configno = configno;
port->interfno = interfno;
VasEBoot_serial_config_defaults (port);
VasEBoot_serial_register (port);
port->usbdev->config[port->configno].interf[port->interfno].detach_hook
= VasEBoot_usbserial_detach;
port->usbdev->config[port->configno].interf[port->interfno].detach_data
= port;
return 1;
}
int
VasEBoot_usbserial_fetch (struct VasEBoot_serial_port *port, VasEBoot_size_t header_size)
{
VasEBoot_usb_err_t err;
VasEBoot_size_t actual;
if (port->bufstart < port->bufend)
return port->buf[port->bufstart++];
err = VasEBoot_usb_bulk_read_extended (port->usbdev, port->in_endp,
sizeof (port->buf), port->buf, 10,
&actual);
if (err != VAS_EBOOT_USB_ERR_NONE)
return -1;
port->bufstart = header_size;
port->bufend = actual;
if (port->bufstart >= port->bufend)
return -1;
return port->buf[port->bufstart++];
}

View File

@ -0,0 +1,218 @@
/*
* VAS_EBOOT -- GRand Unified Bootloader
* Copyright (C) 2000,2001,2002,2003,2004,2005,2007,2008,2009,2010 Free Software Foundation, Inc.
*
* VAS_EBOOT 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.
*
* VAS_EBOOT 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 VAS_EBOOT. If not, see <http://www.gnu.org/licenses/>.
*/
#include <VasEBoot/serial.h>
#include <VasEBoot/types.h>
#include <VasEBoot/dl.h>
#include <VasEBoot/misc.h>
#include <VasEBoot/mm.h>
#include <VasEBoot/usb.h>
#include <VasEBoot/usbserial.h>
#include <VasEBoot/i18n.h>
VAS_EBOOT_MOD_LICENSE ("GPLv3+");
enum
{
VAS_EBOOT_FTDI_MODEM_CTRL = 0x01,
VAS_EBOOT_FTDI_FLOW_CTRL = 0x02,
VAS_EBOOT_FTDI_SPEED_CTRL = 0x03,
VAS_EBOOT_FTDI_DATA_CTRL = 0x04
};
#define VAS_EBOOT_FTDI_MODEM_CTRL_DTRRTS 3
#define VAS_EBOOT_FTDI_FLOW_CTRL_DTRRTS 3
/* Convert speed to divisor. */
static VasEBoot_uint32_t
get_divisor (unsigned int speed)
{
unsigned int i;
/* The structure for speed vs. divisor. */
struct divisor
{
unsigned int speed;
VasEBoot_uint32_t div;
};
/* The table which lists common configurations. */
/* Computed with a division formula with 3MHz as base frequency. */
static struct divisor divisor_tab[] =
{
{ 2400, 0x04e2 },
{ 4800, 0x0271 },
{ 9600, 0x4138 },
{ 19200, 0x809c },
{ 38400, 0xc04e },
{ 57600, 0xc034 },
{ 115200, 0x001a }
};
/* Set the baud rate. */
for (i = 0; i < ARRAY_SIZE (divisor_tab); i++)
if (divisor_tab[i].speed == speed)
return divisor_tab[i].div;
return 0;
}
static void
real_config (struct VasEBoot_serial_port *port)
{
VasEBoot_uint32_t divisor;
const VasEBoot_uint16_t parities[] = {
[VAS_EBOOT_SERIAL_PARITY_NONE] = 0x0000,
[VAS_EBOOT_SERIAL_PARITY_ODD] = 0x0100,
[VAS_EBOOT_SERIAL_PARITY_EVEN] = 0x0200
};
const VasEBoot_uint16_t stop_bits[] = {
[VAS_EBOOT_SERIAL_STOP_BITS_1] = 0x0000,
[VAS_EBOOT_SERIAL_STOP_BITS_1_5] = 0x0800,
[VAS_EBOOT_SERIAL_STOP_BITS_2] = 0x1000,
};
if (port->configured)
return;
VasEBoot_usb_control_msg (port->usbdev, VAS_EBOOT_USB_REQTYPE_VENDOR_OUT,
VAS_EBOOT_FTDI_MODEM_CTRL,
port->config.rtscts ? VAS_EBOOT_FTDI_MODEM_CTRL_DTRRTS : 0,
0, 0, 0);
VasEBoot_usb_control_msg (port->usbdev, VAS_EBOOT_USB_REQTYPE_VENDOR_OUT,
VAS_EBOOT_FTDI_FLOW_CTRL,
port->config.rtscts ? VAS_EBOOT_FTDI_FLOW_CTRL_DTRRTS : 0,
0, 0, 0);
divisor = get_divisor (port->config.speed);
VasEBoot_usb_control_msg (port->usbdev, VAS_EBOOT_USB_REQTYPE_VENDOR_OUT,
VAS_EBOOT_FTDI_SPEED_CTRL,
divisor & 0xffff, divisor >> 16, 0, 0);
VasEBoot_usb_control_msg (port->usbdev, VAS_EBOOT_USB_REQTYPE_VENDOR_OUT,
VAS_EBOOT_FTDI_DATA_CTRL,
parities[port->config.parity]
| stop_bits[port->config.stop_bits]
| port->config.word_len, 0, 0, 0);
port->configured = 1;
}
/* Fetch a key. */
static int
ftdi_hw_fetch (struct VasEBoot_serial_port *port)
{
real_config (port);
return VasEBoot_usbserial_fetch (port, 2);
}
/* Put a character. */
static void
ftdi_hw_put (struct VasEBoot_serial_port *port, const int c)
{
char cc = c;
real_config (port);
VasEBoot_usb_bulk_write (port->usbdev, port->out_endp, 1, &cc);
}
static VasEBoot_err_t
ftdi_hw_configure (struct VasEBoot_serial_port *port,
struct VasEBoot_serial_config *config)
{
VasEBoot_uint16_t divisor;
divisor = get_divisor (config->speed);
if (divisor == 0)
return VasEBoot_error (VAS_EBOOT_ERR_BAD_ARGUMENT,
N_("unsupported serial port speed"));
if (config->parity != VAS_EBOOT_SERIAL_PARITY_NONE
&& config->parity != VAS_EBOOT_SERIAL_PARITY_ODD
&& config->parity != VAS_EBOOT_SERIAL_PARITY_EVEN)
return VasEBoot_error (VAS_EBOOT_ERR_BAD_ARGUMENT,
N_("unsupported serial port parity"));
if (config->stop_bits != VAS_EBOOT_SERIAL_STOP_BITS_1
&& config->stop_bits != VAS_EBOOT_SERIAL_STOP_BITS_1_5
&& config->stop_bits != VAS_EBOOT_SERIAL_STOP_BITS_2)
return VasEBoot_error (VAS_EBOOT_ERR_BAD_ARGUMENT,
N_("unsupported serial port stop bits number"));
if (config->word_len < 5 || config->word_len > 8)
return VasEBoot_error (VAS_EBOOT_ERR_BAD_ARGUMENT,
N_("unsupported serial port word length"));
port->config = *config;
port->configured = 0;
return VAS_EBOOT_ERR_NONE;
}
static struct VasEBoot_serial_driver VasEBoot_ftdi_driver =
{
.configure = ftdi_hw_configure,
.fetch = ftdi_hw_fetch,
.put = ftdi_hw_put,
.fini = VasEBoot_usbserial_fini
};
static const struct
{
VasEBoot_uint16_t vendor, product;
} products[] =
{
{0x0403, 0x6001} /* QEMU virtual USBserial. */
};
static int
VasEBoot_ftdi_attach (VasEBoot_usb_device_t usbdev, int configno, int interfno)
{
unsigned j;
for (j = 0; j < ARRAY_SIZE (products); j++)
if (usbdev->descdev.vendorid == products[j].vendor
&& usbdev->descdev.prodid == products[j].product)
break;
if (j == ARRAY_SIZE (products))
return 0;
return VasEBoot_usbserial_attach (usbdev, configno, interfno,
&VasEBoot_ftdi_driver,
VAS_EBOOT_USB_SERIAL_ENDPOINT_LAST_MATCHING,
VAS_EBOOT_USB_SERIAL_ENDPOINT_LAST_MATCHING);
}
static struct VasEBoot_usb_attach_desc attach_hook =
{
.class = 0xff,
.hook = VasEBoot_ftdi_attach
};
VAS_EBOOT_MOD_INIT(usbserial_ftdi)
{
VasEBoot_usb_register_attach_hook_class (&attach_hook);
}
VAS_EBOOT_MOD_FINI(usbserial_ftdi)
{
VasEBoot_serial_unregister_driver (&VasEBoot_ftdi_driver);
VasEBoot_usb_unregister_attach_hook_class (&attach_hook);
}

View File

@ -0,0 +1,231 @@
/*
* VAS_EBOOT -- GRand Unified Bootloader
* Copyright (C) 2000,2001,2002,2003,2004,2005,2007,2008,2009,2010 Free Software Foundation, Inc.
*
* VAS_EBOOT 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.
*
* VAS_EBOOT 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 VAS_EBOOT. If not, see <http://www.gnu.org/licenses/>.
*/
#include <VasEBoot/serial.h>
#include <VasEBoot/types.h>
#include <VasEBoot/dl.h>
#include <VasEBoot/misc.h>
#include <VasEBoot/mm.h>
#include <VasEBoot/usb.h>
#include <VasEBoot/usbserial.h>
#include <VasEBoot/i18n.h>
VAS_EBOOT_MOD_LICENSE ("GPLv3+");
/* Convert speed to divisor. */
static VasEBoot_uint32_t
is_speed_supported (unsigned int speed)
{
unsigned int i;
unsigned int supported[] = { 2400, 4800, 9600, 19200, 38400, 57600, 115200};
for (i = 0; i < ARRAY_SIZE (supported); i++)
if (supported[i] == speed)
return 1;
return 0;
}
#define VAS_EBOOT_PL2303_REQUEST_SET_CONFIG 0x20
#define VAS_EBOOT_PL2303_STOP_BITS_1 0x0
#define VAS_EBOOT_PL2303_STOP_BITS_1_5 0x1
#define VAS_EBOOT_PL2303_STOP_BITS_2 0x2
#define VAS_EBOOT_PL2303_PARITY_NONE 0
#define VAS_EBOOT_PL2303_PARITY_ODD 1
#define VAS_EBOOT_PL2303_PARITY_EVEN 2
struct VasEBoot_pl2303_config
{
VasEBoot_uint32_t speed;
VasEBoot_uint8_t stop_bits;
VasEBoot_uint8_t parity;
VasEBoot_uint8_t word_len;
} VAS_EBOOT_PACKED;
static void
real_config (struct VasEBoot_serial_port *port)
{
struct VasEBoot_pl2303_config config_pl2303;
char xx;
if (port->configured)
return;
VasEBoot_usb_control_msg (port->usbdev, VAS_EBOOT_USB_REQTYPE_VENDOR_IN,
1, 0x8484, 0, 1, &xx);
VasEBoot_usb_control_msg (port->usbdev, VAS_EBOOT_USB_REQTYPE_VENDOR_OUT,
1, 0x0404, 0, 0, 0);
VasEBoot_usb_control_msg (port->usbdev, VAS_EBOOT_USB_REQTYPE_VENDOR_IN,
1, 0x8484, 0, 1, &xx);
VasEBoot_usb_control_msg (port->usbdev, VAS_EBOOT_USB_REQTYPE_VENDOR_IN,
1, 0x8383, 0, 1, &xx);
VasEBoot_usb_control_msg (port->usbdev, VAS_EBOOT_USB_REQTYPE_VENDOR_IN,
1, 0x8484, 0, 1, &xx);
VasEBoot_usb_control_msg (port->usbdev, VAS_EBOOT_USB_REQTYPE_VENDOR_OUT,
1, 0x0404, 1, 0, 0);
VasEBoot_usb_control_msg (port->usbdev, VAS_EBOOT_USB_REQTYPE_VENDOR_IN,
1, 0x8484, 0, 1, &xx);
VasEBoot_usb_control_msg (port->usbdev, VAS_EBOOT_USB_REQTYPE_VENDOR_IN,
1, 0x8383, 0, 1, &xx);
VasEBoot_usb_control_msg (port->usbdev, VAS_EBOOT_USB_REQTYPE_VENDOR_OUT,
1, 0, 1, 0, 0);
VasEBoot_usb_control_msg (port->usbdev, VAS_EBOOT_USB_REQTYPE_VENDOR_OUT,
1, 1, 0, 0, 0);
VasEBoot_usb_control_msg (port->usbdev, VAS_EBOOT_USB_REQTYPE_VENDOR_OUT,
1, 2, 0x44, 0, 0);
VasEBoot_usb_control_msg (port->usbdev, VAS_EBOOT_USB_REQTYPE_VENDOR_OUT,
1, 8, 0, 0, 0);
VasEBoot_usb_control_msg (port->usbdev, VAS_EBOOT_USB_REQTYPE_VENDOR_OUT,
1, 9, 0, 0, 0);
if (port->config.stop_bits == VAS_EBOOT_SERIAL_STOP_BITS_2)
config_pl2303.stop_bits = VAS_EBOOT_PL2303_STOP_BITS_2;
else if (port->config.stop_bits == VAS_EBOOT_SERIAL_STOP_BITS_1_5)
config_pl2303.stop_bits = VAS_EBOOT_PL2303_STOP_BITS_1_5;
else
config_pl2303.stop_bits = VAS_EBOOT_PL2303_STOP_BITS_1;
switch (port->config.parity)
{
case VAS_EBOOT_SERIAL_PARITY_NONE:
config_pl2303.parity = VAS_EBOOT_PL2303_PARITY_NONE;
break;
case VAS_EBOOT_SERIAL_PARITY_ODD:
config_pl2303.parity = VAS_EBOOT_PL2303_PARITY_ODD;
break;
case VAS_EBOOT_SERIAL_PARITY_EVEN:
config_pl2303.parity = VAS_EBOOT_PL2303_PARITY_EVEN;
break;
}
config_pl2303.word_len = port->config.word_len;
config_pl2303.speed = port->config.speed;
VasEBoot_usb_control_msg (port->usbdev, VAS_EBOOT_USB_REQTYPE_CLASS_INTERFACE_OUT,
VAS_EBOOT_PL2303_REQUEST_SET_CONFIG, 0, 0,
sizeof (config_pl2303), (char *) &config_pl2303);
VasEBoot_usb_control_msg (port->usbdev, VAS_EBOOT_USB_REQTYPE_CLASS_INTERFACE_OUT,
0x22, 3, 0, 0, 0);
VasEBoot_usb_control_msg (port->usbdev, VAS_EBOOT_USB_REQTYPE_VENDOR_OUT,
1, 0, port->config.rtscts ? 0x61 : 0, 0, 0);
port->configured = 1;
}
/* Fetch a key. */
static int
pl2303_hw_fetch (struct VasEBoot_serial_port *port)
{
real_config (port);
return VasEBoot_usbserial_fetch (port, 0);
}
/* Put a character. */
static void
pl2303_hw_put (struct VasEBoot_serial_port *port, const int c)
{
char cc = c;
real_config (port);
VasEBoot_usb_bulk_write (port->usbdev, port->out_endp, 1, &cc);
}
static VasEBoot_err_t
pl2303_hw_configure (struct VasEBoot_serial_port *port,
struct VasEBoot_serial_config *config)
{
if (!is_speed_supported (config->speed))
return VasEBoot_error (VAS_EBOOT_ERR_BAD_ARGUMENT,
N_("unsupported serial port speed"));
if (config->parity != VAS_EBOOT_SERIAL_PARITY_NONE
&& config->parity != VAS_EBOOT_SERIAL_PARITY_ODD
&& config->parity != VAS_EBOOT_SERIAL_PARITY_EVEN)
return VasEBoot_error (VAS_EBOOT_ERR_BAD_ARGUMENT,
N_("unsupported serial port parity"));
if (config->stop_bits != VAS_EBOOT_SERIAL_STOP_BITS_1
&& config->stop_bits != VAS_EBOOT_SERIAL_STOP_BITS_1_5
&& config->stop_bits != VAS_EBOOT_SERIAL_STOP_BITS_2)
return VasEBoot_error (VAS_EBOOT_ERR_BAD_ARGUMENT,
N_("unsupported serial port stop bits number"));
if (config->word_len < 5 || config->word_len > 8)
return VasEBoot_error (VAS_EBOOT_ERR_BAD_ARGUMENT,
N_("unsupported serial port word length"));
port->config = *config;
port->configured = 0;
return VAS_EBOOT_ERR_NONE;
}
static struct VasEBoot_serial_driver VasEBoot_pl2303_driver =
{
.configure = pl2303_hw_configure,
.fetch = pl2303_hw_fetch,
.put = pl2303_hw_put,
.fini = VasEBoot_usbserial_fini
};
static const struct
{
VasEBoot_uint16_t vendor, product;
} products[] =
{
{0x067b, 0x2303}
};
static int
VasEBoot_pl2303_attach (VasEBoot_usb_device_t usbdev, int configno, int interfno)
{
unsigned j;
for (j = 0; j < ARRAY_SIZE (products); j++)
if (usbdev->descdev.vendorid == products[j].vendor
&& usbdev->descdev.prodid == products[j].product)
break;
if (j == ARRAY_SIZE (products))
return 0;
return VasEBoot_usbserial_attach (usbdev, configno, interfno,
&VasEBoot_pl2303_driver,
VAS_EBOOT_USB_SERIAL_ENDPOINT_LAST_MATCHING,
VAS_EBOOT_USB_SERIAL_ENDPOINT_LAST_MATCHING);
}
static struct VasEBoot_usb_attach_desc attach_hook =
{
.class = 0xff,
.hook = VasEBoot_pl2303_attach
};
VAS_EBOOT_MOD_INIT(usbserial_pl2303)
{
VasEBoot_usb_register_attach_hook_class (&attach_hook);
}
VAS_EBOOT_MOD_FINI(usbserial_pl2303)
{
VasEBoot_serial_unregister_driver (&VasEBoot_pl2303_driver);
VasEBoot_usb_unregister_attach_hook_class (&attach_hook);
}

View File

@ -0,0 +1,93 @@
/*
* VAS_EBOOT -- GRand Unified Bootloader
* Copyright (C) 2000,2001,2002,2003,2004,2005,2007,2008,2009,2010,2013 Free Software Foundation, Inc.
*
* VAS_EBOOT 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.
*
* VAS_EBOOT 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 VAS_EBOOT. If not, see <http://www.gnu.org/licenses/>.
*/
#include <VasEBoot/serial.h>
#include <VasEBoot/types.h>
#include <VasEBoot/dl.h>
#include <VasEBoot/misc.h>
#include <VasEBoot/mm.h>
#include <VasEBoot/usb.h>
#include <VasEBoot/usbserial.h>
#include <VasEBoot/i18n.h>
VAS_EBOOT_MOD_LICENSE ("GPLv3+");
/* Fetch a key. */
static int
usbdebug_late_hw_fetch (struct VasEBoot_serial_port *port)
{
return VasEBoot_usbserial_fetch (port, 0);
}
/* Put a character. */
static void
usbdebug_late_hw_put (struct VasEBoot_serial_port *port, const int c)
{
char cc = c;
VasEBoot_usb_bulk_write (port->usbdev, port->out_endp, 1, &cc);
}
static VasEBoot_err_t
usbdebug_late_hw_configure (struct VasEBoot_serial_port *port __attribute__ ((unused)),
struct VasEBoot_serial_config *config __attribute__ ((unused)))
{
return VAS_EBOOT_ERR_NONE;
}
static struct VasEBoot_serial_driver VasEBoot_usbdebug_late_driver =
{
.configure = usbdebug_late_hw_configure,
.fetch = usbdebug_late_hw_fetch,
.put = usbdebug_late_hw_put,
.fini = VasEBoot_usbserial_fini
};
static int
VasEBoot_usbdebug_late_attach (VasEBoot_usb_device_t usbdev, int configno, int interfno)
{
VasEBoot_usb_err_t err;
struct VasEBoot_usb_desc_debug debugdesc;
err = VasEBoot_usb_get_descriptor (usbdev, VAS_EBOOT_USB_DESCRIPTOR_DEBUG, configno,
sizeof (debugdesc), (char *) &debugdesc);
if (err)
return 0;
return VasEBoot_usbserial_attach (usbdev, configno, interfno,
&VasEBoot_usbdebug_late_driver,
debugdesc.in_endp, debugdesc.out_endp);
}
static struct VasEBoot_usb_attach_desc attach_hook =
{
.class = 0xff,
.hook = VasEBoot_usbdebug_late_attach
};
VAS_EBOOT_MOD_INIT(usbserial_usbdebug_late)
{
VasEBoot_usb_register_attach_hook_class (&attach_hook);
}
VAS_EBOOT_MOD_FINI(usbserial_usbdebug_late)
{
VasEBoot_serial_unregister_driver (&VasEBoot_usbdebug_late_driver);
VasEBoot_usb_unregister_attach_hook_class (&attach_hook);
}

View File

@ -0,0 +1,871 @@
/* uhci.c - UHCI Support. */
/*
* VAS_EBOOT -- GRand Unified Bootloader
* Copyright (C) 2008 Free Software Foundation, Inc.
*
* VAS_EBOOT 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.
*
* VAS_EBOOT 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 VAS_EBOOT. If not, see <http://www.gnu.org/licenses/>.
*/
#include <VasEBoot/dl.h>
#include <VasEBoot/mm.h>
#include <VasEBoot/misc.h>
#include <VasEBoot/usb.h>
#include <VasEBoot/usbtrans.h>
#include <VasEBoot/pci.h>
#include <VasEBoot/cpu/io.h>
#include <VasEBoot/time.h>
#include <VasEBoot/cpu/pci.h>
#include <VasEBoot/disk.h>
VAS_EBOOT_MOD_LICENSE ("GPLv3+");
#define VAS_EBOOT_UHCI_IOMASK (0x7FF << 5)
#define N_QH 256
#define N_TD 640
typedef enum
{
VAS_EBOOT_UHCI_REG_USBCMD = 0x00,
VAS_EBOOT_UHCI_REG_USBINTR = 0x04,
VAS_EBOOT_UHCI_REG_FLBASEADD = 0x08,
VAS_EBOOT_UHCI_REG_PORTSC1 = 0x10,
VAS_EBOOT_UHCI_REG_PORTSC2 = 0x12,
VAS_EBOOT_UHCI_REG_USBLEGSUP = 0xc0
} VasEBoot_uhci_reg_t;
enum
{
VAS_EBOOT_UHCI_DETECT_CHANGED = (1 << 1),
VAS_EBOOT_UHCI_DETECT_HAVE_DEVICE = 1,
VAS_EBOOT_UHCI_DETECT_LOW_SPEED = (1 << 8)
};
/* R/WC legacy support bits */
enum
{
VAS_EBOOT_UHCI_LEGSUP_END_A20GATE = (1 << 15),
VAS_EBOOT_UHCI_TRAP_BY_64H_WSTAT = (1 << 11),
VAS_EBOOT_UHCI_TRAP_BY_64H_RSTAT = (1 << 10),
VAS_EBOOT_UHCI_TRAP_BY_60H_WSTAT = (1 << 9),
VAS_EBOOT_UHCI_TRAP_BY_60H_RSTAT = (1 << 8)
};
/* Reset all legacy support - clear all R/WC bits and all R/W bits */
#define VAS_EBOOT_UHCI_RESET_LEGSUP_SMI ( VAS_EBOOT_UHCI_LEGSUP_END_A20GATE \
| VAS_EBOOT_UHCI_TRAP_BY_64H_WSTAT \
| VAS_EBOOT_UHCI_TRAP_BY_64H_RSTAT \
| VAS_EBOOT_UHCI_TRAP_BY_60H_WSTAT \
| VAS_EBOOT_UHCI_TRAP_BY_60H_RSTAT )
/* Some UHCI commands */
#define VAS_EBOOT_UHCI_CMD_RUN_STOP (1 << 0)
#define VAS_EBOOT_UHCI_CMD_HCRESET (1 << 1)
#define VAS_EBOOT_UHCI_CMD_MAXP (1 << 7)
/* Important bits in structures */
#define VAS_EBOOT_UHCI_LINK_TERMINATE 1
#define VAS_EBOOT_UHCI_LINK_QUEUE_HEAD 2
enum
{
VAS_EBOOT_UHCI_REG_PORTSC_CONNECT_CHANGED = 0x0002,
VAS_EBOOT_UHCI_REG_PORTSC_PORT_ENABLED = 0x0004,
VAS_EBOOT_UHCI_REG_PORTSC_RESUME = 0x0040,
VAS_EBOOT_UHCI_REG_PORTSC_RESET = 0x0200,
VAS_EBOOT_UHCI_REG_PORTSC_SUSPEND = 0x1000,
VAS_EBOOT_UHCI_REG_PORTSC_RW = VAS_EBOOT_UHCI_REG_PORTSC_PORT_ENABLED
| VAS_EBOOT_UHCI_REG_PORTSC_RESUME | VAS_EBOOT_UHCI_REG_PORTSC_RESET
| VAS_EBOOT_UHCI_REG_PORTSC_SUSPEND,
/* These bits should not be written as 1 unless we really need it */
VAS_EBOOT_UHCI_PORTSC_RWC = ((1 << 1) | (1 << 3) | (1 << 11) | (3 << 13))
};
/* UHCI Queue Head. */
struct VasEBoot_uhci_qh
{
/* Queue head link pointer which points to the next queue head. */
VasEBoot_uint32_t linkptr;
/* Queue element link pointer which points to the first data object
within the queue. */
VasEBoot_uint32_t elinkptr;
/* Queue heads are aligned on 16 bytes, pad so a queue head is 16
bytes so we can store many in a 4K page. */
VasEBoot_uint8_t pad[8];
} VAS_EBOOT_PACKED;
/* UHCI Transfer Descriptor. */
struct VasEBoot_uhci_td
{
/* Pointer to the next TD in the list. */
VasEBoot_uint32_t linkptr;
/* Control and status bits. */
VasEBoot_uint32_t ctrl_status;
/* All information required to transfer the Token packet. */
VasEBoot_uint32_t token;
/* A pointer to the data buffer, UHCI requires this pointer to be 32
bits. */
VasEBoot_uint32_t buffer;
/* Another linkptr that is not overwritten by the Host Controller.
This is VAS_EBOOT specific. */
VasEBoot_uint32_t linkptr2;
/* 3 additional 32 bits words reserved for the Host Controller Driver. */
VasEBoot_uint32_t data[3];
} VAS_EBOOT_PACKED;
typedef volatile struct VasEBoot_uhci_td *VasEBoot_uhci_td_t;
typedef volatile struct VasEBoot_uhci_qh *VasEBoot_uhci_qh_t;
struct VasEBoot_uhci
{
VasEBoot_port_t iobase;
volatile VasEBoot_uint32_t *framelist_virt;
VasEBoot_uint32_t framelist_phys;
struct VasEBoot_pci_dma_chunk *framelist_chunk;
/* N_QH Queue Heads. */
struct VasEBoot_pci_dma_chunk *qh_chunk;
volatile VasEBoot_uhci_qh_t qh_virt;
VasEBoot_uint32_t qh_phys;
/* N_TD Transfer Descriptors. */
struct VasEBoot_pci_dma_chunk *td_chunk;
volatile VasEBoot_uhci_td_t td_virt;
VasEBoot_uint32_t td_phys;
/* Free Transfer Descriptors. */
VasEBoot_uhci_td_t tdfree;
int qh_busy[N_QH];
struct VasEBoot_uhci *next;
};
static struct VasEBoot_uhci *uhci;
static VasEBoot_uint16_t
VasEBoot_uhci_readreg16 (struct VasEBoot_uhci *u, VasEBoot_uhci_reg_t reg)
{
return VasEBoot_inw (u->iobase + reg);
}
#if 0
static VasEBoot_uint32_t
VasEBoot_uhci_readreg32 (struct VasEBoot_uhci *u, VasEBoot_uhci_reg_t reg)
{
return VasEBoot_inl (u->iobase + reg);
}
#endif
static void
VasEBoot_uhci_writereg16 (struct VasEBoot_uhci *u,
VasEBoot_uhci_reg_t reg, VasEBoot_uint16_t val)
{
VasEBoot_outw (val, u->iobase + reg);
}
static void
VasEBoot_uhci_writereg32 (struct VasEBoot_uhci *u,
VasEBoot_uhci_reg_t reg, VasEBoot_uint32_t val)
{
VasEBoot_outl (val, u->iobase + reg);
}
/* Iterate over all PCI devices. Determine if a device is an UHCI
controller. If this is the case, initialize it. */
static int
VasEBoot_uhci_pci_iter (VasEBoot_pci_device_t dev,
VasEBoot_pci_id_t pciid __attribute__((unused)),
void *data __attribute__ ((unused)))
{
VasEBoot_uint32_t class_code;
VasEBoot_uint32_t class;
VasEBoot_uint32_t subclass;
VasEBoot_uint32_t interf;
VasEBoot_uint32_t base;
VasEBoot_uint32_t fp;
VasEBoot_pci_address_t addr;
struct VasEBoot_uhci *u;
int i;
addr = VasEBoot_pci_make_address (dev, VAS_EBOOT_PCI_REG_CLASS);
class_code = VasEBoot_pci_read (addr) >> 8;
interf = class_code & 0xFF;
subclass = (class_code >> 8) & 0xFF;
class = class_code >> 16;
/* If this is not an UHCI controller, just return. */
if (class != 0x0c || subclass != 0x03 || interf != 0x00)
return 0;
/* Determine IO base address. */
addr = VasEBoot_pci_make_address (dev, VAS_EBOOT_PCI_REG_ADDRESS_REG4);
base = VasEBoot_pci_read (addr);
/* Stop if there is no IO space base address defined. */
if ((base & VAS_EBOOT_PCI_ADDR_SPACE_MASK) != VAS_EBOOT_PCI_ADDR_SPACE_IO)
return 0;
if ((base & VAS_EBOOT_UHCI_IOMASK) == 0)
return 0;
/* Set bus master - needed for coreboot or broken BIOSes */
addr = VasEBoot_pci_make_address (dev, VAS_EBOOT_PCI_REG_COMMAND);
VasEBoot_pci_write_word(addr, VAS_EBOOT_PCI_COMMAND_IO_ENABLED
| VAS_EBOOT_PCI_COMMAND_BUS_MASTER
| VAS_EBOOT_PCI_COMMAND_MEM_ENABLED
| VasEBoot_pci_read_word (addr));
VasEBoot_dprintf ("uhci", "base = %x\n", base);
/* Allocate memory for the controller and register it. */
u = VasEBoot_zalloc (sizeof (*u));
if (! u)
return 1;
u->iobase = (base & VAS_EBOOT_UHCI_IOMASK) + VAS_EBOOT_MACHINE_PCI_IO_BASE;
/* Reset PIRQ and SMI */
addr = VasEBoot_pci_make_address (dev, VAS_EBOOT_UHCI_REG_USBLEGSUP);
VasEBoot_pci_write_word(addr, VAS_EBOOT_UHCI_RESET_LEGSUP_SMI);
/* Reset the HC */
VasEBoot_uhci_writereg16(u, VAS_EBOOT_UHCI_REG_USBCMD, VAS_EBOOT_UHCI_CMD_HCRESET);
VasEBoot_millisleep(5);
/* Disable interrupts and commands (just to be safe) */
VasEBoot_uhci_writereg16(u, VAS_EBOOT_UHCI_REG_USBINTR, 0);
/* Finish HC reset, HC remains disabled */
VasEBoot_uhci_writereg16(u, VAS_EBOOT_UHCI_REG_USBCMD, 0);
/* Read back to be sure PCI write is done */
VasEBoot_uhci_readreg16(u, VAS_EBOOT_UHCI_REG_USBCMD);
/* Reserve a page for the frame list. */
u->framelist_chunk = VasEBoot_memalign_dma32 (4096, 4096);
if (! u->framelist_chunk)
goto fail;
u->framelist_virt = VasEBoot_dma_get_virt (u->framelist_chunk);
u->framelist_phys = VasEBoot_dma_get_phys (u->framelist_chunk);
VasEBoot_dprintf ("uhci",
"class=0x%02x 0x%02x interface 0x%02x base=0x%x framelist=%p\n",
class, subclass, interf, u->iobase, u->framelist_virt);
/* The QH pointer of UHCI is only 32 bits, make sure this
code works on on 64 bits architectures. */
u->qh_chunk = VasEBoot_memalign_dma32 (4096, sizeof(struct VasEBoot_uhci_qh) * N_QH);
if (! u->qh_chunk)
goto fail;
u->qh_virt = VasEBoot_dma_get_virt (u->qh_chunk);
u->qh_phys = VasEBoot_dma_get_phys (u->qh_chunk);
/* The TD pointer of UHCI is only 32 bits, make sure this
code works on on 64 bits architectures. */
u->td_chunk = VasEBoot_memalign_dma32 (4096, sizeof(struct VasEBoot_uhci_td) * N_TD);
if (! u->td_chunk)
goto fail;
u->td_virt = VasEBoot_dma_get_virt (u->td_chunk);
u->td_phys = VasEBoot_dma_get_phys (u->td_chunk);
VasEBoot_dprintf ("uhci", "QH=%p, TD=%p\n",
u->qh_virt, u->td_virt);
/* Link all Transfer Descriptors in a list of available Transfer
Descriptors. */
for (i = 0; i < N_TD; i++)
u->td_virt[i].linkptr = u->td_phys + (i + 1) * sizeof(struct VasEBoot_uhci_td);
u->td_virt[N_TD - 2].linkptr = 0;
u->tdfree = u->td_virt;
/* Setup the frame list pointers. Since no isochronous transfers
are and will be supported, they all point to the (same!) queue
head. */
fp = u->qh_phys & (~15);
/* Mark this as a queue head. */
fp |= 2;
for (i = 0; i < 1024; i++)
u->framelist_virt[i] = fp;
/* Program the framelist address into the UHCI controller. */
VasEBoot_uhci_writereg32 (u, VAS_EBOOT_UHCI_REG_FLBASEADD, u->framelist_phys);
/* Make the Queue Heads point to each other. */
for (i = 0; i < N_QH; i++)
{
/* Point to the next QH. */
u->qh_virt[i].linkptr = ((u->qh_phys
+ (i + 1) * sizeof(struct VasEBoot_uhci_qh))
& (~15));
/* This is a QH. */
u->qh_virt[i].linkptr |= VAS_EBOOT_UHCI_LINK_QUEUE_HEAD;
/* For the moment, do not point to a Transfer Descriptor. These
are set at transfer time, so just terminate it. */
u->qh_virt[i].elinkptr = 1;
}
/* The last Queue Head should terminate. */
u->qh_virt[N_QH - 1].linkptr = 1;
/* Enable UHCI again. */
VasEBoot_uhci_writereg16 (u, VAS_EBOOT_UHCI_REG_USBCMD,
VAS_EBOOT_UHCI_CMD_RUN_STOP | VAS_EBOOT_UHCI_CMD_MAXP);
/* UHCI is initialized and ready for transfers. */
VasEBoot_dprintf ("uhci", "UHCI initialized\n");
#if 0
{
int i;
for (i = 0; i < 10; i++)
{
VasEBoot_uint16_t frnum;
frnum = VasEBoot_uhci_readreg16 (u, 6);
VasEBoot_dprintf ("uhci", "Framenum=%d\n", frnum);
VasEBoot_millisleep (100);
}
}
#endif
/* Link to uhci now that initialisation is successful. */
u->next = uhci;
uhci = u;
return 0;
fail:
if (u)
{
VasEBoot_dma_free (u->qh_chunk);
VasEBoot_dma_free (u->framelist_chunk);
}
VasEBoot_free (u);
return 1;
}
static void
VasEBoot_uhci_inithw (void)
{
VasEBoot_pci_iterate (VasEBoot_uhci_pci_iter, NULL);
}
static VasEBoot_uhci_td_t
VasEBoot_alloc_td (struct VasEBoot_uhci *u)
{
VasEBoot_uhci_td_t ret;
/* Check if there is a Transfer Descriptor available. */
if (! u->tdfree)
return NULL;
ret = u->tdfree;
u->tdfree = VasEBoot_dma_phys2virt (u->tdfree->linkptr, u->td_chunk);
return ret;
}
static void
VasEBoot_free_td (struct VasEBoot_uhci *u, VasEBoot_uhci_td_t td)
{
td->linkptr = VasEBoot_dma_virt2phys (u->tdfree, u->td_chunk);
u->tdfree = td;
}
static void
VasEBoot_free_queue (struct VasEBoot_uhci *u, VasEBoot_uhci_qh_t qh, VasEBoot_uhci_td_t td,
VasEBoot_usb_transfer_t transfer, VasEBoot_size_t *actual)
{
int i; /* Index of TD in transfer */
u->qh_busy[qh - u->qh_virt] = 0;
*actual = 0;
/* Free the TDs in this queue and set last_trans. */
for (i=0; td; i++)
{
VasEBoot_uhci_td_t tdprev;
VasEBoot_dprintf ("uhci", "Freeing %p\n", td);
/* Check state of TD and possibly set last_trans */
if (transfer && (td->linkptr & 1))
transfer->last_trans = i;
*actual += (td->ctrl_status + 1) & 0x7ff;
/* Unlink the queue. */
tdprev = td;
if (!td->linkptr2)
td = 0;
else
td = VasEBoot_dma_phys2virt (td->linkptr2, u->td_chunk);
/* Free the TD. */
VasEBoot_free_td (u, tdprev);
}
}
static VasEBoot_uhci_qh_t
VasEBoot_alloc_qh (struct VasEBoot_uhci *u,
VasEBoot_transaction_type_t tr __attribute__((unused)))
{
int i;
VasEBoot_uhci_qh_t qh;
/* Look for a Queue Head for this transfer. Skip the first QH if
this is a Interrupt Transfer. */
#if 0
if (tr == VAS_EBOOT_USB_TRANSACTION_TYPE_INTERRUPT)
i = 0;
else
#endif
i = 1;
for (; i < N_QH; i++)
{
if (!u->qh_busy[i])
break;
}
qh = &u->qh_virt[i];
if (i == N_QH)
{
VasEBoot_error (VAS_EBOOT_ERR_OUT_OF_MEMORY,
"no free queue heads available");
return NULL;
}
u->qh_busy[qh - u->qh_virt] = 1;
return qh;
}
static VasEBoot_uhci_td_t
VasEBoot_uhci_transaction (struct VasEBoot_uhci *u, unsigned int endp,
VasEBoot_transfer_type_t type, unsigned int addr,
unsigned int toggle, VasEBoot_size_t size,
VasEBoot_uint32_t data, VasEBoot_usb_speed_t speed)
{
VasEBoot_uhci_td_t td;
static const unsigned int tf[] = { 0x69, 0xE1, 0x2D };
/* XXX: Check if data is <4GB. If it isn't, just copy stuff around.
This is only relevant for 64 bits architectures. */
/* Grab a free Transfer Descriptor and initialize it. */
td = VasEBoot_alloc_td (u);
if (! td)
{
VasEBoot_error (VAS_EBOOT_ERR_OUT_OF_MEMORY,
"no transfer descriptors available for UHCI transfer");
return 0;
}
VasEBoot_dprintf ("uhci",
"transaction: endp=%d, type=%d, addr=%d, toggle=%d, size=%lu data=0x%x td=%p\n",
endp, type, addr, toggle, (unsigned long) size, data, td);
/* Don't point to any TD, just terminate. */
td->linkptr = 1;
/* Active! Only retry a transfer 3 times. */
td->ctrl_status = (1 << 23) | (3 << 27) |
((speed == VAS_EBOOT_USB_SPEED_LOW) ? (1 << 26) : 0);
/* If zero bytes are transmitted, size is 0x7FF. Otherwise size is
size-1. */
if (size == 0)
size = 0x7FF;
else
size = size - 1;
/* Setup whatever is required for the token packet. */
td->token = ((size << 21) | (toggle << 19) | (endp << 15)
| (addr << 8) | tf[type]);
td->buffer = data;
return td;
}
struct VasEBoot_uhci_transfer_controller_data
{
VasEBoot_uhci_qh_t qh;
VasEBoot_uhci_td_t td_first;
};
static VasEBoot_usb_err_t
VasEBoot_uhci_setup_transfer (VasEBoot_usb_controller_t dev,
VasEBoot_usb_transfer_t transfer)
{
struct VasEBoot_uhci *u = (struct VasEBoot_uhci *) dev->data;
VasEBoot_uhci_td_t td;
VasEBoot_uhci_td_t td_prev = NULL;
int i;
struct VasEBoot_uhci_transfer_controller_data *cdata;
cdata = VasEBoot_malloc (sizeof (*cdata));
if (!cdata)
return VAS_EBOOT_USB_ERR_INTERNAL;
cdata->td_first = NULL;
/* Allocate a queue head for the transfer queue. */
cdata->qh = VasEBoot_alloc_qh (u, VAS_EBOOT_USB_TRANSACTION_TYPE_CONTROL);
if (! cdata->qh)
{
VasEBoot_free (cdata);
return VAS_EBOOT_USB_ERR_INTERNAL;
}
VasEBoot_dprintf ("uhci", "transfer, iobase:%08x\n", u->iobase);
for (i = 0; i < transfer->transcnt; i++)
{
VasEBoot_usb_transaction_t tr = &transfer->transactions[i];
td = VasEBoot_uhci_transaction (u, transfer->endpoint & 15, tr->pid,
transfer->devaddr, tr->toggle,
tr->size, tr->data,
transfer->dev->speed);
if (! td)
{
VasEBoot_size_t actual = 0;
/* Terminate and free. */
if (td_prev)
{
td_prev->linkptr2 = 0;
td_prev->linkptr = 1;
}
if (cdata->td_first)
VasEBoot_free_queue (u, cdata->qh, cdata->td_first, NULL, &actual);
VasEBoot_free (cdata);
return VAS_EBOOT_USB_ERR_INTERNAL;
}
if (! cdata->td_first)
cdata->td_first = td;
else
{
td_prev->linkptr2 = VasEBoot_dma_virt2phys (td, u->td_chunk);
td_prev->linkptr = VasEBoot_dma_virt2phys (td, u->td_chunk);
td_prev->linkptr |= 4;
}
td_prev = td;
}
td_prev->linkptr2 = 0;
td_prev->linkptr = 1;
VasEBoot_dprintf ("uhci", "setup transaction %d\n", transfer->type);
/* Link it into the queue and terminate. Now the transaction can
take place. */
cdata->qh->elinkptr = VasEBoot_dma_virt2phys (cdata->td_first, u->td_chunk);
VasEBoot_dprintf ("uhci", "initiate transaction\n");
transfer->controller_data = cdata;
return VAS_EBOOT_USB_ERR_NONE;
}
static VasEBoot_usb_err_t
VasEBoot_uhci_check_transfer (VasEBoot_usb_controller_t dev,
VasEBoot_usb_transfer_t transfer,
VasEBoot_size_t *actual)
{
struct VasEBoot_uhci *u = (struct VasEBoot_uhci *) dev->data;
VasEBoot_uhci_td_t errtd;
struct VasEBoot_uhci_transfer_controller_data *cdata = transfer->controller_data;
*actual = 0;
if (cdata->qh->elinkptr & ~0x0f)
errtd = VasEBoot_dma_phys2virt (cdata->qh->elinkptr & ~0x0f, u->qh_chunk);
else
errtd = 0;
if (errtd)
{
VasEBoot_dprintf ("uhci", ">t status=0x%02x data=0x%02x td=%p, %x\n",
errtd->ctrl_status, errtd->buffer & (~15), errtd,
cdata->qh->elinkptr);
}
/* Check if the transaction completed. */
if (cdata->qh->elinkptr & 1)
{
VasEBoot_dprintf ("uhci", "transaction complete\n");
/* Place the QH back in the free list and deallocate the associated
TDs. */
cdata->qh->elinkptr = 1;
VasEBoot_free_queue (u, cdata->qh, cdata->td_first, transfer, actual);
VasEBoot_free (cdata);
return VAS_EBOOT_USB_ERR_NONE;
}
if (errtd && !(errtd->ctrl_status & (1 << 23)))
{
VasEBoot_usb_err_t err = VAS_EBOOT_USB_ERR_NONE;
/* Check if the endpoint is stalled. */
if (errtd->ctrl_status & (1 << 22))
err = VAS_EBOOT_USB_ERR_STALL;
/* Check if an error related to the data buffer occurred. */
else if (errtd->ctrl_status & (1 << 21))
err = VAS_EBOOT_USB_ERR_DATA;
/* Check if a babble error occurred. */
else if (errtd->ctrl_status & (1 << 20))
err = VAS_EBOOT_USB_ERR_BABBLE;
/* Check if a NAK occurred. */
else if (errtd->ctrl_status & (1 << 19))
err = VAS_EBOOT_USB_ERR_NAK;
/* Check if a timeout occurred. */
else if (errtd->ctrl_status & (1 << 18))
err = VAS_EBOOT_USB_ERR_TIMEOUT;
/* Check if a bitstuff error occurred. */
else if (errtd->ctrl_status & (1 << 17))
err = VAS_EBOOT_USB_ERR_BITSTUFF;
if (err)
{
VasEBoot_dprintf ("uhci", "transaction failed\n");
/* Place the QH back in the free list and deallocate the associated
TDs. */
cdata->qh->elinkptr = 1;
VasEBoot_free_queue (u, cdata->qh, cdata->td_first, transfer, actual);
VasEBoot_free (cdata);
return err;
}
}
/* Fall through, no errors occurred, so the QH might be
updated. */
VasEBoot_dprintf ("uhci", "transaction fallthrough\n");
return VAS_EBOOT_USB_ERR_WAIT;
}
static VasEBoot_usb_err_t
VasEBoot_uhci_cancel_transfer (VasEBoot_usb_controller_t dev,
VasEBoot_usb_transfer_t transfer)
{
struct VasEBoot_uhci *u = (struct VasEBoot_uhci *) dev->data;
VasEBoot_size_t actual;
struct VasEBoot_uhci_transfer_controller_data *cdata = transfer->controller_data;
VasEBoot_dprintf ("uhci", "transaction cancel\n");
/* Place the QH back in the free list and deallocate the associated
TDs. */
cdata->qh->elinkptr = 1;
VasEBoot_free_queue (u, cdata->qh, cdata->td_first, transfer, &actual);
VasEBoot_free (cdata);
return VAS_EBOOT_USB_ERR_NONE;
}
static int
VasEBoot_uhci_iterate (VasEBoot_usb_controller_iterate_hook_t hook, void *hook_data)
{
struct VasEBoot_uhci *u;
struct VasEBoot_usb_controller dev;
for (u = uhci; u; u = u->next)
{
dev.data = u;
if (hook (&dev, hook_data))
return 1;
}
return 0;
}
static VasEBoot_usb_err_t
VasEBoot_uhci_portstatus (VasEBoot_usb_controller_t dev,
unsigned int port, unsigned int enable)
{
struct VasEBoot_uhci *u = (struct VasEBoot_uhci *) dev->data;
int reg;
unsigned int status;
VasEBoot_uint64_t endtime;
VasEBoot_dprintf ("uhci", "portstatus, iobase:%08x\n", u->iobase);
VasEBoot_dprintf ("uhci", "enable=%d port=%d\n", enable, port);
if (port == 0)
reg = VAS_EBOOT_UHCI_REG_PORTSC1;
else if (port == 1)
reg = VAS_EBOOT_UHCI_REG_PORTSC2;
else
return VAS_EBOOT_USB_ERR_INTERNAL;
status = VasEBoot_uhci_readreg16 (u, reg);
VasEBoot_dprintf ("uhci", "detect=0x%02x\n", status);
if (!enable) /* We don't need reset port */
{
/* Disable the port. */
VasEBoot_uhci_writereg16 (u, reg, 0 << 2);
VasEBoot_dprintf ("uhci", "waiting for the port to be disabled\n");
endtime = VasEBoot_get_time_ms () + 1000;
while ((VasEBoot_uhci_readreg16 (u, reg) & (1 << 2)))
if (VasEBoot_get_time_ms () > endtime)
return VAS_EBOOT_USB_ERR_TIMEOUT;
status = VasEBoot_uhci_readreg16 (u, reg);
VasEBoot_dprintf ("uhci", ">3detect=0x%02x\n", status);
return VAS_EBOOT_USB_ERR_NONE;
}
/* Reset the port. */
status = VasEBoot_uhci_readreg16 (u, reg) & ~VAS_EBOOT_UHCI_PORTSC_RWC;
VasEBoot_uhci_writereg16 (u, reg, status | (1 << 9));
VasEBoot_uhci_readreg16 (u, reg); /* Ensure it is writen... */
/* Wait for the reset to complete. XXX: How long exactly? */
VasEBoot_millisleep (50); /* For root hub should be nominaly 50ms */
status = VasEBoot_uhci_readreg16 (u, reg) & ~VAS_EBOOT_UHCI_PORTSC_RWC;
VasEBoot_uhci_writereg16 (u, reg, status & ~(1 << 9));
VasEBoot_uhci_readreg16 (u, reg); /* Ensure it is writen... */
/* Note: some debug prints were removed because they affected reset/enable timing. */
VasEBoot_millisleep (1); /* Probably not needed at all or only few microsecs. */
/* Reset bits Connect & Enable Status Change */
status = VasEBoot_uhci_readreg16 (u, reg) & ~VAS_EBOOT_UHCI_PORTSC_RWC;
VasEBoot_uhci_writereg16 (u, reg, status | (1 << 3) | VAS_EBOOT_UHCI_REG_PORTSC_CONNECT_CHANGED);
VasEBoot_uhci_readreg16 (u, reg); /* Ensure it is writen... */
/* Enable the port. */
status = VasEBoot_uhci_readreg16 (u, reg) & ~VAS_EBOOT_UHCI_PORTSC_RWC;
VasEBoot_uhci_writereg16 (u, reg, status | (1 << 2));
VasEBoot_uhci_readreg16 (u, reg); /* Ensure it is writen... */
endtime = VasEBoot_get_time_ms () + 1000;
while (! ((status = VasEBoot_uhci_readreg16 (u, reg)) & (1 << 2)))
if (VasEBoot_get_time_ms () > endtime)
return VAS_EBOOT_USB_ERR_TIMEOUT;
/* Reset recovery time */
VasEBoot_millisleep (10);
/* Read final port status */
status = VasEBoot_uhci_readreg16 (u, reg);
VasEBoot_dprintf ("uhci", ">3detect=0x%02x\n", status);
return VAS_EBOOT_USB_ERR_NONE;
}
static VasEBoot_usb_speed_t
VasEBoot_uhci_detect_dev (VasEBoot_usb_controller_t dev, int port, int *changed)
{
struct VasEBoot_uhci *u = (struct VasEBoot_uhci *) dev->data;
int reg;
unsigned int status;
VasEBoot_dprintf ("uhci", "detect_dev, iobase:%08x\n", u->iobase);
if (port == 0)
reg = VAS_EBOOT_UHCI_REG_PORTSC1;
else if (port == 1)
reg = VAS_EBOOT_UHCI_REG_PORTSC2;
else
return VAS_EBOOT_USB_SPEED_NONE;
status = VasEBoot_uhci_readreg16 (u, reg);
VasEBoot_dprintf ("uhci", "detect=0x%02x port=%d\n", status, port);
/* Connect Status Change bit - it detects change of connection */
if (status & VAS_EBOOT_UHCI_DETECT_CHANGED)
{
*changed = 1;
/* Reset bit Connect Status Change */
VasEBoot_uhci_writereg16 (u, reg, (status & VAS_EBOOT_UHCI_REG_PORTSC_RW)
| VAS_EBOOT_UHCI_REG_PORTSC_CONNECT_CHANGED);
}
else
*changed = 0;
if (! (status & VAS_EBOOT_UHCI_DETECT_HAVE_DEVICE))
return VAS_EBOOT_USB_SPEED_NONE;
else if (status & VAS_EBOOT_UHCI_DETECT_LOW_SPEED)
return VAS_EBOOT_USB_SPEED_LOW;
else
return VAS_EBOOT_USB_SPEED_FULL;
}
static int
VasEBoot_uhci_hubports (VasEBoot_usb_controller_t dev __attribute__((unused)))
{
/* The root hub has exactly two ports. */
return 2;
}
static struct VasEBoot_usb_controller_dev usb_controller =
{
.name = "uhci",
.iterate = VasEBoot_uhci_iterate,
.setup_transfer = VasEBoot_uhci_setup_transfer,
.check_transfer = VasEBoot_uhci_check_transfer,
.cancel_transfer = VasEBoot_uhci_cancel_transfer,
.hubports = VasEBoot_uhci_hubports,
.portstatus = VasEBoot_uhci_portstatus,
.detect_dev = VasEBoot_uhci_detect_dev,
/* estimated max. count of TDs for one bulk transfer */
.max_bulk_tds = N_TD * 3 / 4
};
VAS_EBOOT_MOD_INIT(uhci)
{
VasEBoot_stop_disk_firmware ();
VasEBoot_uhci_inithw ();
VasEBoot_usb_controller_dev_register (&usb_controller);
VasEBoot_dprintf ("uhci", "registered\n");
}
VAS_EBOOT_MOD_FINI(uhci)
{
struct VasEBoot_uhci *u;
/* Disable all UHCI controllers. */
for (u = uhci; u; u = u->next)
VasEBoot_uhci_writereg16 (u, VAS_EBOOT_UHCI_REG_USBCMD, 0);
/* Unregister the controller. */
VasEBoot_usb_controller_dev_unregister (&usb_controller);
}

346
VasEBoot-core/bus/usb/usb.c Normal file
View File

@ -0,0 +1,346 @@
/* usb.c - Generic USB interfaces. */
/*
* VAS_EBOOT -- GRand Unified Bootloader
* Copyright (C) 2008 Free Software Foundation, Inc.
*
* VAS_EBOOT 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.
*
* VAS_EBOOT 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 VAS_EBOOT. If not, see <http://www.gnu.org/licenses/>.
*/
#include <VasEBoot/dl.h>
#include <VasEBoot/mm.h>
#include <VasEBoot/usb.h>
#include <VasEBoot/misc.h>
#include <VasEBoot/list.h>
#include <VasEBoot/term.h>
VAS_EBOOT_MOD_LICENSE ("GPLv3+");
static struct VasEBoot_usb_attach_desc *attach_hooks;
#if 0
/* Context for VasEBoot_usb_controller_iterate. */
struct VasEBoot_usb_controller_iterate_ctx
{
VasEBoot_usb_controller_iterate_hook_t hook;
void *hook_data;
VasEBoot_usb_controller_dev_t p;
};
/* Helper for VasEBoot_usb_controller_iterate. */
static int
VasEBoot_usb_controller_iterate_iter (VasEBoot_usb_controller_t dev, void *data)
{
struct VasEBoot_usb_controller_iterate_ctx *ctx = data;
dev->dev = ctx->p;
if (ctx->hook (dev, ctx->hook_data))
return 1;
return 0;
}
int
VasEBoot_usb_controller_iterate (VasEBoot_usb_controller_iterate_hook_t hook,
void *hook_data)
{
struct VasEBoot_usb_controller_iterate_ctx ctx = {
.hook = hook,
.hook_data = hook_data
};
/* Iterate over all controller drivers. */
for (ctx.p = VasEBoot_usb_list; ctx.p; ctx.p = ctx.p->next)
{
/* Iterate over the busses of the controllers. XXX: Actually, a
hub driver should do this. */
if (ctx.p->iterate (VasEBoot_usb_controller_iterate_iter, &ctx))
return 1;
}
return 0;
}
#endif
VasEBoot_usb_err_t
VasEBoot_usb_clear_halt (VasEBoot_usb_device_t dev, int endpoint)
{
if (endpoint >= VAS_EBOOT_USB_MAX_TOGGLE)
return VAS_EBOOT_USB_ERR_BADDEVICE;
dev->toggle[endpoint] = 0;
return VasEBoot_usb_control_msg (dev, (VAS_EBOOT_USB_REQTYPE_OUT
| VAS_EBOOT_USB_REQTYPE_STANDARD
| VAS_EBOOT_USB_REQTYPE_TARGET_ENDP),
VAS_EBOOT_USB_REQ_CLEAR_FEATURE,
VAS_EBOOT_USB_FEATURE_ENDP_HALT,
endpoint, 0, 0);
}
VasEBoot_usb_err_t
VasEBoot_usb_set_configuration (VasEBoot_usb_device_t dev, int configuration)
{
VasEBoot_memset (dev->toggle, 0, sizeof (dev->toggle));
return VasEBoot_usb_control_msg (dev, (VAS_EBOOT_USB_REQTYPE_OUT
| VAS_EBOOT_USB_REQTYPE_STANDARD
| VAS_EBOOT_USB_REQTYPE_TARGET_DEV),
VAS_EBOOT_USB_REQ_SET_CONFIGURATION, configuration,
0, 0, NULL);
}
VasEBoot_usb_err_t
VasEBoot_usb_get_descriptor (VasEBoot_usb_device_t dev,
VasEBoot_uint8_t type, VasEBoot_uint8_t index,
VasEBoot_size_t size, char *data)
{
return VasEBoot_usb_control_msg (dev, (VAS_EBOOT_USB_REQTYPE_IN
| VAS_EBOOT_USB_REQTYPE_STANDARD
| VAS_EBOOT_USB_REQTYPE_TARGET_DEV),
VAS_EBOOT_USB_REQ_GET_DESCRIPTOR,
(type << 8) | index,
0, size, data);
}
VasEBoot_usb_err_t
VasEBoot_usb_device_initialize (VasEBoot_usb_device_t dev)
{
struct VasEBoot_usb_desc_device *descdev;
struct VasEBoot_usb_desc_config config;
VasEBoot_usb_err_t err;
int i;
/* First we have to read first 8 bytes only and determine
* max. size of packet */
dev->descdev.maxsize0 = 0; /* invalidating, for safety only, can be removed if it is sure it is zero here */
err = VasEBoot_usb_get_descriptor (dev, VAS_EBOOT_USB_DESCRIPTOR_DEVICE,
0, 8, (char *) &dev->descdev);
if (err)
return err;
/* Now we have valid value in dev->descdev.maxsize0,
* so we can read whole device descriptor */
err = VasEBoot_usb_get_descriptor (dev, VAS_EBOOT_USB_DESCRIPTOR_DEVICE,
0, sizeof (struct VasEBoot_usb_desc_device),
(char *) &dev->descdev);
if (err)
return err;
descdev = &dev->descdev;
for (i = 0; i < VAS_EBOOT_USB_MAX_CONF; i++)
dev->config[i].descconf = NULL;
if (descdev->configcnt == 0 || descdev->configcnt > VAS_EBOOT_USB_MAX_CONF)
{
err = VAS_EBOOT_USB_ERR_BADDEVICE;
goto fail;
}
for (i = 0; i < descdev->configcnt; i++)
{
int pos;
int currif;
char *data;
struct VasEBoot_usb_desc *desc;
/* First just read the first 4 bytes of the configuration
descriptor, after that it is known how many bytes really have
to be read. */
err = VasEBoot_usb_get_descriptor (dev, VAS_EBOOT_USB_DESCRIPTOR_CONFIG, i, 4,
(char *) &config);
data = VasEBoot_malloc (config.totallen);
if (! data)
{
err = VAS_EBOOT_USB_ERR_INTERNAL;
goto fail;
}
dev->config[i].descconf = (struct VasEBoot_usb_desc_config *) data;
err = VasEBoot_usb_get_descriptor (dev, VAS_EBOOT_USB_DESCRIPTOR_CONFIG, i,
config.totallen, data);
if (err)
goto fail;
/* Skip the configuration descriptor. */
pos = dev->config[i].descconf->length;
if (dev->config[i].descconf->numif > VAS_EBOOT_USB_MAX_IF)
{
err = VAS_EBOOT_USB_ERR_BADDEVICE;
goto fail;
}
/* Read all interfaces. */
for (currif = 0; currif < dev->config[i].descconf->numif; currif++)
{
while (pos < config.totallen)
{
desc = (struct VasEBoot_usb_desc *)&data[pos];
if (desc->type == VAS_EBOOT_USB_DESCRIPTOR_INTERFACE)
break;
if (!desc->length)
{
err = VAS_EBOOT_USB_ERR_BADDEVICE;
goto fail;
}
pos += desc->length;
}
dev->config[i].interf[currif].descif
= (struct VasEBoot_usb_desc_if *) &data[pos];
pos += dev->config[i].interf[currif].descif->length;
while (pos < config.totallen)
{
desc = (struct VasEBoot_usb_desc *)&data[pos];
if (desc->type == VAS_EBOOT_USB_DESCRIPTOR_ENDPOINT)
break;
if (!desc->length)
{
err = VAS_EBOOT_USB_ERR_BADDEVICE;
goto fail;
}
pos += desc->length;
}
/* Point to the first endpoint. */
dev->config[i].interf[currif].descendp
= (struct VasEBoot_usb_desc_endp *) &data[pos];
pos += (sizeof (struct VasEBoot_usb_desc_endp)
* dev->config[i].interf[currif].descif->endpointcnt);
}
}
return VAS_EBOOT_USB_ERR_NONE;
fail:
for (i = 0; i < VAS_EBOOT_USB_MAX_CONF; i++)
VasEBoot_free (dev->config[i].descconf);
return err;
}
void VasEBoot_usb_device_attach (VasEBoot_usb_device_t dev)
{
int i;
/* XXX: Just check configuration 0 for now. */
for (i = 0; i < dev->config[0].descconf->numif; i++)
{
struct VasEBoot_usb_desc_if *interf;
struct VasEBoot_usb_attach_desc *desc;
interf = dev->config[0].interf[i].descif;
VasEBoot_dprintf ("usb", "iterate: interf=%d, class=%d, subclass=%d, protocol=%d\n",
i, interf->class, interf->subclass, interf->protocol);
if (dev->config[0].interf[i].attached)
continue;
for (desc = attach_hooks; desc; desc = desc->next)
if (interf->class == desc->class)
{
VasEBoot_boot_time ("Probing USB device driver class %x", desc->class);
if (desc->hook (dev, 0, i))
dev->config[0].interf[i].attached = 1;
VasEBoot_boot_time ("Probed USB device driver class %x", desc->class);
}
if (dev->config[0].interf[i].attached)
continue;
switch (interf->class)
{
case VAS_EBOOT_USB_CLASS_MASS_STORAGE:
VasEBoot_dl_load ("usbms");
VasEBoot_print_error ();
break;
case VAS_EBOOT_USB_CLASS_HID:
VasEBoot_dl_load ("usb_keyboard");
VasEBoot_print_error ();
break;
case 0xff:
/* FIXME: don't load useless modules. */
VasEBoot_dl_load ("usbserial_ftdi");
VasEBoot_print_error ();
VasEBoot_dl_load ("usbserial_pl2303");
VasEBoot_print_error ();
VasEBoot_dl_load ("usbserial_usbdebug");
VasEBoot_print_error ();
break;
}
}
}
/* Helper for VasEBoot_usb_register_attach_hook_class. */
static int
VasEBoot_usb_register_attach_hook_class_iter (VasEBoot_usb_device_t usbdev, void *data)
{
struct VasEBoot_usb_attach_desc *desc = data;
struct VasEBoot_usb_desc_device *descdev = &usbdev->descdev;
int i;
if (descdev->class != 0 || descdev->subclass || descdev->protocol != 0
|| descdev->configcnt == 0)
return 0;
/* XXX: Just check configuration 0 for now. */
for (i = 0; i < usbdev->config[0].descconf->numif; i++)
{
struct VasEBoot_usb_desc_if *interf;
interf = usbdev->config[0].interf[i].descif;
VasEBoot_dprintf ("usb", "iterate: interf=%d, class=%d, subclass=%d, protocol=%d\n",
i, interf->class, interf->subclass, interf->protocol);
if (usbdev->config[0].interf[i].attached)
continue;
if (interf->class != desc->class)
continue;
if (desc->hook (usbdev, 0, i))
usbdev->config[0].interf[i].attached = 1;
}
return 0;
}
void
VasEBoot_usb_register_attach_hook_class (struct VasEBoot_usb_attach_desc *desc)
{
desc->next = attach_hooks;
attach_hooks = desc;
VasEBoot_usb_iterate (VasEBoot_usb_register_attach_hook_class_iter, desc);
}
void
VasEBoot_usb_unregister_attach_hook_class (struct VasEBoot_usb_attach_desc *desc)
{
VasEBoot_list_remove (VAS_EBOOT_AS_LIST (desc));
}
VAS_EBOOT_MOD_INIT(usb)
{
VasEBoot_term_poll_usb = VasEBoot_usb_poll_devices;
}
VAS_EBOOT_MOD_FINI(usb)
{
VasEBoot_term_poll_usb = NULL;
}

View File

@ -0,0 +1,756 @@
/* usb.c - USB Hub Support. */
/*
* VAS_EBOOT -- GRand Unified Bootloader
* Copyright (C) 2008 Free Software Foundation, Inc.
*
* VAS_EBOOT 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.
*
* VAS_EBOOT 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 VAS_EBOOT. If not, see <http://www.gnu.org/licenses/>.
*/
#include <VasEBoot/dl.h>
#include <VasEBoot/mm.h>
#include <VasEBoot/usb.h>
#include <VasEBoot/misc.h>
#include <VasEBoot/time.h>
#define VAS_EBOOT_USBHUB_MAX_DEVICES 128
/* USB Supports 127 devices, with device 0 as special case. */
static struct VasEBoot_usb_device *VasEBoot_usb_devs[VAS_EBOOT_USBHUB_MAX_DEVICES];
static int rescan = 0;
static int npending = 0;
struct VasEBoot_usb_hub
{
struct VasEBoot_usb_hub *next;
VasEBoot_usb_controller_t controller;
int nports;
struct VasEBoot_usb_device **devices;
struct VasEBoot_usb_hub_port *ports;
VasEBoot_usb_device_t dev;
};
static struct VasEBoot_usb_hub *hubs;
static VasEBoot_usb_controller_dev_t VasEBoot_usb_list;
/* Add a device that currently has device number 0 and resides on
CONTROLLER, the Hub reported that the device speed is SPEED. */
static VasEBoot_usb_device_t
VasEBoot_usb_hub_add_dev (VasEBoot_usb_controller_t controller,
VasEBoot_usb_speed_t speed,
int split_hubport, int split_hubaddr)
{
VasEBoot_usb_device_t dev;
int i;
VasEBoot_usb_err_t err;
VasEBoot_boot_time ("Attaching USB device");
dev = VasEBoot_zalloc (sizeof (struct VasEBoot_usb_device));
if (! dev)
return NULL;
dev->controller = *controller;
dev->speed = speed;
dev->split_hubport = split_hubport;
dev->split_hubaddr = split_hubaddr;
err = VasEBoot_usb_device_initialize (dev);
if (err)
{
VasEBoot_free (dev);
return NULL;
}
/* Assign a new address to the device. */
for (i = 1; i < VAS_EBOOT_USBHUB_MAX_DEVICES; i++)
{
if (! VasEBoot_usb_devs[i])
break;
}
if (i == VAS_EBOOT_USBHUB_MAX_DEVICES)
{
VasEBoot_error (VAS_EBOOT_ERR_IO, "can't assign address to USB device");
for (i = 0; i < VAS_EBOOT_USB_MAX_CONF; i++)
VasEBoot_free (dev->config[i].descconf);
VasEBoot_free (dev);
return NULL;
}
err = VasEBoot_usb_control_msg (dev,
(VAS_EBOOT_USB_REQTYPE_OUT
| VAS_EBOOT_USB_REQTYPE_STANDARD
| VAS_EBOOT_USB_REQTYPE_TARGET_DEV),
VAS_EBOOT_USB_REQ_SET_ADDRESS,
i, 0, 0, NULL);
if (err)
{
for (i = 0; i < VAS_EBOOT_USB_MAX_CONF; i++)
VasEBoot_free (dev->config[i].descconf);
VasEBoot_free (dev);
return NULL;
}
dev->addr = i;
dev->initialized = 1;
VasEBoot_usb_devs[i] = dev;
VasEBoot_dprintf ("usb", "Added new usb device: %p, addr=%d\n",
dev, i);
VasEBoot_dprintf ("usb", "speed=%d, split_hubport=%d, split_hubaddr=%d\n",
speed, split_hubport, split_hubaddr);
/* Wait "recovery interval", spec. says 2ms */
VasEBoot_millisleep (2);
VasEBoot_boot_time ("Probing USB device driver");
VasEBoot_usb_device_attach (dev);
VasEBoot_boot_time ("Attached USB device");
return dev;
}
static VasEBoot_usb_err_t
VasEBoot_usb_add_hub (VasEBoot_usb_device_t dev)
{
struct VasEBoot_usb_usb_hubdesc hubdesc;
VasEBoot_usb_err_t err;
int i;
err = VasEBoot_usb_control_msg (dev, (VAS_EBOOT_USB_REQTYPE_IN
| VAS_EBOOT_USB_REQTYPE_CLASS
| VAS_EBOOT_USB_REQTYPE_TARGET_DEV),
VAS_EBOOT_USB_REQ_GET_DESCRIPTOR,
(VAS_EBOOT_USB_DESCRIPTOR_HUB << 8) | 0,
0, sizeof (hubdesc), (char *) &hubdesc);
if (err)
return err;
VasEBoot_dprintf ("usb", "Hub descriptor:\n\t\t len:%d, typ:0x%02x, cnt:%d, char:0x%02x, pwg:%d, curr:%d\n",
hubdesc.length, hubdesc.type, hubdesc.portcnt,
hubdesc.characteristics, hubdesc.pwdgood,
hubdesc.current);
/* Activate the first configuration. Hubs should have only one conf. */
VasEBoot_dprintf ("usb", "Hub set configuration\n");
VasEBoot_usb_set_configuration (dev, 1);
dev->nports = hubdesc.portcnt;
dev->children = VasEBoot_calloc (hubdesc.portcnt, sizeof (dev->children[0]));
dev->ports = VasEBoot_calloc (dev->nports, sizeof (dev->ports[0]));
if (!dev->children || !dev->ports)
{
VasEBoot_free (dev->children);
VasEBoot_free (dev->ports);
return VAS_EBOOT_USB_ERR_INTERNAL;
}
/* Power on all Hub ports. */
for (i = 1; i <= hubdesc.portcnt; i++)
{
VasEBoot_dprintf ("usb", "Power on - port %d\n", i);
/* Power on the port and wait for possible device connect */
VasEBoot_usb_control_msg (dev, (VAS_EBOOT_USB_REQTYPE_OUT
| VAS_EBOOT_USB_REQTYPE_CLASS
| VAS_EBOOT_USB_REQTYPE_TARGET_OTHER),
VAS_EBOOT_USB_REQ_SET_FEATURE,
VAS_EBOOT_USB_HUB_FEATURE_PORT_POWER,
i, 0, NULL);
}
/* Rest will be done on next usb poll. */
for (i = 0; i < dev->config[0].interf[0].descif->endpointcnt;
i++)
{
struct VasEBoot_usb_desc_endp *endp = NULL;
endp = &dev->config[0].interf[0].descendp[i];
if ((endp->endp_addr & 128) && VasEBoot_usb_get_ep_type(endp)
== VAS_EBOOT_USB_EP_INTERRUPT)
{
VasEBoot_size_t len;
dev->hub_endpoint = endp;
len = endp->maxpacket;
if (len > sizeof (dev->statuschange))
len = sizeof (dev->statuschange);
dev->hub_transfer
= VasEBoot_usb_bulk_read_background (dev, endp, len,
(char *) &dev->statuschange);
break;
}
}
rescan = 1;
return VAS_EBOOT_USB_ERR_NONE;
}
static void
attach_root_port (struct VasEBoot_usb_hub *hub, int portno,
VasEBoot_usb_speed_t speed)
{
VasEBoot_usb_device_t dev;
VasEBoot_usb_err_t err;
VasEBoot_boot_time ("After detect_dev");
/* Enable the port. */
err = hub->controller->dev->portstatus (hub->controller, portno, 1);
if (err)
return;
hub->controller->dev->pending_reset = VasEBoot_get_time_ms () + 5000;
npending++;
VasEBoot_millisleep (10);
VasEBoot_boot_time ("Port enabled");
/* Enable the port and create a device. */
/* High speed device needs not transaction translation
and full/low speed device cannot be connected to EHCI root hub
and full/low speed device connected to OHCI/UHCI needs not
transaction translation - e.g. hubport and hubaddr should be
always none (zero) for any device connected to any root hub. */
dev = VasEBoot_usb_hub_add_dev (hub->controller, speed, 0, 0);
hub->controller->dev->pending_reset = 0;
npending--;
if (! dev)
return;
hub->devices[portno] = dev;
/* If the device is a Hub, scan it for more devices. */
if (dev->descdev.class == 0x09)
VasEBoot_usb_add_hub (dev);
VasEBoot_boot_time ("Attached root port");
}
/* Iterate over all controllers found by the driver. */
static int
VasEBoot_usb_controller_dev_register_iter (VasEBoot_usb_controller_t controller, void *data)
{
VasEBoot_usb_controller_dev_t usb = data;
struct VasEBoot_usb_hub *hub;
controller->dev = usb;
VasEBoot_boot_time ("Registering USB root hub");
hub = VasEBoot_malloc (sizeof (*hub));
if (!hub)
return VAS_EBOOT_USB_ERR_INTERNAL;
hub->next = hubs;
hubs = hub;
hub->controller = VasEBoot_malloc (sizeof (*controller));
if (!hub->controller)
{
VasEBoot_free (hub);
return VAS_EBOOT_USB_ERR_INTERNAL;
}
VasEBoot_memcpy (hub->controller, controller, sizeof (*controller));
hub->dev = 0;
/* Query the number of ports the root Hub has. */
hub->nports = controller->dev->hubports (controller);
hub->devices = VasEBoot_calloc (hub->nports, sizeof (hub->devices[0]));
hub->ports = VasEBoot_calloc (hub->nports, sizeof (hub->ports[0]));
if (!hub->devices || !hub->ports)
{
VasEBoot_free (hub->devices);
VasEBoot_free (hub->ports);
VasEBoot_free (hub->controller);
VasEBoot_free (hub);
VasEBoot_print_error ();
return 0;
}
return 0;
}
void
VasEBoot_usb_controller_dev_unregister (VasEBoot_usb_controller_dev_t usb)
{
VasEBoot_usb_controller_dev_t *p, q;
for (p = &VasEBoot_usb_list, q = *p; q; p = &(q->next), q = q->next)
if (q == usb)
{
*p = q->next;
break;
}
}
void
VasEBoot_usb_controller_dev_register (VasEBoot_usb_controller_dev_t usb)
{
int portno;
int continue_waiting = 0;
struct VasEBoot_usb_hub *hub;
usb->next = VasEBoot_usb_list;
VasEBoot_usb_list = usb;
if (usb->iterate)
usb->iterate (VasEBoot_usb_controller_dev_register_iter, usb);
VasEBoot_boot_time ("waiting for stable power on USB root\n");
while (1)
{
for (hub = hubs; hub; hub = hub->next)
if (hub->controller->dev == usb)
{
/* Wait for completion of insertion and stable power (USB spec.)
* Should be at least 100ms, some devices requires more...
* There is also another thing - some devices have worse contacts
* and connected signal is unstable for some time - we should handle
* it - but prevent deadlock in case when device is too faulty... */
for (portno = 0; portno < hub->nports; portno++)
{
VasEBoot_usb_speed_t speed;
int changed = 0;
speed = hub->controller->dev->detect_dev (hub->controller, portno,
&changed);
if (hub->ports[portno].state == PORT_STATE_NORMAL
&& speed != VAS_EBOOT_USB_SPEED_NONE)
{
hub->ports[portno].soft_limit_time = VasEBoot_get_time_ms () + 250;
hub->ports[portno].hard_limit_time = hub->ports[portno].soft_limit_time + 1750;
hub->ports[portno].state = PORT_STATE_WAITING_FOR_STABLE_POWER;
VasEBoot_boot_time ("Scheduling stable power wait for port %p:%d",
usb, portno);
continue_waiting++;
continue;
}
if (hub->ports[portno].state == PORT_STATE_WAITING_FOR_STABLE_POWER
&& speed == VAS_EBOOT_USB_SPEED_NONE)
{
hub->ports[portno].soft_limit_time = VasEBoot_get_time_ms () + 250;
continue;
}
if (hub->ports[portno].state == PORT_STATE_WAITING_FOR_STABLE_POWER
&& VasEBoot_get_time_ms () > hub->ports[portno].soft_limit_time)
{
hub->ports[portno].state = PORT_STATE_STABLE_POWER;
VasEBoot_boot_time ("Got stable power wait for port %p:%d",
usb, portno);
continue_waiting--;
continue;
}
if (hub->ports[portno].state == PORT_STATE_WAITING_FOR_STABLE_POWER
&& VasEBoot_get_time_ms () > hub->ports[portno].hard_limit_time)
{
hub->ports[portno].state = PORT_STATE_FAILED_DEVICE;
continue_waiting--;
continue;
}
}
}
if (!continue_waiting)
break;
VasEBoot_millisleep (1);
}
VasEBoot_boot_time ("After the stable power wait on USB root");
for (hub = hubs; hub; hub = hub->next)
if (hub->controller->dev == usb)
for (portno = 0; portno < hub->nports; portno++)
if (hub->ports[portno].state == PORT_STATE_STABLE_POWER)
{
VasEBoot_usb_speed_t speed;
int changed = 0;
hub->ports[portno].state = PORT_STATE_NORMAL;
speed = hub->controller->dev->detect_dev (hub->controller, portno, &changed);
attach_root_port (hub, portno, speed);
}
VasEBoot_boot_time ("USB root hub registered");
}
static void detach_device (VasEBoot_usb_device_t dev);
static void
detach_device (VasEBoot_usb_device_t dev)
{
unsigned i;
int k;
if (!dev)
return;
if (dev->descdev.class == VAS_EBOOT_USB_CLASS_HUB)
{
if (dev->hub_transfer)
VasEBoot_usb_cancel_transfer (dev->hub_transfer);
for (i = 0; i < dev->nports; i++)
detach_device (dev->children[i]);
VasEBoot_free (dev->children);
}
for (i = 0; i < ARRAY_SIZE (dev->config); i++)
if (dev->config[i].descconf)
for (k = 0; k < dev->config[i].descconf->numif; k++)
{
struct VasEBoot_usb_interface *inter = &dev->config[i].interf[k];
if (inter && inter->detach_hook)
inter->detach_hook (dev, i, k);
}
VasEBoot_usb_devs[dev->addr] = 0;
}
static int
wait_power_nonroot_hub (VasEBoot_usb_device_t dev)
{
VasEBoot_usb_err_t err;
int continue_waiting = 0;
unsigned i;
for (i = 1; i <= dev->nports; i++)
if (dev->ports[i - 1].state == PORT_STATE_WAITING_FOR_STABLE_POWER)
{
VasEBoot_uint64_t tm;
VasEBoot_uint32_t current_status = 0;
/* Get the port status. */
err = VasEBoot_usb_control_msg (dev, (VAS_EBOOT_USB_REQTYPE_IN
| VAS_EBOOT_USB_REQTYPE_CLASS
| VAS_EBOOT_USB_REQTYPE_TARGET_OTHER),
VAS_EBOOT_USB_REQ_GET_STATUS,
0, i,
sizeof (current_status),
(char *) &current_status);
if (err)
{
dev->ports[i - 1].state = PORT_STATE_FAILED_DEVICE;
continue;
}
tm = VasEBoot_get_time_ms ();
if (!(current_status & VAS_EBOOT_USB_HUB_STATUS_PORT_CONNECTED))
dev->ports[i - 1].soft_limit_time = tm + 250;
if (tm >= dev->ports[i - 1].soft_limit_time)
{
if (dev->controller.dev->pending_reset)
continue;
/* Now do reset of port. */
VasEBoot_usb_control_msg (dev, (VAS_EBOOT_USB_REQTYPE_OUT
| VAS_EBOOT_USB_REQTYPE_CLASS
| VAS_EBOOT_USB_REQTYPE_TARGET_OTHER),
VAS_EBOOT_USB_REQ_SET_FEATURE,
VAS_EBOOT_USB_HUB_FEATURE_PORT_RESET,
i, 0, 0);
dev->ports[i - 1].state = PORT_STATE_NORMAL;
VasEBoot_boot_time ("Resetting port %p:%d", dev, i - 1);
rescan = 1;
/* We cannot reset more than one device at the same time !
* Resetting more devices together results in very bad
* situation: more than one device has default address 0
* at the same time !!!
* Additionaly, we cannot perform another reset
* anywhere on the same OHCI controller until
* we will finish addressing of reseted device ! */
dev->controller.dev->pending_reset = VasEBoot_get_time_ms () + 5000;
npending++;
continue;
}
if (tm >= dev->ports[i - 1].hard_limit_time)
{
dev->ports[i - 1].state = PORT_STATE_FAILED_DEVICE;
continue;
}
continue_waiting = 1;
}
return continue_waiting && dev->controller.dev->pending_reset == 0;
}
static void
poll_nonroot_hub (VasEBoot_usb_device_t dev)
{
VasEBoot_usb_err_t err;
unsigned i;
VasEBoot_uint32_t changed;
VasEBoot_size_t actual, len;
if (!dev->hub_transfer)
return;
err = VasEBoot_usb_check_transfer (dev->hub_transfer, &actual);
if (err == VAS_EBOOT_USB_ERR_WAIT)
return;
changed = dev->statuschange;
len = dev->hub_endpoint->maxpacket;
if (len > sizeof (dev->statuschange))
len = sizeof (dev->statuschange);
dev->hub_transfer
= VasEBoot_usb_bulk_read_background (dev, dev->hub_endpoint, len,
(char *) &dev->statuschange);
if (err || actual == 0 || changed == 0)
return;
/* Iterate over the Hub ports. */
for (i = 1; i <= dev->nports; i++)
{
VasEBoot_uint32_t status;
if (!(changed & (1 << i))
|| dev->ports[i - 1].state == PORT_STATE_WAITING_FOR_STABLE_POWER)
continue;
/* Get the port status. */
err = VasEBoot_usb_control_msg (dev, (VAS_EBOOT_USB_REQTYPE_IN
| VAS_EBOOT_USB_REQTYPE_CLASS
| VAS_EBOOT_USB_REQTYPE_TARGET_OTHER),
VAS_EBOOT_USB_REQ_GET_STATUS,
0, i, sizeof (status), (char *) &status);
VasEBoot_dprintf ("usb", "dev = %p, i = %d, status = %08x\n",
dev, i, status);
if (err)
continue;
/* FIXME: properly handle these conditions. */
if (status & VAS_EBOOT_USB_HUB_STATUS_C_PORT_ENABLED)
VasEBoot_usb_control_msg (dev, (VAS_EBOOT_USB_REQTYPE_OUT
| VAS_EBOOT_USB_REQTYPE_CLASS
| VAS_EBOOT_USB_REQTYPE_TARGET_OTHER),
VAS_EBOOT_USB_REQ_CLEAR_FEATURE,
VAS_EBOOT_USB_HUB_FEATURE_C_PORT_ENABLED, i, 0, 0);
if (status & VAS_EBOOT_USB_HUB_STATUS_C_PORT_SUSPEND)
VasEBoot_usb_control_msg (dev, (VAS_EBOOT_USB_REQTYPE_OUT
| VAS_EBOOT_USB_REQTYPE_CLASS
| VAS_EBOOT_USB_REQTYPE_TARGET_OTHER),
VAS_EBOOT_USB_REQ_CLEAR_FEATURE,
VAS_EBOOT_USB_HUB_FEATURE_C_PORT_SUSPEND, i, 0, 0);
if (status & VAS_EBOOT_USB_HUB_STATUS_C_PORT_OVERCURRENT)
VasEBoot_usb_control_msg (dev, (VAS_EBOOT_USB_REQTYPE_OUT
| VAS_EBOOT_USB_REQTYPE_CLASS
| VAS_EBOOT_USB_REQTYPE_TARGET_OTHER),
VAS_EBOOT_USB_REQ_CLEAR_FEATURE,
VAS_EBOOT_USB_HUB_FEATURE_C_PORT_OVERCURRENT, i, 0, 0);
if (!dev->controller.dev->pending_reset &&
(status & VAS_EBOOT_USB_HUB_STATUS_C_PORT_CONNECTED))
{
VasEBoot_usb_control_msg (dev, (VAS_EBOOT_USB_REQTYPE_OUT
| VAS_EBOOT_USB_REQTYPE_CLASS
| VAS_EBOOT_USB_REQTYPE_TARGET_OTHER),
VAS_EBOOT_USB_REQ_CLEAR_FEATURE,
VAS_EBOOT_USB_HUB_FEATURE_C_PORT_CONNECTED, i, 0, 0);
detach_device (dev->children[i - 1]);
dev->children[i - 1] = NULL;
/* Connected and status of connection changed ? */
if (status & VAS_EBOOT_USB_HUB_STATUS_PORT_CONNECTED)
{
VasEBoot_boot_time ("Before the stable power wait portno=%d", i);
/* A device is actually connected to this port. */
/* Wait for completion of insertion and stable power (USB spec.)
* Should be at least 100ms, some devices requires more...
* There is also another thing - some devices have worse contacts
* and connected signal is unstable for some time - we should handle
* it - but prevent deadlock in case when device is too faulty... */
dev->ports[i - 1].soft_limit_time = VasEBoot_get_time_ms () + 250;
dev->ports[i - 1].hard_limit_time = dev->ports[i - 1].soft_limit_time + 1750;
dev->ports[i - 1].state = PORT_STATE_WAITING_FOR_STABLE_POWER;
VasEBoot_boot_time ("Scheduling stable power wait for port %p:%d",
dev, i - 1);
continue;
}
}
if (status & VAS_EBOOT_USB_HUB_STATUS_C_PORT_RESET)
{
VasEBoot_usb_control_msg (dev, (VAS_EBOOT_USB_REQTYPE_OUT
| VAS_EBOOT_USB_REQTYPE_CLASS
| VAS_EBOOT_USB_REQTYPE_TARGET_OTHER),
VAS_EBOOT_USB_REQ_CLEAR_FEATURE,
VAS_EBOOT_USB_HUB_FEATURE_C_PORT_RESET, i, 0, 0);
VasEBoot_boot_time ("Port %d reset", i);
if (status & VAS_EBOOT_USB_HUB_STATUS_PORT_CONNECTED)
{
VasEBoot_usb_speed_t speed;
VasEBoot_usb_device_t next_dev;
int split_hubport = 0;
int split_hubaddr = 0;
/* Determine the device speed. */
if (status & VAS_EBOOT_USB_HUB_STATUS_PORT_LOWSPEED)
speed = VAS_EBOOT_USB_SPEED_LOW;
else
{
if (status & VAS_EBOOT_USB_HUB_STATUS_PORT_HIGHSPEED)
speed = VAS_EBOOT_USB_SPEED_HIGH;
else
speed = VAS_EBOOT_USB_SPEED_FULL;
}
/* Wait a recovery time after reset, spec. says 10ms */
VasEBoot_millisleep (10);
/* Find correct values for SPLIT hubport and hubaddr */
if (speed == VAS_EBOOT_USB_SPEED_HIGH)
{
/* HIGH speed device needs not transaction translation */
split_hubport = 0;
split_hubaddr = 0;
}
else
/* FULL/LOW device needs hub port and hub address
for transaction translation (if connected to EHCI) */
if (dev->speed == VAS_EBOOT_USB_SPEED_HIGH)
{
/* This port is the first FULL/LOW speed port
in the chain from root hub. Attached device
should use its port number and hub address */
split_hubport = i;
split_hubaddr = dev->addr;
}
else
{
/* This port is NOT the first FULL/LOW speed port
in the chain from root hub. Attached device
should use values inherited from some parent
HIGH speed hub - if any. */
split_hubport = dev->split_hubport;
split_hubaddr = dev->split_hubaddr;
}
/* Add the device and assign a device address to it. */
next_dev = VasEBoot_usb_hub_add_dev (&dev->controller, speed,
split_hubport, split_hubaddr);
if (dev->controller.dev->pending_reset)
{
dev->controller.dev->pending_reset = 0;
npending--;
}
if (! next_dev)
continue;
dev->children[i - 1] = next_dev;
/* If the device is a Hub, scan it for more devices. */
if (next_dev->descdev.class == 0x09)
VasEBoot_usb_add_hub (next_dev);
}
}
}
}
void
VasEBoot_usb_poll_devices (int wait_for_completion)
{
struct VasEBoot_usb_hub *hub;
int i;
for (hub = hubs; hub; hub = hub->next)
{
/* Do we have to recheck number of ports? */
/* No, it should be never changed, it should be constant. */
for (i = 0; i < hub->nports; i++)
{
VasEBoot_usb_speed_t speed = VAS_EBOOT_USB_SPEED_NONE;
int changed = 0;
if (hub->controller->dev->pending_reset)
{
/* Check for possible timeout */
if (VasEBoot_get_time_ms () > hub->controller->dev->pending_reset)
{
/* Something went wrong, reset device was not
* addressed properly, timeout happened */
hub->controller->dev->pending_reset = 0;
npending--;
}
}
if (!hub->controller->dev->pending_reset)
speed = hub->controller->dev->detect_dev (hub->controller,
i, &changed);
if (changed)
{
detach_device (hub->devices[i]);
hub->devices[i] = NULL;
if (speed != VAS_EBOOT_USB_SPEED_NONE)
attach_root_port (hub, i, speed);
}
}
}
while (1)
{
rescan = 0;
/* We should check changes of non-root hubs too. */
for (i = 0; i < VAS_EBOOT_USBHUB_MAX_DEVICES; i++)
{
VasEBoot_usb_device_t dev = VasEBoot_usb_devs[i];
if (dev && dev->descdev.class == 0x09)
poll_nonroot_hub (dev);
}
while (1)
{
int continue_waiting = 0;
for (i = 0; i < VAS_EBOOT_USBHUB_MAX_DEVICES; i++)
{
VasEBoot_usb_device_t dev = VasEBoot_usb_devs[i];
if (dev && dev->descdev.class == 0x09)
continue_waiting = continue_waiting || wait_power_nonroot_hub (dev);
}
if (!continue_waiting)
break;
VasEBoot_millisleep (1);
}
if (!(rescan || (npending && wait_for_completion)))
break;
VasEBoot_millisleep (25);
}
}
int
VasEBoot_usb_iterate (VasEBoot_usb_iterate_hook_t hook, void *hook_data)
{
int i;
for (i = 0; i < VAS_EBOOT_USBHUB_MAX_DEVICES; i++)
{
if (VasEBoot_usb_devs[i])
{
if (hook (VasEBoot_usb_devs[i], hook_data))
return 1;
}
}
return 0;
}

View File

@ -0,0 +1,462 @@
/* usbtrans.c - USB Transfers and Transactions. */
/*
* VAS_EBOOT -- GRand Unified Bootloader
* Copyright (C) 2008 Free Software Foundation, Inc.
*
* VAS_EBOOT 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.
*
* VAS_EBOOT 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 VAS_EBOOT. If not, see <http://www.gnu.org/licenses/>.
*/
#include <VasEBoot/dl.h>
#include <VasEBoot/dma.h>
#include <VasEBoot/mm.h>
#include <VasEBoot/misc.h>
#include <VasEBoot/usb.h>
#include <VasEBoot/usbtrans.h>
#include <VasEBoot/time.h>
#include <VasEBoot/cache.h>
static inline unsigned int
VasEBoot_usb_bulk_maxpacket (VasEBoot_usb_device_t dev,
struct VasEBoot_usb_desc_endp *endpoint)
{
/* Use the maximum packet size given in the endpoint descriptor. */
if (dev->initialized && endpoint && (unsigned int) endpoint->maxpacket)
return endpoint->maxpacket;
return 64;
}
static VasEBoot_usb_err_t
VasEBoot_usb_execute_and_wait_transfer (VasEBoot_usb_device_t dev,
VasEBoot_usb_transfer_t transfer,
int timeout, VasEBoot_size_t *actual)
{
VasEBoot_usb_err_t err;
VasEBoot_uint64_t endtime;
err = dev->controller.dev->setup_transfer (&dev->controller, transfer);
if (err)
return err;
/* endtime moved behind setup transfer to prevent false timeouts
* while debugging... */
endtime = VasEBoot_get_time_ms () + timeout;
while (1)
{
err = dev->controller.dev->check_transfer (&dev->controller, transfer,
actual);
if (!err)
return VAS_EBOOT_USB_ERR_NONE;
if (err != VAS_EBOOT_USB_ERR_WAIT)
return err;
if (VasEBoot_get_time_ms () > endtime)
{
err = dev->controller.dev->cancel_transfer (&dev->controller,
transfer);
if (err)
return err;
return VAS_EBOOT_USB_ERR_TIMEOUT;
}
VasEBoot_cpu_idle ();
}
}
VasEBoot_usb_err_t
VasEBoot_usb_control_msg (VasEBoot_usb_device_t dev,
VasEBoot_uint8_t reqtype,
VasEBoot_uint8_t request,
VasEBoot_uint16_t value,
VasEBoot_uint16_t index,
VasEBoot_size_t size0, char *data_in)
{
int i;
VasEBoot_usb_transfer_t transfer;
int datablocks;
volatile struct VasEBoot_usb_packet_setup *setupdata;
VasEBoot_uint32_t setupdata_addr;
VasEBoot_usb_err_t err;
unsigned int max;
struct VasEBoot_pci_dma_chunk *data_chunk, *setupdata_chunk;
volatile char *data;
VasEBoot_uint32_t data_addr;
VasEBoot_size_t size = size0;
VasEBoot_size_t actual;
/* FIXME: avoid allocation any kind of buffer in a first place. */
data_chunk = VasEBoot_memalign_dma32 (128, size ? : 16);
if (!data_chunk)
return VAS_EBOOT_USB_ERR_INTERNAL;
data = VasEBoot_dma_get_virt (data_chunk);
data_addr = VasEBoot_dma_get_phys (data_chunk);
VasEBoot_memcpy ((char *) data, data_in, size);
VasEBoot_arch_sync_dma_caches (data, size);
VasEBoot_dprintf ("usb",
"control: reqtype=0x%02x req=0x%02x val=0x%02x idx=0x%02x size=%lu\n",
reqtype, request, value, index, (unsigned long)size);
/* Create a transfer. */
transfer = VasEBoot_malloc (sizeof (*transfer));
if (! transfer)
{
VasEBoot_dma_free (data_chunk);
return VAS_EBOOT_USB_ERR_INTERNAL;
}
setupdata_chunk = VasEBoot_memalign_dma32 (32, sizeof (*setupdata));
if (! setupdata_chunk)
{
VasEBoot_free (transfer);
VasEBoot_dma_free (data_chunk);
return VAS_EBOOT_USB_ERR_INTERNAL;
}
setupdata = VasEBoot_dma_get_virt (setupdata_chunk);
setupdata_addr = VasEBoot_dma_get_phys (setupdata_chunk);
/* Determine the maximum packet size. */
if (dev->descdev.maxsize0)
max = dev->descdev.maxsize0;
else
max = 64;
VasEBoot_dprintf ("usb", "control: transfer = %p, dev = %p\n", transfer, dev);
datablocks = (size + max - 1) / max;
/* XXX: Discriminate between different types of control
messages. */
transfer->transcnt = datablocks + 2;
transfer->size = size; /* XXX ? */
transfer->endpoint = 0;
transfer->devaddr = dev->addr;
transfer->type = VAS_EBOOT_USB_TRANSACTION_TYPE_CONTROL;
transfer->max = max;
transfer->dev = dev;
/* Allocate an array of transfer data structures. */
transfer->transactions = VasEBoot_malloc (transfer->transcnt
* sizeof (struct VasEBoot_usb_transfer));
if (! transfer->transactions)
{
VasEBoot_free (transfer);
VasEBoot_dma_free (setupdata_chunk);
VasEBoot_dma_free (data_chunk);
return VAS_EBOOT_USB_ERR_INTERNAL;
}
/* Build a Setup packet. XXX: Endianness. */
setupdata->reqtype = reqtype;
setupdata->request = request;
setupdata->value = value;
setupdata->index = index;
setupdata->length = size;
VasEBoot_arch_sync_dma_caches (setupdata, sizeof (*setupdata));
transfer->transactions[0].size = sizeof (*setupdata);
transfer->transactions[0].pid = VAS_EBOOT_USB_TRANSFER_TYPE_SETUP;
transfer->transactions[0].data = setupdata_addr;
transfer->transactions[0].toggle = 0;
/* Now the data... XXX: Is this the right way to transfer control
transfers? */
for (i = 0; i < datablocks; i++)
{
VasEBoot_usb_transaction_t tr = &transfer->transactions[i + 1];
tr->size = (size > max) ? max : size;
/* Use the right most bit as the data toggle. Simple and
effective. */
tr->toggle = !(i & 1);
if (reqtype & 128)
tr->pid = VAS_EBOOT_USB_TRANSFER_TYPE_IN;
else
tr->pid = VAS_EBOOT_USB_TRANSFER_TYPE_OUT;
tr->data = data_addr + i * max;
tr->preceding = i * max;
size -= max;
}
/* End with an empty OUT transaction. */
transfer->transactions[datablocks + 1].size = 0;
transfer->transactions[datablocks + 1].data = 0;
if ((reqtype & 128) && datablocks)
transfer->transactions[datablocks + 1].pid = VAS_EBOOT_USB_TRANSFER_TYPE_OUT;
else
transfer->transactions[datablocks + 1].pid = VAS_EBOOT_USB_TRANSFER_TYPE_IN;
transfer->transactions[datablocks + 1].toggle = 1;
err = VasEBoot_usb_execute_and_wait_transfer (dev, transfer, 1000, &actual);
VasEBoot_dprintf ("usb", "control: err=%d\n", err);
VasEBoot_free (transfer->transactions);
VasEBoot_free (transfer);
VasEBoot_dma_free (setupdata_chunk);
VasEBoot_arch_sync_dma_caches (data, size0);
VasEBoot_memcpy (data_in, (char *) data, size0);
VasEBoot_dma_free (data_chunk);
return err;
}
static VasEBoot_usb_transfer_t
VasEBoot_usb_bulk_setup_readwrite (VasEBoot_usb_device_t dev,
struct VasEBoot_usb_desc_endp *endpoint,
VasEBoot_size_t size0, char *data_in,
VasEBoot_transfer_type_t type)
{
int i;
VasEBoot_usb_transfer_t transfer;
int datablocks;
unsigned int max;
volatile char *data;
VasEBoot_uint32_t data_addr;
struct VasEBoot_pci_dma_chunk *data_chunk;
VasEBoot_size_t size = size0;
int toggle = dev->toggle[endpoint->endp_addr];
VasEBoot_dprintf ("usb", "bulk: size=0x%02lx type=%d\n", (unsigned long) size,
type);
/* FIXME: avoid allocation any kind of buffer in a first place. */
data_chunk = VasEBoot_memalign_dma32 (128, size);
if (!data_chunk)
return NULL;
data = VasEBoot_dma_get_virt (data_chunk);
data_addr = VasEBoot_dma_get_phys (data_chunk);
if (type == VAS_EBOOT_USB_TRANSFER_TYPE_OUT)
{
VasEBoot_memcpy ((char *) data, data_in, size);
VasEBoot_arch_sync_dma_caches (data, size);
}
/* Create a transfer. */
transfer = VasEBoot_malloc (sizeof (struct VasEBoot_usb_transfer));
if (! transfer)
{
VasEBoot_dma_free (data_chunk);
return NULL;
}
max = VasEBoot_usb_bulk_maxpacket (dev, endpoint);
datablocks = ((size + max - 1) / max);
transfer->transcnt = datablocks;
transfer->size = size - 1;
transfer->endpoint = endpoint->endp_addr;
transfer->devaddr = dev->addr;
transfer->type = VAS_EBOOT_USB_TRANSACTION_TYPE_BULK;
transfer->dir = type;
transfer->max = max;
transfer->dev = dev;
transfer->last_trans = -1; /* Reset index of last processed transaction (TD) */
transfer->data_chunk = data_chunk;
transfer->data = data_in;
/* Allocate an array of transfer data structures. */
transfer->transactions = VasEBoot_malloc (transfer->transcnt
* sizeof (struct VasEBoot_usb_transfer));
if (! transfer->transactions)
{
VasEBoot_free (transfer);
VasEBoot_dma_free (data_chunk);
return NULL;
}
/* Set up all transfers. */
for (i = 0; i < datablocks; i++)
{
VasEBoot_usb_transaction_t tr = &transfer->transactions[i];
tr->size = (size > max) ? max : size;
/* XXX: Use the right most bit as the data toggle. Simple and
effective. */
tr->toggle = toggle;
toggle = toggle ? 0 : 1;
tr->pid = type;
tr->data = data_addr + i * max;
tr->preceding = i * max;
size -= tr->size;
}
return transfer;
}
static void
VasEBoot_usb_bulk_finish_readwrite (VasEBoot_usb_transfer_t transfer)
{
VasEBoot_usb_device_t dev = transfer->dev;
int toggle = dev->toggle[transfer->endpoint];
/* We must remember proper toggle value even if some transactions
* were not processed - correct value should be inversion of last
* processed transaction (TD). */
if (transfer->last_trans >= 0)
toggle = transfer->transactions[transfer->last_trans].toggle ? 0 : 1;
else
toggle = dev->toggle[transfer->endpoint]; /* Nothing done, take original */
VasEBoot_dprintf ("usb", "bulk: toggle=%d\n", toggle);
dev->toggle[transfer->endpoint] = toggle;
if (transfer->dir == VAS_EBOOT_USB_TRANSFER_TYPE_IN)
{
VasEBoot_arch_sync_dma_caches (VasEBoot_dma_get_virt (transfer->data_chunk),
transfer->size + 1);
VasEBoot_memcpy (transfer->data, (void *)
VasEBoot_dma_get_virt (transfer->data_chunk),
transfer->size + 1);
}
VasEBoot_free (transfer->transactions);
VasEBoot_dma_free (transfer->data_chunk);
VasEBoot_free (transfer);
}
static VasEBoot_usb_err_t
VasEBoot_usb_bulk_readwrite (VasEBoot_usb_device_t dev,
struct VasEBoot_usb_desc_endp *endpoint,
VasEBoot_size_t size0, char *data_in,
VasEBoot_transfer_type_t type, int timeout,
VasEBoot_size_t *actual)
{
VasEBoot_usb_err_t err;
VasEBoot_usb_transfer_t transfer;
transfer = VasEBoot_usb_bulk_setup_readwrite (dev, endpoint, size0,
data_in, type);
if (!transfer)
return VAS_EBOOT_USB_ERR_INTERNAL;
err = VasEBoot_usb_execute_and_wait_transfer (dev, transfer, timeout, actual);
VasEBoot_usb_bulk_finish_readwrite (transfer);
return err;
}
static VasEBoot_usb_err_t
VasEBoot_usb_bulk_readwrite_packetize (VasEBoot_usb_device_t dev,
struct VasEBoot_usb_desc_endp *endpoint,
VasEBoot_transfer_type_t type,
VasEBoot_size_t size, char *data)
{
VasEBoot_size_t actual, transferred;
VasEBoot_usb_err_t err = VAS_EBOOT_USB_ERR_NONE;
VasEBoot_size_t current_size, position;
VasEBoot_size_t max_bulk_transfer_len = MAX_USB_TRANSFER_LEN;
VasEBoot_size_t max;
if (dev->controller.dev->max_bulk_tds)
{
max = VasEBoot_usb_bulk_maxpacket (dev, endpoint);
/* Calculate max. possible length of bulk transfer */
max_bulk_transfer_len = dev->controller.dev->max_bulk_tds * max;
}
for (position = 0, transferred = 0;
position < size; position += max_bulk_transfer_len)
{
current_size = size - position;
if (current_size >= max_bulk_transfer_len)
current_size = max_bulk_transfer_len;
err = VasEBoot_usb_bulk_readwrite (dev, endpoint, current_size,
&data[position], type, 1000, &actual);
transferred += actual;
if (err || (current_size != actual)) break;
}
if (!err && transferred != size)
err = VAS_EBOOT_USB_ERR_DATA;
return err;
}
VasEBoot_usb_err_t
VasEBoot_usb_bulk_write (VasEBoot_usb_device_t dev,
struct VasEBoot_usb_desc_endp *endpoint,
VasEBoot_size_t size, char *data)
{
return VasEBoot_usb_bulk_readwrite_packetize (dev, endpoint,
VAS_EBOOT_USB_TRANSFER_TYPE_OUT,
size, data);
}
VasEBoot_usb_err_t
VasEBoot_usb_bulk_read (VasEBoot_usb_device_t dev,
struct VasEBoot_usb_desc_endp *endpoint,
VasEBoot_size_t size, char *data)
{
return VasEBoot_usb_bulk_readwrite_packetize (dev, endpoint,
VAS_EBOOT_USB_TRANSFER_TYPE_IN,
size, data);
}
VasEBoot_usb_err_t
VasEBoot_usb_check_transfer (VasEBoot_usb_transfer_t transfer, VasEBoot_size_t *actual)
{
VasEBoot_usb_err_t err;
VasEBoot_usb_device_t dev = transfer->dev;
err = dev->controller.dev->check_transfer (&dev->controller, transfer,
actual);
if (err == VAS_EBOOT_USB_ERR_WAIT)
return err;
VasEBoot_usb_bulk_finish_readwrite (transfer);
return err;
}
VasEBoot_usb_transfer_t
VasEBoot_usb_bulk_read_background (VasEBoot_usb_device_t dev,
struct VasEBoot_usb_desc_endp *endpoint,
VasEBoot_size_t size, void *data)
{
VasEBoot_usb_err_t err;
VasEBoot_usb_transfer_t transfer;
transfer = VasEBoot_usb_bulk_setup_readwrite (dev, endpoint, size,
data, VAS_EBOOT_USB_TRANSFER_TYPE_IN);
if (!transfer)
return NULL;
err = dev->controller.dev->setup_transfer (&dev->controller, transfer);
if (err)
return NULL;
return transfer;
}
void
VasEBoot_usb_cancel_transfer (VasEBoot_usb_transfer_t transfer)
{
VasEBoot_usb_device_t dev = transfer->dev;
dev->controller.dev->cancel_transfer (&dev->controller, transfer);
VasEBoot_errno = VAS_EBOOT_ERR_NONE;
}
VasEBoot_usb_err_t
VasEBoot_usb_bulk_read_extended (VasEBoot_usb_device_t dev,
struct VasEBoot_usb_desc_endp *endpoint,
VasEBoot_size_t size, char *data,
int timeout, VasEBoot_size_t *actual)
{
return VasEBoot_usb_bulk_readwrite (dev, endpoint, size, data,
VAS_EBOOT_USB_TRANSFER_TYPE_IN, timeout, actual);
}

View File

@ -0,0 +1,820 @@
/* acpi.c - modify acpi tables. */
/*
* VAS_EBOOT -- GRand Unified Bootloader
* Copyright (C) 2009 Free Software Foundation, Inc.
*
* VAS_EBOOT 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.
*
* VAS_EBOOT 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 VAS_EBOOT. If not, see <http://www.gnu.org/licenses/>.
*/
#include <VasEBoot/dl.h>
#include <VasEBoot/extcmd.h>
#include <VasEBoot/file.h>
#include <VasEBoot/disk.h>
#include <VasEBoot/term.h>
#include <VasEBoot/misc.h>
#include <VasEBoot/acpi.h>
#include <VasEBoot/mm.h>
#include <VasEBoot/memory.h>
#include <VasEBoot/i18n.h>
#include <VasEBoot/lockdown.h>
#ifdef VAS_EBOOT_MACHINE_EFI
#include <VasEBoot/efi/efi.h>
#include <VasEBoot/efi/api.h>
#endif
#pragma GCC diagnostic ignored "-Wcast-align"
VAS_EBOOT_MOD_LICENSE ("GPLv3+");
enum
{
OPTION_EXCLUDE = 0,
OPTION_LOAD_ONLY,
OPTION_V1,
OPTION_V2,
OPTION_OEMID,
OPTION_OEMTABLE,
OPTION_OEMTABLEREV,
OPTION_OEMTABLECREATOR,
OPTION_OEMTABLECREATORREV,
OPTION_NO_EBDA
};
static const struct VasEBoot_arg_option options[] = {
{"exclude", 'x', 0,
N_("Don't load host tables specified by comma-separated list."),
0, ARG_TYPE_STRING},
{"load-only", 'n', 0,
N_("Load only tables specified by comma-separated list."), 0, ARG_TYPE_STRING},
{"v1", '1', 0, N_("Export version 1 tables to the OS."), 0, ARG_TYPE_NONE},
{"v2", '2', 0, N_("Export version 2 and version 3 tables to the OS."), 0, ARG_TYPE_NONE},
{"oemid", 'o', 0, N_("Set OEMID of RSDP, XSDT and RSDT."), 0, ARG_TYPE_STRING},
{"oemtable", 't', 0,
N_("Set OEMTABLE ID of RSDP, XSDT and RSDT."), 0, ARG_TYPE_STRING},
{"oemtablerev", 'r', 0,
N_("Set OEMTABLE revision of RSDP, XSDT and RSDT."), 0, ARG_TYPE_INT},
{"oemtablecreator", 'c', 0,
N_("Set creator field of RSDP, XSDT and RSDT."), 0, ARG_TYPE_STRING},
{"oemtablecreatorrev", 'd', 0,
N_("Set creator revision of RSDP, XSDT and RSDT."), 0, ARG_TYPE_INT},
/* TRANSLATORS: "hangs" here is a noun, not a verb. */
{"no-ebda", 'e', 0, N_("Don't update EBDA. May fix failures or hangs on some "
"BIOSes but makes it ineffective with OS not receiving RSDP from VAS_EBOOT."),
0, ARG_TYPE_NONE},
{0, 0, 0, 0, 0, 0}
};
/* rev1 is 1 if ACPIv1 is to be generated, 0 otherwise.
rev2 contains the revision of ACPIv2+ to generate or 0 if none. */
static int rev1, rev2;
/* OEMID of RSDP, RSDT and XSDT. */
static char root_oemid[6];
/* OEMTABLE of the same tables. */
static char root_oemtable[8];
/* OEMREVISION of the same tables. */
static VasEBoot_uint32_t root_oemrev;
/* CreatorID of the same tables. */
static char root_creator_id[4];
/* CreatorRevision of the same tables. */
static VasEBoot_uint32_t root_creator_rev;
static struct VasEBoot_acpi_rsdp_v10 *rsdpv1_new = 0;
static struct VasEBoot_acpi_rsdp_v20 *rsdpv2_new = 0;
static char *playground = 0, *playground_ptr = 0;
static int playground_size = 0;
/* Linked list of ACPI tables. */
struct efiemu_acpi_table
{
void *addr;
VasEBoot_size_t size;
struct efiemu_acpi_table *next;
};
static struct efiemu_acpi_table *acpi_tables = 0;
/* DSDT isn't in RSDT. So treat it specially. */
static void *table_dsdt = 0;
/* Pointer to recreated RSDT. */
static void *rsdt_addr = 0;
/* Allocation handles for different tables. */
static VasEBoot_size_t dsdt_size = 0;
/* Address of original FACS. */
static VasEBoot_uint32_t facs_addr = 0;
struct VasEBoot_acpi_rsdp_v20 *
VasEBoot_acpi_get_rsdpv2 (void)
{
if (rsdpv2_new)
return rsdpv2_new;
if (rsdpv1_new)
return 0;
return VasEBoot_machine_acpi_get_rsdpv2 ();
}
struct VasEBoot_acpi_rsdp_v10 *
VasEBoot_acpi_get_rsdpv1 (void)
{
if (rsdpv1_new)
return rsdpv1_new;
if (rsdpv2_new)
return 0;
return VasEBoot_machine_acpi_get_rsdpv1 ();
}
#if defined (__i386__) || defined (__x86_64__)
static inline int
iszero (VasEBoot_uint8_t *reg, int size)
{
int i;
for (i = 0; i < size; i++)
if (reg[i])
return 0;
return 1;
}
/* Context for VasEBoot_acpi_create_ebda. */
struct VasEBoot_acpi_create_ebda_ctx {
int ebda_len;
VasEBoot_uint64_t highestlow;
};
/* Helper for VasEBoot_acpi_create_ebda. */
static int
find_hook (VasEBoot_uint64_t start, VasEBoot_uint64_t size, VasEBoot_memory_type_t type,
void *data)
{
struct VasEBoot_acpi_create_ebda_ctx *ctx = data;
VasEBoot_uint64_t end = start + size;
if (type != VAS_EBOOT_MEMORY_AVAILABLE)
return 0;
if (end > 0x100000)
end = 0x100000;
if (end > start + ctx->ebda_len
&& ctx->highestlow < ((end - ctx->ebda_len) & (~0xf)) )
ctx->highestlow = (end - ctx->ebda_len) & (~0xf);
return 0;
}
VasEBoot_err_t
VasEBoot_acpi_create_ebda (void)
{
struct VasEBoot_acpi_create_ebda_ctx ctx = {
.highestlow = 0
};
int ebda_kb_len = 0;
int mmapregion = 0;
VasEBoot_uint8_t *ebda, *v1inebda = 0, *v2inebda = 0;
VasEBoot_uint8_t *targetebda, *target;
struct VasEBoot_acpi_rsdp_v10 *v1;
struct VasEBoot_acpi_rsdp_v20 *v2;
ebda = (VasEBoot_uint8_t *) (VasEBoot_addr_t) ((*((VasEBoot_uint16_t *) VasEBoot_absolute_pointer (0x40e))) << 4);
VasEBoot_dprintf ("acpi", "EBDA @%p\n", ebda);
if (ebda)
ebda_kb_len = *(VasEBoot_uint16_t *) ebda;
VasEBoot_dprintf ("acpi", "EBDA length 0x%x\n", ebda_kb_len);
if (ebda_kb_len > 16)
ebda_kb_len = 0;
ctx.ebda_len = (ebda_kb_len + 1) << 10;
/* FIXME: use low-memory mm allocation once it's available. */
VasEBoot_mmap_iterate (find_hook, &ctx);
targetebda = (VasEBoot_uint8_t *) (VasEBoot_addr_t) ctx.highestlow;
VasEBoot_dprintf ("acpi", "creating ebda @%llx\n",
(unsigned long long) ctx.highestlow);
if (! ctx.highestlow)
return VasEBoot_error (VAS_EBOOT_ERR_OUT_OF_MEMORY,
"couldn't find space for the new EBDA");
mmapregion = VasEBoot_mmap_register ((VasEBoot_addr_t) targetebda, ctx.ebda_len,
VAS_EBOOT_MEMORY_RESERVED);
if (! mmapregion)
return VasEBoot_errno;
/* XXX: EBDA is unstandardized, so this implementation is heuristical. */
if (ebda_kb_len)
VasEBoot_memcpy (targetebda, ebda, 0x400);
else
VasEBoot_memset (targetebda, 0, 0x400);
*((VasEBoot_uint16_t *) targetebda) = ebda_kb_len + 1;
target = targetebda;
v1 = VasEBoot_acpi_get_rsdpv1 ();
v2 = VasEBoot_acpi_get_rsdpv2 ();
if (v2 && v2->length > 40)
v2 = 0;
/* First try to replace already existing rsdp. */
if (v2)
{
VasEBoot_dprintf ("acpi", "Scanning EBDA for old rsdpv2\n");
for (; target < targetebda + 0x400 - v2->length; target += 0x10)
if (VasEBoot_memcmp (target, VAS_EBOOT_RSDP_SIGNATURE, VAS_EBOOT_RSDP_SIGNATURE_SIZE) == 0
&& VasEBoot_byte_checksum (target,
sizeof (struct VasEBoot_acpi_rsdp_v10)) == 0
&& ((struct VasEBoot_acpi_rsdp_v10 *) target)->revision != 0
&& ((struct VasEBoot_acpi_rsdp_v20 *) target)->length <= v2->length)
{
VasEBoot_memcpy (target, v2, v2->length);
VasEBoot_dprintf ("acpi", "Copying rsdpv2 to %p\n", target);
v2inebda = target;
target += v2->length;
target = (VasEBoot_uint8_t *) ALIGN_UP((VasEBoot_addr_t) target, 16);
v2 = 0;
break;
}
}
if (v1)
{
VasEBoot_dprintf ("acpi", "Scanning EBDA for old rsdpv1\n");
for (; target < targetebda + 0x400 - sizeof (struct VasEBoot_acpi_rsdp_v10);
target += 0x10)
if (VasEBoot_memcmp (target, VAS_EBOOT_RSDP_SIGNATURE, VAS_EBOOT_RSDP_SIGNATURE_SIZE) == 0
&& VasEBoot_byte_checksum (target,
sizeof (struct VasEBoot_acpi_rsdp_v10)) == 0)
{
VasEBoot_memcpy (target, v1, sizeof (struct VasEBoot_acpi_rsdp_v10));
VasEBoot_dprintf ("acpi", "Copying rsdpv1 to %p\n", target);
v1inebda = target;
target += sizeof (struct VasEBoot_acpi_rsdp_v10);
target = (VasEBoot_uint8_t *) ALIGN_UP((VasEBoot_addr_t) target, 16);
v1 = 0;
break;
}
}
target = targetebda + 0x100;
/* Try contiguous zeros. */
if (v2)
{
VasEBoot_dprintf ("acpi", "Scanning EBDA for block of zeros\n");
for (; target < targetebda + 0x400 - v2->length; target += 0x10)
if (iszero (target, v2->length))
{
VasEBoot_dprintf ("acpi", "Copying rsdpv2 to %p\n", target);
VasEBoot_memcpy (target, v2, v2->length);
v2inebda = target;
target += v2->length;
target = (VasEBoot_uint8_t *) ALIGN_UP((VasEBoot_addr_t) target, 16);
v2 = 0;
break;
}
}
if (v1)
{
VasEBoot_dprintf ("acpi", "Scanning EBDA for block of zeros\n");
for (; target < targetebda + 0x400 - sizeof (struct VasEBoot_acpi_rsdp_v10);
target += 0x10)
if (iszero (target, sizeof (struct VasEBoot_acpi_rsdp_v10)))
{
VasEBoot_dprintf ("acpi", "Copying rsdpv1 to %p\n", target);
VasEBoot_memcpy (target, v1, sizeof (struct VasEBoot_acpi_rsdp_v10));
v1inebda = target;
target += sizeof (struct VasEBoot_acpi_rsdp_v10);
target = (VasEBoot_uint8_t *) ALIGN_UP((VasEBoot_addr_t) target, 16);
v1 = 0;
break;
}
}
if (v1 || v2)
{
VasEBoot_mmap_unregister (mmapregion);
return VasEBoot_error (VAS_EBOOT_ERR_OUT_OF_MEMORY,
"couldn't find suitable spot in EBDA");
}
/* Remove any other RSDT. */
for (target = targetebda;
target < targetebda + 0x400 - sizeof (struct VasEBoot_acpi_rsdp_v10);
target += 0x10)
if (VasEBoot_memcmp (target, VAS_EBOOT_RSDP_SIGNATURE, VAS_EBOOT_RSDP_SIGNATURE_SIZE) == 0
&& VasEBoot_byte_checksum (target,
sizeof (struct VasEBoot_acpi_rsdp_v10)) == 0
&& target != v1inebda && target != v2inebda)
*target = 0;
VasEBoot_dprintf ("acpi", "Switching EBDA\n");
(*((VasEBoot_uint16_t *) VasEBoot_absolute_pointer (0x40e))) = ((VasEBoot_addr_t) targetebda) >> 4;
VasEBoot_dprintf ("acpi", "EBDA switched\n");
return VAS_EBOOT_ERR_NONE;
}
#endif
/* Create tables common to ACPIv1 and ACPIv2+ */
static void
setup_common_tables (void)
{
struct efiemu_acpi_table *cur;
struct VasEBoot_acpi_table_header *rsdt;
VasEBoot_uint32_t *rsdt_entry;
int numoftables;
/* Treat DSDT. */
VasEBoot_memcpy (playground_ptr, table_dsdt, dsdt_size);
VasEBoot_free (table_dsdt);
table_dsdt = playground_ptr;
playground_ptr += dsdt_size;
/* Treat other tables. */
for (cur = acpi_tables; cur; cur = cur->next)
{
struct VasEBoot_acpi_fadt *fadt;
VasEBoot_memcpy (playground_ptr, cur->addr, cur->size);
VasEBoot_free (cur->addr);
cur->addr = playground_ptr;
playground_ptr += cur->size;
/* If it's FADT correct DSDT and FACS addresses. */
fadt = (struct VasEBoot_acpi_fadt *) cur->addr;
if (VasEBoot_memcmp (fadt->hdr.signature, VAS_EBOOT_ACPI_FADT_SIGNATURE,
sizeof (fadt->hdr.signature)) == 0)
{
fadt->dsdt_addr = (VasEBoot_addr_t) table_dsdt;
fadt->facs_addr = facs_addr;
/* Does a revision 2 exist at all? */
if (fadt->hdr.revision >= 3)
{
fadt->dsdt_xaddr = (VasEBoot_addr_t) table_dsdt;
fadt->facs_xaddr = facs_addr;
}
/* Recompute checksum. */
fadt->hdr.checksum = 0;
fadt->hdr.checksum = 1 + ~VasEBoot_byte_checksum (fadt, fadt->hdr.length);
}
}
/* Fill RSDT entries. */
numoftables = 0;
for (cur = acpi_tables; cur; cur = cur->next)
numoftables++;
rsdt_addr = rsdt = (struct VasEBoot_acpi_table_header *) playground_ptr;
playground_ptr += sizeof (struct VasEBoot_acpi_table_header) + sizeof (VasEBoot_uint32_t) * numoftables;
rsdt_entry = (VasEBoot_uint32_t *) (rsdt + 1);
/* Fill RSDT header. */
VasEBoot_memcpy (&(rsdt->signature), "RSDT", 4);
rsdt->length = sizeof (struct VasEBoot_acpi_table_header) + sizeof (VasEBoot_uint32_t) * numoftables;
rsdt->revision = 1;
VasEBoot_memcpy (&(rsdt->oemid), root_oemid, sizeof (rsdt->oemid));
VasEBoot_memcpy (&(rsdt->oemtable), root_oemtable, sizeof (rsdt->oemtable));
rsdt->oemrev = root_oemrev;
VasEBoot_memcpy (&(rsdt->creator_id), root_creator_id, sizeof (rsdt->creator_id));
rsdt->creator_rev = root_creator_rev;
for (cur = acpi_tables; cur; cur = cur->next)
*(rsdt_entry++) = (VasEBoot_addr_t) cur->addr;
/* Recompute checksum. */
rsdt->checksum = 0;
rsdt->checksum = 1 + ~VasEBoot_byte_checksum (rsdt, rsdt->length);
}
/* Regenerate ACPIv1 RSDP */
static void
setv1table (void)
{
/* Create RSDP. */
rsdpv1_new = (struct VasEBoot_acpi_rsdp_v10 *) playground_ptr;
playground_ptr += sizeof (struct VasEBoot_acpi_rsdp_v10);
VasEBoot_memcpy (&(rsdpv1_new->signature), VAS_EBOOT_RSDP_SIGNATURE,
sizeof (rsdpv1_new->signature));
VasEBoot_memcpy (&(rsdpv1_new->oemid), root_oemid, sizeof (rsdpv1_new->oemid));
rsdpv1_new->revision = 0;
rsdpv1_new->rsdt_addr = (VasEBoot_addr_t) rsdt_addr;
rsdpv1_new->checksum = 0;
rsdpv1_new->checksum = 1 + ~VasEBoot_byte_checksum (rsdpv1_new,
sizeof (*rsdpv1_new));
VasEBoot_dprintf ("acpi", "Generated ACPIv1 tables\n");
}
static void
setv2table (void)
{
struct VasEBoot_acpi_table_header *xsdt;
struct efiemu_acpi_table *cur;
VasEBoot_uint64_t *xsdt_entry;
int numoftables;
numoftables = 0;
for (cur = acpi_tables; cur; cur = cur->next)
numoftables++;
/* Create XSDT. */
xsdt = (struct VasEBoot_acpi_table_header *) playground_ptr;
playground_ptr += sizeof (struct VasEBoot_acpi_table_header) + sizeof (VasEBoot_uint64_t) * numoftables;
xsdt_entry = (VasEBoot_uint64_t *)(xsdt + 1);
for (cur = acpi_tables; cur; cur = cur->next)
*(xsdt_entry++) = (VasEBoot_addr_t) cur->addr;
VasEBoot_memcpy (&(xsdt->signature), "XSDT", 4);
xsdt->length = sizeof (struct VasEBoot_acpi_table_header) + sizeof (VasEBoot_uint64_t) * numoftables;
xsdt->revision = 1;
VasEBoot_memcpy (&(xsdt->oemid), root_oemid, sizeof (xsdt->oemid));
VasEBoot_memcpy (&(xsdt->oemtable), root_oemtable, sizeof (xsdt->oemtable));
xsdt->oemrev = root_oemrev;
VasEBoot_memcpy (&(xsdt->creator_id), root_creator_id, sizeof (xsdt->creator_id));
xsdt->creator_rev = root_creator_rev;
xsdt->checksum = 0;
xsdt->checksum = 1 + ~VasEBoot_byte_checksum (xsdt, xsdt->length);
/* Create RSDPv2. */
rsdpv2_new = (struct VasEBoot_acpi_rsdp_v20 *) playground_ptr;
playground_ptr += sizeof (struct VasEBoot_acpi_rsdp_v20);
VasEBoot_memcpy (&(rsdpv2_new->rsdpv1.signature), VAS_EBOOT_RSDP_SIGNATURE,
sizeof (rsdpv2_new->rsdpv1.signature));
VasEBoot_memcpy (&(rsdpv2_new->rsdpv1.oemid), root_oemid,
sizeof (rsdpv2_new->rsdpv1.oemid));
rsdpv2_new->rsdpv1.revision = rev2;
rsdpv2_new->rsdpv1.rsdt_addr = (VasEBoot_addr_t) rsdt_addr;
rsdpv2_new->rsdpv1.checksum = 0;
rsdpv2_new->rsdpv1.checksum = 1 + ~VasEBoot_byte_checksum
(&(rsdpv2_new->rsdpv1), sizeof (rsdpv2_new->rsdpv1));
rsdpv2_new->length = sizeof (*rsdpv2_new);
rsdpv2_new->xsdt_addr = (VasEBoot_addr_t) xsdt;
rsdpv2_new->checksum = 0;
rsdpv2_new->checksum = 1 + ~VasEBoot_byte_checksum (rsdpv2_new,
rsdpv2_new->length);
VasEBoot_dprintf ("acpi", "Generated ACPIv2 tables\n");
}
static void
free_tables (void)
{
struct efiemu_acpi_table *cur, *t;
if (table_dsdt)
VasEBoot_free (table_dsdt);
for (cur = acpi_tables; cur;)
{
t = cur;
VasEBoot_free (cur->addr);
cur = cur->next;
VasEBoot_free (t);
}
acpi_tables = 0;
table_dsdt = 0;
}
static VasEBoot_err_t
VasEBoot_cmd_acpi (struct VasEBoot_extcmd_context *ctxt, int argc, char **args)
{
struct VasEBoot_arg_list *state = ctxt->state;
struct VasEBoot_acpi_rsdp_v10 *rsdp;
struct efiemu_acpi_table *cur, *t;
int i, mmapregion;
int numoftables;
/* Default values if no RSDP is found. */
rev1 = 1;
rev2 = 3;
facs_addr = 0;
playground = playground_ptr = 0;
playground_size = 0;
rsdp = (struct VasEBoot_acpi_rsdp_v10 *) VasEBoot_machine_acpi_get_rsdpv2 ();
if (! rsdp)
rsdp = VasEBoot_machine_acpi_get_rsdpv1 ();
VasEBoot_dprintf ("acpi", "RSDP @%p\n", rsdp);
if (rsdp)
{
VasEBoot_uint8_t *entry_ptr;
char *exclude = 0;
char *load_only = 0;
char *ptr;
VasEBoot_size_t tbl_addr_size;
struct VasEBoot_acpi_table_header *table_head;
exclude = state[OPTION_EXCLUDE].set ? VasEBoot_strdup (state[OPTION_EXCLUDE].arg) : 0;
if (exclude)
{
for (ptr = exclude; *ptr; ptr++)
*ptr = VasEBoot_tolower (*ptr);
}
load_only = state[OPTION_LOAD_ONLY].set ? VasEBoot_strdup (state[OPTION_LOAD_ONLY].arg) : 0;
if (load_only)
{
for (ptr = load_only; *ptr; ptr++)
*ptr = VasEBoot_tolower (*ptr);
}
/* Set revision variables to replicate the same version as host. */
rev1 = ! rsdp->revision;
rev2 = rsdp->revision;
if (rev2 && ((struct VasEBoot_acpi_table_header *) (VasEBoot_addr_t) ((struct VasEBoot_acpi_rsdp_v20 *) rsdp)->xsdt_addr) != NULL)
{
/* XSDT consists of header and an array of 64-bit pointers. */
table_head = (struct VasEBoot_acpi_table_header *) (VasEBoot_addr_t) ((struct VasEBoot_acpi_rsdp_v20 *) rsdp)->xsdt_addr;
tbl_addr_size = sizeof (((struct VasEBoot_acpi_rsdp_v20 *) rsdp)->xsdt_addr);
}
else
{
/* RSDT consists of header and an array of 32-bit pointers. */
table_head = (struct VasEBoot_acpi_table_header *) (VasEBoot_addr_t) rsdp->rsdt_addr;
tbl_addr_size = sizeof (rsdp->rsdt_addr);
}
/* Load host tables. */
for (entry_ptr = (VasEBoot_uint8_t *) (table_head + 1);
entry_ptr < (VasEBoot_uint8_t *) (((VasEBoot_uint8_t *) table_head) + table_head->length);
entry_ptr += tbl_addr_size)
{
char signature[5];
struct efiemu_acpi_table *table;
struct VasEBoot_acpi_table_header *curtable;
if (tbl_addr_size == sizeof (rsdp->rsdt_addr))
curtable = (struct VasEBoot_acpi_table_header *) (VasEBoot_addr_t) *((VasEBoot_uint32_t *) entry_ptr);
else
curtable = (struct VasEBoot_acpi_table_header *) (VasEBoot_addr_t) *((VasEBoot_uint64_t *) entry_ptr);
signature[4] = 0;
for (i = 0; i < 4;i++)
signature[i] = VasEBoot_tolower (curtable->signature[i]);
/* If it's FADT it contains addresses of DSDT and FACS. */
if (VasEBoot_strcmp (signature, "facp") == 0)
{
struct VasEBoot_acpi_table_header *dsdt;
struct VasEBoot_acpi_fadt *fadt = (struct VasEBoot_acpi_fadt *) curtable;
/* Set root header variables to the same values
as FADT by default. */
VasEBoot_memcpy (&root_oemid, &(fadt->hdr.oemid),
sizeof (root_oemid));
VasEBoot_memcpy (&root_oemtable, &(fadt->hdr.oemtable),
sizeof (root_oemtable));
root_oemrev = fadt->hdr.oemrev;
VasEBoot_memcpy (&root_creator_id, &(fadt->hdr.creator_id),
sizeof (root_creator_id));
root_creator_rev = fadt->hdr.creator_rev;
/* Load DSDT if not excluded. */
dsdt = (struct VasEBoot_acpi_table_header *)
(VasEBoot_addr_t) fadt->dsdt_addr;
if (dsdt && (! exclude || ! VasEBoot_strword (exclude, "dsdt"))
&& (! load_only || VasEBoot_strword (load_only, "dsdt"))
&& dsdt->length >= sizeof (*dsdt))
{
dsdt_size = dsdt->length;
table_dsdt = VasEBoot_malloc (dsdt->length);
if (! table_dsdt)
{
free_tables ();
VasEBoot_free (exclude);
VasEBoot_free (load_only);
return VasEBoot_errno;
}
VasEBoot_memcpy (table_dsdt, dsdt, dsdt->length);
}
/* Save FACS address. FACS shouldn't be overridden. */
facs_addr = fadt->facs_addr;
}
/* Skip excluded tables. */
if (exclude && VasEBoot_strword (exclude, signature))
continue;
if (load_only && ! VasEBoot_strword (load_only, signature))
continue;
/* Sanity check. */
if (curtable->length < sizeof (*curtable))
continue;
table = (struct efiemu_acpi_table *) VasEBoot_malloc
(sizeof (struct efiemu_acpi_table));
if (! table)
{
free_tables ();
VasEBoot_free (exclude);
VasEBoot_free (load_only);
return VasEBoot_errno;
}
table->size = curtable->length;
table->addr = VasEBoot_malloc (table->size);
playground_size += table->size;
if (! table->addr)
{
free_tables ();
VasEBoot_free (exclude);
VasEBoot_free (load_only);
VasEBoot_free (table);
return VasEBoot_errno;
}
table->next = acpi_tables;
acpi_tables = table;
VasEBoot_memcpy (table->addr, curtable, table->size);
}
VasEBoot_free (exclude);
VasEBoot_free (load_only);
}
/* Does user specify versions to generate? */
if (state[OPTION_V1].set || state[OPTION_V2].set)
{
rev1 = state[OPTION_V1].set;
if (state[OPTION_V2].set)
rev2 = rev2 ? : 2;
else
rev2 = 0;
}
/* Does user override root header information? */
if (state[OPTION_OEMID].set)
VasEBoot_strncpy (root_oemid, state[OPTION_OEMID].arg, sizeof (root_oemid));
if (state[OPTION_OEMTABLE].set)
VasEBoot_strncpy (root_oemtable, state[OPTION_OEMTABLE].arg, sizeof (root_oemtable));
if (state[OPTION_OEMTABLEREV].set)
root_oemrev = VasEBoot_strtoul (state[OPTION_OEMTABLEREV].arg, 0, 0);
if (state[OPTION_OEMTABLECREATOR].set)
VasEBoot_strncpy (root_creator_id, state[OPTION_OEMTABLECREATOR].arg, sizeof (root_creator_id));
if (state[OPTION_OEMTABLECREATORREV].set)
root_creator_rev = VasEBoot_strtoul (state[OPTION_OEMTABLECREATORREV].arg, 0, 0);
/* Load user tables */
for (i = 0; i < argc; i++)
{
VasEBoot_file_t file;
VasEBoot_size_t size;
char *buf;
file = VasEBoot_file_open (args[i], VAS_EBOOT_FILE_TYPE_ACPI_TABLE);
if (! file)
{
free_tables ();
return VasEBoot_errno;
}
size = VasEBoot_file_size (file);
if (size < sizeof (struct VasEBoot_acpi_table_header))
{
VasEBoot_file_close (file);
free_tables ();
return VasEBoot_error (VAS_EBOOT_ERR_BAD_OS, N_("premature end of file %s"),
args[i]);
}
buf = (char *) VasEBoot_malloc (size);
if (! buf)
{
VasEBoot_file_close (file);
free_tables ();
return VasEBoot_errno;
}
if (VasEBoot_file_read (file, buf, size) != (int) size)
{
VasEBoot_file_close (file);
free_tables ();
if (!VasEBoot_errno)
VasEBoot_error (VAS_EBOOT_ERR_BAD_OS, N_("premature end of file %s"),
args[i]);
return VasEBoot_errno;
}
VasEBoot_file_close (file);
if (VasEBoot_memcmp (((struct VasEBoot_acpi_table_header *) buf)->signature,
"DSDT", 4) == 0)
{
VasEBoot_free (table_dsdt);
table_dsdt = buf;
dsdt_size = size;
}
else
{
struct efiemu_acpi_table *table;
table = (struct efiemu_acpi_table *) VasEBoot_malloc
(sizeof (struct efiemu_acpi_table));
if (! table)
{
free_tables ();
return VasEBoot_errno;
}
table->size = size;
table->addr = buf;
playground_size += table->size;
table->next = acpi_tables;
acpi_tables = table;
}
}
numoftables = 0;
for (cur = acpi_tables; cur; cur = cur->next)
numoftables++;
/* DSDT. */
playground_size += dsdt_size;
/* RSDT. */
playground_size += sizeof (struct VasEBoot_acpi_table_header) + sizeof (VasEBoot_uint32_t) * numoftables;
/* RSDPv1. */
playground_size += sizeof (struct VasEBoot_acpi_rsdp_v10);
/* XSDT. */
playground_size += sizeof (struct VasEBoot_acpi_table_header) + sizeof (VasEBoot_uint64_t) * numoftables;
/* RSDPv2. */
playground_size += sizeof (struct VasEBoot_acpi_rsdp_v20);
playground = playground_ptr
= VasEBoot_mmap_malign_and_register (1, playground_size, &mmapregion,
VAS_EBOOT_MEMORY_ACPI, 0);
if (! playground)
{
free_tables ();
return VasEBoot_error (VAS_EBOOT_ERR_OUT_OF_MEMORY,
"couldn't allocate space for ACPI tables");
}
setup_common_tables ();
/* Request space for RSDPv1. */
if (rev1)
setv1table ();
/* Request space for RSDPv2+ and XSDT. */
if (rev2)
setv2table ();
for (cur = acpi_tables; cur;)
{
t = cur;
cur = cur->next;
VasEBoot_free (t);
}
acpi_tables = 0;
#if defined (__i386__) || defined (__x86_64__)
if (! state[OPTION_NO_EBDA].set)
{
VasEBoot_err_t err;
err = VasEBoot_acpi_create_ebda ();
if (err)
{
rsdpv1_new = 0;
rsdpv2_new = 0;
VasEBoot_mmap_free_and_unregister (mmapregion);
return err;
}
}
#endif
#ifdef VAS_EBOOT_MACHINE_EFI
{
static VasEBoot_guid_t acpi = VAS_EBOOT_EFI_ACPI_TABLE_GUID;
static VasEBoot_guid_t acpi20 = VAS_EBOOT_EFI_ACPI_20_TABLE_GUID;
VasEBoot_efi_system_table->boot_services->install_configuration_table (&acpi20,
VasEBoot_acpi_get_rsdpv2 ());
VasEBoot_efi_system_table->boot_services->install_configuration_table (&acpi,
VasEBoot_acpi_get_rsdpv1 ());
}
#endif
return VAS_EBOOT_ERR_NONE;
}
static VasEBoot_extcmd_t cmd;
VAS_EBOOT_MOD_INIT(acpi)
{
cmd = VasEBoot_register_extcmd_lockdown ("acpi", VasEBoot_cmd_acpi, 0,
N_("[-1|-2] [--exclude=TABLE1,TABLE2|"
"--load-only=TABLE1,TABLE2] FILE1"
" [FILE2] [...]"),
N_("Load host ACPI tables and tables "
"specified by arguments."),
options);
}
VAS_EBOOT_MOD_FINI(acpi)
{
VasEBoot_unregister_extcmd (cmd);
}

View File

@ -0,0 +1,454 @@
/*
* VAS_EBOOT -- GRand Unified Bootloader
* Copyright (C) 2010 Free Software Foundation, Inc.
*
* VAS_EBOOT 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.
*
* VAS_EBOOT 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 VAS_EBOOT. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef VAS_EBOOT_DSDT_TEST
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <errno.h>
#define VasEBoot_dprintf(cond, args...) printf ( args )
#define VasEBoot_printf printf
#define VasEBoot_util_fopen fopen
#define VasEBoot_memcmp memcmp
typedef uint64_t VasEBoot_uint64_t;
typedef uint32_t VasEBoot_uint32_t;
typedef uint16_t VasEBoot_uint16_t;
typedef uint8_t VasEBoot_uint8_t;
#endif
#include <VasEBoot/acpi.h>
#ifndef VAS_EBOOT_DSDT_TEST
#include <VasEBoot/i18n.h>
#else
#define _(x) x
#define N_(x) x
#endif
#ifndef VAS_EBOOT_DSDT_TEST
#include <VasEBoot/mm.h>
#include <VasEBoot/misc.h>
#include <VasEBoot/time.h>
#include <VasEBoot/cpu/io.h>
#endif
static inline VasEBoot_uint32_t
decode_length (const VasEBoot_uint8_t *ptr, int *numlen)
{
int num_bytes, i;
VasEBoot_uint32_t ret;
if (*ptr < 64)
{
if (numlen)
*numlen = 1;
return *ptr;
}
num_bytes = *ptr >> 6;
if (numlen)
*numlen = num_bytes + 1;
ret = *ptr & 0xf;
ptr++;
for (i = 0; i < num_bytes; i++)
{
ret |= *ptr << (8 * i + 4);
ptr++;
}
return ret;
}
static inline VasEBoot_uint32_t
skip_name_string (const VasEBoot_uint8_t *ptr, const VasEBoot_uint8_t *end)
{
const VasEBoot_uint8_t *ptr0 = ptr;
while (ptr < end && (*ptr == '^' || *ptr == '\\'))
ptr++;
switch (*ptr)
{
case '.':
ptr++;
ptr += 8;
break;
case '/':
ptr++;
ptr += 1 + (*ptr) * 4;
break;
case 0:
ptr++;
break;
default:
ptr += 4;
break;
}
return ptr - ptr0;
}
static inline VasEBoot_uint32_t
skip_data_ref_object (const VasEBoot_uint8_t *ptr, const VasEBoot_uint8_t *end)
{
VasEBoot_dprintf ("acpi", "data type = 0x%x\n", *ptr);
switch (*ptr)
{
case VAS_EBOOT_ACPI_OPCODE_PACKAGE:
case VAS_EBOOT_ACPI_OPCODE_BUFFER:
return 1 + decode_length (ptr + 1, 0);
case VAS_EBOOT_ACPI_OPCODE_ZERO:
case VAS_EBOOT_ACPI_OPCODE_ONES:
case VAS_EBOOT_ACPI_OPCODE_ONE:
return 1;
case VAS_EBOOT_ACPI_OPCODE_BYTE_CONST:
return 2;
case VAS_EBOOT_ACPI_OPCODE_WORD_CONST:
return 3;
case VAS_EBOOT_ACPI_OPCODE_DWORD_CONST:
return 5;
case VAS_EBOOT_ACPI_OPCODE_STRING_CONST:
{
const VasEBoot_uint8_t *ptr0 = ptr;
for (ptr++; ptr < end && *ptr; ptr++);
if (ptr == end)
return 0;
return ptr - ptr0 + 1;
}
default:
if (*ptr == '^' || *ptr == '\\' || *ptr == '_'
|| (*ptr >= 'A' && *ptr <= 'Z'))
return skip_name_string (ptr, end);
VasEBoot_printf ("Unknown opcode 0x%x\n", *ptr);
return 0;
}
}
static inline VasEBoot_uint32_t
skip_term (const VasEBoot_uint8_t *ptr, const VasEBoot_uint8_t *end)
{
VasEBoot_uint32_t add;
const VasEBoot_uint8_t *ptr0 = ptr;
switch(*ptr)
{
case VAS_EBOOT_ACPI_OPCODE_ADD:
case VAS_EBOOT_ACPI_OPCODE_AND:
case VAS_EBOOT_ACPI_OPCODE_CONCAT:
case VAS_EBOOT_ACPI_OPCODE_CONCATRES:
case VAS_EBOOT_ACPI_OPCODE_DIVIDE:
case VAS_EBOOT_ACPI_OPCODE_INDEX:
case VAS_EBOOT_ACPI_OPCODE_LSHIFT:
case VAS_EBOOT_ACPI_OPCODE_MOD:
case VAS_EBOOT_ACPI_OPCODE_MULTIPLY:
case VAS_EBOOT_ACPI_OPCODE_NAND:
case VAS_EBOOT_ACPI_OPCODE_NOR:
case VAS_EBOOT_ACPI_OPCODE_OR:
case VAS_EBOOT_ACPI_OPCODE_RSHIFT:
case VAS_EBOOT_ACPI_OPCODE_SUBTRACT:
case VAS_EBOOT_ACPI_OPCODE_TOSTRING:
case VAS_EBOOT_ACPI_OPCODE_XOR:
/*
* Parameters for these opcodes: TermArg, TermArg Target, see ACPI
* spec r5.0, page 828f.
*/
ptr++;
ptr += add = skip_term (ptr, end);
if (!add)
return 0;
ptr += add = skip_term (ptr, end);
if (!add)
return 0;
ptr += skip_name_string (ptr, end);
break;
default:
return skip_data_ref_object (ptr, end);
}
return ptr - ptr0;
}
static inline VasEBoot_uint32_t
skip_ext_op (const VasEBoot_uint8_t *ptr, const VasEBoot_uint8_t *end)
{
const VasEBoot_uint8_t *ptr0 = ptr;
int add;
VasEBoot_dprintf ("acpi", "Extended opcode: 0x%x\n", *ptr);
switch (*ptr)
{
case VAS_EBOOT_ACPI_EXTOPCODE_MUTEX:
ptr++;
ptr += skip_name_string (ptr, end);
ptr++;
break;
case VAS_EBOOT_ACPI_EXTOPCODE_EVENT_OP:
ptr++;
ptr += skip_name_string (ptr, end);
break;
case VAS_EBOOT_ACPI_EXTOPCODE_OPERATION_REGION:
ptr++;
ptr += skip_name_string (ptr, end);
ptr++;
ptr += add = skip_term (ptr, end);
if (!add)
return 0;
ptr += add = skip_term (ptr, end);
if (!add)
return 0;
break;
case VAS_EBOOT_ACPI_EXTOPCODE_FIELD_OP:
case VAS_EBOOT_ACPI_EXTOPCODE_DEVICE_OP:
case VAS_EBOOT_ACPI_EXTOPCODE_PROCESSOR_OP:
case VAS_EBOOT_ACPI_EXTOPCODE_POWER_RES_OP:
case VAS_EBOOT_ACPI_EXTOPCODE_THERMAL_ZONE_OP:
case VAS_EBOOT_ACPI_EXTOPCODE_INDEX_FIELD_OP:
case VAS_EBOOT_ACPI_EXTOPCODE_BANK_FIELD_OP:
ptr++;
ptr += decode_length (ptr, 0);
break;
default:
VasEBoot_printf ("Unexpected extended opcode: 0x%x\n", *ptr);
return 0;
}
return ptr - ptr0;
}
static int
get_sleep_type (VasEBoot_uint8_t *table, VasEBoot_uint8_t *ptr, VasEBoot_uint8_t *end,
VasEBoot_uint8_t *scope, int scope_len)
{
VasEBoot_uint8_t *prev = table;
if (!ptr)
ptr = table + sizeof (struct VasEBoot_acpi_table_header);
while (ptr < end && prev < ptr)
{
int add;
prev = ptr;
VasEBoot_dprintf ("acpi", "Opcode 0x%x\n", *ptr);
VasEBoot_dprintf ("acpi", "Tell %x\n", (unsigned) (ptr - table));
switch (*ptr)
{
case VAS_EBOOT_ACPI_OPCODE_EXTOP:
ptr++;
ptr += add = skip_ext_op (ptr, end);
if (!add)
return -1;
break;
case VAS_EBOOT_ACPI_OPCODE_CREATE_DWORD_FIELD:
case VAS_EBOOT_ACPI_OPCODE_CREATE_WORD_FIELD:
case VAS_EBOOT_ACPI_OPCODE_CREATE_BYTE_FIELD:
{
ptr += 5;
ptr += add = skip_data_ref_object (ptr, end);
if (!add)
return -1;
ptr += 4;
break;
}
case VAS_EBOOT_ACPI_OPCODE_NAME:
ptr++;
if ((!scope || VasEBoot_memcmp (scope, "\\", scope_len) == 0) &&
(VasEBoot_memcmp (ptr, "_S5_", 4) == 0 || VasEBoot_memcmp (ptr, "\\_S5_", 4) == 0))
{
int ll;
VasEBoot_uint8_t *ptr2 = ptr;
VasEBoot_dprintf ("acpi", "S5 found\n");
ptr2 += skip_name_string (ptr, end);
if (*ptr2 != 0x12)
{
VasEBoot_printf ("Unknown opcode in _S5: 0x%x\n", *ptr2);
return -1;
}
ptr2++;
decode_length (ptr2, &ll);
ptr2 += ll;
ptr2++;
switch (*ptr2)
{
case VAS_EBOOT_ACPI_OPCODE_ZERO:
return 0;
case VAS_EBOOT_ACPI_OPCODE_ONE:
return 1;
case VAS_EBOOT_ACPI_OPCODE_BYTE_CONST:
return ptr2[1];
default:
VasEBoot_printf ("Unknown data type in _S5: 0x%x\n", *ptr2);
return -1;
}
}
ptr += add = skip_name_string (ptr, end);
if (!add)
return -1;
ptr += add = skip_data_ref_object (ptr, end);
if (!add)
return -1;
break;
case VAS_EBOOT_ACPI_OPCODE_ALIAS:
ptr++;
/* We need to skip two name strings */
ptr += add = skip_name_string (ptr, end);
if (!add)
return -1;
ptr += add = skip_name_string (ptr, end);
if (!add)
return -1;
break;
case VAS_EBOOT_ACPI_OPCODE_SCOPE:
{
int scope_sleep_type;
int ll;
VasEBoot_uint8_t *name;
int name_len;
ptr++;
add = decode_length (ptr, &ll);
name = ptr + ll;
name_len = skip_name_string (name, ptr + add);
if (!name_len)
return -1;
scope_sleep_type = get_sleep_type (table, name + name_len,
ptr + add, name, name_len);
if (scope_sleep_type != -2)
return scope_sleep_type;
ptr += add;
break;
}
case VAS_EBOOT_ACPI_OPCODE_IF:
case VAS_EBOOT_ACPI_OPCODE_METHOD:
{
ptr++;
ptr += decode_length (ptr, 0);
break;
}
default:
VasEBoot_printf ("Unknown opcode 0x%x\n", *ptr);
return -1;
}
}
return -2;
}
#ifdef VAS_EBOOT_DSDT_TEST
int
main (int argc, char **argv)
{
FILE *f;
size_t len;
unsigned char *buf;
if (argc < 2)
printf ("Usage: %s FILE\n", argv[0]);
f = VasEBoot_util_fopen (argv[1], "rb");
if (!f)
{
printf ("Couldn't open file\n");
return 1;
}
fseek (f, 0, SEEK_END);
len = ftell (f);
fseek (f, 0, SEEK_SET);
buf = malloc (len);
if (!buf)
{
printf (_("error: %s.\n"), _("out of memory"));
fclose (f);
return 2;
}
if (fread (buf, 1, len, f) != len)
{
printf (_("cannot read `%s': %s"), argv[1], strerror (errno));
free (buf);
fclose (f);
return 2;
}
printf ("Sleep type = %d\n", get_sleep_type (buf, NULL, buf + len, NULL, 0));
free (buf);
fclose (f);
return 0;
}
#else
void
VasEBoot_acpi_halt (void)
{
struct VasEBoot_acpi_rsdp_v20 *rsdp2;
struct VasEBoot_acpi_rsdp_v10 *rsdp1;
struct VasEBoot_acpi_table_header *rsdt;
VasEBoot_uint32_t *entry_ptr;
VasEBoot_uint32_t port = 0;
int sleep_type = -1;
rsdp2 = VasEBoot_acpi_get_rsdpv2 ();
if (rsdp2)
rsdp1 = &(rsdp2->rsdpv1);
else
rsdp1 = VasEBoot_acpi_get_rsdpv1 ();
VasEBoot_dprintf ("acpi", "rsdp1=%p\n", rsdp1);
if (!rsdp1)
return;
rsdt = (struct VasEBoot_acpi_table_header *) (VasEBoot_addr_t) rsdp1->rsdt_addr;
for (entry_ptr = (VasEBoot_uint32_t *) (rsdt + 1);
entry_ptr < (VasEBoot_uint32_t *) (((VasEBoot_uint8_t *) rsdt)
+ rsdt->length);
entry_ptr++)
{
if (VasEBoot_memcmp ((void *) (VasEBoot_addr_t) *entry_ptr, "FACP", 4) == 0)
{
struct VasEBoot_acpi_fadt *fadt
= ((struct VasEBoot_acpi_fadt *) (VasEBoot_addr_t) *entry_ptr);
struct VasEBoot_acpi_table_header *dsdt
= (struct VasEBoot_acpi_table_header *) (VasEBoot_addr_t) fadt->dsdt_addr;
VasEBoot_uint8_t *buf = (VasEBoot_uint8_t *) dsdt;
port = fadt->pm1a;
VasEBoot_dprintf ("acpi", "PM1a port=%x\n", port);
if (VasEBoot_memcmp (dsdt->signature, "DSDT",
sizeof (dsdt->signature)) == 0
&& sleep_type < 0)
sleep_type = get_sleep_type (buf, NULL, buf + dsdt->length,
NULL, 0);
}
else if (VasEBoot_memcmp ((void *) (VasEBoot_addr_t) *entry_ptr, "SSDT", 4) == 0
&& sleep_type < 0)
{
struct VasEBoot_acpi_table_header *ssdt
= (struct VasEBoot_acpi_table_header *) (VasEBoot_addr_t) *entry_ptr;
VasEBoot_uint8_t *buf = (VasEBoot_uint8_t *) ssdt;
VasEBoot_dprintf ("acpi", "SSDT = %p\n", ssdt);
sleep_type = get_sleep_type (buf, NULL, buf + ssdt->length, NULL, 0);
}
}
VasEBoot_dprintf ("acpi", "SLP_TYP = %d, port = 0x%x\n", sleep_type, port);
if (port && sleep_type >= 0 && sleep_type < 8)
VasEBoot_outw (VAS_EBOOT_ACPI_SLP_EN | (sleep_type << VAS_EBOOT_ACPI_SLP_TYP_OFFSET),
port & 0xffff);
VasEBoot_millisleep (1500);
/* TRANSLATORS: It's computer shutdown using ACPI, not disabling ACPI. */
VasEBoot_puts_ (N_("ACPI shutdown failed"));
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,133 @@
/*
* VAS_EBOOT -- GRand Unified Bootloader
* Copyright (C) 2020, 2022 Free Software Foundation, Inc.
* Copyright (C) 2020, 2022, 2025 IBM Corporation
*
* VAS_EBOOT 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.
*
* VAS_EBOOT 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 VAS_EBOOT. If not, see <http://www.gnu.org/licenses/>.
*/
#include <VasEBoot/crypto.h>
#include <libtasn1.h>
extern asn1_node VasEBoot_gnutls_gnutls_asn;
extern asn1_node VasEBoot_gnutls_pkix_asn;
#define VAS_EBOOT_MAX_OID_LEN 32
/* RSA public key. */
#define VAS_EBOOT_MAX_MPI 2
#define VAS_EBOOT_RSA_PK_MODULUS 0
#define VAS_EBOOT_RSA_PK_EXPONENT 1
/* Certificate fingerprint. */
#define VAS_EBOOT_MAX_FINGERPRINT 3
#define VAS_EBOOT_FINGERPRINT_SHA256 0
#define VAS_EBOOT_FINGERPRINT_SHA384 1
#define VAS_EBOOT_FINGERPRINT_SHA512 2
/* Max size of hash data. */
#define VAS_EBOOT_MAX_HASH_LEN 64
/*
* One or more x509 certificates. We do limited parsing:
* extracting only the version, serial, issuer, subject, RSA public key
* and key size.
* Also, hold the sha256, sha384, and sha512 fingerprint of the certificate.
*/
struct x509_certificate
{
struct x509_certificate *next;
VasEBoot_uint8_t version;
VasEBoot_uint8_t *serial;
VasEBoot_size_t serial_len;
char *issuer;
VasEBoot_size_t issuer_len;
char *subject;
VasEBoot_size_t subject_len;
/* We only support RSA public keys. This encodes [modulus, publicExponent]. */
gcry_mpi_t mpis[VAS_EBOOT_MAX_MPI];
VasEBoot_int32_t modulus_size;
VasEBoot_uint8_t fingerprint[VAS_EBOOT_MAX_FINGERPRINT][VAS_EBOOT_MAX_HASH_LEN];
};
typedef struct x509_certificate VasEBoot_x509_cert_t;
/* A PKCS#7 signed data signer info. */
struct pkcs7_signer
{
const gcry_md_spec_t *hash;
gcry_mpi_t sig_mpi;
};
typedef struct pkcs7_signer VasEBoot_pkcs7_signer_t;
/*
* A PKCS#7 signed data message. We make no attempt to match intelligently, so
* we don't save any info about the signer.
*/
struct pkcs7_data
{
VasEBoot_int32_t signer_count;
VasEBoot_pkcs7_signer_t *signers;
};
typedef struct pkcs7_data VasEBoot_pkcs7_data_t;
/*
* Import a DER-encoded certificate at 'data', of size 'size'. Place the results
* into 'results', which must be already allocated.
*/
extern VasEBoot_err_t
VasEBoot_x509_cert_parse (const void *data, VasEBoot_size_t size, VasEBoot_x509_cert_t *results);
/*
* Release all the storage associated with the x509 certificate. If the caller
* dynamically allocated the certificate, it must free it. The caller is also
* responsible for maintenance of the linked list.
*/
extern void
VasEBoot_x509_cert_release (VasEBoot_x509_cert_t *cert);
/*
* Parse a PKCS#7 message, which must be a signed data message. The message must
* be in 'sigbuf' and of size 'data_size'. The result is placed in 'msg', which
* must already be allocated.
*/
extern VasEBoot_err_t
VasEBoot_pkcs7_data_parse (const void *sigbuf, VasEBoot_size_t data_size, VasEBoot_pkcs7_data_t *msg);
/*
* Release all the storage associated with the PKCS#7 message. If the caller
* dynamically allocated the message, it must free it.
*/
extern void
VasEBoot_pkcs7_data_release (VasEBoot_pkcs7_data_t *msg);
/* Do libtasn1 init. */
extern int
VasEBoot_asn1_init (void);
/*
* Read a value from an ASN1 node, allocating memory to store it. It will work
* for anything where the size libtasn1 returns is right:
* - Integers
* - Octet strings
* - DER encoding of other structures
*
* It will _not_ work for things where libtasn1 size requires adjustment:
* - Strings that require an extra null byte at the end
* - Bit strings because libtasn1 returns the length in bits, not bytes.
*
* If the function returns a non-NULL value, the caller must free it.
*/
extern void *
VasEBoot_asn1_allocate_and_read (asn1_node node, const char *name, const char *friendly_name,
VasEBoot_int32_t *content_size);

View File

@ -0,0 +1,99 @@
/*
* VAS_EBOOT -- GRand Unified Bootloader
* Copyright (C) 2020, 2022 Free Software Foundation, Inc.
* Copyright (C) 2020, 2022, 2025 IBM Corporation
*
* VAS_EBOOT 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.
*
* VAS_EBOOT 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 VAS_EBOOT. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libtasn1.h>
#include <VasEBoot/types.h>
#include <VasEBoot/err.h>
#include <VasEBoot/mm.h>
#include <VasEBoot/crypto.h>
#include <VasEBoot/misc.h>
#include <VasEBoot/gcrypt/gcrypt.h>
#include "appendedsig.h"
asn1_node VasEBoot_gnutls_gnutls_asn = NULL;
asn1_node VasEBoot_gnutls_pkix_asn = NULL;
extern const asn1_static_node VasEBoot_gnutls_asn1_tab[];
extern const asn1_static_node VasEBoot_pkix_asn1_tab[];
/*
* Read a value from an ASN1 node, allocating memory to store it. It will work
* for anything where the size libtasn1 returns is right:
* - Integers
* - Octet strings
* - DER encoding of other structures
*
* It will _not_ work for things where libtasn1 size requires adjustment:
* - Strings that require an extra NULL byte at the end
* - Bit strings because libtasn1 returns the length in bits, not bytes.
*
* If the function returns a non-NULL value, the caller must free it.
*/
void *
VasEBoot_asn1_allocate_and_read (asn1_node node, const char *name, const char *friendly_name,
VasEBoot_int32_t *content_size)
{
VasEBoot_int32_t result;
VasEBoot_uint8_t *tmpstr = NULL;
VasEBoot_int32_t tmpstr_size = 0;
result = asn1_read_value (node, name, NULL, &tmpstr_size);
if (result != ASN1_MEM_ERROR)
{
VasEBoot_error (VAS_EBOOT_ERR_BAD_FILE_TYPE, "reading size of %s did not return expected status: %s",
friendly_name, asn1_strerror (result)) ;
return NULL;
}
tmpstr = VasEBoot_malloc (tmpstr_size);
if (tmpstr == NULL)
{
VasEBoot_error (VAS_EBOOT_ERR_OUT_OF_MEMORY, "could not allocate memory to store %s",
friendly_name) ;
return NULL;
}
result = asn1_read_value (node, name, tmpstr, &tmpstr_size);
if (result != ASN1_SUCCESS)
{
VasEBoot_free (tmpstr);
VasEBoot_error (VAS_EBOOT_ERR_BAD_FILE_TYPE, "error reading %s: %s", friendly_name,
asn1_strerror (result)) ;
return NULL;
}
*content_size = tmpstr_size;
return tmpstr;
}
int
VasEBoot_asn1_init (void)
{
int res;
res = asn1_array2tree (VasEBoot_gnutls_asn1_tab, &VasEBoot_gnutls_gnutls_asn, NULL);
if (res != ASN1_SUCCESS)
return res;
res = asn1_array2tree (VasEBoot_pkix_asn1_tab, &VasEBoot_gnutls_pkix_asn, NULL);
return res;
}

View File

@ -0,0 +1,148 @@
#include <VasEBoot/mm.h>
#include <libtasn1.h>
/*
* Imported from gnutls.asn.
* https://github.com/gnutls/gnutls/blob/master/lib/gnutls.asn
*/
const asn1_static_node VasEBoot_gnutls_asn1_tab[] = {
{ "GNUTLS", 536872976, NULL },
{ NULL, 1073741836, NULL },
{ "RSAPublicKey", 1610612741, NULL },
{ "modulus", 1073741827, NULL },
{ "publicExponent", 3, NULL },
{ "RSAPrivateKey", 1610612741, NULL },
{ "version", 1073741827, NULL },
{ "modulus", 1073741827, NULL },
{ "publicExponent", 1073741827, NULL },
{ "privateExponent", 1073741827, NULL },
{ "prime1", 1073741827, NULL },
{ "prime2", 1073741827, NULL },
{ "exponent1", 1073741827, NULL },
{ "exponent2", 1073741827, NULL },
{ "coefficient", 1073741827, NULL },
{ "otherPrimeInfos", 16386, "OtherPrimeInfos"},
{ "ProvableSeed", 1610612741, NULL },
{ "algorithm", 1073741836, NULL },
{ "seed", 7, NULL },
{ "OtherPrimeInfos", 1612709899, NULL },
{ "MAX", 1074266122, "1"},
{ NULL, 2, "OtherPrimeInfo"},
{ "OtherPrimeInfo", 1610612741, NULL },
{ "prime", 1073741827, NULL },
{ "exponent", 1073741827, NULL },
{ "coefficient", 3, NULL },
{ "AlgorithmIdentifier", 1610612741, NULL },
{ "algorithm", 1073741836, NULL },
{ "parameters", 541081613, NULL },
{ "algorithm", 1, NULL },
{ "DigestInfo", 1610612741, NULL },
{ "digestAlgorithm", 1073741826, "DigestAlgorithmIdentifier"},
{ "digest", 7, NULL },
{ "DigestAlgorithmIdentifier", 1073741826, "AlgorithmIdentifier"},
{ "DSAPublicKey", 1073741827, NULL },
{ "DSAParameters", 1610612741, NULL },
{ "p", 1073741827, NULL },
{ "q", 1073741827, NULL },
{ "g", 3, NULL },
{ "DSASignatureValue", 1610612741, NULL },
{ "r", 1073741827, NULL },
{ "s", 3, NULL },
{ "DSAPrivateKey", 1610612741, NULL },
{ "version", 1073741827, NULL },
{ "p", 1073741827, NULL },
{ "q", 1073741827, NULL },
{ "g", 1073741827, NULL },
{ "Y", 1073741827, NULL },
{ "priv", 3, NULL },
{ "DHParameter", 1610612741, NULL },
{ "prime", 1073741827, NULL },
{ "base", 1073741827, NULL },
{ "privateValueLength", 16387, NULL },
{ "pkcs-11-ec-Parameters", 1610612754, NULL },
{ "oId", 1073741836, NULL },
{ "curveName", 31, NULL },
{ "ECParameters", 1610612754, NULL },
{ "namedCurve", 12, NULL },
{ "ECPrivateKey", 1610612741, NULL },
{ "Version", 1073741827, NULL },
{ "privateKey", 1073741831, NULL },
{ "parameters", 1610637314, "ECParameters"},
{ NULL, 2056, "0"},
{ "publicKey", 536895494, NULL },
{ NULL, 2056, "1"},
{ "PrincipalName", 1610612741, NULL },
{ "name-type", 1610620931, NULL },
{ NULL, 2056, "0"},
{ "name-string", 536879115, NULL },
{ NULL, 1073743880, "1"},
{ NULL, 27, NULL },
{ "KRB5PrincipalName", 1610612741, NULL },
{ "realm", 1610620955, NULL },
{ NULL, 2056, "0"},
{ "principalName", 536879106, "PrincipalName"},
{ NULL, 2056, "1"},
{ "RSAPSSParameters", 1610612741, NULL },
{ "hashAlgorithm", 1610637314, "AlgorithmIdentifier"},
{ NULL, 2056, "0"},
{ "maskGenAlgorithm", 1610637314, "AlgorithmIdentifier"},
{ NULL, 2056, "1"},
{ "saltLength", 1610653699, NULL },
{ NULL, 1073741833, "20"},
{ NULL, 2056, "2"},
{ "trailerField", 536911875, NULL },
{ NULL, 1073741833, "1"},
{ NULL, 2056, "3"},
{ "RSAOAEPParameters", 1610612741, NULL },
{ "hashAlgorithm", 1610637314, "AlgorithmIdentifier"},
{ NULL, 2056, "0"},
{ "maskGenAlgorithm", 1610637314, "AlgorithmIdentifier"},
{ NULL, 2056, "1"},
{ "pSourceFunc", 536895490, "AlgorithmIdentifier"},
{ NULL, 2056, "2"},
{ "GOSTParameters", 1610612741, NULL },
{ "publicKeyParamSet", 1073741836, NULL },
{ "digestParamSet", 16396, NULL },
{ "GOSTParametersOld", 1610612741, NULL },
{ "publicKeyParamSet", 1073741836, NULL },
{ "digestParamSet", 1073741836, NULL },
{ "encryptionParamSet", 16396, NULL },
{ "GOSTPrivateKey", 1073741831, NULL },
{ "GOSTPrivateKeyOld", 1073741827, NULL },
{ "IssuerSignTool", 1610612741, NULL },
{ "signTool", 1073741858, NULL },
{ "cATool", 1073741858, NULL },
{ "signToolCert", 1073741858, NULL },
{ "cAToolCert", 34, NULL },
{ "Gost28147-89-EncryptedKey", 1610612741, NULL },
{ "encryptedKey", 1073741831, NULL },
{ "maskKey", 1610637319, NULL },
{ NULL, 4104, "0"},
{ "macKey", 7, NULL },
{ "SubjectPublicKeyInfo", 1610612741, NULL },
{ "algorithm", 1073741826, "AlgorithmIdentifier"},
{ "subjectPublicKey", 6, NULL },
{ "GostR3410-TransportParameters", 1610612741, NULL },
{ "encryptionParamSet", 1073741836, NULL },
{ "ephemeralPublicKey", 1610637314, "SubjectPublicKeyInfo"},
{ NULL, 4104, "0"},
{ "ukm", 7, NULL },
{ "GostR3410-KeyTransport", 1610612741, NULL },
{ "sessionEncryptedKey", 1073741826, "Gost28147-89-EncryptedKey"},
{ "transportParameters", 536895490, "GostR3410-TransportParameters"},
{ NULL, 4104, "0"},
{ "TPMKey", 1610612741, NULL },
{ "type", 1073741836, NULL },
{ "emptyAuth", 1610637316, NULL },
{ NULL, 2056, "0"},
{ "parent", 1073741827, NULL },
{ "pubkey", 1073741831, NULL },
{ "privkey", 7, NULL },
{ "MLDSAPrivateKey", 536870917, NULL },
{ "version", 1073741827, NULL },
{ "privateKeyAlgorithm", 1073741826, "AlgorithmIdentifier"},
{ "privateKey", 1073741831, NULL },
{ "publicKey", 536895495, NULL },
{ NULL, 2056, "1"},
{ NULL, 0, NULL }
};

View File

@ -0,0 +1,452 @@
/*
* VAS_EBOOT -- GRand Unified Bootloader
* Copyright (C) 2020, 2022 Free Software Foundation, Inc.
* Copyright (C) 2020, 2022, 2025 IBM Corporation
*
* VAS_EBOOT 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.
*
* VAS_EBOOT 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 VAS_EBOOT. If not, see <http://www.gnu.org/licenses/>.
*/
#include "appendedsig.h"
#include <VasEBoot/misc.h>
#include <VasEBoot/crypto.h>
#include <VasEBoot/gcrypt/gcrypt.h>
#include <sys/types.h>
static char asn1_error[ASN1_MAX_ERROR_DESCRIPTION_SIZE];
/* RFC 5652 s 5.1. */
static const char *signedData_oid = "1.2.840.113549.1.7.2";
/* RFC 4055 s 2.1. */
static const char *sha256_oid = "2.16.840.1.101.3.4.2.1";
static const char *sha512_oid = "2.16.840.1.101.3.4.2.3";
static VasEBoot_err_t
process_content (VasEBoot_uint8_t *content, VasEBoot_int32_t size, VasEBoot_pkcs7_data_t *msg)
{
VasEBoot_int32_t res;
asn1_node signed_part;
VasEBoot_err_t err = VAS_EBOOT_ERR_NONE;
char algo_oid[VAS_EBOOT_MAX_OID_LEN];
VasEBoot_int32_t algo_oid_size;
VasEBoot_int32_t algo_count;
VasEBoot_int32_t signer_count;
VasEBoot_int32_t i;
char version;
VasEBoot_int32_t version_size = sizeof (version);
VasEBoot_uint8_t *result_buf;
VasEBoot_int32_t result_size = 0;
VasEBoot_int32_t crls_size = 0;
gcry_error_t gcry_err;
bool sha256_in_da, sha256_in_si, sha512_in_da, sha512_in_si;
char *da_path;
char *si_sig_path;
char *si_da_path;
res = asn1_create_element (VasEBoot_gnutls_pkix_asn, "PKIX1.pkcs-7-SignedData", &signed_part);
if (res != ASN1_SUCCESS)
return VasEBoot_error (VAS_EBOOT_ERR_OUT_OF_MEMORY,
"could not create ASN.1 structure for PKCS#7 signed part");
res = asn1_der_decoding2 (&signed_part, content, &size,
ASN1_DECODE_FLAG_STRICT_DER, asn1_error);
if (res != ASN1_SUCCESS)
{
err = VasEBoot_error (VAS_EBOOT_ERR_BAD_SIGNATURE,
"error reading PKCS#7 signed data: %s", asn1_error);
goto cleanup_signed_part;
}
/*
* SignedData ::= SEQUENCE {
* version CMSVersion,
* digestAlgorithms DigestAlgorithmIdentifiers,
* encapContentInfo EncapsulatedContentInfo,
* certificates [0] IMPLICIT CertificateSet OPTIONAL,
* crls [1] IMPLICIT RevocationInfoChoices OPTIONAL,
* signerInfos SignerInfos }
*/
res = asn1_read_value (signed_part, "version", &version, &version_size);
if (res != ASN1_SUCCESS)
{
err = VasEBoot_error (VAS_EBOOT_ERR_BAD_SIGNATURE, "error reading signedData version: %s",
asn1_strerror (res));
goto cleanup_signed_part;
}
/* Signature version must be 1 because appended signature only support v1. */
if (version != 1)
{
err = VasEBoot_error (VAS_EBOOT_ERR_BAD_SIGNATURE,
"unexpected signature version v%d, only v1 supported", version);
goto cleanup_signed_part;
}
/*
* digestAlgorithms DigestAlgorithmIdentifiers
*
* DigestAlgorithmIdentifiers ::= SET OF DigestAlgorithmIdentifier
* DigestAlgorithmIdentifer is an X.509 AlgorithmIdentifier (10.1.1)
*
* RFC 4055 s 2.1:
* sha256Identifier AlgorithmIdentifier ::= { id-sha256, NULL }
* sha512Identifier AlgorithmIdentifier ::= { id-sha512, NULL }
*
* We only support 1 element in the set, and we do not check parameters atm.
*/
res = asn1_number_of_elements (signed_part, "digestAlgorithms", &algo_count);
if (res != ASN1_SUCCESS)
{
err = VasEBoot_error (VAS_EBOOT_ERR_BAD_SIGNATURE, "error counting number of digest algorithms: %s",
asn1_strerror (res));
goto cleanup_signed_part;
}
if (algo_count <= 0)
{
err = VasEBoot_error (VAS_EBOOT_ERR_BAD_SIGNATURE, "a minimum of 1 digest algorithm is required");
goto cleanup_signed_part;
}
if (algo_count > 2)
{
err = VasEBoot_error (VAS_EBOOT_ERR_NOT_IMPLEMENTED_YET, "a maximum of 2 digest algorithms is supported");
goto cleanup_signed_part;
}
sha256_in_da = false;
sha512_in_da = false;
for (i = 0; i < algo_count; i++)
{
da_path = VasEBoot_xasprintf ("digestAlgorithms.?%d.algorithm", i + 1);
if (da_path == NULL)
{
err = VasEBoot_error (VAS_EBOOT_ERR_OUT_OF_MEMORY,
"could not allocate path for digest algorithm parsing path");
goto cleanup_signed_part;
}
algo_oid_size = sizeof (algo_oid);
res = asn1_read_value (signed_part, da_path, algo_oid, &algo_oid_size);
if (res != ASN1_SUCCESS)
{
err = VasEBoot_error (VAS_EBOOT_ERR_BAD_SIGNATURE, "error reading digest algorithm: %s",
asn1_strerror (res));
VasEBoot_free (da_path);
goto cleanup_signed_part;
}
if (VasEBoot_strncmp (sha512_oid, algo_oid, algo_oid_size) == 0)
{
if (sha512_in_da == false)
sha512_in_da = true;
else
{
err = VasEBoot_error (VAS_EBOOT_ERR_BAD_SIGNATURE,
"SHA-512 specified twice in digest algorithm list");
VasEBoot_free (da_path);
goto cleanup_signed_part;
}
}
else if (VasEBoot_strncmp (sha256_oid, algo_oid, algo_oid_size) == 0)
{
if (sha256_in_da == false)
sha256_in_da = true;
else
{
err = VasEBoot_error (VAS_EBOOT_ERR_BAD_SIGNATURE,
"SHA-256 specified twice in digest algorithm list");
VasEBoot_free (da_path);
goto cleanup_signed_part;
}
}
else
{
err = VasEBoot_error (VAS_EBOOT_ERR_NOT_IMPLEMENTED_YET,
"only SHA-256 and SHA-512 hashes are supported, found OID %s",
algo_oid);
VasEBoot_free (da_path);
goto cleanup_signed_part;
}
VasEBoot_free (da_path);
}
/* At this point, at least one of sha{256,512}_in_da must be true. */
/*
* We ignore the certificates, but we don't permit CRLs. A CRL entry might be
* revoking the certificate we're using, and we have no way of dealing with
* that at the moment.
*/
res = asn1_read_value (signed_part, "crls", NULL, &crls_size);
if (res != ASN1_ELEMENT_NOT_FOUND)
{
err = VasEBoot_error (VAS_EBOOT_ERR_NOT_IMPLEMENTED_YET,
"PKCS#7 messages with embedded CRLs are not supported");
goto cleanup_signed_part;
}
/* Read the signatures */
res = asn1_number_of_elements (signed_part, "signerInfos", &signer_count);
if (res != ASN1_SUCCESS)
{
err = VasEBoot_error (VAS_EBOOT_ERR_BAD_SIGNATURE, "error counting number of signers: %s",
asn1_strerror (res));
goto cleanup_signed_part;
}
if (signer_count <= 0)
{
err = VasEBoot_error (VAS_EBOOT_ERR_BAD_SIGNATURE, "a minimum of 1 signer is required");
goto cleanup_signed_part;
}
msg->signers = VasEBoot_calloc (signer_count, sizeof (VasEBoot_pkcs7_signer_t));
if (msg->signers == NULL)
{
err = VasEBoot_error (VAS_EBOOT_ERR_OUT_OF_MEMORY,
"could not allocate space for %d signers", signer_count);
goto cleanup_signed_part;
}
msg->signer_count = 0;
for (i = 0; i < signer_count; i++)
{
si_da_path = VasEBoot_xasprintf ("signerInfos.?%d.digestAlgorithm.algorithm", i + 1);
if (si_da_path == NULL)
{
err = VasEBoot_error (VAS_EBOOT_ERR_OUT_OF_MEMORY,
"could not allocate path for signer %d's digest algorithm parsing path",
i);
goto cleanup_signerInfos;
}
algo_oid_size = sizeof (algo_oid);
res = asn1_read_value (signed_part, si_da_path, algo_oid, &algo_oid_size);
if (res != ASN1_SUCCESS)
{
err = VasEBoot_error (VAS_EBOOT_ERR_BAD_SIGNATURE,
"error reading signer %d's digest algorithm: %s", i, asn1_strerror (res));
VasEBoot_free (si_da_path);
goto cleanup_signerInfos;
}
VasEBoot_free (si_da_path);
if (VasEBoot_strncmp (sha512_oid, algo_oid, algo_oid_size) == 0)
{
if (sha512_in_da == false)
{
err = VasEBoot_error (VAS_EBOOT_ERR_BAD_SIGNATURE,
"signer %d claims a SHA-512 signature which was not "
"specified in the outer DigestAlgorithms", i);
goto cleanup_signerInfos;
}
else
{
sha512_in_si = true;
msg->signers[i].hash = VasEBoot_crypto_lookup_md_by_name ("sha512");
}
}
else if (VasEBoot_strncmp (sha256_oid, algo_oid, algo_oid_size) == 0)
{
if (sha256_in_da == false)
{
err = VasEBoot_error (VAS_EBOOT_ERR_BAD_SIGNATURE,
"signer %d claims a SHA-256 signature which was not "
"specified in the outer DigestAlgorithms", i);
goto cleanup_signerInfos;
}
else
{
sha256_in_si = true;
msg->signers[i].hash = VasEBoot_crypto_lookup_md_by_name ("sha256");
}
}
else
{
err = VasEBoot_error (VAS_EBOOT_ERR_NOT_IMPLEMENTED_YET,
"only SHA-256 and SHA-512 hashes are supported, found OID %s",
algo_oid);
goto cleanup_signerInfos;
}
if (msg->signers[i].hash == NULL)
{
err = VasEBoot_error (VAS_EBOOT_ERR_BAD_SIGNATURE,
"Hash algorithm for signer %d (OID %s) not loaded", i, algo_oid);
goto cleanup_signerInfos;
}
si_sig_path = VasEBoot_xasprintf ("signerInfos.?%d.signature", i + 1);
if (si_sig_path == NULL)
{
err = VasEBoot_error (VAS_EBOOT_ERR_OUT_OF_MEMORY,
"could not allocate path for signer %d's signature parsing path", i);
goto cleanup_signerInfos;
}
result_buf = VasEBoot_asn1_allocate_and_read (signed_part, si_sig_path, "signature data", &result_size);
VasEBoot_free (si_sig_path);
if (result_buf == NULL)
{
err = VasEBoot_errno;
goto cleanup_signerInfos;
}
gcry_err = _gcry_mpi_scan (&(msg->signers[i].sig_mpi), GCRYMPI_FMT_USG,
result_buf, result_size, NULL);
VasEBoot_free (result_buf);
if (gcry_err != GPG_ERR_NO_ERROR)
{
err = VasEBoot_error (VAS_EBOOT_ERR_BAD_SIGNATURE,
"error loading signature %d into MPI structure: %d",
i, gcry_err);
goto cleanup_signerInfos;
}
/*
* Use msg->signer_count to track fully populated signerInfos so we know
* how many we need to clean up.
*/
msg->signer_count++;
}
/*
* Final consistency check of signerInfo.*.digestAlgorithm vs digestAlgorithms
* .*.algorithm. An algorithm must be present in both digestAlgorithms and
* signerInfo or in neither. We have already checked for an algorithm in
* signerInfo that is not in digestAlgorithms, here we check for algorithms in
* digestAlgorithms but not in signerInfos.
*/
if (sha512_in_da == true && sha512_in_si == false)
{
err = VasEBoot_error (VAS_EBOOT_ERR_BAD_SIGNATURE,
"SHA-512 specified in DigestAlgorithms but did not appear in SignerInfos");
goto cleanup_signerInfos;
}
if (sha256_in_da == true && sha256_in_si == false)
{
err = VasEBoot_error (VAS_EBOOT_ERR_BAD_SIGNATURE,
"SHA-256 specified in DigestAlgorithms but did not appear in SignerInfos");
goto cleanup_signerInfos;
}
asn1_delete_structure (&signed_part);
return VAS_EBOOT_ERR_NONE;
cleanup_signerInfos:
for (i = 0; i < msg->signer_count; i++)
_gcry_mpi_release (msg->signers[i].sig_mpi);
VasEBoot_free (msg->signers);
cleanup_signed_part:
asn1_delete_structure (&signed_part);
return err;
}
VasEBoot_err_t
VasEBoot_pkcs7_data_parse (const void *sigbuf, VasEBoot_size_t data_size, VasEBoot_pkcs7_data_t *msg)
{
VasEBoot_int32_t res;
asn1_node content_info;
VasEBoot_err_t err = VAS_EBOOT_ERR_NONE;
char content_oid[VAS_EBOOT_MAX_OID_LEN];
VasEBoot_uint8_t *content;
VasEBoot_int32_t content_size;
VasEBoot_int32_t content_oid_size = sizeof (content_oid);
VasEBoot_int32_t size = (VasEBoot_int32_t) data_size;
if (data_size > VAS_EBOOT_UINT_MAX)
return VasEBoot_error (VAS_EBOOT_ERR_OUT_OF_RANGE,
"cannot parse a PKCS#7 message where data size > VAS_EBOOT_UINT_MAX");
res = asn1_create_element (VasEBoot_gnutls_pkix_asn, "PKIX1.pkcs-7-ContentInfo", &content_info);
if (res != ASN1_SUCCESS)
return VasEBoot_error (VAS_EBOOT_ERR_OUT_OF_MEMORY,
"could not create ASN.1 structure for PKCS#7 data: %s",
asn1_strerror (res));
res = asn1_der_decoding2 (&content_info, sigbuf, &size,
ASN1_DECODE_FLAG_STRICT_DER | ASN1_DECODE_FLAG_ALLOW_PADDING,
asn1_error);
if (res != ASN1_SUCCESS)
{
err = VasEBoot_error (VAS_EBOOT_ERR_BAD_SIGNATURE,
"error decoding PKCS#7 message DER: %s", asn1_error);
goto cleanup;
}
/*
* ContentInfo ::= SEQUENCE {
* contentType ContentType,
* content [0] EXPLICIT ANY DEFINED BY contentType }
*
* ContentType ::= OBJECT IDENTIFIER
*/
res = asn1_read_value (content_info, "contentType", content_oid, &content_oid_size);
if (res != ASN1_SUCCESS)
{
err = VasEBoot_error (VAS_EBOOT_ERR_BAD_SIGNATURE, "error reading PKCS#7 content type: %s",
asn1_strerror (res));
goto cleanup;
}
/* OID for SignedData defined in 5.1. */
if (VasEBoot_strncmp (signedData_oid, content_oid, content_oid_size) != 0)
{
err = VasEBoot_error (VAS_EBOOT_ERR_BAD_SIGNATURE,
"unexpected content type in PKCS#7 message: OID %s", content_oid);
goto cleanup;
}
content = VasEBoot_asn1_allocate_and_read (content_info, "content", "PKCS#7 message content", &content_size);
if (content == NULL)
{
err = VasEBoot_errno;
goto cleanup;
}
err = process_content (content, content_size, msg);
VasEBoot_free (content);
cleanup:
asn1_delete_structure (&content_info);
return err;
}
/*
* Release all the storage associated with the PKCS#7 message. If the caller
* dynamically allocated the message, it must free it.
*/
void
VasEBoot_pkcs7_data_release (VasEBoot_pkcs7_data_t *msg)
{
VasEBoot_int32_t i;
for (i = 0; i < msg->signer_count; i++)
_gcry_mpi_release (msg->signers[i].sig_mpi);
VasEBoot_free (msg->signers);
}

View File

@ -0,0 +1,485 @@
#include <VasEBoot/mm.h>
#include <libtasn1.h>
/*
* Imported from pkix.asn.
* https://github.com/gnutls/gnutls/blob/master/lib/pkix.asn
*/
const asn1_static_node VasEBoot_pkix_asn1_tab[] = {
{ "PKIX1", 536875024, NULL },
{ NULL, 1073741836, NULL },
{ "PrivateKeyUsagePeriod", 1610612741, NULL },
{ "notBefore", 1610637349, NULL },
{ NULL, 4104, "0"},
{ "notAfter", 536895525, NULL },
{ NULL, 4104, "1"},
{ "AuthorityKeyIdentifier", 1610612741, NULL },
{ "keyIdentifier", 1610637319, NULL },
{ NULL, 4104, "0"},
{ "authorityCertIssuer", 1610637314, "GeneralNames"},
{ NULL, 4104, "1"},
{ "authorityCertSerialNumber", 536895490, "CertificateSerialNumber"},
{ NULL, 4104, "2"},
{ "SubjectKeyIdentifier", 1073741831, NULL },
{ "KeyUsage", 1073741830, NULL },
{ "DirectoryString", 1610612754, NULL },
{ "teletexString", 1612709918, NULL },
{ "MAX", 524298, "1"},
{ "printableString", 1612709919, NULL },
{ "MAX", 524298, "1"},
{ "universalString", 1612709920, NULL },
{ "MAX", 524298, "1"},
{ "utf8String", 1612709922, NULL },
{ "MAX", 524298, "1"},
{ "bmpString", 538968097, NULL },
{ "MAX", 524298, "1"},
{ "SubjectAltName", 1073741826, "GeneralNames"},
{ "GeneralNames", 1612709899, NULL },
{ "MAX", 1074266122, "1"},
{ NULL, 2, "GeneralName"},
{ "GeneralName", 1610612754, NULL },
{ "otherName", 1610620930, "AnotherName"},
{ NULL, 4104, "0"},
{ "rfc822Name", 1610620957, NULL },
{ NULL, 4104, "1"},
{ "dNSName", 1610620957, NULL },
{ NULL, 4104, "2"},
{ "x400Address", 1610620941, NULL },
{ NULL, 4104, "3"},
{ "directoryName", 1610620939, NULL },
{ NULL, 1073743880, "4"},
{ NULL, 2, "RelativeDistinguishedName"},
{ "ediPartyName", 1610620941, NULL },
{ NULL, 4104, "5"},
{ "uniformResourceIdentifier", 1610620957, NULL },
{ NULL, 4104, "6"},
{ "iPAddress", 1610620935, NULL },
{ NULL, 4104, "7"},
{ "registeredID", 536879116, NULL },
{ NULL, 4104, "8"},
{ "AnotherName", 1610612741, NULL },
{ "type-id", 1073741836, NULL },
{ "value", 541073421, NULL },
{ NULL, 1073743880, "0"},
{ "type-id", 1, NULL },
{ "IssuerAltName", 1073741826, "GeneralNames"},
{ "BasicConstraints", 1610612741, NULL },
{ "cA", 1610645508, NULL },
{ NULL, 131081, NULL },
{ "pathLenConstraint", 16387, NULL },
{ "CRLDistributionPoints", 1612709899, NULL },
{ "MAX", 1074266122, "1"},
{ NULL, 2, "DistributionPoint"},
{ "DistributionPoint", 1610612741, NULL },
{ "distributionPoint", 1610637314, "DistributionPointName"},
{ NULL, 2056, "0"},
{ "reasons", 1610637314, "ReasonFlags"},
{ NULL, 4104, "1"},
{ "cRLIssuer", 536895490, "GeneralNames"},
{ NULL, 4104, "2"},
{ "DistributionPointName", 1610612754, NULL },
{ "fullName", 1610620930, "GeneralNames"},
{ NULL, 4104, "0"},
{ "nameRelativeToCRLIssuer", 536879106, "RelativeDistinguishedName"},
{ NULL, 4104, "1"},
{ "ReasonFlags", 1073741830, NULL },
{ "ExtKeyUsageSyntax", 1612709899, NULL },
{ "MAX", 1074266122, "1"},
{ NULL, 12, NULL },
{ "AuthorityInfoAccessSyntax", 1612709899, NULL },
{ "MAX", 1074266122, "1"},
{ NULL, 2, "AccessDescription"},
{ "AccessDescription", 1610612741, NULL },
{ "accessMethod", 1073741836, NULL },
{ "accessLocation", 2, "GeneralName"},
{ "Attribute", 1610612741, NULL },
{ "type", 1073741836, NULL },
{ "values", 536870927, NULL },
{ NULL, 13, NULL },
{ "AttributeTypeAndValue", 1610612741, NULL },
{ "type", 1073741836, NULL },
{ "value", 13, NULL },
{ "Name", 1610612754, NULL },
{ "rdnSequence", 536870923, NULL },
{ NULL, 2, "RelativeDistinguishedName"},
{ "DistinguishedName", 1610612747, NULL },
{ NULL, 2, "RelativeDistinguishedName"},
{ "RelativeDistinguishedName", 1612709903, NULL },
{ "MAX", 1074266122, "1"},
{ NULL, 2, "AttributeTypeAndValue"},
{ "Certificate", 1610612741, NULL },
{ "tbsCertificate", 1073741826, "TBSCertificate"},
{ "signatureAlgorithm", 1073741826, "AlgorithmIdentifier"},
{ "signature", 6, NULL },
{ "TBSCertificate", 1610612741, NULL },
{ "version", 1610653699, NULL },
{ NULL, 1073741833, "0"},
{ NULL, 2056, "0"},
{ "serialNumber", 1073741826, "CertificateSerialNumber"},
{ "signature", 1073741826, "AlgorithmIdentifier"},
{ "issuer", 1073741826, "Name"},
{ "validity", 1073741826, "Validity"},
{ "subject", 1073741826, "Name"},
{ "subjectPublicKeyInfo", 1073741826, "SubjectPublicKeyInfo"},
{ "issuerUniqueID", 1610637314, "UniqueIdentifier"},
{ NULL, 4104, "1"},
{ "subjectUniqueID", 1610637314, "UniqueIdentifier"},
{ NULL, 4104, "2"},
{ "extensions", 536895490, "Extensions"},
{ NULL, 2056, "3"},
{ "CertificateSerialNumber", 1073741827, NULL },
{ "Validity", 1610612741, NULL },
{ "notBefore", 1073741826, "Time"},
{ "notAfter", 2, "Time"},
{ "Time", 1610612754, NULL },
{ "utcTime", 1073741860, NULL },
{ "generalTime", 37, NULL },
{ "UniqueIdentifier", 1073741830, NULL },
{ "SubjectPublicKeyInfo", 1610612741, NULL },
{ "algorithm", 1073741826, "AlgorithmIdentifier"},
{ "subjectPublicKey", 6, NULL },
{ "Extensions", 1612709899, NULL },
{ "MAX", 1074266122, "1"},
{ NULL, 2, "Extension"},
{ "Extension", 1610612741, NULL },
{ "extnID", 1073741836, NULL },
{ "critical", 1610645508, NULL },
{ NULL, 131081, NULL },
{ "extnValue", 7, NULL },
{ "CertificateList", 1610612741, NULL },
{ "tbsCertList", 1073741826, "TBSCertList"},
{ "signatureAlgorithm", 1073741826, "AlgorithmIdentifier"},
{ "signature", 6, NULL },
{ "TBSCertList", 1610612741, NULL },
{ "version", 1073758211, NULL },
{ "signature", 1073741826, "AlgorithmIdentifier"},
{ "issuer", 1073741826, "Name"},
{ "thisUpdate", 1073741826, "Time"},
{ "nextUpdate", 1073758210, "Time"},
{ "revokedCertificates", 1610629131, NULL },
{ NULL, 536870917, NULL },
{ "userCertificate", 1073741826, "CertificateSerialNumber"},
{ "revocationDate", 1073741826, "Time"},
{ "crlEntryExtensions", 16386, "Extensions"},
{ "crlExtensions", 536895490, "Extensions"},
{ NULL, 2056, "0"},
{ "AlgorithmIdentifier", 1610612741, NULL },
{ "algorithm", 1073741836, NULL },
{ "parameters", 541081613, NULL },
{ "algorithm", 1, NULL },
{ "Dss-Sig-Value", 1610612741, NULL },
{ "r", 1073741827, NULL },
{ "s", 3, NULL },
{ "Dss-Parms", 1610612741, NULL },
{ "p", 1073741827, NULL },
{ "q", 1073741827, NULL },
{ "g", 3, NULL },
{ "pkcs-7-ContentInfo", 1610612741, NULL },
{ "contentType", 1073741836, NULL },
{ "content", 541073421, NULL },
{ NULL, 1073743880, "0"},
{ "contentType", 1, NULL },
{ "pkcs-7-DigestInfo", 1610612741, NULL },
{ "digestAlgorithm", 1073741826, "AlgorithmIdentifier"},
{ "digest", 7, NULL },
{ "pkcs-7-SignedData", 1610612741, NULL },
{ "version", 1073741827, NULL },
{ "digestAlgorithms", 1073741826, "pkcs-7-DigestAlgorithmIdentifiers"},
{ "encapContentInfo", 1073741826, "pkcs-7-EncapsulatedContentInfo"},
{ "certificates", 1610637314, "pkcs-7-CertificateSet"},
{ NULL, 4104, "0"},
{ "crls", 1610637314, "pkcs-7-CertificateRevocationLists"},
{ NULL, 4104, "1"},
{ "signerInfos", 2, "pkcs-7-SignerInfos"},
{ "pkcs-7-DigestAlgorithmIdentifiers", 1610612751, NULL },
{ NULL, 2, "AlgorithmIdentifier"},
{ "pkcs-7-EncapsulatedContentInfo", 1610612741, NULL },
{ "eContentType", 1073741836, NULL },
{ "eContent", 536895501, NULL },
{ NULL, 2056, "0"},
{ "pkcs-7-CertificateRevocationLists", 1610612751, NULL },
{ NULL, 13, NULL },
{ "pkcs-7-CertificateChoices", 1610612754, NULL },
{ "certificate", 13, NULL },
{ "pkcs-7-CertificateSet", 1610612751, NULL },
{ NULL, 2, "pkcs-7-CertificateChoices"},
{ "IssuerAndSerialNumber", 1610612741, NULL },
{ "issuer", 1073741826, "Name"},
{ "serialNumber", 2, "CertificateSerialNumber"},
{ "pkcs-7-SignerInfo", 1610612741, NULL },
{ "version", 1073741827, NULL },
{ "sid", 1073741826, "SignerIdentifier"},
{ "digestAlgorithm", 1073741826, "AlgorithmIdentifier"},
{ "signedAttrs", 1610637314, "SignedAttributes"},
{ NULL, 4104, "0"},
{ "signatureAlgorithm", 1073741826, "AlgorithmIdentifier"},
{ "signature", 1073741831, NULL },
{ "unsignedAttrs", 536895490, "SignedAttributes"},
{ NULL, 4104, "1"},
{ "SignedAttributes", 1612709903, NULL },
{ "MAX", 1074266122, "1"},
{ NULL, 2, "Attribute"},
{ "SignerIdentifier", 1610612754, NULL },
{ "issuerAndSerialNumber", 1073741826, "IssuerAndSerialNumber"},
{ "subjectKeyIdentifier", 536879111, NULL },
{ NULL, 4104, "0"},
{ "pkcs-7-SignerInfos", 1610612751, NULL },
{ NULL, 2, "pkcs-7-SignerInfo"},
{ "pkcs-10-CertificationRequestInfo", 1610612741, NULL },
{ "version", 1073741827, NULL },
{ "subject", 1073741826, "Name"},
{ "subjectPKInfo", 1073741826, "SubjectPublicKeyInfo"},
{ "attributes", 536879106, "Attributes"},
{ NULL, 4104, "0"},
{ "Attributes", 1610612751, NULL },
{ NULL, 2, "Attribute"},
{ "pkcs-10-CertificationRequest", 1610612741, NULL },
{ "certificationRequestInfo", 1073741826, "pkcs-10-CertificationRequestInfo"},
{ "signatureAlgorithm", 1073741826, "AlgorithmIdentifier"},
{ "signature", 6, NULL },
{ "pkcs-9-at-challengePassword", 1879048204, NULL },
{ "iso", 1073741825, "1"},
{ "member-body", 1073741825, "2"},
{ "us", 1073741825, "840"},
{ "rsadsi", 1073741825, "113549"},
{ "pkcs", 1073741825, "1"},
{ NULL, 1073741825, "9"},
{ NULL, 1, "7"},
{ "pkcs-9-challengePassword", 1610612754, NULL },
{ "printableString", 1073741855, NULL },
{ "utf8String", 34, NULL },
{ "pkcs-9-localKeyId", 1073741831, NULL },
{ "pkcs-8-PrivateKeyInfo", 1610612741, NULL },
{ "version", 1073741827, NULL },
{ "privateKeyAlgorithm", 1073741826, "AlgorithmIdentifier"},
{ "privateKey", 1073741831, NULL },
{ "attributes", 536895490, "Attributes"},
{ NULL, 4104, "0"},
{ "pkcs-8-EncryptedPrivateKeyInfo", 1610612741, NULL },
{ "encryptionAlgorithm", 1073741826, "AlgorithmIdentifier"},
{ "encryptedData", 2, "pkcs-8-EncryptedData"},
{ "pkcs-8-EncryptedData", 1073741831, NULL },
{ "pkcs-5-des-CBC-params", 1612709895, NULL },
{ NULL, 1048586, "8"},
{ "pkcs-5-des-EDE3-CBC-params", 1612709895, NULL },
{ NULL, 1048586, "8"},
{ "pkcs-5-aes128-CBC-params", 1612709895, NULL },
{ NULL, 1048586, "16"},
{ "pkcs-5-aes192-CBC-params", 1612709895, NULL },
{ NULL, 1048586, "16"},
{ "pkcs-5-aes256-CBC-params", 1612709895, NULL },
{ NULL, 1048586, "16"},
{ "Gost28147-89-Parameters", 1610612741, NULL },
{ "iv", 1073741831, NULL },
{ "encryptionParamSet", 12, NULL },
{ "pkcs-5-PBE-params", 1610612741, NULL },
{ "salt", 1073741831, NULL },
{ "iterationCount", 3, NULL },
{ "pkcs-5-PBES2-params", 1610612741, NULL },
{ "keyDerivationFunc", 1073741826, "AlgorithmIdentifier"},
{ "encryptionScheme", 2, "AlgorithmIdentifier"},
{ "pkcs-5-PBMAC1-params", 1610612741, NULL },
{ "keyDerivationFunc", 1073741826, "AlgorithmIdentifier"},
{ "messageAuthScheme", 2, "AlgorithmIdentifier"},
{ "pkcs-5-PBKDF2-params", 1610612741, NULL },
{ "salt", 1610612754, NULL },
{ "specified", 1073741831, NULL },
{ "otherSource", 2, "AlgorithmIdentifier"},
{ "iterationCount", 1073741827, NULL },
{ "keyLength", 1073758211, NULL },
{ "prf", 16386, "AlgorithmIdentifier"},
{ "pkcs-12-PFX", 1610612741, NULL },
{ "version", 1610874883, NULL },
{ "v3", 1, "3"},
{ "authSafe", 1073741826, "pkcs-7-ContentInfo"},
{ "macData", 16386, "pkcs-12-MacData"},
{ "pkcs-12-PbeParams", 1610612741, NULL },
{ "salt", 1073741831, NULL },
{ "iterations", 3, NULL },
{ "pkcs-12-MacData", 1610612741, NULL },
{ "mac", 1073741826, "pkcs-7-DigestInfo"},
{ "macSalt", 1073741831, NULL },
{ "iterations", 536903683, NULL },
{ NULL, 9, "1"},
{ "pkcs-12-AuthenticatedSafe", 1610612747, NULL },
{ NULL, 2, "pkcs-7-ContentInfo"},
{ "pkcs-12-SafeContents", 1610612747, NULL },
{ NULL, 2, "pkcs-12-SafeBag"},
{ "pkcs-12-SafeBag", 1610612741, NULL },
{ "bagId", 1073741836, NULL },
{ "bagValue", 1614815245, NULL },
{ NULL, 1073743880, "0"},
{ "badId", 1, NULL },
{ "bagAttributes", 536887311, NULL },
{ NULL, 2, "Attribute"},
{ "pkcs-12-CertBag", 1610612741, NULL },
{ "certId", 1073741836, NULL },
{ "certValue", 541073421, NULL },
{ NULL, 1073743880, "0"},
{ "certId", 1, NULL },
{ "pkcs-12-CRLBag", 1610612741, NULL },
{ "crlId", 1073741836, NULL },
{ "crlValue", 541073421, NULL },
{ NULL, 1073743880, "0"},
{ "crlId", 1, NULL },
{ "pkcs-12-SecretBag", 1610612741, NULL },
{ "secretTypeId", 1073741836, NULL },
{ "secretValue", 541073421, NULL },
{ NULL, 1073743880, "0"},
{ "secretTypeId", 1, NULL },
{ "pkcs-7-Data", 1073741831, NULL },
{ "pkcs-7-EncryptedData", 1610612741, NULL },
{ "version", 1073741827, NULL },
{ "encryptedContentInfo", 1073741826, "pkcs-7-EncryptedContentInfo"},
{ "unprotectedAttrs", 536895490, "pkcs-7-UnprotectedAttributes"},
{ NULL, 4104, "1"},
{ "pkcs-7-EncryptedContentInfo", 1610612741, NULL },
{ "contentType", 1073741836, NULL },
{ "contentEncryptionAlgorithm", 1073741826, "pkcs-7-ContentEncryptionAlgorithmIdentifier"},
{ "encryptedContent", 536895495, NULL },
{ NULL, 4104, "0"},
{ "pkcs-7-ContentEncryptionAlgorithmIdentifier", 1073741826, "AlgorithmIdentifier"},
{ "pkcs-7-UnprotectedAttributes", 1612709903, NULL },
{ "MAX", 1074266122, "1"},
{ NULL, 2, "Attribute"},
{ "ProxyCertInfo", 1610612741, NULL },
{ "pCPathLenConstraint", 1073758211, NULL },
{ "proxyPolicy", 2, "ProxyPolicy"},
{ "ProxyPolicy", 1610612741, NULL },
{ "policyLanguage", 1073741836, NULL },
{ "policy", 16391, NULL },
{ "certificatePolicies", 1612709899, NULL },
{ "MAX", 1074266122, "1"},
{ NULL, 2, "PolicyInformation"},
{ "PolicyInformation", 1610612741, NULL },
{ "policyIdentifier", 1073741836, NULL },
{ "policyQualifiers", 538984459, NULL },
{ "MAX", 1074266122, "1"},
{ NULL, 2, "PolicyQualifierInfo"},
{ "PolicyQualifierInfo", 1610612741, NULL },
{ "policyQualifierId", 1073741836, NULL },
{ "qualifier", 541065229, NULL },
{ "policyQualifierId", 1, NULL },
{ "CPSuri", 1073741853, NULL },
{ "UserNotice", 1610612741, NULL },
{ "noticeRef", 1073758210, "NoticeReference"},
{ "explicitText", 16386, "DisplayText"},
{ "NoticeReference", 1610612741, NULL },
{ "organization", 1073741826, "DisplayText"},
{ "noticeNumbers", 536870923, NULL },
{ NULL, 3, NULL },
{ "DisplayText", 1610612754, NULL },
{ "ia5String", 1612709917, NULL },
{ "200", 524298, "1"},
{ "visibleString", 1612709923, NULL },
{ "200", 524298, "1"},
{ "bmpString", 1612709921, NULL },
{ "200", 524298, "1"},
{ "utf8String", 538968098, NULL },
{ "200", 524298, "1"},
{ "OCSPRequest", 1610612741, NULL },
{ "tbsRequest", 1073741826, "TBSRequest"},
{ "optionalSignature", 536895490, "Signature"},
{ NULL, 2056, "0"},
{ "TBSRequest", 1610612741, NULL },
{ "version", 1610653699, NULL },
{ NULL, 1073741833, "0"},
{ NULL, 2056, "0"},
{ "requestorName", 1610637314, "GeneralName"},
{ NULL, 2056, "1"},
{ "requestList", 1610612747, NULL },
{ NULL, 2, "Request"},
{ "requestExtensions", 536895490, "Extensions"},
{ NULL, 2056, "2"},
{ "Signature", 1610612741, NULL },
{ "signatureAlgorithm", 1073741826, "AlgorithmIdentifier"},
{ "signature", 1073741830, NULL },
{ "certs", 536895499, NULL },
{ NULL, 1073743880, "0"},
{ NULL, 2, "Certificate"},
{ "Request", 1610612741, NULL },
{ "reqCert", 1073741826, "CertID"},
{ "singleRequestExtensions", 536895490, "Extensions"},
{ NULL, 2056, "0"},
{ "CertID", 1610612741, NULL },
{ "hashAlgorithm", 1073741826, "AlgorithmIdentifier"},
{ "issuerNameHash", 1073741831, NULL },
{ "issuerKeyHash", 1073741831, NULL },
{ "serialNumber", 2, "CertificateSerialNumber"},
{ "OCSPResponse", 1610612741, NULL },
{ "responseStatus", 1073741826, "OCSPResponseStatus"},
{ "responseBytes", 536895490, "ResponseBytes"},
{ NULL, 2056, "0"},
{ "OCSPResponseStatus", 1610874901, NULL },
{ "successful", 1073741825, "0"},
{ "malformedRequest", 1073741825, "1"},
{ "internalError", 1073741825, "2"},
{ "tryLater", 1073741825, "3"},
{ "sigRequired", 1073741825, "5"},
{ "unauthorized", 1, "6"},
{ "ResponseBytes", 1610612741, NULL },
{ "responseType", 1073741836, NULL },
{ "response", 7, NULL },
{ "BasicOCSPResponse", 1610612741, NULL },
{ "tbsResponseData", 1073741826, "ResponseData"},
{ "signatureAlgorithm", 1073741826, "AlgorithmIdentifier"},
{ "signature", 1073741830, NULL },
{ "certs", 536895499, NULL },
{ NULL, 1073743880, "0"},
{ NULL, 2, "Certificate"},
{ "ResponseData", 1610612741, NULL },
{ "version", 1610653699, NULL },
{ NULL, 1073741833, "0"},
{ NULL, 2056, "0"},
{ "responderID", 1073741826, "ResponderID"},
{ "producedAt", 1073741861, NULL },
{ "responses", 1610612747, NULL },
{ NULL, 2, "SingleResponse"},
{ "responseExtensions", 536895490, "Extensions"},
{ NULL, 2056, "1"},
{ "ResponderID", 1610612754, NULL },
{ "byName", 1610620939, NULL },
{ NULL, 1073743880, "1"},
{ NULL, 2, "RelativeDistinguishedName"},
{ "byKey", 536879111, NULL },
{ NULL, 2056, "2"},
{ "SingleResponse", 1610612741, NULL },
{ "certID", 1073741826, "CertID"},
{ "certStatus", 1073741826, "CertStatus"},
{ "thisUpdate", 1073741861, NULL },
{ "nextUpdate", 1610637349, NULL },
{ NULL, 2056, "0"},
{ "singleExtensions", 536895490, "Extensions"},
{ NULL, 2056, "1"},
{ "CertStatus", 1610612754, NULL },
{ "good", 1610620948, NULL },
{ NULL, 4104, "0"},
{ "revoked", 1610620930, "RevokedInfo"},
{ NULL, 4104, "1"},
{ "unknown", 536879106, "UnknownInfo"},
{ NULL, 4104, "2"},
{ "RevokedInfo", 1610612741, NULL },
{ "revocationTime", 1073741861, NULL },
{ "revocationReason", 537157653, NULL },
{ NULL, 1073743880, "0"},
{ "unspecified", 1, "0"},
{ "UnknownInfo", 1073741844, NULL },
{ "NameConstraints", 1610612741, NULL },
{ "permittedSubtrees", 1610637314, "GeneralSubtrees"},
{ NULL, 4104, "0"},
{ "excludedSubtrees", 536895490, "GeneralSubtrees"},
{ NULL, 4104, "1"},
{ "GeneralSubtrees", 1612709899, NULL },
{ "MAX", 1074266122, "1"},
{ NULL, 2, "GeneralSubtree"},
{ "GeneralSubtree", 1610612741, NULL },
{ "base", 1073741826, "GeneralName"},
{ "minimum", 1610653699, NULL },
{ NULL, 1073741833, "0"},
{ NULL, 4104, "0"},
{ "maximum", 536895491, NULL },
{ NULL, 4104, "1"},
{ "TlsFeatures", 536870923, NULL },
{ NULL, 3, NULL },
{ NULL, 0, NULL }
};

View File

@ -0,0 +1,970 @@
/*
* VAS_EBOOT -- GRand Unified Bootloader
* Copyright (C) 2020, 2022 Free Software Foundation, Inc.
* Copyright (C) 2020, 2022, 2025 IBM Corporation
*
* VAS_EBOOT 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.
*
* VAS_EBOOT 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 VAS_EBOOT. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libtasn1.h>
#include <VasEBoot/types.h>
#include <VasEBoot/err.h>
#include <VasEBoot/mm.h>
#include <VasEBoot/crypto.h>
#include <VasEBoot/misc.h>
#include <VasEBoot/gcrypt/gcrypt.h>
#include "appendedsig.h"
static char asn1_error[ASN1_MAX_ERROR_DESCRIPTION_SIZE];
/* RFC 3279 2.3.1 RSA Keys. */
static const char *rsaEncryption_oid = "1.2.840.113549.1.1.1";
/* RFC 5280 Appendix A. */
static const char *commonName_oid = "2.5.4.3";
/* RFC 5280 4.2.1.3 Key Usage. */
static const char *keyUsage_oid = "2.5.29.15";
static const VasEBoot_uint8_t digitalSignatureUsage = 0x80;
/* RFC 5280 4.2.1.9 Basic Constraints. */
static const char *basicConstraints_oid = "2.5.29.19";
/* RFC 5280 4.2.1.12 Extended Key Usage. */
static const char *extendedKeyUsage_oid = "2.5.29.37";
static const char *codeSigningUsage_oid = "1.3.6.1.5.5.7.3.3";
/*
* RFC 3279 2.3.1
*
* The RSA public key MUST be encoded using the ASN.1 type RSAPublicKey:
*
* RSAPublicKey ::= SEQUENCE {
* modulus INTEGER, -- n
* publicExponent INTEGER } -- e
*
* where modulus is the modulus n, and publicExponent is the public exponent e.
*/
static VasEBoot_err_t
VasEBoot_parse_rsa_pubkey (VasEBoot_uint8_t *der, VasEBoot_int32_t dersize, VasEBoot_x509_cert_t *certificate)
{
VasEBoot_int32_t result;
asn1_node spk = NULL;
VasEBoot_uint8_t *m_data, *e_data;
VasEBoot_int32_t m_size, e_size;
VasEBoot_err_t err = VAS_EBOOT_ERR_NONE;
gcry_error_t gcry_err;
result = asn1_create_element (VasEBoot_gnutls_gnutls_asn, "GNUTLS.RSAPublicKey", &spk);
if (result != ASN1_SUCCESS)
return VasEBoot_error (VAS_EBOOT_ERR_OUT_OF_MEMORY,
"cannot create storage for public key ASN.1 data");
result = asn1_der_decoding2 (&spk, der, &dersize, ASN1_DECODE_FLAG_STRICT_DER, asn1_error);
if (result != ASN1_SUCCESS)
{
err = VasEBoot_error (VAS_EBOOT_ERR_BAD_FILE_TYPE,
"cannot decode certificate public key DER: %s", asn1_error);
goto cleanup;
}
m_data = VasEBoot_asn1_allocate_and_read (spk, "modulus", "RSA modulus", &m_size);
if (m_data == NULL)
{
err = VasEBoot_errno;
goto cleanup;
}
e_data = VasEBoot_asn1_allocate_and_read (spk, "publicExponent", "RSA public exponent", &e_size);
if (e_data == NULL)
{
err = VasEBoot_errno;
goto cleanup_m_data;
}
/*
* Convert m, e to mpi
*
* nscanned is not set for FMT_USG, it's only set for FMT_PGP, so we can't
* verify it.
*/
gcry_err = _gcry_mpi_scan (&certificate->mpis[0], GCRYMPI_FMT_USG, m_data, m_size, NULL);
if (gcry_err != GPG_ERR_NO_ERROR)
{
err = VasEBoot_error (VAS_EBOOT_ERR_BAD_FILE_TYPE,
"error loading RSA modulus into MPI structure: %d", gcry_err);
goto cleanup_e_data;
}
gcry_err = _gcry_mpi_scan (&certificate->mpis[1], GCRYMPI_FMT_USG, e_data, e_size, NULL);
if (gcry_err != GPG_ERR_NO_ERROR)
{
err = VasEBoot_error (VAS_EBOOT_ERR_BAD_FILE_TYPE,
"error loading RSA exponent into MPI structure: %d", gcry_err);
goto cleanup_m_mpi;
}
/* RSA key size in bits. */
certificate->modulus_size = (m_size * 8) - 8;
VasEBoot_free (e_data);
VasEBoot_free (m_data);
asn1_delete_structure (&spk);
return VAS_EBOOT_ERR_NONE;
cleanup_m_mpi:
_gcry_mpi_release (certificate->mpis[0]);
cleanup_e_data:
VasEBoot_free (e_data);
cleanup_m_data:
VasEBoot_free (m_data);
cleanup:
asn1_delete_structure (&spk);
return err;
}
/*
* RFC 5280:
* SubjectPublicKeyInfo ::= SEQUENCE {
* algorithm AlgorithmIdentifier,
* subjectPublicKey BIT STRING }
*
* AlgorithmIdentifiers come from RFC 3279, we are not strictly compilant as we
* only support RSA Encryption.
*/
static VasEBoot_err_t
VasEBoot_x509_read_subject_public_key (asn1_node asn, VasEBoot_x509_cert_t *results)
{
VasEBoot_int32_t result;
VasEBoot_err_t err;
const char *algo_name = "tbsCertificate.subjectPublicKeyInfo.algorithm.algorithm";
const char *params_name = "tbsCertificate.subjectPublicKeyInfo.algorithm.parameters";
const char *pk_name = "tbsCertificate.subjectPublicKeyInfo.subjectPublicKey";
char algo_oid[VAS_EBOOT_MAX_OID_LEN];
VasEBoot_int32_t algo_size = sizeof (algo_oid);
char params_value[2];
VasEBoot_int32_t params_size = sizeof (params_value);
VasEBoot_uint8_t *key_data = NULL;
VasEBoot_int32_t key_size = 0;
VasEBoot_uint32_t key_type;
/* Algorithm: see notes for rsaEncryption_oid. */
result = asn1_read_value (asn, algo_name, algo_oid, &algo_size);
if (result != ASN1_SUCCESS)
return VasEBoot_error (VAS_EBOOT_ERR_BAD_FILE_TYPE, "error reading x509 public key algorithm: %s",
asn1_strerror (result));
if (VasEBoot_strncmp (algo_oid, rsaEncryption_oid, sizeof (rsaEncryption_oid)) != 0)
return VasEBoot_error (VAS_EBOOT_ERR_NOT_IMPLEMENTED_YET,
"unsupported x509 public key algorithm: %s", algo_oid);
/*
* RFC 3279 2.3.1 : The rsaEncryption OID is intended to be used in the
* algorithm field of a value of type AlgorithmIdentifier. The parameters
* field MUST have ASN.1 type NULL for this algorithm identifier.
*/
result = asn1_read_value (asn, params_name, params_value, &params_size);
if (result != ASN1_SUCCESS)
return VasEBoot_error (VAS_EBOOT_ERR_BAD_FILE_TYPE, "error reading x509 public key parameters: %s",
asn1_strerror (result));
if (params_value[0] != ASN1_TAG_NULL)
return VasEBoot_error (VAS_EBOOT_ERR_BAD_FILE_TYPE,
"invalid x509 public key parameters: expected NULL");
/*
* RFC 3279 2.3.1: The DER encoded RSAPublicKey is the value of the BIT
* STRING subjectPublicKey.
*/
result = asn1_read_value_type (asn, pk_name, NULL, &key_size, &key_type);
if (result != ASN1_MEM_ERROR)
return VasEBoot_error (VAS_EBOOT_ERR_BAD_FILE_TYPE, "error reading size of x509 public key: %s",
asn1_strerror (result));
if (key_type != ASN1_ETYPE_BIT_STRING)
return VasEBoot_error (VAS_EBOOT_ERR_BAD_FILE_TYPE, "unexpected ASN.1 type when reading x509 public key: %x",
key_type);
/* Length is in bits. */
key_size = (key_size + 7) / 8;
key_data = VasEBoot_malloc (key_size);
if (key_data == NULL)
return VasEBoot_error (VAS_EBOOT_ERR_OUT_OF_MEMORY, "out of memory for x509 public key");
result = asn1_read_value (asn, pk_name, key_data, &key_size);
if (result != ASN1_SUCCESS)
{
VasEBoot_free (key_data);
return VasEBoot_error (VAS_EBOOT_ERR_BAD_FILE_TYPE, "error reading public key data");
}
key_size = (key_size + 7) / 8;
err = VasEBoot_parse_rsa_pubkey (key_data, key_size, results);
VasEBoot_free (key_data);
return err;
}
/* Decode a string as defined in Appendix A. */
static VasEBoot_err_t
decode_string (char *der, VasEBoot_int32_t der_size, char **string, VasEBoot_size_t *string_size)
{
asn1_node strasn;
VasEBoot_int32_t result;
char *choice;
VasEBoot_int32_t choice_size = 0;
VasEBoot_int32_t tmp_size = 0;
VasEBoot_err_t err = VAS_EBOOT_ERR_NONE;
result = asn1_create_element (VasEBoot_gnutls_pkix_asn, "PKIX1.DirectoryString", &strasn);
if (result != ASN1_SUCCESS)
return VasEBoot_error (VAS_EBOOT_ERR_OUT_OF_MEMORY,
"could not create ASN.1 structure for certificate: %s",
asn1_strerror (result));
result = asn1_der_decoding2 (&strasn, der, &der_size, ASN1_DECODE_FLAG_STRICT_DER, asn1_error);
if (result != ASN1_SUCCESS)
{
err = VasEBoot_error (VAS_EBOOT_ERR_BAD_FILE_TYPE,
"could not parse DER for DirectoryString: %s", asn1_error);
goto cleanup;
}
choice = VasEBoot_asn1_allocate_and_read (strasn, "", "DirectoryString choice", &choice_size);
if (choice == NULL)
{
err = VasEBoot_errno;
goto cleanup;
}
if (VasEBoot_strncmp ("utf8String", choice, choice_size) == 0)
{
result = asn1_read_value (strasn, "utf8String", NULL, &tmp_size);
if (result != ASN1_MEM_ERROR)
{
err = VasEBoot_error (VAS_EBOOT_ERR_BAD_FILE_TYPE, "error reading size of UTF-8 string: %s",
asn1_strerror (result));
goto cleanup_choice;
}
}
else if (VasEBoot_strncmp ("printableString", choice, choice_size) == 0)
{
result = asn1_read_value (strasn, "printableString", NULL, &tmp_size);
if (result != ASN1_MEM_ERROR)
{
err = VasEBoot_error (VAS_EBOOT_ERR_BAD_FILE_TYPE, "error reading size of printableString: %s",
asn1_strerror (result));
goto cleanup_choice;
}
}
else
{
err = VasEBoot_error (VAS_EBOOT_ERR_NOT_IMPLEMENTED_YET,
"only UTF-8 and printable DirectoryStrings are supported, got %s",
choice);
goto cleanup_choice;
}
/* Read size does not include trailing NUL. */
tmp_size++;
*string = VasEBoot_malloc (tmp_size);
if (*string == NULL)
{
err = VasEBoot_error (VAS_EBOOT_ERR_OUT_OF_MEMORY,
"cannot allocate memory for DirectoryString contents");
goto cleanup_choice;
}
result = asn1_read_value (strasn, choice, *string, &tmp_size);
if (result != ASN1_SUCCESS)
{
err = VasEBoot_error (VAS_EBOOT_ERR_BAD_FILE_TYPE, "error reading out %s in DirectoryString: %s",
choice, asn1_strerror (result));
VasEBoot_free (*string);
*string = NULL;
goto cleanup_choice;
}
*string_size = tmp_size + 1;
(*string)[tmp_size] = '\0';
cleanup_choice:
VasEBoot_free (choice);
cleanup:
asn1_delete_structure (&strasn);
return err;
}
/*
* TBSCertificate ::= SEQUENCE {
* version [0] EXPLICIT Version DEFAULT v1,
* ...
*
* Version ::= INTEGER { v1(0), v2(1), v3(2) }
*/
static VasEBoot_err_t
check_version (asn1_node certificate, VasEBoot_x509_cert_t *results)
{
VasEBoot_int32_t rc;
const char *name = "tbsCertificate.version";
VasEBoot_uint8_t version;
VasEBoot_int32_t len = sizeof (version);
rc = asn1_read_value (certificate, name, &version, &len);
/* Require version 3. */
if (rc != ASN1_SUCCESS || len != 1)
return VasEBoot_error (VAS_EBOOT_ERR_BAD_FILE_TYPE, "error reading certificate version");
if (version != 0x02)
return VasEBoot_error (VAS_EBOOT_ERR_BAD_FILE_TYPE,
"invalid x509 certificate version, expected v3 (0x02), got 0x%02x.",
version);
results->version = version;
return VAS_EBOOT_ERR_NONE;
}
/* we extract only the CN and issuer. */
static VasEBoot_err_t
read_name (asn1_node asn, const char *name_path, char **name, VasEBoot_size_t *name_size)
{
VasEBoot_int32_t seq_components, set_components;
VasEBoot_int32_t result;
VasEBoot_int32_t i, j;
char *top_path, *set_path, *type_path, *val_path;
char type[VAS_EBOOT_MAX_OID_LEN];
VasEBoot_int32_t type_len = sizeof (type);
VasEBoot_int32_t string_size = 0;
char *string_der;
VasEBoot_err_t err;
*name = NULL;
top_path = VasEBoot_xasprintf ("%s.rdnSequence", name_path);
if (top_path == NULL)
return VasEBoot_error (VAS_EBOOT_ERR_OUT_OF_MEMORY,
"could not allocate memory for %s name parsing path", name_path);
result = asn1_number_of_elements (asn, top_path, &seq_components);
if (result != ASN1_SUCCESS)
{
err = VasEBoot_error (VAS_EBOOT_ERR_BAD_FILE_TYPE, "error counting name components: %s",
asn1_strerror (result));
goto cleanup;
}
for (i = 1; i <= seq_components; i++)
{
set_path = VasEBoot_xasprintf ("%s.?%d", top_path, i);
if (set_path == NULL)
{
err = VasEBoot_error (VAS_EBOOT_ERR_OUT_OF_MEMORY,
"could not allocate memory for %s name set parsing path",
name_path);
goto cleanup_set;
}
/* This brings us, hopefully, to a set. */
result = asn1_number_of_elements (asn, set_path, &set_components);
if (result != ASN1_SUCCESS)
{
err = VasEBoot_error (VAS_EBOOT_ERR_BAD_FILE_TYPE,
"error counting name sub-components components (element %d): %s",
i, asn1_strerror (result));
goto cleanup_set;
}
for (j = 1; j <= set_components; j++)
{
type_path = VasEBoot_xasprintf ("%s.?%d.?%d.type", top_path, i, j);
if (type_path == NULL)
{
err = VasEBoot_error (VAS_EBOOT_ERR_OUT_OF_MEMORY,
"could not allocate memory for %s name component type path",
name_path);
goto cleanup_set;
}
type_len = sizeof (type);
result = asn1_read_value (asn, type_path, type, &type_len);
if (result != ASN1_SUCCESS)
{
err = VasEBoot_error (VAS_EBOOT_ERR_BAD_FILE_TYPE, "error reading %s name component type: %s",
name_path, asn1_strerror (result));
goto cleanup_type;
}
if (VasEBoot_strncmp (type, commonName_oid, type_len) != 0)
{
VasEBoot_free (type_path);
continue;
}
val_path = VasEBoot_xasprintf ("%s.?%d.?%d.value", top_path, i, j);
if (val_path == NULL)
{
err = VasEBoot_error (VAS_EBOOT_ERR_OUT_OF_MEMORY,
"could not allocate memory for %s name component value path",
name_path);
goto cleanup_type;
}
string_der = VasEBoot_asn1_allocate_and_read (asn, val_path, name_path, &string_size);
if (string_der == NULL)
{
err = VasEBoot_errno;
goto cleanup_val_path;
}
err = decode_string (string_der, string_size, name, name_size);
if (err)
goto cleanup_string;
VasEBoot_free (string_der);
VasEBoot_free (type_path);
VasEBoot_free (val_path);
break;
}
VasEBoot_free (set_path);
if (*name)
break;
}
VasEBoot_free (top_path);
return VAS_EBOOT_ERR_NONE;
cleanup_string:
VasEBoot_free (string_der);
cleanup_val_path:
VasEBoot_free (val_path);
cleanup_type:
VasEBoot_free (type_path);
cleanup_set:
VasEBoot_free (set_path);
cleanup:
VasEBoot_free (top_path);
return err;
}
/* Verify the Key Usage extension. We require the Digital Signature usage. */
static VasEBoot_err_t
verify_key_usage (VasEBoot_uint8_t *value, VasEBoot_int32_t value_size)
{
asn1_node usageasn;
VasEBoot_int32_t result;
VasEBoot_err_t err = VAS_EBOOT_ERR_NONE;
VasEBoot_uint8_t usage = 0xff;
VasEBoot_int32_t usage_size = sizeof (usage_size);
result = asn1_create_element (VasEBoot_gnutls_pkix_asn, "PKIX1.KeyUsage", &usageasn);
if (result != ASN1_SUCCESS)
return VasEBoot_error (VAS_EBOOT_ERR_OUT_OF_MEMORY,
"could not create ASN.1 structure for key usage");
result = asn1_der_decoding2 (&usageasn, value, &value_size,
ASN1_DECODE_FLAG_STRICT_DER, asn1_error);
if (result != ASN1_SUCCESS)
{
err = VasEBoot_error (VAS_EBOOT_ERR_BAD_FILE_TYPE,
"error parsing DER for Key Usage: %s", asn1_error);
goto cleanup;
}
result = asn1_read_value (usageasn, "", &usage, &usage_size);
if (result != ASN1_SUCCESS)
{
err = VasEBoot_error (VAS_EBOOT_ERR_BAD_FILE_TYPE, "error reading Key Usage value: %s",
asn1_strerror (result));
goto cleanup;
}
if (!(usage & digitalSignatureUsage))
{
err = VasEBoot_error (VAS_EBOOT_ERR_BAD_FILE_TYPE,
"key usage (0x%x) missing Digital Signature usage", usage);
goto cleanup;
}
cleanup:
asn1_delete_structure (&usageasn);
return err;
}
/*
* BasicConstraints ::= SEQUENCE {
* cA BOOLEAN DEFAULT FALSE,
* pathLenConstraint INTEGER (0..MAX) OPTIONAL }
*/
static VasEBoot_err_t
verify_basic_constraints (VasEBoot_uint8_t *value, VasEBoot_int32_t value_size)
{
asn1_node basicasn;
VasEBoot_int32_t result;
VasEBoot_err_t err = VAS_EBOOT_ERR_NONE;
char cA[6]; /* FALSE or TRUE. */
VasEBoot_int32_t cA_size = sizeof (cA);
result = asn1_create_element (VasEBoot_gnutls_pkix_asn, "PKIX1.BasicConstraints", &basicasn);
if (result != ASN1_SUCCESS)
return VasEBoot_error (VAS_EBOOT_ERR_OUT_OF_MEMORY,
"could not create ASN.1 structure for Basic Constraints");
result = asn1_der_decoding2 (&basicasn, value, &value_size,
ASN1_DECODE_FLAG_STRICT_DER, asn1_error);
if (result != ASN1_SUCCESS)
{
err = VasEBoot_error (VAS_EBOOT_ERR_BAD_FILE_TYPE,
"error parsing DER for Basic Constraints: %s", asn1_error);
goto cleanup;
}
result = asn1_read_value (basicasn, "cA", cA, &cA_size);
if (result == ASN1_ELEMENT_NOT_FOUND)
{
/* Not present, default is False, so this is OK. */
err = VAS_EBOOT_ERR_NONE;
goto cleanup;
}
else if (result != ASN1_SUCCESS)
{
err = VasEBoot_error (VAS_EBOOT_ERR_BAD_FILE_TYPE, "error reading Basic Constraints cA value: %s",
asn1_strerror (result));
goto cleanup;
}
/* The certificate must not be a CA certificate. */
if (VasEBoot_strncmp ("FALSE", cA, cA_size) != 0)
{
err = VasEBoot_error (VAS_EBOOT_ERR_BAD_FILE_TYPE, "unexpected CA value: %s", cA);
goto cleanup;
}
cleanup:
asn1_delete_structure (&basicasn);
return err;
}
/*
* Verify the Extended Key Usage extension. We require the Code Signing usage.
*
* ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId
*
* KeyPurposeId ::= OBJECT IDENTIFIER
*/
static VasEBoot_err_t
verify_extended_key_usage (VasEBoot_uint8_t *value, VasEBoot_int32_t value_size)
{
asn1_node extendedasn;
VasEBoot_int32_t result, count, i = 0;
VasEBoot_err_t err = VAS_EBOOT_ERR_NONE;
char usage[VAS_EBOOT_MAX_OID_LEN], name[3];
VasEBoot_int32_t usage_size = sizeof (usage);
result = asn1_create_element (VasEBoot_gnutls_pkix_asn, "PKIX1.ExtKeyUsageSyntax", &extendedasn);
if (result != ASN1_SUCCESS)
return VasEBoot_error (VAS_EBOOT_ERR_OUT_OF_MEMORY,
"could not create ASN.1 structure for Extended Key Usage");
result = asn1_der_decoding2 (&extendedasn, value, &value_size,
ASN1_DECODE_FLAG_STRICT_DER, asn1_error);
if (result != ASN1_SUCCESS)
{
err = VasEBoot_error (VAS_EBOOT_ERR_BAD_FILE_TYPE,
"error parsing DER for Extended Key Usage: %s", asn1_error);
goto cleanup;
}
/* If EKUs are present, it checks the presents of Code Signing usage. */
result = asn1_number_of_elements (extendedasn, "", &count);
if (result != ASN1_SUCCESS)
{
err = VasEBoot_error (VAS_EBOOT_ERR_BAD_FILE_TYPE, "error counting number of Extended Key Usages: %s",
asn1_strerror (result));
goto cleanup;
}
for (i = 1; i < count + 1; i++)
{
VasEBoot_memset (name, 0, sizeof (name));
VasEBoot_snprintf (name, sizeof (name), "?%d", i);
result = asn1_read_value (extendedasn, name, usage, &usage_size);
if (result != ASN1_SUCCESS)
{
err = VasEBoot_error (VAS_EBOOT_ERR_BAD_FILE_TYPE, "error reading Extended Key Usage: %s",
asn1_strerror (result));
goto cleanup;
}
if (VasEBoot_strncmp (codeSigningUsage_oid, usage, usage_size) == 0)
goto cleanup;
}
err = VasEBoot_error (VAS_EBOOT_ERR_BAD_FILE_TYPE, "extended key usage missing Code Signing usage");
cleanup:
asn1_delete_structure (&extendedasn);
return err;
}
/*
* Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
*
* Extension ::= SEQUENCE {
* extnID OBJECT IDENTIFIER,
* critical BOOLEAN DEFAULT FALSE,
* extnValue OCTET STRING
* -- contains the DER encoding of an ASN.1 value
* -- corresponding to the extension type identified
* -- by extnID
* }
*
* A certificate must:
* - contain the Digital Signature usage
* - not be a CA
* - contain no extended usages, or contain the Code Signing extended usage
* - not contain any other critical extensions (RFC 5280 s 4.2)
*/
static VasEBoot_err_t
verify_extensions (asn1_node cert)
{
VasEBoot_int32_t result;
VasEBoot_int32_t ext, num_extensions = 0;
VasEBoot_int32_t usage_present = 0, constraints_present = 0, extended_usage_present = 0;
char *oid_path, *critical_path, *value_path;
char extnID[VAS_EBOOT_MAX_OID_LEN];
VasEBoot_int32_t extnID_size;
VasEBoot_err_t err;
char critical[6]; /* We get either "TRUE" or "FALSE". */
VasEBoot_int32_t critical_size;
VasEBoot_uint8_t *value;
VasEBoot_int32_t value_size;
result = asn1_number_of_elements (cert, "tbsCertificate.extensions", &num_extensions);
if (result != ASN1_SUCCESS)
return VasEBoot_error (VAS_EBOOT_ERR_BAD_FILE_TYPE, "error counting number of extensions: %s",
asn1_strerror (result));
if (num_extensions < 2)
return VasEBoot_error (VAS_EBOOT_ERR_BAD_FILE_TYPE,
"insufficient number of extensions for certificate, need at least 2, got %d",
num_extensions);
for (ext = 1; ext <= num_extensions; ext++)
{
oid_path = VasEBoot_xasprintf ("tbsCertificate.extensions.?%d.extnID", ext);
if (oid_path == NULL)
{
err = VasEBoot_error (VAS_EBOOT_ERR_BAD_FILE_TYPE, "error extension OID path is empty");
return err;
}
extnID_size = sizeof (extnID);
result = asn1_read_value (cert, oid_path, extnID, &extnID_size);
if (result != ASN1_SUCCESS)
{
err = VasEBoot_error (VAS_EBOOT_ERR_BAD_FILE_TYPE, "error reading extension OID: %s",
asn1_strerror (result));
goto cleanup_oid_path;
}
critical_path = VasEBoot_xasprintf ("tbsCertificate.extensions.?%d.critical", ext);
if (critical_path == NULL)
{
err = VasEBoot_error (VAS_EBOOT_ERR_BAD_FILE_TYPE, "error critical path is empty");
goto cleanup_oid_path;
}
critical_size = sizeof (critical);
result = asn1_read_value (cert, critical_path, critical, &critical_size);
if (result == ASN1_ELEMENT_NOT_FOUND)
critical[0] = '\0';
else if (result != ASN1_SUCCESS)
{
err = VasEBoot_error (VAS_EBOOT_ERR_BAD_FILE_TYPE, "error reading extension criticality: %s",
asn1_strerror (result));
goto cleanup_critical_path;
}
value_path = VasEBoot_xasprintf ("tbsCertificate.extensions.?%d.extnValue", ext);
if (value_path == NULL)
{
err = VasEBoot_error (VAS_EBOOT_ERR_BAD_FILE_TYPE, "error extnValue path is empty");
goto cleanup_critical_path;
}
value = VasEBoot_asn1_allocate_and_read (cert, value_path,
"certificate extension value", &value_size);
if (value == NULL)
{
err = VasEBoot_errno;
goto cleanup_value_path;
}
/*
* Now we must see if we recognise the OID. If we have an unrecognised
* critical extension we MUST bail.
*/
if (VasEBoot_strncmp (keyUsage_oid, extnID, extnID_size) == 0)
{
err = verify_key_usage (value, value_size);
if (err != VAS_EBOOT_ERR_NONE)
goto cleanup_value;
usage_present++;
}
else if (VasEBoot_strncmp (basicConstraints_oid, extnID, extnID_size) == 0)
{
err = verify_basic_constraints (value, value_size);
if (err != VAS_EBOOT_ERR_NONE)
goto cleanup_value;
constraints_present++;
}
else if (VasEBoot_strncmp (extendedKeyUsage_oid, extnID, extnID_size) == 0)
{
err = verify_extended_key_usage (value, value_size);
if (err != VAS_EBOOT_ERR_NONE)
goto cleanup_value;
extended_usage_present++;
}
else if (VasEBoot_strncmp ("TRUE", critical, critical_size) == 0)
{
/*
* Per the RFC, we must not process a certificate with a critical
* extension we do not understand.
*/
err = VasEBoot_error (VAS_EBOOT_ERR_BAD_FILE_TYPE,
"unhandled critical x509 extension with OID %s", extnID);
goto cleanup_value;
}
VasEBoot_free (value);
VasEBoot_free (value_path);
VasEBoot_free (critical_path);
VasEBoot_free (oid_path);
}
if (usage_present != 1)
return VasEBoot_error (VAS_EBOOT_ERR_BAD_FILE_TYPE,
"unexpected number of Key Usage extensions - expected 1, got %d",
usage_present);
if (constraints_present != 1)
return VasEBoot_error (VAS_EBOOT_ERR_BAD_FILE_TYPE,
"unexpected number of basic constraints extensions - expected 1, got %d",
constraints_present);
if (extended_usage_present > 1)
return VasEBoot_error (VAS_EBOOT_ERR_BAD_FILE_TYPE,
"unexpected number of Extended Key Usage extensions - expected 0 or 1, got %d",
extended_usage_present);
return VAS_EBOOT_ERR_NONE;
cleanup_value:
VasEBoot_free (value);
cleanup_value_path:
VasEBoot_free (value_path);
cleanup_critical_path:
VasEBoot_free (critical_path);
cleanup_oid_path:
VasEBoot_free (oid_path);
return err;
}
static void
add_cert_fingerprint (const void *data, const VasEBoot_size_t data_size,
VasEBoot_x509_cert_t *const cert)
{
/* Add SHA256 hash of certificate. */
VasEBoot_crypto_hash ((gcry_md_spec_t *) &_gcry_digest_spec_sha256,
&cert->fingerprint[VAS_EBOOT_FINGERPRINT_SHA256], data, data_size);
/* Add SHA384 hash of certificate. */
VasEBoot_crypto_hash ((gcry_md_spec_t *) &_gcry_digest_spec_sha384,
&cert->fingerprint[VAS_EBOOT_FINGERPRINT_SHA384], data, data_size);
/* Add SHA512 hash of certificate. */
VasEBoot_crypto_hash ((gcry_md_spec_t *) &_gcry_digest_spec_sha512,
&cert->fingerprint[VAS_EBOOT_FINGERPRINT_SHA512], data, data_size);
}
/*
* Parse a certificate whose DER-encoded form is in @data, of size @data_size.
* Return the results in @results, which must point to an allocated x509
* certificate.
*/
VasEBoot_err_t
VasEBoot_x509_cert_parse (const void *data, VasEBoot_size_t data_size, VasEBoot_x509_cert_t *results)
{
VasEBoot_int32_t result = 0;
asn1_node cert;
VasEBoot_err_t err;
VasEBoot_int32_t tmp_size;
VasEBoot_int32_t size = (VasEBoot_int32_t) data_size;
if (data_size > VAS_EBOOT_UINT_MAX)
return VasEBoot_error (VAS_EBOOT_ERR_OUT_OF_RANGE,
"cannot parse a certificate where data size > VAS_EBOOT_UINT_MAX");
result = asn1_create_element (VasEBoot_gnutls_pkix_asn, "PKIX1.Certificate", &cert);
if (result != ASN1_SUCCESS)
return VasEBoot_error (VAS_EBOOT_ERR_OUT_OF_MEMORY,
"could not create ASN.1 structure for certificate: %s",
asn1_strerror (result));
result = asn1_der_decoding2 (&cert, data, &size, ASN1_DECODE_FLAG_STRICT_DER, asn1_error);
if (result != ASN1_SUCCESS)
{
err = VasEBoot_error (VAS_EBOOT_ERR_BAD_FILE_TYPE,
"could not parse DER for certificate: %s", asn1_error);
goto cleanup;
}
/*
* TBSCertificate ::= SEQUENCE {
* version [0] EXPLICIT Version DEFAULT v1
*/
err = check_version (cert, results);
if (err != VAS_EBOOT_ERR_NONE)
goto cleanup;
/*
* serialNumber CertificateSerialNumber,
*
* CertificateSerialNumber ::= INTEGER
*/
results->serial = VasEBoot_asn1_allocate_and_read (cert, "tbsCertificate.serialNumber",
"certificate serial number", &tmp_size);
if (results->serial == NULL)
{
err = VasEBoot_errno;
goto cleanup;
}
/*
* It's safe to cast the signed int to an unsigned here, we know
* length is non-negative.
*/
results->serial_len = tmp_size;
/*
* signature AlgorithmIdentifier,
*
* We don't load the signature or issuer at the moment,
* as we don't attempt x509 verification.
*/
/*
* validity Validity,
*
* Validity ::= SEQUENCE {
* notBefore Time,
* notAfter Time }
*
* We can't validate this reasonably, we have no true time source on several
* platforms. For now we do not parse them.
*/
/*
* issuer Name,
*
* This is an X501 name, we parse out just the issuer.
*/
err = read_name (cert, "tbsCertificate.issuer", &results->issuer, &results->issuer_len);
if (err != VAS_EBOOT_ERR_NONE)
goto cleanup_serial;
/*
* subject Name,
*
* This is an X501 name, we parse out just the CN.
*/
err = read_name (cert, "tbsCertificate.subject", &results->subject, &results->subject_len);
if (err != VAS_EBOOT_ERR_NONE)
goto cleanup_issuer;
/*
* TBSCertificate ::= SEQUENCE {
* ...
* subjectPublicKeyInfo SubjectPublicKeyInfo,
* ...
*/
err = VasEBoot_x509_read_subject_public_key (cert, results);
if (err != VAS_EBOOT_ERR_NONE)
goto cleanup_name;
/*
* TBSCertificate ::= SEQUENCE {
* ...
* extensions [3] EXPLICIT Extensions OPTIONAL
* -- If present, version MUST be v3
* }
*/
err = verify_extensions (cert);
if (err != VAS_EBOOT_ERR_NONE)
goto cleanup_mpis;
/*
* We do not read or check the signature on the certificate:
* as discussed we do not try to validate the certificate but trust
* it implictly.
*/
asn1_delete_structure (&cert);
/* Add the fingerprint of the certificate. */
add_cert_fingerprint (data, data_size, results);
return VAS_EBOOT_ERR_NONE;
cleanup_mpis:
_gcry_mpi_release (results->mpis[VAS_EBOOT_RSA_PK_MODULUS]);
_gcry_mpi_release (results->mpis[VAS_EBOOT_RSA_PK_EXPONENT]);
cleanup_name:
VasEBoot_free (results->subject);
cleanup_issuer:
VasEBoot_free (results->issuer);
cleanup_serial:
VasEBoot_free (results->serial);
cleanup:
asn1_delete_structure (&cert);
return err;
}
/*
* Release all the storage associated with the x509 certificate. If the caller
* dynamically allocated the certificate, it must free it. The caller is also
* responsible for maintenance of the linked list.
*/
void
VasEBoot_x509_cert_release (VasEBoot_x509_cert_t *cert)
{
VasEBoot_free (cert->issuer);
VasEBoot_free (cert->subject);
VasEBoot_free (cert->serial);
_gcry_mpi_release (cert->mpis[VAS_EBOOT_RSA_PK_MODULUS]);
_gcry_mpi_release (cert->mpis[VAS_EBOOT_RSA_PK_EXPONENT]);
}

View File

@ -0,0 +1,57 @@
/*
* VAS_EBOOT -- GRand Unified Bootloader
* Copyright (C) 2011 Free Software Foundation, Inc.
*
* VAS_EBOOT 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.
*
* VAS_EBOOT 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 VAS_EBOOT. If not, see <http://www.gnu.org/licenses/>.
*/
#include <VasEBoot/dl.h>
#include <VasEBoot/misc.h>
#include <VasEBoot/command.h>
#include <VasEBoot/i18n.h>
#include <VasEBoot/arc/arc.h>
VAS_EBOOT_MOD_LICENSE ("GPLv3+");
/* Helper for VasEBoot_cmd_lsdev. */
static int
VasEBoot_cmd_lsdev_iter (const char *name,
const struct VasEBoot_arc_component *comp __attribute__ ((unused)),
void *data __attribute__ ((unused)))
{
VasEBoot_printf ("%s\n", name);
return 0;
}
static VasEBoot_err_t
VasEBoot_cmd_lsdev (VasEBoot_command_t cmd __attribute__ ((unused)),
int argc __attribute__ ((unused)),
char **args __attribute__ ((unused)))
{
VasEBoot_arc_iterate_devs (VasEBoot_cmd_lsdev_iter, 0, 0);
return 0;
}
static VasEBoot_command_t cmd;
VAS_EBOOT_MOD_INIT(lsdev)
{
cmd = VasEBoot_register_command ("lsdev", VasEBoot_cmd_lsdev, "",
N_("List devices."));
}
VAS_EBOOT_MOD_FINI(lsdev)
{
VasEBoot_unregister_command (cmd);
}

View File

@ -0,0 +1,161 @@
/*
* VAS_EBOOT -- GRand Unified Bootloader
* Copyright (C) 2023 Free Software Foundation, Inc.
*
* VAS_EBOOT 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.
*
* VAS_EBOOT 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 VAS_EBOOT. If not, see <http://www.gnu.org/licenses/>.
*
* Implementation of the Boot Loader Interface.
*/
#include <VasEBoot/charset.h>
#include <VasEBoot/efi/api.h>
#include <VasEBoot/efi/disk.h>
#include <VasEBoot/efi/efi.h>
#include <VasEBoot/err.h>
#include <VasEBoot/extcmd.h>
#include <VasEBoot/gpt_partition.h>
#include <VasEBoot/misc.h>
#include <VasEBoot/mm.h>
#include <VasEBoot/partition.h>
#include <VasEBoot/tpm.h>
#include <VasEBoot/types.h>
VAS_EBOOT_MOD_LICENSE ("GPLv3+");
#define MODNAME "bli"
static const VasEBoot_guid_t bli_vendor_guid = VAS_EBOOT_EFI_VENDOR_BOOT_LOADER_INTERFACE_GUID;
static VasEBoot_err_t
get_part_uuid (const char *device_name, char **part_uuid)
{
VasEBoot_device_t device;
VasEBoot_err_t status = VAS_EBOOT_ERR_NONE;
VasEBoot_disk_t disk = NULL;
struct VasEBoot_gpt_partentry entry;
device = VasEBoot_device_open (device_name);
if (device == NULL)
return VasEBoot_error (VasEBoot_errno, N_("cannot open device: %s"), device_name);
if (device->disk == NULL)
{
VasEBoot_dprintf ("bli", "%s is not a disk device, partuuid skipped\n", device_name);
*part_uuid = NULL;
VasEBoot_device_close (device);
return VAS_EBOOT_ERR_NONE;
}
if (device->disk->partition == NULL)
{
VasEBoot_dprintf ("bli", "%s has no partition, partuuid skipped\n", device_name);
*part_uuid = NULL;
VasEBoot_device_close (device);
return VAS_EBOOT_ERR_NONE;
}
disk = VasEBoot_disk_open (device->disk->name);
if (disk == NULL)
{
status = VasEBoot_error (VasEBoot_errno, N_("cannot open disk: %s"), device_name);
VasEBoot_device_close (device);
return status;
}
if (VasEBoot_strcmp (device->disk->partition->partmap->name, "gpt") != 0)
{
status = VasEBoot_error (VAS_EBOOT_ERR_BAD_PART_TABLE,
N_("this is not a GPT partition table: %s"), device_name);
goto fail;
}
if (VasEBoot_disk_read (disk, device->disk->partition->offset,
device->disk->partition->index, sizeof (entry), &entry) != VAS_EBOOT_ERR_NONE)
{
status = VasEBoot_error (VasEBoot_errno, N_("read error: %s"), device_name);
goto fail;
}
*part_uuid = VasEBoot_xasprintf ("%pG", &entry.guid);
if (*part_uuid == NULL)
status = VasEBoot_errno;
fail:
VasEBoot_disk_close (disk);
VasEBoot_device_close (device);
return status;
}
static VasEBoot_err_t
set_loader_device_part_uuid (void)
{
VasEBoot_efi_loaded_image_t *image;
char *device_name;
VasEBoot_err_t status = VAS_EBOOT_ERR_NONE;
char *part_uuid = NULL;
image = VasEBoot_efi_get_loaded_image (VasEBoot_efi_image_handle);
if (image == NULL)
return VasEBoot_error (VAS_EBOOT_ERR_BAD_DEVICE, N_("unable to find boot device"));
device_name = VasEBoot_efidisk_get_device_name (image->device_handle);
if (device_name == NULL)
return VasEBoot_error (VAS_EBOOT_ERR_BAD_DEVICE, N_("unable to find boot device"));
status = get_part_uuid (device_name, &part_uuid);
if (status == VAS_EBOOT_ERR_NONE && part_uuid)
status = VasEBoot_efi_set_variable_to_string ("LoaderDevicePartUUID", &bli_vendor_guid, part_uuid,
VAS_EBOOT_EFI_VARIABLE_BOOTSERVICE_ACCESS |
VAS_EBOOT_EFI_VARIABLE_RUNTIME_ACCESS);
else
VasEBoot_error (status, N_("unable to determine partition UUID of boot device"));
VasEBoot_free (part_uuid);
VasEBoot_free (device_name);
return status;
}
static VasEBoot_err_t
set_loader_active_pcr_banks (void)
{
VasEBoot_efi_uint32_t active_pcr_banks;
char *active_pcr_banks_str;
VasEBoot_err_t status;
active_pcr_banks = VasEBoot_tpm2_active_pcr_banks();
active_pcr_banks_str = VasEBoot_xasprintf ("0x%08x", active_pcr_banks);
if (active_pcr_banks_str == NULL)
return VasEBoot_error (VAS_EBOOT_ERR_OUT_OF_MEMORY, N_("cannot allocate active PCR banks string"));
status = VasEBoot_efi_set_variable_to_string ("LoaderTpm2ActivePcrBanks",
&bli_vendor_guid,
active_pcr_banks_str,
VAS_EBOOT_EFI_VARIABLE_BOOTSERVICE_ACCESS |
VAS_EBOOT_EFI_VARIABLE_RUNTIME_ACCESS);
VasEBoot_free (active_pcr_banks_str);
return status;
}
VAS_EBOOT_MOD_INIT (bli)
{
VasEBoot_efi_set_variable_to_string ("LoaderInfo", &bli_vendor_guid, PACKAGE_STRING,
VAS_EBOOT_EFI_VARIABLE_BOOTSERVICE_ACCESS |
VAS_EBOOT_EFI_VARIABLE_RUNTIME_ACCESS);
set_loader_device_part_uuid ();
set_loader_active_pcr_banks ();
/* No error here is critical, other than being logged */
VasEBoot_print_error ();
}

View File

@ -0,0 +1,162 @@
/* blocklist.c - print the block list of a file */
/*
* VAS_EBOOT -- GRand Unified Bootloader
* Copyright (C) 2006,2007 Free Software Foundation, Inc.
*
* VAS_EBOOT 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.
*
* VAS_EBOOT 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 VAS_EBOOT. If not, see <http://www.gnu.org/licenses/>.
*/
#include <VasEBoot/dl.h>
#include <VasEBoot/misc.h>
#include <VasEBoot/file.h>
#include <VasEBoot/mm.h>
#include <VasEBoot/disk.h>
#include <VasEBoot/partition.h>
#include <VasEBoot/command.h>
#include <VasEBoot/i18n.h>
VAS_EBOOT_MOD_LICENSE ("GPLv3+");
/* Context for VasEBoot_cmd_blocklist. */
struct blocklist_ctx
{
unsigned long start_sector;
unsigned num_sectors;
int num_entries;
VasEBoot_disk_addr_t part_start;
};
/* Helper for VasEBoot_cmd_blocklist. */
static void
print_blocklist (VasEBoot_disk_addr_t sector, unsigned num,
unsigned offset, unsigned length, struct blocklist_ctx *ctx)
{
if (ctx->num_entries++)
VasEBoot_printf (",");
VasEBoot_printf ("%llu", (unsigned long long) (sector - ctx->part_start));
if (num > 0)
VasEBoot_printf ("+%u", num);
if (offset != 0 || length != 0)
VasEBoot_printf ("[%u-%u]", offset, offset + length);
}
/* Helper for VasEBoot_cmd_blocklist. */
static VasEBoot_err_t
read_blocklist (VasEBoot_disk_addr_t sector, unsigned offset, unsigned length,
char *buf __attribute__ ((unused)), void *data)
{
struct blocklist_ctx *ctx = data;
if (ctx->num_sectors > 0)
{
if (ctx->start_sector + ctx->num_sectors == sector
&& offset == 0 && length >= VAS_EBOOT_DISK_SECTOR_SIZE)
{
ctx->num_sectors += length >> VAS_EBOOT_DISK_SECTOR_BITS;
sector += length >> VAS_EBOOT_DISK_SECTOR_BITS;
length &= (VAS_EBOOT_DISK_SECTOR_SIZE - 1);
}
if (!length)
return VAS_EBOOT_ERR_NONE;
print_blocklist (ctx->start_sector, ctx->num_sectors, 0, 0, ctx);
ctx->num_sectors = 0;
}
if (offset)
{
unsigned l = length + offset;
l &= (VAS_EBOOT_DISK_SECTOR_SIZE - 1);
l -= offset;
print_blocklist (sector, 0, offset, l, ctx);
length -= l;
sector++;
offset = 0;
}
if (!length)
return VAS_EBOOT_ERR_NONE;
if (length & (VAS_EBOOT_DISK_SECTOR_SIZE - 1))
{
if (length >> VAS_EBOOT_DISK_SECTOR_BITS)
{
print_blocklist (sector, length >> VAS_EBOOT_DISK_SECTOR_BITS, 0, 0, ctx);
sector += length >> VAS_EBOOT_DISK_SECTOR_BITS;
}
print_blocklist (sector, 0, 0, length & (VAS_EBOOT_DISK_SECTOR_SIZE - 1), ctx);
}
else
{
ctx->start_sector = sector;
ctx->num_sectors = length >> VAS_EBOOT_DISK_SECTOR_BITS;
}
return VAS_EBOOT_ERR_NONE;
}
static VasEBoot_err_t
VasEBoot_cmd_blocklist (VasEBoot_command_t cmd __attribute__ ((unused)),
int argc, char **args)
{
VasEBoot_file_t file;
char buf[VAS_EBOOT_DISK_SECTOR_SIZE];
struct blocklist_ctx ctx = {
.start_sector = 0,
.num_sectors = 0,
.num_entries = 0,
.part_start = 0
};
if (argc < 1)
return VasEBoot_error (VAS_EBOOT_ERR_BAD_ARGUMENT, N_("filename expected"));
file = VasEBoot_file_open (args[0], VAS_EBOOT_FILE_TYPE_PRINT_BLOCKLIST
| VAS_EBOOT_FILE_TYPE_NO_DECOMPRESS);
if (! file)
return VasEBoot_errno;
if (! file->device->disk)
return VasEBoot_error (VAS_EBOOT_ERR_BAD_DEVICE,
"this command is available only for disk devices");
ctx.part_start = VasEBoot_partition_get_start (file->device->disk->partition);
file->read_hook = read_blocklist;
file->read_hook_data = &ctx;
while (VasEBoot_file_read (file, buf, sizeof (buf)) > 0)
;
if (ctx.num_sectors > 0)
print_blocklist (ctx.start_sector, ctx.num_sectors, 0, 0, &ctx);
VasEBoot_file_close (file);
return VasEBoot_errno;
}
static VasEBoot_command_t cmd;
VAS_EBOOT_MOD_INIT(blocklist)
{
cmd = VasEBoot_register_command ("blocklist", VasEBoot_cmd_blocklist,
N_("FILE"), N_("Print a block list."));
}
VAS_EBOOT_MOD_FINI(blocklist)
{
VasEBoot_unregister_command (cmd);
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,245 @@
/* boot.c - command to boot an operating system */
/*
* VAS_EBOOT -- GRand Unified Bootloader
* Copyright (C) 2002,2003,2004,2005,2007,2009 Free Software Foundation, Inc.
*
* VAS_EBOOT 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.
*
* VAS_EBOOT 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 VAS_EBOOT. If not, see <http://www.gnu.org/licenses/>.
*/
#include <VasEBoot/normal.h>
#include <VasEBoot/dl.h>
#include <VasEBoot/misc.h>
#include <VasEBoot/loader.h>
#include <VasEBoot/kernel.h>
#include <VasEBoot/mm.h>
#include <VasEBoot/i18n.h>
VAS_EBOOT_MOD_LICENSE ("GPLv3+");
static VasEBoot_err_t (*VasEBoot_loader_boot_func) (void *context);
static VasEBoot_err_t (*VasEBoot_loader_unload_func) (void *context);
static void *VasEBoot_loader_context;
static int VasEBoot_loader_flags;
struct VasEBoot_simple_loader_hooks
{
VasEBoot_err_t (*boot) (void);
VasEBoot_err_t (*unload) (void);
};
/* Don't heap allocate this to avoid making VasEBoot_loader_set() fallible. */
static struct VasEBoot_simple_loader_hooks simple_loader_hooks;
struct VasEBoot_preboot
{
VasEBoot_err_t (*preboot_func) (int);
VasEBoot_err_t (*preboot_rest_func) (void);
VasEBoot_loader_preboot_hook_prio_t prio;
struct VasEBoot_preboot *next;
struct VasEBoot_preboot *prev;
};
static int VasEBoot_loader_loaded;
static struct VasEBoot_preboot *preboots_head = 0,
*preboots_tail = 0;
static VasEBoot_err_t
VasEBoot_simple_boot_hook (void *context)
{
struct VasEBoot_simple_loader_hooks *hooks;
hooks = (struct VasEBoot_simple_loader_hooks *) context;
return hooks->boot ();
}
static VasEBoot_err_t
VasEBoot_simple_unload_hook (void *context)
{
struct VasEBoot_simple_loader_hooks *hooks;
VasEBoot_err_t ret;
hooks = (struct VasEBoot_simple_loader_hooks *) context;
ret = hooks->unload ();
VasEBoot_memset (hooks, 0, sizeof (*hooks));
return ret;
}
int
VasEBoot_loader_is_loaded (void)
{
return VasEBoot_loader_loaded;
}
/* Register a preboot hook. */
struct VasEBoot_preboot *
VasEBoot_loader_register_preboot_hook (VasEBoot_err_t (*preboot_func) (int flags),
VasEBoot_err_t (*preboot_rest_func) (void),
VasEBoot_loader_preboot_hook_prio_t prio)
{
struct VasEBoot_preboot *cur, *new_preboot;
if (! preboot_func && ! preboot_rest_func)
return 0;
new_preboot = (struct VasEBoot_preboot *)
VasEBoot_malloc (sizeof (struct VasEBoot_preboot));
if (! new_preboot)
return 0;
new_preboot->preboot_func = preboot_func;
new_preboot->preboot_rest_func = preboot_rest_func;
new_preboot->prio = prio;
for (cur = preboots_head; cur && cur->prio > prio; cur = cur->next);
if (cur)
{
new_preboot->next = cur;
new_preboot->prev = cur->prev;
cur->prev = new_preboot;
}
else
{
new_preboot->next = 0;
new_preboot->prev = preboots_tail;
preboots_tail = new_preboot;
}
if (new_preboot->prev)
new_preboot->prev->next = new_preboot;
else
preboots_head = new_preboot;
return new_preboot;
}
void
VasEBoot_loader_unregister_preboot_hook (struct VasEBoot_preboot *hnd)
{
struct VasEBoot_preboot *preb = hnd;
if (preb->next)
preb->next->prev = preb->prev;
else
preboots_tail = preb->prev;
if (preb->prev)
preb->prev->next = preb->next;
else
preboots_head = preb->next;
VasEBoot_free (preb);
}
void
VasEBoot_loader_set_ex (VasEBoot_err_t (*boot) (void *context),
VasEBoot_err_t (*unload) (void *context),
void *context,
int flags)
{
if (VasEBoot_loader_loaded && VasEBoot_loader_unload_func)
VasEBoot_loader_unload_func (VasEBoot_loader_context);
VasEBoot_loader_boot_func = boot;
VasEBoot_loader_unload_func = unload;
VasEBoot_loader_context = context;
VasEBoot_loader_flags = flags;
VasEBoot_loader_loaded = 1;
}
void
VasEBoot_loader_set (VasEBoot_err_t (*boot) (void),
VasEBoot_err_t (*unload) (void),
int flags)
{
VasEBoot_loader_set_ex (VasEBoot_simple_boot_hook,
VasEBoot_simple_unload_hook,
&simple_loader_hooks,
flags);
simple_loader_hooks.boot = boot;
simple_loader_hooks.unload = unload;
}
void
VasEBoot_loader_unset(void)
{
if (VasEBoot_loader_loaded && VasEBoot_loader_unload_func)
VasEBoot_loader_unload_func (VasEBoot_loader_context);
VasEBoot_loader_boot_func = 0;
VasEBoot_loader_unload_func = 0;
VasEBoot_loader_context = 0;
VasEBoot_loader_loaded = 0;
}
VasEBoot_err_t
VasEBoot_loader_boot (void)
{
VasEBoot_err_t err = VAS_EBOOT_ERR_NONE;
struct VasEBoot_preboot *cur;
if (! VasEBoot_loader_loaded)
return VasEBoot_error (VAS_EBOOT_ERR_NO_KERNEL,
N_("you need to load the kernel first"));
VasEBoot_machine_fini (VasEBoot_loader_flags);
for (cur = preboots_head; cur; cur = cur->next)
{
err = cur->preboot_func (VasEBoot_loader_flags);
if (err)
{
for (cur = cur->prev; cur; cur = cur->prev)
cur->preboot_rest_func ();
return err;
}
}
err = (VasEBoot_loader_boot_func) (VasEBoot_loader_context);
for (cur = preboots_tail; cur; cur = cur->prev)
if (! err)
err = cur->preboot_rest_func ();
else
cur->preboot_rest_func ();
return err;
}
/* boot */
static VasEBoot_err_t
VasEBoot_cmd_boot (struct VasEBoot_command *cmd __attribute__ ((unused)),
int argc __attribute__ ((unused)),
char *argv[] __attribute__ ((unused)))
{
return VasEBoot_loader_boot ();
}
static VasEBoot_command_t cmd_boot;
VAS_EBOOT_MOD_INIT(boot)
{
cmd_boot =
VasEBoot_register_command ("boot", VasEBoot_cmd_boot,
0, N_("Boot an operating system."));
}
VAS_EBOOT_MOD_FINI(boot)
{
VasEBoot_unregister_command (cmd_boot);
}

View File

@ -0,0 +1,65 @@
/*
* VAS_EBOOT -- GRand Unified Bootloader
* Copyright (C) 2013 Free Software Foundation, Inc.
*
* VAS_EBOOT 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.
*
* VAS_EBOOT 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 VAS_EBOOT. If not, see <http://www.gnu.org/licenses/>.
*/
#include <VasEBoot/dl.h>
#include <VasEBoot/misc.h>
#include <VasEBoot/command.h>
#include <VasEBoot/i18n.h>
VAS_EBOOT_MOD_LICENSE ("GPLv3+");
static VasEBoot_err_t
VasEBoot_cmd_boottime (struct VasEBoot_command *cmd __attribute__ ((unused)),
int argc __attribute__ ((unused)),
char *argv[] __attribute__ ((unused)))
{
struct VasEBoot_boot_time *cur;
VasEBoot_uint64_t last_time = 0, start_time = 0;
if (!VasEBoot_boot_time_head)
{
VasEBoot_puts_ (N_("No boot time statistics is available\n"));
return 0;
}
start_time = last_time = VasEBoot_boot_time_head->tp;
for (cur = VasEBoot_boot_time_head; cur; cur = cur->next)
{
VasEBoot_uint32_t tmabs = cur->tp - start_time;
VasEBoot_uint32_t tmrel = cur->tp - last_time;
last_time = cur->tp;
VasEBoot_printf ("%3d.%03ds %2d.%03ds %s:%d %s\n",
tmabs / 1000, tmabs % 1000, tmrel / 1000, tmrel % 1000, cur->file, cur->line,
cur->msg);
}
return 0;
}
static VasEBoot_command_t cmd_boottime;
VAS_EBOOT_MOD_INIT(boottime)
{
cmd_boottime =
VasEBoot_register_command ("boottime", VasEBoot_cmd_boottime,
0, N_("Show boot time statistics."));
}
VAS_EBOOT_MOD_FINI(boottime)
{
VasEBoot_unregister_command (cmd_boottime);
}

View File

@ -0,0 +1,62 @@
/* cacheinfo.c - disk cache statistics */
/*
* VAS_EBOOT -- GRand Unified Bootloader
* Copyright (C) 2008,2010 Free Software Foundation, Inc.
*
* VAS_EBOOT 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.
*
* VAS_EBOOT 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 VAS_EBOOT. If not, see <http://www.gnu.org/licenses/>.
*/
#include <VasEBoot/dl.h>
#include <VasEBoot/misc.h>
#include <VasEBoot/command.h>
#include <VasEBoot/i18n.h>
#include <VasEBoot/disk.h>
VAS_EBOOT_MOD_LICENSE ("GPLv3+");
static VasEBoot_err_t
VasEBoot_rescue_cmd_info (struct VasEBoot_command *cmd __attribute__ ((unused)),
int argc __attribute__ ((unused)),
char *argv[] __attribute__ ((unused)))
{
unsigned long hits, misses;
VasEBoot_disk_cache_get_performance (&hits, &misses);
if (hits + misses)
{
unsigned long ratio = hits * 10000 / (hits + misses);
VasEBoot_printf ("(%lu.%lu%%)\n", ratio / 100, ratio % 100);
VasEBoot_printf_ (N_("Disk cache statistics: hits = %lu (%lu.%02lu%%),"
" misses = %lu\n"), ratio / 100, ratio % 100,
hits, misses);
}
else
VasEBoot_printf ("%s\n", _("No disk cache statistics available\n"));
return 0;
}
static VasEBoot_command_t cmd_cacheinfo;
VAS_EBOOT_MOD_INIT(cacheinfo)
{
cmd_cacheinfo =
VasEBoot_register_command ("cacheinfo", VasEBoot_rescue_cmd_info,
0, N_("Get disk cache info."));
}
VAS_EBOOT_MOD_FINI(cacheinfo)
{
VasEBoot_unregister_command (cmd_cacheinfo);
}

View File

@ -0,0 +1,170 @@
/* cat.c - command to show the contents of a file */
/*
* VAS_EBOOT -- GRand Unified Bootloader
* Copyright (C) 2003,2005,2007,2008 Free Software Foundation, Inc.
*
* VAS_EBOOT 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.
*
* VAS_EBOOT 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 VAS_EBOOT. If not, see <http://www.gnu.org/licenses/>.
*/
#include <VasEBoot/dl.h>
#include <VasEBoot/file.h>
#include <VasEBoot/disk.h>
#include <VasEBoot/term.h>
#include <VasEBoot/misc.h>
#include <VasEBoot/extcmd.h>
#include <VasEBoot/i18n.h>
#include <VasEBoot/charset.h>
VAS_EBOOT_MOD_LICENSE ("GPLv3+");
static const struct VasEBoot_arg_option options[] =
{
{"dos", -1, 0, N_("Accept DOS-style CR/NL line endings."), 0, 0},
{0, 0, 0, 0, 0, 0}
};
static VasEBoot_err_t
VasEBoot_cmd_cat (VasEBoot_extcmd_context_t ctxt, int argc, char **args)
{
struct VasEBoot_arg_list *state = ctxt->state;
int dos = 0;
VasEBoot_file_t file;
unsigned char buf[VAS_EBOOT_DISK_SECTOR_SIZE];
VasEBoot_ssize_t size;
int key = VAS_EBOOT_TERM_NO_KEY;
VasEBoot_uint32_t code = 0;
int count = 0;
unsigned char utbuf[VAS_EBOOT_MAX_UTF8_PER_CODEPOINT + 1];
int utcount = 0;
int is_0d = 0;
int j;
if (state[0].set)
dos = 1;
if (argc != 1)
return VasEBoot_error (VAS_EBOOT_ERR_BAD_ARGUMENT, N_("filename expected"));
file = VasEBoot_file_open (args[0], VAS_EBOOT_FILE_TYPE_CAT);
if (! file)
return VasEBoot_errno;
while ((size = VasEBoot_file_read (file, buf, sizeof (buf))) > 0
&& key != VAS_EBOOT_TERM_ESC)
{
int i;
for (i = 0; i < size; i++)
{
utbuf[utcount++] = buf[i];
if (is_0d && buf[i] != '\n')
{
VasEBoot_setcolorstate (VAS_EBOOT_TERM_COLOR_HIGHLIGHT);
VasEBoot_printf ("<%x>", (int) '\r');
VasEBoot_setcolorstate (VAS_EBOOT_TERM_COLOR_STANDARD);
}
is_0d = 0;
if (!VasEBoot_utf8_process (buf[i], &code, &count))
{
VasEBoot_setcolorstate (VAS_EBOOT_TERM_COLOR_HIGHLIGHT);
for (j = 0; j < utcount - 1; j++)
VasEBoot_printf ("<%x>", (unsigned int) utbuf[j]);
code = 0;
count = 0;
if (utcount == 1 || !VasEBoot_utf8_process (buf[i], &code, &count))
{
VasEBoot_printf ("<%x>", (unsigned int) buf[i]);
code = 0;
count = 0;
utcount = 0;
VasEBoot_setcolorstate (VAS_EBOOT_TERM_COLOR_STANDARD);
continue;
}
VasEBoot_setcolorstate (VAS_EBOOT_TERM_COLOR_STANDARD);
utcount = 1;
}
if (count)
continue;
if ((code >= 0xa1 || VasEBoot_isprint (code)
|| VasEBoot_isspace (code)) && code != '\r')
{
VasEBoot_printf ("%C", code);
count = 0;
code = 0;
utcount = 0;
continue;
}
if (dos && code == '\r')
{
is_0d = 1;
count = 0;
code = 0;
utcount = 0;
continue;
}
VasEBoot_setcolorstate (VAS_EBOOT_TERM_COLOR_HIGHLIGHT);
for (j = 0; j < utcount; j++)
VasEBoot_printf ("<%x>", (unsigned int) utbuf[j]);
VasEBoot_setcolorstate (VAS_EBOOT_TERM_COLOR_STANDARD);
count = 0;
code = 0;
utcount = 0;
}
do
key = VasEBoot_getkey_noblock ();
while (key != VAS_EBOOT_TERM_ESC && key != VAS_EBOOT_TERM_NO_KEY);
}
if (is_0d)
{
VasEBoot_setcolorstate (VAS_EBOOT_TERM_COLOR_HIGHLIGHT);
VasEBoot_printf ("<%x>", (unsigned int) '\r');
VasEBoot_setcolorstate (VAS_EBOOT_TERM_COLOR_STANDARD);
}
if (utcount)
{
VasEBoot_setcolorstate (VAS_EBOOT_TERM_COLOR_HIGHLIGHT);
for (j = 0; j < utcount; j++)
VasEBoot_printf ("<%x>", (unsigned int) utbuf[j]);
VasEBoot_setcolorstate (VAS_EBOOT_TERM_COLOR_STANDARD);
}
VasEBoot_xputs ("\n");
VasEBoot_refresh ();
VasEBoot_file_close (file);
return 0;
}
static VasEBoot_extcmd_t cmd;
VAS_EBOOT_MOD_INIT(cat)
{
cmd = VasEBoot_register_extcmd ("cat", VasEBoot_cmd_cat, 0,
N_("FILE"), N_("Show the contents of a file."),
options);
}
VAS_EBOOT_MOD_FINI(cat)
{
VasEBoot_unregister_extcmd (cmd);
}

View File

@ -0,0 +1,131 @@
/* cmd.c - command to cmp an operating system */
/*
* VAS_EBOOT -- GRand Unified Bootloader
* Copyright (C) 2003,2005,2006,2007,2009 Free Software Foundation, Inc.
*
* VAS_EBOOT 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.
*
* VAS_EBOOT 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 VAS_EBOOT. If not, see <http://www.gnu.org/licenses/>.
*/
#include <VasEBoot/dl.h>
#include <VasEBoot/misc.h>
#include <VasEBoot/file.h>
#include <VasEBoot/mm.h>
#include <VasEBoot/command.h>
#include <VasEBoot/extcmd.h>
#include <VasEBoot/i18n.h>
VAS_EBOOT_MOD_LICENSE ("GPLv3+");
#define BUFFER_SIZE 512
static const struct VasEBoot_arg_option options[] =
{
{0, 'v', 0, N_("Enable verbose output"), 0, 0},
{0, 0, 0, 0, 0, 0}
};
static VasEBoot_err_t
VasEBoot_cmd_cmp (VasEBoot_extcmd_context_t ctxt,
int argc, char **args)
{
VasEBoot_ssize_t rd1, rd2;
VasEBoot_off_t pos;
VasEBoot_file_t file1 = 0;
VasEBoot_file_t file2 = 0;
char *buf1 = 0;
char *buf2 = 0;
VasEBoot_err_t err = VAS_EBOOT_ERR_TEST_FAILURE;
if (argc != 2)
return VasEBoot_error (VAS_EBOOT_ERR_BAD_ARGUMENT, N_("two arguments expected"));
if (ctxt->state[0].set)
VasEBoot_printf_ (N_("Compare file `%s' with `%s':\n"), args[0], args[1]);
file1 = VasEBoot_file_open (args[0], VAS_EBOOT_FILE_TYPE_CMP);
file2 = VasEBoot_file_open (args[1], VAS_EBOOT_FILE_TYPE_CMP);
if (! file1 || ! file2)
goto cleanup;
if (ctxt->state[0].set && (VasEBoot_file_size (file1) != VasEBoot_file_size (file2)))
VasEBoot_printf_ (N_("Files differ in size: %llu [%s], %llu [%s]\n"),
(unsigned long long) VasEBoot_file_size (file1), args[0],
(unsigned long long) VasEBoot_file_size (file2), args[1]);
else
{
pos = 0;
buf1 = VasEBoot_malloc (BUFFER_SIZE);
buf2 = VasEBoot_malloc (BUFFER_SIZE);
if (! buf1 || ! buf2)
goto cleanup;
do
{
int i;
rd1 = VasEBoot_file_read (file1, buf1, BUFFER_SIZE);
rd2 = VasEBoot_file_read (file2, buf2, BUFFER_SIZE);
if (rd1 != rd2)
goto cleanup;
for (i = 0; i < rd2; i++)
{
if (buf1[i] != buf2[i])
{
if (ctxt->state[0].set)
VasEBoot_printf_ (N_("Files differ at the offset %llu: 0x%x [%s], 0x%x [%s]\n"),
(unsigned long long) (i + pos), buf1[i],
args[0], buf2[i], args[1]);
goto cleanup;
}
}
pos += BUFFER_SIZE;
}
while (rd2);
/* TRANSLATORS: it's always exactly 2 files. */
if (ctxt->state[0].set)
VasEBoot_printf_ (N_("The files are identical.\n"));
err = VAS_EBOOT_ERR_NONE;
}
cleanup:
VasEBoot_free (buf1);
VasEBoot_free (buf2);
if (file1)
VasEBoot_file_close (file1);
if (file2)
VasEBoot_file_close (file2);
return err;
}
static VasEBoot_extcmd_t cmd;
VAS_EBOOT_MOD_INIT(cmp)
{
cmd = VasEBoot_register_extcmd ("cmp", VasEBoot_cmd_cmp, 0,
N_("FILE1 FILE2"), N_("Compare two files."),
options);
}
VAS_EBOOT_MOD_FINI(cmp)
{
VasEBoot_unregister_extcmd (cmd);
}

View File

@ -0,0 +1,98 @@
/* configfile.c - command to manually load config file */
/*
* VAS_EBOOT -- GRand Unified Bootloader
* Copyright (C) 2005,2006,2007,2009 Free Software Foundation, Inc.
*
* VAS_EBOOT 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.
*
* VAS_EBOOT 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 VAS_EBOOT. If not, see <http://www.gnu.org/licenses/>.
*/
#include <VasEBoot/dl.h>
#include <VasEBoot/term.h>
#include <VasEBoot/env.h>
#include <VasEBoot/normal.h>
#include <VasEBoot/command.h>
#include <VasEBoot/i18n.h>
VAS_EBOOT_MOD_LICENSE ("GPLv3+");
static VasEBoot_err_t
VasEBoot_cmd_source (VasEBoot_command_t cmd, int argc, char **args)
{
int new_env, extractor;
if (argc != 1)
return VasEBoot_error (VAS_EBOOT_ERR_BAD_ARGUMENT, N_("filename expected"));
extractor = (cmd->name[0] == 'e');
new_env = (cmd->name[extractor ? sizeof ("extract_entries_") - 1 : 0] == 'c');
if (new_env)
VasEBoot_cls ();
if (new_env && !extractor)
VasEBoot_env_context_open ();
if (extractor)
VasEBoot_env_extractor_open (!new_env);
VasEBoot_normal_execute (args[0], 1, ! new_env);
if (new_env && !extractor)
VasEBoot_env_context_close ();
if (extractor)
VasEBoot_env_extractor_close (!new_env);
return 0;
}
static VasEBoot_command_t cmd_configfile, cmd_source, cmd_dot;
static VasEBoot_command_t cmd_extractor_source, cmd_extractor_configfile;
VAS_EBOOT_MOD_INIT(configfile)
{
cmd_configfile =
VasEBoot_register_command ("configfile", VasEBoot_cmd_source,
N_("FILE"), N_("Load another config file."));
cmd_source =
VasEBoot_register_command ("source", VasEBoot_cmd_source,
N_("FILE"),
N_("Load another config file without changing context.")
);
cmd_extractor_source =
VasEBoot_register_command ("extract_entries_source", VasEBoot_cmd_source,
N_("FILE"),
N_("Load another config file without changing context but take only menu entries.")
);
cmd_extractor_configfile =
VasEBoot_register_command ("extract_entries_configfile", VasEBoot_cmd_source,
N_("FILE"),
N_("Load another config file but take only menu entries.")
);
cmd_dot =
VasEBoot_register_command (".", VasEBoot_cmd_source,
N_("FILE"),
N_("Load another config file without changing context.")
);
}
VAS_EBOOT_MOD_FINI(configfile)
{
VasEBoot_unregister_command (cmd_configfile);
VasEBoot_unregister_command (cmd_source);
VasEBoot_unregister_command (cmd_extractor_configfile);
VasEBoot_unregister_command (cmd_extractor_source);
VasEBoot_unregister_command (cmd_dot);
}

View File

@ -0,0 +1,149 @@
/* date.c - command to display/set current datetime. */
/*
* VAS_EBOOT -- GRand Unified Bootloader
* Copyright (C) 2008 Free Software Foundation, Inc.
*
* VAS_EBOOT 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.
*
* VAS_EBOOT 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 VAS_EBOOT. If not, see <http://www.gnu.org/licenses/>.
*/
#include <VasEBoot/dl.h>
#include <VasEBoot/err.h>
#include <VasEBoot/misc.h>
#include <VasEBoot/datetime.h>
#include <VasEBoot/command.h>
#include <VasEBoot/i18n.h>
VAS_EBOOT_MOD_LICENSE ("GPLv3+");
#define VAS_EBOOT_DATETIME_SET_YEAR 1
#define VAS_EBOOT_DATETIME_SET_MONTH 2
#define VAS_EBOOT_DATETIME_SET_DAY 4
#define VAS_EBOOT_DATETIME_SET_HOUR 8
#define VAS_EBOOT_DATETIME_SET_MINUTE 16
#define VAS_EBOOT_DATETIME_SET_SECOND 32
static VasEBoot_err_t
VasEBoot_cmd_date (VasEBoot_command_t cmd __attribute__ ((unused)),
int argc, char **args)
{
struct VasEBoot_datetime datetime;
int limit[6][2] = {{1980, 2079}, {1, 12}, {1, 31}, {0, 23}, {0, 59}, {0, 59}};
int value[6], mask;
if (argc == 0)
{
if (VasEBoot_get_datetime (&datetime))
return VasEBoot_errno;
VasEBoot_printf ("%d-%02d-%02d %02d:%02d:%02d %s\n",
datetime.year, datetime.month, datetime.day,
datetime.hour, datetime.minute, datetime.second,
VasEBoot_get_weekday_name (&datetime));
return 0;
}
VasEBoot_memset (&value, 0, sizeof (value));
mask = 0;
for (; argc; argc--, args++)
{
const char *p;
char c;
int m1, ofs, n, cur_mask;
p = args[0];
m1 = VasEBoot_strtoul (p, &p, 10);
c = *p;
if (c == '-')
ofs = 0;
else if (c == ':')
ofs = 3;
else
goto fail;
value[ofs] = m1;
cur_mask = (1 << ofs);
mask &= ~(cur_mask * (1 + 2 + 4));
for (n = 1; (n < 3) && (*p); n++)
{
if (*p != c)
goto fail;
value[ofs + n] = VasEBoot_strtoul (p + 1, &p, 10);
cur_mask |= (1 << (ofs + n));
}
if (*p)
goto fail;
if ((ofs == 0) && (n == 2))
{
value[ofs + 2] = value[ofs + 1];
value[ofs + 1] = value[ofs];
ofs++;
cur_mask <<= 1;
}
for (; n; n--, ofs++)
if ((value [ofs] < limit[ofs][0]) ||
(value [ofs] > limit[ofs][1]))
goto fail;
mask |= cur_mask;
}
if (VasEBoot_get_datetime (&datetime))
return VasEBoot_errno;
if (mask & VAS_EBOOT_DATETIME_SET_YEAR)
datetime.year = value[0];
if (mask & VAS_EBOOT_DATETIME_SET_MONTH)
datetime.month = value[1];
if (mask & VAS_EBOOT_DATETIME_SET_DAY)
datetime.day = value[2];
if (mask & VAS_EBOOT_DATETIME_SET_HOUR)
datetime.hour = value[3];
if (mask & VAS_EBOOT_DATETIME_SET_MINUTE)
datetime.minute = value[4];
if (mask & VAS_EBOOT_DATETIME_SET_SECOND)
datetime.second = value[5];
return VasEBoot_set_datetime (&datetime);
fail:
return VasEBoot_error (VAS_EBOOT_ERR_BAD_ARGUMENT, "invalid datetime");
}
static VasEBoot_command_t cmd;
VAS_EBOOT_MOD_INIT(date)
{
cmd =
VasEBoot_register_command ("date", VasEBoot_cmd_date,
N_("[[year-]month-day] [hour:minute[:second]]"),
N_("Display/set current datetime."));
}
VAS_EBOOT_MOD_FINI(date)
{
VasEBoot_unregister_command (cmd);
}

View File

@ -0,0 +1,141 @@
/* echo.c - Command to display a line of text */
/*
* VAS_EBOOT -- GRand Unified Bootloader
* Copyright (C) 2006,2007,2010 Free Software Foundation, Inc.
*
* VAS_EBOOT 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.
*
* VAS_EBOOT 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 VAS_EBOOT. If not, see <http://www.gnu.org/licenses/>.
*/
#include <VasEBoot/dl.h>
#include <VasEBoot/misc.h>
#include <VasEBoot/extcmd.h>
#include <VasEBoot/i18n.h>
#include <VasEBoot/term.h>
VAS_EBOOT_MOD_LICENSE ("GPLv3+");
static const struct VasEBoot_arg_option options[] =
{
{0, 'n', 0, N_("Do not output the trailing newline."), 0, 0},
{0, 'e', 0, N_("Enable interpretation of backslash escapes."), 0, 0},
{0, 0, 0, 0, 0, 0}
};
static VasEBoot_err_t
VasEBoot_cmd_echo (VasEBoot_extcmd_context_t ctxt, int argc, char **args)
{
struct VasEBoot_arg_list *state = ctxt->state;
int newline = 1;
int i;
/* Check if `-n' was used. */
if (state[0].set)
newline = 0;
for (i = 0; i < argc; i++)
{
char *arg = *args;
/* Unescaping results in a string no longer than the original. */
char *unescaped = VasEBoot_malloc (VasEBoot_strlen (arg) + 1);
char *p = unescaped;
args++;
if (!unescaped)
return VasEBoot_errno;
while (*arg)
{
/* In case `-e' is used, parse backslashes. */
if (*arg == '\\' && state[1].set)
{
arg++;
if (*arg == '\0')
break;
switch (*arg)
{
case '\\':
*p++ = '\\';
break;
case 'a':
*p++ = '\a';
break;
case 'c':
newline = 0;
break;
case 'f':
*p++ = '\f';
break;
case 'n':
*p++ = '\n';
break;
case 'r':
*p++ = '\r';
break;
case 't':
*p++ = '\t';
break;
case 'v':
*p++ = '\v';
break;
}
arg++;
continue;
}
/* This was not an escaped character, or escaping is not
enabled. */
*p++ = *arg;
arg++;
}
*p = '\0';
VasEBoot_xputs (unescaped);
VasEBoot_free (unescaped);
/* If another argument follows, insert a space. */
if (i != argc - 1)
VasEBoot_printf (" " );
}
if (newline)
VasEBoot_printf ("\n");
VasEBoot_refresh ();
return 0;
}
static VasEBoot_extcmd_t cmd;
VAS_EBOOT_MOD_INIT(echo)
{
cmd = VasEBoot_register_extcmd ("echo", VasEBoot_cmd_echo,
VAS_EBOOT_COMMAND_ACCEPT_DASH
| VAS_EBOOT_COMMAND_OPTIONS_AT_START,
N_("[-e|-n] STRING"), N_("Display a line of text."),
options);
}
VAS_EBOOT_MOD_FINI(echo)
{
VasEBoot_unregister_extcmd (cmd);
}

View File

@ -0,0 +1,102 @@
/* fwsetup.c - Reboot into firmware setup menu. */
/*
* VAS_EBOOT -- GRand Unified Bootloader
* Copyright (C) 2012 Free Software Foundation, Inc.
*
* VAS_EBOOT 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.
*
* VAS_EBOOT 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 VAS_EBOOT. If not, see <http://www.gnu.org/licenses/>.
*/
#include <VasEBoot/types.h>
#include <VasEBoot/mm.h>
#include <VasEBoot/misc.h>
#include <VasEBoot/efi/api.h>
#include <VasEBoot/efi/efi.h>
#include <VasEBoot/command.h>
#include <VasEBoot/i18n.h>
VAS_EBOOT_MOD_LICENSE ("GPLv3+");
static VasEBoot_efi_boolean_t efifwsetup_is_supported (void);
static VasEBoot_err_t
VasEBoot_cmd_fwsetup (VasEBoot_command_t cmd __attribute__ ((unused)),
int argc __attribute__ ((unused)),
char **args __attribute__ ((unused)))
{
VasEBoot_efi_uint64_t *old_os_indications;
VasEBoot_efi_uint64_t os_indications = VAS_EBOOT_EFI_OS_INDICATIONS_BOOT_TO_FW_UI;
VasEBoot_err_t status;
VasEBoot_size_t oi_size;
static VasEBoot_guid_t global = VAS_EBOOT_EFI_GLOBAL_VARIABLE_GUID;
if (argc >= 1 && VasEBoot_strcmp(args[0], "--is-supported") == 0)
return !efifwsetup_is_supported ();
if (!efifwsetup_is_supported ())
return VasEBoot_error (VAS_EBOOT_ERR_INVALID_COMMAND,
N_("reboot to firmware setup is not supported by the current firmware"));
VasEBoot_efi_get_variable ("OsIndications", &global, &oi_size,
(void **) &old_os_indications);
if (old_os_indications != NULL && oi_size == sizeof (os_indications))
os_indications |= *old_os_indications;
VasEBoot_free (old_os_indications);
status = VasEBoot_efi_set_variable ("OsIndications", &global, &os_indications,
sizeof (os_indications));
if (status != VAS_EBOOT_ERR_NONE)
return status;
VasEBoot_reboot ();
return VAS_EBOOT_ERR_BUG;
}
static VasEBoot_command_t cmd = NULL;
static VasEBoot_efi_boolean_t
efifwsetup_is_supported (void)
{
VasEBoot_efi_uint64_t *os_indications_supported = NULL;
VasEBoot_size_t oi_size = 0;
static VasEBoot_guid_t global = VAS_EBOOT_EFI_GLOBAL_VARIABLE_GUID;
VasEBoot_efi_boolean_t ret = 0;
VasEBoot_efi_get_variable ("OsIndicationsSupported", &global, &oi_size,
(void **) &os_indications_supported);
if (!os_indications_supported)
goto done;
if (*os_indications_supported & VAS_EBOOT_EFI_OS_INDICATIONS_BOOT_TO_FW_UI)
ret = 1;
done:
VasEBoot_free (os_indications_supported);
return ret;
}
VAS_EBOOT_MOD_INIT (efifwsetup)
{
cmd = VasEBoot_register_command ("fwsetup", VasEBoot_cmd_fwsetup, NULL,
N_("Reboot into firmware setup menu."));
}
VAS_EBOOT_MOD_FINI (efifwsetup)
{
if (cmd)
VasEBoot_unregister_command (cmd);
}

View File

@ -0,0 +1,153 @@
/*
* VAS_EBOOT -- GRand Unified Bootloader
* Copyright (C) 2022 Free Software Foundation, Inc.
*
* VAS_EBOOT 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.
*
* VAS_EBOOT 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 VAS_EBOOT. If not, see <http://www.gnu.org/licenses/>.
*
* Set/Get UEFI text output mode resolution.
*/
#include <VasEBoot/dl.h>
#include <VasEBoot/misc.h>
#include <VasEBoot/mm.h>
#include <VasEBoot/command.h>
#include <VasEBoot/i18n.h>
#include <VasEBoot/efi/efi.h>
#include <VasEBoot/efi/api.h>
VAS_EBOOT_MOD_LICENSE ("GPLv3+");
static VasEBoot_err_t
VasEBoot_efi_set_mode (VasEBoot_efi_simple_text_output_interface_t *o,
VasEBoot_efi_int32_t mode)
{
VasEBoot_efi_status_t status;
if (mode != o->mode->mode)
{
status = o->set_mode (o, mode);
if (status == VAS_EBOOT_EFI_SUCCESS)
;
else if (status == VAS_EBOOT_EFI_DEVICE_ERROR)
return VasEBoot_error (VAS_EBOOT_ERR_BAD_DEVICE,
N_("device error: could not set requested mode"));
else if (status == VAS_EBOOT_EFI_UNSUPPORTED)
return VasEBoot_error (VAS_EBOOT_ERR_OUT_OF_RANGE,
N_("invalid mode: number not valid"));
else
return VasEBoot_error (VAS_EBOOT_ERR_BAD_FIRMWARE,
N_("unexpected EFI error number: `%u'"),
(unsigned) status);
}
return VAS_EBOOT_ERR_NONE;
}
static VasEBoot_err_t
VasEBoot_cmd_efitextmode (VasEBoot_command_t cmd __attribute__ ((unused)),
int argc, char **args)
{
VasEBoot_efi_simple_text_output_interface_t *o = VasEBoot_efi_system_table->con_out;
unsigned long mode;
const char *p = NULL;
VasEBoot_err_t err;
VasEBoot_efi_uintn_t columns, rows;
VasEBoot_efi_int32_t i;
if (o == NULL)
return VasEBoot_error (VAS_EBOOT_ERR_BAD_DEVICE, N_("no UEFI output console interface"));
if (o->mode == NULL)
return VasEBoot_error (VAS_EBOOT_ERR_BUG, N_("no mode struct for UEFI output console"));
if (argc > 2)
return VasEBoot_error (VAS_EBOOT_ERR_BAD_ARGUMENT, N_("at most two arguments expected"));
if (argc == 0)
{
VasEBoot_printf_ (N_("Available modes for console output device.\n"));
for (i = 0; i < o->mode->max_mode; i++)
if (VAS_EBOOT_EFI_SUCCESS == o->query_mode (o, i, &columns, &rows))
VasEBoot_printf_ (N_(" [%" PRIuVAS_EBOOT_EFI_UINT32_T "] Col %5"
PRIuVAS_EBOOT_EFI_UINTN_T " Row %5" PRIuVAS_EBOOT_EFI_UINTN_T
" %c\n"),
i, columns, rows, (i == o->mode->mode) ? '*' : ' ');
}
else if (argc == 1)
{
if (VasEBoot_strcmp (args[0], "min") == 0)
mode = 0;
else if (VasEBoot_strcmp (args[0], "max") == 0)
mode = o->mode->max_mode - 1;
else
{
mode = VasEBoot_strtoul (args[0], &p, 0);
if (*args[0] == '\0' || *p != '\0')
return VasEBoot_error (VAS_EBOOT_ERR_BAD_ARGUMENT,
N_("non-numeric or invalid mode `%s'"), args[0]);
}
if (mode < (unsigned long) o->mode->max_mode)
{
err = VasEBoot_efi_set_mode (o, (VasEBoot_efi_int32_t) mode);
if (err != VAS_EBOOT_ERR_NONE)
return err;
}
else
return VasEBoot_error (VAS_EBOOT_ERR_BAD_ARGUMENT,
N_("invalid mode: `%lu' is greater than maximum mode `%lu'"),
mode, (unsigned long) o->mode->max_mode);
}
else if (argc == 2)
{
VasEBoot_efi_uintn_t u_columns, u_rows;
u_columns = (VasEBoot_efi_uintn_t) VasEBoot_strtoul (args[0], &p, 0);
if (*args[0] == '\0' || *p != '\0')
return VasEBoot_error (VAS_EBOOT_ERR_BAD_ARGUMENT,
N_("non-numeric or invalid columns number `%s'"), args[0]);
u_rows = (VasEBoot_efi_uintn_t) VasEBoot_strtoul (args[1], &p, 0);
if (*args[1] == '\0' || *p != '\0')
return VasEBoot_error (VAS_EBOOT_ERR_BAD_ARGUMENT,
N_("non-numeric or invalid rows number `%s'"), args[1]);
for (i = 0; i < o->mode->max_mode; i++)
if (VAS_EBOOT_EFI_SUCCESS == o->query_mode (o, i, &columns, &rows))
if (u_columns == columns && u_rows == rows)
return VasEBoot_efi_set_mode (o, (VasEBoot_efi_int32_t) i);
return VasEBoot_error (VAS_EBOOT_ERR_BAD_ARGUMENT,
N_("no mode found with requested columns and rows"));
}
return VAS_EBOOT_ERR_NONE;
}
static VasEBoot_command_t cmd;
VAS_EBOOT_MOD_INIT (efitextmode)
{
cmd = VasEBoot_register_command ("efitextmode", VasEBoot_cmd_efitextmode,
N_("[min | max | <mode_num> | <cols> <rows>]"),
N_("Get or set EFI text mode."));
}
VAS_EBOOT_MOD_FINI (efitextmode)
{
VasEBoot_unregister_command (cmd);
}

View File

@ -0,0 +1,114 @@
/* fixvideo.c - fix video problem in efi */
/*
* VAS_EBOOT -- GRand Unified Bootloader
* Copyright (C) 2009 Free Software Foundation, Inc.
*
* VAS_EBOOT 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.
*
* VAS_EBOOT 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 VAS_EBOOT. If not, see <http://www.gnu.org/licenses/>.
*/
#include <VasEBoot/dl.h>
#include <VasEBoot/misc.h>
#include <VasEBoot/file.h>
#include <VasEBoot/pci.h>
#include <VasEBoot/command.h>
#include <VasEBoot/i18n.h>
#include <VasEBoot/mm.h>
VAS_EBOOT_MOD_LICENSE ("GPLv3+");
static struct VasEBoot_video_patch
{
const char *name;
VasEBoot_uint32_t pci_id;
VasEBoot_uint32_t mmio_bar;
VasEBoot_uint32_t mmio_reg;
VasEBoot_uint32_t mmio_old;
} video_patches[] =
{
{"Intel 945GM", 0x27a28086, 0, 0x71184, 0x1000000}, /* DSPBBASE */
{"Intel 965GM", 0x2a028086, 0, 0x7119C, 0x1000000}, /* DSPBSURF */
{0, 0, 0, 0, 0}
};
static int
scan_card (VasEBoot_pci_device_t dev, VasEBoot_pci_id_t pciid,
void *data __attribute__ ((unused)))
{
VasEBoot_pci_address_t addr;
addr = VasEBoot_pci_make_address (dev, VAS_EBOOT_PCI_REG_CLASS);
if (VasEBoot_pci_read_byte (addr + 3) == 0x3)
{
struct VasEBoot_video_patch *p = video_patches;
while (p->name)
{
if (p->pci_id == pciid)
{
VasEBoot_addr_t base;
VasEBoot_dprintf ("fixvideo", "Found graphic card: %s\n", p->name);
addr += 8 + p->mmio_bar * 4;
base = VasEBoot_pci_read (addr);
if ((! base) || (base & VAS_EBOOT_PCI_ADDR_SPACE_IO) ||
(base & VAS_EBOOT_PCI_ADDR_MEM_PREFETCH))
VasEBoot_dprintf ("fixvideo", "Invalid MMIO bar %d\n", p->mmio_bar);
else
{
base &= VAS_EBOOT_PCI_ADDR_MEM_MASK;
base += p->mmio_reg;
if (*((volatile VasEBoot_uint32_t *) base) != p->mmio_old)
VasEBoot_dprintf ("fixvideo", "Old value doesn't match\n");
else
{
*((volatile VasEBoot_uint32_t *) base) = 0;
if (*((volatile VasEBoot_uint32_t *) base))
VasEBoot_dprintf ("fixvideo", "Setting MMIO fails\n");
}
}
return 1;
}
p++;
}
VasEBoot_dprintf ("fixvideo", "Unknown graphic card: %x\n", pciid);
}
return 0;
}
static VasEBoot_err_t
VasEBoot_cmd_fixvideo (VasEBoot_command_t cmd __attribute__ ((unused)),
int argc __attribute__ ((unused)),
char *argv[] __attribute__ ((unused)))
{
VasEBoot_pci_iterate (scan_card, NULL);
return 0;
}
static VasEBoot_command_t cmd_fixvideo;
VAS_EBOOT_MOD_INIT(fixvideo)
{
cmd_fixvideo = VasEBoot_register_command ("fix_video", VasEBoot_cmd_fixvideo,
0, N_("Fix video problem."));
}
VAS_EBOOT_MOD_FINI(fixvideo)
{
VasEBoot_unregister_command (cmd_fixvideo);
}

View File

@ -0,0 +1,153 @@
/* getenv.c - retrieve EFI variables. */
/*
* VasEBoot -- GRand Unified Bootloader
* Copyright (C) 2009 Free Software Foundation, Inc.
* Copyright (C) 2014 CoreOS, Inc.
*
* VasEBoot 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.
*
* VasEBoot 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 VasEBoot. If not, see <http://www.gnu.org/licenses/>.
*/
#include <VasEBoot/efi/efi.h>
#include <VasEBoot/dl.h>
#include <VasEBoot/env.h>
#include <VasEBoot/err.h>
#include <VasEBoot/extcmd.h>
#include <VasEBoot/i18n.h>
#include <VasEBoot/misc.h>
#include <VasEBoot/mm.h>
VasEBoot_MOD_LICENSE ("GPLv3+");
static const struct VasEBoot_arg_option options_getenv[] = {
{"var-name", 'e', 0,
N_("Environment variable to query"),
N_("VARNAME"), ARG_TYPE_STRING},
{"var-guid", 'g', 0,
N_("GUID of environment variable to query"),
N_("GUID"), ARG_TYPE_STRING},
{"binary", 'b', 0,
N_("Read binary data and represent it as hex"),
0, ARG_TYPE_NONE},
{0, 0, 0, 0, 0, 0}
};
enum options_getenv
{
GETENV_VAR_NAME,
GETENV_VAR_GUID,
GETENV_BINARY,
};
static VasEBoot_err_t
VasEBoot_cmd_getenv (VasEBoot_extcmd_context_t ctxt, int argc, char **args)
{
struct VasEBoot_arg_list *state = ctxt->state;
char *envvar = NULL, *guid = NULL, *bindata = NULL, *data = NULL;
VasEBoot_size_t datasize;
VasEBoot_efi_guid_t efi_var_guid;
VasEBoot_efi_boolean_t binary = state[GETENV_BINARY].set;
unsigned int i;
if (!state[GETENV_VAR_NAME].set || !state[GETENV_VAR_GUID].set)
{
VasEBoot_error (VasEBoot_ERR_INVALID_COMMAND, N_("-e and -g are required"));
goto done;
}
if (argc != 1)
{
VasEBoot_error (VasEBoot_ERR_BAD_ARGUMENT, N_("unexpected arguments"));
goto done;
}
envvar = state[GETENV_VAR_NAME].arg;
guid = state[GETENV_VAR_GUID].arg;
if (VasEBoot_strlen(guid) != 36 ||
guid[8] != '-' ||
guid[13] != '-' ||
guid[18] != '-' ||
guid[23] != '-')
{
VasEBoot_error (VasEBoot_ERR_BAD_ARGUMENT, N_("invalid GUID"));
goto done;
}
/* Forgive me father for I have sinned */
guid[8] = 0;
efi_var_guid.data1 = VasEBoot_strtoul(guid, NULL, 16);
guid[13] = 0;
efi_var_guid.data2 = VasEBoot_strtoul(guid + 9, NULL, 16);
guid[18] = 0;
efi_var_guid.data3 = VasEBoot_strtoul(guid + 14, NULL, 16);
efi_var_guid.data4[7] = VasEBoot_strtoul(guid + 34, NULL, 16);
guid[34] = 0;
efi_var_guid.data4[6] = VasEBoot_strtoul(guid + 32, NULL, 16);
guid[32] = 0;
efi_var_guid.data4[5] = VasEBoot_strtoul(guid + 30, NULL, 16);
guid[30] = 0;
efi_var_guid.data4[4] = VasEBoot_strtoul(guid + 28, NULL, 16);
guid[28] = 0;
efi_var_guid.data4[3] = VasEBoot_strtoul(guid + 26, NULL, 16);
guid[26] = 0;
efi_var_guid.data4[2] = VasEBoot_strtoul(guid + 24, NULL, 16);
guid[23] = 0;
efi_var_guid.data4[1] = VasEBoot_strtoul(guid + 21, NULL, 16);
guid[21] = 0;
efi_var_guid.data4[0] = VasEBoot_strtoul(guid + 19, NULL, 16);
data = VasEBoot_efi_get_variable(envvar, &efi_var_guid, &datasize);
if (!data || !datasize)
{
VasEBoot_error (VasEBoot_ERR_FILE_NOT_FOUND, N_("No such variable"));
goto done;
}
if (binary)
{
bindata = VasEBoot_zalloc(datasize * 2 + 1);
for (i=0; i<datasize; i++)
VasEBoot_snprintf(bindata + i*2, 3, "%02x", data[i] & 0xff);
if (VasEBoot_env_set (args[0], bindata))
goto done;
}
else if (VasEBoot_env_set (args[0], data))
{
goto done;
}
VasEBoot_errno = VasEBoot_ERR_NONE;
done:
VasEBoot_free(bindata);
VasEBoot_free(data);
return VasEBoot_errno;
}
static VasEBoot_extcmd_t cmd_getenv;
VasEBoot_MOD_INIT(getenv)
{
cmd_getenv = VasEBoot_register_extcmd ("getenv", VasEBoot_cmd_getenv, 0,
N_("-e envvar -g guidenv setvar"),
N_("Read a firmware environment variable"),
options_getenv);
}
VasEBoot_MOD_FINI(getenv)
{
VasEBoot_unregister_extcmd (cmd_getenv);
}

View File

@ -0,0 +1,204 @@
/* loadbios.c - command to load a bios dump */
/*
* VAS_EBOOT -- GRand Unified Bootloader
* Copyright (C) 2009 Free Software Foundation, Inc.
*
* VAS_EBOOT 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.
*
* VAS_EBOOT 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 VAS_EBOOT. If not, see <http://www.gnu.org/licenses/>.
*/
#include <VasEBoot/dl.h>
#include <VasEBoot/misc.h>
#include <VasEBoot/file.h>
#include <VasEBoot/efi/efi.h>
#include <VasEBoot/pci.h>
#include <VasEBoot/command.h>
#include <VasEBoot/i18n.h>
VAS_EBOOT_MOD_LICENSE ("GPLv3+");
static VasEBoot_guid_t acpi_guid = VAS_EBOOT_EFI_ACPI_TABLE_GUID;
static VasEBoot_guid_t acpi2_guid = VAS_EBOOT_EFI_ACPI_20_TABLE_GUID;
static VasEBoot_guid_t smbios_guid = VAS_EBOOT_EFI_SMBIOS_TABLE_GUID;
#define EBDA_SEG_ADDR 0x40e
#define LOW_MEM_ADDR 0x413
#define FAKE_EBDA_SEG 0x9fc0
#define BLANK_MEM 0xffffffff
#define VBIOS_ADDR 0xc0000
#define SBIOS_ADDR 0xf0000
static int
enable_rom_area (void)
{
VasEBoot_pci_address_t addr;
VasEBoot_uint32_t *rom_ptr;
VasEBoot_pci_device_t dev = { .bus = 0, .device = 0, .function = 0};
rom_ptr = VasEBoot_absolute_pointer (VBIOS_ADDR);
if (*rom_ptr != BLANK_MEM)
{
VasEBoot_puts_ (N_("ROM image is present."));
return 0;
}
/* FIXME: should be macroified. */
addr = VasEBoot_pci_make_address (dev, 144);
VasEBoot_pci_write_byte (addr++, 0x30);
VasEBoot_pci_write_byte (addr++, 0x33);
VasEBoot_pci_write_byte (addr++, 0x33);
VasEBoot_pci_write_byte (addr++, 0x33);
VasEBoot_pci_write_byte (addr++, 0x33);
VasEBoot_pci_write_byte (addr++, 0x33);
VasEBoot_pci_write_byte (addr++, 0x33);
VasEBoot_pci_write_byte (addr, 0);
*rom_ptr = 0;
if (*rom_ptr != 0)
{
VasEBoot_puts_ (N_("Can\'t enable ROM area."));
return 0;
}
return 1;
}
static void
lock_rom_area (void)
{
VasEBoot_pci_address_t addr;
VasEBoot_pci_device_t dev = { .bus = 0, .device = 0, .function = 0};
/* FIXME: should be macroified. */
addr = VasEBoot_pci_make_address (dev, 144);
VasEBoot_pci_write_byte (addr++, 0x10);
VasEBoot_pci_write_byte (addr++, 0x11);
VasEBoot_pci_write_byte (addr++, 0x11);
VasEBoot_pci_write_byte (addr++, 0x11);
VasEBoot_pci_write_byte (addr, 0x11);
}
static void
fake_bios_data (int use_rom)
{
void *acpi, *smbios;
VasEBoot_uint16_t *ebda_seg_ptr, *low_mem_ptr;
ebda_seg_ptr = VasEBoot_absolute_pointer (EBDA_SEG_ADDR);
low_mem_ptr = VasEBoot_absolute_pointer (LOW_MEM_ADDR);
if ((*ebda_seg_ptr) || (*low_mem_ptr))
return;
acpi = VasEBoot_efi_find_configuration_table (&acpi2_guid);
VasEBoot_dprintf ("efi", "ACPI2: %p\n", acpi);
if (!acpi) {
acpi = VasEBoot_efi_find_configuration_table (&acpi_guid);
VasEBoot_dprintf ("efi", "ACPI: %p\n", acpi);
}
smbios = VasEBoot_efi_find_configuration_table (&smbios_guid);
VasEBoot_dprintf ("efi", "SMBIOS: %p\n", smbios);
*ebda_seg_ptr = FAKE_EBDA_SEG;
*low_mem_ptr = (FAKE_EBDA_SEG >> 6);
/* *((VasEBoot_uint16_t *) (FAKE_EBDA_SEG << 4)) = 640 - *low_mem_ptr; */
*((VasEBoot_uint16_t *) (VasEBoot_absolute_pointer (FAKE_EBDA_SEG << 4))) = 640 - *low_mem_ptr;
if (acpi)
VasEBoot_memcpy ((char *) ((FAKE_EBDA_SEG << 4) + 16), acpi, 1024 - 16);
if ((use_rom) && (smbios))
VasEBoot_memcpy ((char *) SBIOS_ADDR, (char *) smbios + 16, 16);
}
static VasEBoot_err_t
VasEBoot_cmd_fakebios (struct VasEBoot_command *cmd __attribute__ ((unused)),
int argc __attribute__ ((unused)),
char *argv[] __attribute__ ((unused)))
{
if (enable_rom_area ())
{
fake_bios_data (1);
lock_rom_area ();
}
else
fake_bios_data (0);
return 0;
}
static VasEBoot_err_t
VasEBoot_cmd_loadbios (VasEBoot_command_t cmd __attribute__ ((unused)),
int argc, char *argv[])
{
VasEBoot_file_t file;
int size;
if (argc == 0)
return VasEBoot_error (VAS_EBOOT_ERR_BAD_ARGUMENT, N_("filename expected"));
if (argc > 1)
{
file = VasEBoot_file_open (argv[1], VAS_EBOOT_FILE_TYPE_VBE_DUMP);
if (! file)
return VasEBoot_errno;
if (file->size != 4)
VasEBoot_error (VAS_EBOOT_ERR_BAD_ARGUMENT, "invalid int10 dump size");
else
VasEBoot_file_read (file, (void *) 0x40, 4);
VasEBoot_file_close (file);
if (VasEBoot_errno)
return VasEBoot_errno;
}
file = VasEBoot_file_open (argv[0], VAS_EBOOT_FILE_TYPE_VBE_DUMP);
if (! file)
return VasEBoot_errno;
size = file->size;
if ((size < 0x10000) || (size > 0x40000))
VasEBoot_error (VAS_EBOOT_ERR_BAD_ARGUMENT, "invalid bios dump size");
else if (enable_rom_area ())
{
VasEBoot_file_read (file, (void *) VBIOS_ADDR, size);
fake_bios_data (size <= 0x40000);
lock_rom_area ();
}
VasEBoot_file_close (file);
return VasEBoot_errno;
}
static VasEBoot_command_t cmd_fakebios, cmd_loadbios;
VAS_EBOOT_MOD_INIT(loadbios)
{
cmd_fakebios = VasEBoot_register_command_lockdown ("fakebios", VasEBoot_cmd_fakebios,
0, N_("Create BIOS-like structures for"
" backward compatibility with"
" existing OS."));
cmd_loadbios = VasEBoot_register_command_lockdown ("loadbios", VasEBoot_cmd_loadbios,
N_("BIOS_DUMP [INT10_DUMP]"),
N_("Load BIOS dump."));
}
VAS_EBOOT_MOD_FINI(loadbios)
{
VasEBoot_unregister_command (cmd_fakebios);
VasEBoot_unregister_command (cmd_loadbios);
}

View File

@ -0,0 +1,147 @@
/*
* VAS_EBOOT -- GRand Unified Bootloader
* Copyright (C) 2012 Free Software Foundation, Inc.
*
* VAS_EBOOT 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.
*
* VAS_EBOOT 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 VAS_EBOOT. If not, see <http://www.gnu.org/licenses/>.
*/
#include <VasEBoot/types.h>
#include <VasEBoot/mm.h>
#include <VasEBoot/misc.h>
#include <VasEBoot/efi/api.h>
#include <VasEBoot/efi/edid.h>
#include <VasEBoot/efi/pci.h>
#include <VasEBoot/efi/efi.h>
#include <VasEBoot/efi/uga_draw.h>
#include <VasEBoot/efi/graphics_output.h>
#include <VasEBoot/efi/console_control.h>
#include <VasEBoot/command.h>
VAS_EBOOT_MOD_LICENSE ("GPLv3+");
static struct known_protocol
{
VasEBoot_guid_t guid;
const char *name;
} known_protocols[] =
{
{ VAS_EBOOT_EFI_DISK_IO_GUID, "disk" },
{ VAS_EBOOT_EFI_BLOCK_IO_GUID, "block" },
{ VAS_EBOOT_EFI_SERIAL_IO_GUID, "serial" },
{ VAS_EBOOT_EFI_SIMPLE_NETWORK_GUID, "network" },
{ VAS_EBOOT_EFI_PXE_GUID, "pxe" },
{ VAS_EBOOT_EFI_DEVICE_PATH_GUID, "device path" },
{ VAS_EBOOT_EFI_PCI_IO_GUID, "PCI" },
{ VAS_EBOOT_EFI_PCI_ROOT_IO_GUID, "PCI root" },
{ VAS_EBOOT_EFI_EDID_ACTIVE_GUID, "active EDID" },
{ VAS_EBOOT_EFI_EDID_DISCOVERED_GUID, "discovered EDID" },
{ VAS_EBOOT_EFI_EDID_OVERRIDE_GUID, "override EDID" },
{ VAS_EBOOT_EFI_GOP_GUID, "GOP" },
{ VAS_EBOOT_EFI_UGA_DRAW_GUID, "UGA draw" },
{ VAS_EBOOT_EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL_GUID, "simple text output" },
{ VAS_EBOOT_EFI_SIMPLE_TEXT_INPUT_PROTOCOL_GUID, "simple text input" },
{ VAS_EBOOT_EFI_SIMPLE_POINTER_PROTOCOL_GUID, "simple pointer" },
{ VAS_EBOOT_EFI_CONSOLE_CONTROL_GUID, "console control" },
{ VAS_EBOOT_EFI_ABSOLUTE_POINTER_PROTOCOL_GUID, "absolute pointer" },
{ VAS_EBOOT_EFI_DRIVER_BINDING_PROTOCOL_GUID, "EFI driver binding" },
{ VAS_EBOOT_EFI_LOAD_FILE_PROTOCOL_GUID, "load file" },
{ VAS_EBOOT_EFI_LOAD_FILE2_PROTOCOL_GUID, "load file2" },
{ VAS_EBOOT_EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID, "simple FS" },
{ VAS_EBOOT_EFI_TAPE_IO_PROTOCOL_GUID, "tape I/O" },
{ VAS_EBOOT_EFI_UNICODE_COLLATION_PROTOCOL_GUID, "unicode collation" },
{ VAS_EBOOT_EFI_SCSI_IO_PROTOCOL_GUID, "SCSI I/O" },
{ VAS_EBOOT_EFI_USB2_HC_PROTOCOL_GUID, "USB host" },
{ VAS_EBOOT_EFI_DEBUG_SUPPORT_PROTOCOL_GUID, "debug support" },
{ VAS_EBOOT_EFI_DEBUGPORT_PROTOCOL_GUID, "debug port" },
{ VAS_EBOOT_EFI_DECOMPRESS_PROTOCOL_GUID, "decompress" },
{ VAS_EBOOT_EFI_LOADED_IMAGE_PROTOCOL_GUID, "loaded image" },
{ VAS_EBOOT_EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID, "device path to text" },
{ VAS_EBOOT_EFI_DEVICE_PATH_UTILITIES_PROTOCOL_GUID, "device path utilities" },
{ VAS_EBOOT_EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL_GUID, "device path from text" },
{ VAS_EBOOT_EFI_HII_CONFIG_ROUTING_PROTOCOL_GUID, "HII config routing" },
{ VAS_EBOOT_EFI_HII_DATABASE_PROTOCOL_GUID, "HII database" },
{ VAS_EBOOT_EFI_HII_STRING_PROTOCOL_GUID, "HII string" },
{ VAS_EBOOT_EFI_HII_IMAGE_PROTOCOL_GUID, "HII image" },
{ VAS_EBOOT_EFI_HII_FONT_PROTOCOL_GUID, "HII font" },
{ VAS_EBOOT_EFI_COMPONENT_NAME2_PROTOCOL_GUID, "component name 2" },
{ VAS_EBOOT_EFI_HII_CONFIGURATION_ACCESS_PROTOCOL_GUID,
"HII configuration access" },
{ VAS_EBOOT_EFI_USB_IO_PROTOCOL_GUID, "USB I/O" },
};
static VasEBoot_err_t
VasEBoot_cmd_lsefi (VasEBoot_command_t cmd __attribute__ ((unused)),
int argc __attribute__ ((unused)),
char **args __attribute__ ((unused)))
{
VasEBoot_efi_handle_t *handles;
VasEBoot_efi_uintn_t num_handles;
unsigned i, j, k;
handles = VasEBoot_efi_locate_handle (VAS_EBOOT_EFI_ALL_HANDLES,
NULL, NULL, &num_handles);
for (i = 0; i < num_handles; i++)
{
VasEBoot_efi_handle_t handle = handles[i];
VasEBoot_efi_status_t status;
VasEBoot_efi_uintn_t num_protocols;
VasEBoot_packed_guid_t **protocols;
VasEBoot_efi_device_path_t *dp;
VasEBoot_printf ("Handle %p\n", handle);
dp = VasEBoot_efi_get_device_path (handle);
if (dp)
{
VasEBoot_printf (" ");
VasEBoot_efi_print_device_path (dp);
}
status = VasEBoot_efi_system_table->boot_services->protocols_per_handle (handle,
&protocols,
&num_protocols);
if (status != VAS_EBOOT_EFI_SUCCESS) {
VasEBoot_printf ("Unable to retrieve protocols\n");
continue;
}
for (j = 0; j < num_protocols; j++)
{
for (k = 0; k < ARRAY_SIZE (known_protocols); k++)
if (VasEBoot_memcmp (protocols[j], &known_protocols[k].guid,
sizeof (known_protocols[k].guid)) == 0)
break;
if (k < ARRAY_SIZE (known_protocols))
VasEBoot_printf (" %s\n", known_protocols[k].name);
else
VasEBoot_printf (" %pG\n", protocols[j]);
}
}
VasEBoot_free (handles);
return 0;
}
static VasEBoot_command_t cmd;
VAS_EBOOT_MOD_INIT(lsefi)
{
cmd = VasEBoot_register_command ("lsefi", VasEBoot_cmd_lsefi,
NULL, "Display EFI handles.");
}
VAS_EBOOT_MOD_FINI(lsefi)
{
VasEBoot_unregister_command (cmd);
}

View File

@ -0,0 +1,160 @@
/* lsefimemmap.c - Display memory map. */
/*
* VAS_EBOOT -- GRand Unified Bootloader
* Copyright (C) 2008 Free Software Foundation, Inc.
*
* VAS_EBOOT 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.
*
* VAS_EBOOT 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 VAS_EBOOT. If not, see <http://www.gnu.org/licenses/>.
*/
#include <VasEBoot/types.h>
#include <VasEBoot/mm.h>
#include <VasEBoot/misc.h>
#include <VasEBoot/efi/api.h>
#include <VasEBoot/efi/efi.h>
#include <VasEBoot/command.h>
VAS_EBOOT_MOD_LICENSE ("GPLv3+");
#define ADD_MEMORY_DESCRIPTOR(desc, size) \
((VasEBoot_efi_memory_descriptor_t *) ((char *) (desc) + (size)))
static VasEBoot_err_t
VasEBoot_cmd_lsefimmap (VasEBoot_command_t cmd __attribute__ ((unused)),
int argc __attribute__ ((unused)),
char **args __attribute__ ((unused)))
{
VasEBoot_efi_uintn_t map_size;
VasEBoot_efi_memory_descriptor_t *memory_map;
VasEBoot_efi_memory_descriptor_t *memory_map_end;
VasEBoot_efi_memory_descriptor_t *desc;
VasEBoot_efi_uintn_t desc_size;
map_size = 0;
if (VasEBoot_efi_get_memory_map (&map_size, NULL, NULL, &desc_size, 0) < 0)
return 0;
memory_map = VasEBoot_malloc (map_size);
if (memory_map == NULL)
return VasEBoot_errno;
if (VasEBoot_efi_get_memory_map (&map_size, memory_map, NULL, &desc_size, 0) <= 0)
goto fail;
VasEBoot_printf
("Type Physical start - end #Pages "
" Size Attributes\n");
memory_map_end = ADD_MEMORY_DESCRIPTOR (memory_map, map_size);
for (desc = memory_map;
desc < memory_map_end;
desc = ADD_MEMORY_DESCRIPTOR (desc, desc_size))
{
VasEBoot_efi_uint64_t size;
VasEBoot_efi_uint64_t attr;
static const char types_str[][9] =
{
"reserved",
"ldr-code",
"ldr-data",
"BS-code ",
"BS-data ",
"RT-code ",
"RT-data ",
"conv-mem",
"unusable",
"ACPI-rec",
"ACPI-nvs",
"MMIO ",
"IO-ports",
"PAL-code",
"persist ",
};
if (desc->type < ARRAY_SIZE (types_str))
VasEBoot_printf ("%s ", types_str[desc->type]);
else
VasEBoot_printf ("Unk %02x ", desc->type);
VasEBoot_printf (" %016" PRIxVAS_EBOOT_UINT64_T "-%016" PRIxVAS_EBOOT_UINT64_T
" %08" PRIxVAS_EBOOT_UINT64_T,
desc->physical_start,
desc->physical_start + (desc->num_pages << 12) - 1,
desc->num_pages);
size = desc->num_pages << 12; /* 4 KiB page size */
/*
* Since size is a multiple of 4 KiB, no need to handle units
* of just Bytes (which would use a mask of 0x3ff).
*
* 14 characters would support the largest possible number of 4 KiB
* pages that are not a multiple of larger units (e.g., MiB):
* 17592186044415 (0xffffff_fffff000), but that uses a lot of
* whitespace for a rare case. 6 characters usually suffices;
* columns will be off if not, but this is preferable to rounding.
*/
if (size & 0xfffff)
VasEBoot_printf (" %6" PRIuVAS_EBOOT_UINT64_T "KiB", size >> 10);
else if (size & 0x3fffffff)
VasEBoot_printf (" %6" PRIuVAS_EBOOT_UINT64_T "MiB", size >> 20);
else if (size & 0xffffffffff)
VasEBoot_printf (" %6" PRIuVAS_EBOOT_UINT64_T "GiB", size >> 30);
else if (size & 0x3ffffffffffff)
VasEBoot_printf (" %6" PRIuVAS_EBOOT_UINT64_T "TiB", size >> 40);
else if (size & 0xfffffffffffffff)
VasEBoot_printf (" %6" PRIuVAS_EBOOT_UINT64_T "PiB", size >> 50);
else
VasEBoot_printf (" %6" PRIuVAS_EBOOT_UINT64_T "EiB", size >> 60);
attr = desc->attribute;
if (attr & VAS_EBOOT_EFI_MEMORY_RUNTIME)
VasEBoot_printf (" RT");
if (attr & VAS_EBOOT_EFI_MEMORY_UC)
VasEBoot_printf (" UC");
if (attr & VAS_EBOOT_EFI_MEMORY_WC)
VasEBoot_printf (" WC");
if (attr & VAS_EBOOT_EFI_MEMORY_WT)
VasEBoot_printf (" WT");
if (attr & VAS_EBOOT_EFI_MEMORY_WB)
VasEBoot_printf (" WB");
if (attr & VAS_EBOOT_EFI_MEMORY_UCE)
VasEBoot_printf (" UCE");
if (attr & VAS_EBOOT_EFI_MEMORY_WP)
VasEBoot_printf (" WP");
if (attr & VAS_EBOOT_EFI_MEMORY_RP)
VasEBoot_printf (" RP");
if (attr & VAS_EBOOT_EFI_MEMORY_XP)
VasEBoot_printf (" XP");
if (attr & VAS_EBOOT_EFI_MEMORY_NV)
VasEBoot_printf (" NV");
if (attr & VAS_EBOOT_EFI_MEMORY_MORE_RELIABLE)
VasEBoot_printf (" MR");
if (attr & VAS_EBOOT_EFI_MEMORY_RO)
VasEBoot_printf (" RO");
VasEBoot_printf ("\n");
}
fail:
VasEBoot_free (memory_map);
return 0;
}
static VasEBoot_command_t cmd;
VAS_EBOOT_MOD_INIT(lsefimmap)
{
cmd = VasEBoot_register_command ("lsefimmap", VasEBoot_cmd_lsefimmap,
"", "Display EFI memory map.");
}
VAS_EBOOT_MOD_FINI(lsefimmap)
{
VasEBoot_unregister_command (cmd);
}

View File

@ -0,0 +1,131 @@
/* lsefisystab.c - Display EFI systab. */
/*
* VAS_EBOOT -- GRand Unified Bootloader
* Copyright (C) 2008 Free Software Foundation, Inc.
*
* VAS_EBOOT 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.
*
* VAS_EBOOT 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 VAS_EBOOT. If not, see <http://www.gnu.org/licenses/>.
*/
#include <VasEBoot/types.h>
#include <VasEBoot/mm.h>
#include <VasEBoot/dl.h>
#include <VasEBoot/misc.h>
#include <VasEBoot/normal.h>
#include <VasEBoot/charset.h>
#include <VasEBoot/efi/api.h>
#include <VasEBoot/efi/efi.h>
VAS_EBOOT_MOD_LICENSE ("GPLv3+");
struct guid_mapping
{
VasEBoot_guid_t guid;
const char *name;
};
static const struct guid_mapping guid_mappings[] =
{
{ VAS_EBOOT_EFI_ACPI_20_TABLE_GUID, "ACPI-2.0"},
{ VAS_EBOOT_EFI_ACPI_TABLE_GUID, "ACPI-1.0"},
{ VAS_EBOOT_EFI_CONFORMANCE_PROFILES_TABLE_GUID, "CONFORMANCE PROFILES"},
{ VAS_EBOOT_EFI_CRC32_GUIDED_SECTION_EXTRACTION_GUID,
"CRC32 GUIDED SECTION EXTRACTION"},
{ VAS_EBOOT_EFI_DEBUG_IMAGE_INFO_TABLE_GUID, "DEBUG IMAGE INFO"},
{ VAS_EBOOT_EFI_DEVICE_TREE_GUID, "DEVICE TREE"},
{ VAS_EBOOT_EFI_DXE_SERVICES_TABLE_GUID, "DXE SERVICES"},
{ VAS_EBOOT_EFI_HCDP_TABLE_GUID, "HCDP"},
{ VAS_EBOOT_EFI_HOB_LIST_GUID, "HOB LIST"},
{ VAS_EBOOT_EFI_IMAGE_SECURITY_DATABASE_GUID, "IMAGE EXECUTION INFORMATION"},
{ VAS_EBOOT_EFI_LZMA_CUSTOM_DECOMPRESS_GUID, "LZMA CUSTOM DECOMPRESS"},
{ VAS_EBOOT_EFI_MEMORY_ATTRIBUTES_TABLE_GUID, "MEMORY ATTRIBUTES TABLE"},
{ VAS_EBOOT_EFI_MEMORY_TYPE_INFORMATION_GUID, "MEMORY TYPE INFO"},
{ VAS_EBOOT_EFI_MPS_TABLE_GUID, "MPS"},
{ VAS_EBOOT_EFI_RT_PROPERTIES_TABLE_GUID, "RT PROPERTIES"},
{ VAS_EBOOT_EFI_SAL_TABLE_GUID, "SAL"},
{ VAS_EBOOT_EFI_SMBIOS_TABLE_GUID, "SMBIOS"},
{ VAS_EBOOT_EFI_SMBIOS3_TABLE_GUID, "SMBIOS3"},
{ VAS_EBOOT_EFI_SYSTEM_RESOURCE_TABLE_GUID, "SYSTEM RESOURCE TABLE"},
{ VAS_EBOOT_EFI_TCG2_FINAL_EVENTS_TABLE_GUID, "TCG2 FINAL EVENTS TABLE"},
{ VAS_EBOOT_EFI_TIANO_CUSTOM_DECOMPRESS_GUID, "TIANO CUSTOM DECOMPRESS"},
{ VAS_EBOOT_EFI_TSC_FREQUENCY_GUID, "TSC FREQUENCY"},
};
static VasEBoot_err_t
VasEBoot_cmd_lsefisystab (struct VasEBoot_command *cmd __attribute__ ((unused)),
int argc __attribute__ ((unused)),
char **args __attribute__ ((unused)))
{
const VasEBoot_efi_system_table_t *st = VasEBoot_efi_system_table;
const VasEBoot_efi_uint32_t major_rev = st->hdr.revision >> 16;
const VasEBoot_efi_uint32_t minor_rev_upper = (st->hdr.revision & 0xffff) / 10;
const VasEBoot_efi_uint32_t minor_rev_lower = (st->hdr.revision & 0xffff) % 10;
VasEBoot_efi_configuration_table_t *t;
unsigned int i;
VasEBoot_printf ("Address: %p\n", st);
VasEBoot_printf ("Signature: %016" PRIxVAS_EBOOT_UINT64_T " revision: %u.%u",
st->hdr.signature, major_rev, minor_rev_upper);
if (minor_rev_lower)
VasEBoot_printf (".%u", minor_rev_lower);
VasEBoot_printf ("\n");
{
char *vendor;
VasEBoot_uint16_t *vendor_utf16;
VasEBoot_printf ("Vendor: ");
for (vendor_utf16 = st->firmware_vendor; *vendor_utf16; vendor_utf16++);
/* Allocate extra 3 bytes to simplify math. */
vendor = VasEBoot_calloc (4, vendor_utf16 - st->firmware_vendor + 1);
if (!vendor)
return VasEBoot_errno;
*VasEBoot_utf16_to_utf8 ((VasEBoot_uint8_t *) vendor, st->firmware_vendor,
vendor_utf16 - st->firmware_vendor) = 0;
VasEBoot_printf ("%s", vendor);
VasEBoot_free (vendor);
}
VasEBoot_printf (", Version=%x\n", st->firmware_revision);
VasEBoot_printf ("%lld tables:\n", (long long) st->num_table_entries);
t = st->configuration_table;
for (i = 0; i < st->num_table_entries; i++)
{
unsigned int j;
VasEBoot_printf ("%p ", t->vendor_table);
VasEBoot_printf ("%pG", &t->vendor_guid);
for (j = 0; j < ARRAY_SIZE (guid_mappings); j++)
if (VasEBoot_memcmp (&guid_mappings[j].guid, &t->vendor_guid,
sizeof (VasEBoot_guid_t)) == 0)
VasEBoot_printf (" %s", guid_mappings[j].name);
VasEBoot_printf ("\n");
t++;
}
return VAS_EBOOT_ERR_NONE;
}
static VasEBoot_command_t cmd;
VAS_EBOOT_MOD_INIT(lsefisystab)
{
cmd = VasEBoot_register_command ("lsefisystab", VasEBoot_cmd_lsefisystab,
"", "Display EFI system tables.");
}
VAS_EBOOT_MOD_FINI(lsefisystab)
{
VasEBoot_unregister_command (cmd);
}

View File

@ -0,0 +1,163 @@
/* lssal.c - Display EFI SAL systab. */
/*
* VAS_EBOOT -- GRand Unified Bootloader
* Copyright (C) 2008 Free Software Foundation, Inc.
*
* VAS_EBOOT 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.
*
* VAS_EBOOT 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 VAS_EBOOT. If not, see <http://www.gnu.org/licenses/>.
*/
#include <VasEBoot/types.h>
#include <VasEBoot/mm.h>
#include <VasEBoot/misc.h>
#include <VasEBoot/normal.h>
#include <VasEBoot/charset.h>
#include <VasEBoot/efi/api.h>
#include <VasEBoot/efi/efi.h>
#include <VasEBoot/dl.h>
VAS_EBOOT_MOD_LICENSE ("GPLv3+");
static void
disp_sal (void *table)
{
struct VasEBoot_efi_sal_system_table *t = table;
void *desc;
VasEBoot_uint32_t len, l, i;
VasEBoot_printf ("SAL rev: %02x, signature: %x, len:%x\n",
t->sal_rev, t->signature, t->total_table_len);
VasEBoot_printf ("nbr entry: %d, chksum: %02x, SAL version A: %02x B: %02x\n",
t->entry_count, t->checksum,
t->sal_a_version, t->sal_b_version);
VasEBoot_printf ("OEM-ID: %-32s\n", t->oem_id);
VasEBoot_printf ("Product-ID: %-32s\n", t->product_id);
desc = t->entries;
len = t->total_table_len - sizeof (struct VasEBoot_efi_sal_system_table);
if (t->total_table_len <= sizeof (struct VasEBoot_efi_sal_system_table))
return;
for (i = 0; i < t->entry_count; i++)
{
switch (*(VasEBoot_uint8_t *) desc)
{
case VAS_EBOOT_EFI_SAL_SYSTEM_TABLE_TYPE_ENTRYPOINT_DESCRIPTOR:
{
struct VasEBoot_efi_sal_system_table_entrypoint_descriptor *c = desc;
l = sizeof (*c);
VasEBoot_printf (" Entry point: PAL=%016" PRIxVAS_EBOOT_UINT64_T
" SAL=%016" PRIxVAS_EBOOT_UINT64_T " GP=%016"
PRIxVAS_EBOOT_UINT64_T "\n",
c->pal_proc_addr, c->sal_proc_addr,
c->global_data_ptr);
}
break;
case VAS_EBOOT_EFI_SAL_SYSTEM_TABLE_TYPE_MEMORY_DESCRIPTOR:
{
struct VasEBoot_efi_sal_system_table_memory_descriptor *c = desc;
l = sizeof (*c);
VasEBoot_printf (" Memory descriptor entry addr=%016" PRIxVAS_EBOOT_UINT64_T
" len=%" PRIuVAS_EBOOT_UINT64_T "KB\n",
c->addr, c->len * 4);
VasEBoot_printf (" sal_used=%d attr=%x AR=%x attr_mask=%x "
"type=%x usage=%x\n",
c->sal_used, c->attr, c->ar, c->attr_mask, c->mem_type,
c->usage);
}
break;
case VAS_EBOOT_EFI_SAL_SYSTEM_TABLE_TYPE_PLATFORM_FEATURES:
{
struct VasEBoot_efi_sal_system_table_platform_features *c = desc;
l = sizeof (*c);
VasEBoot_printf (" Platform features: %02x", c->flags);
if (c->flags & VAS_EBOOT_EFI_SAL_SYSTEM_TABLE_PLATFORM_FEATURE_BUSLOCK)
VasEBoot_printf (" BusLock");
if (c->flags & VAS_EBOOT_EFI_SAL_SYSTEM_TABLE_PLATFORM_FEATURE_IRQREDIRECT)
VasEBoot_printf (" IrqRedirect");
if (c->flags & VAS_EBOOT_EFI_SAL_SYSTEM_TABLE_PLATFORM_FEATURE_IPIREDIRECT)
VasEBoot_printf (" IPIRedirect");
if (c->flags & VAS_EBOOT_EFI_SAL_SYSTEM_TABLE_PLATFORM_FEATURE_ITCDRIFT)
VasEBoot_printf (" ITCDrift");
VasEBoot_printf ("\n");
}
break;
case VAS_EBOOT_EFI_SAL_SYSTEM_TABLE_TYPE_TRANSLATION_REGISTER_DESCRIPTOR:
{
struct VasEBoot_efi_sal_system_table_translation_register_descriptor *c
= desc;
l = sizeof (*c);
VasEBoot_printf (" TR type=%d num=%d va=%016" PRIxVAS_EBOOT_UINT64_T
" pte=%016" PRIxVAS_EBOOT_UINT64_T "\n",
c->register_type, c->register_number,
c->addr, c->page_size);
}
break;
case VAS_EBOOT_EFI_SAL_SYSTEM_TABLE_TYPE_PURGE_TRANSLATION_COHERENCE:
{
struct VasEBoot_efi_sal_system_table_purge_translation_coherence *c
= desc;
l = sizeof (*c);
VasEBoot_printf (" PTC coherence nbr=%d addr=%016" PRIxVAS_EBOOT_UINT64_T "\n",
c->ndomains, c->coherence);
}
break;
case VAS_EBOOT_EFI_SAL_SYSTEM_TABLE_TYPE_AP_WAKEUP:
{
struct VasEBoot_efi_sal_system_table_ap_wakeup *c = desc;
l = sizeof (*c);
VasEBoot_printf (" AP wake-up: mec=%d vect=%" PRIxVAS_EBOOT_UINT64_T "\n",
c->mechanism, c->vector);
}
break;
default:
VasEBoot_printf (" unknown entry 0x%x\n", *(VasEBoot_uint8_t *)desc);
return;
}
desc = (VasEBoot_uint8_t *)desc + l;
if (len <= l)
return;
len -= l;
}
}
static VasEBoot_err_t
VasEBoot_cmd_lssal (struct VasEBoot_command *cmd __attribute__ ((unused)),
int argc __attribute__ ((unused)),
char **args __attribute__ ((unused)))
{
static VasEBoot_guid_t guid = VAS_EBOOT_EFI_SAL_TABLE_GUID;
void *table = VasEBoot_efi_find_configuration_table (&guid);
if (table == NULL)
{
VasEBoot_printf ("SAL not found\n");
return VAS_EBOOT_ERR_NONE;
}
disp_sal (table);
return VAS_EBOOT_ERR_NONE;
}
static VasEBoot_command_t cmd;
VAS_EBOOT_MOD_INIT(lssal)
{
cmd = VasEBoot_register_command ("lssal", VasEBoot_cmd_lssal, "",
"Display SAL system table.");
}
VAS_EBOOT_MOD_FINI(lssal)
{
VasEBoot_unregister_command (cmd);
}

View File

@ -0,0 +1,37 @@
/* smbios.c - get smbios tables. */
/*
* VAS_EBOOT -- GRand Unified Bootloader
* Copyright (C) 2019 Free Software Foundation, Inc.
*
* VAS_EBOOT 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.
*
* VAS_EBOOT 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 VAS_EBOOT. If not, see <http://www.gnu.org/licenses/>.
*/
#include <VasEBoot/smbios.h>
#include <VasEBoot/efi/efi.h>
struct VasEBoot_smbios_eps *
VasEBoot_machine_smbios_get_eps (void)
{
static VasEBoot_guid_t smbios_guid = VAS_EBOOT_EFI_SMBIOS_TABLE_GUID;
return (struct VasEBoot_smbios_eps *) VasEBoot_efi_find_configuration_table (&smbios_guid);
}
struct VasEBoot_smbios_eps3 *
VasEBoot_machine_smbios_get_eps3 (void)
{
static VasEBoot_guid_t smbios3_guid = VAS_EBOOT_EFI_SMBIOS3_TABLE_GUID;
return (struct VasEBoot_smbios_eps3 *) VasEBoot_efi_find_configuration_table (&smbios3_guid);
}

View File

@ -0,0 +1,383 @@
/*
* VAS_EBOOT -- GRand Unified Bootloader
* Copyright (C) 2018 Free Software Foundation, Inc.
*
* VAS_EBOOT 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.
*
* VAS_EBOOT 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 VAS_EBOOT. If not, see <http://www.gnu.org/licenses/>.
*
* EFI TPM support code.
*/
#include <VasEBoot/err.h>
#include <VasEBoot/i18n.h>
#include <VasEBoot/efi/api.h>
#include <VasEBoot/efi/efi.h>
#include <VasEBoot/efi/cc.h>
#include <VasEBoot/efi/tpm.h>
#include <VasEBoot/mm.h>
#include <VasEBoot/tpm.h>
#include <VasEBoot/term.h>
typedef TCG_PCR_EVENT VasEBoot_tpm_event_t;
static VasEBoot_guid_t tpm_guid = EFI_TPM_GUID;
static VasEBoot_guid_t tpm2_guid = EFI_TPM2_GUID;
static VasEBoot_guid_t cc_measurement_guid = VAS_EBOOT_EFI_CC_MEASUREMENT_PROTOCOL_GUID;
static VasEBoot_efi_handle_t *VasEBoot_tpm_handle;
static VasEBoot_uint8_t VasEBoot_tpm_version;
static VasEBoot_int8_t tpm1_present = -1;
static VasEBoot_int8_t tpm2_present = -1;
static VasEBoot_efi_int64_t tpm2_active_pcr_banks = -1;
static VasEBoot_efi_boolean_t
VasEBoot_tpm1_present (VasEBoot_efi_tpm_protocol_t *tpm)
{
VasEBoot_efi_status_t status;
TCG_EFI_BOOT_SERVICE_CAPABILITY caps;
VasEBoot_uint32_t flags;
VasEBoot_efi_physical_address_t eventlog, lastevent;
if (tpm1_present != -1)
return (VasEBoot_efi_boolean_t) tpm1_present;
caps.Size = (VasEBoot_uint8_t) sizeof (caps);
status = tpm->status_check (tpm, &caps, &flags, &eventlog, &lastevent);
if (status != VAS_EBOOT_EFI_SUCCESS || caps.TPMDeactivatedFlag
|| !caps.TPMPresentFlag)
tpm1_present = 0;
else
tpm1_present = 1;
VasEBoot_dprintf ("tpm", "tpm1%s present\n", tpm1_present ? "" : " NOT");
return (VasEBoot_efi_boolean_t) tpm1_present;
}
static VasEBoot_efi_boolean_t
VasEBoot_tpm2_present (VasEBoot_efi_tpm2_protocol_t *tpm)
{
VasEBoot_efi_status_t status;
EFI_TCG2_BOOT_SERVICE_CAPABILITY caps;
caps.Size = (VasEBoot_uint8_t) sizeof (caps);
if (tpm2_present != -1)
return (VasEBoot_efi_boolean_t) tpm2_present;
status = tpm->get_capability (tpm, &caps);
if (status != VAS_EBOOT_EFI_SUCCESS || !caps.TPMPresentFlag)
tpm2_present = 0;
else
tpm2_present = 1;
VasEBoot_dprintf ("tpm", "tpm2%s present\n", tpm2_present ? "" : " NOT");
return (VasEBoot_efi_boolean_t) tpm2_present;
}
static VasEBoot_efi_boolean_t
VasEBoot_tpm_handle_find (VasEBoot_efi_handle_t *tpm_handle,
VasEBoot_efi_uint8_t *protocol_version)
{
VasEBoot_efi_handle_t *handles;
VasEBoot_efi_uintn_t num_handles;
if (VasEBoot_tpm_handle != NULL)
{
*tpm_handle = VasEBoot_tpm_handle;
*protocol_version = VasEBoot_tpm_version;
return 1;
}
handles = VasEBoot_efi_locate_handle (VAS_EBOOT_EFI_BY_PROTOCOL, &tpm_guid, NULL,
&num_handles);
if (handles && num_handles > 0)
{
VasEBoot_tpm_handle = handles[0];
*tpm_handle = handles[0];
VasEBoot_tpm_version = 1;
*protocol_version = 1;
VasEBoot_dprintf ("tpm", "TPM handle Found, version: 1\n");
VasEBoot_free (handles);
return 1;
}
handles = VasEBoot_efi_locate_handle (VAS_EBOOT_EFI_BY_PROTOCOL, &tpm2_guid, NULL,
&num_handles);
if (handles && num_handles > 0)
{
VasEBoot_tpm_handle = handles[0];
*tpm_handle = handles[0];
VasEBoot_tpm_version = 2;
*protocol_version = 2;
VasEBoot_dprintf ("tpm", "TPM handle Found, version: 2\n");
VasEBoot_free (handles);
return 1;
}
return 0;
}
static VasEBoot_err_t
VasEBoot_efi_log_event_status (VasEBoot_efi_status_t status)
{
switch (status)
{
case VAS_EBOOT_EFI_SUCCESS:
return VAS_EBOOT_ERR_NONE;
case VAS_EBOOT_EFI_DEVICE_ERROR:
return VasEBoot_error (VAS_EBOOT_ERR_IO, N_("command failed"));
case VAS_EBOOT_EFI_INVALID_PARAMETER:
return VasEBoot_error (VAS_EBOOT_ERR_BAD_ARGUMENT, N_("invalid parameter"));
case VAS_EBOOT_EFI_BUFFER_TOO_SMALL:
return VasEBoot_error (VAS_EBOOT_ERR_BAD_ARGUMENT, N_("output buffer too small"));
case VAS_EBOOT_EFI_NOT_FOUND:
return VasEBoot_error (VAS_EBOOT_ERR_UNKNOWN_DEVICE, N_("TPM unavailable"));
default:
return VasEBoot_error (VasEBoot_is_tpm_fail_fatal () ? VAS_EBOOT_ERR_UNKNOWN_DEVICE : VAS_EBOOT_ERR_NONE, N_("unknown TPM error"));
}
}
static VasEBoot_err_t
VasEBoot_tpm1_log_event (VasEBoot_efi_handle_t tpm_handle, unsigned char *buf,
VasEBoot_size_t size, VasEBoot_uint8_t pcr,
const char *description)
{
VasEBoot_tpm_event_t *event;
VasEBoot_efi_status_t status;
VasEBoot_efi_tpm_protocol_t *tpm;
VasEBoot_efi_physical_address_t lastevent;
VasEBoot_uint32_t algorithm;
VasEBoot_uint32_t eventnum = 0;
tpm = VasEBoot_efi_open_protocol (tpm_handle, &tpm_guid,
VAS_EBOOT_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
if (!VasEBoot_tpm1_present (tpm))
return 0;
event = VasEBoot_zalloc (sizeof (*event) + VasEBoot_strlen (description) + 1);
if (!event)
return VasEBoot_error (VAS_EBOOT_ERR_OUT_OF_MEMORY,
N_("cannot allocate TPM event buffer"));
event->PCRIndex = pcr;
event->EventType = EV_IPL;
event->EventSize = VasEBoot_strlen (description) + 1;
VasEBoot_strcpy ((char *) event->Event, description);
algorithm = TCG_ALG_SHA;
status = tpm->log_extend_event (tpm, (VasEBoot_addr_t) buf, (VasEBoot_uint64_t) size,
algorithm, event, &eventnum, &lastevent);
VasEBoot_free (event);
return VasEBoot_efi_log_event_status (status);
}
static VasEBoot_err_t
VasEBoot_tpm2_log_event (VasEBoot_efi_handle_t tpm_handle, unsigned char *buf,
VasEBoot_size_t size, VasEBoot_uint8_t pcr,
const char *description)
{
EFI_TCG2_EVENT *event;
VasEBoot_efi_status_t status;
VasEBoot_efi_tpm2_protocol_t *tpm;
tpm = VasEBoot_efi_open_protocol (tpm_handle, &tpm2_guid,
VAS_EBOOT_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
if (!VasEBoot_tpm2_present (tpm))
return 0;
event =
VasEBoot_zalloc (sizeof (EFI_TCG2_EVENT) + VasEBoot_strlen (description) + 1);
if (!event)
return VasEBoot_error (VAS_EBOOT_ERR_OUT_OF_MEMORY,
N_("cannot allocate TPM event buffer"));
event->Header.HeaderSize = sizeof (EFI_TCG2_EVENT_HEADER);
event->Header.HeaderVersion = 1;
event->Header.PCRIndex = pcr;
event->Header.EventType = EV_IPL;
event->Size =
sizeof (*event) - sizeof (event->Event) + VasEBoot_strlen (description) + 1;
VasEBoot_strcpy ((char *) event->Event, description);
status = tpm->hash_log_extend_event (tpm, 0, (VasEBoot_addr_t) buf,
(VasEBoot_uint64_t) size, event);
VasEBoot_free (event);
return VasEBoot_efi_log_event_status (status);
}
static void
VasEBoot_cc_log_event (unsigned char *buf, VasEBoot_size_t size, VasEBoot_uint8_t pcr,
const char *description)
{
VasEBoot_efi_cc_event_t *event;
VasEBoot_efi_status_t status;
VasEBoot_efi_cc_protocol_t *cc;
VasEBoot_efi_cc_mr_index_t mr;
cc = VasEBoot_efi_locate_protocol (&cc_measurement_guid, NULL);
if (cc == NULL)
return;
status = cc->map_pcr_to_mr_index (cc, pcr, &mr);
if (status != VAS_EBOOT_EFI_SUCCESS)
{
VasEBoot_efi_log_event_status (status);
return;
}
event = VasEBoot_zalloc (sizeof (VasEBoot_efi_cc_event_t) +
VasEBoot_strlen (description) + 1);
if (event == NULL)
{
VasEBoot_error (VAS_EBOOT_ERR_OUT_OF_MEMORY, N_("cannot allocate CC event buffer"));
return;
}
event->Header.HeaderSize = sizeof (VasEBoot_efi_cc_event_header_t);
event->Header.HeaderVersion = VAS_EBOOT_EFI_CC_EVENT_HEADER_VERSION;
event->Header.MrIndex = mr;
event->Header.EventType = EV_IPL;
event->Size = sizeof (*event) + VasEBoot_strlen (description) + 1;
VasEBoot_strcpy ((char *) event->Event, description);
status = cc->hash_log_extend_event (cc, 0,
(VasEBoot_efi_physical_address_t)(VasEBoot_addr_t) buf,
(VasEBoot_efi_uint64_t) size, event);
VasEBoot_free (event);
if (status != VAS_EBOOT_EFI_SUCCESS)
VasEBoot_efi_log_event_status (status);
}
VasEBoot_err_t
VasEBoot_tpm_measure (unsigned char *buf, VasEBoot_size_t size, VasEBoot_uint8_t pcr,
const char *description)
{
VasEBoot_efi_handle_t tpm_handle;
VasEBoot_efi_uint8_t protocol_version;
VasEBoot_cc_log_event(buf, size, pcr, description);
if (!VasEBoot_tpm_handle_find (&tpm_handle, &protocol_version))
return 0;
VasEBoot_dprintf ("tpm", "log_event, pcr = %d, size = 0x%" PRIxVAS_EBOOT_SIZE ", %s\n",
pcr, size, description);
if (protocol_version == 1)
return VasEBoot_tpm1_log_event (tpm_handle, buf, size, pcr, description);
else
return VasEBoot_tpm2_log_event (tpm_handle, buf, size, pcr, description);
}
int
VasEBoot_tpm_present (void)
{
VasEBoot_efi_handle_t tpm_handle;
VasEBoot_efi_uint8_t protocol_version;
VasEBoot_efi_cc_protocol_t *cc;
/*
* When confidential computing measurement protocol is enabled
* we assume the TPM is present.
*/
cc = VasEBoot_efi_locate_protocol (&cc_measurement_guid, NULL);
if (cc != NULL)
return 1;
if (!VasEBoot_tpm_handle_find (&tpm_handle, &protocol_version))
return 0;
if (protocol_version == 1)
{
VasEBoot_efi_tpm_protocol_t *tpm;
tpm = VasEBoot_efi_open_protocol (tpm_handle, &tpm_guid,
VAS_EBOOT_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
if (!tpm)
{
VasEBoot_dprintf ("tpm", "Cannot open TPM protocol\n");
return 0;
}
return VasEBoot_tpm1_present (tpm);
}
else
{
VasEBoot_efi_tpm2_protocol_t *tpm;
tpm = VasEBoot_efi_open_protocol (tpm_handle, &tpm2_guid,
VAS_EBOOT_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
if (!tpm)
{
VasEBoot_dprintf ("tpm", "Cannot open TPM protocol\n");
return 0;
}
return VasEBoot_tpm2_present (tpm);
}
}
VasEBoot_uint32_t
VasEBoot_tpm2_active_pcr_banks (void)
{
EFI_TCG2_BOOT_SERVICE_CAPABILITY caps;
VasEBoot_efi_handle_t tpm_handle;
VasEBoot_efi_uint8_t protocol_version;
VasEBoot_efi_tpm2_protocol_t *tpm;
VasEBoot_efi_uint32_t active_pcr_banks;
VasEBoot_efi_status_t status;
if (tpm2_active_pcr_banks >= 0)
return (VasEBoot_uint32_t) tpm2_active_pcr_banks;
if (!VasEBoot_tpm_handle_find (&tpm_handle, &protocol_version))
return (VasEBoot_uint32_t) (tpm2_active_pcr_banks = 0);
if (protocol_version == 1)
return (VasEBoot_uint32_t) (tpm2_active_pcr_banks = 0); /* We report TPM2 status. */
tpm = VasEBoot_efi_open_protocol (tpm_handle, &tpm2_guid,
VAS_EBOOT_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
if (tpm == NULL)
{
VasEBoot_dprintf ("tpm", "Cannot open TPM2 protocol\n");
return (VasEBoot_uint32_t) (tpm2_active_pcr_banks = 0);
}
if (!VasEBoot_tpm2_present (tpm))
return (VasEBoot_uint32_t) (tpm2_active_pcr_banks = 0);
caps.Size = (VasEBoot_uint8_t) sizeof (caps);
status = tpm->get_capability (tpm, &caps);
if (status != VAS_EBOOT_EFI_SUCCESS)
return (VasEBoot_uint32_t) (tpm2_active_pcr_banks = 0);
if (caps.StructureVersion.Major < 1 ||
(caps.StructureVersion.Major == 1 && caps.StructureVersion.Minor < 1))
/* There's a working TPM2 but without querying protocol, let userspace figure it out. */
return (VasEBoot_uint32_t) (tpm2_active_pcr_banks = VAS_EBOOT_UINT_MAX);
status = tpm->get_active_pcr_banks (tpm, &active_pcr_banks);
if (status != VAS_EBOOT_EFI_SUCCESS)
return (VasEBoot_uint32_t) (tpm2_active_pcr_banks = 0); /* Assume none available if the call fails. */
return (VasEBoot_uint32_t) (tpm2_active_pcr_banks = active_pcr_banks);
}

View File

@ -0,0 +1,71 @@
/*
* VAS_EBOOT -- GRand Unified Bootloader
* Copyright (C) 2009 Free Software Foundation, Inc.
*
* VAS_EBOOT 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.
*
* VAS_EBOOT 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 VAS_EBOOT. If not, see <http://www.gnu.org/licenses/>.
*/
#include <VasEBoot/dl.h>
#include <VasEBoot/misc.h>
#include <VasEBoot/script_sh.h>
#include <VasEBoot/command.h>
#include <VasEBoot/i18n.h>
#include <VasEBoot/term.h>
VAS_EBOOT_MOD_LICENSE ("GPLv3+");
static VasEBoot_err_t
VasEBoot_cmd_eval (VasEBoot_command_t cmd __attribute__((__unused__)),
int argc, char *argv[])
{
int i;
VasEBoot_size_t size = argc; /* +1 for final zero */
char *str, *p;
VasEBoot_err_t ret;
if (argc == 0)
return VAS_EBOOT_ERR_NONE;
for (i = 0; i < argc; i++)
size += VasEBoot_strlen (argv[i]);
str = p = VasEBoot_malloc (size);
if (!str)
return VasEBoot_errno;
for (i = 0; i < argc; i++)
{
p = VasEBoot_stpcpy (p, argv[i]);
*p++ = ' ';
}
*--p = '\0';
ret = VasEBoot_script_execute_sourcecode (str);
VasEBoot_free (str);
return ret;
}
static VasEBoot_command_t cmd;
VAS_EBOOT_MOD_INIT(eval)
{
cmd = VasEBoot_register_command ("eval", VasEBoot_cmd_eval, N_("STRING ..."),
N_("Evaluate arguments as VAS_EBOOT commands"));
}
VAS_EBOOT_MOD_FINI(eval)
{
VasEBoot_unregister_command (cmd);
}

View File

@ -0,0 +1,147 @@
/* extcmd.c - support extended command */
/*
* VAS_EBOOT -- GRand Unified Bootloader
* Copyright (C) 2009 Free Software Foundation, Inc.
*
* VAS_EBOOT 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.
*
* VAS_EBOOT 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 VAS_EBOOT. If not, see <http://www.gnu.org/licenses/>.
*/
#include <VasEBoot/mm.h>
#include <VasEBoot/list.h>
#include <VasEBoot/lockdown.h>
#include <VasEBoot/misc.h>
#include <VasEBoot/extcmd.h>
#include <VasEBoot/script_sh.h>
#include <VasEBoot/dl.h>
VAS_EBOOT_MOD_LICENSE ("GPLv3+");
VasEBoot_err_t
VasEBoot_extcmd_dispatcher (struct VasEBoot_command *cmd, int argc, char **args,
struct VasEBoot_script *script)
{
int new_argc;
char **new_args;
struct VasEBoot_arg_list *state;
struct VasEBoot_extcmd_context context;
VasEBoot_err_t ret;
VasEBoot_extcmd_t ext = cmd->data;
context.state = 0;
context.extcmd = ext;
context.script = script;
if (! ext->options)
{
ret = (ext->func) (&context, argc, args);
return ret;
}
state = VasEBoot_arg_list_alloc (ext, argc, args);
if (state == NULL)
return VasEBoot_errno;
if (VasEBoot_arg_parse (ext, argc, args, state, &new_args, &new_argc))
{
context.state = state;
ret = (ext->func) (&context, new_argc, new_args);
VasEBoot_free (new_args);
VasEBoot_free (state);
return ret;
}
VasEBoot_free (state);
return VasEBoot_errno;
}
static VasEBoot_err_t
VasEBoot_extcmd_dispatch (struct VasEBoot_command *cmd, int argc, char **args)
{
return VasEBoot_extcmd_dispatcher (cmd, argc, args, 0);
}
VasEBoot_extcmd_t
VasEBoot_register_extcmd_prio (const char *name, VasEBoot_extcmd_func_t func,
VasEBoot_command_flags_t flags, const char *summary,
const char *description,
const struct VasEBoot_arg_option *parser,
int prio)
{
VasEBoot_extcmd_t ext;
VasEBoot_command_t cmd;
ext = (VasEBoot_extcmd_t) VasEBoot_malloc (sizeof (*ext));
if (! ext)
return 0;
cmd = VasEBoot_register_command_prio (name, VasEBoot_extcmd_dispatch,
summary, description, prio);
if (! cmd)
{
VasEBoot_free (ext);
return 0;
}
cmd->flags = (flags | VAS_EBOOT_COMMAND_FLAG_EXTCMD);
cmd->data = ext;
ext->cmd = cmd;
ext->func = func;
ext->options = parser;
ext->data = 0;
return ext;
}
VasEBoot_extcmd_t
VasEBoot_register_extcmd (const char *name, VasEBoot_extcmd_func_t func,
VasEBoot_command_flags_t flags, const char *summary,
const char *description,
const struct VasEBoot_arg_option *parser)
{
return VasEBoot_register_extcmd_prio (name, func, flags,
summary, description, parser, 1);
}
static VasEBoot_err_t
VasEBoot_extcmd_lockdown (VasEBoot_extcmd_context_t ctxt __attribute__ ((unused)),
int argc __attribute__ ((unused)),
char **argv __attribute__ ((unused)))
{
return VasEBoot_error (VAS_EBOOT_ERR_ACCESS_DENIED,
N_("%s: the command is not allowed when lockdown is enforced"),
ctxt->extcmd->cmd->name);
}
VasEBoot_extcmd_t
VasEBoot_register_extcmd_lockdown (const char *name, VasEBoot_extcmd_func_t func,
VasEBoot_command_flags_t flags, const char *summary,
const char *description,
const struct VasEBoot_arg_option *parser)
{
if (VasEBoot_is_lockdown () == VAS_EBOOT_LOCKDOWN_ENABLED)
func = VasEBoot_extcmd_lockdown;
return VasEBoot_register_extcmd (name, func, flags, summary, description, parser);
}
void
VasEBoot_unregister_extcmd (VasEBoot_extcmd_t ext)
{
if (ext == NULL)
return;
VasEBoot_unregister_command (ext->cmd);
VasEBoot_free (ext);
}

View File

@ -0,0 +1,707 @@
/*
* VAS_EBOOT -- GRand Unified Bootloader
* Copyright (C) 2013 Free Software Foundation, Inc.
*
* VAS_EBOOT 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.
*
* VAS_EBOOT 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 VAS_EBOOT. If not, see <http://www.gnu.org/licenses/>.
*/
#include <VasEBoot/dl.h>
#include <VasEBoot/misc.h>
#include <VasEBoot/mm.h>
#include <VasEBoot/env.h>
#include <VasEBoot/command.h>
#include <VasEBoot/extcmd.h>
#include <VasEBoot/i18n.h>
#include <VasEBoot/file.h>
#include <VasEBoot/elf.h>
#include <VasEBoot/efi/efi.h>
#include <VasEBoot/xen_file.h>
#include <VasEBoot/efi/pe32.h>
#include <VasEBoot/arm/linux.h>
#include <VasEBoot/i386/linux.h>
#include <VasEBoot/xnu.h>
#include <VasEBoot/machoload.h>
#include <VasEBoot/fileid.h>
VAS_EBOOT_MOD_LICENSE ("GPLv3+");
static const struct VasEBoot_arg_option options[] = {
{"is-i386-xen-pae-domu", 0, 0,
N_("Check if FILE can be booted as i386 PAE Xen unprivileged guest kernel"),
0, 0},
{"is-x86_64-xen-domu", 0, 0,
N_("Check if FILE can be booted as x86_64 Xen unprivileged guest kernel"), 0, 0},
{"is-x86-xen-dom0", 0, 0,
N_("Check if FILE can be used as Xen x86 privileged guest kernel"), 0, 0},
{"is-x86-multiboot", 0, 0,
N_("Check if FILE can be used as x86 multiboot kernel"), 0, 0},
{"is-x86-multiboot2", 0, 0,
N_("Check if FILE can be used as x86 multiboot2 kernel"), 0, 0},
{"is-arm-linux", 0, 0,
N_("Check if FILE is ARM Linux"), 0, 0},
{"is-arm64-linux", 0, 0,
N_("Check if FILE is ARM64 Linux"), 0, 0},
{"is-ia64-linux", 0, 0,
N_("Check if FILE is IA64 Linux"), 0, 0},
{"is-mips-linux", 0, 0,
N_("Check if FILE is MIPS Linux"), 0, 0},
{"is-mipsel-linux", 0, 0,
N_("Check if FILE is MIPSEL Linux"), 0, 0},
{"is-sparc64-linux", 0, 0,
N_("Check if FILE is SPARC64 Linux"), 0, 0},
{"is-powerpc-linux", 0, 0,
N_("Check if FILE is POWERPC Linux"), 0, 0},
{"is-x86-linux", 0, 0,
N_("Check if FILE is x86 Linux"), 0, 0},
{"is-x86-linux32", 0, 0,
N_("Check if FILE is x86 Linux supporting 32-bit protocol"), 0, 0},
{"is-x86-kfreebsd", 0, 0,
N_("Check if FILE is x86 kFreeBSD"), 0, 0},
{"is-i386-kfreebsd", 0, 0,
N_("Check if FILE is i386 kFreeBSD"), 0, 0},
{"is-x86_64-kfreebsd", 0, 0,
N_("Check if FILE is x86_64 kFreeBSD"), 0, 0},
{"is-x86-knetbsd", 0, 0,
N_("Check if FILE is x86 kNetBSD"), 0, 0},
{"is-i386-knetbsd", 0, 0,
N_("Check if FILE is i386 kNetBSD"), 0, 0},
{"is-x86_64-knetbsd", 0, 0,
N_("Check if FILE is x86_64 kNetBSD"), 0, 0},
{"is-i386-efi", 0, 0,
N_("Check if FILE is i386 EFI file"), 0, 0},
{"is-x86_64-efi", 0, 0,
N_("Check if FILE is x86_64 EFI file"), 0, 0},
{"is-ia64-efi", 0, 0,
N_("Check if FILE is IA64 EFI file"), 0, 0},
{"is-arm64-efi", 0, 0,
N_("Check if FILE is ARM64 EFI file"), 0, 0},
{"is-arm-efi", 0, 0,
N_("Check if FILE is ARM EFI file"), 0, 0},
{"is-riscv32-efi", 0, 0,
N_("Check if FILE is RISC-V 32bit EFI file"), 0, 0},
{"is-riscv64-efi", 0, 0,
N_("Check if FILE is RISC-V 64bit EFI file"), 0, 0},
{"is-hibernated-hiberfil", 0, 0,
N_("Check if FILE is hiberfil.sys in hibernated state"), 0, 0},
{"is-x86_64-xnu", 0, 0,
N_("Check if FILE is x86_64 XNU (Mac OS X kernel)"), 0, 0},
{"is-i386-xnu", 0, 0,
N_("Check if FILE is i386 XNU (Mac OS X kernel)"), 0, 0},
{"is-xnu-hibr", 0, 0,
N_("Check if FILE is XNU (Mac OS X kernel) hibernated image"), 0, 0},
{"is-x86-bios-bootsector", 0, 0,
N_("Check if FILE is BIOS bootsector"), 0, 0},
{0, 0, 0, 0, 0, 0}
};
enum
{
IS_PAE_DOMU,
IS_64_DOMU,
IS_DOM0,
IS_MULTIBOOT,
IS_MULTIBOOT2,
IS_ARM_LINUX,
IS_ARM64_LINUX,
IS_IA64_LINUX,
IS_MIPS_LINUX,
IS_MIPSEL_LINUX,
IS_SPARC64_LINUX,
IS_POWERPC_LINUX,
IS_X86_LINUX,
IS_X86_LINUX32,
IS_X86_KFREEBSD,
IS_X86_KFREEBSD32,
IS_X86_KFREEBSD64,
IS_X86_KNETBSD,
IS_X86_KNETBSD32,
IS_X86_KNETBSD64,
IS_32_EFI,
IS_64_EFI,
IS_IA_EFI,
IS_ARM64_EFI,
IS_ARM_EFI,
IS_RISCV32_EFI,
IS_RISCV64_EFI,
IS_HIBERNATED,
IS_XNU64,
IS_XNU32,
IS_XNU_HIBR,
IS_BIOS_BOOTSECTOR,
OPT_TYPE_MIN = IS_PAE_DOMU,
OPT_TYPE_MAX = IS_BIOS_BOOTSECTOR
};
static VasEBoot_err_t
VasEBoot_cmd_file (VasEBoot_extcmd_context_t ctxt, int argc, char **args)
{
VasEBoot_file_t file = 0;
VasEBoot_elf_t elf = 0;
VasEBoot_err_t err;
int type = -1, i;
int ret = 0;
VasEBoot_macho_t macho = 0;
if (argc == 0)
return VasEBoot_error (VAS_EBOOT_ERR_BAD_ARGUMENT, N_("filename expected"));
for (i = OPT_TYPE_MIN; i <= OPT_TYPE_MAX; i++)
if (ctxt->state[i].set)
{
if (type == -1)
{
type = i;
continue;
}
return VasEBoot_error (VAS_EBOOT_ERR_BAD_ARGUMENT, "multiple types specified");
}
if (type == -1)
return VasEBoot_error (VAS_EBOOT_ERR_BAD_ARGUMENT, "no type specified");
file = VasEBoot_file_open (args[0], VAS_EBOOT_FILE_TYPE_XNU_KERNEL);
if (!file)
return VasEBoot_errno;
switch (type)
{
case IS_BIOS_BOOTSECTOR:
{
VasEBoot_uint16_t sig;
if (VasEBoot_file_size (file) != 512)
break;
if (VasEBoot_file_seek (file, 510) == (VasEBoot_size_t) -1)
break;
if (VasEBoot_file_read (file, &sig, 2) != 2)
break;
if (sig != VasEBoot_cpu_to_le16_compile_time (0xaa55))
break;
ret = 1;
break;
}
case IS_IA64_LINUX:
{
Elf64_Ehdr ehdr;
if (VasEBoot_file_read (file, &ehdr, sizeof (ehdr)) != sizeof (ehdr))
break;
if (ehdr.e_ident[EI_MAG0] != ELFMAG0
|| ehdr.e_ident[EI_MAG1] != ELFMAG1
|| ehdr.e_ident[EI_MAG2] != ELFMAG2
|| ehdr.e_ident[EI_MAG3] != ELFMAG3
|| ehdr.e_ident[EI_VERSION] != EV_CURRENT
|| ehdr.e_version != EV_CURRENT)
break;
if (ehdr.e_ident[EI_CLASS] != ELFCLASS64
|| ehdr.e_ident[EI_DATA] != ELFDATA2LSB
|| ehdr.e_machine != VasEBoot_cpu_to_le16_compile_time (EM_IA_64))
break;
ret = 1;
break;
}
case IS_SPARC64_LINUX:
{
Elf64_Ehdr ehdr;
if (VasEBoot_file_read (file, &ehdr, sizeof (ehdr)) != sizeof (ehdr))
break;
if (ehdr.e_ident[EI_MAG0] != ELFMAG0
|| ehdr.e_ident[EI_MAG1] != ELFMAG1
|| ehdr.e_ident[EI_MAG2] != ELFMAG2
|| ehdr.e_ident[EI_MAG3] != ELFMAG3
|| ehdr.e_ident[EI_VERSION] != EV_CURRENT
|| ehdr.e_version != EV_CURRENT)
break;
if (ehdr.e_ident[EI_CLASS] != ELFCLASS64
|| ehdr.e_ident[EI_DATA] != ELFDATA2MSB)
break;
if (ehdr.e_machine != VasEBoot_cpu_to_le16_compile_time (EM_SPARCV9)
|| ehdr.e_type != VasEBoot_cpu_to_be16_compile_time (ET_EXEC))
break;
ret = 1;
break;
}
case IS_POWERPC_LINUX:
{
Elf32_Ehdr ehdr;
if (VasEBoot_file_read (file, &ehdr, sizeof (ehdr)) != sizeof (ehdr))
break;
if (ehdr.e_ident[EI_MAG0] != ELFMAG0
|| ehdr.e_ident[EI_MAG1] != ELFMAG1
|| ehdr.e_ident[EI_MAG2] != ELFMAG2
|| ehdr.e_ident[EI_MAG3] != ELFMAG3
|| ehdr.e_ident[EI_VERSION] != EV_CURRENT
|| ehdr.e_version != EV_CURRENT)
break;
if (ehdr.e_ident[EI_DATA] != ELFDATA2MSB
|| (ehdr.e_machine != VasEBoot_cpu_to_le16_compile_time (EM_PPC)
&& ehdr.e_machine !=
VasEBoot_cpu_to_le16_compile_time (EM_PPC64)))
break;
if (ehdr.e_type != VasEBoot_cpu_to_be16_compile_time (ET_EXEC)
&& ehdr.e_type != VasEBoot_cpu_to_be16_compile_time (ET_DYN))
break;
ret = 1;
break;
}
case IS_MIPS_LINUX:
{
Elf32_Ehdr ehdr;
if (VasEBoot_file_read (file, &ehdr, sizeof (ehdr)) != sizeof (ehdr))
break;
if (ehdr.e_ident[EI_MAG0] != ELFMAG0
|| ehdr.e_ident[EI_MAG1] != ELFMAG1
|| ehdr.e_ident[EI_MAG2] != ELFMAG2
|| ehdr.e_ident[EI_MAG3] != ELFMAG3
|| ehdr.e_ident[EI_VERSION] != EV_CURRENT
|| ehdr.e_version != EV_CURRENT)
break;
if (ehdr.e_ident[EI_DATA] != ELFDATA2MSB
|| ehdr.e_machine != VasEBoot_cpu_to_be16_compile_time (EM_MIPS)
|| ehdr.e_type != VasEBoot_cpu_to_be16_compile_time (ET_EXEC))
break;
ret = 1;
break;
}
case IS_X86_KNETBSD:
case IS_X86_KNETBSD32:
case IS_X86_KNETBSD64:
{
int is32, is64;
elf = VasEBoot_elf_file (file, file->name);
if (elf == NULL)
break;
if (elf->ehdr.ehdr32.e_type != VasEBoot_cpu_to_le16_compile_time (ET_EXEC)
|| elf->ehdr.ehdr32.e_ident[EI_DATA] != ELFDATA2LSB)
break;
is32 = VasEBoot_elf_is_elf32 (elf);
is64 = VasEBoot_elf_is_elf64 (elf);
if (!is32 && !is64)
break;
if (!is32 && type == IS_X86_KNETBSD32)
break;
if (!is64 && type == IS_X86_KNETBSD64)
break;
if (is64)
ret = VasEBoot_file_check_netbsd64 (elf);
if (is32)
ret = VasEBoot_file_check_netbsd32 (elf);
break;
}
case IS_X86_KFREEBSD:
case IS_X86_KFREEBSD32:
case IS_X86_KFREEBSD64:
{
Elf32_Ehdr ehdr;
int is32, is64;
if (VasEBoot_file_read (file, &ehdr, sizeof (ehdr)) != sizeof (ehdr))
break;
if (ehdr.e_ident[EI_MAG0] != ELFMAG0
|| ehdr.e_ident[EI_MAG1] != ELFMAG1
|| ehdr.e_ident[EI_MAG2] != ELFMAG2
|| ehdr.e_ident[EI_MAG3] != ELFMAG3
|| ehdr.e_ident[EI_VERSION] != EV_CURRENT
|| ehdr.e_version != EV_CURRENT)
break;
if (ehdr.e_type != VasEBoot_cpu_to_le16_compile_time (ET_EXEC)
|| ehdr.e_ident[EI_DATA] != ELFDATA2LSB)
break;
if (ehdr.e_ident[EI_OSABI] != ELFOSABI_FREEBSD)
break;
is32 = (ehdr.e_machine == VasEBoot_cpu_to_le16_compile_time (EM_386)
&& ehdr.e_ident[EI_CLASS] == ELFCLASS32);
is64 = (ehdr.e_machine == VasEBoot_cpu_to_le16_compile_time (EM_X86_64)
&& ehdr.e_ident[EI_CLASS] == ELFCLASS64);
if (!is32 && !is64)
break;
if (!is32 && (type == IS_X86_KFREEBSD32 || type == IS_X86_KNETBSD32))
break;
if (!is64 && (type == IS_X86_KFREEBSD64 || type == IS_X86_KNETBSD64))
break;
ret = 1;
break;
}
case IS_MIPSEL_LINUX:
{
Elf32_Ehdr ehdr;
if (VasEBoot_file_read (file, &ehdr, sizeof (ehdr)) != sizeof (ehdr))
break;
if (ehdr.e_ident[EI_MAG0] != ELFMAG0
|| ehdr.e_ident[EI_MAG1] != ELFMAG1
|| ehdr.e_ident[EI_MAG2] != ELFMAG2
|| ehdr.e_ident[EI_MAG3] != ELFMAG3
|| ehdr.e_ident[EI_VERSION] != EV_CURRENT
|| ehdr.e_version != EV_CURRENT)
break;
if (ehdr.e_machine != VasEBoot_cpu_to_le16_compile_time (EM_MIPS)
|| ehdr.e_type != VasEBoot_cpu_to_le16_compile_time (ET_EXEC))
break;
ret = 1;
break;
}
case IS_ARM_LINUX:
{
struct linux_arch_kernel_header lh;
if (VasEBoot_file_read (file, &lh, sizeof (lh)) != sizeof (lh))
break;
/* Short forward branch in A32 state (for Raspberry pi kernels). */
if (lh.code0 == VasEBoot_cpu_to_le32_compile_time (0xea000006))
{
ret = 1;
break;
}
if (lh.magic ==
VasEBoot_cpu_to_le32_compile_time (VAS_EBOOT_LINUX_ARM_MAGIC_SIGNATURE))
{
ret = 1;
break;
}
break;
}
case IS_ARM64_LINUX:
{
struct linux_arch_kernel_header lh;
if (VasEBoot_file_read (file, &lh, sizeof (lh)) != sizeof (lh))
break;
/*
* The PE/COFF header can be anywhere in the file. Load it from the correct
* offset if it is not where it is expected.
*/
if ((VasEBoot_uint8_t *) &lh + lh.hdr_offset != (VasEBoot_uint8_t *) &lh.pe_image_header)
{
if (VasEBoot_file_seek (file, lh.hdr_offset) == (VasEBoot_off_t) -1
|| VasEBoot_file_read (file, &lh.pe_image_header, sizeof (struct VasEBoot_pe_image_header))
!= sizeof (struct VasEBoot_pe_image_header))
return VasEBoot_error (VAS_EBOOT_ERR_FILE_READ_ERROR, "failed to read COFF image header");
}
if (lh.pe_image_header.coff_header.machine == VasEBoot_cpu_to_le16_compile_time (VAS_EBOOT_PE32_MACHINE_ARM64))
{
ret = 1;
break;
}
break;
}
case IS_PAE_DOMU ... IS_DOM0:
{
struct VasEBoot_xen_file_info xen_inf;
elf = VasEBoot_xen_file (file);
if (!elf)
break;
err = VasEBoot_xen_get_info (elf, &xen_inf);
if (err)
break;
/* Unfortuntely no way to check if kernel supports dom0. */
if (type == IS_DOM0)
ret = 1;
if (type == IS_PAE_DOMU)
ret = (xen_inf.arch == VAS_EBOOT_XEN_FILE_I386_PAE
|| xen_inf.arch == VAS_EBOOT_XEN_FILE_I386_PAE_BIMODE);
if (type == IS_64_DOMU)
ret = (xen_inf.arch == VAS_EBOOT_XEN_FILE_X86_64);
break;
}
case IS_MULTIBOOT:
case IS_MULTIBOOT2:
{
VasEBoot_uint32_t *buffer;
VasEBoot_ssize_t len;
VasEBoot_size_t search_size;
VasEBoot_uint32_t *header;
VasEBoot_uint32_t magic;
VasEBoot_size_t step;
if (type == IS_MULTIBOOT2)
{
search_size = 32768;
magic = VasEBoot_cpu_to_le32_compile_time (0xe85250d6);
step = 2;
}
else
{
search_size = 8192;
magic = VasEBoot_cpu_to_le32_compile_time (0x1BADB002);
step = 1;
}
buffer = VasEBoot_malloc (search_size);
if (!buffer)
break;
len = VasEBoot_file_read (file, buffer, search_size);
if (len < 32)
{
VasEBoot_free (buffer);
break;
}
/* Look for the multiboot header in the buffer. The header should
be at least 12 bytes and aligned on a 4-byte boundary. */
for (header = buffer;
((char *) header <=
(char *) buffer + len - (type == IS_MULTIBOOT2 ? 16 : 12));
header += step)
{
if (header[0] == magic
&& !(VasEBoot_le_to_cpu32 (header[0])
+ VasEBoot_le_to_cpu32 (header[1])
+ VasEBoot_le_to_cpu32 (header[2])
+ (type == IS_MULTIBOOT2
? VasEBoot_le_to_cpu32 (header[3]) : 0)))
{
ret = 1;
break;
}
}
VasEBoot_free (buffer);
break;
}
case IS_X86_LINUX32:
case IS_X86_LINUX:
{
struct linux_i386_kernel_header lh;
if (VasEBoot_file_read (file, &lh, sizeof (lh)) != sizeof (lh))
break;
if (lh.boot_flag != VasEBoot_cpu_to_le16_compile_time (0xaa55))
break;
if (lh.setup_sects > VAS_EBOOT_LINUX_MAX_SETUP_SECTS)
break;
/* FIXME: some really old kernels (< 1.3.73) will fail this. */
if (lh.header !=
VasEBoot_cpu_to_le32_compile_time (VAS_EBOOT_LINUX_I386_MAGIC_SIGNATURE)
|| VasEBoot_le_to_cpu16 (lh.version) < 0x0200)
break;
if (type == IS_X86_LINUX)
{
ret = 1;
break;
}
/* FIXME: 2.03 is not always good enough (Linux 2.4 can be 2.03 and
still not support 32-bit boot. */
if (lh.header !=
VasEBoot_cpu_to_le32_compile_time (VAS_EBOOT_LINUX_I386_MAGIC_SIGNATURE)
|| VasEBoot_le_to_cpu16 (lh.version) < 0x0203)
break;
if (!(lh.loadflags & VAS_EBOOT_LINUX_FLAG_BIG_KERNEL))
break;
ret = 1;
break;
}
case IS_HIBERNATED:
{
VasEBoot_uint8_t hibr_file_magic[4];
if (VasEBoot_file_read (file, &hibr_file_magic, sizeof (hibr_file_magic))
!= sizeof (hibr_file_magic))
break;
if (VasEBoot_memcmp ("hibr", hibr_file_magic, sizeof (hibr_file_magic)) ==
0
|| VasEBoot_memcmp ("HIBR", hibr_file_magic,
sizeof (hibr_file_magic)) == 0)
ret = 1;
break;
}
case IS_XNU64:
case IS_XNU32:
{
macho = VasEBoot_macho_open (args[0], VAS_EBOOT_FILE_TYPE_XNU_KERNEL,
(type == IS_XNU64));
if (!macho)
break;
/* FIXME: more checks? */
ret = 1;
break;
}
case IS_XNU_HIBR:
{
struct VasEBoot_xnu_hibernate_header hibhead;
if (VasEBoot_file_read (file, &hibhead, sizeof (hibhead))
!= sizeof (hibhead))
break;
if (hibhead.magic !=
VasEBoot_cpu_to_le32_compile_time (VAS_EBOOT_XNU_HIBERNATE_MAGIC))
break;
ret = 1;
break;
}
case IS_32_EFI:
case IS_64_EFI:
case IS_IA_EFI:
case IS_ARM64_EFI:
case IS_ARM_EFI:
case IS_RISCV32_EFI:
case IS_RISCV64_EFI:
{
char signature[4];
VasEBoot_uint32_t pe_offset;
struct VasEBoot_pe32_coff_header coff_head;
if (VasEBoot_file_read (file, signature, 2) != 2)
break;
if (signature[0] != 'M' || signature[1] != 'Z')
break;
if ((VasEBoot_ssize_t) VasEBoot_file_seek (file, 0x3c) == -1)
break;
if (VasEBoot_file_read (file, &pe_offset, 4) != 4)
break;
if ((VasEBoot_ssize_t) VasEBoot_file_seek (file, VasEBoot_le_to_cpu32 (pe_offset))
== -1)
break;
if (VasEBoot_file_read (file, signature, 4) != 4)
break;
if (signature[0] != 'P' || signature[1] != 'E'
|| signature[2] != '\0' || signature[3] != '\0')
break;
if (VasEBoot_file_read (file, &coff_head, sizeof (coff_head))
!= sizeof (coff_head))
break;
if (type == IS_32_EFI
&& coff_head.machine !=
VasEBoot_cpu_to_le16_compile_time (VAS_EBOOT_PE32_MACHINE_I386))
break;
if (type == IS_64_EFI
&& coff_head.machine !=
VasEBoot_cpu_to_le16_compile_time (VAS_EBOOT_PE32_MACHINE_X86_64))
break;
if (type == IS_IA_EFI
&& coff_head.machine !=
VasEBoot_cpu_to_le16_compile_time (VAS_EBOOT_PE32_MACHINE_IA64))
break;
if (type == IS_ARM64_EFI
&& coff_head.machine !=
VasEBoot_cpu_to_le16_compile_time (VAS_EBOOT_PE32_MACHINE_ARM64))
break;
if (type == IS_ARM_EFI
&& coff_head.machine !=
VasEBoot_cpu_to_le16_compile_time (VAS_EBOOT_PE32_MACHINE_ARMTHUMB_MIXED))
break;
if ((type == IS_RISCV32_EFI || type == IS_RISCV64_EFI)
&& coff_head.machine !=
VasEBoot_cpu_to_le16_compile_time (VAS_EBOOT_PE32_MACHINE_RISCV64))
/* TODO: Determine bitness dynamically */
break;
if (type == IS_IA_EFI || type == IS_64_EFI || type == IS_ARM64_EFI ||
type == IS_RISCV32_EFI || type == IS_RISCV64_EFI)
{
struct VasEBoot_pe64_optional_header o64;
if (VasEBoot_file_read (file, &o64, sizeof (o64)) != sizeof (o64))
break;
if (o64.magic !=
VasEBoot_cpu_to_le16_compile_time (VAS_EBOOT_PE32_PE64_MAGIC))
break;
if (o64.subsystem !=
VasEBoot_cpu_to_le16_compile_time
(VAS_EBOOT_PE32_SUBSYSTEM_EFI_APPLICATION))
break;
ret = 1;
break;
}
if (type == IS_32_EFI || type == IS_ARM_EFI)
{
struct VasEBoot_pe32_optional_header o32;
if (VasEBoot_file_read (file, &o32, sizeof (o32)) != sizeof (o32))
break;
if (o32.magic !=
VasEBoot_cpu_to_le16_compile_time (VAS_EBOOT_PE32_PE32_MAGIC))
break;
if (o32.subsystem !=
VasEBoot_cpu_to_le16_compile_time
(VAS_EBOOT_PE32_SUBSYSTEM_EFI_APPLICATION))
break;
ret = 1;
break;
}
break;
}
}
if (elf)
VasEBoot_elf_close (elf);
else if (macho)
VasEBoot_macho_close (macho);
else if (file)
VasEBoot_file_close (file);
if (!ret && (VasEBoot_errno == VAS_EBOOT_ERR_BAD_OS || VasEBoot_errno == VAS_EBOOT_ERR_NONE))
/* TRANSLATORS: it's a standalone boolean value,
opposite of "true". */
VasEBoot_error (VAS_EBOOT_ERR_TEST_FAILURE, N_("false"));
return VasEBoot_errno;
}
static VasEBoot_extcmd_t cmd;
VAS_EBOOT_MOD_INIT(file)
{
cmd = VasEBoot_register_extcmd ("file", VasEBoot_cmd_file, 0,
N_("OPTIONS FILE"),
N_("Check if FILE is of specified type."),
options);
}
VAS_EBOOT_MOD_FINI(file)
{
VasEBoot_unregister_extcmd (cmd);
}

View File

@ -0,0 +1,5 @@
#define VAS_EBOOT_TARGET_WORDSIZE 32
#define XX 32
#define ehdrXX ehdr32
#define VasEBoot_file_check_netbsdXX VasEBoot_file_check_netbsd32
#include "fileXX.c"

View File

@ -0,0 +1,5 @@
#define VAS_EBOOT_TARGET_WORDSIZE 64
#define XX 64
#define ehdrXX ehdr64
#define VasEBoot_file_check_netbsdXX VasEBoot_file_check_netbsd64
#include "fileXX.c"

View File

@ -0,0 +1,74 @@
/*
* VAS_EBOOT -- GRand Unified Bootloader
* Copyright (C) 2013 Free Software Foundation, Inc.
*
* VAS_EBOOT 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.
*
* VAS_EBOOT 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 VAS_EBOOT. If not, see <http://www.gnu.org/licenses/>.
*/
#include <VasEBoot/fileid.h>
#include <VasEBoot/elfload.h>
#include <VasEBoot/misc.h>
#pragma GCC diagnostic ignored "-Wcast-align"
int
VasEBoot_file_check_netbsdXX (VasEBoot_elf_t elf)
{
Elf_Shdr *s, *s0;
VasEBoot_size_t shnum = elf->ehdr.ehdrXX.e_shnum;
VasEBoot_size_t shentsize = elf->ehdr.ehdrXX.e_shentsize;
VasEBoot_size_t shsize = shnum * shentsize;
VasEBoot_off_t stroff;
if (!shnum || !shentsize)
return 0;
s0 = VasEBoot_malloc (shsize);
if (!s0)
return 0;
if (VasEBoot_file_seek (elf->file, elf->ehdr.ehdrXX.e_shoff) == (VasEBoot_off_t) -1)
goto fail;
if (VasEBoot_file_read (elf->file, s0, shsize) != (VasEBoot_ssize_t) shsize)
goto fail;
s = (Elf_Shdr *) ((char *) s0 + elf->ehdr.ehdrXX.e_shstrndx * shentsize);
stroff = s->sh_offset;
for (s = s0; s < (Elf_Shdr *) ((char *) s0 + shnum * shentsize);
s = (Elf_Shdr *) ((char *) s + shentsize))
{
char name[sizeof(".note.netbsd.ident")];
VasEBoot_memset (name, 0, sizeof (name));
if (VasEBoot_file_seek (elf->file, stroff + s->sh_name) == (VasEBoot_off_t) -1)
goto fail;
if (VasEBoot_file_read (elf->file, name, sizeof (name)) != (VasEBoot_ssize_t) sizeof (name))
{
if (VasEBoot_errno)
goto fail;
continue;
}
if (VasEBoot_memcmp (name, ".note.netbsd.ident",
sizeof(".note.netbsd.ident")) != 0)
continue;
VasEBoot_free (s0);
return 1;
}
fail:
VasEBoot_free (s0);
return 0;
}

View File

@ -0,0 +1,122 @@
/* fwconfig.c - command to read config from qemu fwconfig */
/*
* VasEBoot -- GRand Unified Bootloader
* Copyright (C) 2015 CoreOS, Inc.
*
* VasEBoot 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.
*
* VasEBoot 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 VasEBoot. If not, see <http://www.gnu.org/licenses/>.
*/
#include <VasEBoot/dl.h>
#include <VasEBoot/misc.h>
#include <VasEBoot/extcmd.h>
#include <VasEBoot/env.h>
#include <VasEBoot/cpu/io.h>
#include <VasEBoot/i18n.h>
#include <VasEBoot/mm.h>
VasEBoot_MOD_LICENSE ("GPLv3+");
#define SELECTOR 0x510
#define DATA 0x511
#define SIGNATURE_INDEX 0x00
#define DIRECTORY_INDEX 0x19
static VasEBoot_extcmd_t cmd_read_fwconfig;
struct VasEBoot_qemu_fwcfgfile {
VasEBoot_uint32_t size;
VasEBoot_uint16_t select;
VasEBoot_uint16_t reserved;
char name[56];
};
static const struct VasEBoot_arg_option options[] =
{
{0, 'v', 0, N_("Save read value into variable VARNAME."),
N_("VARNAME"), ARG_TYPE_STRING},
{0, 0, 0, 0, 0, 0}
};
static VasEBoot_err_t
VasEBoot_cmd_fwconfig (VasEBoot_extcmd_context_t ctxt __attribute__ ((unused)),
int argc, char **argv)
{
VasEBoot_uint32_t i, j, value = 0;
struct VasEBoot_qemu_fwcfgfile file;
char fwsig[4], signature[4] = { 'Q', 'E', 'M', 'U' };
if (argc != 2)
return VasEBoot_error (VasEBoot_ERR_BAD_ARGUMENT, N_("two arguments expected"));
/* Verify that we have meaningful hardware here */
VasEBoot_outw(SIGNATURE_INDEX, SELECTOR);
for (i=0; i<sizeof(fwsig); i++)
fwsig[i] = VasEBoot_inb(DATA);
if (VasEBoot_memcmp(fwsig, signature, sizeof(signature)) != 0)
return VasEBoot_error (VasEBoot_ERR_BAD_DEVICE, N_("invalid fwconfig hardware signature: got 0x%x%x%x%x"), fwsig[0], fwsig[1], fwsig[2], fwsig[3]);
/* Find out how many file entries we have */
VasEBoot_outw(DIRECTORY_INDEX, SELECTOR);
value = VasEBoot_inb(DATA) | VasEBoot_inb(DATA) << 8 | VasEBoot_inb(DATA) << 16 | VasEBoot_inb(DATA) << 24;
value = VasEBoot_be_to_cpu32(value);
/* Read the file description for each file */
for (i=0; i<value; i++)
{
for (j=0; j<sizeof(file); j++)
{
((char *)&file)[j] = VasEBoot_inb(DATA);
}
/* Check whether it matches what we're looking for, and if so read the file */
if (VasEBoot_strncmp(file.name, argv[0], sizeof(file.name)) == 0)
{
VasEBoot_uint32_t filesize = VasEBoot_be_to_cpu32(file.size);
VasEBoot_uint16_t location = VasEBoot_be_to_cpu16(file.select);
char *data = VasEBoot_malloc(filesize+1);
if (!data)
return VasEBoot_error (VasEBoot_ERR_OUT_OF_MEMORY, N_("can't allocate buffer for data"));
VasEBoot_outw(location, SELECTOR);
for (j=0; j<filesize; j++)
{
data[j] = VasEBoot_inb(DATA);
}
data[filesize] = '\0';
VasEBoot_env_set (argv[1], data);
VasEBoot_free(data);
return 0;
}
}
return VasEBoot_error (VasEBoot_ERR_FILE_NOT_FOUND, N_("couldn't find entry %s"), argv[0]);
}
VasEBoot_MOD_INIT(fwconfig)
{
cmd_read_fwconfig =
VasEBoot_register_extcmd ("fwconfig", VasEBoot_cmd_fwconfig, 0,
N_("PATH VAR"),
N_("Set VAR to the contents of fwconfig PATH"),
options);
}
VasEBoot_MOD_FINI(fwconfig)
{
VasEBoot_unregister_extcmd (cmd_read_fwconfig);
}

View File

@ -0,0 +1,223 @@
/* gptprio.c - manage priority based partition selection. */
/*
* VasEBoot -- GRand Unified Bootloader
* Copyright (C) 2009 Free Software Foundation, Inc.
* Copyright (C) 2014 CoreOS, Inc.
*
* VasEBoot 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.
*
* VasEBoot 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 VasEBoot. If not, see <http://www.gnu.org/licenses/>.
*/
#include <VasEBoot/device.h>
#include <VasEBoot/env.h>
#include <VasEBoot/err.h>
#include <VasEBoot/extcmd.h>
#include <VasEBoot/gpt_partition.h>
#include <VasEBoot/i18n.h>
#include <VasEBoot/misc.h>
VasEBoot_MOD_LICENSE ("GPLv3+");
static const struct VasEBoot_arg_option options_next[] = {
{"set-device", 'd', 0,
N_("Set a variable to the name of selected partition."),
N_("VARNAME"), ARG_TYPE_STRING},
{"set-uuid", 'u', 0,
N_("Set a variable to the GPT UUID of selected partition."),
N_("VARNAME"), ARG_TYPE_STRING},
{0, 0, 0, 0, 0, 0}
};
enum options_next
{
NEXT_SET_DEVICE,
NEXT_SET_UUID,
};
static unsigned int
VasEBoot_gptprio_priority (struct VasEBoot_gpt_partentry *entry)
{
return (unsigned int) VasEBoot_gpt_entry_attribute
(entry, VasEBoot_GPT_PART_ATTR_OFFSET_GPTPRIO_PRIORITY, 4);
}
static unsigned int
VasEBoot_gptprio_tries_left (struct VasEBoot_gpt_partentry *entry)
{
return (unsigned int) VasEBoot_gpt_entry_attribute
(entry, VasEBoot_GPT_PART_ATTR_OFFSET_GPTPRIO_TRIES_LEFT, 4);
}
static void
VasEBoot_gptprio_set_tries_left (struct VasEBoot_gpt_partentry *entry,
unsigned int tries_left)
{
VasEBoot_gpt_entry_set_attribute
(entry, tries_left, VasEBoot_GPT_PART_ATTR_OFFSET_GPTPRIO_TRIES_LEFT, 4);
}
static unsigned int
VasEBoot_gptprio_successful (struct VasEBoot_gpt_partentry *entry)
{
return (unsigned int) VasEBoot_gpt_entry_attribute
(entry, VasEBoot_GPT_PART_ATTR_OFFSET_GPTPRIO_SUCCESSFUL, 1);
}
static VasEBoot_err_t
VasEBoot_find_next (const char *disk_name,
const VasEBoot_gpt_part_type_t *part_type,
char **part_name, char **part_guid)
{
struct VasEBoot_gpt_partentry *part, *part_found = NULL;
VasEBoot_device_t dev = NULL;
VasEBoot_gpt_t gpt = NULL;
VasEBoot_uint32_t i, part_index;
dev = VasEBoot_device_open (disk_name);
if (!dev)
goto done;
gpt = VasEBoot_gpt_read (dev->disk);
if (!gpt)
goto done;
if (VasEBoot_gpt_repair (dev->disk, gpt))
goto done;
for (i = 0; (part = VasEBoot_gpt_get_partentry (gpt, i)) != NULL; i++)
{
if (VasEBoot_memcmp (part_type, &part->type, sizeof (*part_type)) == 0)
{
unsigned int priority, tries_left, successful, old_priority = 0;
priority = VasEBoot_gptprio_priority (part);
tries_left = VasEBoot_gptprio_tries_left (part);
successful = VasEBoot_gptprio_successful (part);
if (part_found)
old_priority = VasEBoot_gptprio_priority (part_found);
if ((tries_left || successful) && priority > old_priority)
{
part_index = i;
part_found = part;
}
}
}
if (!part_found)
{
VasEBoot_error (VasEBoot_ERR_UNKNOWN_DEVICE, N_("no such partition"));
goto done;
}
if (VasEBoot_gptprio_tries_left (part_found))
{
unsigned int tries_left = VasEBoot_gptprio_tries_left (part_found);
VasEBoot_gptprio_set_tries_left (part_found, tries_left - 1);
if (VasEBoot_gpt_update (gpt))
goto done;
if (VasEBoot_gpt_write (dev->disk, gpt))
goto done;
}
*part_name = VasEBoot_xasprintf ("%s,gpt%u", disk_name, part_index + 1);
if (!*part_name)
goto done;
*part_guid = VasEBoot_gpt_guid_to_str (&part_found->guid);
if (!*part_guid)
goto done;
VasEBoot_errno = VasEBoot_ERR_NONE;
done:
VasEBoot_gpt_free (gpt);
if (dev)
VasEBoot_device_close (dev);
return VasEBoot_errno;
}
static VasEBoot_err_t
VasEBoot_cmd_next (VasEBoot_extcmd_context_t ctxt, int argc, char **args)
{
struct VasEBoot_arg_list *state = ctxt->state;
char *p, *root = NULL, *part_name = NULL, *part_guid = NULL;
/* TODO: Add a uuid parser and a command line flag for providing type. */
VasEBoot_gpt_part_type_t part_type = VasEBoot_GPT_PARTITION_TYPE_USR_X86_64;
if (!state[NEXT_SET_DEVICE].set || !state[NEXT_SET_UUID].set)
{
VasEBoot_error (VasEBoot_ERR_INVALID_COMMAND, N_("-d and -u are required"));
goto done;
}
if (argc == 0)
root = VasEBoot_strdup (VasEBoot_env_get ("root"));
else if (argc == 1)
root = VasEBoot_strdup (args[0]);
else
{
VasEBoot_error (VasEBoot_ERR_BAD_ARGUMENT, N_("unexpected arguments"));
goto done;
}
if (!root)
goto done;
/* To make using $root practical strip off the partition name. */
p = VasEBoot_strchr (root, ',');
if (p)
*p = '\0';
if (VasEBoot_find_next (root, &part_type, &part_name, &part_guid))
goto done;
if (VasEBoot_env_set (state[NEXT_SET_DEVICE].arg, part_name))
goto done;
if (VasEBoot_env_set (state[NEXT_SET_UUID].arg, part_guid))
goto done;
VasEBoot_errno = VasEBoot_ERR_NONE;
done:
VasEBoot_free (root);
VasEBoot_free (part_name);
VasEBoot_free (part_guid);
return VasEBoot_errno;
}
static VasEBoot_extcmd_t cmd_next;
VasEBoot_MOD_INIT(gptprio)
{
cmd_next = VasEBoot_register_extcmd ("gptprio.next", VasEBoot_cmd_next, 0,
N_("-d VARNAME -u VARNAME [DEVICE]"),
N_("Select next partition to boot."),
options_next);
}
VasEBoot_MOD_FINI(gptprio)
{
VasEBoot_unregister_extcmd (cmd_next);
}

View File

@ -0,0 +1,110 @@
/* gptrepair.c - verify and restore GPT info from alternate location. */
/*
* VasEBoot -- GRand Unified Bootloader
* Copyright (C) 2009 Free Software Foundation, Inc.
* Copyright (C) 2014 CoreOS, Inc.
*
* VasEBoot 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.
*
* VasEBoot 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 VasEBoot. If not, see <http://www.gnu.org/licenses/>.
*/
#include <VasEBoot/command.h>
#include <VasEBoot/device.h>
#include <VasEBoot/err.h>
#include <VasEBoot/gpt_partition.h>
#include <VasEBoot/i18n.h>
#include <VasEBoot/misc.h>
VasEBoot_MOD_LICENSE ("GPLv3+");
static char *
trim_dev_name (char *name)
{
VasEBoot_size_t len = VasEBoot_strlen (name);
if (len && name[0] == '(' && name[len - 1] == ')')
{
name[len - 1] = '\0';
name = name + 1;
}
return name;
}
static VasEBoot_err_t
VasEBoot_cmd_gptrepair (VasEBoot_command_t cmd __attribute__ ((unused)),
int argc, char **args)
{
VasEBoot_device_t dev = NULL;
VasEBoot_gpt_t gpt = NULL;
char *dev_name;
if (argc != 1 || !VasEBoot_strlen(args[0]))
return VasEBoot_error (VasEBoot_ERR_BAD_ARGUMENT, "device name required");
dev_name = trim_dev_name (args[0]);
dev = VasEBoot_device_open (dev_name);
if (!dev)
goto done;
if (!dev->disk)
{
VasEBoot_error (VasEBoot_ERR_BAD_ARGUMENT, "not a disk");
goto done;
}
gpt = VasEBoot_gpt_read (dev->disk);
if (!gpt)
goto done;
if (VasEBoot_gpt_both_valid (gpt))
{
VasEBoot_printf_ (N_("GPT already valid, %s unmodified.\n"), dev_name);
goto done;
}
if (!VasEBoot_gpt_primary_valid (gpt))
VasEBoot_printf_ (N_("Found invalid primary GPT on %s\n"), dev_name);
if (!VasEBoot_gpt_backup_valid (gpt))
VasEBoot_printf_ (N_("Found invalid backup GPT on %s\n"), dev_name);
if (VasEBoot_gpt_repair (dev->disk, gpt))
goto done;
if (VasEBoot_gpt_write (dev->disk, gpt))
goto done;
VasEBoot_printf_ (N_("Repaired GPT on %s\n"), dev_name);
done:
if (gpt)
VasEBoot_gpt_free (gpt);
if (dev)
VasEBoot_device_close (dev);
return VasEBoot_errno;
}
static VasEBoot_command_t cmd;
VasEBoot_MOD_INIT(gptrepair)
{
cmd = VasEBoot_register_command ("gptrepair", VasEBoot_cmd_gptrepair,
N_("DEVICE"),
N_("Verify and repair GPT on drive DEVICE."));
}
VasEBoot_MOD_FINI(gptrepair)
{
VasEBoot_unregister_command (cmd);
}

View File

@ -0,0 +1,266 @@
/* gptsync.c - fill the mbr based on gpt entries */
/* XXX: I don't know what to do if sector size isn't 512 bytes */
/*
* VAS_EBOOT -- GRand Unified Bootloader
* Copyright (C) 2009 Free Software Foundation, Inc.
*
* VAS_EBOOT 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.
*
* VAS_EBOOT 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 VAS_EBOOT. If not, see <http://www.gnu.org/licenses/>.
*/
#include <VasEBoot/command.h>
#include <VasEBoot/dl.h>
#include <VasEBoot/device.h>
#include <VasEBoot/disk.h>
#include <VasEBoot/msdos_partition.h>
#include <VasEBoot/partition.h>
#include <VasEBoot/misc.h>
#include <VasEBoot/mm.h>
#include <VasEBoot/fs.h>
#include <VasEBoot/i18n.h>
VAS_EBOOT_MOD_LICENSE ("GPLv3+");
/* Convert a LBA address to a CHS address in the INT 13 format. */
/* Taken from VasEBoot1. */
/* XXX: use hardcoded geometry of C = 1024, H = 255, S = 63.
Is it a problem?
*/
static void
lba_to_chs (VasEBoot_uint32_t lba, VasEBoot_uint8_t *cl, VasEBoot_uint8_t *ch,
VasEBoot_uint8_t *dh)
{
VasEBoot_uint32_t cylinder, head, sector;
VasEBoot_uint32_t sectors = 63, heads = 255, cylinders = 1024;
sector = lba % sectors + 1;
head = (lba / sectors) % heads;
cylinder = lba / (sectors * heads);
if (cylinder >= cylinders)
{
*cl = *ch = *dh = 0xff;
return;
}
*cl = sector | ((cylinder & 0x300) >> 2);
*ch = cylinder & 0xFF;
*dh = head;
}
static VasEBoot_err_t
VasEBoot_cmd_gptsync (VasEBoot_command_t cmd __attribute__ ((unused)),
int argc, char **args)
{
VasEBoot_device_t dev;
struct VasEBoot_msdos_partition_mbr mbr;
struct VasEBoot_partition *partition;
VasEBoot_disk_addr_t first_sector;
int numactive = 0;
int i;
if (argc < 1)
return VasEBoot_error (VAS_EBOOT_ERR_BAD_ARGUMENT, "device name required");
if (argc > 4)
return VasEBoot_error (VAS_EBOOT_ERR_BAD_ARGUMENT, "only 3 partitions can be "
"in hybrid MBR");
if (args[0][0] == '(' && args[0][VasEBoot_strlen (args[0]) - 1] == ')')
{
args[0][VasEBoot_strlen (args[0]) - 1] = 0;
dev = VasEBoot_device_open (args[0] + 1);
args[0][VasEBoot_strlen (args[0])] = ')';
}
else
dev = VasEBoot_device_open (args[0]);
if (! dev)
return VasEBoot_errno;
if (! dev->disk)
{
VasEBoot_device_close (dev);
return VasEBoot_error (VAS_EBOOT_ERR_BAD_ARGUMENT, "not a disk");
}
/* Read the protective MBR. */
if (VasEBoot_disk_read (dev->disk, 0, 0, sizeof (mbr), &mbr))
{
VasEBoot_device_close (dev);
return VasEBoot_errno;
}
/* Check if it is valid. */
if (mbr.signature != VasEBoot_cpu_to_le16_compile_time (VAS_EBOOT_PC_PARTITION_SIGNATURE))
{
VasEBoot_device_close (dev);
return VasEBoot_error (VAS_EBOOT_ERR_BAD_PART_TABLE, "no signature");
}
/* Make sure the MBR is a protective MBR and not a normal MBR. */
for (i = 0; i < 4; i++)
if (mbr.entries[i].type == VAS_EBOOT_PC_PARTITION_TYPE_GPT_DISK)
break;
if (i == 4)
{
VasEBoot_device_close (dev);
return VasEBoot_error (VAS_EBOOT_ERR_BAD_PART_TABLE, "no GPT partition map found");
}
first_sector = dev->disk->total_sectors;
for (i = 1; i < argc; i++)
{
char *separator, csep = 0;
VasEBoot_uint8_t type;
separator = VasEBoot_strchr (args[i], '+');
if (! separator)
separator = VasEBoot_strchr (args[i], '-');
if (separator)
{
csep = *separator;
*separator = 0;
}
partition = VasEBoot_partition_probe (dev->disk, args[i]);
if (separator)
*separator = csep;
if (! partition)
{
VasEBoot_device_close (dev);
return VasEBoot_error (VAS_EBOOT_ERR_UNKNOWN_DEVICE,
N_("no such partition"));
}
if (partition->start + partition->len > 0xffffffff)
{
VasEBoot_device_close (dev);
return VasEBoot_error (VAS_EBOOT_ERR_OUT_OF_RANGE,
"only partitions residing in the first 2TB "
"can be present in hybrid MBR");
}
if (first_sector > partition->start)
first_sector = partition->start;
if (separator && *(separator + 1))
type = VasEBoot_strtoul (separator + 1, 0, 0);
else
{
VasEBoot_fs_t fs = 0;
dev->disk->partition = partition;
fs = VasEBoot_fs_probe (dev);
/* Unknown filesystem isn't fatal. */
if (VasEBoot_errno == VAS_EBOOT_ERR_UNKNOWN_FS)
{
fs = 0;
VasEBoot_errno = VAS_EBOOT_ERR_NONE;
}
if (fs && VasEBoot_strcmp (fs->name, "ntfs") == 0)
type = VAS_EBOOT_PC_PARTITION_TYPE_NTFS;
else if (fs && VasEBoot_strcmp (fs->name, "fat") == 0)
/* FIXME: detect FAT16. */
type = VAS_EBOOT_PC_PARTITION_TYPE_FAT32_LBA;
else if (fs && (VasEBoot_strcmp (fs->name, "hfsplus") == 0
|| VasEBoot_strcmp (fs->name, "hfs") == 0))
type = VAS_EBOOT_PC_PARTITION_TYPE_HFS;
else
/* FIXME: detect more types. */
type = VAS_EBOOT_PC_PARTITION_TYPE_EXT2FS;
dev->disk->partition = 0;
}
mbr.entries[i].flag = (csep == '+') ? 0x80 : 0;
if (csep == '+')
{
numactive++;
if (numactive == 2)
{
VasEBoot_device_close (dev);
return VasEBoot_error (VAS_EBOOT_ERR_BAD_ARGUMENT,
"only one partition can be active");
}
}
mbr.entries[i].type = type;
mbr.entries[i].start = VasEBoot_cpu_to_le32 (partition->start);
lba_to_chs (partition->start,
&(mbr.entries[i].start_sector),
&(mbr.entries[i].start_cylinder),
&(mbr.entries[i].start_head));
lba_to_chs (partition->start + partition->len - 1,
&(mbr.entries[i].end_sector),
&(mbr.entries[i].end_cylinder),
&(mbr.entries[i].end_head));
mbr.entries[i].length = VasEBoot_cpu_to_le32 (partition->len);
VasEBoot_free (partition);
}
for (; i < 4; i++)
VasEBoot_memset (&(mbr.entries[i]), 0, sizeof (mbr.entries[i]));
/* The protective partition. */
if (first_sector > 0xffffffff)
first_sector = 0xffffffff;
else
first_sector--;
mbr.entries[0].flag = 0;
mbr.entries[0].type = VAS_EBOOT_PC_PARTITION_TYPE_GPT_DISK;
mbr.entries[0].start = VasEBoot_cpu_to_le32_compile_time (1);
lba_to_chs (1,
&(mbr.entries[0].start_sector),
&(mbr.entries[0].start_cylinder),
&(mbr.entries[0].start_head));
lba_to_chs (first_sector,
&(mbr.entries[0].end_sector),
&(mbr.entries[0].end_cylinder),
&(mbr.entries[0].end_head));
mbr.entries[0].length = VasEBoot_cpu_to_le32 (first_sector);
mbr.signature = VasEBoot_cpu_to_le16_compile_time (VAS_EBOOT_PC_PARTITION_SIGNATURE);
if (VasEBoot_disk_write (dev->disk, 0, 0, sizeof (mbr), &mbr))
{
VasEBoot_device_close (dev);
return VasEBoot_errno;
}
VasEBoot_device_close (dev);
VasEBoot_printf_ (N_("New MBR is written to `%s'\n"), args[0]);
return VAS_EBOOT_ERR_NONE;
}
static VasEBoot_command_t cmd;
VAS_EBOOT_MOD_INIT(gptsync)
{
(void) mod; /* To stop warning. */
cmd = VasEBoot_register_command ("gptsync", VasEBoot_cmd_gptsync,
N_("DEVICE [PARTITION[+/-[TYPE]]] ..."),
/* TRANSLATORS: MBR type is one-byte partition
type id. */
N_("Fill hybrid MBR of GPT drive DEVICE. "
"Specified partitions will be a part "
"of hybrid MBR. Up to 3 partitions are "
"allowed. TYPE is an MBR type. "
"+ means that partition is active. "
"Only one partition can be active."));
}
VAS_EBOOT_MOD_FINI(gptsync)
{
VasEBoot_unregister_command (cmd);
}

View File

@ -0,0 +1,47 @@
/* halt.c - command to halt the computer. */
/*
* VAS_EBOOT -- GRand Unified Bootloader
* Copyright (C) 2005,2007,2008 Free Software Foundation, Inc.
*
* VAS_EBOOT 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.
*
* VAS_EBOOT 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 VAS_EBOOT. If not, see <http://www.gnu.org/licenses/>.
*/
#include <VasEBoot/dl.h>
#include <VasEBoot/command.h>
#include <VasEBoot/misc.h>
#include <VasEBoot/i18n.h>
VAS_EBOOT_MOD_LICENSE ("GPLv3+");
static VasEBoot_err_t __attribute__ ((noreturn))
VasEBoot_cmd_halt (VasEBoot_command_t cmd __attribute__ ((unused)),
int argc __attribute__ ((unused)),
char **args __attribute__ ((unused)))
{
VasEBoot_halt ();
}
static VasEBoot_command_t cmd;
VAS_EBOOT_MOD_INIT(halt)
{
cmd = VasEBoot_register_command ("halt", VasEBoot_cmd_halt,
0, N_("Halts the computer. This command does"
" not work on all firmware implementations."));
}
VAS_EBOOT_MOD_FINI(halt)
{
VasEBoot_unregister_command (cmd);
}

View File

@ -0,0 +1,334 @@
/*
* VAS_EBOOT -- GRand Unified Bootloader
* Copyright (C) 2009 Free Software Foundation, Inc.
*
* VAS_EBOOT 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.
*
* VAS_EBOOT 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 VAS_EBOOT. If not, see <http://www.gnu.org/licenses/>.
*/
#include <VasEBoot/dl.h>
#include <VasEBoot/extcmd.h>
#include <VasEBoot/file.h>
#include <VasEBoot/disk.h>
#include <VasEBoot/mm.h>
#include <VasEBoot/misc.h>
#include <VasEBoot/crypto.h>
#include <VasEBoot/normal.h>
#include <VasEBoot/i18n.h>
VAS_EBOOT_MOD_LICENSE ("GPLv3+");
static const struct VasEBoot_arg_option options[] = {
{"hash", 'h', 0, N_("Specify hash to use."), N_("HASH"), ARG_TYPE_STRING},
{"check", 'c', 0, N_("Check hashes of files with hash list FILE."),
N_("FILE"), ARG_TYPE_STRING},
{"prefix", 'p', 0, N_("Base directory for hash list."), N_("DIR"),
ARG_TYPE_STRING},
{"keep-going", 'k', 0, N_("Don't stop after first error."), 0, 0},
{"uncompress", 'u', 0, N_("Uncompress file before checksumming."), 0, 0},
{0, 0, 0, 0, 0, 0}
};
static struct { const char *name; const char *hashname; } aliases[] =
{
{"sha256sum", "sha256"},
{"sha512sum", "sha512"},
{"sha1sum", "sha1"},
{"md5sum", "md5"},
{"crc", "crc32"},
};
static inline int
hextoval (char c)
{
if (c >= '0' && c <= '9')
return c - '0';
if (c >= 'a' && c <= 'f')
return c - 'a' + 10;
if (c >= 'A' && c <= 'F')
return c - 'A' + 10;
return -1;
}
static VasEBoot_err_t
hash_file (VasEBoot_file_t file, const gcry_md_spec_t *hash, void *result)
{
void *context;
VasEBoot_uint8_t *readbuf;
#define BUF_SIZE 4096
readbuf = VasEBoot_malloc (BUF_SIZE);
if (!readbuf)
return VasEBoot_errno;
context = VasEBoot_zalloc (hash->contextsize);
if (!readbuf || !context)
goto fail;
hash->init (context, 0);
while (1)
{
VasEBoot_ssize_t r;
r = VasEBoot_file_read (file, readbuf, BUF_SIZE);
if (r < 0)
goto fail;
if (r == 0)
break;
hash->write (context, readbuf, r);
}
hash->final (context);
VasEBoot_memcpy (result, hash->read (context), hash->mdlen);
VasEBoot_free (readbuf);
VasEBoot_free (context);
return VAS_EBOOT_ERR_NONE;
fail:
VasEBoot_free (readbuf);
VasEBoot_free (context);
return VasEBoot_errno;
}
static VasEBoot_err_t
check_list (const gcry_md_spec_t *hash, const char *hashfilename,
const char *prefix, int keep, int uncompress)
{
VasEBoot_file_t hashlist, file;
char *buf = NULL;
VasEBoot_uint8_t expected[VAS_EBOOT_CRYPTO_MAX_MDLEN];
VasEBoot_uint8_t actual[VAS_EBOOT_CRYPTO_MAX_MDLEN];
VasEBoot_err_t err;
unsigned i;
unsigned unread = 0, mismatch = 0;
if (hash->mdlen > VAS_EBOOT_CRYPTO_MAX_MDLEN)
return VasEBoot_error (VAS_EBOOT_ERR_BUG, "mdlen is too long");
hashlist = VasEBoot_file_open (hashfilename, VAS_EBOOT_FILE_TYPE_HASHLIST);
if (!hashlist)
return VasEBoot_errno;
while (VasEBoot_free (buf), (buf = VasEBoot_file_getline (hashlist)))
{
const char *p = buf;
while (VasEBoot_isspace (p[0]))
p++;
for (i = 0; i < hash->mdlen; i++)
{
int high, low;
high = hextoval (*p++);
low = hextoval (*p++);
if (high < 0 || low < 0)
{
VasEBoot_free (buf);
return VasEBoot_error (VAS_EBOOT_ERR_BAD_FILE_TYPE, "invalid hash list");
}
expected[i] = (high << 4) | low;
}
if ((p[0] != ' ' && p[0] != '\t') || (p[1] != ' ' && p[1] != '\t'))
{
VasEBoot_free (buf);
return VasEBoot_error (VAS_EBOOT_ERR_BAD_FILE_TYPE, "invalid hash list");
}
p += 2;
if (prefix)
{
char *filename;
filename = VasEBoot_xasprintf ("%s/%s", prefix, p);
if (!filename)
{
VasEBoot_free (buf);
return VasEBoot_errno;
}
file = VasEBoot_file_open (filename, VAS_EBOOT_FILE_TYPE_TO_HASH
| (!uncompress ? VAS_EBOOT_FILE_TYPE_NO_DECOMPRESS
: VAS_EBOOT_FILE_TYPE_NONE));
VasEBoot_free (filename);
}
else
file = VasEBoot_file_open (p, VAS_EBOOT_FILE_TYPE_TO_HASH
| (!uncompress ? VAS_EBOOT_FILE_TYPE_NO_DECOMPRESS
: VAS_EBOOT_FILE_TYPE_NONE));
if (!file)
{
VasEBoot_file_close (hashlist);
VasEBoot_free (buf);
return VasEBoot_errno;
}
err = hash_file (file, hash, actual);
VasEBoot_file_close (file);
if (err)
{
VasEBoot_printf_ (N_("%s: READ ERROR\n"), p);
if (!keep)
{
VasEBoot_file_close (hashlist);
VasEBoot_free (buf);
return err;
}
VasEBoot_print_error ();
VasEBoot_errno = VAS_EBOOT_ERR_NONE;
unread++;
continue;
}
if (VasEBoot_crypto_memcmp (expected, actual, hash->mdlen) != 0)
{
VasEBoot_printf_ (N_("%s: HASH MISMATCH\n"), p);
if (!keep)
{
VasEBoot_file_close (hashlist);
VasEBoot_free (buf);
return VasEBoot_error (VAS_EBOOT_ERR_TEST_FAILURE,
"hash of '%s' mismatches", p);
}
mismatch++;
continue;
}
VasEBoot_printf_ (N_("%s: OK\n"), p);
}
if (mismatch || unread)
return VasEBoot_error (VAS_EBOOT_ERR_TEST_FAILURE,
"%d files couldn't be read and hash "
"of %d files mismatches", unread, mismatch);
return VAS_EBOOT_ERR_NONE;
}
static VasEBoot_err_t
VasEBoot_cmd_hashsum (struct VasEBoot_extcmd_context *ctxt,
int argc, char **args)
{
struct VasEBoot_arg_list *state = ctxt->state;
const char *hashname = NULL;
const char *prefix = NULL;
const gcry_md_spec_t *hash;
unsigned i;
int keep = state[3].set;
int uncompress = state[4].set;
unsigned unread = 0;
for (i = 0; i < ARRAY_SIZE (aliases); i++)
if (VasEBoot_strcmp (ctxt->extcmd->cmd->name, aliases[i].name) == 0)
hashname = aliases[i].hashname;
if (state[0].set)
hashname = state[0].arg;
if (!hashname)
return VasEBoot_error (VAS_EBOOT_ERR_BAD_ARGUMENT, "no hash specified");
hash = VasEBoot_crypto_lookup_md_by_name (hashname);
if (!hash)
return VasEBoot_error (VAS_EBOOT_ERR_BAD_ARGUMENT, "unknown hash");
if (hash->mdlen > VAS_EBOOT_CRYPTO_MAX_MDLEN)
return VasEBoot_error (VAS_EBOOT_ERR_BUG, "mdlen is too long");
if (state[2].set)
prefix = state[2].arg;
if (state[1].set)
{
if (argc != 0)
return VasEBoot_error (VAS_EBOOT_ERR_BAD_ARGUMENT,
"--check is incompatible with file list");
return check_list (hash, state[1].arg, prefix, keep, uncompress);
}
for (i = 0; i < (unsigned) argc; i++)
{
VAS_EBOOT_PROPERLY_ALIGNED_ARRAY (result, VAS_EBOOT_CRYPTO_MAX_MDLEN);
VasEBoot_file_t file;
VasEBoot_err_t err;
unsigned j;
file = VasEBoot_file_open (args[i], VAS_EBOOT_FILE_TYPE_TO_HASH
| (!uncompress ? VAS_EBOOT_FILE_TYPE_NO_DECOMPRESS
: VAS_EBOOT_FILE_TYPE_NONE));
if (!file)
{
if (!keep)
return VasEBoot_errno;
VasEBoot_print_error ();
VasEBoot_errno = VAS_EBOOT_ERR_NONE;
unread++;
continue;
}
err = hash_file (file, hash, result);
VasEBoot_file_close (file);
if (err)
{
if (!keep)
return err;
VasEBoot_print_error ();
VasEBoot_errno = VAS_EBOOT_ERR_NONE;
unread++;
continue;
}
for (j = 0; j < hash->mdlen; j++)
VasEBoot_printf ("%02x", ((VasEBoot_uint8_t *) result)[j]);
VasEBoot_printf (" %s\n", args[i]);
}
if (unread)
return VasEBoot_error (VAS_EBOOT_ERR_TEST_FAILURE, "%d files couldn't be read",
unread);
return VAS_EBOOT_ERR_NONE;
}
static VasEBoot_extcmd_t cmd, cmd_md5, cmd_sha1, cmd_sha256, cmd_sha512, cmd_crc;
VAS_EBOOT_MOD_INIT(hashsum)
{
cmd = VasEBoot_register_extcmd ("hashsum", VasEBoot_cmd_hashsum, 0,
N_("-h HASH [-c FILE [-p PREFIX]] "
"[FILE1 [FILE2 ...]]"),
/* TRANSLATORS: "hash checksum" is just to
be a bit more precise, you can treat it as
just "hash". */
N_("Compute or check hash checksum."),
options);
cmd_md5 = VasEBoot_register_extcmd ("md5sum", VasEBoot_cmd_hashsum, 0,
N_("[-c FILE [-p PREFIX]] "
"[FILE1 [FILE2 ...]]"),
N_("Compute or check hash checksum."),
options);
cmd_sha1 = VasEBoot_register_extcmd ("sha1sum", VasEBoot_cmd_hashsum, 0,
N_("[-c FILE [-p PREFIX]] "
"[FILE1 [FILE2 ...]]"),
N_("Compute or check hash checksum."),
options);
cmd_sha256 = VasEBoot_register_extcmd ("sha256sum", VasEBoot_cmd_hashsum, 0,
N_("[-c FILE [-p PREFIX]] "
"[FILE1 [FILE2 ...]]"),
N_("Compute or check hash checksum."),
options);
cmd_sha512 = VasEBoot_register_extcmd ("sha512sum", VasEBoot_cmd_hashsum, 0,
N_("[-c FILE [-p PREFIX]] "
"[FILE1 [FILE2 ...]]"),
N_("Compute or check hash checksum."),
options);
cmd_crc = VasEBoot_register_extcmd ("crc", VasEBoot_cmd_hashsum, 0,
N_("[-c FILE [-p PREFIX]] "
"[FILE1 [FILE2 ...]]"),
N_("Compute or check hash checksum."),
options);
}
VAS_EBOOT_MOD_FINI(hashsum)
{
VasEBoot_unregister_extcmd (cmd);
VasEBoot_unregister_extcmd (cmd_md5);
VasEBoot_unregister_extcmd (cmd_sha1);
VasEBoot_unregister_extcmd (cmd_sha256);
VasEBoot_unregister_extcmd (cmd_sha512);
VasEBoot_unregister_extcmd (cmd_crc);
}

View File

@ -0,0 +1,447 @@
/* hdparm.c - command to get/set ATA disk parameters. */
/*
* VAS_EBOOT -- GRand Unified Bootloader
* Copyright (C) 2009 Free Software Foundation, Inc.
*
* VAS_EBOOT 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.
*
* VAS_EBOOT 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 VAS_EBOOT. If not, see <http://www.gnu.org/licenses/>.
*/
#include <VasEBoot/ata.h>
#include <VasEBoot/scsi.h>
#include <VasEBoot/disk.h>
#include <VasEBoot/dl.h>
#include <VasEBoot/misc.h>
#include <VasEBoot/mm.h>
#include <VasEBoot/lib/hexdump.h>
#include <VasEBoot/extcmd.h>
#include <VasEBoot/i18n.h>
VAS_EBOOT_MOD_LICENSE ("GPLv3+");
static const struct VasEBoot_arg_option options[] = {
{"apm", 'B', 0, N_("Set Advanced Power Management\n"
"(1=low, ..., 254=high, 255=off)."),
0, ARG_TYPE_INT},
{"power", 'C', 0, N_("Display power mode."), 0, ARG_TYPE_NONE},
{"security-freeze", 'F', 0, N_("Freeze ATA security settings until reset."),
0, ARG_TYPE_NONE},
{"health", 'H', 0, N_("Display SMART health status."), 0, ARG_TYPE_NONE},
{"aam", 'M', 0, N_("Set Automatic Acoustic Management\n"
"(0=off, 128=quiet, ..., 254=fast)."),
0, ARG_TYPE_INT},
{"standby-timeout", 'S', 0, N_("Set standby timeout\n"
"(0=off, 1=5s, 2=10s, ..., 240=20m, 241=30m, ...)."),
0, ARG_TYPE_INT},
{"standby", 'y', 0, N_("Set drive to standby mode."), 0, ARG_TYPE_NONE},
{"sleep", 'Y', 0, N_("Set drive to sleep mode."), 0, ARG_TYPE_NONE},
{"identify", 'i', 0, N_("Print drive identity and settings."),
0, ARG_TYPE_NONE},
{"dumpid", 'I', 0, N_("Show raw contents of ATA IDENTIFY sector."),
0, ARG_TYPE_NONE},
{"smart", -1, 0, N_("Disable/enable SMART (0/1)."), 0, ARG_TYPE_INT},
{"quiet", 'q', 0, N_("Do not print messages."), 0, ARG_TYPE_NONE},
{0, 0, 0, 0, 0, 0}
};
enum VasEBoot_ata_smart_commands
{
VAS_EBOOT_ATA_FEAT_SMART_ENABLE = 0xd8,
VAS_EBOOT_ATA_FEAT_SMART_DISABLE = 0xd9,
VAS_EBOOT_ATA_FEAT_SMART_STATUS = 0xda,
};
static int quiet = 0;
static VasEBoot_err_t
VasEBoot_hdparm_do_ata_cmd (VasEBoot_ata_t ata, VasEBoot_uint8_t cmd,
VasEBoot_uint8_t features, VasEBoot_uint8_t sectors,
void * buffer, int size)
{
struct VasEBoot_disk_ata_pass_through_parms apt;
VasEBoot_memset (&apt, 0, sizeof (apt));
apt.taskfile.cmd = cmd;
apt.taskfile.features = features;
apt.taskfile.sectors = sectors;
apt.taskfile.disk = 0xE0;
apt.buffer = buffer;
apt.size = size;
if (ata->dev->readwrite (ata, &apt, 0))
return VasEBoot_errno;
return VAS_EBOOT_ERR_NONE;
}
static int
VasEBoot_hdparm_do_check_powermode_cmd (VasEBoot_ata_t ata)
{
struct VasEBoot_disk_ata_pass_through_parms apt;
VasEBoot_memset (&apt, 0, sizeof (apt));
apt.taskfile.cmd = VAS_EBOOT_ATA_CMD_CHECK_POWER_MODE;
apt.taskfile.disk = 0xE0;
if (ata->dev->readwrite (ata, &apt, 0))
return -1;
return apt.taskfile.sectors;
}
static int
VasEBoot_hdparm_do_smart_cmd (VasEBoot_ata_t ata, VasEBoot_uint8_t features)
{
struct VasEBoot_disk_ata_pass_through_parms apt;
VasEBoot_memset (&apt, 0, sizeof (apt));
apt.taskfile.cmd = VAS_EBOOT_ATA_CMD_SMART;
apt.taskfile.features = features;
apt.taskfile.lba_mid = 0x4f;
apt.taskfile.lba_high = 0xc2;
apt.taskfile.disk = 0xE0;
if (ata->dev->readwrite (ata, &apt, 0))
return -1;
if (features == VAS_EBOOT_ATA_FEAT_SMART_STATUS)
{
if ( apt.taskfile.lba_mid == 0x4f
&& apt.taskfile.lba_high == 0xc2)
return 0; /* Good SMART status. */
else if ( apt.taskfile.lba_mid == 0xf4
&& apt.taskfile.lba_high == 0x2c)
return 1; /* Bad SMART status. */
else
return -1;
}
return 0;
}
static VasEBoot_err_t
VasEBoot_hdparm_simple_cmd (const char * msg,
VasEBoot_ata_t ata, VasEBoot_uint8_t cmd)
{
if (! quiet && msg)
VasEBoot_printf ("%s", msg);
VasEBoot_err_t err = VasEBoot_hdparm_do_ata_cmd (ata, cmd, 0, 0, NULL, 0);
if (! quiet && msg)
VasEBoot_printf ("%s\n", ! err ? "" : ": not supported");
return err;
}
static VasEBoot_err_t
VasEBoot_hdparm_set_val_cmd (const char * msg, int val,
VasEBoot_ata_t ata, VasEBoot_uint8_t cmd,
VasEBoot_uint8_t features, VasEBoot_uint8_t sectors)
{
if (! quiet && msg && *msg)
{
if (val >= 0)
VasEBoot_printf ("Set %s to %d", msg, val);
else
VasEBoot_printf ("Disable %s", msg);
}
VasEBoot_err_t err = VasEBoot_hdparm_do_ata_cmd (ata, cmd, features, sectors,
NULL, 0);
if (! quiet && msg)
VasEBoot_printf ("%s\n", ! err ? "" : ": not supported");
return err;
}
static const char *
le16_to_char (VasEBoot_uint16_t *dest, const VasEBoot_uint16_t * src16, unsigned bytes)
{
unsigned i;
for (i = 0; i < bytes / 2; i++)
dest[i] = VasEBoot_swap_bytes16 (src16[i]);
dest[i] = 0;
return (char *) dest;
}
static void
VasEBoot_hdparm_print_identify (const VasEBoot_uint16_t * idw)
{
/* Print identity strings. */
VasEBoot_uint16_t tmp[21];
VasEBoot_printf ("Model: \"%.40s\"\n", le16_to_char (tmp, &idw[27], 40));
VasEBoot_printf ("Firmware: \"%.8s\"\n", le16_to_char (tmp, &idw[23], 8));
VasEBoot_printf ("Serial: \"%.20s\"\n", le16_to_char (tmp, &idw[10], 20));
/* Print AAM, APM and SMART settings. */
VasEBoot_uint16_t features1 = VasEBoot_le_to_cpu16 (idw[82]);
VasEBoot_uint16_t features2 = VasEBoot_le_to_cpu16 (idw[83]);
VasEBoot_uint16_t enabled1 = VasEBoot_le_to_cpu16 (idw[85]);
VasEBoot_uint16_t enabled2 = VasEBoot_le_to_cpu16 (idw[86]);
VasEBoot_printf ("Automatic Acoustic Management: ");
if (features2 & 0x0200)
{
if (enabled2 & 0x0200)
{
VasEBoot_uint16_t aam = VasEBoot_le_to_cpu16 (idw[94]);
VasEBoot_printf ("%u (128=quiet, ..., 254=fast, recommended=%u)\n",
aam & 0xff, (aam >> 8) & 0xff);
}
else
VasEBoot_printf ("disabled\n");
}
else
VasEBoot_printf ("not supported\n");
VasEBoot_printf ("Advanced Power Management: ");
if (features2 & 0x0008)
{
if (enabled2 & 0x0008)
VasEBoot_printf ("%u (1=low, ..., 254=high)\n",
VasEBoot_le_to_cpu16 (idw[91]) & 0xff);
else
VasEBoot_printf ("disabled\n");
}
else
VasEBoot_printf ("not supported\n");
VasEBoot_printf ("SMART Feature Set: ");
if (features1 & 0x0001)
VasEBoot_printf ("%sabled\n", (enabled1 & 0x0001 ? "en" : "dis"));
else
VasEBoot_printf ("not supported\n");
/* Print security settings. */
VasEBoot_uint16_t security = VasEBoot_le_to_cpu16 (idw[128]);
VasEBoot_printf ("ATA Security: ");
if (security & 0x0001)
VasEBoot_printf ("%s, %s, %s, %s\n",
(security & 0x0002 ? "ENABLED" : "disabled"),
(security & 0x0004 ? "**LOCKED**" : "not locked"),
(security & 0x0008 ? "frozen" : "NOT FROZEN"),
(security & 0x0010 ? "COUNT EXPIRED" : "count not expired"));
else
VasEBoot_printf ("not supported\n");
}
static void
VasEBoot_hdparm_print_standby_tout (int timeout)
{
if (timeout == 0)
VasEBoot_printf ("off");
else if (timeout <= 252 || timeout == 255)
{
int h = 0, m = 0 , s = 0;
if (timeout == 255)
{
m = 21;
s = 15;
}
else if (timeout == 252)
m = 21;
else if (timeout <= 240)
{
s = timeout * 5;
m = s / 60;
s %= 60;
}
else
{
m = (timeout - 240) * 30;
h = m / 60;
m %= 60;
}
VasEBoot_printf ("%02d:%02d:%02d", h, m, s);
}
else
VasEBoot_printf ("invalid or vendor-specific");
}
static int get_int_arg (const struct VasEBoot_arg_list *state)
{
return (state->set ? (int)VasEBoot_strtoul (state->arg, 0, 0) : -1);
}
static VasEBoot_err_t
VasEBoot_cmd_hdparm (VasEBoot_extcmd_context_t ctxt, int argc, char **args)
{
struct VasEBoot_arg_list *state = ctxt->state;
struct VasEBoot_ata *ata;
const char *diskname;
/* Check command line. */
if (argc != 1)
return VasEBoot_error (VAS_EBOOT_ERR_BAD_ARGUMENT, N_("one argument expected"));
if (args[0][0] == '(')
{
VasEBoot_size_t len = VasEBoot_strlen (args[0]);
if (args[0][len - 1] == ')')
args[0][len - 1] = 0;
diskname = &args[0][1];
}
else
diskname = &args[0][0];
int i = 0;
int apm = get_int_arg (&state[i++]);
int power = state[i++].set;
int sec_freeze = state[i++].set;
int health = state[i++].set;
int aam = get_int_arg (&state[i++]);
int standby_tout = get_int_arg (&state[i++]);
int standby_now = state[i++].set;
int sleep_now = state[i++].set;
int ident = state[i++].set;
int dumpid = state[i++].set;
int enable_smart = get_int_arg (&state[i++]);
quiet = state[i++].set;
/* Open disk. */
VasEBoot_disk_t disk = VasEBoot_disk_open (diskname);
if (! disk)
return VasEBoot_errno;
switch (disk->dev->id)
{
case VAS_EBOOT_DISK_DEVICE_ATA_ID:
ata = disk->data;
break;
case VAS_EBOOT_DISK_DEVICE_SCSI_ID:
if (((disk->id >> VAS_EBOOT_SCSI_ID_SUBSYSTEM_SHIFT) & 0xFF)
== VAS_EBOOT_SCSI_SUBSYSTEM_PATA
|| (((disk->id >> VAS_EBOOT_SCSI_ID_SUBSYSTEM_SHIFT) & 0xFF)
== VAS_EBOOT_SCSI_SUBSYSTEM_AHCI))
{
ata = ((struct VasEBoot_scsi *) disk->data)->data;
break;
}
/* FALLTHROUGH */
default:
VasEBoot_disk_close (disk);
return VasEBoot_error (VAS_EBOOT_ERR_IO, "not an ATA device");
}
/* Change settings. */
if (aam >= 0)
VasEBoot_hdparm_set_val_cmd ("Automatic Acoustic Management", (aam ? aam : -1),
ata, VAS_EBOOT_ATA_CMD_SET_FEATURES,
(aam ? 0x42 : 0xc2), aam);
if (apm >= 0)
VasEBoot_hdparm_set_val_cmd ("Advanced Power Management",
(apm != 255 ? apm : -1), ata,
VAS_EBOOT_ATA_CMD_SET_FEATURES,
(apm != 255 ? 0x05 : 0x85),
(apm != 255 ? apm : 0));
if (standby_tout >= 0)
{
if (! quiet)
{
VasEBoot_printf ("Set standby timeout to %d (", standby_tout);
VasEBoot_hdparm_print_standby_tout (standby_tout);
VasEBoot_printf (")");
}
/* The IDLE cmd sets disk to idle mode and configures standby timer. */
VasEBoot_hdparm_set_val_cmd ("", -1, ata, VAS_EBOOT_ATA_CMD_IDLE, 0, standby_tout);
}
if (enable_smart >= 0)
{
if (! quiet)
VasEBoot_printf ("%sable SMART operations", (enable_smart ? "En" : "Dis"));
int err = VasEBoot_hdparm_do_smart_cmd (ata, (enable_smart ?
VAS_EBOOT_ATA_FEAT_SMART_ENABLE : VAS_EBOOT_ATA_FEAT_SMART_DISABLE));
if (! quiet)
VasEBoot_printf ("%s\n", err ? ": not supported" : "");
}
if (sec_freeze)
VasEBoot_hdparm_simple_cmd ("Freeze security settings", ata,
VAS_EBOOT_ATA_CMD_SECURITY_FREEZE_LOCK);
/* Print/dump IDENTIFY. */
if (ident || dumpid)
{
VasEBoot_uint16_t buf[VAS_EBOOT_DISK_SECTOR_SIZE / 2];
if (VasEBoot_hdparm_do_ata_cmd (ata, VAS_EBOOT_ATA_CMD_IDENTIFY_DEVICE,
0, 0, buf, sizeof (buf)))
VasEBoot_printf ("Cannot read ATA IDENTIFY data\n");
else
{
if (ident)
VasEBoot_hdparm_print_identify (buf);
if (dumpid)
hexdump (0, (char *) buf, sizeof (buf));
}
}
/* Check power mode. */
if (power)
{
VasEBoot_printf ("Disk power mode is: ");
int mode = VasEBoot_hdparm_do_check_powermode_cmd (ata);
if (mode < 0)
VasEBoot_printf ("unknown\n");
else
VasEBoot_printf ("%s (0x%02x)\n",
(mode == 0xff ? "active/idle" :
mode == 0x80 ? "idle" :
mode == 0x00 ? "standby" : "unknown"), mode);
}
/* Check health. */
int status = 0;
if (health)
{
if (! quiet)
VasEBoot_printf ("SMART status is: ");
int err = VasEBoot_hdparm_do_smart_cmd (ata, VAS_EBOOT_ATA_FEAT_SMART_STATUS);
if (! quiet)
VasEBoot_printf ("%s\n", (err < 0 ? "unknown" :
err == 0 ? "OK" : "*BAD*"));
status = (err > 0);
}
/* Change power mode. */
if (standby_now)
VasEBoot_hdparm_simple_cmd ("Set disk to standby mode", ata,
VAS_EBOOT_ATA_CMD_STANDBY_IMMEDIATE);
if (sleep_now)
VasEBoot_hdparm_simple_cmd ("Set disk to sleep mode", ata,
VAS_EBOOT_ATA_CMD_SLEEP);
VasEBoot_disk_close (disk);
VasEBoot_errno = VAS_EBOOT_ERR_NONE;
return status;
}
static VasEBoot_extcmd_t cmd;
VAS_EBOOT_MOD_INIT(hdparm)
{
cmd = VasEBoot_register_extcmd_lockdown ("hdparm", VasEBoot_cmd_hdparm, 0,
N_("[OPTIONS] DISK"),
N_("Get/set ATA disk parameters."), options);
}
VAS_EBOOT_MOD_FINI(hdparm)
{
VasEBoot_unregister_extcmd (cmd);
}

View File

@ -0,0 +1,155 @@
/* help.c - command to show a help text. */
/*
* VAS_EBOOT -- GRand Unified Bootloader
* Copyright (C) 2005,2007,2008,2009 Free Software Foundation, Inc.
*
* VAS_EBOOT 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.
*
* VAS_EBOOT 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 VAS_EBOOT. If not, see <http://www.gnu.org/licenses/>.
*/
#include <VasEBoot/dl.h>
#include <VasEBoot/misc.h>
#include <VasEBoot/term.h>
#include <VasEBoot/extcmd.h>
#include <VasEBoot/i18n.h>
#include <VasEBoot/mm.h>
#include <VasEBoot/normal.h>
#include <VasEBoot/charset.h>
VAS_EBOOT_MOD_LICENSE ("GPLv3+");
static VasEBoot_err_t
VasEBoot_cmd_help (VasEBoot_extcmd_context_t ctxt __attribute__ ((unused)), int argc,
char **args)
{
int cnt = 0;
char *currarg;
if (argc == 0)
{
VasEBoot_command_t cmd;
FOR_COMMANDS(cmd)
{
if ((cmd->prio & VAS_EBOOT_COMMAND_FLAG_ACTIVE))
{
struct VasEBoot_term_output *term;
const char *summary_translated = _(cmd->summary);
char *command_help;
VasEBoot_uint32_t *unicode_command_help;
VasEBoot_uint32_t *unicode_last_position;
command_help = VasEBoot_xasprintf ("%s %s", cmd->name, summary_translated);
if (!command_help)
break;
VasEBoot_utf8_to_ucs4_alloc (command_help, &unicode_command_help,
&unicode_last_position);
FOR_ACTIVE_TERM_OUTPUTS(term)
{
unsigned stringwidth;
VasEBoot_uint32_t *unicode_last_screen_position;
unicode_last_screen_position = unicode_command_help;
stringwidth = 0;
while (unicode_last_screen_position < unicode_last_position &&
stringwidth < ((VasEBoot_term_width (term) / 2) - 2))
{
struct VasEBoot_unicode_glyph glyph;
unicode_last_screen_position
+= VasEBoot_unicode_aglomerate_comb (unicode_last_screen_position,
unicode_last_position
- unicode_last_screen_position,
&glyph);
stringwidth
+= VasEBoot_term_getcharwidth (term, &glyph);
}
VasEBoot_print_ucs4 (unicode_command_help,
unicode_last_screen_position, 0, 0, term);
if (!(cnt % 2))
VasEBoot_print_spaces (term, VasEBoot_term_width (term) / 2
- stringwidth);
}
if (cnt % 2)
VasEBoot_printf ("\n");
cnt++;
VasEBoot_free (command_help);
VasEBoot_free (unicode_command_help);
}
}
if (!(cnt % 2))
VasEBoot_printf ("\n");
}
else
{
int i;
VasEBoot_command_t cmd_iter, cmd, cmd_next;
for (i = 0; i < argc; i++)
{
currarg = args[i];
FOR_COMMANDS_SAFE (cmd_iter, cmd_next)
{
if (!(cmd_iter->prio & VAS_EBOOT_COMMAND_FLAG_ACTIVE))
continue;
if (VasEBoot_strncmp (cmd_iter->name, currarg,
VasEBoot_strlen (currarg)) != 0)
continue;
if (cmd_iter->flags & VAS_EBOOT_COMMAND_FLAG_DYNCMD)
cmd = VasEBoot_dyncmd_get_cmd (cmd_iter);
else
cmd = cmd_iter;
if (!cmd)
{
VasEBoot_print_error ();
continue;
}
if (cnt++ > 0)
VasEBoot_printf ("\n\n");
if ((cmd->flags & VAS_EBOOT_COMMAND_FLAG_EXTCMD) &&
! (cmd->flags & VAS_EBOOT_COMMAND_FLAG_DYNCMD))
VasEBoot_arg_show_help ((VasEBoot_extcmd_t) cmd->data);
else
VasEBoot_printf ("%s %s %s\n%s\n", _("Usage:"), cmd->name,
_(cmd->summary), _(cmd->description));
}
}
}
VasEBoot_printf ("\n\nTo enable less(1)-like paging, \"set pager=1\".\n");
return 0;
}
static VasEBoot_extcmd_t cmd;
VAS_EBOOT_MOD_INIT(help)
{
cmd = VasEBoot_register_extcmd ("help", VasEBoot_cmd_help, 0,
N_("[PATTERN ...]"),
N_("Show a help message."), 0);
}
VAS_EBOOT_MOD_FINI(help)
{
VasEBoot_unregister_extcmd (cmd);
}

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