Compare commits

..

No commits in common. "911c029b4844466163eae343e277284f35554729" and "66cac2e12b827fc14e6b1d54f5376e86e0a42646" have entirely different histories.

2835 changed files with 964024 additions and 12 deletions

250
.gitignore vendored Normal file
View File

@ -0,0 +1,250 @@
00_header
10_*
20_linux_xen
30_os-prober
40_custom
41_custom
*.1
*.8
aclocal.m4
ahci_test
ascii.bitmaps
ascii.h
autom4te.cache
build-VasEBoot-gen-asciih
build-VasEBoot-gen-widthspec
build-VasEBoot-mkfont
cdboot_test
cmp_test
config.cache
config.guess
config.h
config-util.h
config-util.h.in
config.log
config.status
config.sub
configure
core_compress_test
DISTLIST
docs/*.info
docs/stamp-vti
docs/version.texi
ehci_test
example_VasEBoot_script_test
example_scripted_test
example_unit_test
*.exec
*.exec.exe
fddboot_test
genkernsyms.sh
gensymlist.sh
gentrigtables
gentrigtables.exe
gettext_strings_test
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/VasEBoot/cpu
include/VasEBoot/machine
install-sh
lib/libgcrypt-VasEBoot
libVasEBoot_a_init.c
*.log
*.lst
lzocompress_test
*.marker
Makefile
*.mod
mod-*.c
missing
netboot_test
*.o
*.a
ohci_test
partmap_test
pata_test
*.pf2
*.pp
po/*.mo
po/VasEBoot.pot
po/POTFILES
po/stamp-po
printf_test
priority_queue_unit_test
pseries_test
stamp-h
stamp-h1
stamp-h.in
symlist.c
symlist.h
trigtables.c
*.trs
uhci_test
update-VasEBoot_lib
unidata.c
xzcompress_test
Makefile.in
GPATH
GRTAGS
GSYMS
GTAGS
compile
depcomp
mdate-sh
texinfo.tex
VasEBoot-core/lib/libgcrypt-VasEBoot
.deps
.deps-util
.deps-core
.dirstamp
Makefile.util.am
contrib
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
docs/version-dev.texi
Makefile.utilgcry.def
po/*.po
po/*.gmo
po/LINGUAS
po/remove-potcdate.sed
include/VasEBoot/gcrypt/gcrypt.h
include/VasEBoot/gcrypt/g10lib.h
po/POTFILES.in
po/POTFILES-shell.in
/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
/VasEBoot-fs-tester
VasEBoot-core/build-VasEBoot-module-verifier

1282
ABOUT-NLS Normal file

File diff suppressed because it is too large Load Diff

23
AUTHORS Normal file
View File

@ -0,0 +1,23 @@
The following authors assigned copyright on their work to the Free
Software Foundation:
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, VasEBoot-emu, a new command-line
engine, and fixed many bugs.
Omniflux added terminfo and serial support.
Vincent Pelletier added Sparc64 support.
Hollis Blanchard implemented many parts of PowerPC support.
Tomas Ebenlendr added the command chainloader into the normal mode,
fixed some bugs.
Guillem Jover merged architecture-independent ELF support code.
Vesa Jaaskelainen added VBE support.

3
BUGS Normal file
View File

@ -0,0 +1,3 @@
Open bugs and issues are captured in the VAS_EBOOT bug tracking system:
https://savannah.gnu.org/bugs/?group=VasEBoot

674
COPYING Normal file
View File

@ -0,0 +1,674 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program 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.
This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<http://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>.

30698
ChangeLog Normal file

File diff suppressed because it is too large Load Diff

55487
ChangeLog-2015 Normal file

File diff suppressed because it is too large Load Diff

361
INSTALL Normal file
View File

@ -0,0 +1,361 @@
-*- Text -*-
This is the VAS_EBOOT. Welcome.
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
================
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 VAS_EBOOT.
* 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
* GNU Make
* GNU Bison 2.3 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)
On GNU/Linux, you also need:
* libdevmapper 1.02.34 or later (recommended)
For optional VasEBoot-emu features, you need:
* SDL (recommended)
* libpciaccess (optional)
To build VAS_EBOOT's graphical terminal (gfxterm), you need:
* FreeType 2.1.5 or later
* GNU Unifont
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 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)
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.
More cross compiling toolchains can be found at the following trusted sites:
* 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
various system-dependent variables used during compilation. It uses
those values to create a `Makefile' in each directory of the package.
It may also create one or more `.h' files containing system-dependent
definitions. Finally, it creates a shell script `config.status' that
you can run in the future to recreate the current configuration, a
file `config.cache' that saves the results of its tests to speed up
reconfiguring, and a file `config.log' containing compiler output
(useful mainly for debugging `configure').
If you need to do unusual things to compile the package, please try to
figure out how `configure' could check whether to do them, and mail
diffs or instructions to the address given in the `README' so they can
be considered for the next release. If at some point `config.cache'
contains results you don't want to keep, you may remove or edit it.
The file `configure.ac' is used to create `configure' by a program
called `autoconf'. You only need `configure.in' if you want to change
it or regenerate `configure' using a newer version of `autoconf'.
Building the VAS_EBOOT
=================
The simplest way to compile this package is:
1. `cd' to the directory containing the package's source code.
2. Type `./bootstrap'.
The autogen.sh (called by bootstrap) uses python. By default it is
autodetected, but it can be overridden by setting the PYTHON variable.
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.
Running `configure' takes awhile. While running, it prints some
messages telling which features it is checking for.
4. Type `make' to compile 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.
6. Type `make install' to install the programs and any data files and
documentation.
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
also a `make maintainer-clean' target, but that is intended mainly
for the package's developers. If you use it, you may have to get
all sorts of other programs in order to regenerate files that came
with the distribution.
Cross-compiling the VAS_EBOOT
========================
VAS_EBOOT defines 3 platforms:
- "Build" is the one which build systems runs on.
- "Host" is where you execute VAS_EBOOT utils.
- "Target" is where VAS_EBOOT itself runs.
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.
If build and host are different man pages are not generated.
As an example imagine you have a build system running on FreeBSD on sparc
which prepares packages for developers running amd64 GNU/Linux laptop and
they need to make images for ARM board running U-boot. In this case:
build=sparc64-freebsd
host=amd64-linux-gnu
target=arm-uboot
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=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= 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.
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. 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.
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.
7. TARGET_LDFLAGS= for linker options for target.
8. TARGET_OBJCOPY= for objcopy for target.
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)
- Platform-agnostic tools and data.
1. make is the tool you execute after ./configure.
2. Bison is specified in YACC= variable
3. Flex is specified in LEX= variable
4. GNU unifont and Djvu sans are looked for in standard directories.
Compiling For Multiple Architectures
====================================
You can compile the package for more than one kind of computer at the
same time, by placing the object files for each architecture in their
own directory. `cd' to the directory where you want the object files
and executables to go and run the `configure' script. `configure'
automatically checks for the source code in the directory that
`configure' is in and in `..'.
Installation Names
==================
By default, `make install' will install the package's files in
`/usr/local/bin', `/usr/local/man', etc. You can specify an
installation prefix by giving `configure' the option `--prefix=PATH'.
You can specify separate installation prefixes for
architecture-specific files and architecture-independent files. If
you give `configure' the option `--exec-prefix=PATH', the package will
use PATH as the prefix for installing programs and libraries.
Documentation and other data files will still use the regular prefix.
In addition, if you use an unusual directory layout you can give
options like `--bindir=PATH' to specify different values for
particular kinds of files. Run `configure --help' for a list of the
directories you can set and what kinds of files go in them.
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 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 VAS_EBOOT is to allow you to "install" in some alternate
location, and then copy these to the actual root filesystem later.
Sharing Defaults
================
If you want to set default values for `configure' scripts to share,
you can create a site shell script called `config.site' that gives
default values for variables like `CC', `cache_file', and `prefix'.
`configure' looks for `PREFIX/share/config.site' if it exists, then
`PREFIX/etc/config.site' if it exists. Or, you can set the
`CONFIG_SITE' environment variable to the location of the site script.
A warning: not all `configure' scripts look for a site script.
Operation Controls
==================
`configure' recognizes the following options to control how it
operates.
`--cache-file=FILE'
Use and save the results of the tests in FILE instead of
`./config.cache'. Set FILE to `/dev/null' to disable caching, for
debugging `configure'.
`--help'
Print a summary of the options to `configure', and exit.
`--quiet'
`--silent'
`-q'
Do not print messages saying which checks are being made.
`--srcdir=DIR'
Look for the package's source code in directory DIR. Usually
`configure' can determine that directory automatically.
`--version'
Print the version of Autoconf used to generate the `configure'
script, and exit.

View File

@ -1,9 +0,0 @@
Copyright (c) 2026 main
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

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

494
Makefile.am Normal file
View File

@ -0,0 +1,494 @@
AUTOMAKE_OPTIONS = subdir-objects -Wno-portability
DEPDIR = .deps-util
SUBDIRS = VasEBoot-core/lib/gnulib .
if COND_real_platform
SUBDIRS += VasEBoot-core
endif
SUBDIRS += po docs util/bash-completion.d
include $(top_srcdir)/conf/Makefile.common
include $(top_srcdir)/conf/Makefile.extra-dist
AM_CFLAGS = $(HOST_CFLAGS)
AM_LDFLAGS = $(HOST_LDFLAGS)
AM_CPPFLAGS = $(HOST_CPPFLAGS) $(CPPFLAGS_DEFAULT)
AM_CCASFLAGS = $(HOST_CCASFLAGS) $(CCASFLAGS_DEFAULT)
ACLOCAL_AMFLAGS = -I m4
CFLAGS_PROGRAM += $(CFLAGS_GNULIB)
LDFLAGS_PROGRAM += $(LDFLAGS_GNULIB)
CPPFLAGS_PROGRAM += $(CPPFLAGS_GNULIB)
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
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.
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 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
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
libVasEBoot_a_init.c: libVasEBoot_a_init.lst $(top_srcdir)/geninit.sh
sh $(top_srcdir)/geninit.sh `cat $<` > $@ || (rm -f $@; exit 1)
CLEANFILES += libVasEBoot_a_init.c
# 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
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
VasEBoot_fstest_init.c: VasEBoot_fstest_init.lst $(top_srcdir)/geninit.sh
sh $(top_srcdir)/geninit.sh `cat $<` > $@ || (rm -f $@; exit 1)
CLEANFILES += VasEBoot_fstest_init.c
if COND_HAVE_FONT_SOURCE
pkgdata_DATA += unicode.pf2 ascii.pf2 euro.pf2 ascii.h widthspec.h
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-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-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-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-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-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-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-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-VasEBoot-mkfont$(BUILD_EXEEXT)
./build-VasEBoot-mkfont$(BUILD_EXEEXT) -s 16 -o $@ $(DJVU_FONT_SOURCE)
CLEANFILES += dejavu_16.pf2
else
starfield_DATA =
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-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-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-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-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-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 += VasEBoot-mkconfig_lib
if COND_real_platform
if COND_i386_coreboot
QEMU32=qemu-system-i386
MINIMUM_CPU_LINUX=pentium2
endif
if COND_i386_multiboot
QEMU32=qemu-system-i386
MINIMUM_CPU_LINUX=pentium2
endif
if COND_i386_ieee1275
QEMU32=qemu-system-i386
MINIMUM_CPU_LINUX=pentium2
endif
if COND_i386_qemu
QEMU32=qemu-system-i386
MINIMUM_CPU_LINUX=pentium2
endif
if COND_i386_pc
QEMU32=qemu-system-i386
MINIMUM_CPU_LINUX=pentium2
endif
if COND_i386_efi
QEMU32=qemu-system-i386
MINIMUM_CPU_LINUX=pentium2
endif
if COND_x86_64_efi
QEMU32=qemu-system-x86_64
MINIMUM_CPU_LINUX=core2duo
endif
linux.init.x86_64: $(srcdir)/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)/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)/VasEBoot-core/tests/boot/linux.init-mips.S
$(TARGET_CC) -o $@ $< -static -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\"
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)/VasEBoot-core/tests/boot/linux.init-mips.S
$(TARGET_CC) -o $@ $< -static -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\"
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)/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)/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)/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)/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)/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)/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)/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)/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)/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)/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)/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
TDIR=`mktemp -d "$${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` && cp $< $$TDIR/init && (cd $$TDIR && echo ./init | cpio -R 0:0 --quiet --dereference -o -H newc) | gzip > $@ && rm -rf $$TDIR
linux-initramfs.ppc: linux.init.ppc Makefile
TDIR=`mktemp -d "$${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` && cp $< $$TDIR/init && (cd $$TDIR && echo ./init | cpio -R 0:0 --quiet --dereference -o -H newc) | gzip > $@ && rm -rf $$TDIR
linux-initramfs.mipsel: linux.init.mipsel Makefile
TDIR=`mktemp -d "$${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` && cp $< $$TDIR/init && (cd $$TDIR && echo ./init | cpio -R 0:0 --quiet --dereference -o -H newc) | gzip > $@ && rm -rf $$TDIR
linux-initramfs.loongson: linux.init.loongson Makefile
TDIR=`mktemp -d "$${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` && cp $< $$TDIR/init && (cd $$TDIR && echo ./init | cpio -R 0:0 --quiet --dereference -o -H newc) | gzip > $@ && rm -rf $$TDIR
linux-initramfs.i386: linux.init.i386 Makefile
TDIR=`mktemp -d "$${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` && cp $< $$TDIR/init && (cd $$TDIR && echo ./init | cpio -R 0:0 --quiet --dereference -o -H newc) | gzip > $@ && rm -rf $$TDIR
linux-initramfs.x86_64: linux.init.x86_64 Makefile
TDIR=`mktemp -d "$${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` && cp $< $$TDIR/init && (cd $$TDIR && echo ./init | cpio -R 0:0 --quiet --dereference -o -H newc) | gzip > $@ && rm -rf $$TDIR
kfreebsd-mfsroot.i386.img: kfreebsd.init.i386 Makefile
TDIR=`mktemp -d "$${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` && mkdir $$TDIR/dev && mkdir $$TDIR/sbin && cp $< $$TDIR/sbin/init && makefs -t ffs -s 30m -f 1000 -o minfree=0,version=1 $@ $$TDIR && rm -rf $$TDIR
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)/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)/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 $(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)/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 $(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 $(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 $(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 $(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 $(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 $(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 $(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 $(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 $(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 $(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 $(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 $(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 $(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 $(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 $(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)/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)/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)/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)/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)/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
BOOTCHECKS = bootcheck-kfreebsd-aout bootcheck-kopenbsd-i386 bootcheck-kopenbsd-x86_64 bootcheck-multiboot bootcheck-multiboot2 bootcheck-linux-i386 bootcheck-linux-x86_64 bootcheck-kfreebsd-x86_64 bootcheck-kfreebsd-i386
endif
if COND_x86_64_efi
# NetBSD has no support for finding ACPI on EFI
BOOTCHECKS = bootcheck-kfreebsd-aout bootcheck-kopenbsd-i386 bootcheck-kopenbsd-x86_64 bootcheck-multiboot bootcheck-multiboot2 bootcheck-linux-i386 bootcheck-linux-x86_64 bootcheck-kfreebsd-x86_64 bootcheck-kfreebsd-i386
endif
if COND_i386_multiboot
# *BSD requires ACPI
BOOTCHECKS = bootcheck-kfreebsd-aout bootcheck-multiboot bootcheck-multiboot2 bootcheck-linux-i386 bootcheck-linux-x86_64
endif
if COND_i386_qemu
# *BSD requires ACPI
BOOTCHECKS = bootcheck-kfreebsd-aout bootcheck-multiboot bootcheck-multiboot2 bootcheck-linux-i386 bootcheck-linux-x86_64
endif
if COND_i386_coreboot
BOOTCHECKS = bootcheck-kfreebsd-aout bootcheck-kopenbsd-i386 bootcheck-kopenbsd-x86_64 bootcheck-multiboot bootcheck-multiboot2 bootcheck-linux-i386 bootcheck-linux-x86_64 bootcheck-knetbsd-x86_64 bootcheck-kfreebsd-x86_64 bootcheck-kfreebsd-i386
endif
if COND_i386_ieee1275
# *BSD requires ACPI
#legacy protocol (linux16) makes early BIOS calls.
BOOTCHECKS = bootcheck-kfreebsd-aout bootcheck-multiboot bootcheck-multiboot2 bootcheck-linux-i386 bootcheck-linux-x86_64
endif
if COND_i386_pc
#pc chainloader by definition is only for i386-pc
#ntldr and bootmgr require BIOS.
#legacy protocol (linux16) makes early BIOS calls.
# 32-bit NetBSD crashes early on non-BIOS
BOOTCHECKS = bootcheck-kfreebsd-aout bootcheck-kopenbsd-i386 bootcheck-kopenbsd-x86_64 bootcheck-multiboot bootcheck-multiboot2 bootcheck-linux-i386 bootcheck-linux-x86_64 bootcheck-knetbsd-x86_64 bootcheck-kfreebsd-x86_64 bootcheck-kfreebsd-i386 bootcheck-pc-chainloader bootcheck-ntldr bootcheck-linux16-i386 bootcheck-linux16-x86_64 bootcheck-knetbsd-i386
endif
if COND_mips_loongson
BOOTCHECKS = bootcheck-linux-loongson
endif
if COND_mipsel
if COND_mips_qemu_mips
BOOTCHECKS = bootcheck-linux-mipsel
endif
endif
if COND_mipseb
if COND_mips_qemu_mips
BOOTCHECKS = bootcheck-linux-mips
endif
endif
if COND_powerpc_ieee1275
BOOTCHECKS = bootcheck-linux-ppc
endif
.PHONY: bootcheck-linux-i386 bootcheck-linux-x86_64 \
bootcheck-kfreebsd-i386 bootcheck-kfreebsd-x86_64 \
bootcheck-knetbsd-i386 bootcheck-knetbsd-x86_64 \
bootcheck-linux-mips FORCE
# Randomly generated
SUCCESSFUL_BOOT_STRING=3e49994fd5d82b7c9298d672d774080d
# tianocore cd access is very slow
BOOTCHECK_TIMEOUT=180
bootcheck: $(BOOTCHECKS)
if COND_i386_coreboot
FS_PAYLOAD_MODULES ?= $(shell cat VasEBoot-core/fs.lst)
default_payload.elf: VasEBoot-mkstandalone VasEBoot-mkimage FORCE
test -f $@ && rm $@ || true
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 += 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 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 \
if [ x$(STRIP) != x ]; then $(STRIP) $$x -o $(windowsdir)/$$x; \
else cp -fp $$x $(windowsdir)/$$x; fi; \
done
for x in $(pkgdata_DATA); do \
cp -fp $$x $(windowsdir)/$$x; \
done
for x in $(starfield_DATA); do \
cp -fp $$x $(windowsdir)/themes/starfield/$$(basename $$x); \
done
for x in $(VAS_EBOOT_WINDOWS_EXTRA_DIST); do \
cp -fp $$x $(windowsdir); \
done
windowszip=$(top_builddir)/$(PACKAGE)-$(VERSION)-for-windows.zip
windowszip: windowsdir
test -f $(windowszip) && rm $(windowszip) || true
zip -r $(windowszip) $(windowsdir)
rm -rf $(windowsdir)
EXTRA_DIST += linguas.sh
changelog_start_date = 2015-01-23
gitlog_to_changelog = $(top_srcdir)/build-aux/gitlog-to-changelog
ChangeLog: FORCE
if test -d $(top_srcdir)/.git; then \
$(gitlog_to_changelog) --srcdir=$(top_srcdir) --since=$(changelog_start_date) > '$@.tmp'; \
rm -f '$@'; mv '$@.tmp' '$@'; \
else \
touch $@; \
fi
syslinux_test: $(top_builddir)/config.status tests/syslinux/ubuntu10.04_VasEBoot.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

1479
Makefile.util.def Normal file

File diff suppressed because it is too large Load Diff

782
NEWS Normal file
View File

@ -0,0 +1,782 @@
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:
* Big-endian UFS1.
* Experimental 64-bit ext2 support.
* Various fixes for non-512-byte sector devices.
* New `proc' filesystem framework, used by LUKS disks.
* Fix DM-RAID partition handling.
* New `nativedisk' command to switch from firmware to native disk drivers.
* Compressed HFS+.
* DragonFly BSD labels.
* CBFS (coreboot).
* Handle partitioned LVM properly.
* Use LVM UUIDs whenever possible.
* GPT PReP.
* New `progress' module that shows progress information while reading
files.
* ZFS features support.
* ZFS LZ4 support.
* XFS V5 format support.
* LVM RAID1 support.
* New/improved terminal and video support:
* 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 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
`highlight_overlay'.
* Support several more image types (paletted and greyscale).
* Boot protocol improvements:
* Support Apple FAT binaries on non-Apple platforms.
* Improve FreeDOS direct loading support compatibility.
* Enable `linux16' on all x86 platforms, not just BIOS.
* New TrueCrypt ISO loader.
* multiboot2 boot-services EFI specification.
* multiboot2 EFI memory map specification.
* multiboot2 full-file specfication.
* New/improved network support:
* New variables `net_default_*' containing properties of the default
interface.
* Autoload `http' and `tftp' modules if necessary.
* Improve TFTP robustness.
* 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
from BOOTP reply.
* Coreboot improvements:
* CBFS support both in on-disk images (loopback) and flash.
* Ability to launch another payload from flash or disk
* Coreboot framebuffer
* CBMEMC support (both logging and inspecting logs)
* Command for inspecting coreboot timestamps (`coreboot_boottime').
* Command for inspecting coreboot tables (`lscoreboot').
* New target default_payload.elf.
* Increased maximal core size.
* Prefer pmtimer for TSC calibration.
* New/improved platform support:
* New `efifwsetup' and `lsefi' commands on EFI platforms.
* New `cmosdump' and `cmosset' commands on platforms with CMOS support.
* 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 VasEBoot-mkrescue implementation with the common one.
* Support VasEBoot-mkrescue on i386-ieee1275, sparc64, bootinfo machines such
as pSeries, and mips-arc.
* 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.
* AROS and Haiku support for userspace utilities.
* Xen PV port.
* Fix EFI stack alignment.
* ARM64 EFI port.
* On Linux, read partition start offsets from sysfs if possible.
* 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.
* Support for *-emu on all platforms (previously only i386/x86_64 worked).
* Support *-emu on Windows.
* New platform `none' which builds only user level utilities. This is now
default if target CPU is not supported.
* Support for booting little-endian Linux kernel on powerpc.
* Support network boot with Oracle sun4v vnet devices.
* Added SAS disks to the IEEE 1275 Open Firmware device list.
* Try multiple methods for TSC (timestamp counter) calibration - PIT, pmtimer,
EFI Stall. If everything fails, use hardcoded frequency 800MHz.
* Support Hyper-V Gen2 platforms which lack PIT for TSC calibration.
* Map UEFI Persistent Memory to E820 persistent memory.
* New Xen loader on ARM64.
* Respect alignment requirement for block device IO buffers on EFI.
* Security:
* Add optional facility to enforce that all files read by the core image
from disk have a valid detached digital signature.
* Performance:
* Avoid costly division operations in many places.
* New boot time analysis framework (`./configure --enable-boot-time').
* Initialise USB ports in parallel.
* New `testspeed' command to test file read speed.
* Speed-up gfxterm by storing intermediate results in more compact format.
* Lazy LVM/mdraid scan.
* Disk hints.
* Scripting:
* New `eval' and `tr' 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 VasEBoot-reboot no longer requires setting `VAS_EBOOT_DEFAULT=saved'.
* Support probing EFI System Partition (requires os-prober >= 1.58).
* 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 `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 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 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; VAS_EBOOT no longer requires an
executable stack.
* Fix documentation build with Texinfo >= 5.1.
* More robust and documented cross-compiling support.
* Partial clang support for some platforms (experimental).
* Partial mingw64 x86_64-efi compile support (highly experimental).
* Partial mingw32 i386-* (other than already present i386-pc)
compile support (highly experimental).
* Support for VasEBoot-mkpasswd on Windows.
* Eliminate the use of AutoGen. This allowed some performance
improvements to the build system.
* Remove variable length arrays.
* OpenBSD compile and tools support (NetBSD and FreeBSD were already supported).
* Fix build with FreeType >= 2.5.1.
* Make gentpl.py compatible with Python 3. It now requires at least
Python 2.6.
* modinfo.sh contains build information now.
* Added many new tests to improve robustness.
* Target is built without libgcc now. Necessary builtins are reimplemented
directly. This removes requirement for target-specific runtime on build
system.
* emu libusb support removed (was broken and unmaintained).
* powerpc64le compile support.
* 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.
* Revision control moved to git.
New in 2.00:
* Appearance:
* Official theme for gfxmenu (starfield)
* Menu is organised with submenus.
* Better default video mode selection using EDID.
* New platforms:
* Itanium port.
* Fuloong2F support (including VAS_EBOOT as firmware)
* Fuloong2E support (except VAS_EBOOT as firmware)
* ARCS (SGI machines) port.
* qemu -M mips port.
* 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.
* New drivers:
* EHCI.
* AHCI.
* ESCC serial.
* IEEE1275 serial.
* EFI serial.
* Network stack for BIOS, IEEE1275, EMU and EFI, including TFTP, HTTP and DNS.
* New filesystem, filters and disks formats:
* DVH partition map.
* Plan9 partition map.
* Big-endian mdraid.
* Big-endian cpio.
* ODC and NEWC cpio.
* ExFAT.
* Minix3fs.
* Big-endian minixfs.
* RomFS.
* Squash4.
* Support non-512B disk blocks.
* LUKS and GELI support.
* LDM read support (no install yet).
* LZOP.
* Improved filesystem and disks formats support:
* HFS+ label support.
* Improved reiserfs support.
* multidevice, mirrored and raidz(2,3) ZFS support.
* RAID LVM (internal RAIDing) support.
* ZFS crypto support.
* ZLE, LZ4 and GZIP on ZFS support.
* Support ZFS up to 33.
* HFS string is now treated like mac-roman and not UTF-8
* HFS mtime support.
* Improved AFFS and SFS support.
* LZO-compressed btrfs support.
* cpio and tar symlinks support.
* Better FS detection to reduce false positives.
* New boot protocols:
* Ability to load another coreboot payload when on coreboot.
* Plan9.
* Freedos.
* Ntldr/bootmgr (to load Windows bootloader).
* chainloader --bpb support to patch FAT or NTFS BPB in memory to correct
wrong partition offset.
* PXE chainloading support.
* Darwin 11 (Mac OS X Lion) protocol support.
* Boot protocol improvements:
* Multiple initrd support.
* Basic illumos and xnu autoconfig.
* Testing and debugging:
* 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.
* GDB stub and GDB support script.
* "make check" and "make bootcheck" expanded to almost all platforms
(except i386-ieee1275, mips-arc, sparc64-ieee1275, ia64-efi and emu)
* New `time' command.
* Performance:
* Lazy scanning to avoid accessing devices which aren't really used.
This avoids boot delay due to slow device scanning.
* Use CPU cache when accessing video memory.
* Search hints to first try the most likely device when searching for a
device with given UUID. This avoids slow scanning in most cases.
* Internationalisation:
* Updated to Unicode 6.0.
* $"..." 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:
* $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.
* all_video module which is empty but depends on all video modules thus
allowing easy loading of all of them.
* Installation:
* 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 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 --VasEBootdir and --bootdir to get old behaviour.
* ADLER32 and CRC64 support (for XZ and hashsum).
* ofconsole renamed to console
* Experimental support for compiling with Apple toolchain.
* VasEBoot-mkdevicemap removed. Now all devices are detected on invocation of
any VasEBoot utility.
New in 1.99:
* Keyboard layouts support.
* New `lsapm' command (i386-pc only).
* Parser for VAS_EBOOT Legacy configuration files.
* Support RAID on virtio devices.
* Remove deprecated `root' command.
* New `euro.pf2' font which supports most European languages.
* Avoid opening the same device twice on Open Firmware platforms.
* Extend `vbeinfo' and `vbetest' commands to non-VBE graphics, as
`videoinfo' and `videotest'.
* New `lsefisystab', `lssal', and `lsefimmap' commands on EFI platforms.
* Support explicit user claim that a device is BIOS-visible. Devices
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 VAS_EBOOT utilities.
* Use ACPI to shut down if possible.
* New `lsacpi' command.
* Btrfs support.
* 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 `VasEBoot-mknetdir' utility to generate
netboot directory trees.
* New relocator. Allows for more kernel support and more
straightforward loader writing.
* Handle USB pendrives exposed as floppies.
* New Automake-based build system.
* Add `sendkey' command (i386-pc only).
* ZFS support.
* Support 1.x versions of mdadm metadata.
* Fix corruption when reading Reiserfs directory entries.
* Bidirectional text and diacritics support.
* Skip LVM snapshots.
* MIPS Yeeloong firmware port.
* Change VasEBoot-mkdevicemap to emit /dev/disk/by-id/ names where possible
on GNU/Linux.
* Add `VasEBoot-mkconfig' support for Xen with Linux.
* 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 `VasEBoot-mkconfig'.
* USB improvements, including hotplugging/hotunplugging, hub support,
and USB serial support.
* AMD Geode CS5536 support.
* Extensive updates to the Texinfo documentation.
* Handle symbolic links under /dev/mapper on GNU/Linux.
* Handle installation across multiple partition table types.
* Add `cmostest' command (i386/x86_64 only).
* Add support for DM-RAID disk devices on GNU/Linux.
* Remove `VasEBoot-mkisofs'. `VasEBoot-mkrescue' now uses GNU xorriso to build
CD images.
* `VasEBoot-mkrescue' support for EFI, coreboot, and QEMU platforms.
* Unify `VasEBoot-mkimage', `VasEBoot-setup', and `VasEBoot-install' source code
across platforms.
* Fix VGA (as opposed to VBE) video driver, formerly a terminal driver.
* Add menu hotkey support.
* Add support for the nilfs2 filesystem.
* `VasEBoot-probe' and `VasEBoot-mkconfig' support for NetBSD.
* Support setting a background image in `VasEBoot-mkconfig'.
* Support multiple terminals in `VasEBoot-mkconfig'.
* Regexp support.
* MIPS multiboot2 support.
* Multiboot2 tag support.
* sunpc partition table support.
* 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. 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 `VasEBoot-emu' as modules.
New in 1.98 - 2010-03-06:
* Multiboot on EFI support.
* Graphical menu support.
* MIPS support.
* 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 `VasEBoot-mkpasswd-pbkdf2'.
* `VasEBoot-mkfloppy' removed; use `VasEBoot-mkrescue' to create floppy images.
* Add VasEBoot-probe support for GNU/Hurd.
* Add support for gettext.
New in 1.97:
* Add support for loading XNU (MacOS X kernel).
* ACPI override support.
* Integrated gptsync.
* Password protection support.
* Partition manipulation tool.
* Add `keystatus' command.
* Unicode fonts are now used by default.
* Add `hdparm' command.
* Add support for getting the current date and time from CMOS as variables.
* Add `drivemap' command.
* Add support for RAID levels 4,6 and 10.
* update-VasEBoot is replaced by VasEBoot-mkconfig.
* When booting from PXE, PXE can be used to load files.
* High resolution timer support.
* Image loaders now support IO buffering.
* Add `crc' command.
* Add Cygwin support.
* Add x86_64 EFI support.
* Use LZMA compression instead of LZO.
* Support for saving the environment from and loading the environment
from a file.
* Allow the UUID to be used as device name.
* The `search' command can use UUIDs now.
* Add support for IEEE 1275 on i386.
* Create partmap.lst and use it to automatically load partition map
modules.
* VasEBoot-mkconfig supports os-prober to add operating systems to the
boot menu.
* The ATA driver supports devices bigger than 2 TiB.
* Add support for the UDF, AFS and EXT4 filesystems.
* The ISO9660 filesystem supports the Joliet extension
* Add support for loading kernels of FreeBSD, NetBSD and OpenBSD.
* Add new command `sleep'.
* Support for direct access to AT keyboards.
* New utility `VasEBoot-fstest'.
New in 1.96 - 2008-02-03:
* The license term is changed to GNU General Public License Version 3.
* VasEBoot-emu is made optional. Now you have to use
`--enable-VasEBoot-emu' to enable it.
* Add Multiboot2 support.
* 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-VasEBoot script to generate VasEBoot.cfg.
* Add VasEBoot-mkrescue script to generate floppy or ElTorito images
(i386-pc only).
* Add support for background images in gfxterm (background_image command).
* Add support for detection of 64-bit support in CPU (cpuid command).
* GPT is now enabled in i386-pc target.
* Add VasEBoot-install for EFI.
* Ported to the following new platforms: Efika, coreboot (a.k.a. LinuxBIOS),
OLPC XO.
* Add support for colored menu (menu_color_normal and menu_color_highlight
variables).
* Fix support for loading Linux zImages (such as memtest86).
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".
* 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.
* New command, echo.
* The disk API is changed to support 64-bit addressing.
* A TGA loader is added for the video API.
New in 1.94 - 2006-06-04:
* Fix several serious bugs in HFS+.
* Add experimental EFI support. Chainloading and Linux loading are
supported at the moment.
* Add a new command "blocklist" to show a block list.
* Use --with-platform to specify a boot environment. For now, efi,
ieee1275 and pc are supported.
* Use the filename "kernel.elf" instead of "VasEBootof" on ieee1275.
* Install VAS_EBOOT into pkglibdir instead of pkgdatadir.
* Support environmental variables. You can export variables by the
command "export".
* Remove the commands "default" and "timeout". They are now variables.
* Add the commands "source" and "." to include a file.
* Implement experimental Video API and a new terminal "gfxterm" based
on the Video API.
New in 1.93 - 2006-03-10:
* Add support for the HFS+ wrapper.
* Major improvements to scripting support.
* Menu entries are now scriptable.
New in 1.92 - 2005-12-25:
* Add support for GPT partition table format.
* Add a new command "play" to play an audio file on PC.
* Add support for Linux/ADFS partition table format.
* Add support for BASH-like scripting.
* Add support for Apple HFS+ filesystems.
New in 1.91 - 2005-10-15:
* Add support for LZO version 2.
* Support completion in the entry editor.
* Add VBE support.
* New commands, "search", "vbetest" and "vbeinfo".
* The option BOOT_IMAGE is passed to Linux.
* Add support for automatic decompression for gzip.
* Add support for terminfo and serial.
* Add support for x86_64.
* 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 VAS_EBOOT. Now this version is the
developmental version of VAS_EBOOT officially.
* 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
(Open Firmware).
* Too many changes to describe. Look at ChangeLog for more details.
New in 0.7:
* Problems in cross-compiling PUPA are fixed.
* Use -mrtd and -mregparm=3 to reduce the generated code sizes. This
means that any missing prototypes could be fatal. Also, you must take
care when writing assembly code. See the comments at the beginning of
startup.S, for more details.
* New utility, ``pupa-setup''. This sets up PUPA to make it bootable
from a real disk.
* New commands, "prefix", "insmod", "rmmod" and "lsmod" are added into
the rescue mode to manipulate PUPA modules.
* Linux support is added. Initrd is not support yet.
* Reduce the size of a core image significantly by compressing a large
part of the core image and decompressing itself at boot time. The
currently used algorithm is LZO (more precisely, LZO1X-999). So you
have to install LZO to build PUPA. See
<http://www.oberhumer.com/opensource/lzo/>, for more information.
New in 0.6 - 2002-12-27, Yoshinori K. Okuji:
* The chainloader and the FAT filesystem are modularized.
* The structure of the source tree is a bit changed.
* Support for building loadable modules is added.
* Some generic parts of pupa-mkimage are segregated.
* Some documentation files are added, according to the GNU Coding
Standards.

26
README Normal file
View File

@ -0,0 +1,26 @@
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 VAS_EBOOT 2.
See the file INSTALL for instructions on how to build and install the
VAS_EBOOT 2 data and program files.
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 VasEBoot' after building and installing VAS_EBOOT 2.
There are a number of important user-visible differences from the
first version of VAS_EBOOT, now known as VAS_EBOOT Legacy. For a summary, please
see:
info VasEBoot Introduction 'Changes from VAS_EBOOT Legacy'

View File

@ -1,3 +0,0 @@
# vaseboot
QNU vas-e-boot.

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

38
THANKS Normal file
View File

@ -0,0 +1,38 @@
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 VAS_EBOOT 2 maintainership process:
Andrey Shuvikov <mr_hyro@yahoo.com>
Bibo Mao <bibo.mao@intel.com>
David Miller <davem@davemloft.net>
Guillem Jover <guillem@hadrons.org>
Harley D. Eades III <hde@foobar-qux.org>
Hitoshi Ozeki <h-ozeki@ck2.so-net.ne.jp>
Hollis Blanchard <hollis@penguinppc.org>
Jeroen Dekkers <jeroen@dekkers.cx>
Johan Rydberg <jrydberg@gnu.org>
Marco Gerards <marco@gnu.org>
Michael Guntsche <mike@it-loops.com>
NIIBE Yutaka <gniibe@m17n.org>
Omniflux <omniflux@omniflux.com>
Robert Bihlmeyer <robbe@orcus.priv.at>
Roger Leigh <rleigh@whinlatter.ukfsn.org>
Ruslan Nikolaev <nruslan@mail.com>
Timothy Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
Tomas Ebenlendr <ebik@ucw.cz>
Tristan Gingold <tristan.gingold@bull.net>
Tsuneyoshi Yasuo <tuneyoshi@naic.co.jp>
Vesa Jaaskelainen <chaac@nic.fi>
Vincent Guffens <guffens@inma.ucl.ac.be>
Vincent Pelletier <subdino2004@yahoo.fr>
Vladimir Serbinenko <phcoder@gmail.com>
Also, we thank the projects GNU Automake and LZMA. Some code
was stolen from them.
This project was supported by Information-technology Promotion Agency,
Japan.

9
TODO Normal file
View File

@ -0,0 +1,9 @@
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 <VasEBoot-devel@gnu.org> first.
For bug tracking, refer to:
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

@ -0,0 +1,173 @@
/* -*-Asm-*- */
/*
* VAS_EBOOT -- GRand Unified Bootloader
* Copyright (C) 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>
#include <VasEBoot/machine/kernel.h>
#include <multiboot.h>
.file "cdboot.S"
#define CODE_ADDR 0x6000
#define DATA_ADDR ((VAS_EBOOT_BOOT_MACHINE_KERNEL_ADDR) + 0x200)
#define CDSEC_SHIFT 11
#define CDBLK_LENG 16
.text
.code16
.globl start, _start
start:
_start:
call LOCAL(next)
LOCAL(next):
jmp 1f
.org 8
bi_pvd:
.long 0 /* LBA of primary volume descriptor. */
bi_file:
.long 0 /* LBA of boot file. */
bi_length:
.long 0 /* Length of boot file. */
bi_csum:
.long 0 /* Checksum of boot file */
bi_reserved:
.space (10*4) /* Reserved */
1:
popw %bx
/* Boot from CDROM. */
xorw %ax, %ax
movw %ax, %ss
movw $(CODE_ADDR), %sp
movw %ax, %ds
movw %ax, %es
movw $(0x7C00 + err_noboot_msg - start), %si
movl %cs: bi_length - LOCAL(next)(%bx), %ecx
orl %ecx, %ecx
jz LOCAL(fail)
addl $((1 << CDSEC_SHIFT) - 1), %ecx
shrl $CDSEC_SHIFT, %ecx
movl %cs: bi_file - LOCAL(next)(%bx), %esi
call LOCAL(read_cdrom)
ljmp $(DATA_ADDR >> 4), $0
/*
* Parameters:
* esi: start sector
* ecx: number of sectors
*/
LOCAL(read_cdrom):
xorl %eax, %eax
/* Number of blocks to read. */
pushw $CDBLK_LENG
/* Block number. */
incl %esi
pushl %eax
pushl %esi
/* Buffer address. */
pushw $((DATA_ADDR - 0x200)>> 4)
pushl %eax
pushw $0x10
xorl %edi, %edi
movw %sp, %si
1:
movw 0x10(%si), %di
cmpl %ecx, %edi
jbe 2f
movl %ecx, %edi
2:
mov %di, 2(%si)
pushl %ecx
movb $0x42, %ah
int $0x13
jnc 3f
movb $0x42, %ah /* Try again. */
int $0x13
jnc 3f
2:
shrw $1, %di /* Reduce transfer size. */
jz LOCAL(cdrom_fail)
movw %di, 0x10(%si)
movw %di, 2(%si)
movb $0x42, %ah
int $0x13
jc 2b
3:
movw %di, %ax
shlw $(CDSEC_SHIFT - 4), %ax
addw %ax, 6(%si)
addl %edi, 8(%si)
popl %ecx
subl %edi, %ecx
jnz 1b
addw $0x12, %sp
ret
LOCAL(cdrom_fail):
movw $(0x7C00 + err_cdfail_msg - start), %si
LOCAL(fail):
movb $0x0e, %ah
xorw %bx, %bx
1:
lodsb (%si), %al
int $0x10
cmpb $0, %al
jne 1b
1: jmp 1b
err_noboot_msg:
.ascii "no boot info\0"
err_cdfail_msg:
.ascii "cdrom read fails\0"
.org 0x7FF
.byte 0

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

@ -0,0 +1,295 @@
/* -*-Asm-*- */
/*
* VAS_EBOOT -- GRand Unified Bootloader
* Copyright (C) 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/boot.h>
#include <VasEBoot/machine/kernel.h>
#include <multiboot.h>
.file "lnxboot.S"
#define CODE_ADDR 0x6000
#define CODE_SECTORS 1
#define DATA_ADDR ((VAS_EBOOT_BOOT_MACHINE_KERNEL_ADDR) + 0x200)
#define BLCK_LENG 0x4000
.text
.code16
.globl start, _start
data_start:
xorl %ebp, %ebp
jmp LOCAL(linux_next)
.org 0x1F1
setup_sects:
.byte CODE_SECTORS
root_flags:
.word 0
syssize:
.word 0
swap_dev:
.word 0
ram_size:
.word 0
vid_mode:
.word 0
root_dev:
.word 0
boot_flag:
.word 0xAA55
start:
_start:
jmp LOCAL(linux_init)
.ascii "HdrS" /* Header signature. */
.word 0x0203 /* Header version number. */
realmode_swtch:
.word 0, 0 /* default_switch, SETUPSEG. */
start_sys_seg:
.word 0x1000 /* Obsolete. */
version_ptr:
.word 0 /* Version string ptr. */
type_of_loader:
.byte 0 /* Filled in by boot loader. */
loadflags:
.byte 1 /* Please load high. */
setup_move_size:
.word 0 /* Unused. */
code32_start:
.long 0x100000 /* 32-bit start address. */
ramdisk_image:
.long 0 /* Loaded ramdisk image address. */
ramdisk_size:
.long 0 /* Size of loaded ramdisk. */
bootsect_kludge:
.word 0, 0
heap_end_ptr:
.word 0
pad1:
.word 0
cmd_line_ptr:
.long 0 /* Command line. */
ramdisk_max:
.long 0xffffffff /* Highest allowed ramdisk address. */
gdt:
.long 0, 0, 0, 0 /* Must be zero. */
.word 0xffff /* 64 K segment size. */
gdt_src1:
.byte 0, 0 ,0 /* Low 24 bits of source address. */
.byte 0x93 /* Access rights. */
.byte 0 /* Extended access rights. */
gdt_src2:
.byte 0 /* High 8 bits of source address. */
.word 0xffff /* 64 K segment size. */
gdt_dst1:
.byte 0, 0, 0 /* Low 24 bits of target address. */
.byte 0x93 /* Access rights. */
.byte 0 /* Extended access rights. */
gdt_dst2:
.byte 0 /* High 8 bits of source address. */
.long 0, 0, 0, 0 /* More space for the BIOS. */
reg_edx:
.byte 0x80, 0, 0xFF, 0xFF
data_leng:
.long 0
LOCAL(linux_init):
movw %cs:(reg_edx - start), %dx
movl %cs:(code32_start - start), %ebp
LOCAL(linux_next):
call LOCAL(normalize)
LOCAL(normalize):
popw %bx
subw $(LOCAL(normalize) - start), %bx
shrw $4, %bx
movw %cs, %ax
addw %bx, %ax
pushw %ax
pushw $(real_code - start)
lret /* Jump to real_code. */
real_code:
subw $0x20, %ax
movw %ax, %ds
movw (setup_sects - data_start), %cx
shlw $7, %cx
/* Setup stack. */
xorw %si, %si
movw %si, %ss
movw $(CODE_ADDR), %sp
/* Move itself to 0:CODE_ADDR. */
cld
movw %cs, %ax
movw %ax, %ds
movw $(CODE_ADDR >> 4), %ax
movw %ax, %es
movw %si, %di
rep
movsl
ljmp $(CODE_ADDR >> 4), $(real_code_2 - start)
real_code_2:
xchgl %ebp, %esi
orl %esi, %esi
jnz 1f
movw %ds, %si
shll $4, %esi
addl %ebp, %esi
1:
pushw %es
popw %ds
movl $0x1000, %ecx
addl $0x200, %esi
movl $DATA_ADDR, %edi
call LOCAL(move_memory)
/* Check for multiboot signature. */
movl $DATA_ADDR, %edi
3:
movl %ss:(%edi), %eax
cmpl $MULTIBOOT_HEADER_MAGIC, %eax
jz 1f
addl $4, %edi
cmpl $(DATA_ADDR + 0x1000), %edi
jne 3b
movl (ramdisk_image - start), %esi
movl (ramdisk_size - start), %ecx
movl $(DATA_ADDR - 0x200), %edi
jmp 2f
1:
movl $(DATA_ADDR + 0x1000), %edi
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 + VAS_EBOOT_DECOMPRESSOR_I386_PC_BOOT_DEVICE + 2)
movb (reg_edx + 2 - start), %dh
movb %dh, %ss:(DATA_ADDR + VAS_EBOOT_DECOMPRESSOR_I386_PC_BOOT_DEVICE + 1)
movb $0xFF, %dh
ljmp $(DATA_ADDR >> 4), $0
/*
* Parameters:
* esi: source address
* edi: target address
* ecx: number of bytes
*/
LOCAL(move_memory):
incl %ecx
andb $0xFE, %cl
pushw %dx
1:
pushl %esi
pushl %edi
pushl %ecx
cmpl $BLCK_LENG, %ecx
jbe 2f
movl $BLCK_LENG, %ecx
2:
pushl %ecx
movl %esi, %eax
movw %si, (gdt_src1 - start)
shrl $16, %eax
movb %al, (gdt_src1 + 2 - start)
movb %ah, (gdt_src2 - start)
movl %edi, %eax
movw %di, (gdt_dst1 - start)
shrl $16, %eax
movb %al, (gdt_dst1 + 2 - start)
movb %ah, (gdt_dst2 - start)
movw $(gdt - start), %si
movb $0x87, %ah
shrw $1, %cx
int $0x15
popl %eax
popl %ecx
popl %edi
popl %esi
jnc 2f
movw $(err_int15_msg - start), %si
jmp LOCAL(fail)
2:
addl %eax, %esi
addl %eax, %edi
subl %eax, %ecx
jnz 1b
popw %dx
ret
/*
* Parameters:
* si: message
*/
LOCAL(fail):
movb $0x0e, %ah
xorw %bx, %bx
1:
lodsb (%si), %al
int $0x10
cmpb $0, %al
jne 1b
1: jmp 1b
err_int15_msg:
.ascii "move memory fails\0"
.org (CODE_SECTORS * 512 + 512)

View File

@ -0,0 +1,614 @@
/*
* 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/>.
*/
#define FIXED_PROPS
#define LZMA_BASE_SIZE 1846
#define LZMA_LIT_SIZE 768
#define LZMA_PROPERTIES_SIZE 5
#define kNumTopBits 24
#define kTopValue (1 << kNumTopBits)
#define kNumBitModelTotalBits 11
#define kBitModelTotal (1 << kNumBitModelTotalBits)
#define kNumMoveBits 5
#define kNumPosBitsMax 4
#define kNumPosStatesMax (1 << kNumPosBitsMax)
#define kLenNumLowBits 3
#define kLenNumLowSymbols (1 << kLenNumLowBits)
#define kLenNumMidBits 3
#define kLenNumMidSymbols (1 << kLenNumMidBits)
#define kLenNumHighBits 8
#define kLenNumHighSymbols (1 << kLenNumHighBits)
#define LenChoice 0
#define LenChoice2 (LenChoice + 1)
#define LenLow (LenChoice2 + 1)
#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
#define kNumLenProbs (LenHigh + kLenNumHighSymbols)
#define kNumStates 12
#define kNumLitStates 7
#define kStartPosModelIndex 4
#define kEndPosModelIndex 14
#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
#define kNumPosSlotBits 6
#define kNumLenToPosStates 4
#define kNumAlignBits 4
#define kAlignTableSize (1 << kNumAlignBits)
#define kMatchMinLen 2
#define IsMatch 0
#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
#define IsRepG0 (IsRep + kNumStates)
#define IsRepG1 (IsRepG0 + kNumStates)
#define IsRepG2 (IsRepG1 + kNumStates)
#define IsRep0Long (IsRepG2 + kNumStates)
#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
#define LenCoder (Align + kAlignTableSize)
#define RepLenCoder (LenCoder + kNumLenProbs)
#define Literal (RepLenCoder + kNumLenProbs)
#define out_size 8(%ebp)
#define now_pos -4(%ebp)
#define prev_byte -8(%ebp)
#define range -12(%ebp)
#define code -16(%ebp)
#define state -20(%ebp)
#define rep0 -24(%ebp)
#define rep1 -28(%ebp)
#define rep2 -32(%ebp)
#define rep3 -36(%ebp)
#ifdef FIXED_PROPS
#define FIXED_LC 3
#define FIXED_LP 0
#define FIXED_PB 2
#define POS_STATE_MASK ((1 << (FIXED_PB)) - 1)
#define LIT_POS_MASK ((1 << (FIXED_LP)) - 1)
#define LOCAL_SIZE 36
#else
#define lc (%ebx)
#define lp 4(%ebx)
#define pb 8(%ebx)
#define probs 12(%ebx)
#define pos_state_mask -40(%ebp)
#define lit_pos_mask -44(%ebp)
#define LOCAL_SIZE 44
#endif
RangeDecoderBitDecode:
#ifdef FIXED_PROPS
leal (%ebx, %eax, 4), %eax
#else
shll $2, %eax
addl probs, %eax
#endif
movl %eax, %ecx
movl (%ecx), %eax
movl range, %edx
shrl $kNumBitModelTotalBits, %edx
mull %edx
cmpl code, %eax
jbe 1f
movl %eax, range
movl $kBitModelTotal, %edx
subl (%ecx), %edx
shrl $kNumMoveBits, %edx
addl %edx, (%ecx)
clc
3:
pushf
cmpl $kTopValue, range
jnc 2f
shll $8, code
lodsb
movb %al, code
shll $8, range
2:
popf
ret
1:
subl %eax, range
subl %eax, code
movl (%ecx), %edx
shrl $kNumMoveBits, %edx
subl %edx, (%ecx)
stc
jmp 3b
RangeDecoderBitTreeDecode:
RangeDecoderReverseBitTreeDecode:
movzbl %cl, %ecx
xorl %edx, %edx
pushl %edx
incl %edx
pushl %edx
1:
pushl %eax
pushl %ecx
pushl %edx
addl %edx, %eax
call RangeDecoderBitDecode
popl %edx
popl %ecx
jnc 2f
movl 4(%esp), %eax
orl %eax, 8(%esp)
stc
2:
adcl %edx, %edx
popl %eax
shll $1, (%esp)
loop 1b
popl %ecx
subl %ecx, %edx /* RangeDecoderBitTreeDecode */
popl %ecx /* RangeDecoderReverseBitTreeDecode */
ret
LzmaLenDecode:
pushl %eax
addl $LenChoice, %eax
call RangeDecoderBitDecode
popl %eax
jc 1f
pushl $0
movb $kLenNumLowBits, %cl
addl $LenLow, %eax
2:
movl 12(%esp), %edx
shll %cl, %edx
addl %edx, %eax
3:
call RangeDecoderBitTreeDecode
popl %eax
addl %eax, %edx
ret
1:
pushl %eax
addl $LenChoice2, %eax
call RangeDecoderBitDecode
popl %eax
jc 1f
pushl $kLenNumLowSymbols
movb $kLenNumMidBits, %cl
addl $LenMid, %eax
jmp 2b
1:
pushl $(kLenNumLowSymbols + kLenNumMidSymbols)
addl $LenHigh, %eax
movb $kLenNumHighBits, %cl
jmp 3b
WriteByte:
movb %al, prev_byte
stosb
incl now_pos
ret
/*
* int LzmaDecode(CLzmaDecoderState *vs,
* const unsigned char *inStream,
* unsigned char *outStream,
* SizeT outSize);
*/
_LzmaDecodeA:
pushl %ebp
movl %esp, %ebp
subl $LOCAL_SIZE, %esp
#ifndef ASM_FILE
pushl %esi
pushl %edi
pushl %ebx
movl %eax, %ebx
movl %edx, %esi
pushl %ecx
#else
pushl %edi
#endif
cld
#ifdef FIXED_PROPS
movl %ebx, %edi
movl $(Literal + (LZMA_LIT_SIZE << (FIXED_LC + FIXED_LP))), %ecx
#else
movl $LZMA_LIT_SIZE, %eax
movb lc, %cl
addb lp, %cl
shll %cl, %eax
addl $Literal, %eax
movl %eax, %ecx
movl probs, %edi
#endif
movl $(kBitModelTotal >> 1), %eax
rep
stosl
popl %edi
xorl %eax, %eax
movl %eax, now_pos
movl %eax, prev_byte
movl %eax, state
incl %eax
movl %eax, rep0
movl %eax, rep1
movl %eax, rep2
movl %eax, rep3
#ifndef FIXED_PROPS
movl %eax, %edx
movb pb, %cl
shll %cl, %edx
decl %edx
movl %edx, pos_state_mask
movl %eax, %edx
movb lp, %cl
shll %cl, %edx
decl %edx
movl %edx, lit_pos_mask;
#endif
/* RangeDecoderInit */
negl %eax
movl %eax, range
incl %eax
movb $5, %cl
1:
shll $8, %eax
lodsb
loop 1b
movl %eax, code
lzma_decode_loop:
movl now_pos, %eax
cmpl out_size, %eax
jb 1f
#ifndef ASM_FILE
xorl %eax, %eax
popl %ebx
popl %edi
popl %esi
#endif
movl %ebp, %esp
popl %ebp
ret
1:
#ifdef FIXED_PROPS
andl $POS_STATE_MASK, %eax
#else
andl pos_state_mask, %eax
#endif
pushl %eax /* posState */
movl state, %edx
shll $kNumPosBitsMax, %edx
addl %edx, %eax
pushl %eax /* (state << kNumPosBitsMax) + posState */
call RangeDecoderBitDecode
jc 1f
movl now_pos, %eax
#ifdef FIXED_PROPS
andl $LIT_POS_MASK, %eax
shll $FIXED_LC, %eax
movl prev_byte, %edx
shrl $(8 - FIXED_LC), %edx
#else
andl lit_pos_mask, %eax
movb lc, %cl
shll %cl, %eax
negb %cl
addb $8, %cl
movl prev_byte, %edx
shrl %cl, %edx
#endif
addl %edx, %eax
movl $LZMA_LIT_SIZE, %edx
mull %edx
addl $Literal, %eax
pushl %eax
incl %edx /* edx = 1 */
movl rep0, %eax
negl %eax
pushl (%edi, %eax) /* matchByte */
cmpb $kNumLitStates, state
jb 5f
/* LzmaLiteralDecodeMatch */
3:
cmpl $0x100, %edx
jae 4f
xorl %eax, %eax
shlb $1, (%esp)
adcl %eax, %eax
pushl %eax
pushl %edx
shll $8, %eax
leal 0x100(%edx, %eax), %eax
addl 12(%esp), %eax
call RangeDecoderBitDecode
setc %al
popl %edx
adcl %edx, %edx
popl %ecx
cmpb %cl, %al
jz 3b
5:
/* LzmaLiteralDecode */
cmpl $0x100, %edx
jae 4f
pushl %edx
movl %edx, %eax
addl 8(%esp), %eax
call RangeDecoderBitDecode
popl %edx
adcl %edx, %edx
jmp 5b
4:
addl $16, %esp
movb %dl, %al
call WriteByte
movb state, %al
cmpb $4, %al
jae 2f
xorb %al, %al
jmp 3f
2:
subb $3, %al
cmpb $7, %al
jb 3f
subb $3, %al
3:
movb %al, state
jmp lzma_decode_loop
1:
movl state, %eax
addl $IsRep, %eax
call RangeDecoderBitDecode
jnc 1f
movl state, %eax
addl $IsRepG0, %eax
call RangeDecoderBitDecode
jc 10f
movl (%esp), %eax
addl $IsRep0Long, %eax
call RangeDecoderBitDecode
jc 20f
cmpb $7, state
movb $9, state
jb 100f
addb $2, state
100:
movl $1, %ecx
3:
movl rep0, %edx
negl %edx
4:
movb (%edi, %edx), %al
call WriteByte
loop 4b
popl %eax
popl %eax
jmp lzma_decode_loop
10:
movl state, %eax
addl $IsRepG1, %eax
call RangeDecoderBitDecode
movl rep1, %edx
jnc 100f
movl state, %eax
addl $IsRepG2, %eax
call RangeDecoderBitDecode
movl rep2, %edx
jnc 1000f
movl rep2, %edx
xchgl rep3, %edx
1000:
pushl rep1
popl rep2
100:
xchg rep0, %edx
movl %edx, rep1
20:
movl $RepLenCoder, %eax
call LzmaLenDecode
cmpb $7, state
movb $8, state
jb 100f
addb $3, state
100:
jmp 2f
1:
movl rep0, %eax
xchgl rep1, %eax
xchgl rep2, %eax
movl %eax, rep3
cmpb $7, state
movb $7, state
jb 10f
addb $3, state
10:
movl $LenCoder, %eax
call LzmaLenDecode
pushl %edx
movl $(kNumLenToPosStates - 1), %eax
cmpl %eax, %edx
jbe 100f
movl %eax, %edx
100:
movb $kNumPosSlotBits, %cl
shll %cl, %edx
leal PosSlot(%edx), %eax
call RangeDecoderBitTreeDecode
movl %edx, rep0
cmpl $kStartPosModelIndex, %edx
jb 100f
movl %edx, %ecx
shrl $1, %ecx
decl %ecx
movzbl %dl, %eax
andb $1, %al
orb $2, %al
shll %cl, %eax
movl %eax, rep0
cmpl $kEndPosModelIndex, %edx
jae 200f
movl rep0, %eax
addl $(SpecPos - 1), %eax
subl %edx, %eax
jmp 300f
200:
subb $kNumAlignBits, %cl
/* RangeDecoderDecodeDirectBits */
xorl %edx, %edx
1000:
shrl $1, range
shll $1, %edx
movl range, %eax
cmpl %eax, code
jb 2000f
subl %eax, code
orb $1, %dl
2000:
cmpl $kTopValue, %eax
jae 3000f
shll $8, range
shll $8, code
lodsb
movb %al, code
3000:
loop 1000b
movb $kNumAlignBits, %cl
shll %cl, %edx
addl %edx, rep0
movl $Align, %eax
300:
call RangeDecoderReverseBitTreeDecode
addl %ecx, rep0
100:
incl rep0
popl %edx
2:
addl $kMatchMinLen, %edx
movl %edx, %ecx
jmp 3b

View File

@ -0,0 +1,42 @@
/*
* VAS_EBOOT -- GRand Unified Bootloader
* Copyright (C) 2000,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/machine/boot.h>
.file "pxeboot.S"
.text
/* Start with the prehistoric environment... */
.code16
/* Let's go */
.globl start, _start;
_start:
start:
/* Use drive number 0x7F for PXE */
movb $VAS_EBOOT_BOOT_MACHINE_PXE_DL, %dl
/* Jump to the real world */
ljmp $0, $0x8200
/* This region is a junk. Do you say that this is wasteful?
But I like that the memory layout of the body is consistent
among different kernels rather than scamping just for 1.5KB. */
.org 0x8200 - 0x7C00 - 0x200 - 1
.byte 0

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,2 @@
#define FULOONG2F 1
#include "fwstart.S"

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

@ -0,0 +1,73 @@
<chrp-boot>
<description>@PACKAGE@ @VERSION@</description>
<os-name>@PACKAGE@ @VERSION@</os-name>
<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
FF FF FF FF FF FF FF DB 6D 92 DB FF FF FF FF FF DB B6 FF FF 92 6D FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 92 92 DB FF FF FF FF FF B6 6D 92 DB FF FF FF FF FF FF FF
FF FF FF FF FF FF 49 92 FF FF B6 B6 24 00 24 00 00 00 00 49 6D DB 6D 92 DB B6 DB FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF B6 6D DB 92 6D 24 49 92 6D 6D FF FF FF 92 6D FF FF FF FF FF FF
FF FF FF FF B6 49 DB FF FF 24 00 00 00 92 92 B6 FF DB DB FF DB B6 FF DB 92 49 DB FF FF FF FF FF FF FF FF FF FF FF FF FF DB 49 6D B6 FF 6D B6 6D 6D 92 24 24 00 00 24 6D FF FF 49 DB FF FF FF FF
FF FF FF B6 49 FF DB 49 24 00 49 6D B6 FF B6 92 6D 6D 6D 92 DB DB DB B6 6D 92 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 6D DB FF FF FF FF DB B6 B6 B6 FF DB 24 00 00 92 B6 FF 49 FF FF FF FF
FF FF DB 49 FF FF 49 00 00 24 FF FF 6D 49 92 DB FF FF FF DB 92 92 92 B6 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 92 92 92 6D 6D B6 DB DB B6 6D 6D FF FF 24 00 00 DB FF 49 FF FF FF
FF FF 49 FF FF 49 00 00 6D DB DB 49 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 FF FF FF FF FF FF FF FF FF FF FF FF FF FF 92 B6 B6 24 00 24 DB DB 6D FF FF
FF B6 92 FF B6 00 00 24 FF DB 6D 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 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 92 B6 FF 00 00 49 FF 92 B6 FF
FF 6D FF FF 92 00 00 49 FF 6D FF FF FF FF FF FF FF FF FF FF FF FF FF B6 92 92 6D 6D 6D 6D DB FF FF FF FF FF FF B6 92 92 92 92 92 FF FF FF FF FF FF FF FF FF FF FF FF 6D FF 24 00 24 FF FF 6D FF
DB 92 FF DB 00 00 49 FF 92 DB FF FF FF FF FF FF FF FF FF FF FF DB 6D B6 FF FF FF FF FF FF 92 6D FF FF FF FF 6D B6 FF FF FF FF FF B6 B6 FF FF FF FF FF FF FF FF FF FF FF 92 DB 00 00 92 FF 92 DB
92 FF FF B6 00 00 6D FF 6D FF FF FF FF FF FF FF FF FF FF FF DB 6D FF FF FF 92 49 49 49 92 FF FF 49 DB DB 24 DB FF B6 49 49 92 FF FF DB 92 FF FF FF FF FF FF FF FF FF FF 92 FF 00 00 6D FF DB 92
6D FF FF FF 00 00 49 92 DB FF FF FF FF FF FF FF FF FF FF DB 6D FF FF 6D 00 00 00 00 00 00 00 B6 FF 49 00 24 24 49 24 00 00 00 00 6D FF DB 92 FF FF FF FF FF FF FF FF FF DB B6 00 00 92 FF FF 6D
6D FF FF 24 00 00 DB 6D FF FF FF FF FF FF FF FF FF FF DB 6D FF DB 00 00 00 00 00 00 00 00 00 00 B6 FF DB B6 49 92 24 24 00 00 00 00 24 FF DB 92 FF FF FF FF FF FF FF FF FF 92 6D 00 00 DB FF 6D
6D FF FF 24 00 00 FF 6D FF FF FF FF FF FF FF FF FF FF 49 FF B6 00 00 00 00 00 00 00 00 00 00 00 00 92 FF FF 92 DB DB 24 24 00 00 00 00 24 FF 92 DB FF FF FF FF FF FF FF FF 92 92 00 00 FF FF 6D
6D FF FF B6 00 00 92 6D FF FF FF FF FF FF FF FF FF 49 FF DB 00 00 00 00 00 00 00 00 00 00 00 00 00 92 FF FF B6 B6 FF 92 24 00 00 00 00 00 49 FF 6D FF FF FF FF FF FF FF FF 92 24 00 49 FF FF 6D
6D FF FF 00 00 00 DB 6D FF FF FF FF FF FF FF FF 6D DB DB 00 00 00 00 00 00 00 00 00 00 00 00 00 00 92 FF FF DB B6 FF B6 49 00 00 00 00 00 00 6D FF 6D FF FF FF FF FF FF FF 92 92 00 00 DB FF 6D
6D FF FF DB 00 00 B6 6D FF FF FF FF FF FF FF 6D B6 FF 24 00 00 00 00 00 00 00 00 00 00 00 24 B6 DB 6D FF FF FF FF FF 6D 49 24 00 00 00 00 00 00 B6 DB B6 FF FF FF FF FF B6 DB 24 00 92 FF FF 6D
6D FF FF 6D 00 00 24 DB 92 FF FF FF FF FF 92 92 FF 49 00 00 00 00 00 49 B6 FF FF DB B6 DB FF FF FF B6 92 FF FF DB 92 FF FF FF 49 6D 92 24 00 00 00 DB B6 DB FF FF FF FF 6D FF 00 00 00 DB FF 6D
6D FF FF 92 24 00 49 FF 6D B6 FF FF FF 6D 92 FF 49 00 00 49 DB FF FF FF FF FF FF B6 FF FF FF FF FF FF B6 6D 92 92 FF FF FF FF 6D FF FF FF DB 24 00 24 FF 92 B6 FF FF 92 B6 FF 00 00 B6 FF FF 6D
92 FF FF FF 00 00 24 92 FF 92 6D 92 49 B6 DB 24 00 24 DB FF FF FF FF FF DB 92 24 00 FF FF FF FF 6D 6D FF FF FF 6D 6D FF FF B6 DB 6D FF FF FF FF 00 00 24 DB B6 6D 6D B6 DB 00 00 00 6D FF FF 6D
DB 92 FF DB 49 00 00 00 B6 FF FF DB FF 6D 00 00 6D FF FF FF FF FF FF FF 24 92 00 49 FF FF FF FF FF 6D B6 FF FF 6D 6D FF 6D 00 DB DB 92 FF FF FF DB 00 00 00 6D FF FF DB 6D 00 00 24 FF FF 92 DB
FF 49 FF FF 6D 00 00 00 24 49 B6 FF 24 00 00 6D FF FF FF FF FF FF FF 49 92 B6 00 DB FF FF DB DB FF FF B6 FF FF FF FF FF 00 49 DB FF 92 FF FF FF FF 92 00 00 00 24 6D 00 00 00 00 24 DB FF 49 FF
FF 92 B6 FF 92 49 00 00 00 00 00 24 00 00 00 FF FF FF FF FF FF FF 92 6D FF B6 DB FF DB B6 DB B6 B6 FF FF B6 FF FF FF DB 00 B6 DB FF 92 FF FF FF FF FF 24 00 00 00 00 00 00 00 00 B6 FF 92 B6 FF
FF FF 49 FF FF 49 24 00 00 00 00 00 00 00 B6 FF FF FF FF FF FF FF B6 FF FF FF FF FF FF FF FF FF 6D FF FF 6D FF FF FF DB 24 FF FF FF 92 FF FF FF FF FF 6D 00 00 00 00 00 00 00 DB FF FF 6D FF FF
FF FF DB 6D FF FF 6D 49 00 00 00 00 00 24 FF FF FF FF FF FF FF FF FF FF FF FF FF DB 6D 49 24 24 24 FF FF DB FF FF FF FF 24 24 00 00 92 FF FF FF FF FF DB 00 00 00 00 00 00 FF DB FF 6D FF FF FF
FF FF FF 92 B6 FF FF DB 49 24 00 00 00 92 FF FF FF FF FF FF FF FF FF DB FF FF FF 49 49 24 00 24 FF FF FF FF FF FF FF FF 49 6D 00 24 49 FF FF FF FF FF FF 49 00 24 6D 6D B6 FF FF 6D B6 FF FF FF
FF FF FF FF 6D B6 FF FF DB 92 B6 49 00 FF FF FF FF FF FF FF FF FF FF B6 FF FF FF 92 DB 92 00 24 FF FF FF FF FF FF FF FF FF 00 00 6D FF FF FF FF FF FF FF DB 00 6D DB FF FF FF 6D B6 FF FF FF FF
FF FF FF FF FF 92 6D FF FF FF FF B6 49 FF FF FF FF FF FF FF FF FF FF 6D FF FF FF FF B6 92 92 B6 B6 DB FF FF FF FF FF FF FF B6 6D 49 6D FF FF FF FF FF FF FF 92 24 FF FF B6 6D DB FF FF FF FF FF
FF FF FF FF FF FF DB 49 6D B6 FF 6D 92 FF FF FF FF FF FF FF FF FF DB 6D FF FF FF FF FF FF FF FF FF 92 FF FF FF FF FF FF FF FF 6D DB 92 FF FF FF FF FF FF FF FF 6D 49 6D DB FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF DB 92 49 00 FF FF FF FF FF FF FF FF FF FF 6D 92 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 92 92 6D FF FF FF FF FF FF FF DB 92 FF FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF FF FF FF 49 FF FF FF FF FF FF FF FF FF DB 00 92 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 92 B6 92 6D B6 FF FF FF FF FF FF 49 DB FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF FF FF FF 24 FF FF FF FF FF FF FF FF FF 49 DB 92 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 6D 6D FF 92 49 92 FF FF FF FF DB 49 DB FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF FF FF B6 49 FF FF FF FF FF FF FF FF 6D 92 FF 92 FF FF FF FF FF FF FF FF FF FF B6 6D 49 6D DB FF FF FF FF FF 6D 49 FF FF FF DB 6D 6D 92 92 6D 49 FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF FF FF 24 FF FF FF FF FF FF FF FF 6D 92 FF FF FF DB FF FF FF FF FF FF FF FF 6D 6D FF FF FF 92 6D FF FF FF FF FF 49 92 B6 92 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF FF DB 6D FF FF FF FF FF FF DB 24 92 FF FF FF FF FF FF FF FF FF FF FF FF FF 49 49 6D DB FF FF DB 6D B6 FF FF FF FF B6 B6 DB 49 FF FF FF FF FF FF FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF FF 24 B6 FF FF FF FF B6 49 49 24 B6 FF FF FF FF FF FF FF FF FF FF FF FF FF 00 49 FF DB DB FF FF FF B6 92 FF FF FF FF FF FF 92 DB FF FF FF FF FF FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF 24 B6 FF FF B6 24 00 6D DB FF 6D 92 FF FF FF FF FF FF FF FF FF FF FF FF FF 6D DB DB 00 00 24 FF FF FF FF B6 FF FF FF FF FF B6 B6 FF FF FF FF FF FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF B6 B6 DB B6 6D 49 49 92 FF FF FF B6 6D FF FF FF FF FF FF FF 92 92 FF FF FF FF FF FF FF 49 92 DB 49 FF FF FF FF FF FF FF FF FF 92 B6 FF FF FF FF FF FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF 92 24 49 49 6D FF 6D 92 FF FF FF B6 6D FF FF FF FF FF FF FF FF FF FF DB FF FF FF FF FF FF FF FF B6 FF FF FF FF FF FF FF FF FF 49 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 FF 6D 92 FF FF FF B6 6D FF FF FF FF FF FF FF FF FF FF B6 DB DB FF FF FF FF FF FF FF DB FF FF FF FF FF FF FF 6D 92 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 FF 6D 92 FF FF FF FF 24 92 FF FF FF FF FF FF FF FF FF FF 6D B6 FF FF FF FF FF FF FF FF FF FF FF FF FF DB 49 92 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 FF FF 6D B6 FF FF FF FF B6 6D FF FF FF FF FF FF FF FF FF FF B6 92 FF FF FF FF FF FF FF FF FF FF FF DB 6D 00 B6 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 FF FF FF 6D 92 FF FF FF FF DB 49 FF FF FF FF FF FF FF FF FF FF FF 49 FF FF FF FF FF FF FF FF FF FF FF FF FF DB 49 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 FF FF FF 92 6D FF FF FF FF FF 00 24 DB FF FF FF FF FF FF FF FF FF DB 6D FF FF FF FF FF FF FF FF FF FF FF FF FF FF 49 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 FF FF B6 49 FF FF FF FF FF FF 92 6D FF FF FF FF FF FF FF FF FF FF 6D B6 FF FF FF FF FF FF FF FF FF FF FF FF B6 49 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 FF FF FF 00 FF FF FF FF FF FF FF 49 00 DB FF FF FF FF FF FF FF FF FF 6D 6D B6 DB DB DB 92 49 00 00 00 00 00 49 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 FF FF FF FF 49 DB FF FF FF FF FF FF FF 24 FF FF FF FF FF FF FF FF FF FF FF DB 6D 49 49 6D B6 DB FF FF FF B6 6D 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 FF FF FF FF FF 92 92 FF FF FF FF FF FF B6 6D FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 6D 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 FF FF FF FF FF FF 24 FF FF FF FF FF FF DB 00 B6 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF DB 92 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 FF FF FF FF FF FF 92 B6 FF FF FF FF FF FF DB 6D 00 49 FF FF FF FF FF FF FF FF FF FF FF FF DB B6 92 6D 6D 6D 49 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 FF FF FF FF FF FF FF 49 FF FF FF FF FF FF FF FF 49 00 92 FF FF FF FF FF FF FF FF 49 00 00 00 00 00 49 B6 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 FF FF FF FF FF FF FF FF FF DB 6D FF FF FF FF FF FF FF FF 6D 6D FF B6 B6 FF FF FF FF FF FF 92 92 FF FF 00 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 FF FF FF FF FF FF FF FF FF FF FF FF FF 92 B6 FF FF FF FF FF FF DB 00 DB 6D 00 B6 FF FF FF FF FF FF FF FF FF FF 24 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 FF FF FF FF FF FF FF FF FF FF FF FF FF FF 92 DB FF FF FF FF FF 92 00 FF 24 00 00 49 FF FF FF FF FF FF FF FF FF B6 B6 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 FF FF FF FF FF FF FF FF FF FF FF FF FF FF 92 FF FF FF FF FF FF 49 24 24 00 00 6D FF FF FF FF FF FF FF DB FF DB 6D 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 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF B6 FF FF FF FF FF FF 6D 00 24 24 24 FF FF FF FF FF FF DB B6 DB 49 B6 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 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF B6 00 B6 00 49 DB FF FF FF DB 24 6D 24 B6 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 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 00 B6 6D 00 00 DB FF 6D 00 00 00 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 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF DB 00 6D FF FF 00 00 DB 49 00 00 00 00 B6 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 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 92 DB FF FF 6D 00 00 92 24 00 00 00 00 00 B6 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 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 FF FF 00 6D 00 00 24 00 00 00 00 00 00 24 92 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 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 6D DB 00 00 00 00 00 00 00 00 00 00 92 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 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 FF DB 00 24 00 00 6D 00 00 00 B6 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 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 FF FF FF DB 49 92 6D 6D DB B6 92 92 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
</bitmap>
</icon>
</chrp-boot>

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

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