diff options
Diffstat (limited to 'qemu/roms/openbios')
667 files changed, 119030 insertions, 0 deletions
diff --git a/qemu/roms/openbios/.gitignore b/qemu/roms/openbios/.gitignore new file mode 100644 index 000000000..38e6dd89e --- /dev/null +++ b/qemu/roms/openbios/.gitignore @@ -0,0 +1,3 @@ +obj-* +.stgit-* +config-host.mak diff --git a/qemu/roms/openbios/COPYING b/qemu/roms/openbios/COPYING new file mode 100644 index 000000000..8a6932a7c --- /dev/null +++ b/qemu/roms/openbios/COPYING @@ -0,0 +1,341 @@ + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) 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 +this service 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 make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. 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. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute 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 and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +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 +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the 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 a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, 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. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE 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. + + 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 +convey 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) 19yy <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 2 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, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision 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, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + <signature of Ty Coon>, 1 April 1989 + Ty Coon, President of Vice + +This 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 Library General +Public License instead of this License. diff --git a/qemu/roms/openbios/Documentation/ChangeLog.arch b/qemu/roms/openbios/Documentation/ChangeLog.arch new file mode 100644 index 000000000..8213b28b2 --- /dev/null +++ b/qemu/roms/openbios/Documentation/ChangeLog.arch @@ -0,0 +1,1895 @@ +# do not edit -- automatically generated by arch changelog +# arch-tag: automatic-ChangeLog--stepan@openbios.org--devel/openbios--main--1.0 +# + +2006-04-26 11:52:05 GMT Stefan Reinauer <stepan@openbios.org> patch-26 + + Summary: + small gcc4 changes + Revision: + openbios--main--1.0--patch-26 + + lvalue stuff + + + modified files: + Documentation/ChangeLog.arch config/examples/x86_config.xml + kernel/bootstrap.c kernel/dict.c + + +2006-02-22 17:01:41 GMT Stefan Reinauer <stepan@openbios.org> patch-25 + + Summary: + make romheaders work on non linux systems + Revision: + openbios--main--1.0--patch-25 + + removes endian dependency and some signed/unsigned comparisons + + + + modified files: + Documentation/ChangeLog.arch utils/romheaders/Makefile + utils/romheaders/romheaders.c + + +2005-10-15 16:01:47 GMT Stefan Reinauer <stepan@openbios.org> patch-24 + + Summary: + toke fix: hex string handling + Revision: + openbios--main--1.0--patch-24 + + This revision fixes a bug in toke when creating hex definitions within strings. + It also contains a little documentation update. + + + removed files: + toke/.arch-ids/TODO.id toke/TODO + + modified files: + Documentation/ChangeLog.arch toke/ChangeLog toke/README + toke/scanner.c toke/toke.c + + +2005-10-05 18:26:56 GMT Stefan Reinauer <stepan@openbios.org> patch-23 + + Summary: + address change, second attempt + Revision: + openbios--main--1.0--patch-23 + + The correct address of FSF is: + + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + + + modified files: + COPYING Documentation/ChangeLog.arch + Documentation/kernel/COPYING drivers/adb.c drivers/adb.h + drivers/kbd.c drivers/kbd.h fs/grubfs/jfs.h fs/grubfs/xfs.h + toke/COPYING toke/Makefile toke/dictionary.c toke/dictionary.h + toke/emit.c toke/emit.h toke/macros.c toke/scanner.c + toke/stack.c toke/stack.h toke/stream.c toke/stream.h + toke/toke.c toke/toke.h utils/detok/COPYING + utils/detok/Makefile utils/detok/decode.c utils/detok/detok.c + utils/detok/detok.h utils/detok/dictionary.c + utils/detok/stream.c utils/detok/stream.h + utils/devbios/COPYING utils/devbios/bios.h + utils/devbios/bios_core.c utils/devbios/filesystem.c + utils/devbios/flashchips.c utils/devbios/flashchips.h + utils/devbios/pcisets.c utils/devbios/pcisets.h + utils/devbios/procfs.c utils/devbios/programming.c + utils/devbios/programming.h utils/fccc/COPYING + utils/romheaders/Makefile + + +2005-10-05 17:44:01 GMT Stefan Reinauer <stepan@openbios.org> patch-22 + + Summary: + Update FSF address all over the tree + Revision: + openbios--main--1.0--patch-22 + + The FSF moved to a new address this April already. The old address was + still in place in many files in the tree. Now we're up to date again ;) + + + modified files: + COPYING Documentation/ChangeLog.arch + Documentation/kernel/COPYING drivers/adb.c drivers/adb.h + drivers/kbd.c drivers/kbd.h utils/detok/COPYING + utils/detok/Makefile utils/detok/decode.c utils/detok/detok.c + utils/detok/detok.h utils/detok/dictionary.c + utils/detok/stream.c utils/detok/stream.h + utils/devbios/COPYING utils/devbios/bios.h + utils/devbios/bios_core.c utils/devbios/filesystem.c + utils/devbios/flashchips.c utils/devbios/flashchips.h + utils/devbios/pcisets.c utils/devbios/pcisets.h + utils/devbios/procfs.c utils/devbios/programming.c + utils/devbios/programming.h utils/fccc/COPYING + utils/romheaders/Makefile + + +2005-10-05 17:40:18 GMT Stefan Reinauer <stepan@openbios.org> patch-21 + + Summary: + fix two bugs in toke, update FSF address + Revision: + openbios--main--1.0--patch-21 + + * toke: fix signed/unsigned bug + * toke: error if maximum word count is exceeded + * toke: change FSF address to 51 Franklin St, Fifth Floor, Boston, MA, 02111-1301 USA + + + modified files: + Documentation/ChangeLog.arch toke/COPYING toke/ChangeLog + toke/Makefile toke/dictionary.c toke/dictionary.h toke/emit.c + toke/emit.h toke/macros.c toke/scanner.c toke/stack.c + toke/stack.h toke/stream.c toke/stream.h toke/toke.c + toke/toke.h + + +2005-10-02 12:18:38 GMT Stefan Reinauer <stepan@openbios.org> patch-20 + + Summary: + add preliminary floppy driver + Revision: + openbios--main--1.0--patch-20 + + This is a simple floppy driver, borrowed from linuxbios v1 + + + new files: + drivers/.arch-ids/floppy.c.id drivers/.arch-ids/floppy.h.id + drivers/floppy.c drivers/floppy.h + + modified files: + Documentation/ChangeLog.arch arch/x86/openbios.c + config/examples/x86_config.xml drivers/build.xml + + +2005-09-17 15:29:08 GMT Stefan Reinauer <stepan@openbios.org> patch-19 + + Summary: + merge openbios--xml--1.0--patch-48 back into openbios--main + Revision: + openbios--main--1.0--patch-19 + + finally merging the xml tree back to the main tree. Some things are missing + like a decent config tool (Kconfig?) But well.. + + Patches applied: + + * oxygene@openbios.org--2005/openbios--xml--1.0--base-0 + tag of stepan@openbios.org--devel/openbios--xml--1.0--patch-29 + + * oxygene@openbios.org--2005/openbios--xml--1.0--patch-1 + update openbios--xml with openbios--main + + * oxygene@openbios.org--2005/openbios--xml--1.0--patch-2 + change to word "dev" + + * stepan@openbios.org--devel/openbios--xml--1.0--base-0 + tag of stepan@openbios.org--devel/openbios--main--1.0--patch-14 + + * stepan@openbios.org--devel/openbios--xml--1.0--patch-1 + initial checkin + + * stepan@openbios.org--devel/openbios--xml--1.0--patch-2 + get briq building + + * stepan@openbios.org--devel/openbios--xml--1.0--patch-3 + latest changes. clean ppc building up, etc pp + + * stepan@openbios.org--devel/openbios--xml--1.0--patch-4 + checksum support + + * stepan@openbios.org--devel/openbios--xml--1.0--patch-5 + first merge of cross platform abstraction + + * stepan@openbios.org--devel/openbios--xml--1.0--patch-6 + more cross api changes + + * stepan@openbios.org--devel/openbios--xml--1.0--patch-7 + more cross api merges + + * stepan@openbios.org--devel/openbios--xml--1.0--patch-8 + + + * stepan@openbios.org--devel/openbios--xml--1.0--patch-9 + toke fixes + + * stepan@openbios.org--devel/openbios--xml--1.0--patch-10 + fix detok, v0.6.1 + + * stepan@openbios.org--devel/openbios--xml--1.0--patch-11 + release ready version + + * stepan@openbios.org--devel/openbios--xml--1.0--patch-12 + 2 flash chips supported + + * stepan@openbios.org--devel/openbios--xml--1.0--patch-13 + devbios: fix filesystem.c + + * stepan@openbios.org--devel/openbios--xml--1.0--patch-14 + fix devbios for 2.6.10. + + * stepan@openbios.org--devel/openbios--xml--1.0--patch-15 + small fixes for ppc and filesystems + + * stepan@openbios.org--devel/openbios--xml--1.0--patch-16 + cross api and other cleanups + + * stepan@openbios.org--devel/openbios--xml--1.0--patch-17 + activate central trampoline for bootstrapping + + * stepan@openbios.org--devel/openbios--xml--1.0--patch-18 + getting build process more into shape + + * stepan@openbios.org--devel/openbios--xml--1.0--patch-19 + cross api: 64->32bit cross compilation + + * stepan@openbios.org--devel/openbios--xml--1.0--patch-20 + only use cross.h during bootstrap. + + * stepan@openbios.org--devel/openbios--xml--1.0--patch-21 + cross api swapped endian support. + + * stepan@openbios.org--devel/openbios--xml--1.0--patch-22 + smaller fixes + + * stepan@openbios.org--devel/openbios--xml--1.0--patch-23 + fill in cylinders on non chs disks as well + + * stepan@openbios.org--devel/openbios--xml--1.0--patch-24 + fix NULL phandle problem + + * stepan@openbios.org--devel/openbios--xml--1.0--patch-25 + fix ppc dictionary cross compiling + + * stepan@openbios.org--devel/openbios--xml--1.0--patch-26 + small ppc pci update + + * stepan@openbios.org--devel/openbios--xml--1.0--patch-27 + first merge of pearpc target + + * stepan@openbios.org--devel/openbios--xml--1.0--patch-28 + fix pearpc nvram access + + * stepan@openbios.org--devel/openbios--xml--1.0--patch-29 + pearpc update + + * stepan@openbios.org--devel/openbios--xml--1.0--patch-30 + remove some gnuisms + + * stepan@openbios.org--devel/openbios--xml--1.0--patch-31 + merge from patrick, some smaller updates + + * stepan@openbios.org--devel/openbios--xml--1.0--patch-32 + add freebsd UFS driver (patch from Ed Schouten) + + * stepan@openbios.org--devel/openbios--xml--1.0--patch-33 + two more missing files for UFS support.. + + * stepan@openbios.org--devel/openbios--xml--1.0--patch-34 + fix gnuish leftovers (&>) + + * stepan@openbios.org--devel/openbios--xml--1.0--patch-35 + small fix and ufs config file update + + * stepan@openbios.org--devel/openbios--xml--1.0--patch-36 + another one: fix build.xml for UFS + + * stepan@openbios.org--devel/openbios--xml--1.0--patch-37 + fix warnings in ufs driver + + * stepan@openbios.org--devel/openbios--xml--1.0--patch-38 + get strcpy right + + * stepan@openbios.org--devel/openbios--xml--1.0--patch-39 + start unifying video console code + + * stepan@openbios.org--devel/openbios--xml--1.0--patch-40 + first try for xbox console output + + * stepan@openbios.org--devel/openbios--xml--1.0--patch-41 + small preprocessor fix + + * stepan@openbios.org--devel/openbios--xml--1.0--patch-42 + fix -ldl issue for non-linux systems. + + * stepan@openbios.org--devel/openbios--xml--1.0--patch-43 + next try xbox console.. + + * stepan@openbios.org--devel/openbios--xml--1.0--patch-44 + remove xml namespace from base tag + + * stepan@openbios.org--devel/openbios--xml--1.0--patch-45 + drop video.c from ppc platform specific code + + * stepan@openbios.org--devel/openbios--xml--1.0--patch-46 + add load address masking to boot fbsd kernels + + * stepan@openbios.org--devel/openbios--xml--1.0--patch-47 + add openfirmware client interface example. + + * stepan@openbios.org--devel/openbios--xml--1.0--patch-48 + lots of endian fixes + + + new files: + .arch-ids/build.xml.id .arch-ids/config.xml.id + .arch-ids/rules.xml.id arch/.arch-ids/build.xml.id + arch/amd64/.arch-ids/build.xml.id arch/amd64/build.xml + arch/build.xml arch/ia64/.arch-ids/build.xml.id + arch/ia64/build.xml arch/ppc/.arch-ids/build.xml.id + arch/ppc/build.xml arch/ppc/pearpc/.arch-ids/=id + arch/ppc/pearpc/.arch-ids/console.c.id + arch/ppc/pearpc/.arch-ids/init.c.id + arch/ppc/pearpc/.arch-ids/kernel.c.id + arch/ppc/pearpc/.arch-ids/main.c.id + arch/ppc/pearpc/.arch-ids/methods.c.id + arch/ppc/pearpc/.arch-ids/pearpc.c.id + arch/ppc/pearpc/.arch-ids/pearpc.fs.id + arch/ppc/pearpc/.arch-ids/pearpc.h.id + arch/ppc/pearpc/.arch-ids/tree.c.id + arch/ppc/pearpc/.arch-ids/tree.fs.id + arch/ppc/pearpc/.arch-ids/vfd.c.id arch/ppc/pearpc/console.c + arch/ppc/pearpc/init.c arch/ppc/pearpc/kernel.c + arch/ppc/pearpc/main.c arch/ppc/pearpc/methods.c + arch/ppc/pearpc/pearpc.c arch/ppc/pearpc/pearpc.fs + arch/ppc/pearpc/pearpc.h arch/ppc/pearpc/tree.c + arch/ppc/pearpc/tree.fs arch/ppc/pearpc/vfd.c + arch/unix/.arch-ids/build.xml.id arch/unix/build.xml + arch/x86/.arch-ids/build.xml.id arch/x86/build.xml + arch/x86/xbox/.arch-ids/=id + arch/x86/xbox/.arch-ids/console.c.id + arch/x86/xbox/.arch-ids/methods.c.id arch/x86/xbox/console.c + arch/x86/xbox/methods.c build.xml config.xml + config/.arch-ids/=id config/examples/.arch-ids/=id + config/examples/.arch-ids/amd64_config.xml.id + config/examples/.arch-ids/amd64_rules.xml.id + config/examples/.arch-ids/cross-ppc_config.xml.id + config/examples/.arch-ids/cross-ppc_rules.xml.id + config/examples/.arch-ids/x86_config.xml.id + config/examples/.arch-ids/x86_rules.xml.id + config/examples/amd64_config.xml + config/examples/amd64_rules.xml + config/examples/cross-ppc_config.xml + config/examples/cross-ppc_rules.xml + config/examples/x86_config.xml config/examples/x86_rules.xml + config/scripts/.arch-ids/switch-arch.id + config/scripts/switch-arch config/xml/.arch-ids/=id + config/xml/.arch-ids/config-c.xsl.id + config/xml/.arch-ids/config-forth.xsl.id + config/xml/.arch-ids/dictionary.xsl.id + config/xml/.arch-ids/makefile.xsl.id + config/xml/.arch-ids/object.xsl.id + config/xml/.arch-ids/util.xsl.id + config/xml/.arch-ids/xinclude.xsl.id config/xml/config-c.xsl + config/xml/config-forth.xsl config/xml/dictionary.xsl + config/xml/makefile.xsl config/xml/object.xsl + config/xml/util.xsl config/xml/xinclude.xsl + drivers/.arch-ids/adb.c.id drivers/.arch-ids/adb.fs.id + drivers/.arch-ids/adb.h.id drivers/.arch-ids/build.xml.id + drivers/.arch-ids/cuda.c.id drivers/.arch-ids/cuda.h.id + drivers/.arch-ids/kbd.c.id drivers/.arch-ids/kbd.h.id + drivers/adb.c drivers/adb.fs drivers/adb.h drivers/build.xml + drivers/cuda.c drivers/cuda.h drivers/kbd.c drivers/kbd.h + forth/.arch-ids/build.xml.id + forth/admin/.arch-ids/build.xml.id forth/admin/build.xml + forth/bootstrap/.arch-ids/build.xml.id + forth/bootstrap/build.xml forth/build.xml + forth/debugging/.arch-ids/build.xml.id + forth/debugging/build.xml forth/device/.arch-ids/build.xml.id + forth/device/build.xml forth/lib/.arch-ids/build.xml.id + forth/lib/.arch-ids/preinclude.fs.id forth/lib/build.xml + forth/lib/preinclude.fs forth/packages/.arch-ids/build.xml.id + forth/packages/build.xml forth/system/.arch-ids/build.xml.id + forth/system/build.xml forth/testsuite/.arch-ids/build.xml.id + forth/testsuite/build.xml forth/util/.arch-ids/build.xml.id + forth/util/build.xml fs/.arch-ids/build.xml.id fs/build.xml + fs/grubfs/.arch-ids/build.xml.id + fs/grubfs/.arch-ids/fsys_ufs.c.id + fs/grubfs/.arch-ids/ufs_dinode.h.id + fs/grubfs/.arch-ids/ufs_fs.h.id fs/grubfs/build.xml + fs/grubfs/fsys_ufs.c fs/grubfs/ufs_dinode.h fs/grubfs/ufs_fs.h + fs/hfs/.arch-ids/build.xml.id fs/hfs/build.xml + fs/hfsplus/.arch-ids/build.xml.id fs/hfsplus/build.xml + include/.arch-ids/mconfig.h.id include/mconfig.h + include/ppc/.arch-ids/pci.h.id include/ppc/pci.h + kernel/.arch-ids/build.xml.id kernel/.arch-ids/cross.h.id + kernel/build.xml kernel/cross.h libc/.arch-ids/build.xml.id + libc/build.xml modules/.arch-ids/build.xml.id + modules/.arch-ids/console.c.id modules/.arch-ids/video.c.id + modules/build.xml modules/console.c modules/video.c rules.xml + toke/.arch-ids/Makefile.id toke/.arch-ids/build.xml.id + toke/Makefile toke/build.xml utils/ofclient/.arch-ids/=id + utils/ofclient/.arch-ids/Makefile.id + utils/ofclient/.arch-ids/README.id + utils/ofclient/.arch-ids/endian.h.id + utils/ofclient/.arch-ids/of1275.c.id + utils/ofclient/.arch-ids/of1275.h.id + utils/ofclient/.arch-ids/of1275_io.c.id + utils/ofclient/.arch-ids/ofclient.c.id utils/ofclient/Makefile + utils/ofclient/README utils/ofclient/endian.h + utils/ofclient/of1275.c utils/ofclient/of1275.h + utils/ofclient/of1275_io.c utils/ofclient/ofclient.c + + removed files: + .arch-ids/autogen.sh.id .arch-ids/configure.id + .arch-ids/setup_links.id arch/amd64/.arch-ids/Makefile.asm.id + arch/amd64/.arch-ids/Makefile.id arch/amd64/Makefile + arch/amd64/Makefile.asm arch/ia64/.arch-ids/Makefile.asm.id + arch/ia64/.arch-ids/Makefile.id arch/ia64/Makefile + arch/ia64/Makefile.asm arch/ppc/mol/.arch-ids/video.c.id + arch/ppc/mol/video.c arch/x86/.arch-ids/Makefile.asm.id + arch/x86/.arch-ids/Makefile.id arch/x86/Makefile + arch/x86/Makefile.asm autogen.sh config/.arch-ids/=id + config/.arch-ids/Makefile.defs.in.id + config/.arch-ids/Makefile.id + config/.arch-ids/Makefile.master.id + config/.arch-ids/Makefile.top.id + config/.arch-ids/Rules.forth.id config/.arch-ids/Rules.make.id + config/.arch-ids/configure.in.id config/Makefile + config/Makefile.defs.in config/Makefile.master + config/Makefile.top config/Rules.forth config/Rules.make + config/configure.in config/kconfig/.arch-ids/=id + config/kconfig/.arch-ids/Makefile.id + config/kconfig/.arch-ids/conf.c.id + config/kconfig/.arch-ids/confdata.c.id + config/kconfig/.arch-ids/expr.c.id + config/kconfig/.arch-ids/expr.h.id + config/kconfig/.arch-ids/lkc.h.id + config/kconfig/.arch-ids/lkc_proto.h.id + config/kconfig/.arch-ids/mconf.c.id + config/kconfig/.arch-ids/menu.c.id + config/kconfig/.arch-ids/symbol.c.id + config/kconfig/.arch-ids/zconf-l.l.id + config/kconfig/.arch-ids/zconf-y.y.id config/kconfig/Makefile + config/kconfig/conf.c config/kconfig/confdata.c + config/kconfig/expr.c config/kconfig/expr.h + config/kconfig/lkc.h config/kconfig/lkc_proto.h + config/kconfig/mconf.c config/kconfig/menu.c + config/kconfig/symbol.c config/kconfig/zconf-l.l + config/kconfig/zconf-y.y config/lxdialog/.arch-ids/=id + config/lxdialog/.arch-ids/Makefile.id + config/lxdialog/.arch-ids/checklist.c.id + config/lxdialog/.arch-ids/colors.h.id + config/lxdialog/.arch-ids/dialog.h.id + config/lxdialog/.arch-ids/inputbox.c.id + config/lxdialog/.arch-ids/lxdialog.c.id + config/lxdialog/.arch-ids/menubox.c.id + config/lxdialog/.arch-ids/msgbox.c.id + config/lxdialog/.arch-ids/textbox.c.id + config/lxdialog/.arch-ids/util.c.id + config/lxdialog/.arch-ids/yesno.c.id config/lxdialog/Makefile + config/lxdialog/checklist.c config/lxdialog/colors.h + config/lxdialog/dialog.h config/lxdialog/inputbox.c + config/lxdialog/lxdialog.c config/lxdialog/menubox.c + config/lxdialog/msgbox.c config/lxdialog/textbox.c + config/lxdialog/util.c config/lxdialog/yesno.c configure + drivers/.arch-ids/Makefile.id drivers/Makefile + forth/.arch-ids/Makefile.id forth/Makefile + forth/admin/.arch-ids/Makefile.id forth/admin/Makefile + forth/debugging/.arch-ids/Makefile.id forth/debugging/Makefile + forth/device/.arch-ids/Makefile.id forth/device/Makefile + forth/lib/.arch-ids/Makefile.id forth/lib/Makefile + forth/packages/.arch-ids/Makefile.id forth/packages/Makefile + forth/system/.arch-ids/Makefile.id forth/system/Makefile + forth/testsuite/.arch-ids/Makefile.id forth/testsuite/Makefile + forth/util/.arch-ids/Makefile.id forth/util/Makefile + fs/.arch-ids/Makefile.id fs/Makefile + fs/grubfs/.arch-ids/Makefile.id fs/grubfs/Makefile + fs/hfs/.arch-ids/Makefile.id fs/hfs/Makefile + fs/hfsplus/.arch-ids/Makefile.id fs/hfsplus/Makefile + kernel/.arch-ids/Makefile.id kernel/Makefile + libc/.arch-ids/Makefile.id libc/.arch-ids/byteorder.c.id + libc/Makefile libc/byteorder.c modules/.arch-ids/Makefile.id + modules/Makefile setup_links toke/.arch-ids/Makefile.id + toke/Makefile + + modified files: + Documentation/ChangeLog.arch Makefile README + arch/ppc/briq/briq.c arch/ppc/briq/init.c + arch/ppc/briq/kernel.c arch/ppc/mol/console.c arch/ppc/ofmem.c + arch/unix/Makefile arch/unix/plugins/Makefile arch/unix/unix.c + arch/x86/elfload.c arch/x86/multiboot.c arch/x86/openbios.c + arch/x86/sys_info.c drivers/ide.c drivers/pci.c drivers/pci.fs + forth/admin/banner.fs forth/admin/devices.fs + forth/bootstrap/bootstrap.fs forth/device/font.fs + fs/grubfs/Kconfig fs/grubfs/filesys.h fs/grubfs/fsys_ext2fs.c + fs/grubfs/fsys_reiserfs.c fs/grubfs/fsys_xfs.c + fs/grubfs/grubfs_fs.c include/amd64/io.h + include/libc/byteorder.h include/libc/stdlib.h + include/openbios/stack.h include/ppc/io.h include/ppc/types.h + include/x86/io.h include/x86/pci.h include/x86/types.h + kernel/bootstrap.c kernel/dict.c kernel/forth.c + kernel/include/dict.h kernel/internal.c kernel/primitives.c + modules/bindings.c modules/pc-parts.c toke/ChangeLog + toke/dictionary.c toke/dictionary.h toke/emit.c toke/emit.h + toke/macros.c toke/scanner.c toke/stack.c toke/stack.h + toke/stream.c toke/stream.h toke/toke.c toke/toke.h + utils/README utils/devbios/filesystem.c + utils/devbios/flashchips.c utils/devbios/pcisets.c + + renamed files: + arch/ppc/mol/.arch-ids/font_8x8.c.id + ==> modules/.arch-ids/font_8x8.c.id + arch/ppc/mol/font_8x8.c + ==> modules/font_8x8.c + dist/.arch-ids/=id + ==> utils/dist/.arch-ids/=id + dist/.arch-ids/openbios.spec.id + ==> utils/dist/.arch-ids/openbios.spec.id + dist/debian/.arch-ids/=id + ==> utils/dist/debian/.arch-ids/=id + dist/debian/.arch-ids/changelog.id + ==> utils/dist/debian/.arch-ids/changelog.id + dist/debian/.arch-ids/control.id + ==> utils/dist/debian/.arch-ids/control.id + dist/debian/.arch-ids/packages.id + ==> utils/dist/debian/.arch-ids/packages.id + dist/debian/.arch-ids/rules.id + ==> utils/dist/debian/.arch-ids/rules.id + + new directories: + arch/ppc/pearpc arch/ppc/pearpc/.arch-ids arch/x86/xbox + arch/x86/xbox/.arch-ids config config/examples + config/examples/.arch-ids config/xml config/xml/.arch-ids + utils/dist/.arch-ids utils/dist/debian/.arch-ids + utils/ofclient utils/ofclient/.arch-ids + + removed directories: + config config/kconfig config/kconfig/.arch-ids config/lxdialog + config/lxdialog/.arch-ids dist/.arch-ids dist/debian/.arch-ids + + modified directories: + config/.arch-ids + + renamed directories: + config/.arch-ids + ==> config/.arch-ids + config/scripts + ==> config/scripts + dist + ==> utils/dist + + new patches: + oxygene@openbios.org--2005/openbios--xml--1.0--base-0 + oxygene@openbios.org--2005/openbios--xml--1.0--patch-1 + oxygene@openbios.org--2005/openbios--xml--1.0--patch-2 + stepan@openbios.org--devel/openbios--xml--1.0--base-0 + stepan@openbios.org--devel/openbios--xml--1.0--patch-1 + stepan@openbios.org--devel/openbios--xml--1.0--patch-2 + stepan@openbios.org--devel/openbios--xml--1.0--patch-3 + stepan@openbios.org--devel/openbios--xml--1.0--patch-4 + stepan@openbios.org--devel/openbios--xml--1.0--patch-5 + stepan@openbios.org--devel/openbios--xml--1.0--patch-6 + stepan@openbios.org--devel/openbios--xml--1.0--patch-7 + stepan@openbios.org--devel/openbios--xml--1.0--patch-8 + stepan@openbios.org--devel/openbios--xml--1.0--patch-9 + stepan@openbios.org--devel/openbios--xml--1.0--patch-10 + stepan@openbios.org--devel/openbios--xml--1.0--patch-11 + stepan@openbios.org--devel/openbios--xml--1.0--patch-12 + stepan@openbios.org--devel/openbios--xml--1.0--patch-13 + stepan@openbios.org--devel/openbios--xml--1.0--patch-14 + stepan@openbios.org--devel/openbios--xml--1.0--patch-15 + stepan@openbios.org--devel/openbios--xml--1.0--patch-16 + stepan@openbios.org--devel/openbios--xml--1.0--patch-17 + stepan@openbios.org--devel/openbios--xml--1.0--patch-18 + stepan@openbios.org--devel/openbios--xml--1.0--patch-19 + stepan@openbios.org--devel/openbios--xml--1.0--patch-20 + stepan@openbios.org--devel/openbios--xml--1.0--patch-21 + stepan@openbios.org--devel/openbios--xml--1.0--patch-22 + stepan@openbios.org--devel/openbios--xml--1.0--patch-23 + stepan@openbios.org--devel/openbios--xml--1.0--patch-24 + stepan@openbios.org--devel/openbios--xml--1.0--patch-25 + stepan@openbios.org--devel/openbios--xml--1.0--patch-26 + stepan@openbios.org--devel/openbios--xml--1.0--patch-27 + stepan@openbios.org--devel/openbios--xml--1.0--patch-28 + stepan@openbios.org--devel/openbios--xml--1.0--patch-29 + stepan@openbios.org--devel/openbios--xml--1.0--patch-30 + stepan@openbios.org--devel/openbios--xml--1.0--patch-31 + stepan@openbios.org--devel/openbios--xml--1.0--patch-32 + stepan@openbios.org--devel/openbios--xml--1.0--patch-33 + stepan@openbios.org--devel/openbios--xml--1.0--patch-34 + stepan@openbios.org--devel/openbios--xml--1.0--patch-35 + stepan@openbios.org--devel/openbios--xml--1.0--patch-36 + stepan@openbios.org--devel/openbios--xml--1.0--patch-37 + stepan@openbios.org--devel/openbios--xml--1.0--patch-38 + stepan@openbios.org--devel/openbios--xml--1.0--patch-39 + stepan@openbios.org--devel/openbios--xml--1.0--patch-40 + stepan@openbios.org--devel/openbios--xml--1.0--patch-41 + stepan@openbios.org--devel/openbios--xml--1.0--patch-42 + stepan@openbios.org--devel/openbios--xml--1.0--patch-43 + stepan@openbios.org--devel/openbios--xml--1.0--patch-44 + stepan@openbios.org--devel/openbios--xml--1.0--patch-45 + stepan@openbios.org--devel/openbios--xml--1.0--patch-46 + stepan@openbios.org--devel/openbios--xml--1.0--patch-47 + stepan@openbios.org--devel/openbios--xml--1.0--patch-48 + + +2005-03-10 14:46:23 GMT Stefan Reinauer <stepan@openbios.org> patch-18 + + Summary: + detok update: 0.6.1 + Revision: + openbios--main--1.0--patch-18 + + * fix bug in output of strings. Strings were cut off when 0 bytes + occured, in a C manner. Now detok prints correct forth strings. + Thanks to Arti Itra <a.itra@ieee.org> for reporting this. + + * free string after printing it. + + + modified files: + Documentation/ChangeLog.arch utils/detok/ChangeLog + utils/detok/Makefile utils/detok/README utils/detok/decode.c + utils/detok/detok.c utils/detok/detok.h + utils/detok/dictionary.c utils/detok/stream.c + utils/detok/stream.h + + +2005-03-10 12:52:08 GMT Stefan Reinauer <stepan@openbios.org> patch-17 + + Summary: + toke update + Revision: + openbios--main--1.0--patch-17 + + * fix fload. Problem reported by David L. Paktor <dlpaktor@us.ibm.com> + * remove debug enforcement in scanner.c + + + modified files: + Documentation/ChangeLog.arch toke/scanner.c toke/stream.c + + +2005-02-22 21:54:06 GMT Stefan Reinauer <stepan@openbios.org> patch-16 + + Summary: + fix uninitialized variable + Revision: + openbios--main--1.0--patch-16 + + step towards fixing devbios + + + modified files: + Documentation/ChangeLog.arch utils/devbios/pcisets.c + + +2005-01-27 10:12:20 GMT Stefan Reinauer <stepan@openbios.org> patch-15 + + Summary: + update documentation + Revision: + openbios--main--1.0--patch-15 + + Documentation update (thanks to Brian Sammon) + + + modified files: + Documentation/ChangeLog.arch README + + +2004-11-01 20:33:55 GMT Stefan Reinauer <stepan@openbios.org> patch-14 + + Summary: + add exception handling for x86 + Revision: + openbios--main--1.0--patch-14 + + simple exception handling for x86. Safe return does not seem to work yet. + + + new files: + arch/x86/.arch-ids/exception.c.id arch/x86/exception.c + + modified files: + Documentation/ChangeLog.arch arch/unix/unix.c + arch/x86/Makefile arch/x86/context.c arch/x86/entry.S + + renamed files: + arch/x86/.arch-ids/switch.S.id + ==> arch/x86/.arch-ids/entry.S.id + arch/x86/switch.S + ==> arch/x86/entry.S + + +2004-09-19 20:24:46 GMT Stefan Reinauer <stepan@openbios.org> patch-13 + + Summary: + type cleanups + Revision: + openbios--main--1.0--patch-13 + + applying first patch of issue 38 + + + + modified files: + Documentation/ChangeLog.arch kernel/bootstrap.c kernel/forth.c + + +2004-09-19 15:34:22 GMT Stefan Reinauer <stepan@openbios.org> patch-12 + + Summary: + use ranlib instead of "ar s" + Revision: + openbios--main--1.0--patch-12 + + "ar s" is GNU specific and the documenation says it is equal to ranlib. So we + rather use ranlib and stay portable (ie. to Solaris9) + + fixes issue 36 + + + modified files: + Documentation/ChangeLog.arch config/Rules.make + + +2004-09-19 13:38:37 GMT Stefan Reinauer <stepan@openbios.org> patch-11 + + Summary: + initialize ofmem structure properly + Revision: + openbios--main--1.0--patch-11 + + initialize ofmem structure with zero. The correct fix + would be to obtain all information from either linuxbios, + uboot, the hardware or a defined per-board function + + + modified files: + Documentation/ChangeLog.arch arch/ppc/ofmem.c + + +2004-09-12 15:02:04 GMT Stefan Reinauer <stepan@openbios.org> patch-10 + + Summary: + initialize nvram structure completely + Revision: + openbios--main--1.0--patch-10 + + fixes issue 17. nvram structure did not get initialized completely + + + modified files: + Documentation/ChangeLog.arch modules/nvram.c + + +2004-09-12 14:43:23 GMT Stefan Reinauer <stepan@openbios.org> patch-9 + + Summary: + fix little endian/big endian handling + Revision: + openbios--main--1.0--patch-9 + + this should fix issue 20. Switch all endianess handling to use + CONFIG_LITTLE_ENDIAN/CONFIG_BIG_ENDIAN + + + + modified files: + Documentation/ChangeLog.arch fs/hfsplus/btree.c + include/amd64/types.h include/ia64/types.h include/ppc/types.h + include/x86/types.h kernel/bootstrap.c kernel/forth.c + + +2004-09-12 12:29:55 GMT Stefan Reinauer <stepan@openbios.org> patch-8 + + Summary: + + Revision: + openbios--main--1.0--patch-8 + + + + + modified files: + Documentation/ChangeLog.arch arch/amd64/boot.c + arch/amd64/context.c arch/amd64/elfload.c arch/amd64/lib.c + arch/amd64/linux_load.c arch/amd64/multiboot.c + arch/amd64/segment.c arch/amd64/sys_info.c + arch/ppc/briq/briq.c arch/ppc/briq/init.c arch/ppc/briq/main.c + arch/ppc/briq/methods.c arch/ppc/kernel.c arch/ppc/mol/init.c + arch/ppc/mol/main.c arch/ppc/mol/methods.c arch/ppc/mol/mol.c + arch/ppc/mol/osi-blk.c arch/ppc/mol/osi-scsi.c + arch/ppc/mol/prom.c arch/ppc/mol/pseudodisk.c + arch/ppc/mol/tree.c arch/ppc/mol/video.c arch/ppc/ofmem.c + arch/unix/blk.c arch/unix/boot.c arch/unix/unix.c + arch/x86/boot.c arch/x86/context.c arch/x86/elfload.c + arch/x86/forthload.c arch/x86/lib.c arch/x86/linux_load.c + arch/x86/multiboot.c arch/x86/segment.c arch/x86/sys_info.c + drivers/ide.c drivers/pci.c fs/grubfs/grubfs_fs.c + fs/hfs/hfs_fs.c fs/hfsplus/hfsp_fs.c fs/ioglue.c + include/openbios/sysinclude.h kernel/internal.c + modules/bindings.c modules/client.c modules/deblocker.c + modules/disk-label.c modules/elfload.c modules/elfnote.c + modules/filesystems.c modules/linuxbios.c modules/mac-parts.c + modules/nvram.c modules/pc-parts.c + + +2004-09-11 23:18:56 GMT Stefan Reinauer <stepan@openbios.org> patch-7 + + Summary: + get tla silent on commit + Revision: + openbios--main--1.0--patch-7 + + get tla silent on commit. add some files to precious + + + modified files: + Documentation/ChangeLog.arch {arch}/=tagging-method + + +2004-09-11 22:21:05 GMT Stefan Reinauer <stepan@openbios.org> patch-6 + + Summary: + elimination of variables tramp_semis and trampoline + Revision: + openbios--main--1.0--patch-6 + + This fixes https://openbios.org/roundup/openbios/issue22 + + + modified files: + Documentation/ChangeLog.arch kernel/internal.c + + +2004-09-11 21:55:42 GMT Stefan Reinauer <stepan@openbios.org> patch-5 + + Summary: + initialize cache_xt and catch_xt to 0 + Revision: + openbios--main--1.0--patch-5 + + this fixes openbios to work with compilers that do not null out uninitialized + variables. (fixes issues 13 and 18) + + + modified files: + Documentation/ChangeLog.arch include/openbios/bindings.h + modules/bindings.c + + +2004-09-11 21:33:13 GMT Stefan Reinauer <stepan@openbios.org> patch-4 + + Summary: + IDE fix + Revision: + openbios--main--1.0--patch-4 + + shame, shame, shame, shame.. + shame on me.. + + + modified files: + Documentation/ChangeLog.arch drivers/ide.c + + +2004-09-05 17:41:18 GMT Stefan Reinauer <stepan@openbios.org> patch-3 + + Summary: + fix briq build + Revision: + openbios--main--1.0--patch-3 + + fix build for Total Impact Briq systems. This is mostly fixing typos that I + introduced in Gregs recent changes. + + + modified files: + Documentation/ChangeLog.arch arch/ppc/Makefile + arch/ppc/briq/briq.h arch/ppc/briq/kernel.c drivers/Kconfig + drivers/ide.c drivers/ide.h drivers/timer.c drivers/timer.h + + +2004-09-03 19:40:52 GMT Stefan Reinauer <stepan@openbios.org> patch-2 + + Summary: + oxygene fixed the file permissions + Revision: + openbios--main--1.0--patch-2 + + merged from Patricks tree + + Patches applied: + + * oxygene@studentenbude.ath.cx--2004/openbios--porting--0--patch-4 + make all files writable, we're not using bitkeeper + + + modified files: + .arch-ids/COPYING.id .arch-ids/Makefile.id .arch-ids/README.id + .arch-ids/autogen.sh.id .arch-ids/configure.id + .arch-ids/setup_links.id COPYING Documentation/.arch-ids/=id + Documentation/ChangeLog.arch + Documentation/kernel/.arch-ids/=id + Documentation/kernel/.arch-ids/AUTHORS.id + Documentation/kernel/.arch-ids/COPYING.id + Documentation/kernel/.arch-ids/Changelog.stepan.id + Documentation/kernel/.arch-ids/TODO.id + Documentation/kernel/.arch-ids/dictformat.txt.id + Documentation/kernel/.arch-ids/glossary.txt.id + Documentation/kernel/.arch-ids/initializers.txt.id + Documentation/kernel/AUTHORS Documentation/kernel/COPYING + Documentation/kernel/Changelog.stepan + Documentation/kernel/TODO Documentation/kernel/dictformat.txt + Documentation/kernel/glossary.txt + Documentation/kernel/initializers.txt Makefile README + arch/.arch-ids/=id arch/amd64/.arch-ids/=id + arch/amd64/.arch-ids/Kconfig.id + arch/amd64/.arch-ids/Makefile.asm.id + arch/amd64/.arch-ids/Makefile.id + arch/amd64/.arch-ids/boot.c.id + arch/amd64/.arch-ids/builtin.c.id + arch/amd64/.arch-ids/console.c.id + arch/amd64/.arch-ids/context.c.id + arch/amd64/.arch-ids/context.h.id + arch/amd64/.arch-ids/defconfig.id + arch/amd64/.arch-ids/elfload.c.id + arch/amd64/.arch-ids/init.fs.id + arch/amd64/.arch-ids/ldscript.id arch/amd64/.arch-ids/lib.c.id + arch/amd64/.arch-ids/linux_load.c.id + arch/amd64/.arch-ids/loadfs.c.id + arch/amd64/.arch-ids/loadfs.h.id + arch/amd64/.arch-ids/multiboot.c.id + arch/amd64/.arch-ids/multiboot.h.id + arch/amd64/.arch-ids/openbios.c.id + arch/amd64/.arch-ids/openbios.h.id + arch/amd64/.arch-ids/plainboot.c.id + arch/amd64/.arch-ids/relocate.h.id + arch/amd64/.arch-ids/segment.c.id + arch/amd64/.arch-ids/segment.h.id + arch/amd64/.arch-ids/switch.S.id + arch/amd64/.arch-ids/sys_info.c.id arch/amd64/Kconfig + arch/amd64/Makefile arch/amd64/Makefile.asm arch/amd64/boot.c + arch/amd64/builtin.c arch/amd64/console.c arch/amd64/context.c + arch/amd64/context.h arch/amd64/defconfig arch/amd64/elfload.c + arch/amd64/init.fs arch/amd64/ldscript arch/amd64/lib.c + arch/amd64/linux_load.c arch/amd64/loadfs.c + arch/amd64/loadfs.h arch/amd64/multiboot.c + arch/amd64/multiboot.h arch/amd64/openbios.c + arch/amd64/openbios.h arch/amd64/plainboot.c + arch/amd64/relocate.h arch/amd64/segment.c + arch/amd64/segment.h arch/amd64/switch.S arch/amd64/sys_info.c + arch/ia64/.arch-ids/=id arch/ia64/.arch-ids/Kconfig.id + arch/ia64/.arch-ids/Makefile.asm.id + arch/ia64/.arch-ids/Makefile.id + arch/ia64/.arch-ids/defconfig.id + arch/ia64/.arch-ids/init.fs.id arch/ia64/Kconfig + arch/ia64/Makefile arch/ia64/Makefile.asm arch/ia64/defconfig + arch/ia64/init.fs arch/ppc/.arch-ids/=id + arch/ppc/.arch-ids/Kconfig.id + arch/ppc/.arch-ids/Makefile.asm.id + arch/ppc/.arch-ids/Makefile.id arch/ppc/.arch-ids/defconfig.id + arch/ppc/.arch-ids/kernel.c.id arch/ppc/.arch-ids/kernel.h.id + arch/ppc/.arch-ids/misc.S.id arch/ppc/.arch-ids/mmutypes.h.id + arch/ppc/.arch-ids/ofmem.c.id arch/ppc/.arch-ids/osi.h.id + arch/ppc/.arch-ids/osi_calls.h.id arch/ppc/.arch-ids/ppc.fs.id + arch/ppc/.arch-ids/start.S.id arch/ppc/.arch-ids/timebase.S.id + arch/ppc/Kconfig arch/ppc/Makefile arch/ppc/Makefile.asm + arch/ppc/briq/.arch-ids/=id arch/ppc/briq/.arch-ids/briq.c.id + arch/ppc/briq/.arch-ids/briq.fs.id + arch/ppc/briq/.arch-ids/briq.h.id + arch/ppc/briq/.arch-ids/init.c.id + arch/ppc/briq/.arch-ids/kernel.c.id + arch/ppc/briq/.arch-ids/main.c.id + arch/ppc/briq/.arch-ids/methods.c.id + arch/ppc/briq/.arch-ids/tree.c.id + arch/ppc/briq/.arch-ids/tree.fs.id + arch/ppc/briq/.arch-ids/vfd.c.id arch/ppc/briq/briq.c + arch/ppc/briq/briq.fs arch/ppc/briq/briq.h + arch/ppc/briq/init.c arch/ppc/briq/kernel.c + arch/ppc/briq/main.c arch/ppc/briq/methods.c + arch/ppc/briq/tree.c arch/ppc/briq/tree.fs arch/ppc/briq/vfd.c + arch/ppc/defconfig arch/ppc/kernel.c arch/ppc/kernel.h + arch/ppc/misc.S arch/ppc/mmutypes.h arch/ppc/mol/.arch-ids/=id + arch/ppc/mol/.arch-ids/console.c.id + arch/ppc/mol/.arch-ids/font_8x8.c.id + arch/ppc/mol/.arch-ids/init.c.id + arch/ppc/mol/.arch-ids/kernel.c.id + arch/ppc/mol/.arch-ids/main.c.id + arch/ppc/mol/.arch-ids/methods.c.id + arch/ppc/mol/.arch-ids/mol.c.id + arch/ppc/mol/.arch-ids/mol.fs.id + arch/ppc/mol/.arch-ids/mol.h.id + arch/ppc/mol/.arch-ids/osi-blk.c.id + arch/ppc/mol/.arch-ids/osi-scsi.c.id + arch/ppc/mol/.arch-ids/prom.c.id + arch/ppc/mol/.arch-ids/prom.h.id + arch/ppc/mol/.arch-ids/pseudodisk.c.id + arch/ppc/mol/.arch-ids/tree.c.id + arch/ppc/mol/.arch-ids/tree.fs.id + arch/ppc/mol/.arch-ids/video.c.id arch/ppc/mol/console.c + arch/ppc/mol/font_8x8.c arch/ppc/mol/init.c + arch/ppc/mol/kernel.c arch/ppc/mol/main.c + arch/ppc/mol/methods.c arch/ppc/mol/mol.c arch/ppc/mol/mol.fs + arch/ppc/mol/mol.h arch/ppc/mol/osi-blk.c + arch/ppc/mol/osi-scsi.c arch/ppc/mol/prom.c + arch/ppc/mol/prom.h arch/ppc/mol/pseudodisk.c + arch/ppc/mol/tree.c arch/ppc/mol/tree.fs arch/ppc/mol/video.c + arch/ppc/ofmem.c arch/ppc/osi.h arch/ppc/osi_calls.h + arch/ppc/ppc.fs arch/ppc/start.S arch/ppc/timebase.S + arch/unix/.arch-ids/=id arch/unix/.arch-ids/Kconfig.id + arch/unix/.arch-ids/Makefile.id arch/unix/.arch-ids/blk.c.id + arch/unix/.arch-ids/blk.h.id arch/unix/.arch-ids/boot.c.id + arch/unix/.arch-ids/plugins.c.id + arch/unix/.arch-ids/tree.fs.id arch/unix/.arch-ids/unix.c.id + arch/unix/Kconfig arch/unix/Makefile arch/unix/blk.c + arch/unix/blk.h arch/unix/boot.c + arch/unix/gui_qt/.arch-ids/=id + arch/unix/gui_qt/.arch-ids/Makefile.id + arch/unix/gui_qt/.arch-ids/gui-qt.cpp.id + arch/unix/gui_qt/.arch-ids/gui-qt.h.id + arch/unix/gui_qt/.arch-ids/gui-qt.pro.id + arch/unix/gui_qt/.arch-ids/logo.xpm.id + arch/unix/gui_qt/.arch-ids/qt-main.cpp.id + arch/unix/gui_qt/Makefile arch/unix/gui_qt/gui-qt.cpp + arch/unix/gui_qt/gui-qt.h arch/unix/gui_qt/gui-qt.pro + arch/unix/gui_qt/logo.xpm arch/unix/gui_qt/qt-main.cpp + arch/unix/plugins.c arch/unix/plugins/.arch-ids/=id + arch/unix/plugins/.arch-ids/Kconfig.id + arch/unix/plugins/.arch-ids/Makefile.id + arch/unix/plugins/.arch-ids/Rules.plugin.id + arch/unix/plugins/.arch-ids/loader.c.id + arch/unix/plugins/Kconfig arch/unix/plugins/Makefile + arch/unix/plugins/Rules.plugin arch/unix/plugins/loader.c + arch/unix/plugins/plugin_pci/.arch-ids/=id + arch/unix/plugins/plugin_pci/.arch-ids/Makefile.id + arch/unix/plugins/plugin_pci/.arch-ids/Makefile.old.id + arch/unix/plugins/plugin_pci/.arch-ids/plugin_pci.c.id + arch/unix/plugins/plugin_pci/Makefile + arch/unix/plugins/plugin_pci/Makefile.old + arch/unix/plugins/plugin_pci/plugin_pci.c + arch/unix/plugins/plugin_qt/.arch-ids/=id + arch/unix/plugins/plugin_qt/.arch-ids/Makefile.id + arch/unix/plugins/plugin_qt/.arch-ids/logo.xpm.id + arch/unix/plugins/plugin_qt/.arch-ids/pciconfig.h.id + arch/unix/plugins/plugin_qt/.arch-ids/plugin_qt.cpp.id + arch/unix/plugins/plugin_qt/.arch-ids/plugin_qt.h.id + arch/unix/plugins/plugin_qt/.arch-ids/plugin_qt.pro.id + arch/unix/plugins/plugin_qt/.arch-ids/qt_main.cpp.id + arch/unix/plugins/plugin_qt/.arch-ids/qt_rom.fs.id + arch/unix/plugins/plugin_qt/Makefile + arch/unix/plugins/plugin_qt/logo.xpm + arch/unix/plugins/plugin_qt/pciconfig.h + arch/unix/plugins/plugin_qt/plugin_qt.cpp + arch/unix/plugins/plugin_qt/plugin_qt.h + arch/unix/plugins/plugin_qt/plugin_qt.pro + arch/unix/plugins/plugin_qt/qt_main.cpp + arch/unix/plugins/plugin_qt/qt_rom.fs arch/unix/tree.fs + arch/unix/unix.c arch/x86/.arch-ids/=id + arch/x86/.arch-ids/Kconfig.id + arch/x86/.arch-ids/Makefile.asm.id + arch/x86/.arch-ids/Makefile.id arch/x86/.arch-ids/boot.c.id + arch/x86/.arch-ids/boot.h.id arch/x86/.arch-ids/builtin.c.id + arch/x86/.arch-ids/console.c.id + arch/x86/.arch-ids/context.c.id + arch/x86/.arch-ids/context.h.id + arch/x86/.arch-ids/defconfig.id + arch/x86/.arch-ids/elfload.c.id + arch/x86/.arch-ids/forthload.c.id + arch/x86/.arch-ids/init.fs.id arch/x86/.arch-ids/ldscript.id + arch/x86/.arch-ids/lib.c.id arch/x86/.arch-ids/linux_load.c.id + arch/x86/.arch-ids/loadfs.c.id arch/x86/.arch-ids/loadfs.h.id + arch/x86/.arch-ids/multiboot.c.id + arch/x86/.arch-ids/multiboot.h.id + arch/x86/.arch-ids/openbios.c.id + arch/x86/.arch-ids/openbios.h.id + arch/x86/.arch-ids/plainboot.c.id + arch/x86/.arch-ids/relocate.h.id + arch/x86/.arch-ids/segment.c.id + arch/x86/.arch-ids/segment.h.id arch/x86/.arch-ids/switch.S.id + arch/x86/.arch-ids/sys_info.c.id arch/x86/Kconfig + arch/x86/Makefile arch/x86/Makefile.asm arch/x86/boot.c + arch/x86/boot.h arch/x86/builtin.c arch/x86/console.c + arch/x86/context.c arch/x86/context.h arch/x86/defconfig + arch/x86/elfload.c arch/x86/forthload.c arch/x86/init.fs + arch/x86/ldscript arch/x86/lib.c arch/x86/linux_load.c + arch/x86/loadfs.c arch/x86/loadfs.h arch/x86/multiboot.c + arch/x86/multiboot.h arch/x86/openbios.c arch/x86/openbios.h + arch/x86/plainboot.c arch/x86/relocate.h arch/x86/segment.c + arch/x86/segment.h arch/x86/switch.S arch/x86/sys_info.c + autogen.sh config/.arch-ids/=id + config/.arch-ids/Makefile.defs.in.id + config/.arch-ids/Makefile.id + config/.arch-ids/Makefile.master.id + config/.arch-ids/Makefile.top.id + config/.arch-ids/Rules.forth.id config/.arch-ids/Rules.make.id + config/.arch-ids/configure.in.id config/Makefile + config/Makefile.defs.in config/Makefile.master + config/Makefile.top config/Rules.forth config/Rules.make + config/configure.in config/kconfig/.arch-ids/=id + config/kconfig/.arch-ids/Makefile.id + config/kconfig/.arch-ids/conf.c.id + config/kconfig/.arch-ids/confdata.c.id + config/kconfig/.arch-ids/expr.c.id + config/kconfig/.arch-ids/expr.h.id + config/kconfig/.arch-ids/lkc.h.id + config/kconfig/.arch-ids/lkc_proto.h.id + config/kconfig/.arch-ids/mconf.c.id + config/kconfig/.arch-ids/menu.c.id + config/kconfig/.arch-ids/symbol.c.id + config/kconfig/.arch-ids/zconf-l.l.id + config/kconfig/.arch-ids/zconf-y.y.id config/kconfig/Makefile + config/kconfig/conf.c config/kconfig/confdata.c + config/kconfig/expr.c config/kconfig/expr.h + config/kconfig/lkc.h config/kconfig/lkc_proto.h + config/kconfig/mconf.c config/kconfig/menu.c + config/kconfig/symbol.c config/kconfig/zconf-l.l + config/kconfig/zconf-y.y config/lxdialog/.arch-ids/=id + config/lxdialog/.arch-ids/Makefile.id + config/lxdialog/.arch-ids/checklist.c.id + config/lxdialog/.arch-ids/colors.h.id + config/lxdialog/.arch-ids/dialog.h.id + config/lxdialog/.arch-ids/inputbox.c.id + config/lxdialog/.arch-ids/lxdialog.c.id + config/lxdialog/.arch-ids/menubox.c.id + config/lxdialog/.arch-ids/msgbox.c.id + config/lxdialog/.arch-ids/textbox.c.id + config/lxdialog/.arch-ids/util.c.id + config/lxdialog/.arch-ids/yesno.c.id config/lxdialog/Makefile + config/lxdialog/checklist.c config/lxdialog/colors.h + config/lxdialog/dialog.h config/lxdialog/inputbox.c + config/lxdialog/lxdialog.c config/lxdialog/menubox.c + config/lxdialog/msgbox.c config/lxdialog/textbox.c + config/lxdialog/util.c config/lxdialog/yesno.c + config/scripts/.arch-ids/=id + config/scripts/.arch-ids/archname.id + config/scripts/.arch-ids/reldir.id config/scripts/archname + config/scripts/reldir configure dist/.arch-ids/=id + dist/.arch-ids/openbios.spec.id dist/debian/.arch-ids/=id + dist/debian/.arch-ids/changelog.id + dist/debian/.arch-ids/control.id + dist/debian/.arch-ids/packages.id + dist/debian/.arch-ids/rules.id dist/debian/changelog + dist/debian/control dist/debian/packages dist/debian/rules + dist/openbios.spec drivers/.arch-ids/=id + drivers/.arch-ids/Kconfig.id drivers/.arch-ids/Makefile.id + drivers/.arch-ids/hdreg.h.id drivers/.arch-ids/ide.c.id + drivers/.arch-ids/ide.fs.id drivers/.arch-ids/ide.h.id + drivers/.arch-ids/pci.c.id drivers/.arch-ids/pci.fs.id + drivers/.arch-ids/pci.h.id drivers/.arch-ids/timer.c.id + drivers/.arch-ids/timer.h.id drivers/Kconfig drivers/Makefile + drivers/hdreg.h drivers/ide.c drivers/ide.fs drivers/ide.h + drivers/pci.c drivers/pci.fs drivers/pci.h drivers/timer.c + drivers/timer.h forth/.arch-ids/=id forth/.arch-ids/Kconfig.id + forth/.arch-ids/Makefile.id forth/Kconfig forth/Makefile + forth/admin/.arch-ids/=id forth/admin/.arch-ids/Makefile.id + forth/admin/.arch-ids/README.id + forth/admin/.arch-ids/banner.fs.id + forth/admin/.arch-ids/callback.fs.id + forth/admin/.arch-ids/devices.fs.id + forth/admin/.arch-ids/help.fs.id + forth/admin/.arch-ids/iocontrol.fs.id + forth/admin/.arch-ids/nvram.fs.id + forth/admin/.arch-ids/reset.fs.id + forth/admin/.arch-ids/script.fs.id + forth/admin/.arch-ids/security.fs.id + forth/admin/.arch-ids/selftest.fs.id + forth/admin/.arch-ids/userboot.fs.id forth/admin/Makefile + forth/admin/README forth/admin/banner.fs + forth/admin/callback.fs forth/admin/devices.fs + forth/admin/help.fs forth/admin/iocontrol.fs + forth/admin/nvram.fs forth/admin/reset.fs + forth/admin/script.fs forth/admin/security.fs + forth/admin/selftest.fs forth/admin/userboot.fs + forth/bootstrap/.arch-ids/=id + forth/bootstrap/.arch-ids/bootstrap.fs.id + forth/bootstrap/.arch-ids/builtin.fs.id + forth/bootstrap/.arch-ids/hayes.fs.id + forth/bootstrap/.arch-ids/interpreter.fs.id + forth/bootstrap/.arch-ids/memory.fs.id + forth/bootstrap/.arch-ids/start.fs.id + forth/bootstrap/bootstrap.fs forth/bootstrap/builtin.fs + forth/bootstrap/hayes.fs forth/bootstrap/interpreter.fs + forth/bootstrap/memory.fs forth/bootstrap/start.fs + forth/debugging/.arch-ids/=id + forth/debugging/.arch-ids/Makefile.id + forth/debugging/.arch-ids/client.fs.id + forth/debugging/.arch-ids/fcode.fs.id + forth/debugging/.arch-ids/firmware.fs.id + forth/debugging/.arch-ids/see.fs.id forth/debugging/Makefile + forth/debugging/client.fs forth/debugging/fcode.fs + forth/debugging/firmware.fs forth/debugging/see.fs + forth/device/.arch-ids/=id forth/device/.arch-ids/Makefile.id + forth/device/.arch-ids/README.device.id + forth/device/.arch-ids/builtin.fs.id + forth/device/.arch-ids/device.fs.id + forth/device/.arch-ids/display.fs.id + forth/device/.arch-ids/extra.fs.id + forth/device/.arch-ids/fcode.fs.id + forth/device/.arch-ids/feval.fs.id + forth/device/.arch-ids/font.fs.id + forth/device/.arch-ids/logo.fs.id + forth/device/.arch-ids/missing.id + forth/device/.arch-ids/other.fs.id + forth/device/.arch-ids/package.fs.id + forth/device/.arch-ids/pathres.fs.id + forth/device/.arch-ids/preof.fs.id + forth/device/.arch-ids/property.fs.id + forth/device/.arch-ids/romfont.bin.id + forth/device/.arch-ids/structures.fs.id + forth/device/.arch-ids/table.fs.id + forth/device/.arch-ids/terminal.fs.id + forth/device/.arch-ids/tree.fs.id forth/device/Makefile + forth/device/README.device forth/device/builtin.fs + forth/device/device.fs forth/device/display.fs + forth/device/extra.fs forth/device/fcode.fs + forth/device/feval.fs forth/device/font.fs + forth/device/logo.fs forth/device/missing + forth/device/other.fs forth/device/package.fs + forth/device/pathres.fs forth/device/preof.fs + forth/device/property.fs forth/device/romfont.bin + forth/device/structures.fs forth/device/table.fs + forth/device/terminal.fs forth/device/tree.fs + forth/lib/.arch-ids/=id forth/lib/.arch-ids/Makefile.id + forth/lib/.arch-ids/creation.fs.id + forth/lib/.arch-ids/lists.fs.id + forth/lib/.arch-ids/preprocessor.fs.id + forth/lib/.arch-ids/split.fs.id + forth/lib/.arch-ids/string.fs.id + forth/lib/.arch-ids/vocabulary.fs.id forth/lib/Makefile + forth/lib/creation.fs forth/lib/lists.fs + forth/lib/preprocessor.fs forth/lib/split.fs + forth/lib/string.fs forth/lib/vocabulary.fs + forth/packages/.arch-ids/=id + forth/packages/.arch-ids/Kconfig.id + forth/packages/.arch-ids/Makefile.id + forth/packages/.arch-ids/README.id + forth/packages/.arch-ids/deblocker.fs.id + forth/packages/.arch-ids/disklabel.fs.id + forth/packages/.arch-ids/obp-tftp.fs.id + forth/packages/.arch-ids/packages.fs.id + forth/packages/.arch-ids/terminal-emulator.fs.id + forth/packages/Kconfig forth/packages/Makefile + forth/packages/README forth/packages/deblocker.fs + forth/packages/disklabel.fs forth/packages/obp-tftp.fs + forth/packages/packages.fs forth/packages/terminal-emulator.fs + forth/system/.arch-ids/=id forth/system/.arch-ids/Makefile.id + forth/system/.arch-ids/ciface.fs.id + forth/system/.arch-ids/main.fs.id forth/system/Makefile + forth/system/ciface.fs forth/system/main.fs + forth/testsuite/.arch-ids/=id + forth/testsuite/.arch-ids/Makefile.id + forth/testsuite/.arch-ids/README.id + forth/testsuite/.arch-ids/fract.fs.id + forth/testsuite/.arch-ids/framebuffer-test.fs.id + forth/testsuite/.arch-ids/memory-testsuite.fs.id + forth/testsuite/.arch-ids/splitfunc-testsuite.fs.id + forth/testsuite/Makefile forth/testsuite/README + forth/testsuite/fract.fs forth/testsuite/framebuffer-test.fs + forth/testsuite/memory-testsuite.fs + forth/testsuite/splitfunc-testsuite.fs + forth/util/.arch-ids/=id forth/util/.arch-ids/Makefile.id + forth/util/.arch-ids/apic.fs.id forth/util/.arch-ids/pci.fs.id + forth/util/.arch-ids/util.fs.id forth/util/Makefile + forth/util/apic.fs forth/util/pci.fs forth/util/util.fs + fs/.arch-ids/=id fs/.arch-ids/Makefile.id + fs/.arch-ids/hfs_mdb.h.id fs/.arch-ids/ioglue.c.id + fs/.arch-ids/os.h.id fs/Makefile fs/grubfs/.arch-ids/=id + fs/grubfs/.arch-ids/Kconfig.id fs/grubfs/.arch-ids/Makefile.id + fs/grubfs/.arch-ids/debug.h.id fs/grubfs/.arch-ids/defs.h.id + fs/grubfs/.arch-ids/dir.h.id + fs/grubfs/.arch-ids/disk_inode.h.id + fs/grubfs/.arch-ids/disk_inode_ffs.h.id + fs/grubfs/.arch-ids/fat.h.id fs/grubfs/.arch-ids/filesys.h.id + fs/grubfs/.arch-ids/fs.h.id fs/grubfs/.arch-ids/fsys_affs.c.id + fs/grubfs/.arch-ids/fsys_ext2fs.c.id + fs/grubfs/.arch-ids/fsys_fat.c.id + fs/grubfs/.arch-ids/fsys_ffs.c.id + fs/grubfs/.arch-ids/fsys_iso9660.c.id + fs/grubfs/.arch-ids/fsys_jfs.c.id + fs/grubfs/.arch-ids/fsys_minix.c.id + fs/grubfs/.arch-ids/fsys_ntfs.c.id + fs/grubfs/.arch-ids/fsys_reiserfs.c.id + fs/grubfs/.arch-ids/fsys_vstafs.c.id + fs/grubfs/.arch-ids/fsys_xfs.c.id + fs/grubfs/.arch-ids/glue.h.id + fs/grubfs/.arch-ids/grubfs_fs.c.id + fs/grubfs/.arch-ids/iso9660.h.id fs/grubfs/.arch-ids/jfs.h.id + fs/grubfs/.arch-ids/shared.h.id + fs/grubfs/.arch-ids/vstafs.h.id fs/grubfs/.arch-ids/xfs.h.id + fs/grubfs/Kconfig fs/grubfs/Makefile fs/grubfs/debug.h + fs/grubfs/defs.h fs/grubfs/dir.h fs/grubfs/disk_inode.h + fs/grubfs/disk_inode_ffs.h fs/grubfs/fat.h fs/grubfs/filesys.h + fs/grubfs/fs.h fs/grubfs/fsys_affs.c fs/grubfs/fsys_ext2fs.c + fs/grubfs/fsys_fat.c fs/grubfs/fsys_ffs.c + fs/grubfs/fsys_iso9660.c fs/grubfs/fsys_jfs.c + fs/grubfs/fsys_minix.c fs/grubfs/fsys_ntfs.c + fs/grubfs/fsys_reiserfs.c fs/grubfs/fsys_vstafs.c + fs/grubfs/fsys_xfs.c fs/grubfs/glue.h fs/grubfs/grubfs_fs.c + fs/grubfs/iso9660.h fs/grubfs/jfs.h fs/grubfs/shared.h + fs/grubfs/vstafs.h fs/grubfs/xfs.h fs/hfs/.arch-ids/=id + fs/hfs/.arch-ids/Makefile.id fs/hfs/.arch-ids/block.c.id + fs/hfs/.arch-ids/btree.c.id fs/hfs/.arch-ids/data.c.id + fs/hfs/.arch-ids/file.c.id fs/hfs/.arch-ids/hfs.c.id + fs/hfs/.arch-ids/hfs_fs.c.id fs/hfs/.arch-ids/low.c.id + fs/hfs/.arch-ids/medium.c.id fs/hfs/.arch-ids/node.c.id + fs/hfs/.arch-ids/record.c.id fs/hfs/.arch-ids/volume.c.id + fs/hfs/Makefile fs/hfs/block.c fs/hfs/btree.c fs/hfs/data.c + fs/hfs/file.c fs/hfs/hfs.c fs/hfs/hfs_fs.c + fs/hfs/include/.arch-ids/=id + fs/hfs/include/.arch-ids/apple.h.id + fs/hfs/include/.arch-ids/block.h.id + fs/hfs/include/.arch-ids/btree.h.id + fs/hfs/include/.arch-ids/data.h.id + fs/hfs/include/.arch-ids/file.h.id + fs/hfs/include/.arch-ids/hfs.h.id + fs/hfs/include/.arch-ids/libhfs.h.id + fs/hfs/include/.arch-ids/low.h.id + fs/hfs/include/.arch-ids/medium.h.id + fs/hfs/include/.arch-ids/node.h.id + fs/hfs/include/.arch-ids/record.h.id + fs/hfs/include/.arch-ids/volume.h.id fs/hfs/include/apple.h + fs/hfs/include/block.h fs/hfs/include/btree.h + fs/hfs/include/data.h fs/hfs/include/file.h + fs/hfs/include/hfs.h fs/hfs/include/libhfs.h + fs/hfs/include/low.h fs/hfs/include/medium.h + fs/hfs/include/node.h fs/hfs/include/record.h + fs/hfs/include/volume.h fs/hfs/low.c fs/hfs/medium.c + fs/hfs/node.c fs/hfs/record.c fs/hfs/volume.c fs/hfs_mdb.h + fs/hfsplus/.arch-ids/=id fs/hfsplus/.arch-ids/Makefile.id + fs/hfsplus/.arch-ids/blockiter.c.id + fs/hfsplus/.arch-ids/btree.c.id + fs/hfsplus/.arch-ids/hfsp_fs.c.id + fs/hfsplus/.arch-ids/libhfsp.c.id + fs/hfsplus/.arch-ids/record.c.id + fs/hfsplus/.arch-ids/unicode.c.id + fs/hfsplus/.arch-ids/volume.c.id fs/hfsplus/Makefile + fs/hfsplus/blockiter.c fs/hfsplus/btree.c fs/hfsplus/hfsp_fs.c + fs/hfsplus/include/.arch-ids/=id + fs/hfsplus/include/.arch-ids/apple.h.id + fs/hfsplus/include/.arch-ids/blockiter.h.id + fs/hfsplus/include/.arch-ids/btree.h.id + fs/hfsplus/include/.arch-ids/hfs.h.id + fs/hfsplus/include/.arch-ids/hfsp.h.id + fs/hfsplus/include/.arch-ids/hfstime.h.id + fs/hfsplus/include/.arch-ids/libhfsp.h.id + fs/hfsplus/include/.arch-ids/record.h.id + fs/hfsplus/include/.arch-ids/swab.h.id + fs/hfsplus/include/.arch-ids/unicode.h.id + fs/hfsplus/include/.arch-ids/volume.h.id + fs/hfsplus/include/apple.h fs/hfsplus/include/blockiter.h + fs/hfsplus/include/btree.h fs/hfsplus/include/hfs.h + fs/hfsplus/include/hfsp.h fs/hfsplus/include/hfstime.h + fs/hfsplus/include/libhfsp.h fs/hfsplus/include/record.h + fs/hfsplus/include/swab.h fs/hfsplus/include/unicode.h + fs/hfsplus/include/volume.h fs/hfsplus/libhfsp.c + fs/hfsplus/record.c fs/hfsplus/unicode.c fs/hfsplus/volume.c + fs/ioglue.c fs/os.h include/.arch-ids/=id + include/.arch-ids/elf_boot.h.id + include/.arch-ids/ipchecksum.h.id include/.arch-ids/ofmem.h.id + include/.arch-ids/sys_info.h.id include/amd64/.arch-ids/=id + include/amd64/.arch-ids/elf.h.id + include/amd64/.arch-ids/io.h.id + include/amd64/.arch-ids/types.h.id include/amd64/elf.h + include/amd64/io.h include/amd64/types.h include/elf_boot.h + include/ia64/.arch-ids/=id include/ia64/.arch-ids/elf.h.id + include/ia64/.arch-ids/io.h.id + include/ia64/.arch-ids/types.h.id include/ia64/elf.h + include/ia64/io.h include/ia64/types.h include/ipchecksum.h + include/libc/.arch-ids/=id + include/libc/.arch-ids/byteorder.h.id + include/libc/.arch-ids/diskio.h.id + include/libc/.arch-ids/stdlib.h.id + include/libc/.arch-ids/string.h.id + include/libc/.arch-ids/vsprintf.h.id include/libc/byteorder.h + include/libc/diskio.h include/libc/stdlib.h + include/libc/string.h include/libc/vsprintf.h include/ofmem.h + include/openbios/.arch-ids/=id + include/openbios/.arch-ids/asm.m4.id + include/openbios/.arch-ids/bindings.h.id + include/openbios/.arch-ids/config.h.id + include/openbios/.arch-ids/drivers.h.id + include/openbios/.arch-ids/elf.h.id + include/openbios/.arch-ids/elfload.h.id + include/openbios/.arch-ids/fs.h.id + include/openbios/.arch-ids/kernel.h.id + include/openbios/.arch-ids/nvram.h.id + include/openbios/.arch-ids/of.h.id + include/openbios/.arch-ids/stack.h.id + include/openbios/.arch-ids/sysinclude.h.id + include/openbios/asm.m4 include/openbios/bindings.h + include/openbios/config.h include/openbios/drivers.h + include/openbios/elf.h include/openbios/elfload.h + include/openbios/fs.h include/openbios/kernel.h + include/openbios/nvram.h include/openbios/of.h + include/openbios/stack.h include/openbios/sysinclude.h + include/ppc/.arch-ids/=id include/ppc/.arch-ids/asmdefs.h.id + include/ppc/.arch-ids/elf.h.id include/ppc/.arch-ids/io.h.id + include/ppc/.arch-ids/processor.h.id + include/ppc/.arch-ids/types.h.id include/ppc/asmdefs.h + include/ppc/elf.h include/ppc/io.h include/ppc/processor.h + include/ppc/types.h include/sys_info.h + include/unix/.arch-ids/=id + include/unix/.arch-ids/plugin_pci.h.id + include/unix/.arch-ids/plugins.h.id include/unix/plugin_pci.h + include/unix/plugins.h include/x86/.arch-ids/=id + include/x86/.arch-ids/elf.h.id include/x86/.arch-ids/io.h.id + include/x86/.arch-ids/pci.h.id + include/x86/.arch-ids/types.h.id include/x86/elf.h + include/x86/io.h include/x86/pci.h include/x86/types.h + kernel/.arch-ids/=id kernel/.arch-ids/Kconfig.id + kernel/.arch-ids/Makefile.id kernel/.arch-ids/README.id + kernel/.arch-ids/bootstrap.c.id kernel/.arch-ids/dict.c.id + kernel/.arch-ids/forth.c.id kernel/.arch-ids/internal.c.id + kernel/.arch-ids/primitives.c.id kernel/.arch-ids/stack.c.id + kernel/Kconfig kernel/Makefile kernel/README + kernel/bootstrap.c kernel/dict.c kernel/forth.c + kernel/include/.arch-ids/=id + kernel/include/.arch-ids/dict.h.id kernel/include/dict.h + kernel/internal.c kernel/primitives.c kernel/stack.c + libc/.arch-ids/=id libc/.arch-ids/Makefile.id + libc/.arch-ids/byteorder.c.id libc/.arch-ids/ctype.c.id + libc/.arch-ids/diskio.c.id libc/.arch-ids/extra.c.id + libc/.arch-ids/misc.c.id libc/.arch-ids/string.c.id + libc/.arch-ids/vsprintf.c.id libc/Makefile libc/byteorder.c + libc/ctype.c libc/diskio.c libc/extra.c libc/misc.c + libc/string.c libc/vsprintf.c modules/.arch-ids/=id + modules/.arch-ids/Kconfig.id modules/.arch-ids/Makefile.id + modules/.arch-ids/bindings.c.id modules/.arch-ids/clib.fs.id + modules/.arch-ids/client.c.id modules/.arch-ids/cmdline.c.id + modules/.arch-ids/deblocker.c.id + modules/.arch-ids/disk-label.c.id + modules/.arch-ids/elfload.c.id modules/.arch-ids/elfnote.c.id + modules/.arch-ids/filesystems.c.id + modules/.arch-ids/helpers.fs.id modules/.arch-ids/init.c.id + modules/.arch-ids/ipchecksum.c.id + modules/.arch-ids/linuxbios.c.id + modules/.arch-ids/linuxbios.h.id + modules/.arch-ids/mac-parts.c.id + modules/.arch-ids/mac-parts.h.id + modules/.arch-ids/modules.h.id modules/.arch-ids/nvram.c.id + modules/.arch-ids/pc-parts.c.id + modules/.arch-ids/support.fs.id modules/Kconfig + modules/Makefile modules/bindings.c modules/clib.fs + modules/client.c modules/cmdline.c modules/deblocker.c + modules/disk-label.c modules/elfload.c modules/elfnote.c + modules/filesystems.c modules/helpers.fs modules/init.c + modules/ipchecksum.c modules/linuxbios.c modules/linuxbios.h + modules/mac-parts.c modules/mac-parts.h modules/modules.h + modules/nvram.c modules/pc-parts.c modules/support.fs + setup_links toke/.arch-ids/=id toke/.arch-ids/COPYING.id + toke/.arch-ids/ChangeLog.id toke/.arch-ids/Makefile.id + toke/.arch-ids/README.id toke/.arch-ids/Rules.make.id + toke/.arch-ids/TODO.id toke/.arch-ids/dictionary.c.id + toke/.arch-ids/dictionary.h.id toke/.arch-ids/emit.c.id + toke/.arch-ids/emit.h.id toke/.arch-ids/macros.c.id + toke/.arch-ids/scanner.c.id toke/.arch-ids/stack.c.id + toke/.arch-ids/stack.h.id toke/.arch-ids/stream.c.id + toke/.arch-ids/stream.h.id toke/.arch-ids/toke.c.id + toke/.arch-ids/toke.h.id toke/COPYING toke/ChangeLog + toke/Makefile toke/README toke/Rules.make toke/TODO + toke/dictionary.c toke/dictionary.h toke/emit.c toke/emit.h + toke/examples/.arch-ids/=id toke/examples/.arch-ids/case.fs.id + toke/examples/.arch-ids/date.fs.id + toke/examples/.arch-ids/display.fs.id + toke/examples/.arch-ids/fcdisp.fs.id + toke/examples/.arch-ids/fract.fs.id + toke/examples/.arch-ids/pciexample.fs.id + toke/examples/.arch-ids/primes.fs.id + toke/examples/.arch-ids/simple.fs.id + toke/examples/.arch-ids/version1.fs.id + toke/examples/.arch-ids/world.fs.id toke/examples/case.fs + toke/examples/date.fs toke/examples/display.fs + toke/examples/fcdisp.fs toke/examples/fract.fs + toke/examples/pciexample.fs toke/examples/primes.fs + toke/examples/scsi-sample/.arch-ids/=id + toke/examples/scsi-sample/.arch-ids/README.sample.id + toke/examples/scsi-sample/.arch-ids/hacom.fs.id + toke/examples/scsi-sample/.arch-ids/overall.fs.id + toke/examples/scsi-sample/.arch-ids/scsicom.fs.id + toke/examples/scsi-sample/.arch-ids/scsidisk.fs.id + toke/examples/scsi-sample/.arch-ids/scsiha.fs.id + toke/examples/scsi-sample/.arch-ids/scsitape.fs.id + toke/examples/scsi-sample/README.sample + toke/examples/scsi-sample/hacom.fs + toke/examples/scsi-sample/overall.fs + toke/examples/scsi-sample/scsicom.fs + toke/examples/scsi-sample/scsidisk.fs + toke/examples/scsi-sample/scsiha.fs + toke/examples/scsi-sample/scsitape.fs toke/examples/simple.fs + toke/examples/version1.fs toke/examples/world.fs toke/macros.c + toke/scanner.c toke/stack.c toke/stack.h toke/stream.c + toke/stream.h toke/toke.c toke/toke.h utils/.arch-ids/=id + utils/.arch-ids/README.id utils/README + utils/detok/.arch-ids/=id utils/detok/.arch-ids/COPYING.id + utils/detok/.arch-ids/ChangeLog.id + utils/detok/.arch-ids/Makefile.id + utils/detok/.arch-ids/README.id + utils/detok/.arch-ids/Rules.make.id + utils/detok/.arch-ids/decode.c.id + utils/detok/.arch-ids/detok.c.id + utils/detok/.arch-ids/detok.h.id + utils/detok/.arch-ids/dictionary.c.id + utils/detok/.arch-ids/stream.c.id + utils/detok/.arch-ids/stream.h.id utils/detok/COPYING + utils/detok/ChangeLog utils/detok/Makefile utils/detok/README + utils/detok/Rules.make utils/detok/decode.c + utils/detok/detok.c utils/detok/detok.h + utils/detok/dictionary.c utils/detok/stream.c + utils/detok/stream.h utils/devbios/.arch-ids/=id + utils/devbios/.arch-ids/COPYING.id + utils/devbios/.arch-ids/CREDITS.id + utils/devbios/.arch-ids/ChangeLog.id + utils/devbios/.arch-ids/Makefile.24.id + utils/devbios/.arch-ids/Makefile.id + utils/devbios/.arch-ids/README.bios.id + utils/devbios/.arch-ids/ToDo.id + utils/devbios/.arch-ids/bios.h.id + utils/devbios/.arch-ids/bios_core.c.id + utils/devbios/.arch-ids/comp.c.id + utils/devbios/.arch-ids/filesystem.c.id + utils/devbios/.arch-ids/flashchips.c.id + utils/devbios/.arch-ids/flashchips.h.id + utils/devbios/.arch-ids/pcisets.c.id + utils/devbios/.arch-ids/pcisets.h.id + utils/devbios/.arch-ids/procfs.c.id + utils/devbios/.arch-ids/programming.c.id + utils/devbios/.arch-ids/programming.h.id utils/devbios/COPYING + utils/devbios/CREDITS utils/devbios/ChangeLog + utils/devbios/Makefile utils/devbios/Makefile.24 + utils/devbios/README.bios utils/devbios/ToDo + utils/devbios/bios.h utils/devbios/bios_core.c + utils/devbios/comp.c utils/devbios/filesystem.c + utils/devbios/flashchips.c utils/devbios/flashchips.h + utils/devbios/pcisets.c utils/devbios/pcisets.h + utils/devbios/procfs.c utils/devbios/programming.c + utils/devbios/programming.h utils/fccc/.arch-ids/=id + utils/fccc/.arch-ids/COPYING.id utils/fccc/COPYING + utils/fccc/include/.arch-ids/=id + utils/fccc/include/.arch-ids/fccc-tools.h.id + utils/fccc/include/.arch-ids/fccc.h.id + utils/fccc/include/.arch-ids/linklist.h.id + utils/fccc/include/.arch-ids/parserfunctions.h.id + utils/fccc/include/.arch-ids/symboltable.h.id + utils/fccc/include/fccc-tools.h utils/fccc/include/fccc.h + utils/fccc/include/linklist.h + utils/fccc/include/parserfunctions.h + utils/fccc/include/symboltable.h utils/fccc/src/.arch-ids/=id + utils/fccc/src/.arch-ids/Makefile.id + utils/fccc/src/.arch-ids/fccc-tools.c.id + utils/fccc/src/.arch-ids/fccc.lex.id + utils/fccc/src/.arch-ids/fccc.y.id + utils/fccc/src/.arch-ids/linklist.c.id + utils/fccc/src/.arch-ids/plain_ass.c.id + utils/fccc/src/.arch-ids/symboltable.c.id + utils/fccc/src/Makefile utils/fccc/src/fccc-tools.c + utils/fccc/src/fccc.lex utils/fccc/src/fccc.y + utils/fccc/src/linklist.c utils/fccc/src/plain_ass.c + utils/fccc/src/symboltable.c utils/fccc/test/.arch-ids/=id + utils/fccc/test/.arch-ids/test1.c.id utils/fccc/test/test1.c + utils/romheaders/.arch-ids/=id + utils/romheaders/.arch-ids/Makefile.id + utils/romheaders/.arch-ids/romheaders.c.id + utils/romheaders/Makefile utils/romheaders/romheaders.c + {arch}/.arch-project-tree {arch}/=tagging-method + {arch}/openbios/openbios--main/openbios--main--1.0/stepan@openbios.org--devel/patch-log/base-0 + {arch}/openbios/openbios--porting/openbios--porting--0/oxygene@studentenbude.ath.cx--2004/patch-log/base-0 + {arch}/openbios/openbios--porting/openbios--porting--0/oxygene@studentenbude.ath.cx--2004/patch-log/patch-1 + {arch}/openbios/openbios--porting/openbios--porting--0/oxygene@studentenbude.ath.cx--2004/patch-log/patch-2 + {arch}/openbios/openbios--porting/openbios--porting--0/oxygene@studentenbude.ath.cx--2004/patch-log/patch-3 + + modified directories: + .arch-ids Documentation/.arch-ids + Documentation/kernel/.arch-ids arch/.arch-ids + arch/amd64/.arch-ids arch/ia64/.arch-ids arch/ppc/.arch-ids + arch/ppc/briq/.arch-ids arch/ppc/mol/.arch-ids + arch/unix/.arch-ids arch/unix/gui_qt/.arch-ids + arch/unix/plugins/.arch-ids + arch/unix/plugins/plugin_pci/.arch-ids + arch/unix/plugins/plugin_qt/.arch-ids arch/x86/.arch-ids + config/.arch-ids config/kconfig/.arch-ids + config/lxdialog/.arch-ids config/scripts/.arch-ids + dist/.arch-ids dist/debian/.arch-ids drivers/.arch-ids + forth/.arch-ids forth/admin/.arch-ids + forth/bootstrap/.arch-ids forth/debugging/.arch-ids + forth/device/.arch-ids forth/lib/.arch-ids + forth/packages/.arch-ids forth/system/.arch-ids + forth/testsuite/.arch-ids forth/util/.arch-ids fs/.arch-ids + fs/grubfs/.arch-ids fs/hfs/.arch-ids fs/hfs/include/.arch-ids + fs/hfsplus/.arch-ids fs/hfsplus/include/.arch-ids + include/.arch-ids include/amd64/.arch-ids + include/ia64/.arch-ids include/libc/.arch-ids + include/openbios/.arch-ids include/ppc/.arch-ids + include/unix/.arch-ids include/x86/.arch-ids kernel/.arch-ids + kernel/include/.arch-ids libc/.arch-ids modules/.arch-ids + toke/.arch-ids toke/examples/.arch-ids + toke/examples/scsi-sample/.arch-ids utils/.arch-ids + utils/detok/.arch-ids utils/devbios/.arch-ids + utils/fccc/.arch-ids utils/fccc/include/.arch-ids + utils/fccc/src/.arch-ids utils/fccc/test/.arch-ids + utils/romheaders/.arch-ids {arch} {arch}/openbios + {arch}/openbios/openbios--main + {arch}/openbios/openbios--main/openbios--main--1.0 + {arch}/openbios/openbios--main/openbios--main--1.0/stepan@openbios.org--devel + {arch}/openbios/openbios--main/openbios--main--1.0/stepan@openbios.org--devel/patch-log + {arch}/openbios/openbios--porting + {arch}/openbios/openbios--porting/openbios--porting--0 + {arch}/openbios/openbios--porting/openbios--porting--0/oxygene@studentenbude.ath.cx--2004 + {arch}/openbios/openbios--porting/openbios--porting--0/oxygene@studentenbude.ath.cx--2004/patch-log + + new patches: + oxygene@studentenbude.ath.cx--2004/openbios--porting--0--patch-4 + + +2004-09-01 19:03:41 GMT Stefan Reinauer <stepan@openbios.org> patch-1 + + Summary: + + Revision: + openbios--main--1.0--patch-1 + + + + Patches applied: + + * oxygene@studentenbude.ath.cx--2004/openbios--porting--0--base-0 + tag of stepan@openbios.org--devel/openbios--main--1.0--base-0 + + * oxygene@studentenbude.ath.cx--2004/openbios--porting--0--patch-1 + changes to make it build on dragonflybsd + + * oxygene@studentenbude.ath.cx--2004/openbios--porting--0--patch-2 + no need for the uue hack anymore + + * oxygene@studentenbude.ath.cx--2004/openbios--porting--0--patch-3 + check for stack protector for gcc and disable if present + + + new files: + forth/device/.arch-ids/romfont.bin.id forth/device/romfont.bin + + removed files: + forth/device/.arch-ids/romfont.uue.id forth/device/romfont.uue + + modified files: + Documentation/ChangeLog.arch arch/unix/unix.c + arch/x86/builtin.c config/configure.in drivers/ide.h + forth/device/Makefile include/openbios/kernel.h + include/x86/types.h {arch}/=tagging-method + + new patches: + oxygene@studentenbude.ath.cx--2004/openbios--porting--0--base-0 + oxygene@studentenbude.ath.cx--2004/openbios--porting--0--patch-1 + oxygene@studentenbude.ath.cx--2004/openbios--porting--0--patch-2 + oxygene@studentenbude.ath.cx--2004/openbios--porting--0--patch-3 + + +2004-08-29 13:29:22 GMT Stefan Reinauer <stepan@openbios.org> base-0 + + Summary: + initial import + Revision: + openbios--main--1.0--base-0 + + + (automatically generated log message) + + new files: + COPYING Documentation/ChangeLog.arch + Documentation/kernel/AUTHORS Documentation/kernel/COPYING + Documentation/kernel/Changelog.stepan + Documentation/kernel/TODO Documentation/kernel/dictformat.txt + Documentation/kernel/glossary.txt + Documentation/kernel/initializers.txt Makefile README + arch/amd64/Kconfig arch/amd64/Makefile arch/amd64/Makefile.asm + arch/amd64/boot.c arch/amd64/builtin.c arch/amd64/console.c + arch/amd64/context.c arch/amd64/context.h arch/amd64/defconfig + arch/amd64/elfload.c arch/amd64/init.fs arch/amd64/ldscript + arch/amd64/lib.c arch/amd64/linux_load.c arch/amd64/loadfs.c + arch/amd64/loadfs.h arch/amd64/multiboot.c + arch/amd64/multiboot.h arch/amd64/openbios.c + arch/amd64/openbios.h arch/amd64/plainboot.c + arch/amd64/relocate.h arch/amd64/segment.c + arch/amd64/segment.h arch/amd64/switch.S arch/amd64/sys_info.c + arch/ia64/Kconfig arch/ia64/Makefile arch/ia64/Makefile.asm + arch/ia64/defconfig arch/ia64/init.fs arch/ppc/Kconfig + arch/ppc/Makefile arch/ppc/Makefile.asm arch/ppc/briq/briq.c + arch/ppc/briq/briq.fs arch/ppc/briq/briq.h + arch/ppc/briq/init.c arch/ppc/briq/kernel.c + arch/ppc/briq/main.c arch/ppc/briq/methods.c + arch/ppc/briq/tree.c arch/ppc/briq/tree.fs arch/ppc/briq/vfd.c + arch/ppc/defconfig arch/ppc/kernel.c arch/ppc/kernel.h + arch/ppc/misc.S arch/ppc/mmutypes.h arch/ppc/mol/console.c + arch/ppc/mol/font_8x8.c arch/ppc/mol/init.c + arch/ppc/mol/kernel.c arch/ppc/mol/main.c + arch/ppc/mol/methods.c arch/ppc/mol/mol.c arch/ppc/mol/mol.fs + arch/ppc/mol/mol.h arch/ppc/mol/osi-blk.c + arch/ppc/mol/osi-scsi.c arch/ppc/mol/prom.c + arch/ppc/mol/prom.h arch/ppc/mol/pseudodisk.c + arch/ppc/mol/tree.c arch/ppc/mol/tree.fs arch/ppc/mol/video.c + arch/ppc/ofmem.c arch/ppc/osi.h arch/ppc/osi_calls.h + arch/ppc/ppc.fs arch/ppc/start.S arch/ppc/timebase.S + arch/unix/Kconfig arch/unix/Makefile arch/unix/blk.c + arch/unix/blk.h arch/unix/boot.c arch/unix/gui_qt/Makefile + arch/unix/gui_qt/gui-qt.cpp arch/unix/gui_qt/gui-qt.h + arch/unix/gui_qt/gui-qt.pro arch/unix/gui_qt/logo.xpm + arch/unix/gui_qt/qt-main.cpp arch/unix/plugins.c + arch/unix/plugins/Kconfig arch/unix/plugins/Makefile + arch/unix/plugins/Rules.plugin arch/unix/plugins/loader.c + arch/unix/plugins/plugin_pci/Makefile + arch/unix/plugins/plugin_pci/Makefile.old + arch/unix/plugins/plugin_pci/plugin_pci.c + arch/unix/plugins/plugin_qt/Makefile + arch/unix/plugins/plugin_qt/logo.xpm + arch/unix/plugins/plugin_qt/pciconfig.h + arch/unix/plugins/plugin_qt/plugin_qt.cpp + arch/unix/plugins/plugin_qt/plugin_qt.h + arch/unix/plugins/plugin_qt/plugin_qt.pro + arch/unix/plugins/plugin_qt/qt_main.cpp + arch/unix/plugins/plugin_qt/qt_rom.fs arch/unix/tree.fs + arch/unix/unix.c arch/x86/Kconfig arch/x86/Makefile + arch/x86/Makefile.asm arch/x86/boot.c arch/x86/boot.h + arch/x86/builtin.c arch/x86/console.c arch/x86/context.c + arch/x86/context.h arch/x86/defconfig arch/x86/elfload.c + arch/x86/forthload.c arch/x86/init.fs arch/x86/ldscript + arch/x86/lib.c arch/x86/linux_load.c arch/x86/loadfs.c + arch/x86/loadfs.h arch/x86/multiboot.c arch/x86/multiboot.h + arch/x86/openbios.c arch/x86/openbios.h arch/x86/plainboot.c + arch/x86/relocate.h arch/x86/segment.c arch/x86/segment.h + arch/x86/switch.S arch/x86/sys_info.c autogen.sh + config/Makefile config/Makefile.defs.in config/Makefile.master + config/Makefile.top config/Rules.forth config/Rules.make + config/configure.in config/kconfig/Makefile + config/kconfig/conf.c config/kconfig/confdata.c + config/kconfig/expr.c config/kconfig/expr.h + config/kconfig/lkc.h config/kconfig/lkc_proto.h + config/kconfig/mconf.c config/kconfig/menu.c + config/kconfig/symbol.c config/kconfig/zconf-l.l + config/kconfig/zconf-y.y config/lxdialog/Makefile + config/lxdialog/checklist.c config/lxdialog/colors.h + config/lxdialog/dialog.h config/lxdialog/inputbox.c + config/lxdialog/lxdialog.c config/lxdialog/menubox.c + config/lxdialog/msgbox.c config/lxdialog/textbox.c + config/lxdialog/util.c config/lxdialog/yesno.c + config/scripts/archname config/scripts/reldir configure + dist/debian/changelog dist/debian/control dist/debian/packages + dist/debian/rules dist/openbios.spec drivers/Kconfig + drivers/Makefile drivers/hdreg.h drivers/ide.c drivers/ide.fs + drivers/ide.h drivers/pci.c drivers/pci.fs drivers/pci.h + drivers/timer.c drivers/timer.h forth/Kconfig forth/Makefile + forth/admin/Makefile forth/admin/README forth/admin/banner.fs + forth/admin/callback.fs forth/admin/devices.fs + forth/admin/help.fs forth/admin/iocontrol.fs + forth/admin/nvram.fs forth/admin/reset.fs + forth/admin/script.fs forth/admin/security.fs + forth/admin/selftest.fs forth/admin/userboot.fs + forth/bootstrap/bootstrap.fs forth/bootstrap/builtin.fs + forth/bootstrap/hayes.fs forth/bootstrap/interpreter.fs + forth/bootstrap/memory.fs forth/bootstrap/start.fs + forth/debugging/Makefile forth/debugging/client.fs + forth/debugging/fcode.fs forth/debugging/firmware.fs + forth/debugging/see.fs forth/device/Makefile + forth/device/README.device forth/device/builtin.fs + forth/device/device.fs forth/device/display.fs + forth/device/extra.fs forth/device/fcode.fs + forth/device/feval.fs forth/device/font.fs + forth/device/logo.fs forth/device/missing + forth/device/other.fs forth/device/package.fs + forth/device/pathres.fs forth/device/preof.fs + forth/device/property.fs forth/device/romfont.uue + forth/device/structures.fs forth/device/table.fs + forth/device/terminal.fs forth/device/tree.fs + forth/lib/Makefile forth/lib/creation.fs forth/lib/lists.fs + forth/lib/preprocessor.fs forth/lib/split.fs + forth/lib/string.fs forth/lib/vocabulary.fs + forth/packages/Kconfig forth/packages/Makefile + forth/packages/README forth/packages/deblocker.fs + forth/packages/disklabel.fs forth/packages/obp-tftp.fs + forth/packages/packages.fs forth/packages/terminal-emulator.fs + forth/system/Makefile forth/system/ciface.fs + forth/system/main.fs forth/testsuite/Makefile + forth/testsuite/README forth/testsuite/fract.fs + forth/testsuite/framebuffer-test.fs + forth/testsuite/memory-testsuite.fs + forth/testsuite/splitfunc-testsuite.fs forth/util/Makefile + forth/util/apic.fs forth/util/pci.fs forth/util/util.fs + fs/Makefile fs/grubfs/Kconfig fs/grubfs/Makefile + fs/grubfs/debug.h fs/grubfs/defs.h fs/grubfs/dir.h + fs/grubfs/disk_inode.h fs/grubfs/disk_inode_ffs.h + fs/grubfs/fat.h fs/grubfs/filesys.h fs/grubfs/fs.h + fs/grubfs/fsys_affs.c fs/grubfs/fsys_ext2fs.c + fs/grubfs/fsys_fat.c fs/grubfs/fsys_ffs.c + fs/grubfs/fsys_iso9660.c fs/grubfs/fsys_jfs.c + fs/grubfs/fsys_minix.c fs/grubfs/fsys_ntfs.c + fs/grubfs/fsys_reiserfs.c fs/grubfs/fsys_vstafs.c + fs/grubfs/fsys_xfs.c fs/grubfs/glue.h fs/grubfs/grubfs_fs.c + fs/grubfs/iso9660.h fs/grubfs/jfs.h fs/grubfs/shared.h + fs/grubfs/vstafs.h fs/grubfs/xfs.h fs/hfs/Makefile + fs/hfs/block.c fs/hfs/btree.c fs/hfs/data.c fs/hfs/file.c + fs/hfs/hfs.c fs/hfs/hfs_fs.c fs/hfs/include/apple.h + fs/hfs/include/block.h fs/hfs/include/btree.h + fs/hfs/include/data.h fs/hfs/include/file.h + fs/hfs/include/hfs.h fs/hfs/include/libhfs.h + fs/hfs/include/low.h fs/hfs/include/medium.h + fs/hfs/include/node.h fs/hfs/include/record.h + fs/hfs/include/volume.h fs/hfs/low.c fs/hfs/medium.c + fs/hfs/node.c fs/hfs/record.c fs/hfs/volume.c fs/hfs_mdb.h + fs/hfsplus/Makefile fs/hfsplus/blockiter.c fs/hfsplus/btree.c + fs/hfsplus/hfsp_fs.c fs/hfsplus/include/apple.h + fs/hfsplus/include/blockiter.h fs/hfsplus/include/btree.h + fs/hfsplus/include/hfs.h fs/hfsplus/include/hfsp.h + fs/hfsplus/include/hfstime.h fs/hfsplus/include/libhfsp.h + fs/hfsplus/include/record.h fs/hfsplus/include/swab.h + fs/hfsplus/include/unicode.h fs/hfsplus/include/volume.h + fs/hfsplus/libhfsp.c fs/hfsplus/record.c fs/hfsplus/unicode.c + fs/hfsplus/volume.c fs/ioglue.c fs/os.h include/amd64/elf.h + include/amd64/io.h include/amd64/types.h include/elf_boot.h + include/ia64/elf.h include/ia64/io.h include/ia64/types.h + include/ipchecksum.h include/libc/byteorder.h + include/libc/diskio.h include/libc/stdlib.h + include/libc/string.h include/libc/vsprintf.h include/ofmem.h + include/openbios/asm.m4 include/openbios/bindings.h + include/openbios/config.h include/openbios/drivers.h + include/openbios/elf.h include/openbios/elfload.h + include/openbios/fs.h include/openbios/kernel.h + include/openbios/nvram.h include/openbios/of.h + include/openbios/stack.h include/openbios/sysinclude.h + include/ppc/asmdefs.h include/ppc/elf.h include/ppc/io.h + include/ppc/processor.h include/ppc/types.h include/sys_info.h + include/unix/plugin_pci.h include/unix/plugins.h + include/x86/elf.h include/x86/io.h include/x86/pci.h + include/x86/types.h kernel/Kconfig kernel/Makefile + kernel/README kernel/bootstrap.c kernel/dict.c kernel/forth.c + kernel/include/dict.h kernel/internal.c kernel/primitives.c + kernel/stack.c libc/Makefile libc/byteorder.c libc/ctype.c + libc/diskio.c libc/extra.c libc/misc.c libc/string.c + libc/vsprintf.c modules/Kconfig modules/Makefile + modules/bindings.c modules/clib.fs modules/client.c + modules/cmdline.c modules/deblocker.c modules/disk-label.c + modules/elfload.c modules/elfnote.c modules/filesystems.c + modules/helpers.fs modules/init.c modules/ipchecksum.c + modules/linuxbios.c modules/linuxbios.h modules/mac-parts.c + modules/mac-parts.h modules/modules.h modules/nvram.c + modules/pc-parts.c modules/support.fs setup_links toke/COPYING + toke/ChangeLog toke/Makefile toke/README toke/Rules.make + toke/TODO toke/dictionary.c toke/dictionary.h toke/emit.c + toke/emit.h toke/examples/case.fs toke/examples/date.fs + toke/examples/display.fs toke/examples/fcdisp.fs + toke/examples/fract.fs toke/examples/pciexample.fs + toke/examples/primes.fs + toke/examples/scsi-sample/README.sample + toke/examples/scsi-sample/hacom.fs + toke/examples/scsi-sample/overall.fs + toke/examples/scsi-sample/scsicom.fs + toke/examples/scsi-sample/scsidisk.fs + toke/examples/scsi-sample/scsiha.fs + toke/examples/scsi-sample/scsitape.fs toke/examples/simple.fs + toke/examples/version1.fs toke/examples/world.fs toke/macros.c + toke/scanner.c toke/stack.c toke/stack.h toke/stream.c + toke/stream.h toke/toke.c toke/toke.h utils/README + utils/detok/COPYING utils/detok/ChangeLog utils/detok/Makefile + utils/detok/README utils/detok/Rules.make utils/detok/decode.c + utils/detok/detok.c utils/detok/detok.h + utils/detok/dictionary.c utils/detok/stream.c + utils/detok/stream.h utils/devbios/COPYING + utils/devbios/CREDITS utils/devbios/ChangeLog + utils/devbios/Makefile utils/devbios/Makefile.24 + utils/devbios/README.bios utils/devbios/ToDo + utils/devbios/bios.h utils/devbios/bios_core.c + utils/devbios/comp.c utils/devbios/filesystem.c + utils/devbios/flashchips.c utils/devbios/flashchips.h + utils/devbios/pcisets.c utils/devbios/pcisets.h + utils/devbios/procfs.c utils/devbios/programming.c + utils/devbios/programming.h utils/fccc/COPYING + utils/fccc/include/fccc-tools.h utils/fccc/include/fccc.h + utils/fccc/include/linklist.h + utils/fccc/include/parserfunctions.h + utils/fccc/include/symboltable.h utils/fccc/src/Makefile + utils/fccc/src/fccc-tools.c utils/fccc/src/fccc.lex + utils/fccc/src/fccc.y utils/fccc/src/linklist.c + utils/fccc/src/plain_ass.c utils/fccc/src/symboltable.c + utils/fccc/test/test1.c utils/romheaders/Makefile + utils/romheaders/romheaders.c + + diff --git a/qemu/roms/openbios/Documentation/README.debugger b/qemu/roms/openbios/Documentation/README.debugger new file mode 100644 index 000000000..a44f5a857 --- /dev/null +++ b/qemu/roms/openbios/Documentation/README.debugger @@ -0,0 +1,50 @@ +The following Forth words can be used for debugging: + + debug <xt> - Mark word for debugging + debug-off - Unmark all words for debugging + resume - Return from subordinate Forth interpreter + +The source debugger also implements the following commands when it has been activated: + + Up - Unmark current word for debugging, mark parent and continue + Down - Mark next word for debugging + Trace - Continue execution until end of word displaying + debug information + Rstack - Display contents of the Rstack + Forth - Launch subordinate Forth interpreter + +An example session: +0 > see boot +: boot + linefeed parse cr " platform-boot" $find if + execute then + 2drop cr " Booting " type type cr " ... not supported on this system." type cr + ; + ok +0 > debug boot +Stepper keys: <space>/<enter> Up Down Trace Rstack Forth + ok +0 > boot +: boot ( Empty ) +00000000ffe26b08: linefeed ( a ) +00000000ffe26b10: parse ( ffec6e24 0 ) +00000000ffe26b18: cr + ( ffec6e24 0 ) +00000000ffe26b20: (") ( ffec6e24 0 ffe26b30 d ) +00000000ffe26b40: $find ( ffec6e24 0 ffe31710 ffffffffffffffff ) +00000000ffe26b48: do?branch ( ffec6e24 0 ffe31710 ) +00000000ffe26b58: execute [sparc64] Booting file 'cdrom' with parameters '' +Not a bootable ELF image +Not a Linux kernel image +Not a bootable a.out image +Loading FCode image... +Loaded 5936 bytes +entry point is 0x4000 +Evaluating FCode... +open isn't unique. +Boot load failed. + ( Empty ) +00000000ffe26b60: dobranch ( Empty ) +00000000ffe26bf8: (semis) +[ Finished boot ] ok +0 > diff --git a/qemu/roms/openbios/Documentation/TODO.sparc b/qemu/roms/openbios/Documentation/TODO.sparc new file mode 100644 index 000000000..1dda96f6e --- /dev/null +++ b/qemu/roms/openbios/Documentation/TODO.sparc @@ -0,0 +1,64 @@ +TODO-list: + +Sparc common: +- Unimplemented features/bugs: + - Send keycode on keypress + - Remove compiler warnings + - Clean up + +- Optimizations/improvements: + - Merge allocators (lib.c malloc, romvec opb_, iommu, OF /memory, Sparc64) + - Warm reset detection + - Boot logo + +Sparc32: +- Unimplemented features/bugs: + - Some console escape codes (Debian 3.1R1, NetBSD) + - Arbitrary resolution support + - Add cg6, bwtwo + - Probe devices (like Proll?) + - Less fixed hardware choices, conditional HW + - SBus slot probing, FCode ROM support + - Compile for least capable CPU + - DBRI audio (Am7930) + - BPP parallel + - Diagnostic switch + +Sparc64: +- Unimplemented features/bugs: + - Debug direct kernel boot + - Boot from drive, cdrom or floppy + +- Optimizations/improvements: + - Hypervisor + +Sun4: +- Support to be added + +Sun4c: +- Support to be added + +Sun4m: +- Unimplemented features/bugs: + - JavaStation machines + - Realistic SMP probing + - SS600MP ledma -> lebuffer + +Sun4d: +- Support to be added + +Sun4u: +- Unimplemented features/bugs: + - Interrupt controller setup + - PCI/IOMMU support (Simba, JIO, Tomatillo, Psycho, Schizo, Safari...) + - SMP/CMT + - Happy Meal Ethernet, flash, I2C, GPIO + - A lot of real machine types + +Sun4v: +- Support to be added + +Ideas: + - Real machine test with special entry.S + - Unix compile with uClibc + - Sparc64: Emulate hypervisor so that OpenBoot image can be used diff --git a/qemu/roms/openbios/Documentation/kernel/AUTHORS b/qemu/roms/openbios/Documentation/kernel/AUTHORS new file mode 100644 index 000000000..365e098db --- /dev/null +++ b/qemu/roms/openbios/Documentation/kernel/AUTHORS @@ -0,0 +1,6 @@ +The OpenBIOS forth engine was written by + + Patrick Mauritz <oxygene@openbios.info> + Stefan Reinauer <stepan@openbios.info> + +# tag: list of authors diff --git a/qemu/roms/openbios/Documentation/kernel/COPYING b/qemu/roms/openbios/Documentation/kernel/COPYING new file mode 100644 index 000000000..91f234ff1 --- /dev/null +++ b/qemu/roms/openbios/Documentation/kernel/COPYING @@ -0,0 +1,358 @@ +All or most of the source files in this distribution refer to this +file for copyright and warranty information. This file should be +included whenever those files are redistributed. + +This software is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License, version 2, as +published by the Free Software Foundation. This license is reproduced +below. + +Please note that we explicitely do not allow applying any newer version +of the GPL to this work. Once the FSF releases such a revision we will +reconsider to allow it as well. + +----------------- verbatim license text below --------------------- + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) 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 +this service 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 make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. 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. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute 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 and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +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 +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the 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 a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, 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. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE 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. + + 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 +convey 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 2 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, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision 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, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + <signature of Ty Coon>, 1 April 1989 + Ty Coon, President of Vice + +This 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 Library General +Public License instead of this License. + +# tag: General Public License text +# diff --git a/qemu/roms/openbios/Documentation/kernel/Changelog.stepan b/qemu/roms/openbios/Documentation/kernel/Changelog.stepan new file mode 100644 index 000000000..1b4d5344f --- /dev/null +++ b/qemu/roms/openbios/Documentation/kernel/Changelog.stepan @@ -0,0 +1,300 @@ +# tag: stepan's changelog for CVS + +Mon Jul 14 02:16:49 CEST 2003 + - fix segv overrun while dumping dictionary in unix.c + - implement first version of >number and $number + - add stack diagram to digit + - no newline after accept + - new version of the interpreter + - fix make run target + +Mon Jul 14 20:15:40 CEST 2003 + - negate true value in prims + - get rid of primitive word bounds. + - get rid of some obsolete code. + - implement io[cwl][@!] + - reorganize [in|out][bwl] + - start adding stack diagrams to primitives. + +Mon Jul 14 23:57:46 CEST 2003 + - added some more stack diagrams in forth.h + - move parse, parse-word, word to bootstrap.fs + - include memory.fs from bootstrap.fs for above. + +Wed Jul 16 22:57:31 CEST 2003 + - add include guards + - add banner + - fix primitives' dependencies + +Sun Jul 20 03:27:40 CEST 2003 + - remove unneeded readcell + - rename ' to ['] to meet specs + +Sun Jul 20 14:08:43 CEST 2003 + - add rest of stack diagrams in forth.h + - move here and here! to forth.h (from internal.h) + - indent includes + - merge system.h into forth.h + - Change tag of forth.h (!) because the old one + did not meet the meaning of the code. + - update comments in primitives.c + +Sun Jul 27 01:53:18 CEST 2003 + - include great new do/?do/loop/+loop + implementation from Patrick. + - include testsuite enhancement from Patrick + - include trampoline from Patrick (fixes execute) + +Sun Jul 27 21:11:50 CEST 2003 + - update x86 console code to become when using + multiboot (vga/keyboard). + - fix exit properly + - revert to old case..endcase code + - fix >number and $number + - add number parsing to interpreter + - add simple stack checking to interpreter + - add 2 testcases (exit and case2) + +Mon Jul 28 14:49:31 CEST 2003 + - move 7.3.7 Flag constants up in bootstrap.fs + - move 7.3.9.2.4 Miscellaneous dictionary down. + - add reveal, recursive, recurse, environment? to 7.3.9.2.4 + - move (to) to bootstrap.fs + +Mon Jul 28 17:08:58 CEST 2003 + - add stack overflow check to interpreter + - check parse-word result in interpreter. + - add ascii and char, add helper handle-lit + +Tue Jul 29 09:20:18 CEST 2003 + - add s" and ." + - add [char] and control + - heavily move around words in bootstrap.fs + to get dependencies resolved. + - fix skipws crash + - rename query to refill + - interpreter reads several words in a line now + - interpreter stops now if error encountered in + currently parsed line. + - add forth definitions of ( and \ + - change c parser/interpreter to handle comments + correctly. + - indent, clean up unix.c + +Tue Jul 29 18:13:27 CEST 2003 + - add .( (chapter 7.3.4.4) + - add pack, -trailing (chapter 7.3.4.8) + - add d#, h#, o# (chapter 7.3.5.2) + - let first stack element start at 1 instead of 0 + to have a 1 cell guard band. + - set SA_NODEFER flag to signal handler to ensure + that it is entered recursively. + +Tue Jul 29 19:06:18 CEST 2003 + - more simplification for unix.c + - add ', ['], find + - fix pack, count + - add literal, compile, [compile], compile, + - fix [ + +Wed Jul 30 01:24:24 CEST 2003 + - add >body, body> + - add helpers: flags?, immediate?, compile-only?, header + - add :, ;, constant, value, variable, buffer: + - parse word's flags in interpreter to make colon + definitions work + - add "compiled" acknowledge when interpreter is in compile mode + +Wed Jul 30 07:27:58 CEST 2003 + - fix flags handling in interpreter + - fix handle-text compile mode behaviour + - add defer, struct, field + - add behaviour, to + - add $create, create, does> (missing c code DODOES) + - add abort + +Thu Jul 31 07:58:35 CEST 2003 + - fix DODOES cfa code + - make 2@ and 2! colon definitions instead of primitives. + - add word "cell" + - add warning message as described in 7.3.9.1 if an already + existing word is created + +Fri Aug 1 23:32:57 CEST 2003 + - fix s" in C interpreter (compare case insensitive) + - fix forth source dependencies + - fix forth word sm/rem + +Sat Aug 2 13:34:43 CEST 2003 + - add band guard around input buffer + - make sure that "header" pads null bytes + - define -1,0,1,2,3 early to safe dictionary space + +Sat Aug 2 16:58:31 CEST 2003 + - use getopt/getopt_long for option parsing + - add include path option -I to unix + - don't create obsolete symlink in forth/Makefile + - fix recurse + - fix prim word / + - implement postpone + - fix 2!, ['] and ' + - implement evaluate/eval + +Sun Aug 3 11:48:18 CEST 2003 + - implement "bye" to leave the engine + - change initial word to "initialize" and + make quit restart the forth engine. + - fix missing ; in u. + - fix return value of find when handling an immediate + - getting rid of primitives mod, /mod and /, replacing + them by floored variants as IEEE 1275-1994 says. + - clean up primitives. + +Sun Aug 3 23:06:39 CEST 2003 + - fix >body, body> + - make not a synonym for invert as described in IEEE 1275 + - todigit can now switch between capital and small letters via + value capital-hex? + +Mon Aug 4 21:57:06 CEST 2003 + - indent unix.c + - reimplement do, ?do, loop, +loop with prim helpers. It now + passes hayes' ans forth test suite. + - adopt unix.c and bootstrap.fs to new (?)do..(+)loop + - remove unneeded if around ?do..loop in ", + - interpreter: clear input buffer before refilling it + - serialize PC changes in dobranch and do?branch + +Thu Aug 7 19:00:43 CEST 2003 + - add/change missing/incomplete copyright notices + - implement " + +Sun Aug 10 19:52:20 CEST 2003 + - reimplement catch, through + - implement abort" + - rephrase endcase + - change interpreter to use exception words + - implement forget + - add dummy "forth" + +Sun Aug 10 22:12:28 CEST 2003 + - fix "spaces" + - create subdir util for types.sh and new bin2hex + - enable forth.html again, running hayes test suite. + - include dictionary in char array instead of elf section + when building an x86 "full" image + - don't newline in accept. + - fix " compile mode behavior. + - move throw/catch and use it with ' and ['] + - add :noname + +Thu Aug 14 23:02:15 CEST 2003 + - fix "field" + - implement second stage bootstrapping + NOTE: changes dictionary format! + - drop initxt from dictionary, since we know "last" now. + - output dictionary can be named on command line. + - make segfault handler optional + +Mon Sep 1 19:41:23 CEST 2003 + - move findword() et al to dict.c (needed by openbios.c due + to last dictionary change) + - fix findword() return values and optimize it slightly. + - indented some files. + +Mon Sep 8 22:43:55 CEST 2003 + - add initial AMD64 support (cloned x86 target) + - get vocabulary implementation working. maybe buggy, but operable + - enable vocabulary support by default (vocabularies? set to true) + - drop duplicate "forth" + - fix some comments in forth files. + +Sun Sep 28 14:26:41 CEST 2003 + - some documentation and comment fixes + - fix parameter passing for io words. + +Thu Oct 2 08:21:06 CEST 2003 + - clean up lit + - inline some functions from internal.h (reduces size and execution + time) + +Fri Oct 3 15:20:44 CEST 2003 + - make i and j primitives. This safes a lot of time in loops. + i.e. the following dummy loop executes 300% faster: + : fbar 1000 0 do 1000 0 do j drop i drop loop loop ; + +Sat Oct 11 20:18:22 CEST 2003 + - include plugin interface for unix hosted version. + - add plugin_pci and plugin_qt as examples. + - add simple set of pci functions for testing the pci plugin + - add state variable "runforth" to be changed by the qt plugin + on exit. + +Sun Oct 12 14:57:54 CEST 2003 + - move internal.h and forth.h to kernel/ + - replace make by $(MAKE) in some places. + +Tue Oct 14 01:06:39 CEST 2003 + - add (immediate) and (compile-only) + +Wed Oct 15 00:52:49 CEST 2003 + - check whether dlopen() needs libdl. + - include BSD compile fixes from oxygene + - fix abort" + +Tue Oct 21 22:08:00 CEST 2003 + - fix forth.html dependencies + - yet another indent orgy + +Thu Oct 30 16:10:01 CET 2003 + - add "call" to execute native code functions + - plugin_qt: fix framebuffer address on 64bit systems + - plugin_pci: create position independent code. + +Wed Nov 5 08:38:18 CET 2003 + - fix "comp" (from Samuel Rydh) + - include instance support (from Samuel Rydh) + +Sun Nov 9 15:53:33 CET 2003 + - some changes for "see" + - apply more patches from Samuel. + - smaller, better implementation of handle-text + +Mon Nov 10 22:06:32 CET 2003 + - increase max dictionary size from 64k to 128k + - add simple fcode to qt plugin + - fix handle-text (move null-align up) + +Tue Nov 11 22:53:27 CET 2003 + - rename ?key to key?. + - clean up .s + - add (cr + +Tue Nov 17 22:42:54 CET 2003 + - enterforth rstack fix (from Samuel) + - include latest version of qt interface + fcode driver + - fix "header" (from Samuel) + +Wed Nov 26 15:12:07 CET 2003 + - merge patches from Samuel: + - add $buffer: + - fill all of "ib", not only 80 characters + - interpreted conditionals support + - late initializers + +Sun Nov 30 23:04:28 CET 2003 + - fix bug in enterforth (non-colon words would destroy PC) + +Sat Dec 13 00:57:01 CET 2003 + - add initial ppc infrastructure + - only search current wordlist in "header" + - seperate unix host binary and bootstrap interpreter. + +Sun Dec 14 18:13:29 CET 2003 + - add sys-debug word and use it to stop forth interpreter + during bootstrap if an error occurs. + +Sat Mar 13 16:30:30 CET 2004 + - fix digit problem + diff --git a/qemu/roms/openbios/Documentation/kernel/TODO b/qemu/roms/openbios/Documentation/kernel/TODO new file mode 100644 index 000000000..82ebf7b3e --- /dev/null +++ b/qemu/roms/openbios/Documentation/kernel/TODO @@ -0,0 +1,11 @@ +TODO + +booting + * support more arches than x86+amd64 + * compressed + rommable dictionary + +forth bootstrap + * make prompt configurable + * check state-variable when defining a new word. + +tag: TODO for the forth system diff --git a/qemu/roms/openbios/Documentation/kernel/dictformat.txt b/qemu/roms/openbios/Documentation/kernel/dictformat.txt new file mode 100644 index 000000000..431e2cd3c --- /dev/null +++ b/qemu/roms/openbios/Documentation/kernel/dictformat.txt @@ -0,0 +1,8 @@ +# tag: contains a description of the dictionary format + +name | length of name in bytes + 0x80 | align with 0's | flags (bit 7 set) | LFA | CFA | PFA + +LFA == link field address (backlink) +CFA == code field address ("word type") +PFA == program field address (definitions) + diff --git a/qemu/roms/openbios/Documentation/kernel/glossary.txt b/qemu/roms/openbios/Documentation/kernel/glossary.txt new file mode 100644 index 000000000..74785f121 --- /dev/null +++ b/qemu/roms/openbios/Documentation/kernel/glossary.txt @@ -0,0 +1,14 @@ +# tag: glossary of openbios forth + +# dictionary +LFA == link field address (backlink) +CFA == code field address ("word type") +PFA == program field address (definitions) + +# forth engine +TIB == text input buffer + +inner interpreter: interprets dictionary, does threading +outer interpreter: "user" interpreter, reads forth words from user. + + diff --git a/qemu/roms/openbios/Documentation/kernel/initializers.txt b/qemu/roms/openbios/Documentation/kernel/initializers.txt new file mode 100644 index 000000000..18a8e23a7 --- /dev/null +++ b/qemu/roms/openbios/Documentation/kernel/initializers.txt @@ -0,0 +1,24 @@ + +Initializers are called when the forth kernel is started, to do some +initialization stuff. +Pro: If code needs initialization you can keep this in place with the code +and don't need to patch the kernel itself to do so. + +There are 2 types of initializers. "Normal" and "Late" initializers. + +Since initializers are only called during startup, they don't need a name. + +Definition: + initializer ( xt -- ) + late-initializer ( xt -- ) + +Examples: + :noname <definition> ; initializer + + :noname + some-base initializations + ; late-initializer + +Late initializers are run after all ordinary initializers have +been executed. + diff --git a/qemu/roms/openbios/Makefile b/qemu/roms/openbios/Makefile new file mode 100644 index 000000000..172f4507b --- /dev/null +++ b/qemu/roms/openbios/Makefile @@ -0,0 +1,51 @@ +include config-host.mak + +all: requirements info build + +requirements: + @which xsltproc &>/dev/null || ( echo ; echo "Please install libxslt2"; \ + echo; exit 1 ) + +info: + @echo "Building OpenBIOS for $(TARGETS)" + +clean: + @echo "Cleaning up..." + @for dir in $(ODIRS); do \ + $(MAKE) -C $$dir clean; \ + done + +build: start-build + @for dir in $(ODIRS); do \ + $(MAKE) -C $$dir > $$dir/build.log 2>&1 && echo "ok." || \ + ( echo "error:"; tail -15 $$dir/build.log; exit 1 ) \ + done + +SUBDIR_RULES=$(patsubst %,subdir-%, $(TARGETS)) +SUBDIR_MAKEFLAGS=$(if $(V),,--no-print-directory) + +quiet-command = $(if $(V),$1,$(if $(2),@echo $2 && $1, @$1)) + +build-verbose: start-build $(SUBDIR_RULES) + +subdir-%: + $(call quiet-command,$(MAKE) $(SUBDIR_MAKEFLAGS) -C obj-$* V="$(V)" all,) + +start-build: + @echo "Building..." + +run: + @echo "Running..." + @for dir in $(ODIRS); do \ + $$dir/openbios-unix $$dir/openbios-unix.dict; \ + done + + +# The following two targets will only work on x86 so far. +# +$(ODIR)/openbios.iso: $(ODIR)/openbios.multiboot $(ODIR)/openbios-x86.dict + @mkisofs -input-charset UTF-8 -r -b boot/grub/stage2_eltorito -no-emul-boot \ + -boot-load-size 4 -boot-info-table -o $@ utils/iso $^ + +runiso: $(ODIR)/openbios.iso + qemu -cdrom $^ diff --git a/qemu/roms/openbios/Makefile.target b/qemu/roms/openbios/Makefile.target new file mode 100644 index 000000000..a7363e667 --- /dev/null +++ b/qemu/roms/openbios/Makefile.target @@ -0,0 +1,86 @@ +# +# OpenBIOS Makefile +# (C) 2004-2009 by the OpenBIOS team +# + +include config.mak + +ODIR := . +HOSTCC := gcc + +HOSTCFLAGS+= -O2 -g -DFCOMPILER -DBOOTSTRAP $(CROSSCFLAGS) +HOSTCFLAGS+= -Wall -Wredundant-decls -Wshadow -Wpointer-arith +HOSTCFLAGS+= -Wstrict-prototypes -Wmissing-declarations -Wundef -Wendif-labels +HOSTCFLAGS+= -Wstrict-aliasing -Wwrite-strings -Wmissing-prototypes -Wnested-externs +HOSTCFLAGS+= -W +# Flags for dependency generation +HOSTCFLAGS+= -MMD -MP -MT $@ -MF '$(*D)/$(*F).d' +HOSTINCLUDES := -I$(SRCDIR)/include -I$(SRCDIR)/kernel -I$(SRCDIR)/kernel/include -I$(ODIR)/target/include + +CC := $(TARGET)gcc +AS := $(TARGET)as +AR := $(TARGET)ar +LD := $(TARGET)ld +NM := $(TARGET)nm +STRIP := $(TARGET)strip +RANLIB := $(TARGET)ranlib + +CFLAGS+= -Os -g -DNATIVE_BITWIDTH_EQUALS_HOST_BITWIDTH -USWAP_ENDIANNESS +CFLAGS+= -Wall -Wredundant-decls -Wshadow -Wpointer-arith +CFLAGS+= -Wstrict-prototypes -Wmissing-declarations -Wundef -Wendif-labels +CFLAGS+= -Wstrict-aliasing -Wwrite-strings -Wmissing-prototypes -Wnested-externs +CFLAGS+= -Werror +# Flags for dependency generation +CFLAGS+= -MMD -MP -MT $@ -MF '$(*D)/$(*F).d' +INCLUDES := -I$(SRCDIR)/include -I$(SRCDIR)/kernel/include -I$(ODIR)/target/include +AS_FLAGS+= -g + +# FCode tokeniser +TOKE := toke + +quiet-command = $(if $(V),$1,$(if $(2),@echo $2 && $1, @$1)) + +VPATH_SUFFIXES = %.c %.h %.S %.fs +set-vpath = $(if $1,$(foreach PATTERN,$(VPATH_SUFFIXES),$(eval vpath $(PATTERN) $1))) +$(call set-vpath, $(SRCDIR)) + +# +# pre rules +# + +all: versions dictionaries host-libraries target-libraries host-executables target-executables + +versions: $(ODIR)/target/include/openbios-version.h $(ODIR)/forth/version.fs + +$(ODIR)/forth/version.fs: + $(call quiet-command,true, " GEN $(TARGET_DIR)$@") + @DATE="$(shell echo `LC_ALL=C TZ=UTC date +'%b %e %Y %H:%M'`)" ; \ + ( echo ": builddate \" $$DATE\" ; " ; \ + echo ": version \" $(VERSION)\" ; " ; ) \ + > $(dir $@)/version.fs + +$(ODIR)/target/include/openbios-version.h: + $(call quiet-command,true, " GEN $(TARGET_DIR)$@") + @DATE="$(shell echo `LC_ALL=C TZ=UTC date +'%b %e %Y %H:%M'`)" ; \ + ( echo "#define OPENBIOS_BUILD_DATE \"$$DATE\"" ; \ + echo "#define OPENBIOS_VERSION_STR \"$(VERSION)\"" ; ) \ + > $(dir $@)/openbios-version.h + +info: + @echo "Building OpenBIOS on $(HOSTARCH) for $(ARCH)" + +clean: + @printf "Cleaning up for $(ARCH)..." + @rm -rf forth.dict.core forthstrap *.dict openbios-* + @rm -f $(ODIR)/target/include/openbios-version.h $(ODIR)/forth/version.fs + @find . -type f \( -name "*~" -o -name '*.o' -o -name '*.d' -o -name '*.a' \) -exec rm \{\} \; + @echo " ok" + +build-verbose: info build + +build: all + +include rules.mak + +# Include automatically generated dependency files +-include $(wildcard $(ODIR)/*.d $(ODIR)/host/kernel/*.d $(ODIR)/target/*/*.d $(ODIR)/target/*/*/*.d $(ODIR)/target/*/*/*/*.d) diff --git a/qemu/roms/openbios/README b/qemu/roms/openbios/README new file mode 100644 index 000000000..b6a9978ac --- /dev/null +++ b/qemu/roms/openbios/README @@ -0,0 +1,132 @@ +Welcome to OpenBIOS +------------------- + +OpenBIOS is a free, portable implementation of IEEE 1275-1994 +(Open Firmware). Find detailed information about OpenBIOS at +http://www.openbios.org/ + +What is OpenBIOS? +----------------- + +OpenBIOS can replace your system firmware (BIOS) partly or completely. It +can also be used as a bootloader to create an Open Firmware compatible +interface between legacy firmware and an operating system. + +This is achieved by a modular concept that consists of a portable Forth +kernel and three interfaces for user interaction, device initialization +and client (operating system) control. + +While far not all possible applications of OpenBIOS are implemented yet, +a lot of functionality is already there. OpenBIOS can be used to enhance +LinuxBIOS (http://www.linuxbios.org), or be booted from any multiboot +capable bootloader to bring Open Firmware to your machine. OpenBIOS can +also be used when an operating system is already running. It provides +the needed OpenFirmware functionality to MOL (MacOnLinux) to boot MacOS +9 and X on PPC machines, as well as Linux (all supported platforms) + +OpenBIOS build options +--------------------- + + config/scripts/switch-arch <platform> - build for specified platform + Look in config/example for + platforms. + + make - build all configured binaries + + make run - run unix example. + + +How OpenBIOS works +------------------ + + The OpenBIOS forth core is split into a forth kernel written in portable + C and a forth dictionary which operated on by the kernel. + + When building the forth core, you get different versions of + the forth kernel: + + * a unix executable program + + - to execute a forth dictionary from a file. This can be used for + easily testing and developing OpenBIOS on a unix host. + + - to create a dictionary file. Such a dictionary file sets up + all of the forth language. Primitives are indexed to save relocations. + + The default is to create a forth dictionary forth.dict from + forth/start.fs. This file includes all of the basic forth language + constructs from forth/bootstrap.fs and starts the interpreter. + + To achieve this, the hosted unix version contains a basic set of + forth words coded in C that allow creating a full dictionary. + + * a varying number of target specific binaries. On x86 you can start + openbios for example from GRUB or LinuxBIOS. They are all based on + the same forth engine consisting of a dictionary scheduler, primitive + words needed to build the forth environment, 2 stacks and a simple + set of console functions. These binaries can not be started directly + in the unix host environment. + +Requirements +------------ + * gcc + * gnu make + * OpenBIOS FCode Utils + Download with svn co svn://openbios.org/openbios/fcode-utils + * grub or any other multiboot loader to run the multiboot + binary "openbios.multiboot" with it's module "openbios-<platform>.dict" + * xsltproc + +Building & Usage +---------------- + + * make + + this builds "openbios.multiboot", the standalone image and "openbios-unix", + the hosted image. Additionally it creates a forth dictionary + file from forth/start.fs. All generated files are written to + the absolute directory held by the variable BUILDDIR, which defaults + to obj-[platform]. Some compile time parameters can be tweaked in + include/config.h + + * use "openbios-unix" to create a forth dictionary on your own: + $ obj-x86/openbios-unix -Iforth start.fs + creates the file forth.dict from forth source forth/start.fs. + + * use "openbios-unix" to run a created dictionary: + $ obj-x86/openbios-unix obj-x86/openbios-unix.dict + This is useful for testing + + * booting openbios + You can boot openbios i.e. in grub. Add the following lines to + your menu.lst: + + title openbios + kernel (hd0,2)/boot/openbios.multiboot + module (hd0,2)/boot/openbios-x86.dict + + Note: change (hd0,2) to the partition you copied the openbios image and + openbios-x86.dict to. + + To boot OpenBIOS from LinuxBIOS/etherboot, you can either use + "openbios-plain.elf" or "openbios-builtin.elf": + + - openbios-plain.elf is the pure kernel that loads the dictionary from a + hardcoded address in flash memory (0xfffe0000) + + - openbios-builtin.elf also includes the dictionary directly so that it + can be easily used from etherboot or the LinuxBIOS builtin ELF + loader without taking care of the dictionary + +CREDITS +------- +OpenBIOS was developed by Stefan Reinauer, Samuel Rydh and Patrick Mauritz. +The OpenBIOS IDE driver was written by Jens Axboe. +For license details on this piece of software, see Documentation/COPYING. + + +If you have patches, questions, comments, feel free to contact the OpenBIOS +mailinglist. + +Regards, + the OpenBIOS team diff --git a/qemu/roms/openbios/VERSION b/qemu/roms/openbios/VERSION new file mode 100644 index 000000000..9459d4ba2 --- /dev/null +++ b/qemu/roms/openbios/VERSION @@ -0,0 +1 @@ +1.1 diff --git a/qemu/roms/openbios/arch/amd64/Kconfig b/qemu/roms/openbios/arch/amd64/Kconfig new file mode 100644 index 000000000..f1f677dba --- /dev/null +++ b/qemu/roms/openbios/arch/amd64/Kconfig @@ -0,0 +1,48 @@ +mainmenu "OpenBIOS Configuration" + +config AMD64 + bool + default y + help + Building for AMD64 hardware. + +config LITTLE_ENDIAN + bool + default y + help + AMD64 is little endian. + + +menu "Kernel binaries (AMD64)" + +config IMAGE_ELF + bool "ELF image (for LinuxBIOS)" + default y + help + Build a simple elf image that can be used with LinuxBIOS + This image will be called openbios.elf + +config IMAGE_ELF_EMBEDDED + bool "ELF image with embedded dictionary" + default y + help + Build an elf image with embedded dictionary. This image + can easily be used with etherboot. + The image filename is openbios.full + +config IMAGE_ELF_MULTIBOOT + bool "Multiboot image" + default y + help + Build a multiboot image for booting with grub + +endmenu + +menu "Build hosted UNIX Binary" +source "arch/unix/Kconfig" +endmenu + +source "kernel/Kconfig" +source "forth/Kconfig" +source "libopenbios/Kconfig" +source "drivers/Kconfig" diff --git a/qemu/roms/openbios/arch/amd64/boot.c b/qemu/roms/openbios/arch/amd64/boot.c new file mode 100644 index 000000000..0e1fe7efd --- /dev/null +++ b/qemu/roms/openbios/arch/amd64/boot.c @@ -0,0 +1,41 @@ +/* + * + */ +#undef BOOTSTRAP +#include "config.h" +#include "libopenbios/bindings.h" +#include "libopenbios/elfload.h" +#include "arch/common/nvram.h" +#include "libc/diskio.h" +#include "libopenbios/sys_info.h" + +int elf_load(struct sys_info *, const char *filename, const char *cmdline); +int linux_load(struct sys_info *, const char *filename, const char *cmdline); + +void boot(void); + +void boot(void) +{ + char *path=pop_fstr_copy(), *param; + + // char *param="root=/dev/hda2 console=ttyS0,115200n8 console=tty0"; + + if(!path) { + printk("[x86] Booting default not supported.\n"); + return; + } + + param = strchr(path, ' '); + if(param) { + *param = '\0'; + param++; + } + + printk("[x86] Booting file '%s' with parameters '%s'\n",path, param); + + if (elf_load(&sys_info, path, param) == LOADER_NOT_SUPPORT) + if (linux_load(&sys_info, path, param) == LOADER_NOT_SUPPORT) + printk("Unsupported image format\n"); + + free(path); +} diff --git a/qemu/roms/openbios/arch/amd64/build.xml b/qemu/roms/openbios/arch/amd64/build.xml new file mode 100644 index 000000000..8f436d001 --- /dev/null +++ b/qemu/roms/openbios/arch/amd64/build.xml @@ -0,0 +1,6 @@ +<build condition="AMD64"> + <dictionary name="openbios-amd64" init="openbios" target="forth"> + <object source="init.fs"/> + <object source="QEMU,VGA.bin" target="fcode" condition="DRIVER_VGA" /> + </dictionary> +</build> diff --git a/qemu/roms/openbios/arch/amd64/builtin.c b/qemu/roms/openbios/arch/amd64/builtin.c new file mode 100644 index 000000000..93ced0ae3 --- /dev/null +++ b/qemu/roms/openbios/arch/amd64/builtin.c @@ -0,0 +1,25 @@ +/* tag: openbios forth starter for builtin dictionary for amd64 + * + * Copyright (C) 2003 Stefan Reinauer + * + * See the file "COPYING" for further information about + * the copyright and warranty status of this work. + */ + +#include "config.h" +#include <asm/types.h> +#include "libopenbios/sys_info.h" + +/* + * wrap an array around the hex'ed dictionary file + */ + +#include "static-dict.h" + +void collect_multiboot_info(struct sys_info *info); +void collect_multiboot_info(struct sys_info *info) +{ + info->dict_start=(unsigned long *)forth_dictionary; + info->dict_end=(unsigned long *)((ucell)forth_dictionary + + sizeof(forth_dictionary)); +} diff --git a/qemu/roms/openbios/arch/amd64/console.c b/qemu/roms/openbios/arch/amd64/console.c new file mode 100644 index 000000000..71a22b681 --- /dev/null +++ b/qemu/roms/openbios/arch/amd64/console.c @@ -0,0 +1,417 @@ +/* + * Copyright (C) 2003, 2004 Stefan Reinauer + * + * See the file "COPYING" for further information about + * the copyright and warranty status of this work. + */ + +#include "config.h" +#include "kernel/kernel.h" +#include "openbios.h" + +#ifdef CONFIG_DEBUG_CONSOLE + +/* ****************************************************************** + * serial console functions + * ****************************************************************** */ + +#ifdef CONFIG_DEBUG_CONSOLE_SERIAL + +#define RBR(x) x==2?0x2f8:0x3f8 +#define THR(x) x==2?0x2f8:0x3f8 +#define IER(x) x==2?0x2f9:0x3f9 +#define IIR(x) x==2?0x2fa:0x3fa +#define LCR(x) x==2?0x2fb:0x3fb +#define MCR(x) x==2?0x2fc:0x3fc +#define LSR(x) x==2?0x2fd:0x3fd +#define MSR(x) x==2?0x2fe:0x3fe +#define SCR(x) x==2?0x2ff:0x3ff +#define DLL(x) x==2?0x2f8:0x3f8 +#define DLM(x) x==2?0x2f9:0x3f9 + +static int uart_charav(int port) +{ + if (!port) + return -1; + return ((inb(LSR(port)) & 1) != 0); +} + +static char uart_getchar(int port) +{ + if (!port) + return -1; + while (!uart_charav(port)); + return ((char) inb(RBR(port)) & 0177); +} + +static void uart_putchar(int port, unsigned char c) +{ + if (!port) + return; + if (c == '\n') + uart_putchar(port, '\r'); + while (!(inb(LSR(port)) & 0x20)); + outb(c, THR(port)); +} + +static void uart_init_line(int port, unsigned long baud) +{ + int i, baudconst; + + if (!port) + return; + + switch (baud) { + case 115200: + baudconst = 1; + break; + case 57600: + baudconst = 2; + break; + case 38400: + baudconst = 3; + break; + case 19200: + baudconst = 6; + break; + case 9600: + default: + baudconst = 12; + break; + } + + outb(0x87, LCR(port)); + outb(0x00, DLM(port)); + outb(baudconst, DLL(port)); + outb(0x07, LCR(port)); + outb(0x0f, MCR(port)); + + for (i = 10; i > 0; i--) { + if (inb(LSR(port)) == (unsigned int) 0) + break; + inb(RBR(port)); + } +} + +int uart_init(int port, unsigned long speed) +{ + if (port) + uart_init_line(port, speed); + return -1; +} + +static void serial_putchar(int c) +{ + uart_putchar(CONFIG_SERIAL_PORT, (unsigned char) (c & 0xff)); +} + +static void serial_cls(void) +{ + serial_putchar(27); + serial_putchar('['); + serial_putchar('H'); + serial_putchar(27); + serial_putchar('['); + serial_putchar('J'); +} + +#endif + +/* ****************************************************************** + * simple polling video/keyboard console functions + * ****************************************************************** */ + +#ifdef CONFIG_DEBUG_CONSOLE_VGA + +/* raw vga text mode */ +#define COLUMNS 80 /* The number of columns. */ +#define LINES 25 /* The number of lines. */ +#define ATTRIBUTE 7 /* The attribute of an character. */ + +#define VGA_BASE 0xB8000 /* The video memory address. */ + +/* VGA Index and Data Registers */ +#define VGA_REG_INDEX 0x03D4 /* VGA index register */ +#define VGA_REG_DATA 0x03D5 /* VGA data register */ + +#define VGA_IDX_CURMSL 0x09 /* cursor maximum scan line */ +#define VGA_IDX_CURSTART 0x0A /* cursor start */ +#define VGA_IDX_CUREND 0x0B /* cursor end */ +#define VGA_IDX_CURLO 0x0F /* cursor position (low 8 bits) */ +#define VGA_IDX_CURHI 0x0E /* cursor position (high 8 bits) */ + +/* Save the X and Y position. */ +static int xpos, ypos; +/* Point to the video memory. */ +static volatile unsigned char *video = (unsigned char *) VGA_BASE; + +static void video_initcursor(void) +{ + u8 val; + outb(VGA_IDX_CURMSL, VGA_REG_INDEX); + val = inb(VGA_REG_DATA) & 0x1f; /* maximum scan line -1 */ + + outb(VGA_IDX_CURSTART, VGA_REG_INDEX); + outb(0, VGA_REG_DATA); + + outb(VGA_IDX_CUREND, VGA_REG_INDEX); + outb(val, VGA_REG_DATA); +} + + + +static void video_poscursor(unsigned int x, unsigned int y) +{ + unsigned short pos; + + /* Calculate new cursor position as a function of x and y */ + pos = (y * COLUMNS) + x; + + /* Output the new position to VGA card */ + outb(VGA_IDX_CURLO, VGA_REG_INDEX); /* output low 8 bits */ + outb((u8) (pos), VGA_REG_DATA); + outb(VGA_IDX_CURHI, VGA_REG_INDEX); /* output high 8 bits */ + outb((u8) (pos >> 8), VGA_REG_DATA); + +}; + + +static void video_newline(void) +{ + xpos = 0; + + if (ypos < LINES - 1) { + ypos++; + } else { + int i; + memmove((void *) video, (void *) (video + 2 * COLUMNS), + (LINES - 1) * COLUMNS * 2); + + for (i = ((LINES - 1) * 2 * COLUMNS); + i < 2 * COLUMNS * LINES;) { + video[i++] = 0; + video[i++] = ATTRIBUTE; + } + } + +} + +/* Put the character C on the screen. */ +static void video_putchar(int c) +{ + int p=1; + + if (c == '\n' || c == '\r') { + video_newline(); + return; + } + + if (c == '\b') { + if (xpos) xpos--; + c=' '; + p=0; + } + + + if (xpos >= COLUMNS) + video_newline(); + + *(video + (xpos + ypos * COLUMNS) * 2) = c & 0xFF; + *(video + (xpos + ypos * COLUMNS) * 2 + 1) = ATTRIBUTE; + + if (p) + xpos++; + + video_poscursor(xpos, ypos); +} + +static void video_cls(void) +{ + int i; + + for (i = 0; i < 2 * COLUMNS * LINES;) { + video[i++] = 0; + video[i++] = ATTRIBUTE; + } + + + xpos = 0; + ypos = 0; + + video_initcursor(); + video_poscursor(xpos, ypos); +} + +void video_init(void) +{ + video=phys_to_virt((unsigned char*)VGA_BASE); +} + +/* + * keyboard driver + */ + +static char normal[] = { + 0x0, 0x1b, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', + '=', '\b', '\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', + 'p', '[', ']', 0xa, 0x0, 'a', 's', 'd', 'f', 'g', 'h', 'j', + 'k', 'l', ';', 0x27, 0x60, 0x0, 0x5c, 'z', 'x', 'c', 'v', 'b', + 'n', 'm', ',', '.', '/', 0x0, '*', 0x0, ' ', 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, '0', 0x7f +}; + +static char shifted[] = { + 0x0, 0x1b, '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', + '+', '\b', '\t', 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', + 'P', '{', '}', 0xa, 0x0, 'A', 'S', 'D', 'F', 'G', 'H', 'J', + 'K', 'L', ':', 0x22, '~', 0x0, '|', 'Z', 'X', 'C', 'V', 'B', + 'N', 'M', '<', '>', '?', 0x0, '*', 0x0, ' ', 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, '7', '8', + '9', 0x0, '4', '5', '6', 0x0, '1', '2', '3', '0', 0x7f +}; + +static int key_ext; +static int key_lshift = 0, key_rshift = 0, key_caps = 0; + +static char last_key; + +static void keyboard_cmd(unsigned char cmd, unsigned char val) +{ + outb(cmd, 0x60); + /* wait until keyboard controller accepts cmds: */ + while (inb(0x64) & 2); + outb(val, 0x60); + while (inb(0x64) & 2); +} + +static char keyboard_poll(void) +{ + unsigned int c; + if (inb(0x64) & 1) { + c = inb(0x60); + switch (c) { + case 0xe0: + key_ext = 1; + return 0; + case 0x2a: + key_lshift = 1; + return 0; + case 0x36: + key_rshift = 1; + return 0; + case 0xaa: + key_lshift = 0; + return 0; + case 0xb6: + key_rshift = 0; + return 0; + case 0x3a: + if (key_caps) { + key_caps = 0; + keyboard_cmd(0xed, 0); + } else { + key_caps = 1; + keyboard_cmd(0xed, 4); /* set caps led */ + } + return 0; + } + + if (key_ext) { + // void printk(const char *format, ...); + printk("extended keycode: %x\n", c); + + key_ext = 0; + return 0; + } + + if (c & 0x80) /* unhandled key release */ + return 0; + + if (key_lshift || key_rshift) + return key_caps ? normal[c] : shifted[c]; + else + return key_caps ? shifted[c] : normal[c]; + } + return 0; +} + +static int keyboard_dataready(void) +{ + if (last_key) + return 1; + + last_key = keyboard_poll(); + + return (last_key != 0); +} + +static unsigned char keyboard_readdata(void) +{ + char tmp; + while (!keyboard_dataready()); + tmp = last_key; + last_key = 0; + return tmp; +} +#endif + + +/* ****************************************************************** + * common functions, implementing simple concurrent console + * ****************************************************************** */ + +int arch_putchar(int c) +{ +#ifdef CONFIG_DEBUG_CONSOLE_SERIAL + serial_putchar(c); +#endif +#ifdef CONFIG_DEBUG_CONSOLE_VGA + video_putchar(c); +#endif + return c; +} + +int arch_availchar(void) +{ +#ifdef CONFIG_DEBUG_CONSOLE_SERIAL + if (uart_charav(CONFIG_SERIAL_PORT)) + return 1; +#endif +#ifdef CONFIG_DEBUG_CONSOLE_VGA + if (keyboard_dataready()) + return 1; +#endif + return 0; +} + +int arch_getchar(void) +{ +#ifdef CONFIG_DEBUG_CONSOLE_SERIAL + if (uart_charav(CONFIG_SERIAL_PORT)) + return (uart_getchar(CONFIG_SERIAL_PORT)); +#endif +#ifdef CONFIG_DEBUG_CONSOLE_VGA + if (keyboard_dataready()) + return (keyboard_readdata()); +#endif + return 0; +} + +void cls(void) +{ +#ifdef CONFIG_DEBUG_CONSOLE_SERIAL + serial_cls(); +#endif +#ifdef CONFIG_DEBUG_CONSOLE_VGA + video_cls(); +#endif +} + +struct _console_ops arch_console_ops = { + .putchar = arch_putchar, + .availchar = arch_availchar, + .getchar = arch_getchar +}; + +#endif // CONFIG_DEBUG_CONSOLE diff --git a/qemu/roms/openbios/arch/amd64/context.c b/qemu/roms/openbios/arch/amd64/context.c new file mode 100644 index 000000000..2e4df6a3d --- /dev/null +++ b/qemu/roms/openbios/arch/amd64/context.c @@ -0,0 +1,124 @@ +/* + * context switching + * 2003-10 by SONE Takeshi + */ + +#include "config.h" +#include "kernel/kernel.h" +#include "segment.h" +#include "context.h" + +#define MAIN_STACK_SIZE 16384 +#define IMAGE_STACK_SIZE 4096 + +#define debug printk + +static void start_main(void); /* forward decl. */ +void __exit_context(void); /* assembly routine */ + +/* + * Main context structure + * It is placed at the bottom of our stack, and loaded by assembly routine + * to start us up. + */ +struct context main_ctx __attribute__((section (".initctx"))) = { + .gdt_base = (uint64_t) gdt, + .gdt_limit = GDT_LIMIT, + .cs = FLAT_CS, + .ds = FLAT_DS, + .es = FLAT_DS, + .fs = FLAT_DS, + .gs = FLAT_DS, + .ss = FLAT_DS, + .esp = (uint32_t) ESP_LOC(&main_ctx), + .eip = (uint32_t) start_main, + .return_addr = (uint32_t) __exit_context, +}; + +/* This is used by assembly routine to load/store the context which + * it is to switch/switched. */ +struct context *__context = &main_ctx; + +/* Stack for loaded ELF image */ +static uint8_t image_stack[IMAGE_STACK_SIZE]; + +/* Pointer to startup context (physical address) */ +unsigned long __boot_ctx; + +/* + * Main starter + * This is the C function that runs first. + */ +static void start_main(void) +{ + int retval; + extern int openbios(void); + + /* Save startup context, so we can refer to it later. + * We have to keep it in physical address since we will relocate. */ + __boot_ctx = virt_to_phys(__context); + + /* Start the real fun */ + retval = openbios(); + + /* Pass return value to startup context. Bootloader may see it. */ + boot_ctx->eax = retval; + + /* Returning from here should jump to __exit_context */ + __context = boot_ctx; +} + +/* Setup a new context using the given stack. + */ +struct context * +init_context(uint8_t *stack, uint32_t stack_size, int num_params) +{ + struct context *ctx; + + ctx = (struct context *) + (stack + stack_size - (sizeof(*ctx) + num_params*sizeof(uint32_t))); + memset(ctx, 0, sizeof(*ctx)); + + /* Fill in reasonable default for flat memory model */ + ctx->gdt_base = virt_to_phys(gdt); + ctx->gdt_limit = GDT_LIMIT; + ctx->cs = FLAT_CS; + ctx->ds = FLAT_DS; + ctx->es = FLAT_DS; + ctx->fs = FLAT_DS; + ctx->gs = FLAT_DS; + ctx->ss = FLAT_DS; + ctx->esp = virt_to_phys(ESP_LOC(ctx)); + ctx->return_addr = virt_to_phys(__exit_context); + + return ctx; +} + +/* Switch to another context. */ +struct context *switch_to(struct context *ctx) +{ + struct context *save, *ret; + + debug("switching to new context:\n"); + save = __context; + __context = ctx; + asm ("pushl %cs; call __switch_context"); + ret = __context; + __context = save; + return ret; +} + +/* Start ELF Boot image */ +uint32_t start_elf(uint32_t entry_point, uint32_t param) +{ + struct context *ctx; + + ctx = init_context(image_stack, sizeof image_stack, 1); + ctx->eip = entry_point; + ctx->param[0] = param; + ctx->eax = 0xe1fb007; + ctx->ebx = param; + + ctx = switch_to(ctx); + return ctx->eax; +} diff --git a/qemu/roms/openbios/arch/amd64/context.h b/qemu/roms/openbios/arch/amd64/context.h new file mode 100644 index 000000000..4c3832efb --- /dev/null +++ b/qemu/roms/openbios/arch/amd64/context.h @@ -0,0 +1,48 @@ +#ifndef AMD64_CONTEXT_H +#define AMD64_CONTEXT_H + +struct context { + /* Stack Segment, placed here because of the alignment issue... */ + uint16_t ss; + /* Used with sgdt/lgdt */ + uint16_t gdt_limit; + uint64_t gdt_base; + /* General registers, accessed with pushal/popal */ + uint32_t edi; + uint32_t esi; + uint32_t ebp; + uint32_t esp; /* points just below eax */ + uint32_t ebx; + uint32_t edx; + uint32_t ecx; + uint32_t eax; +#define ESP_LOC(ctx) (&(ctx)->gs) + /* Segment registers */ + uint32_t gs; + uint32_t fs; + uint32_t es; + uint32_t ds; + /* Flags */ + uint32_t eflags; + /* Code segment:offset */ + uint32_t eip; + uint32_t cs; + /* Optional stack contents */ + uint32_t return_addr; + uint32_t param[0]; +}; + +/* Create a new context in the given stack */ +struct context * +init_context(uint8_t *stack, uint32_t stack_size, int num_param); + +/* Switch context */ +struct context *switch_to(struct context *); + +/* Holds physical address of boot context */ +extern unsigned long __boot_ctx; + +/* This can always be safely used to refer to the boot context */ +#define boot_ctx ((struct context *) phys_to_virt(__boot_ctx)) + +#endif /* AMD64_CONTEXT_H */ diff --git a/qemu/roms/openbios/arch/amd64/defconfig b/qemu/roms/openbios/arch/amd64/defconfig new file mode 100644 index 000000000..570a6c869 --- /dev/null +++ b/qemu/roms/openbios/arch/amd64/defconfig @@ -0,0 +1,65 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_AMD64=y +CONFIG_LITTLE_ENDIAN=y + +# +# Kernel binaries (AMD64) +# +# CONFIG_IMAGE_ELF is not set +# CONFIG_IMAGE_ELF_EMBEDDED is not set +# CONFIG_IMAGE_ELF_MULTIBOOT is not set + +# +# Build hosted UNIX Binary +# +CONFIG_HOST_UNIX=y +# CONFIG_PLUGIN_PCI is not set + +# +# Kernel Debugging +# +# CONFIG_DEBUG is not set +CONFIG_DEBUG_CONSOLE=y +CONFIG_DEBUG_CONSOLE_SERIAL=y +CONFIG_SERIAL_PORT=1 +CONFIG_SERIAL_SPEED=115200 +CONFIG_DEBUG_CONSOLE_VGA=y + +# +# Module Configuration +# +CONFIG_CMDLINE=y +CONFIG_DEBLOCKER=y + +# +# Filesystem Configuration +# +CONFIG_DISK_LABEL=y +CONFIG_PART_SUPPORT=y +CONFIG_PC_PARTS=y +CONFIG_FS=y +CONFIG_GRUBFS=y +CONFIG_FSYS_EXT2FS=y +CONFIG_FSYS_FAT=y +CONFIG_FSYS_JFS=y +# CONFIG_FSYS_MINIX is not set +CONFIG_FSYS_REISERFS=y +CONFIG_FSYS_XFS=y +CONFIG_FSYS_ISO9660=y +# CONFIG_FSYS_FFS is not set +# CONFIG_FSYS_VSTAFS is not set +# CONFIG_DEBUG_FS is not set + +# +# Miscellaneous +# +CONFIG_LINUXBIOS=y + +# +# Drivers +# +CONFIG_DRIVER_PCI=y +CONFIG_DRIVER_IDE=y +# CONFIG_DEBUG_IDE is not set diff --git a/qemu/roms/openbios/arch/amd64/init.fs b/qemu/roms/openbios/arch/amd64/init.fs new file mode 100644 index 000000000..fda3acdc8 --- /dev/null +++ b/qemu/roms/openbios/arch/amd64/init.fs @@ -0,0 +1,83 @@ +include config.fs + +:noname + ." Type 'help' for detailed information" cr + \ ." boot secondary slave cdrom: " cr + \ ." 0 > boot hd:2,\boot\vmlinuz root=/dev/hda2" cr + ; DIAG-initializer + +" /" find-device + +new-device + " memory" device-name + \ 12230 encode-int " reg" property + external + : open true ; + : close ; + \ claim ( phys size align -- base ) + \ release ( phys size -- ) +finish-device + +new-device + " cpus" device-name + 1 " #address-cells" int-property + 0 " #size-cells" int-property + + external + : open true ; + : close ; + : decode-unit parse-hex ; + +finish-device + +: make-openable ( path ) + find-dev if + begin ?dup while + \ install trivial open and close methods + dup active-package! is-open + parent + repeat + then +; + +: preopen ( chosen-str node-path ) + 2dup make-openable + + " /chosen" find-device + open-dev ?dup if + encode-int 2swap property + else + 2drop + then +; + +:noname + set-defaults +; SYSTEM-initializer + +\ preopen device nodes (and store the ihandles under /chosen) +:noname + " memory" " /memory" preopen + " mmu" " /cpus/@0" preopen + " stdout" " /builtin/console" preopen + " stdin" " /builtin/console" preopen + +; SYSTEM-initializer + +\ use the tty interface if available +:noname + " /builtin/console" find-dev if drop + " /builtin/console" " input-device" $setenv + " /builtin/console" " output-device" $setenv + then +; SYSTEM-initializer + +:noname + " keyboard" input +; CONSOLE-IN-initializer + +\ Load VGA FCode driver blob +[IFDEF] CONFIG_DRIVER_VGA + -1 value vga-driver-fcode + " QEMU,VGA.bin" $encode-file to vga-driver-fcode +[THEN] diff --git a/qemu/roms/openbios/arch/amd64/ldscript b/qemu/roms/openbios/arch/amd64/ldscript new file mode 100644 index 000000000..8976c7af0 --- /dev/null +++ b/qemu/roms/openbios/arch/amd64/ldscript @@ -0,0 +1,73 @@ +OUTPUT_FORMAT(elf32-i386) +OUTPUT_ARCH(i386) + +ENTRY(entry) + +/* Initial load address + * To be loaded by GRUB, this must be >= 1MB + */ +BASE_ADDR = 0x100000; + +/* 16KB heap and stack */ +HEAP_SIZE = 16384; +STACK_SIZE = 16384; + +SECTIONS +{ + . = BASE_ADDR; + + /* Put Multiboot header near beginning of file, if any. */ + .hdr : { *(.hdr) *(.hdr.*) } + + /* Start of the program. + * Now the version string is in the note, we must include it + * in the program. Otherwise we lose the string after relocation. */ + . = ALIGN(16); + _start = .; + + /* Putting ELF notes near beginning of file might help bootloaders. + * We discard .note sections other than .note.ELFBoot, + * because some versions of GCC generates useless ones. */ + .note : { *(.note.ELFBoot) } + + /* Normal sections */ + .text : { *(.text) *(.text.*) } + .rodata : { + . = ALIGN(4); + sound_drivers_start = .; + *(.rodata.sound_drivers) + sound_drivers_end = .; + *(.rodata) + *(.rodata.*) + } + .data : { *(.data) *(.data.*) } + + .bss : { + *(.bss) + *(.bss.*) + *(COMMON) + + /* Put heap and stack here, so they are included in PT_LOAD segment + * and the bootloader is aware of it. */ + + . = ALIGN(16); + _heap = .; + . += HEAP_SIZE; + . = ALIGN(16); + _eheap = .; + + _stack = .; + . += STACK_SIZE; + . = ALIGN(16); + _estack = .; + } + + .initctx : { + /* Initial contents of stack. This MUST BE just after the stack. */ + *(.initctx) + } + + _end = .; + + /DISCARD/ : { *(.comment) *(.note) } +} diff --git a/qemu/roms/openbios/arch/amd64/lib.c b/qemu/roms/openbios/arch/amd64/lib.c new file mode 100644 index 000000000..f04458e1a --- /dev/null +++ b/qemu/roms/openbios/arch/amd64/lib.c @@ -0,0 +1,56 @@ +/* lib.c + * tag: simple function library + * + * Copyright (C) 2003 Stefan Reinauer + * + * See the file "COPYING" for further information about + * the copyright and warranty status of this work. + */ + +#include "config.h" +#include "asm/types.h" +#include <stdarg.h> +#include "libc/stdlib.h" +#include "libc/vsprintf.h" +#include "kernel/kernel.h" + +/* Format a string and print it on the screen, just like the libc + * function printf. + */ +int printk( const char *fmt, ... ) +{ + char *p, buf[512]; + va_list args; + int i; + + va_start(args, fmt); + i = vsnprintf(buf, sizeof(buf), fmt, args); + va_end(args); + + for( p=buf; *p; p++ ) + putchar(*p); + return i; +} + +// dumb quick memory allocator until we get a decent thing here. + +#define MEMSIZE 128*1024 +static char memory[MEMSIZE]; +static void *memptr=memory; +static int memsize=MEMSIZE; + +void *malloc(int size) +{ + void *ret=(void *)0; + if(memsize>=size) { + memsize-=size; + ret=memptr; + memptr+=size; + } + return ret; +} + +void free(void *ptr) +{ + /* Nothing yet */ +} diff --git a/qemu/roms/openbios/arch/amd64/linux_load.c b/qemu/roms/openbios/arch/amd64/linux_load.c new file mode 100644 index 000000000..f1ed98df1 --- /dev/null +++ b/qemu/roms/openbios/arch/amd64/linux_load.c @@ -0,0 +1,647 @@ +/* + * Linux/i386 loader + * Supports bzImage, zImage and Image format. + * + * Based on work by Steve Gehlbach. + * Portions are taken from mkelfImage. + * + * 2003-09 by SONE Takeshi + */ + +#include "config.h" +#include "kernel/kernel.h" +#include "libopenbios/bindings.h" +#include "libopenbios/sys_info.h" +#include "context.h" +#include "segment.h" +#include "loadfs.h" + +#define printf printk +#define debug printk +#define strtoull_with_suffix strtol + +#define LINUX_PARAM_LOC 0x90000 +#define COMMAND_LINE_LOC 0x91000 +#define GDT_LOC 0x92000 +#define STACK_LOC 0x93000 + +#define E820MAX 32 /* number of entries in E820MAP */ +struct e820entry { + unsigned long long addr; /* start of memory segment */ + unsigned long long size; /* size of memory segment */ + unsigned long type; /* type of memory segment */ +#define E820_RAM 1 +#define E820_RESERVED 2 +#define E820_ACPI 3 /* usable as RAM once ACPI tables have been read */ +#define E820_NVS 4 +}; + +/* The header of Linux/i386 kernel */ +struct linux_header { + uint8_t reserved1[0x1f1]; /* 0x000 */ + uint8_t setup_sects; /* 0x1f1 */ + uint16_t root_flags; /* 0x1f2 */ + uint8_t reserved2[6]; /* 0x1f4 */ + uint16_t vid_mode; /* 0x1fa */ + uint16_t root_dev; /* 0x1fc */ + uint16_t boot_sector_magic; /* 0x1fe */ + /* 2.00+ */ + uint8_t reserved3[2]; /* 0x200 */ + uint8_t header_magic[4]; /* 0x202 */ + uint16_t protocol_version; /* 0x206 */ + uint32_t realmode_swtch; /* 0x208 */ + uint16_t start_sys; /* 0x20c */ + uint16_t kver_addr; /* 0x20e */ + uint8_t type_of_loader; /* 0x210 */ + uint8_t loadflags; /* 0x211 */ + uint16_t setup_move_size; /* 0x212 */ + uint32_t code32_start; /* 0x214 */ + uint32_t ramdisk_image; /* 0x218 */ + uint32_t ramdisk_size; /* 0x21c */ + uint8_t reserved4[4]; /* 0x220 */ + /* 2.01+ */ + uint16_t heap_end_ptr; /* 0x224 */ + uint8_t reserved5[2]; /* 0x226 */ + /* 2.02+ */ + uint32_t cmd_line_ptr; /* 0x228 */ + /* 2.03+ */ + uint32_t initrd_addr_max; /* 0x22c */ +} __attribute__ ((packed)); + + +/* Paramters passed to 32-bit part of Linux + * This is another view of the structure above.. */ +struct linux_params { + uint8_t orig_x; /* 0x00 */ + uint8_t orig_y; /* 0x01 */ + uint16_t ext_mem_k; /* 0x02 -- EXT_MEM_K sits here */ + uint16_t orig_video_page; /* 0x04 */ + uint8_t orig_video_mode; /* 0x06 */ + uint8_t orig_video_cols; /* 0x07 */ + uint16_t unused2; /* 0x08 */ + uint16_t orig_video_ega_bx; /* 0x0a */ + uint16_t unused3; /* 0x0c */ + uint8_t orig_video_lines; /* 0x0e */ + uint8_t orig_video_isVGA; /* 0x0f */ + uint16_t orig_video_points; /* 0x10 */ + + /* VESA graphic mode -- linear frame buffer */ + uint16_t lfb_width; /* 0x12 */ + uint16_t lfb_height; /* 0x14 */ + uint16_t lfb_depth; /* 0x16 */ + uint32_t lfb_base; /* 0x18 */ + uint32_t lfb_size; /* 0x1c */ + uint16_t cl_magic; /* 0x20 */ +#define CL_MAGIC_VALUE 0xA33F + uint16_t cl_offset; /* 0x22 */ + uint16_t lfb_linelength; /* 0x24 */ + uint8_t red_size; /* 0x26 */ + uint8_t red_pos; /* 0x27 */ + uint8_t green_size; /* 0x28 */ + uint8_t green_pos; /* 0x29 */ + uint8_t blue_size; /* 0x2a */ + uint8_t blue_pos; /* 0x2b */ + uint8_t rsvd_size; /* 0x2c */ + uint8_t rsvd_pos; /* 0x2d */ + uint16_t vesapm_seg; /* 0x2e */ + uint16_t vesapm_off; /* 0x30 */ + uint16_t pages; /* 0x32 */ + uint8_t reserved4[12]; /* 0x34 -- 0x3f reserved for future expansion */ + + //struct apm_bios_info apm_bios_info; /* 0x40 */ + uint8_t apm_bios_info[0x40]; + //struct drive_info_struct drive_info; /* 0x80 */ + uint8_t drive_info[0x20]; + //struct sys_desc_table sys_desc_table; /* 0xa0 */ + uint8_t sys_desc_table[0x140]; + uint32_t alt_mem_k; /* 0x1e0 */ + uint8_t reserved5[4]; /* 0x1e4 */ + uint8_t e820_map_nr; /* 0x1e8 */ + uint8_t reserved6[9]; /* 0x1e9 */ + uint16_t mount_root_rdonly; /* 0x1f2 */ + uint8_t reserved7[4]; /* 0x1f4 */ + uint16_t ramdisk_flags; /* 0x1f8 */ +#define RAMDISK_IMAGE_START_MASK 0x07FF +#define RAMDISK_PROMPT_FLAG 0x8000 +#define RAMDISK_LOAD_FLAG 0x4000 + uint8_t reserved8[2]; /* 0x1fa */ + uint16_t orig_root_dev; /* 0x1fc */ + uint8_t reserved9[1]; /* 0x1fe */ + uint8_t aux_device_info; /* 0x1ff */ + uint8_t reserved10[2]; /* 0x200 */ + uint8_t param_block_signature[4]; /* 0x202 */ + uint16_t param_block_version; /* 0x206 */ + uint8_t reserved11[8]; /* 0x208 */ + uint8_t loader_type; /* 0x210 */ +#define LOADER_TYPE_LOADLIN 1 +#define LOADER_TYPE_BOOTSECT_LOADER 2 +#define LOADER_TYPE_SYSLINUX 3 +#define LOADER_TYPE_ETHERBOOT 4 +#define LOADER_TYPE_KERNEL 5 + uint8_t loader_flags; /* 0x211 */ + uint8_t reserved12[2]; /* 0x212 */ + uint32_t kernel_start; /* 0x214 */ + uint32_t initrd_start; /* 0x218 */ + uint32_t initrd_size; /* 0x21c */ + uint8_t reserved12_5[8]; /* 0x220 */ + uint32_t cmd_line_ptr; /* 0x228 */ + uint8_t reserved13[164]; /* 0x22c */ + struct e820entry e820_map[E820MAX]; /* 0x2d0 */ + uint8_t reserved16[688]; /* 0x550 */ +#define COMMAND_LINE_SIZE 256 + /* Command line is copied here by 32-bit i386/kernel/head.S. + * So I will follow the boot protocol, rather than putting it + * directly here. --ts1 */ + uint8_t command_line[COMMAND_LINE_SIZE]; /* 0x800 */ + uint8_t reserved17[1792]; /* 0x900 - 0x1000 */ +}; + +uint64_t forced_memsize; + +/* Load the first part the file and check if it's Linux */ +static uint32_t load_linux_header(struct linux_header *hdr) +{ + int load_high; + uint32_t kern_addr; + + if (lfile_read(hdr, sizeof *hdr) != sizeof *hdr) { + debug("Can't read Linux header\n"); + return 0; + } + if (hdr->boot_sector_magic != 0xaa55) { + debug("Not a Linux kernel image\n"); + return 0; + } + + /* Linux is found. Print some information */ + if (memcmp(hdr->header_magic, "HdrS", 4) != 0) { + /* This may be floppy disk image or something. + * Perform a simple (incomplete) sanity check. */ + if (hdr->setup_sects >= 16 + || file_size() - (hdr->setup_sects<<9) >= 512<<10) { + debug("This looks like a bootdisk image but not like Linux...\n"); + return 0; + } + + printf("Possible very old Linux"); + /* This kernel does not even have a protocol version. + * Force the value. */ + hdr->protocol_version = 0; /* pre-2.00 */ + } else + printf("Found Linux"); + if (hdr->protocol_version >= 0x200 && hdr->kver_addr) { + char kver[256]; + file_seek(hdr->kver_addr + 0x200); + if (lfile_read(kver, sizeof kver) != 0) { + kver[255] = 0; + printf(" version %s", kver); + } + } + debug(" (protocol %#x)", hdr->protocol_version); + load_high = 0; + if (hdr->protocol_version >= 0x200) { + debug(" (loadflags %#x)", hdr->loadflags); + load_high = hdr->loadflags & 1; + } + if (load_high) { + printf(" bzImage"); + kern_addr = 0x100000; + } else { + printf(" zImage or Image"); + kern_addr = 0x1000; + } + printf(".\n"); + + return kern_addr; +} + +/* Set up parameters for 32-bit kernel */ +static void +init_linux_params(struct linux_params *params, struct linux_header *hdr) +{ + debug("Setting up paramters at %#lx\n", virt_to_phys(params)); + memset(params, 0, sizeof *params); + + /* Copy some useful values from header */ + params->mount_root_rdonly = hdr->root_flags; + params->orig_root_dev = hdr->root_dev; + + /* Video parameters. + * This assumes we have VGA in standard 80x25 text mode, + * just like our vga.c does. + * Cursor position is filled later to allow some more printf's. */ + params->orig_video_mode = 3; + params->orig_video_cols = 80; + params->orig_video_lines = 25; + params->orig_video_isVGA = 1; + params->orig_video_points = 16; + + params->loader_type = 0xff; /* Unregistered Linux loader */ +} + +/* Memory map */ +static void +set_memory_size(struct linux_params *params, struct sys_info *info) +{ + int i; + uint64_t end; + uint32_t ramtop = 0; + struct e820entry *linux_map; + struct memrange *filo_map; + + linux_map = params->e820_map; + filo_map = info->memrange; + for (i = 0; i < info->n_memranges; i++, linux_map++, filo_map++) { + if (i < E820MAX) { + /* Convert to BIOS e820 style */ + linux_map->addr = filo_map->base; + linux_map->size = filo_map->size; + linux_map->type = E820_RAM; + debug("%016Lx - %016Lx\n", linux_map->addr, + linux_map->addr + linux_map->size); + params->e820_map_nr = i+1; + } + + /* Find out top of RAM. XXX This ignores hole above 1MB */ + end = filo_map->base + filo_map->size; + if (end < (1ULL << 32)) { /* don't count memory above 4GB */ + if (end > ramtop) + ramtop = (uint32_t) end; + } + } + debug("ramtop=%#x\n", ramtop); + /* Size of memory above 1MB in KB */ + params->alt_mem_k = (ramtop - (1<<20)) >> 10; + /* old style, 64MB max */ + if (ramtop >= (64<<20)) + params->ext_mem_k = (63<<10); + else + params->ext_mem_k = params->alt_mem_k; + debug("ext_mem_k=%d, alt_mem_k=%d\n", params->ext_mem_k, params->alt_mem_k); +} + +/* + * Parse command line + * Some parameters, like initrd=<file>, are not passed to kernel, + * we are responsible to process them. + * Parameters for kernel are copied to kern_cmdline. Returns name of initrd. + */ +static char *parse_command_line(const char *orig_cmdline, char *kern_cmdline) +{ + const char *start, *sep, *end, *val; + char name[64]; + int len; + int k_len; + int to_kern; + char *initrd = 0; + int toolong = 0; + + forced_memsize = 0; + + if (!orig_cmdline) { + *kern_cmdline = 0; + return 0; + } + + k_len = 0; + debug("original command line: \"%s\"\n", orig_cmdline); + debug("kernel command line at %#lx\n", virt_to_phys(kern_cmdline)); + + start = orig_cmdline; + while (*start == ' ') + start++; + while (*start) { + end = strchr(start, ' '); + if (!end) + end = start + strlen(start); + sep = strchr(start, '='); + if (!sep || sep > end) + sep = end; + len = sep - start; + if (len >= sizeof(name)) + len = sizeof(name) - 1; + memcpy(name, start, len); + name[len] = 0; + + if (*sep == '=') { + val = sep + 1; + len = end - val; + } else { + val = 0; + len = 0; + } + + /* Only initrd= and mem= are handled here. vga= is not, + * which I believe is a paramter to the realmode part of Linux, + * which we don't execute. */ + if (strcmp(name, "initrd") == 0) { + if (!val) + printf("Missing filename to initrd parameter\n"); + else { + initrd = malloc(len + 1); + memcpy(initrd, val, len); + initrd[len] = 0; + debug("initrd=%s\n", initrd); + } + /* Don't pass this to kernel */ + to_kern = 0; + } else if (strcmp(name, "mem") == 0) { + if (!val) + printf("Missing value for mem parameter\n"); + else { + forced_memsize = strtoull_with_suffix(val, (char**)&val, 0); + if (forced_memsize == 0) + printf("Invalid mem option, ignored\n"); + if (val != end) { + printf("Garbage after mem=<size>, ignored\n"); + forced_memsize = 0; + } + debug("mem=%Lu\n", forced_memsize); + } + /* mem= is for both loader and kernel */ + to_kern = 1; + } else + to_kern = 1; + + if (to_kern) { + /* Copy to kernel command line buffer */ + if (k_len != 0) + kern_cmdline[k_len++] = ' '; /* put separator */ + len = end - start; + if (k_len + len >= COMMAND_LINE_SIZE) { + len = COMMAND_LINE_SIZE - k_len - 1; + if (!toolong) { + printf("Kernel command line is too long; truncated to " + "%d bytes\n", COMMAND_LINE_SIZE-1); + toolong = 1; + } + } + memcpy(kern_cmdline + k_len, start, len); + k_len += len; + } + + start = end; + while (*start == ' ') + start++; + } + kern_cmdline[k_len] = 0; + debug("kernel command line (%d bytes): \"%s\"\n", k_len, kern_cmdline); + + return initrd; +} + +/* Set command line location */ +static void set_command_line_loc(struct linux_params *params, + struct linux_header *hdr) +{ + if (hdr->protocol_version >= 0x202) { + /* new style */ + params->cmd_line_ptr = COMMAND_LINE_LOC; + } else { + /* old style */ + params->cl_magic = CL_MAGIC_VALUE; + params->cl_offset = COMMAND_LINE_LOC - LINUX_PARAM_LOC; + } +} + +/* Load 32-bit part of kernel */ +static int load_linux_kernel(struct linux_header *hdr, uint32_t kern_addr) +{ + uint32_t kern_offset, kern_size; + + if (hdr->setup_sects == 0) + hdr->setup_sects = 4; + kern_offset = (hdr->setup_sects + 1) * 512; + file_seek(kern_offset); + kern_size = file_size() - kern_offset; + debug("offset=%#x addr=%#x size=%#x\n", kern_offset, kern_addr, kern_size); + +#if 0 + if (using_devsize) { + printf("Attempt to load up to end of device as kernel; " + "specify the image size\n"); + return 0; + } +#endif + + printf("Loading kernel... "); + if (lfile_read(phys_to_virt(kern_addr), kern_size) != kern_size) { + printf("Can't read kernel\n"); + return 0; + } + printf("ok\n"); + + return kern_size; +} + +static int load_initrd(struct linux_header *hdr, struct sys_info *info, + uint32_t kern_end, struct linux_params *params, const char *initrd_file) +{ + uint32_t max; + uint32_t start, end, size; + uint64_t forced; + extern char _start[], _end[]; + + if (!file_open(initrd_file)) { + printf("Can't open initrd: %s\n", initrd_file); + return -1; + } + +#if 0 + if (using_devsize) { + printf("Attempt to load up to end of device as initrd; " + "specify the image size\n"); + return -1; + } +#endif + + size = file_size(); + + + /* Find out the kernel's restriction on how high the initrd can be + * placed */ + if (hdr->protocol_version >= 0x203) + max = hdr->initrd_addr_max; + else + max = 0x38000000; /* Hardcoded value for older kernels */ + + /* FILO itself is at the top of RAM. (relocated) + * So, try putting initrd just below us. */ + end = virt_to_phys(_start); + if (end > max) + end = max; + + /* If "mem=" option is given, we have to put the initrd within + * the specified range. */ + if (forced_memsize) { + forced = forced_memsize; + if (forced > max) + forced = max; + /* If the "mem=" is lower, it's easy */ + if (forced <= end) + end = forced; + else { + /* Otherwise, see if we can put it above us */ + if (virt_to_phys(_end) + size <= forced) + end = forced; /* Ok */ + } + } + + start = end - size; + start &= ~0xfff; /* page align */ + end = start + size; + + debug("start=%#x end=%#x\n", start, end); + + if (start < kern_end) { + printf("Initrd is too big to fit in memory\n"); + return -1; + } + + printf("Loading initrd... "); + if (lfile_read(phys_to_virt(start), size) != size) { + printf("Can't read initrd\n"); + return -1; + } + printf("ok\n"); + + params->initrd_start = start; + params->initrd_size = size; + + return 0; +} + +static void hardware_setup(void) +{ + /* Disable nmi */ + outb(0x80, 0x70); + + /* Make sure any coprocessor is properly reset.. */ + outb(0, 0xf0); + outb(0, 0xf1); + + /* we're getting screwed again and again by this problem of the 8259. + * so we're going to leave this lying around for inclusion into + * crt0.S on an as-needed basis. + * + * well, that went ok, I hope. Now we have to reprogram the interrupts :-( + * we put them right after the intel-reserved hardware interrupts, at + * int 0x20-0x2F. There they won't mess up anything. Sadly IBM really + * messed this up with the original PC, and they haven't been able to + * rectify it afterwards. Thus the bios puts interrupts at 0x08-0x0f, + * which is used for the internal hardware interrupts as well. We just + * have to reprogram the 8259's, and it isn't fun. + */ + + outb(0x11, 0x20); /* initialization sequence to 8259A-1 */ + outb(0x11, 0xA0); /* and to 8259A-2 */ + + outb(0x20, 0x21); /* start of hardware int's (0x20) */ + outb(0x28, 0xA1); /* start of hardware int's 2 (0x28) */ + + outb(0x04, 0x21); /* 8259-1 is master */ + outb(0x02, 0xA1); /* 8259-2 is slave */ + + outb(0x01, 0x21); /* 8086 mode for both */ + outb(0x01, 0xA1); + + outb(0xFF, 0xA1); /* mask off all interrupts for now */ + outb(0xFB, 0x21); /* mask all irq's but irq2 which is cascaded */ +} + +/* Start Linux */ +static int start_linux(uint32_t kern_addr, struct linux_params *params) +{ + struct segment_desc *linux_gdt; + struct context *ctx; + //extern int cursor_x, cursor_y; + + ctx = init_context(phys_to_virt(STACK_LOC), 4096, 0); + + /* Linux expects GDT being in low memory */ + linux_gdt = phys_to_virt(GDT_LOC); + memset(linux_gdt, 0, 13*sizeof(struct segment_desc)); + /* Normal kernel code/data segments */ + linux_gdt[2] = gdt[FLAT_CODE]; + linux_gdt[3] = gdt[FLAT_DATA]; + /* 2.6 kernel uses 12 and 13, but head.S uses backward-compatible + * segments (2 and 3), so it SHOULD not be a problem. + * However, some distro kernels (eg. RH9) with backported threading + * patch use 12 and 13 also when booting... */ + linux_gdt[12] = gdt[FLAT_CODE]; + linux_gdt[13] = gdt[FLAT_DATA]; + ctx->gdt_base = GDT_LOC; + ctx->gdt_limit = 14*8-1; + ctx->cs = 0x10; + ctx->ds = 0x18; + ctx->es = 0x18; + ctx->fs = 0x18; + ctx->gs = 0x18; + ctx->ss = 0x18; + + /* Parameter location */ + ctx->esi = virt_to_phys(params); + + /* Entry point */ + ctx->eip = kern_addr; + + debug("eip=%#x\n", kern_addr); + printf("Jumping to entry point...\n"); + +#ifdef VGA_CONSOLE + /* Update VGA cursor position. + * This must be here because the printf changes the value! */ + params->orig_x = cursor_x; + params->orig_y = cursor_y; +#endif + + /* Go... */ + ctx = switch_to(ctx); + + /* It's impossible but... */ + printf("Returned with eax=%#x\n", ctx->eax); + + return ctx->eax; +} + +int linux_load(struct sys_info *info, const char *file, const char *cmdline) +{ + struct linux_header hdr; + struct linux_params *params; + uint32_t kern_addr, kern_size; + char *initrd_file = 0; + + if (!file_open(file)) + return -1; + + kern_addr = load_linux_header(&hdr); + if (kern_addr == 0) + return LOADER_NOT_SUPPORT; + + params = phys_to_virt(LINUX_PARAM_LOC); + init_linux_params(params, &hdr); + set_memory_size(params, info); + initrd_file = parse_command_line(cmdline, phys_to_virt(COMMAND_LINE_LOC)); + set_command_line_loc(params, &hdr); + + kern_size = load_linux_kernel(&hdr, kern_addr); + if (kern_size == 0) { + if (initrd_file) + free(initrd_file); + return -1; + } + + if (initrd_file) { + if (load_initrd(&hdr, info, kern_addr+kern_size, params, initrd_file) + != 0) { + free(initrd_file); + return -1; + } + free(initrd_file); + } + + hardware_setup(); + + start_linux(kern_addr, params); + return 0; +} diff --git a/qemu/roms/openbios/arch/amd64/multiboot.c b/qemu/roms/openbios/arch/amd64/multiboot.c new file mode 100644 index 000000000..4271bd52b --- /dev/null +++ b/qemu/roms/openbios/arch/amd64/multiboot.c @@ -0,0 +1,125 @@ +/* Support for Multiboot */ + +#include "config.h" +#include "asm/io.h" +#include "libopenbios/sys_info.h" +#include "multiboot.h" + +#define printf printk +#ifdef CONFIG_DEBUG_BOOT +#define debug printk +#else +#define debug(x...) +#endif + +struct mbheader { + unsigned int magic, flags, checksum; +}; +const struct mbheader multiboot_header + __attribute__((section (".hdr"))) = +{ + MULTIBOOT_HEADER_MAGIC, + MULTIBOOT_HEADER_FLAGS, + -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS) +}; + +/* Multiboot information structure, provided by loader to us */ + +struct multiboot_mmap { + unsigned entry_size; + unsigned base_lo, base_hi; + unsigned size_lo, size_hi; + unsigned type; +}; + +#define MULTIBOOT_MEM_VALID 0x01 +#define MULTIBOOT_BOOT_DEV_VALID 0x02 +#define MULTIBOOT_CMDLINE_VALID 0x04 +#define MULTIBOOT_MODS_VALID 0x08 +#define MULTIBOOT_AOUT_SYMS_VALID 0x10 +#define MULTIBOOT_ELF_SYMS_VALID 0x20 +#define MULTIBOOT_MMAP_VALID 0x40 + +void collect_multiboot_info(struct sys_info *info); +void collect_multiboot_info(struct sys_info *info) +{ + struct multiboot_info *mbinfo; + struct multiboot_mmap *mbmem; + unsigned mbcount, mbaddr; + int i; + struct memrange *mmap; + int mmap_count; + module_t *mod; + + if (info->boot_type != 0x2BADB002) + return; + + debug("Using Multiboot information at %#lx\n", info->boot_data); + + mbinfo = phys_to_virt(info->boot_data); + + if (mbinfo->mods_count != 1) { + printf("Multiboot: no dictionary\n"); + return; + } + + mod = (module_t *) mbinfo->mods_addr; + info->dict_start=(unsigned long *)mod->mod_start; + info->dict_end=(unsigned long *)mod->mod_end; + + if (mbinfo->flags & MULTIBOOT_MMAP_VALID) { + /* convert mmap records */ + mbmem = phys_to_virt(mbinfo->mmap_addr); + mbcount = mbinfo->mmap_length / (mbmem->entry_size + 4); + mmap = malloc(mbcount * sizeof(struct memrange)); + mmap_count = 0; + mbaddr = mbinfo->mmap_addr; + for (i = 0; i < mbcount; i++) { + mbmem = phys_to_virt(mbaddr); + debug("%08x%08x %08x%08x (%d)\n", + mbmem->base_hi, + mbmem->base_lo, + mbmem->size_hi, + mbmem->size_lo, + mbmem->type); + if (mbmem->type == 1) { /* Only normal RAM */ + mmap[mmap_count].base = mbmem->base_lo + + (((unsigned long long) mbmem->base_hi) << 32); + mmap[mmap_count].size = mbmem->size_lo + + (((unsigned long long) mbmem->size_hi) << 32); + mmap_count++; + } + mbaddr += mbmem->entry_size + 4; + if (mbaddr >= mbinfo->mmap_addr + mbinfo->mmap_length) + break; + } + /* simple sanity check - there should be at least 2 RAM segments + * (base 640k and extended) */ + if (mmap_count >= 2) + goto got_it; + + printf("Multiboot mmap is broken\n"); + free(mmap); + /* fall back to mem_lower/mem_upper */ + } + + if (mbinfo->flags & MULTIBOOT_MEM_VALID) { + /* use mem_lower and mem_upper */ + mmap_count = 2; + mmap = malloc(2 * sizeof(*mmap)); + mmap[0].base = 0; + mmap[0].size = mbinfo->mem_lower << 10; + mmap[1].base = 1 << 20; /* 1MB */ + mmap[1].size = mbinfo->mem_upper << 10; + goto got_it; + } + + printf("Can't get memory information from Multiboot\n"); + return; + +got_it: + info->memrange = mmap; + info->n_memranges = mmap_count; + + return; +} diff --git a/qemu/roms/openbios/arch/amd64/multiboot.h b/qemu/roms/openbios/arch/amd64/multiboot.h new file mode 100644 index 000000000..17cf202ec --- /dev/null +++ b/qemu/roms/openbios/arch/amd64/multiboot.h @@ -0,0 +1,96 @@ +/* multiboot.h + * tag: header for multiboot + * + * Copyright (C) 2003-2004 Stefan Reinauer + * + * See the file "COPYING" for further information about + * the copyright and warranty status of this work. + */ + +/* magic number for multiboot header */ +#define MULTIBOOT_HEADER_MAGIC 0x1BADB002 + +/* flags for multiboot header */ +#define MULTIBOOT_HEADER_FLAGS 0x00010003 + +/* magic number passed by multiboot-compliant boot loader. */ +#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002 + +/* The size of our stack (8KB). */ +#define STACK_SIZE 0x2000 + +/* C symbol format. HAVE_ASM_USCORE is defined by configure. */ +#ifdef HAVE_ASM_USCORE +# define EXT_C(sym) _ ## sym +#else +# define EXT_C(sym) sym +#endif + +#ifndef ASM +/* We don't want these declarations in boot.S */ + +/* multiboot header */ +typedef struct multiboot_header { + unsigned long magic; + unsigned long flags; + unsigned long checksum; + unsigned long header_addr; + unsigned long load_addr; + unsigned long load_end_addr; + unsigned long bss_end_addr; + unsigned long entry_addr; +} multiboot_header_t; + +/* symbol table for a.out */ +typedef struct aout_symbol_table { + unsigned long tabsize; + unsigned long strsize; + unsigned long addr; + unsigned long reserved; +} aout_symbol_table_t; + +/* section header table for ELF */ +typedef struct elf_section_header_table { + unsigned long num; + unsigned long size; + unsigned long addr; + unsigned long shndx; +} elf_section_header_table_t; + +/* multiboot information */ +typedef struct multiboot_info { + unsigned long flags; + unsigned long mem_lower; + unsigned long mem_upper; + unsigned long boot_device; + unsigned long cmdline; + unsigned long mods_count; + unsigned long mods_addr; + union { + aout_symbol_table_t aout_sym; + elf_section_header_table_t elf_sec; + } u; + unsigned long mmap_length; + unsigned long mmap_addr; +} multiboot_info_t; + +/* module structure */ +typedef struct module { + unsigned long mod_start; + unsigned long mod_end; + unsigned long string; + unsigned long reserved; +} module_t; + +/* memory map. Be careful that the offset 0 is base_addr_low + but no size. */ +typedef struct memory_map { + unsigned long size; + unsigned long base_addr_low; + unsigned long base_addr_high; + unsigned long length_low; + unsigned long length_high; + unsigned long type; +} memory_map_t; + +#endif /* ! ASM */ diff --git a/qemu/roms/openbios/arch/amd64/openbios.c b/qemu/roms/openbios/arch/amd64/openbios.c new file mode 100644 index 000000000..15d3b6254 --- /dev/null +++ b/qemu/roms/openbios/arch/amd64/openbios.c @@ -0,0 +1,108 @@ +/* tag: openbios forth environment, executable code + * + * Copyright (C) 2003 Patrick Mauritz, Stefan Reinauer + * + * See the file "COPYING" for further information about + * the copyright and warranty status of this work. + */ + +#include "config.h" +#include "libopenbios/openbios.h" +#include "libopenbios/bindings.h" +#include "asm/types.h" +#include "dict.h" +#include "kernel/kernel.h" +#include "kernel/stack.h" +#include "libopenbios/sys_info.h" +#include "openbios.h" +#include "relocate.h" + +void boot(void); + +#define DICTIONARY_SIZE (256*1024) /* 256K for the dictionary */ +static char intdict[DICTIONARY_SIZE]; + +static void init_memory(void) +{ + /* push start and end of available memory to the stack + * so that the forth word QUIT can initialize memory + * management. For now we use hardcoded memory between + * 0x10000 and 0x9ffff (576k). If we need more memory + * than that we have serious bloat. + */ + + PUSH(0x10000); + PUSH(0x9FFFF); +} + +static void +arch_init( void ) +{ + void setup_timers(void); + + openbios_init(); + modules_init(); +#ifdef CONFIG_DRIVER_IDE + setup_timers(); + ob_ide_init("/pci/pci-ata", 0x1f0, 0x3f6, 0x170, 0x376); +#endif + device_end(); + bind_func("platform-boot", boot ); +} + +extern struct _console_ops arch_console_ops; + +int openbios(void) +{ +#ifdef CONFIG_DEBUG_CONSOLE + init_console(arch_console_ops); +#ifdef CONFIG_DEBUG_CONSOLE_SERIAL + uart_init(CONFIG_SERIAL_PORT, CONFIG_SERIAL_SPEED); +#endif + /* Clear the screen. */ + cls(); +#endif + + collect_sys_info(&sys_info); + + dict=intdict; + dictlimit = DICTIONARY_SIZE; + + load_dictionary((char *)sys_info.dict_start, + sys_info.dict_end-sys_info.dict_start); + forth_init(); + + relocate(&sys_info); + +#ifdef CONFIG_DEBUG_CONSOLE + video_init(); +#endif +#ifdef CONFIG_DEBUG_BOOT + printk("forth started.\n"); + printk("initializing memory..."); +#endif + + init_memory(); + +#ifdef CONFIG_DEBUG_BOOT + printk("done\n"); +#endif + + PUSH_xt( bind_noname_func(arch_init) ); + fword("PREPOST-initializer"); + + PC = (ucell)findword("initialize-of"); + + if (!PC) { + printk("panic: no dictionary entry point.\n"); + return -1; + } +#ifdef CONFIG_DEBUG_DICTIONARY + printk("done (%d bytes).\n", dicthead); + printk("Jumping to dictionary...\n"); +#endif + + enterforth((xt_t)PC); + + return 0; +} diff --git a/qemu/roms/openbios/arch/amd64/openbios.h b/qemu/roms/openbios/arch/amd64/openbios.h new file mode 100644 index 000000000..2d49dbf54 --- /dev/null +++ b/qemu/roms/openbios/arch/amd64/openbios.h @@ -0,0 +1,29 @@ +/* + * Creation Date: <2004/01/15 16:14:05 samuel> + * Time-stamp: <2004/01/15 16:14:05 samuel> + * + * <openbios.h> + * + * + * + * Copyright (C) 2004 Samuel Rydh (samuel@ibrium.se) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#ifndef _H_OPENBIOS +#define _H_OPENBIOS + +int openbios(void); + +/* console.c */ +extern void cls(void); +#ifdef CONFIG_DEBUG_CONSOLE +extern int uart_init(int port, unsigned long speed); +extern void video_init(void); +#endif + +#endif /* _H_OPENBIOS */ diff --git a/qemu/roms/openbios/arch/amd64/plainboot.c b/qemu/roms/openbios/arch/amd64/plainboot.c new file mode 100644 index 000000000..08dab2d12 --- /dev/null +++ b/qemu/roms/openbios/arch/amd64/plainboot.c @@ -0,0 +1,21 @@ +/* tag: openbios fixed address forth starter + * + * Copyright (C) 2003 Stefan Reinauer + * + * See the file "COPYING" for further information about + * the copyright and warranty status of this work. + */ + +#include "config.h" +#include "libopenbios/sys_info.h" +#include "multiboot.h" + +#define FIXED_DICTSTART 0xfffe0000 +#define FIXED_DICTEND 0xfffeffff + +void collect_multiboot_info(struct sys_info *info); +void collect_multiboot_info(struct sys_info *info) +{ + info->dict_start=(unsigned long *)FIXED_DICTSTART; + info->dict_end=(unsigned long *)FIXED_DICTEND; +} diff --git a/qemu/roms/openbios/arch/amd64/relocate.h b/qemu/roms/openbios/arch/amd64/relocate.h new file mode 100644 index 000000000..d91160a03 --- /dev/null +++ b/qemu/roms/openbios/arch/amd64/relocate.h @@ -0,0 +1 @@ +void relocate(struct sys_info *); diff --git a/qemu/roms/openbios/arch/amd64/segment.c b/qemu/roms/openbios/arch/amd64/segment.c new file mode 100644 index 000000000..09763bd14 --- /dev/null +++ b/qemu/roms/openbios/arch/amd64/segment.c @@ -0,0 +1,134 @@ +/* Segmentation of the AMD64 architecture. + * + * 2003-07 by SONE Takeshi + */ + +#include "config.h" +#include "kernel/kernel.h" +#include "libopenbios/sys_info.h" +#include "relocate.h" +#include "segment.h" + +#define printf printk +#ifdef CONFIG_DEBUG_BOOT +#define debug printk +#else +#define debug(x...) +#endif + +/* i386 lgdt argument */ +struct gdtarg { + unsigned short limit; + unsigned int base; +} __attribute__((packed)); + +/* How far the virtual address (used in C) is different from physical + * address. Since we start in flat mode, the initial value is zero. */ +unsigned long virt_offset = 0; + +/* GDT, the global descriptor table */ +struct segment_desc gdt[NUM_SEG] = { + /* 0x00: null segment */ + {0, 0, 0, 0, 0, 0}, + /* 0x08: flat code segment */ + {0xffff, 0, 0, 0x9f, 0xcf, 0}, + /* 0x10: flat data segment */ + {0xffff, 0, 0, 0x93, 0xcf, 0}, + /* 0x18: code segment for relocated execution */ + {0xffff, 0, 0, 0x9f, 0xcf, 0}, + /* 0x20: data segment for relocated execution */ + {0xffff, 0, 0, 0x93, 0xcf, 0}, +}; + +extern char _start[], _end[]; + +void relocate(struct sys_info *info) +{ + int i; + unsigned long prog_addr; + unsigned long prog_size; + unsigned long addr, new_base; + unsigned long long segsize; + unsigned long new_offset; + unsigned d0, d1, d2; + struct gdtarg gdtarg; +#define ALIGNMENT 16 + + prog_addr = virt_to_phys(&_start); + prog_size = virt_to_phys(&_end) - virt_to_phys(&_start); + debug("Current location: %#lx-%#lx\n", prog_addr, prog_addr+prog_size-1); + + new_base = 0; + for (i = 0; i < info->n_memranges; i++) { + if (info->memrange[i].base >= 1ULL<<32) + continue; + segsize = info->memrange[i].size; + if (info->memrange[i].base + segsize > 1ULL<<32) + segsize = (1ULL<<32) - info->memrange[i].base; + if (segsize < prog_size+ALIGNMENT) + continue; + addr = info->memrange[i].base + segsize - prog_size; + addr &= ~(ALIGNMENT-1); + if (addr >= prog_addr && addr < prog_addr + prog_size) + continue; + if (prog_addr >= addr && prog_addr < addr + prog_size) + continue; + if (addr > new_base) + new_base = addr; + } + if (new_base == 0) { + printf("Can't find address to relocate\n"); + return; + } + + debug("Relocating to %#lx-%#lx... ", + new_base, new_base + prog_size - 1); + + /* New virtual address offset */ + new_offset = new_base - (unsigned long) &_start; + + /* Tweak the GDT */ + gdt[RELOC_CODE].base_0 = (unsigned short) new_offset; + gdt[RELOC_CODE].base_16 = (unsigned char) (new_offset>>16); + gdt[RELOC_CODE].base_24 = (unsigned char) (new_offset>>24); + gdt[RELOC_DATA].base_0 = (unsigned short) new_offset; + gdt[RELOC_DATA].base_16 = (unsigned char) (new_offset>>16); + gdt[RELOC_DATA].base_24 = (unsigned char) (new_offset>>24); + + /* Load new GDT and reload segments */ + gdtarg.base = new_offset + (unsigned long) gdt; + gdtarg.limit = GDT_LIMIT; + __asm__ __volatile__ ( + "rep; movsb\n\t" /* copy everything */ + "lgdt %3\n\t" + "ljmp %4, $1f\n1:\t" + "movw %5, %%ds\n\t" + "movw %5, %%es\n\t" + "movw %5, %%fs\n\t" + "movw %5, %%gs\n\t" + "movw %5, %%ss\n" + : "=&S" (d0), "=&D" (d1), "=&c" (d2) + : "m" (gdtarg), "n" (RELOC_CS), "q" ((unsigned short) RELOC_DS), + "0" (&_start), "1" (new_base), "2" (prog_size)); + + virt_offset = new_offset; + debug("ok\n"); +} + +#if 0 +/* Copy GDT to new location and reload it */ +void move_gdt(unsigned long newgdt) +{ + struct gdtarg gdtarg; + + debug("Moving GDT to %#lx...", newgdt); + memcpy(phys_to_virt(newgdt), gdt, sizeof gdt); + gdtarg.base = newgdt; + gdtarg.limit = GDT_LIMIT; + debug("reloading GDT..."); + __asm__ __volatile__ ("lgdt %0\n\t" : : "m" (gdtarg)); + debug("reloading CS for fun..."); + __asm__ __volatile__ ("ljmp %0, $1f\n1:" : : "n" (RELOC_CS)); + debug("ok\n"); +} +#endif diff --git a/qemu/roms/openbios/arch/amd64/segment.h b/qemu/roms/openbios/arch/amd64/segment.h new file mode 100644 index 000000000..0371a80ae --- /dev/null +++ b/qemu/roms/openbios/arch/amd64/segment.h @@ -0,0 +1,30 @@ + +/* Segment indexes. Must match the gdt definition in segment.c. */ +enum { + NULL_SEG, + FLAT_CODE, + FLAT_DATA, + RELOC_CODE, + RELOC_DATA, + NUM_SEG, +}; + +/* Values for segment selector register */ +#define FLAT_CS (FLAT_CODE << 3) +#define FLAT_DS (FLAT_DATA << 3) +#define RELOC_CS (RELOC_CODE << 3) +#define RELOC_DS (RELOC_DATA << 3) + +/* i386 segment descriptor */ +struct segment_desc { + unsigned short limit_0; + unsigned short base_0; + unsigned char base_16; + unsigned char types; + unsigned char flags; + unsigned char base_24; +}; + +extern struct segment_desc gdt[NUM_SEG]; + +#define GDT_LIMIT ((NUM_SEG << 3) - 1) diff --git a/qemu/roms/openbios/arch/amd64/switch.S b/qemu/roms/openbios/arch/amd64/switch.S new file mode 100644 index 000000000..66668150d --- /dev/null +++ b/qemu/roms/openbios/arch/amd64/switch.S @@ -0,0 +1,116 @@ + .globl entry, __switch_context, __exit_context, halt + + .text + .align 4 + +/* + * Entry point + * We start execution from here. + * It is assumed that CPU is in 32-bit protected mode and + * all segments are 4GB and base zero (flat model). + */ +entry: + /* Save boot context and switch to our main context. + * Main context is statically defined in C. + */ + pushl %cs + call __switch_context + + /* We get here when the main context switches back to + * the boot context. + * Return to previous bootloader. + */ + ret + +/* + * Switch execution context + * This saves registers, segments, and GDT in the stack, then + * switches the stack, and restores everything from the new stack. + * This function takes no argument. New stack pointer is + * taken from global variable __context, and old stack pointer + * is also saved to __context. This way we can just jump to + * this routine to get back to the original context. + * + * Call this routine with lcall or pushl %cs; call. + */ +__switch_context: + /* Save everything in current stack */ + pushfl /* 56 */ + pushl %ds /* 52 */ + pushl %es /* 48 */ + pushl %fs /* 44 */ + pushl %gs /* 40 */ + pushal /* 8 */ + subl $8, %esp + movw %ss, (%esp) /* 0 */ + sgdt 2(%esp) /* 2 */ + +#if 0 + /* Swap %cs and %eip on the stack, so lret will work */ + movl 60(%esp), %eax + xchgl %eax, 64(%esp) + movl %eax, 60(%esp) +#endif + + /* At this point we don't know if we are on flat segment + * or relocated. So compute the address offset from %eip. + * Assuming CS.base==DS.base==SS.base. + */ + call 1f +1: popl %ebx + subl $1b, %ebx + + /* Interrupts are not allowed... */ + cli + + /* Current context pointer is our stack pointer */ + movl %esp, %esi + + /* Normalize the ctx pointer */ + subl %ebx, %esi + + /* Swap it with new value */ + xchgl %esi, __context(%ebx) + + /* Adjust new ctx pointer for current address offset */ + addl %ebx, %esi + + /* Load new %ss and %esp to temporary */ + movzwl (%esi), %edx + movl 20(%esi), %eax + + /* Load new GDT */ + lgdt 2(%esi) + + /* Load new stack segment with new GDT */ + movl %edx, %ss + + /* Set new stack pointer, but we have to adjust it because + * pushal saves %esp value before pushal, and we want the value + * after pushal. + */ + leal -32(%eax), %esp + + /* Load the rest from new stack */ + popal + popl %gs + popl %fs + popl %es + popl %ds + popfl + + /* Finally, load new %cs and %eip */ + lret + +__exit_context: + /* Get back to the original context */ + pushl %cs + call __switch_context + + /* We get here if the other context attempt to switch to this + * dead context. This should not happen. */ + +halt: + cli + hlt + jmp halt diff --git a/qemu/roms/openbios/arch/amd64/sys_info.c b/qemu/roms/openbios/arch/amd64/sys_info.c new file mode 100644 index 000000000..d62070be0 --- /dev/null +++ b/qemu/roms/openbios/arch/amd64/sys_info.c @@ -0,0 +1,58 @@ +#include "config.h" +#include "kernel/kernel.h" +#include "libopenbios/sys_info.h" +#include "context.h" + +#define printf printk +#ifdef CONFIG_DEBUG_BOOT +#define debug printk +#else +#define debug(x...) +#endif + +void collect_multiboot_info(struct sys_info *); +void collect_sys_info(struct sys_info *info); + +void collect_sys_info(struct sys_info *info) +{ + int i; + unsigned long long total = 0; + struct memrange *mmap; + + /* Pick up paramters given by bootloader to us */ + info->boot_type = boot_ctx->eax; + info->boot_data = boot_ctx->ebx; + info->boot_arg = boot_ctx->param[0]; + debug("boot eax = %#lx\n", info->boot_type); + debug("boot ebx = %#lx\n", info->boot_data); + debug("boot arg = %#lx\n", info->boot_arg); + + collect_elfboot_info(info); +#ifdef CONFIG_LINUXBIOS + collect_linuxbios_info(info); +#endif +#ifdef CONFIG_IMAGE_ELF_MULTIBOOT + collect_multiboot_info(info); +#endif + + if (!info->memrange) { + printf("Can't get memory map from firmware. " + "Using hardcoded default.\n"); + info->n_memranges = 2; + info->memrange = malloc(2 * sizeof(struct memrange)); + info->memrange[0].base = 0; + info->memrange[0].size = 640*1024; + info->memrange[1].base = 1024*1024; + info->memrange[1].size = 32*1024*1024 + - info->memrange[1].base; + } + + debug("\n"); + mmap=info->memrange; + for (i = 0; i < info->n_memranges; i++) { + debug("%016Lx-", mmap[i].base); + debug("%016Lx\n", mmap[i].base+mmap[i].size); + total += mmap[i].size; + } + debug("RAM %Ld MB\n", (total + 512*1024) >> 20); +} diff --git a/qemu/roms/openbios/arch/build.xml b/qemu/roms/openbios/arch/build.xml new file mode 100644 index 000000000..e3f324412 --- /dev/null +++ b/qemu/roms/openbios/arch/build.xml @@ -0,0 +1,10 @@ +<?xml version="1.0"?> +<build> + <include href="x86/build.xml"/> + <include href="amd64/build.xml"/> + <include href="ppc/build.xml"/> + <include href="ia64/build.xml"/> + <include href="unix/build.xml"/> + <include href="sparc32/build.xml"/> + <include href="sparc64/build.xml"/> +</build> diff --git a/qemu/roms/openbios/arch/ia64/Kconfig b/qemu/roms/openbios/arch/ia64/Kconfig new file mode 100644 index 000000000..6ba86de5d --- /dev/null +++ b/qemu/roms/openbios/arch/ia64/Kconfig @@ -0,0 +1,22 @@ +mainmenu "OpenBIOS Configuration" + +config IPF + bool + default y + help + Building for IPF hardware. + +config LITTLE_ENDIAN + bool + default y + help + IPF is little endian. + +menu "Build hosted UNIX Binary" +source "arch/unix/Kconfig" +endmenu + +source "kernel/Kconfig" +source "forth/Kconfig" +source "libopenbios/Kconfig" +source "drivers/Kconfig" diff --git a/qemu/roms/openbios/arch/ia64/build.xml b/qemu/roms/openbios/arch/ia64/build.xml new file mode 100644 index 000000000..8f3ea0d86 --- /dev/null +++ b/qemu/roms/openbios/arch/ia64/build.xml @@ -0,0 +1,5 @@ +<build condition="IPF"> + <dictionary name="openbios-ia64" init="openbios" target="forth"> + <object source="init.fs"/> + </dictionary> +</build> diff --git a/qemu/roms/openbios/arch/ia64/defconfig b/qemu/roms/openbios/arch/ia64/defconfig new file mode 100644 index 000000000..70cd97e51 --- /dev/null +++ b/qemu/roms/openbios/arch/ia64/defconfig @@ -0,0 +1,65 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_IPF=y +CONFIG_LITTLE_ENDIAN=y + +# +# Kernel binaries (x86) +# +# CONFIG_IMAGE_ELF is not set +# CONFIG_IMAGE_ELF_EMBEDDED is not set +# CONFIG_IMAGE_ELF_MULTIBOOT is not set + +# +# Build hosted UNIX Binary +# +CONFIG_HOST_UNIX=y +# CONFIG_PLUGIN_PCI is not set + +# +# Kernel Debugging +# +# CONFIG_DEBUG is not set +CONFIG_DEBUG_CONSOLE=y +CONFIG_DEBUG_CONSOLE_SERIAL=y +CONFIG_SERIAL_PORT=1 +CONFIG_SERIAL_SPEED=115200 +CONFIG_DEBUG_CONSOLE_VGA=y + +# +# Module Configuration +# +CONFIG_CMDLINE=y +CONFIG_DEBLOCKER=y + +# +# Filesystem Configuration +# +CONFIG_DISK_LABEL=y +CONFIG_PART_SUPPORT=y +CONFIG_PC_PARTS=y +CONFIG_FS=y +CONFIG_GRUBFS=y +CONFIG_FSYS_EXT2FS=y +CONFIG_FSYS_FAT=y +CONFIG_FSYS_JFS=y +# CONFIG_FSYS_MINIX is not set +CONFIG_FSYS_REISERFS=y +CONFIG_FSYS_XFS=y +CONFIG_FSYS_ISO9660=y +# CONFIG_FSYS_FFS is not set +# CONFIG_FSYS_VSTAFS is not set +# CONFIG_DEBUG_FS is not set + +# +# Miscellaneous +# +CONFIG_LINUXBIOS=y + +# +# Drivers +# +CONFIG_DRIVER_PCI=y +CONFIG_DRIVER_IDE=y +# CONFIG_DEBUG_IDE is not set diff --git a/qemu/roms/openbios/arch/ia64/init.fs b/qemu/roms/openbios/arch/ia64/init.fs new file mode 100644 index 000000000..5b65dd103 --- /dev/null +++ b/qemu/roms/openbios/arch/ia64/init.fs @@ -0,0 +1,76 @@ +:noname + ." Type 'help' for detailed information" cr + \ ." boot secondary slave cdrom: " cr + \ ." 0 > boot hd:2,\boot\vmlinuz root=/dev/hda2" cr + ; DIAG-initializer + +" /" find-device + +new-device + " memory" device-name + \ 12230 encode-int " reg" property + external + : open true ; + : close ; + \ claim ( phys size align -- base ) + \ release ( phys size -- ) +finish-device + +new-device + " cpus" device-name + 1 " #address-cells" int-property + 0 " #size-cells" int-property + + external + : open true ; + : close ; + : decode-unit parse-hex ; + +finish-device + +: make-openable ( path ) + find-dev if + begin ?dup while + \ install trivial open and close methods + dup active-package! is-open + parent + repeat + then +; + +: preopen ( chosen-str node-path ) + 2dup make-openable + + " /chosen" find-device + open-dev ?dup if + encode-int 2swap property + else + 2drop + then +; + +:noname + set-defaults +; SYSTEM-initializer + +\ preopen device nodes (and store the ihandles under /chosen) +:noname + " memory" " /memory" preopen + " mmu" " /cpus/@0" preopen + " stdout" " /builtin/console" preopen + " stdin" " /builtin/console" preopen + +; SYSTEM-initializer + +\ use the tty interface if available +:noname + " /builtin/console" find-dev if drop + " /builtin/console" " input-device" $setenv + " /builtin/console" " output-device" $setenv + then +; SYSTEM-initializer + +:noname + " keyboard" input +; CONSOLE-IN-initializer + diff --git a/qemu/roms/openbios/arch/ppc/Kconfig b/qemu/roms/openbios/arch/ppc/Kconfig new file mode 100644 index 000000000..f317c0a4d --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/Kconfig @@ -0,0 +1,48 @@ +mainmenu "OpenBIOS Configuration" + +config PPC + bool + default y + help + Building for PPC hardware. + +config BIG_ENDIAN + bool + default y + help + PPC hardware is big endian (per default) + +choice + prompt "Platform Type" + default MOL + +config MOL + bool "Mac-on-Linux" + help + Build an image for Mac-on-Linux + +config MPC107 + bool "MPC107 board (Crescendo)" + help + Build for Crescendo board. + +config BRIQ + bool "Total Impact briQ" + help + Build an image for the Total Impact briQ + +config NO_ARCH + bool "None" + help + Don't build any images. + +endchoice + +menu "Build hosted UNIX Binary" +source "arch/unix/Kconfig" +endmenu + +source "kernel/Kconfig" +source "forth/Kconfig" +source "libopenbios/Kconfig" +source "drivers/Kconfig" diff --git a/qemu/roms/openbios/arch/ppc/Makefile b/qemu/roms/openbios/arch/ppc/Makefile new file mode 100644 index 000000000..e182825e5 --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/Makefile @@ -0,0 +1,79 @@ + +include ../../config/Makefile.top + +SUBDIRS = +MOL = $(CONFIG_MOL:y=mol) +BRIQ = $(CONFIG_BRIQ:y=briq) +XTARGETS = $(MOL) $(BRIQ) ppc mollink +DICTIONARIES = $(MOL) $(BRIQ) + +INCLUDES = -I../../kernel -I../../kernel/include \ + -I../../include/molasm -I$(ODIR)/include + +############################################################################# + +mol-OBJS = mol/init.o mol/main.o mol/mol.o mol/console.o mol/osi-blk.o \ + mol/osi-scsi.o mol/pseudodisk.o mol/methods.o ofmem.o \ + mol/video.o mol/prom.o mol/tree.o misc.o mol/kernel.o + +briq-OBJS = briq/init.o briq/main.o briq/briq.o briq/vfd.o \ + ofmem.o briq/methods.o briq/tree.o \ + misc.o briq/kernel.o + +ppc-OBJS = $(KOBJS) $(MODULE_LIBS) \ + $(FS_LIBS) $(DRIVER_LIBS) $(LIBC_LIBS) + +all-$(CONFIG_MOL) += $(ODIR)/mol.image +all-$(CONFIG_BRIQ) += $(ODIR)/briq.image +all-$(CONFIG_MPC107) += $(ODIR)/mpc107.image + + +############################################################################# + +mol-SRC = ppc.fs tree.fs mol.fs $(ARCHDICT_SRC) +briq-SRC = ppc.fs briq/tree.fs briq/briq.fs $(ARCHDICT_SRC) + +$(ODIR)/mol/kernel.o: $(ODIR)/include/mol-dict.h +$(ODIR)/briq/kernel.o: $(ODIR)/include/briq-dict.h + +$(ODIR)/include/mol-dict.h: $(ODIR)/mol.dict + test -d $(dir $@) || $(INSTALL) -d $(dir $@) + @echo "static const char forth_dictionary[] = {" > $@ + @cat $< | hexdump -ve '1/0 "\t" 8/1 "0x%02x, " 1/0 "\n"' \ + | sed 's/0x ,//g' >> $@ + @echo "};" >> $@ + +$(ODIR)/include/briq-dict.h: $(ODIR)/briq.dict + test -d $(dir $@) || $(INSTALL) -d $(dir $@) + @echo "static const char forth_dictionary[] = {" > $@ + @cat $< | hexdump -ve '1/0 "\t" 8/1 "0x%02x, " 1/0 "\n"' \ + | sed 's/0x ,//g' >> $@ + @echo "};" >> $@ + +############################################################################# + +$(ODIR)/mol.image: $(ODIR)/start.o $(ODIR)/libmol.a $(ODIR)/libppc.a + @printf "= Building %-22s : " $@ + building= + $(LD) -Ttext=0x01e01000 -Bstatic $^ $(LIBGCC) -o $@ + @nm $@ | sort > $(ODIR)/mol.syms + strip -g $@ + @echo "ok" + +$(ODIR)/briq.image: $(ODIR)/start.o $(ODIR)/timebase.o $(ODIR)/libbriq.a $(ODIR)/libppc.a + @printf "= Building %-22s : " $@ + building= + $(LD) -g -Ttext=0x01e01000 -Bstatic $^ $(LIBGCC) -o $@ + @nm $@ | sort > $(ODIR)/briq.syms + #strip -g $@ + @echo "ok" + +$(ODIR)/mpc107.image: + @echo "BUILDING mpc107.image (not yet implemented)" + +clean-local: + $(RM) $(ODIR)/*.image $(ODIR)/*.syms $(ODIR)/include/mol-dict.h + +include Makefile.asm +include $(rules)/Rules.make +include $(rules)/Rules.forth diff --git a/qemu/roms/openbios/arch/ppc/Makefile.asm b/qemu/roms/openbios/arch/ppc/Makefile.asm new file mode 100644 index 000000000..32d43376d --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/Makefile.asm @@ -0,0 +1,32 @@ +# -*- makefile -*- +# +# Makefile.asm - assembly support +# +# Copyright (C) 2004 Samuel Rydh (samuel@ibrium.se) +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# version 2 + + +################################################# +# Rules for asm targets +################################################# + +ASMFLAGS = -D__ASSEMBLY__ -I$(top_srcdir) $(ALTIVEC) +FILTERBIN = $(top_srcdir)/scripts/asfilter +ASFILTER = $(shell if test -x $(FILTERBIN) ; then echo $(FILTERBIN) \ + ; else echo "tr ';' '\n'" ; fi) +INVOKE_M4 = | $(M4) -s $(M4_NO_GNU) | $(ASFILTER) + +$(ODIR)/%.o: %.S + @printf " Compiling %-20s: " $(notdir $@) + assembly= + @install -d $(dir $@) + @$(RM) $@ $@.s + @$(CPP) $(ASMFLAGS) $(IDIRS) $< > /dev/null + $(CPP) $(ASMFLAGS) $(IDIRS) $(DEPFLAGS) $< $(INVOKE_M4) > $@.s + $(AS) $@.s $(AS_FLAGS) -o $@ + @$(DEPEXTRA) + @$(RM) $@.s + @echo "ok" diff --git a/qemu/roms/openbios/arch/ppc/briq/briq.c b/qemu/roms/openbios/arch/ppc/briq/briq.c new file mode 100644 index 000000000..a8541c370 --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/briq/briq.c @@ -0,0 +1,194 @@ +/* + * Creation Date: <2004/08/28 18:38:22 greg> + * Time-stamp: <2004/08/28 18:38:22 greg> + * + * <briq.c> + * + * Copyright (C) 2004, Greg Watson + * + * derived from mol.c + * + * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#include "config.h" +#include "kernel/kernel.h" +#include "arch/common/nvram.h" +#include "libc/vsprintf.h" +#include "libc/string.h" +#include "briq/briq.h" +#include <stdarg.h> + +#define UART_BASE 0x3f8 + +unsigned long virt_offset = 0; + +void +exit( int status ) +{ + for (;;); +} + +void +fatal_error( const char *err ) +{ + printk("Fatal error: %s\n", err ); + exit(0); +} + +void +panic( const char *err ) +{ + printk("Panic: %s\n", err ); + exit(0); + + /* won't come here... this keeps the gcc happy */ + for( ;; ) + ; +} + + +/************************************************************************/ +/* print using OSI interface */ +/************************************************************************/ + +static int do_indent; + +int +printk( const char *fmt, ... ) +{ + char *p, buf[1024]; + va_list args; + int i; + + va_start(args, fmt); + i = vnsprintf(buf, sizeof(buf), fmt, args); + va_end(args); + + for( p=buf; *p; p++ ) { + if( *p == '\n' ) + do_indent = 0; + if( do_indent++ == 1 ) { + putchar( '>' ); + putchar( '>' ); + putchar( ' ' ); + } + putchar( *p ); + } + return i; +} + + +/************************************************************************/ +/* TTY iface */ +/************************************************************************/ + +static int ttychar = -1; + +static int +tty_avail( void ) +{ + return 1; +} + +static int +tty_putchar( int c ) +{ + if( tty_avail() ) { + while (!(inb(UART_BASE + 0x05) & 0x20)) + ; + outb(c, UART_BASE); + while (!(inb(UART_BASE + 0x05) & 0x40)) + ; + } + return c; +} + +int +availchar( void ) +{ + if( !tty_avail() ) + return 0; + + if( ttychar < 0 ) + ttychar = inb(UART_BASE); + return (ttychar >= 0); +} + +int +getchar( void ) +{ + int ch; + + if( !tty_avail() ) + return 0; + + if( ttychar < 0 ) + return inb(UART_BASE); + ch = ttychar; + ttychar = -1; + return ch; +} + +int +putchar( int c ) +{ + if (c == '\n') + tty_putchar('\r'); + return tty_putchar(c); +} + + +/************************************************************************/ +/* briQ specific stuff */ +/************************************************************************/ + +static char nvram[2048]; + +void +dump_nvram(void) +{ + static char hexdigit[] = "0123456789abcdef"; + int i; + for (i = 0; i < 16*4; i++) + { + printk ("%c", hexdigit[nvram[i] >> 4]); + printk ("%c", hexdigit[nvram[i] % 16]); + if (!((i + 1) % 16)) + { + printk ("\n"); + } + else + { + printk (" "); + } + } +} + + +int +arch_nvram_size( void ) +{ + return sizeof(nvram); +} + +void +arch_nvram_put( char *buf ) +{ + memcpy(nvram, buf, sizeof(nvram)); + printk("new nvram:\n"); + dump_nvram(); +} + +void +arch_nvram_get( char *buf ) +{ + memcpy(buf, nvram, sizeof(nvram)); + printk("current nvram:\n"); + dump_nvram(); +} diff --git a/qemu/roms/openbios/arch/ppc/briq/briq.fs b/qemu/roms/openbios/arch/ppc/briq/briq.fs new file mode 100644 index 000000000..78d77970c --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/briq/briq.fs @@ -0,0 +1,115 @@ +\ briq specific initialization code +\ +\ Copyright (C) 2004 Greg Watson +\ +\ 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 +\ + + +\ ------------------------------------------------------------------------- +\ initialization +\ ------------------------------------------------------------------------- + +: make-openable ( path ) + find-dev if + begin ?dup while + \ install trivial open and close methods + dup active-package! is-open + parent + repeat + then +; + +: preopen ( chosen-str node-path ) + 2dup make-openable + + " /chosen" find-device + open-dev ?dup if + encode-int 2swap property + else + 2drop + then +; + +\ preopen device nodes (and store the ihandles under /chosen) +:noname + " rtc" " /pci/isa/rtc" preopen + " memory" " /memory" preopen + " mmu" " /cpu@0" preopen + " stdout" " /packages/terminal-emulator" preopen + " stdin" " keyboard" preopen + +; SYSTEM-initializer + + +\ ------------------------------------------------------------------------- +\ device tree fixing +\ ------------------------------------------------------------------------- + +\ add decode-address methods +: (make-decodable) ( phandle -- ) + + dup " #address-cells" rot get-package-property 0= if + decode-int nip nip + over " decode-unit" rot find-method if 2drop else + ( save phandle ncells ) + + over active-package! + case + 1 of ['] parse-hex " decode-unit" is-xt-func endof + 3 of + " bus-range" active-package get-package-property 0= if + decode-int nip nip + ['] encode-unit-pci " encode-unit" is-xt-func + " decode-unit" is-func-begin + ['] (lit) , , + ['] decode-unit-pci-bus , + is-func-end + then + endof + endcase + then + then + drop +; + +: init-briq-tree ( -- ) + active-package + + iterate-tree-begin + begin ?dup while + + dup (make-decodable) + + iterate-tree + repeat + + active-package! +; + +\ use the tty interface if available +: activate-tty-interface + " /packages/terminal-emulator" find-dev if drop + " /packages/terminal-emulator" " input-device" $setenv + " /packages/terminal-emulator" " output-device" $setenv + then +; + +:noname + " keyboard" input +; CONSOLE-IN-initializer + + +\ ------------------------------------------------------------------------- +\ pre-booting +\ ------------------------------------------------------------------------- + +: update-chosen + " /chosen" find-device + stdin @ encode-int " stdin" property + stdout @ encode-int " stdout" property + " /pci/isa/interrupt-controller" find-dev if encode-int " interrupt-controller" property then + device-end +; diff --git a/qemu/roms/openbios/arch/ppc/briq/briq.h b/qemu/roms/openbios/arch/ppc/briq/briq.h new file mode 100644 index 000000000..33a2cafa8 --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/briq/briq.h @@ -0,0 +1,24 @@ +/* + * Creation Date: <2004/08/28 17:50:12 stepan> + * Time-stamp: <2004/08/28 17:50:12 stepan> + * + * <briq.h> + * + * Copyright (C) 2004 Stefan Reinauer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#ifndef _H_BRIQ +#define _H_BRIQ + +/* vfd.c */ +extern int vfd_draw_str( const char *str ); +extern void vfd_close( void ); + +#include "kernel.h" + +#endif /* _H_BRIQ */ diff --git a/qemu/roms/openbios/arch/ppc/briq/init.c b/qemu/roms/openbios/arch/ppc/briq/init.c new file mode 100644 index 000000000..b32e97aa2 --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/briq/init.c @@ -0,0 +1,130 @@ +/* + * Creation Date: <2004/08/28 18:38:22 greg> + * Time-stamp: <2004/08/28 18:38:22 greg> + * + * <init.c> + * + * Initialization for briq + * + * Copyright (C) 2004 Greg Watson + * + * based on mol/init.c: + * + * Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 Samuel & David Rydh + * (samuel@ibrium.se, dary@lindesign.se) + * + * 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 + * + */ + +#include "config.h" +#include "libopenbios/openbios.h" +#include "libopenbios/bindings.h" +#include "arch/common/nvram.h" +#include "briq/briq.h" +#include "libopenbios/ofmem.h" +#include "openbios-version.h" + +extern void unexpected_excep( int vector ); +extern void setup_timers( void ); + +#if 0 +int +get_bool_res( const char *res ) +{ + char buf[8], *p; + + p = BootHGetStrRes( res, buf, sizeof(buf) ); + if( !p ) + return -1; + if( !strcasecmp(p,"true") || !strcasecmp(p,"yes") || !strcasecmp(p,"1") ) + return 1; + return 0; +} +#endif + +void +unexpected_excep( int vector ) +{ + printk("briQ panic: Unexpected exception %x\n", vector ); + for( ;; ) + ; +} + +unsigned long isa_io_base; + +void +entry( void ) +{ + isa_io_base = 0x80000000; + + printk("\n"); + printk("=============================================================\n"); + printk(PROGRAM_NAME " " OPENBIOS_VERSION_STR " [%s]\n", + OPENBIOS_BUILD_DATE); + + ofmem_init(); + initialize_forth(); + /* won't return */ + + printk("of_startup returned!\n"); + for( ;; ) + ; +} + +static void +setenv( char *env, char *value ) +{ + push_str( value ); + push_str( env ); + fword("$setenv"); +} + +void +arch_of_init( void ) +{ +#if CONFIG_RTAS + phandle_t ph; +#endif + int autoboot; + + devtree_init(); + node_methods_init(); + modules_init(); + setup_timers(); +#ifdef CONFIG_DRIVER_PCI + ob_pci_init(); +#endif + +#if CONFIG_RTAS + if( !(ph=find_dev("/rtas")) ) + printk("Warning: No /rtas node\n"); + else { + unsigned long size = 0x1000; + while( size < (unsigned long)of_rtas_end - (unsigned long)of_rtas_start ) + size *= 2; + set_property( ph, "rtas-size", (char*)&size, sizeof(size) ); + } +#endif + +#if 0 + /* tweak boot settings */ + autoboot = !!get_bool_res("autoboot"); +#endif + autoboot = 0; + if( !autoboot ) + printk("Autobooting disabled - dropping into OpenFirmware\n"); + setenv("auto-boot?", autoboot ? "true" : "false" ); + setenv("boot-command", "briqboot"); + +#if 0 + if( get_bool_res("tty-interface") == 1 ) +#endif + fword("activate-tty-interface"); + + /* hack */ + device_end(); + bind_func("briqboot", boot ); +} diff --git a/qemu/roms/openbios/arch/ppc/briq/kernel.c b/qemu/roms/openbios/arch/ppc/briq/kernel.c new file mode 100644 index 000000000..e85134d43 --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/briq/kernel.c @@ -0,0 +1,16 @@ +/* + * Creation Date: <2004/08/28 18:03:25 stepan> + * Time-stamp: <2004/08/28 18:03:25 stepan> + * + * <briq/kernel.c> + * + * Copyright (C) 2004 Stefan Reinauer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#include "briq-dict.h" +#include "../kernel.c" diff --git a/qemu/roms/openbios/arch/ppc/briq/main.c b/qemu/roms/openbios/arch/ppc/briq/main.c new file mode 100644 index 000000000..fbb2a26de --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/briq/main.c @@ -0,0 +1,145 @@ +/* + * Creation Date: <2004/08/28 18:38:22 greg> + * Time-stamp: <2004/08/28 18:38:22 greg> + * + * <main.c> + * + * Copyright (C) 2004 Greg Watson + * + * Based on MOL specific code which is + * Copyright (C) 2002, 2003, 2004 Samuel Rydh (samuel@ibrium.se) + * + * 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 + * + */ + + +#include "config.h" +#include "libopenbios/bindings.h" +#include "libopenbios/elfload.h" +#include "arch/common/nvram.h" +#include "libc/diskio.h" +#include "libc/vsprintf.h" +#include "briq/briq.h" +#include "libopenbios/ofmem.h" + +static void +transfer_control_to_elf( unsigned long entry ) +{ + extern void call_elf( unsigned long entry ); + printk("Starting ELF image at 0x%08lX\n", entry); + call_elf( 0x400000 ); + //call_elf( entry ); + + fatal_error("call_elf returned unexpectedly\n"); +} + +static int +load_elf_rom( unsigned long *entry, int fd ) +{ + int i, lszz_offs, elf_offs; + char buf[128], *addr; + Elf_ehdr ehdr; + Elf_phdr *phdr; + size_t s; + + printk("Loading '%s'\n", get_file_path(fd)); + + /* the ELF-image (usually) starts at offset 0x4000 */ + if( (elf_offs=find_elf(fd)) < 0 ) { + printk("----> %s is not an ELF image\n", buf ); + exit(1); + } + if( !(phdr=elf_readhdrs(fd, elf_offs, &ehdr)) ) + fatal_error("elf_readhdrs failed\n"); + + *entry = ehdr.e_entry; + + /* load segments. Compressed ROM-image assumed to be located immediately + * after the last segment */ + lszz_offs = elf_offs; + for( i=0; i<ehdr.e_phnum; i++ ) { + /* p_memsz, p_flags */ + s = MIN( phdr[i].p_filesz, phdr[i].p_memsz ); + seek_io( fd, elf_offs + phdr[i].p_offset ); + + /* printk("filesz: %08lX memsz: %08lX p_offset: %08lX p_vaddr %08lX\n", + phdr[i].p_filesz, phdr[i].p_memsz, phdr[i].p_offset, + phdr[i].p_vaddr ); */ + + if( phdr[i].p_vaddr != phdr[i].p_paddr ) + printk("WARNING: ELF segment virtual addr != physical addr\n"); + lszz_offs = MAX( lszz_offs, elf_offs + phdr[i].p_offset + phdr[i].p_filesz ); + if( !s ) + continue; + if( ofmem_claim( phdr[i].p_vaddr, phdr[i].p_memsz, 0 ) == -1 ) + fatal_error("Claim failed!\n"); + + addr = (char*)phdr[i].p_vaddr; + if( read_io(fd, addr, s) != s ) + fatal_error("read failed\n"); + +#if 0 + /* patch CODE segment */ + if( *entry >= phdr[i].p_vaddr && *entry < phdr[i].p_vaddr + s ) { + patch_newworld_rom( (char*)phdr[i].p_vaddr, s ); + newworld_timer_hack( (char*)phdr[i].p_vaddr, s ); + } +#endif + flush_icache_range( addr, addr+s ); + + /*printk("ELF ROM-section loaded at %08lX (size %08lX)\n", + (unsigned long)phdr[i].p_vaddr, (unsigned long)phdr[i].p_memsz );*/ + } + free( phdr ); + return lszz_offs; +} + + +static void +encode_bootpath( const char *spec, const char *args ) +{ + phandle_t chosen_ph = find_dev("/chosen"); + set_property( chosen_ph, "bootpath", spec, strlen(spec)+1 ); + set_property( chosen_ph, "bootargs", args, strlen(args)+1 ); +} + +/************************************************************************/ +/* briq booting */ +/************************************************************************/ + +static void +briq_startup( void ) +{ + const char *paths[] = { "hd:0,\\zImage.chrp", NULL }; + const char *args[] = { "root=/dev/hda2 console=ttyS0,115200", NULL }; + unsigned long entry; + int i, fd; + + for( i=0; paths[i]; i++ ) { + if( (fd=open_io(paths[i])) == -1 ) + continue; + (void) load_elf_rom( &entry, fd ); + close_io( fd ); + encode_bootpath( paths[i], args[i] ); + + update_nvram(); + transfer_control_to_elf( entry ); + /* won't come here */ + } + printk("*** Boot failure! No secondary bootloader specified ***\n"); +} + + +/************************************************************************/ +/* entry */ +/************************************************************************/ + +void +boot( void ) +{ + fword("update-chosen"); + briq_startup(); +} diff --git a/qemu/roms/openbios/arch/ppc/briq/methods.c b/qemu/roms/openbios/arch/ppc/briq/methods.c new file mode 100644 index 000000000..649e9bafa --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/briq/methods.c @@ -0,0 +1,333 @@ +/* + * Creation Date: <2004/08/28 18:38:22 greg> + * Time-stamp: <2004/08/28 18:38:22 greg> + * + * <methods.c> + * + * Misc device node methods + * + * Copyright (C) 2004 Greg Watson + * + * Based on MOL specific code which is + * + * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#include "config.h" +#include "libopenbios/bindings.h" +#include "libc/string.h" +#include "briq/briq.h" +#include "libopenbios/ofmem.h" + +/************************************************************************/ +/* RTAS (run-time abstraction services) */ +/************************************************************************/ + +#ifdef CONFIG_RTAS +DECLARE_NODE( rtas, INSTALL_OPEN, 0, "+/rtas" ); + +/* ( physbase -- rtas_callback ) */ +static void +rtas_instantiate( void ) +{ + int physbase = POP(); + int s=0x1000, size = (int)of_rtas_end - (int)of_rtas_start; + unsigned long virt; + + while( s < size ) + s += 0x1000; + virt = ofmem_claim_virt( 0, s, 0x1000 ); + ofmem_map( physbase, virt, s, -1 ); + memcpy( (char*)virt, of_rtas_start, size ); + + printk("RTAS instantiated at %08x\n", physbase ); + flush_icache_range( (char*)virt, (char*)virt + size ); + + PUSH( physbase ); +} + +NODE_METHODS( rtas ) = { + { "instantiate", rtas_instantiate }, + { "instantiate-rtas", rtas_instantiate }, +}; +#endif + + +/************************************************************************/ +/* stdout */ +/************************************************************************/ + +DECLARE_NODE( vfd_stdout, INSTALL_OPEN, 0, "Tdisplay" ); + +/* ( addr len -- actual ) */ +static void +stdout_write( void ) +{ + int len = POP(); + char *addr = (char*)POP(); + char *s = malloc( len + 1 ); + + strncpy_nopad( s, addr, len ); + s[len]=0; + + printk( "%s", s ); + //vfd_draw_str( s ); + free( s ); + + PUSH( len ); +} + +NODE_METHODS( vfd_stdout ) = { + { "write", stdout_write }, +}; + + +/************************************************************************/ +/* tty */ +/************************************************************************/ + +DECLARE_NODE( tty, INSTALL_OPEN, 0, "/packages/terminal-emulator" ); + +/* ( addr len -- actual ) */ +static void +tty_read( void ) +{ + int ch, len = POP(); + char *p = (char*)POP(); + int ret=0; + + if( len > 0 ) { + ret = 1; + ch = getchar(); + if( ch >= 0 ) { + *p = ch; + } else { + ret = 0; + } + } + PUSH( ret ); +} + +/* ( addr len -- actual ) */ +static void +tty_write( void ) +{ + int i, len = POP(); + char *p = (char*)POP(); + for( i=0; i<len; i++ ) + putchar( *p++ ); + RET( len ); +} + +NODE_METHODS( tty ) = { + { "read", tty_read }, + { "write", tty_write }, +}; + +/************************************************************************/ +/* client interface 'quiesce' */ +/************************************************************************/ + +DECLARE_NODE( ciface, 0, 0, "/packages/client-iface" ); + +/* ( -- ) */ +static void +ciface_quiesce( unsigned long args[], unsigned long ret[] ) +{ +#if 0 + unsigned long msr; + /* This seems to be the correct thing to do - but I'm not sure */ + asm volatile("mfmsr %0" : "=r" (msr) : ); + msr &= ~(MSR_IR | MSR_DR); + asm volatile("mtmsr %0" :: "r" (msr) ); +#endif + printk("=============================================================\n\n"); +} + +/* ( -- ms ) */ +static void +ciface_milliseconds( unsigned long args[], unsigned long ret[] ) +{ + extern unsigned long get_timer_freq(); + static unsigned long mticks=0, usecs=0; + unsigned long t; + + asm volatile("mftb %0" : "=r" (t) : ); + if( mticks ) + usecs += get_timer_freq() / 1000000 * ( t-mticks ); + mticks = t; + + PUSH( usecs/1000 ); +} + + +NODE_METHODS( ciface ) = { + { "quiesce", ciface_quiesce }, + { "milliseconds", ciface_milliseconds }, +}; + + +/************************************************************************/ +/* MMU/memory methods */ +/************************************************************************/ + +DECLARE_NODE( memory, INSTALL_OPEN, 0, "/memory" ); +DECLARE_NODE( mmu, INSTALL_OPEN, 0, "/cpu@0" ); +DECLARE_NODE( mmu_ciface, 0, 0, "/packages/client-iface" ); + + +/* ( phys size align --- base ) */ +static void +mem_claim( void ) +{ + int align = POP(); + int size = POP(); + int phys = POP(); + int ret = ofmem_claim_phys( phys, size, align ); + + if( ret == -1 ) { + printk("MEM: claim failure\n"); + throw( -13 ); + return; + } + PUSH( ret ); +} + +/* ( phys size --- ) */ +static void +mem_release( void ) +{ + POP(); POP(); +} + +/* ( phys size align --- base ) */ +static void +mmu_claim( void ) +{ + int align = POP(); + int size = POP(); + int phys = POP(); + int ret = ofmem_claim_virt( phys, size, align ); + + if( ret == -1 ) { + printk("MMU: CLAIM failure\n"); + throw( -13 ); + return; + } + PUSH( ret ); +} + +/* ( phys size --- ) */ +static void +mmu_release( void ) +{ + POP(); POP(); +} + +/* ( phys virt size mode -- [ret???] ) */ +static void +mmu_map( void ) +{ + int mode = POP(); + int size = POP(); + int virt = POP(); + int phys = POP(); + int ret; + + /* printk("mmu_map: %x %x %x %x\n", phys, virt, size, mode ); */ + ret = ofmem_map( phys, virt, size, mode ); + + if( ret ) { + printk("MMU: map failure\n"); + throw( -13 ); + return; + } +} + +/* ( virt size -- ) */ +static void +mmu_unmap( void ) +{ + POP(); POP(); +} + +/* ( virt -- false | phys mode true ) */ +static void +mmu_translate( void ) +{ + ucell mode; + ucell virt = POP(); + ucell phys = ofmem_translate( virt, &mode ); + + if( phys == -1 ) { + PUSH( 0 ); + } else { + PUSH( phys ); + PUSH( mode ); + PUSH( -1 ); + } +} + +/* ( virt size align -- baseaddr|-1 ) */ +static void +ciface_claim( void ) +{ + int align = POP(); + int size = POP(); + int virt = POP(); + int ret = ofmem_claim( virt, size, align ); + + /* printk("ciface_claim: %08x %08x %x\n", virt, size, align ); */ + PUSH( ret ); +} + +/* ( virt size -- ) */ +static void +ciface_release( void ) +{ + POP(); + POP(); +} + + +NODE_METHODS( memory ) = { + { "claim", mem_claim }, + { "release", mem_release }, +}; + +NODE_METHODS( mmu ) = { + { "claim", mmu_claim }, + { "release", mmu_release }, + { "map", mmu_map }, + { "unmap", mmu_unmap }, + { "translate", mmu_translate }, +}; + +NODE_METHODS( mmu_ciface ) = { + { "cif-claim", ciface_claim }, + { "cif-release", ciface_release }, +}; + + +/************************************************************************/ +/* init */ +/************************************************************************/ + +void +node_methods_init( void ) +{ +#ifdef CONFIG_RTAS + REGISTER_NODE( rtas ); +#endif + REGISTER_NODE( vfd_stdout ); + REGISTER_NODE( ciface ); + REGISTER_NODE( memory ); + REGISTER_NODE( mmu ); + REGISTER_NODE( mmu_ciface ); + REGISTER_NODE( tty ); +} diff --git a/qemu/roms/openbios/arch/ppc/briq/tree.c b/qemu/roms/openbios/arch/ppc/briq/tree.c new file mode 100644 index 000000000..177183889 --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/briq/tree.c @@ -0,0 +1,23 @@ +/* + * Creation Date: <2004/08/28 18:38:22 greg> + * Time-stamp: <2004/08/28 18:38:22 greg> + * + * <tree.c> + * + * device tree setup + * + * Copyright (C) 2004 Greg Watson + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#include "config.h" +#include "libopenbios/bindings.h" + +void devtree_init( void ) +{ + fword("init-briq-tree"); +} diff --git a/qemu/roms/openbios/arch/ppc/briq/tree.fs b/qemu/roms/openbios/arch/ppc/briq/tree.fs new file mode 100644 index 000000000..ae503266c --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/briq/tree.fs @@ -0,0 +1,305 @@ +\ briq specific initialization code +\ +\ Copyright (C) 2004 Greg Watson +\ +\ 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 +\ + +\ ------------------------------------------------------------- +\ device-tree +\ ------------------------------------------------------------- + +" /" find-device + +" chrp" device-type +" TotalImpact,BRIQ-1" model +h# 80000000 encode-int " isa-io-base" property +1 encode-int " #interrupt-cells" property +1 encode-int " #size-cells" property + +new-device + " memory" device-name + " memory" device-type + 0 encode-int h# 1E00000 encode-int encode+ + h# 2000000 encode-int encode+ h# 40000000 encode-int encode+ + " available" property + 0 h# 40000000 reg + external + : open true ; + : close ; +finish-device + +new-device + " cpu" device-name + " cpu" device-type + " " encode-string " translations" property + 0 encode-phys h# 8000000 encode-int encode+ " available" property + d# 32 encode-int " d-cache-block-size" property + 8 encode-int " d-cache-sets" property + d# 32768 encode-int " d-cache-size" property + d# 32 encode-int " i-cache-block-size" property + 8 encode-int " i-cache-sets" property + d# 32768 encode-int " i-cache-size" property + " " encode-string " cache-unified" property + 2 encode-int " i-tlb-sets" property + d# 128 encode-int " i-tlb-size" property + 2 encode-int " d-tlb-sets" property + d# 128 encode-int " d-tlb-size" property + " " encode-string " tlb-split" property + 2 encode-int " tlb-sets" property + d# 256 encode-int " tlb-size" property + " " encode-string " performance-monitor" property + " " encode-string " graphics" property + 4 encode-int " reservation-granule-size" property + d# 25000000 encode-int " timebase-frequency" property + d# 300000000 encode-int " clock-frequency" property + d# 66000000 encode-int " bus-frequency" property + h# 88201 encode-int " cpu-version" property + 0 encode-int " reg" property +finish-device + +" /pci" find-device + h# 01000000 encode-int 0 encode-int encode+ 0 encode-int encode+ + h# 80000000 encode-int encode+ 0 encode-int encode+ + h# 01000000 encode-int encode+ + h# 02000000 encode-int encode+ 0 encode-int encode+ 0 encode-int encode+ + h# C0000000 encode-int encode+ 0 encode-int encode+ + h# 08000000 encode-int encode+ + " ranges" property + " IBM,CPC710" model + h# FF5F7700 encode-int " 8259-interrupt-acknowledge" property + h# 0000F800 encode-int 0 encode-int encode+ 0 encode-int encode+ + 7 encode-int encode+ + " interrupt-map-mask" property + 1 encode-int " #interrupt-cells" property + h# 80000000 encode-int " system-dma-base" property + d# 33333333 encode-int " clock-frequency" property + " " encode-string " primary-bridge" property + 0 encode-int " pci-bridge-number" property + h# FF500000 encode-int h# 100000 encode-int encode+ " reg" property + 0 encode-int 0 encode-int encode+ " bus-range" property + +new-device + " isa" device-name + " isa" device-type + 2 encode-int " #address-cells" property + 1 encode-int " #size-cells" property + + external + : open true ; + : close ; + +finish-device + +: ?devalias ( alias-str alias-len device-str device-len -- + \ alias-str alias-len false | true ) + active-package >r + " /aliases" find-device + \ 2dup ." Checking " type + 2dup find-dev if \ check if device exists + drop + 2over find-dev if \ do we already have an alias? + \ ." alias exists" cr + drop 2drop false + else + \ ." device exists" cr + encode-string + 2swap property + true + then + else + \ ." device doesn't exist" cr + 2drop false + then + r> active-package! + ; + +:noname + " hd" + " /pci/pci-ata/ata-1/disk@0" ?devalias not if + " /pci/pci-ata/ata-1/disk@1" ?devalias not if + " /pci/pci-ata/ata-2/disk@0" ?devalias not if + " /pci/pci-ata/ata-2/disk@1" ?devalias not if + 2drop ." No disk found." cr + then + then + then + then + + " cdrom" + " /pci/pci-ata/ata-1/cdrom@0" ?devalias not if + " /pci/pci-ata/ata-1/cdrom@1" ?devalias not if + " /pci/pci-ata/ata-2/cdrom@0" ?devalias not if + " /pci/pci-ata/ata-2/cdrom@1" ?devalias not if + 2drop ." No cdrom found" cr + then + then + then + then +; SYSTEM-initializer + +new-device + " ide" device-name + " ide" device-type + " WINBOND,82C553" model + h# 28 encode-int " max-latency" property + h# 2 encode-int " min-grant" property + h# 1 encode-int " devsel-speed" property + h# 0 encode-int " subsystem-vendor-id" property + h# 0 encode-int " subsystem-id" property + h# 1018A encode-int " class-code" property + h# 5 encode-int " revision-id" property + h# 105 encode-int " device-id" property + h# 10AD encode-int " vendor-id" property + h# 1003110 encode-int 0 encode-int encode+ h# 10020 encode-int encode+ + h# 10 encode-int encode+ 0 encode-int encode+ + h# 1003114 encode-int 0 encode-int encode+ h# 10030 encode-int encode+ + h# 4 encode-int encode+ 0 encode-int encode+ + h# 1003118 encode-int 0 encode-int encode+ h# 10040 encode-int encode+ + h# 10 encode-int encode+ 0 encode-int encode+ + h# 100311C encode-int 0 encode-int encode+ h# 10034 encode-int encode+ + h# 4 encode-int encode+ 0 encode-int encode+ + h# 1003120 encode-int 0 encode-int encode+ h# 10050 encode-int encode+ + h# 10 encode-int encode+ 0 encode-int encode+ + h# 1003124 encode-int 0 encode-int encode+ h# 10060 encode-int encode+ + h# 10 encode-int encode+ 0 encode-int encode+ + " assigned-addresses" property + h# 3100 encode-int 0 encode-int encode+ 0 encode-int encode+ + 0 encode-int encode+ 0 encode-int encode+ + h# 1003110 encode-int 0 encode-int encode+ h# 0 encode-int encode+ + h# 10 encode-int encode+ 0 encode-int encode+ + h# 1003114 encode-int 0 encode-int encode+ h# 0 encode-int encode+ + h# 4 encode-int encode+ 0 encode-int encode+ + h# 1003118 encode-int 0 encode-int encode+ h# 0 encode-int encode+ + h# 10 encode-int encode+ 0 encode-int encode+ + h# 100311C encode-int 0 encode-int encode+ h# 0 encode-int encode+ + h# 4 encode-int encode+ 0 encode-int encode+ + h# 1003120 encode-int 0 encode-int encode+ h# 0 encode-int encode+ + h# 10 encode-int encode+ 0 encode-int encode+ + h# 1003124 encode-int 0 encode-int encode+ h# 0 encode-int encode+ + h# 10 encode-int encode+ 0 encode-int encode+ + " reg" property +finish-device + +new-device + " ethernet" device-name + " network" device-type + " AMD,79C973" model + h# 3800 encode-int 0 encode-int encode+ 0 encode-int encode+ + 0 encode-int encode+ 0 encode-int encode+ + " reg" property +finish-device + +" /pci/isa" find-device + 0 0 " assigned-addresses" property + 0 0 " ranges" property + 0 encode-int " slot-names" property + d# 8333333 encode-int " clock-frequency" property + 0 encode-int " eisa-slots" property + 2 encode-int " #interrupt-cells" property + " W83C553F" encode-string " compatible" property + " WINBOND,82C553" model + 0 encode-int " max-latency" property + 0 encode-int " min-grant" property + 1 encode-int " devsel-speed" property + 0 encode-int " subsystem-vendor-id" property + 0 encode-int " subsystem-id" property + h# 60100 encode-int " class-code" property + h# 10 encode-int " revision-id" property + h# 565 encode-int " device-id" property + h# 10AD encode-int " vendor-id" property + h# 3000 encode-int 0 encode-int encode+ 0 encode-int encode+ + 0 encode-int encode+ 0 encode-int encode+ " reg" property + +new-device + " rtc" device-name + " rtc" device-type + " DS17285S" model + " MC146818" encode-string + " DS17285S" encode-string encode+ + " pnpPNP,b00" encode-string encode+ " compatible" property + 8 encode-int 0 encode-int encode+ " interrupts" property + h# 70 encode-int 1 encode-int encode+ + 2 encode-int encode+ " reg" property +finish-device + +new-device + " interrupt-controller" device-name + " interrupt-controller" device-type + " 8259" model + " " encode-string " interrupt-controller" property + 2 encode-int " #interrupt-cells" property + 1 encode-int + 2 encode-int encode+ + 3 encode-int encode+ + 6 encode-int encode+ + " reserved-interrupts" property + " 8259" encode-string + " chrp,iic" encode-string encode+ + " compatible" property + h# 20 encode-int 1 encode-int encode+ + 2 encode-int encode+ " reg" property +finish-device + +new-device + " serial" device-name + " serial" device-type + " no" encode-string " ctsrts" property + " no" encode-string " xon" property + " no" encode-string " parity" property + d# 115200 encode-int " bps" property + 1 encode-int " stop-bits" property + 8 encode-int " data-bits" property + h# 70800 encode-int " divisor" property + h# 708000 encode-int " clock-frequency" property + 4 encode-int 0 encode-int encode+ " interrupts" property + h# 3F8 encode-int 1 encode-int encode+ + 8 encode-int encode+ " reg" property +finish-device + +" /pci" find-device + " /pci/isa/interrupt-controller" find-dev if + encode-int " interrupt-parent" property + then + h# 3800 encode-int 0 encode-int encode+ + 0 encode-int encode+ 1 encode-int encode+ + " /pci/isa/interrupt-controller" find-dev if + encode-int encode+ + then + h# 0C encode-int encode+ 1 encode-int encode+ + " interrupt-map" property + +" /pci/isa" find-device + " /pci/isa/interrupt-controller" find-dev if + encode-int " interrupt-parent" property + then + +\ ------------------------------------------------------------- +\ /packages +\ ------------------------------------------------------------- + +" /packages" find-device + + " packages" device-name + external + \ allow packages to be opened with open-dev + : open true ; + : close ; + +\ /packages/terminal-emulator +new-device + " terminal-emulator" device-name + external + : open true ; + : close ; + \ : write ( addr len -- actual ) + \ dup -rot type + \ ; +finish-device + +\ ------------------------------------------------------------- +\ The END +\ ------------------------------------------------------------- +device-end diff --git a/qemu/roms/openbios/arch/ppc/briq/vfd.c b/qemu/roms/openbios/arch/ppc/briq/vfd.c new file mode 100644 index 000000000..ffc87a079 --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/briq/vfd.c @@ -0,0 +1,42 @@ +/* + * Creation Date: <2004/08/28 17:29:43 greg> + * Time-stamp: <2004/08/28 17:29:43 greg> + * + * <vfd.c> + * + * Simple text console + * + * Copyright (C) 2004 Greg Watson + * + * 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 + * + */ + +#include "config.h" +#include "libopenbios/bindings.h" +#include "briq/briq.h" + +static int vfd_is_open; + +static int +vfd_init( void ) +{ + vfd_is_open = 1; + return 0; +} + +void +vfd_close( void ) +{ +} + +int +vfd_draw_str( const char *str ) +{ + if (!vfd_is_open) + vfd_init(); + + return 0; +} diff --git a/qemu/roms/openbios/arch/ppc/build.xml b/qemu/roms/openbios/arch/ppc/build.xml new file mode 100644 index 000000000..29f6601f9 --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/build.xml @@ -0,0 +1,211 @@ +<?xml version="1.0"?> +<build condition="PPC"> + + <dictionary name="openbios-briq" init="openbios" target="forth" condition="BRIQ"> + <object source="ppc.fs"/> + <object source="briq/tree.fs"/> + <object source="briq/briq.fs"/> + <object source="QEMU,VGA.bin" target="fcode" condition="DRIVER_VGA"/> + </dictionary> + + <dictionary name="openbios-pearpc" init="openbios" target="forth" condition="PEARPC"> + <object source="ppc.fs"/> + <object source="pearpc/tree.fs"/> + <object source="pearpc/pearpc.fs"/> + <object source="QEMU,VGA.bin" target="fcode" condition="DRIVER_VGA"/> + </dictionary> + + <dictionary name="openbios-qemu" init="openbios" target="forth" condition="QEMU"> + <object source="ppc.fs"/> + <object source="qemu/tree.fs"/> + <object source="qemu/qemu.fs"/> + <object source="QEMU,VGA.bin" target="fcode" condition="DRIVER_VGA"/> + </dictionary> + + <dictionary name="openbios-mol" init="openbios" target="forth" condition="MOL"> + <object source="ppc.fs"/> + <object source="mol/tree.fs"/> + <object source="mol/mol.fs"/> + <object source="QEMU,VGA.bin" target="fcode" condition="DRIVER_VGA"/> + </dictionary> + + <!-- HACK ALERT --> + + <executable name="target/include/briq-dict.h" target="target" condition="BRIQ"> + <rule><![CDATA[ + $(call quiet-command,true, " GEN $(TARGET_DIR)$@") + @echo "static const char forth_dictionary[] = {" > $@ + @cat $< | hexdump -ve '1/0 "\t" 8/1 "0x%02x, " 1/0 "\n"' \ + | sed 's/0x ,//g' >> $@ + @echo "};" >> $@]]></rule> + <external-object source="openbios-briq.dict"/> + </executable> + + <executable name="target/arch/ppc/briq/kernel.o" target="target" condition="BRIQ"> + <rule><![CDATA[ $(SRCDIR)/arch/ppc/briq/kernel.c $(ODIR)/target/include/static-dict.h + $(call quiet-command,$(CC) $$EXTRACFLAGS $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/arch/ppc/briq/kernel.c, " CC $(TARGET_DIR)$@")]]></rule> + </executable> + + + <executable name="target/include/pearpc-dict.h" target="target" condition="PEARPC"> + <rule><![CDATA[ + $(call quiet-command,true, " GEN $(TARGET_DIR)$@") + @echo "static const char forth_dictionary[] = {" > $@ + @cat $< | hexdump -ve '1/0 "\t" 8/1 "0x%02x, " 1/0 "\n"' \ + | sed 's/0x ,//g' >> $@ + @echo "};" >> $@]]></rule> + <external-object source="openbios-pearpc.dict"/> + </executable> + + <executable name="target/arch/ppc/pearpc/kernel.o" target="target" condition="PEARPC"> + <rule><![CDATA[ $(SRCDIR)/arch/ppc/pearpc/kernel.c $(ODIR)/target/include/pearpc-dict.h + $(call quiet-command,$(CC) $$EXTRACFLAGS $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/arch/ppc/pearpc/kernel.c, " CC $(TARGET_DIR)$@")]]></rule> + </executable> + + <executable name="target/include/qemu-dict.h" target="target" condition="QEMU"> + <rule><![CDATA[ + $(call quiet-command,$(ODIR)/forthstrap -x -D $@ -d $< </dev/null, " GEN $(TARGET_DIR)$@")]]></rule> + <external-object source="openbios-qemu.dict"/> + </executable> + + <executable name="target/arch/ppc/qemu/kernel.o" target="target" condition="QEMU"> + <rule><![CDATA[ $(SRCDIR)/arch/ppc/qemu/kernel.c $(ODIR)/target/include/qemu-dict.h + $(call quiet-command,$(CC) $$EXTRACFLAGS $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/arch/ppc/qemu/kernel.c, " CC $(TARGET_DIR)$@")]]></rule> + </executable> + + + <executable name="target/include/mol-dict.h" target="target" condition="MOL"> + <rule><![CDATA[ + $(call quiet-command,true, " GEN $(TARGET_DIR)$@") + @echo "static const char forth_dictionary[] = {" > $@ + @cat $< | hexdump -ve '1/0 "\t" 8/1 "0x%02x, " 1/0 "\n"' \ + | sed 's/0x ,//g' >> $@ + @echo "};" >> $@]]></rule> + <external-object source="openbios-mol.dict"/> + </executable> + + <executable name="target/arch/ppc/mol/kernel.o" target="target" condition="MOL"> + <rule><![CDATA[ + $(call quiet-command,$(CC) $$EXTRACFLAGS $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/arch/ppc/mol/kernel.c, " CC $(TARGET_DIR)$@")]]></rule> + </executable> + + <!-- END OF HACK ALERT --> + + <library name="briq" target="target" type="static" condition="BRIQ"> + <object source="misc.S"/> + <object source="ofmem.c"/> + <object source="briq/briq.c" flags="-I$(SRCDIR)/arch/ppc"/> + <object source="briq/init.c" flags="-I$(SRCDIR)/arch/ppc"/> + <external-object source="target/arch/ppc/briq/kernel.o"/> + <object source="briq/main.c" flags="-I$(SRCDIR)/arch/ppc"/> + <object source="briq/methods.c" flags="-I$(SRCDIR)/arch/ppc"/> + <object source="briq/tree.c" flags="-I$(SRCDIR)/arch/ppc"/> + <object source="briq/vfd.c" flags="-I$(SRCDIR)/arch/ppc"/> + </library> + + <library name="pearpc" target="target" type="static" condition="PEARPC"> + <object source="misc.S"/> + <object source="ofmem.c"/> + <object source="pearpc/pearpc.c" flags="-I$(SRCDIR)/arch/ppc"/> + <object source="pearpc/init.c" flags="-I$(SRCDIR)/arch/ppc"/> + <external-object source="target/arch/ppc/pearpc/kernel.o"/> + <object source="pearpc/main.c" flags="-I$(SRCDIR)/arch/ppc"/> + <object source="pearpc/methods.c" flags="-I$(SRCDIR)/arch/ppc"/> + <object source="pearpc/tree.c" flags="-I$(SRCDIR)/arch/ppc"/> + <object source="pearpc/vfd.c" flags="-I$(SRCDIR)/arch/ppc"/> + <!-- taken from mol: generalize --> + <object source="pearpc/console.c" flags="-I$(SRCDIR)/arch/ppc"/> + </library> + + <library name="qemu" target="target" type="static" condition="QEMU"> + <object source="qemu/ofmem.c"/> + <object source="qemu/qemu.c" flags="-I$(SRCDIR)/arch/ppc"/> + <object source="qemu/init.c" flags="-I$(SRCDIR)/arch/ppc"/> + <external-object source="target/arch/ppc/qemu/kernel.o"/> + <object source="qemu/main.c" flags="-I$(SRCDIR)/arch/ppc"/> + <object source="qemu/methods.c" flags="-I$(SRCDIR)/arch/ppc"/> + <object source="qemu/vfd.c" flags="-I$(SRCDIR)/arch/ppc"/> + <object source="qemu/console.c" flags="-I$(SRCDIR)/arch/ppc"/> + </library> + + <library name="mol" target="target" type="static" condition="MOL"> + <object source="misc.S"/> + <object source="ofmem.c"/> + <object source="mol/init.c" flags="-I$(SRCDIR)/arch/ppc"/> + <object source="mol/main.c" flags="-I$(SRCDIR)/arch/ppc"/> + <object source="mol/mol.c" flags="-I$(SRCDIR)/arch/ppc"/> + <object source="mol/console.c" flags="-I$(SRCDIR)/arch/ppc"/> + <object source="mol/osi-blk.c" flags="-I$(SRCDIR)/arch/ppc"/> + <object source="mol/osi-scsi.c" flags="-I$(SRCDIR)/arch/ppc"/> + <object source="mol/pseudodisk.c" flags="-I$(SRCDIR)/arch/ppc"/> + <object source="mol/methods.c" flags="-I$(SRCDIR)/arch/ppc"/> + <object source="mol/prom.c" flags="-I$(SRCDIR)/arch/ppc"/> + <object source="mol/tree.c" flags="-I$(SRCDIR)/arch/ppc"/> + <external-object source="target/arch/ppc/mol/kernel.o"/> + </library> + + <executable name="openbios-briq.elf" target="target" condition="BRIQ"> + <rule> + $(call quiet-command,$(LD) -g -Ttext=0x01e01000 -Bstatic $^ $(shell $(CC) -print-libgcc-file-name) -o $@.nostrip --whole-archive $^," LINK $(TARGET_DIR)$@") + $(call quiet-command,$(NM) $@.nostrip | sort > $(ODIR)/openbios-briq.syms," GEN $(TARGET_DIR)$@.syms") + $(call quiet-command,$(STRIP) $@.nostrip -o $@," STRIP $(TARGET_DIR)$@")</rule> + <object source="start.S"/> + <object source="timebase.S"/> + <external-object source="libbriq.a"/> + <external-object source="libbootstrap.a"/> + <external-object source="libopenbios.a"/> + <external-object source="libpackages.a"/> + <external-object source="libdrivers.a"/> + <external-object source="libfs.a"/> + <external-object source="liblibc.a"/> + </executable> + + <executable name="openbios-pearpc.elf" target="target" condition="PEARPC"> + <rule> + $(call quiet-command,$(LD) -g -Ttext=0x01e01000 -Bstatic $^ $(shell $(CC) -print-libgcc-file-name) -o $@.nostrip --whole-archive $^," LINK $(TARGET_DIR)$@") + $(call quiet-command,$(NM) $@.nostrip | sort > $(ODIR)/openbios-pearpc.syms," GEN $(TARGET_DIR)$@.syms") + $(call quiet-command,$(STRIP) $@.nostrip -o $@," STRIP $(TARGET_DIR)$@")</rule> + <object source="start.S"/> + <object source="timebase.S"/> + <external-object source="libpearpc.a"/> + <external-object source="libbootstrap.a"/> + <external-object source="libopenbios.a"/> + <external-object source="libpackages.a"/> + <external-object source="libdrivers.a"/> + <external-object source="libfs.a"/> + <external-object source="liblibc.a"/> + </executable> + + <executable name="openbios-qemu.elf" target="target" condition="QEMU"> + <rule> + $(call quiet-command,$(LD) --warn-common -N -T $(SRCDIR)/arch/$(ARCH)/qemu/ldscript -o $@.nostrip --whole-archive $^," LINK $(TARGET_DIR)$@") + $(call quiet-command,$(NM) $@.nostrip | sort > $(ODIR)/openbios-qemu.syms," GEN $(TARGET_DIR)$@.syms") + $(call quiet-command,$(STRIP) $@.nostrip -o $@," STRIP $(TARGET_DIR)$@")</rule> + <object source="qemu/start.S"/> + <object source="timebase.S"/> + <external-object source="libqemu.a"/> + <external-object source="libbootstrap.a"/> + <external-object source="libopenbios.a"/> + <external-object source="libpackages.a"/> + <external-object source="libdrivers.a"/> + <external-object source="libfs.a"/> + <external-object source="liblibc.a"/> + <external-object source="libgcc.a"/> + </executable> + + <executable name="openbios-mol.elf" target="target" condition="MOL"> + <rule> + $(call quiet-command,$(LD) -g -Ttext=0x01e01000 -Bstatic $^ $(shell $(CC) -print-libgcc-file-name) -o $@.nostrip --whole-archive $^," LINK $(TARGET_DIR)$@") + $(call quiet-command,$(NM) $@.nostrip | sort > $(ODIR)/openbios-mol.syms," GEN $(TARGET_DIR)$@.syms") + $(call quiet-command,$(STRIP) $@.nostrip -o $@," STRIP $(TARGET_DIR)$@")</rule> + <object source="start.S"/> + <external-object source="libmol.a"/> + <external-object source="libbootstrap.a"/> + <external-object source="libopenbios.a"/> + <external-object source="libpackages.a"/> + <external-object source="libdrivers.a"/> + <external-object source="libfs.a"/> + <external-object source="liblibc.a"/> + </executable> + +</build> diff --git a/qemu/roms/openbios/arch/ppc/defconfig b/qemu/roms/openbios/arch/ppc/defconfig new file mode 100644 index 000000000..adfb181ea --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/defconfig @@ -0,0 +1,48 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_PPC=y +CONFIG_MOL=y +# CONFIG_MPC107 is not set +# CONFIG_NO_ARCH is not set + +# +# Build hosted UNIX Binary +# +CONFIG_HOST_UNIX=y +# CONFIG_PLUGIN_PCI is not set + +# +# Kernel Debugging +# +CONFIG_DEBUG=y +CONFIG_DEBUG_BOOT=y +# CONFIG_DEBUG_DSTACK is not set +# CONFIG_DEBUG_RSTACK is not set +# CONFIG_DEBUG_DICTIONARY is not set +# CONFIG_DEBUG_INTERNAL is not set +# CONFIG_DEBUG_INTERPRETER is not set +CONFIG_DEBUG_CONSOLE=y +CONFIG_DEBUG_CONSOLE_SERIAL=y +CONFIG_SERIAL_PORT=1 +CONFIG_SERIAL_SPEED=115200 +CONFIG_DEBUG_CONSOLE_VGA=y + +# +# Packages +# +# CONFIG_PKG_DEBLOCKER is not set +# CONFIG_PKG_DISKLABEL is not set +# CONFIG_PKG_OBP_TFTP is not set +# CONFIG_PKG_TERMINAL_EMULATOR is not set + +# +# Module Configuration +# +CONFIG_DEBLOCKER=y +CONFIG_DISK_LABEL=y +CONFIG_PART_SUPPORT=y +CONFIG_MAC_PARTS=y +CONFIG_FS=y +CONFIG_HFS=y +CONFIG_HFSP=y diff --git a/qemu/roms/openbios/arch/ppc/kernel.c b/qemu/roms/openbios/arch/ppc/kernel.c new file mode 100644 index 000000000..28f2965bb --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/kernel.c @@ -0,0 +1,99 @@ +/* + * Creation Date: <2003/10/25 14:07:17 samuel> + * Time-stamp: <2004/08/28 17:48:19 stepan> + * + * <kernel.c> + * + * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se) + * Copyright (C) 2003, 2004 Stefan Reinauer + * + * Based upon unix.c (from OpenBIOS): + * + * Copyright (C) 2003 Patrick Mauritz, Stefan Reinauer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#include "config.h" +#include "dict.h" +#include "libopenbios/bindings.h" +#include "kernel/stack.h" +#include "kernel/kernel.h" +#include "libc/string.h" +#include "kernel.h" + +#define MEMORY_SIZE (256*1024) /* 256K ram for hosted system */ +#define DICTIONARY_SIZE (512*1024) /* 512K for the dictionary */ + +static ucell *memory; + +/************************************************************************/ +/* F U N C T I O N S */ +/************************************************************************/ + +int +forth_segv_handler( char *segv_addr ) +{ + ucell addr = 0xdeadbeef; + + if( PC >= (ucell) dict && PC <= (ucell) dict + dicthead ) + addr = *(ucell *) PC; + + printk("panic: segmentation violation at %x\n", (int)segv_addr); + printk("dict=0x%x here=0x%x(dict+0x%x) pc=0x%x(dict+0x%x)\n", + (int)dict, (int)(dict + dicthead), dicthead, + PC, PC - (ucell) dict); + printk("dstackcnt=%d rstackcnt=%d instruction=%x\n", + dstackcnt, rstackcnt, addr); + +#ifdef DEBUG_DSTACK + printdstack(); +#endif +#ifdef DEBUG_RSTACK + printrstack(); +#endif + return -1; +} + +/* + * allocate memory and prepare engine for memory management. + */ + +static void +init_memory( void ) +{ + memory = malloc(MEMORY_SIZE); + if( !memory ) + panic("panic: not enough memory on host system.\n"); + + /* we push start and end of memory to the stack + * so that it can be used by the forth word QUIT + * to initialize the memory allocator + */ + + PUSH( (ucell)memory ); + PUSH( (ucell)memory + MEMORY_SIZE ); +} + +int +initialize_forth( void ) +{ + dict = malloc(DICTIONARY_SIZE); + load_dictionary( forth_dictionary, sizeof(forth_dictionary) ); + forth_init(); + + PUSH_xt( bind_noname_func(arch_of_init) ); + fword("PREPOST-initializer"); + + PC = (ucell)findword("initialize-of"); + if( PC ) { + init_memory(); + enterforth((xt_t)PC); + free( memory ); + } + free( dict ); + return 0; +} diff --git a/qemu/roms/openbios/arch/ppc/kernel.h b/qemu/roms/openbios/arch/ppc/kernel.h new file mode 100644 index 000000000..20cda489e --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/kernel.h @@ -0,0 +1,41 @@ +/* + * Creation Date: <2004/08/28 17:50:12 stepan> + * Time-stamp: <2004/08/28 17:50:12 stepan> + * + * <kernel.h> + * + * Copyright (C) 2004 Stefan Reinauer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#ifndef __KERNEL_H__ +#define __KERNEL_H__ + +/* misc.c */ +extern void fatal_error( const char *str ); +extern void exit( int status ); + +/* start.S */ +extern void flush_icache_range( char *start, char *stop ); +extern char of_rtas_start[], of_rtas_end[]; + +/* methods.c */ +extern void node_methods_init( void ); + +/* main.c */ +extern void boot( void ); + +/* init.c */ +extern void entry( void ); +extern void arch_of_init( void ); +extern int get_bool_res( const char *str ); + +/* tree.c */ +extern void devtree_init( void ); + + +#endif /* __KERNEL_H__ */ diff --git a/qemu/roms/openbios/arch/ppc/misc.S b/qemu/roms/openbios/arch/ppc/misc.S new file mode 100644 index 000000000..435ce0eca --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/misc.S @@ -0,0 +1,74 @@ +/* + * Creation Date: <2002/10/20 15:54:50 samuel> + * Time-stamp: <2002/10/20 15:57:21 samuel> + * + * <misc.S> + * + * Low-level stuff + * + * Copyright (C) 2002, 2003 Samuel Rydh (samuel@ibrium.se) + * + * Based upon misc.S from the the linux kernel with the following + * copyrights: + * + * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org), + * Cort Dougan (cort@cs.nmt.edu), Paul Mackerras + * + * 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 + * + */ + +#include "asm/asmdefs.h" +#include "asm/processor.h" + + +/* + * Extended precision shifts. + * + * Updated to be valid for shift counts from 0 to 63 inclusive. + * -- Gabriel + * + * R3/R4 has 64 bit value + * R5 has shift count + * result in R3/R4 + * + * ashrdi3: arithmetic right shift (sign propagation) + * lshrdi3: logical right shift + * ashldi3: left shift + */ +GLOBL(__ashrdi3): + subfic r6,r5,32 + srw r4,r4,r5 # LSW = count > 31 ? 0 : LSW >> count + addi r7,r5,32 # could be xori, or addi with -32 + slw r6,r3,r6 # t1 = count > 31 ? 0 : MSW << (32-count) + rlwinm r8,r7,0,32 # t3 = (count < 32) ? 32 : 0 + sraw r7,r3,r7 # t2 = MSW >> (count-32) + or r4,r4,r6 # LSW |= t1 + slw r7,r7,r8 # t2 = (count < 32) ? 0 : t2 + sraw r3,r3,r5 # MSW = MSW >> count + or r4,r4,r7 # LSW |= t2 + blr + +GLOBL(__ashldi3): + subfic r6,r5,32 + slw r3,r3,r5 # MSW = count > 31 ? 0 : MSW << count + addi r7,r5,32 # could be xori, or addi with -32 + srw r6,r4,r6 # t1 = count > 31 ? 0 : LSW >> (32-count) + slw r7,r4,r7 # t2 = count < 32 ? 0 : LSW << (count-32) + or r3,r3,r6 # MSW |= t1 + slw r4,r4,r5 # LSW = LSW << count + or r3,r3,r7 # MSW |= t2 + blr + +GLOBL(__lshrdi3): + subfic r6,r5,32 + srw r4,r4,r5 # LSW = count > 31 ? 0 : LSW >> count + addi r7,r5,32 # could be xori, or addi with -32 + slw r6,r3,r6 # t1 = count > 31 ? 0 : MSW << (32-count) + srw r7,r3,r7 # t2 = count < 32 ? 0 : MSW >> (count-32) + or r4,r4,r6 # LSW |= t1 + srw r3,r3,r5 # MSW = MSW >> count + or r4,r4,r7 # LSW |= t2 + blr diff --git a/qemu/roms/openbios/arch/ppc/mmutypes.h b/qemu/roms/openbios/arch/ppc/mmutypes.h new file mode 100644 index 000000000..441d7f8bc --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/mmutypes.h @@ -0,0 +1,76 @@ +/* + * Creation Date: <2002/01/13 13:53:14 samuel> + * Time-stamp: <2002/01/27 19:56:11 samuel> + * + * <mmutypes.h> + * + * MMU definitions + * + * Most of these declarations originate from the Linux Kernel + * + * Copyright (C) 2002 Samuel Rydh (samuel@ibrium.se) + * + * 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 + * + */ + +#ifndef _H_MMUTYPES +#define _H_MMUTYPES + +/* Hardware Page Table Entry */ +typedef struct mPTE { + unsigned long v:1; /* Entry is valid */ + unsigned long vsid:24; /* Virtual segment identifier */ + unsigned long h:1; /* Hash algorithm indicator */ + unsigned long api:6; /* Abbreviated page index */ + + unsigned long rpn:20; /* Real (physical) page number */ + unsigned long :3; /* Unused */ + unsigned long r:1; /* Referenced */ + unsigned long c:1; /* Changed */ + unsigned long w:1; /* Write-thru cache mode */ + unsigned long i:1; /* Cache inhibited */ + unsigned long m:1; /* Memory coherence */ + unsigned long g:1; /* Guarded */ + unsigned long :1; /* Unused */ + unsigned long pp:2; /* Page protection */ +} mPTE_t; + + +typedef struct _mBATU { /* Upper part of BAT (all except 601) */ + unsigned long bepi:15; /* Effective page index (virtual address) */ + unsigned long :4; /* Unused */ + unsigned long bl:11; /* Block size mask */ + unsigned long vs:1; /* Supervisor valid */ + unsigned long vp:1; /* User valid */ +} mBATU; + +typedef struct _mBATL { /* Lower part of BAT (all except 601) */ + unsigned long brpn:15; /* Real page index (physical address) */ + unsigned long :10; /* Unused */ + unsigned long w:1; /* Write-thru cache */ + unsigned long i:1; /* Cache inhibit */ + unsigned long m:1; /* Memory coherence */ + unsigned long g:1; /* Guarded (MBZ in IBAT) */ + unsigned long :1; /* Unused */ + unsigned long pp:2; /* Page access protections */ +} mBATL; + +typedef struct _mBAT { + mBATU batu; /* Upper register */ + mBATL batl; /* Lower register */ +} mBAT; + +typedef struct _mSEGREG { + unsigned long t:1; /* Normal or I/O type */ + unsigned long ks:1; /* Supervisor 'key' (normally 0) */ + unsigned long kp:1; /* User 'key' (normally 1) */ + unsigned long n:1; /* No-execute */ + unsigned long :4; /* Unused */ + unsigned long vsid:24; /* Virtual Segment Identifier */ +} mSEGREG; + + +#endif /* _H_MMUTYPES */ diff --git a/qemu/roms/openbios/arch/ppc/mol/console.c b/qemu/roms/openbios/arch/ppc/mol/console.c new file mode 100644 index 000000000..966011e19 --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/mol/console.c @@ -0,0 +1,30 @@ +/* + * Creation Date: <2002/10/29 18:59:05 samuel> + * Time-stamp: <2003/12/28 22:51:11 samuel> + * + * <console.c> + * + * Simple text console + * + * Copyright (C) 2002, 2003, 2004 Samuel Rydh (samuel@ibrium.se) + * Copyright (C) 2005 Stefan Reinauer <stepan@openbios.org> + * + * 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 + * + */ + +#include "config.h" +#include "libopenbios/bindings.h" +#include "libc/diskio.h" +#include "osi_calls.h" +#include "libopenbios/ofmem.h" +#include "mol/mol.h" +#include "boothelper_sh.h" +#include "video_sh.h" + +#define openbios_GetFBInfo(x) OSI_GetFBInfo(x) + +#include "../../../packages/video.c" +#include "../../../libopenbios/console_common.c" diff --git a/qemu/roms/openbios/arch/ppc/mol/init.c b/qemu/roms/openbios/arch/ppc/mol/init.c new file mode 100644 index 000000000..15333b4e1 --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/mol/init.c @@ -0,0 +1,119 @@ +/* + * Creation Date: <1999/11/16 00:49:26 samuel> + * Time-stamp: <2004/04/12 16:26:50 samuel> + * + * <init.c> + * + * Initialization + * + * Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 Samuel & David Rydh + # (samuel@ibrium.se, dary@lindesign.se) + * + * 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 + * + */ + +#include "config.h" +#include "libopenbios/openbios.h" +#include "libopenbios/bindings.h" +#include "arch/common/nvram.h" +#include "mol/mol.h" +#include "libopenbios/ofmem.h" +#include "mol/prom.h" +#include "openbios-version.h" +#include "osi_calls.h" +#include "boothelper_sh.h" + +extern void unexpected_excep( int vector ); + +int +get_bool_res( const char *res ) +{ + char buf[8], *p; + + p = BootHGetStrRes( res, buf, sizeof(buf) ); + if( !p ) + return -1; + if( !strcasecmp(p,"true") || !strcasecmp(p,"yes") || !strcasecmp(p,"1") ) + return 1; + return 0; +} + +void +unexpected_excep( int vector ) +{ + printk("MOL panic: Unexpected exception %x\n", vector ); + for( ;; ) + ; +} + +unsigned long isa_io_base; + +void +entry( void ) +{ + isa_io_base = 0x80000000; + + printk("\n"); + printk("=============================================================\n"); + printk(PROGRAM_NAME " " OPENBIOS_VERSION_STR " [%s]\n", + OPENBIOS_BUILD_DATE); + + ofmem_init(); + initialize_forth(); + /* won't return */ + + printk("of_startup returned!\n"); + for( ;; ) + ; +} + +static void +setenv( char *env, char *value ) +{ + push_str( value ); + push_str( env ); + fword("$setenv"); +} + +void +arch_of_init( void ) +{ + mol_phandle_t ph; + int autoboot; + + devtree_init(); + node_methods_init(); + nvram_init("/pci/mac-io/nvram"); + openbios_init(); + modules_init(); + pseudodisk_init(); + osiblk_init(); + osiscsi_init(); + init_video(); + + if( (ph=prom_find_device("/rtas")) == -1 ) + printk("Warning: No /rtas node\n"); + else { + unsigned long size = 0x1000; + while( size < (unsigned long)of_rtas_end - (unsigned long)of_rtas_start ) + size *= 2; + prom_set_prop( ph, "rtas-size", (char*)&size, sizeof(size) ); + } + + /* tweak boot settings */ + autoboot = !!get_bool_res("autoboot"); + if( !autoboot ) + printk("Autobooting disabled - dropping into OpenFirmware\n"); + setenv("auto-boot?", autoboot ? "true" : "false" ); + setenv("boot-command", "molboot"); + + if( get_bool_res("tty-interface") == 1 ) + fword("activate-tty-interface"); + + /* hack */ + device_end(); + bind_func("molboot", boot ); +} diff --git a/qemu/roms/openbios/arch/ppc/mol/kernel.c b/qemu/roms/openbios/arch/ppc/mol/kernel.c new file mode 100644 index 000000000..1454b8a85 --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/mol/kernel.c @@ -0,0 +1,16 @@ +/* + * Creation Date: <2004/08/28 18:03:25 stepan> + * Time-stamp: <2004/08/28 18:03:25 stepan> + * + * <mol/kernel.c> + * + * Copyright (C) 2004 Stefan Reinauer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#include "mol-dict.h" +#include "../kernel.c" diff --git a/qemu/roms/openbios/arch/ppc/mol/main.c b/qemu/roms/openbios/arch/ppc/mol/main.c new file mode 100644 index 000000000..f6ed934d0 --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/mol/main.c @@ -0,0 +1,370 @@ +/* + * Creation Date: <2002/10/02 22:24:24 samuel> + * Time-stamp: <2004/03/27 01:57:55 samuel> + * + * <main.c> + * + * + * + * Copyright (C) 2002, 2003, 2004 Samuel Rydh (samuel@ibrium.se) + * + * 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 + * + */ + + +#include "config.h" +#include "libopenbios/bindings.h" +#include "libopenbios/elfload.h" +#include "arch/common/nvram.h" +#include "libc/diskio.h" +#include "libc/vsprintf.h" +#include "mol/mol.h" +#include "libopenbios/ofmem.h" +#include "osi_calls.h" +#include "ablk_sh.h" +#include "boothelper_sh.h" + + +static void patch_newworld_rom( char *start, size_t size ); +static void newworld_timer_hack( char *start, size_t size ); + +static void +transfer_control_to_elf( unsigned long entry ) +{ + extern void call_elf( unsigned long entry ); + printk("Starting ELF boot loader\n"); + call_elf( entry ); + + fatal_error("call_elf returned unexpectedly\n"); +} + +static int +load_elf_rom( unsigned long *entry, int fd ) +{ + int i, lszz_offs, elf_offs; + char buf[128], *addr; + Elf_ehdr ehdr; + Elf_phdr *phdr; + size_t s; + + printk("Loading '%s' from '%s'\n", get_file_path(fd), + get_volume_name(fd) ); + + /* the ELF-image (usually) starts at offset 0x4000 */ + if( (elf_offs=find_elf(fd)) < 0 ) { + printk("----> %s is not an ELF image\n", buf ); + exit(1); + } + if( !(phdr=elf_readhdrs(fd, elf_offs, &ehdr)) ) + fatal_error("elf_readhdrs failed\n"); + + *entry = ehdr.e_entry; + + /* load segments. Compressed ROM-image assumed to be located immediately + * after the last segment */ + lszz_offs = elf_offs; + for( i=0; i<ehdr.e_phnum; i++ ) { + /* p_memsz, p_flags */ + s = MIN( phdr[i].p_filesz, phdr[i].p_memsz ); + seek_io( fd, elf_offs + phdr[i].p_offset ); + + /* printk("filesz: %08lX memsz: %08lX p_offset: %08lX p_vaddr %08lX\n", + phdr[i].p_filesz, phdr[i].p_memsz, phdr[i].p_offset, + phdr[i].p_vaddr ); */ + + if( phdr[i].p_vaddr != phdr[i].p_paddr ) + printk("WARNING: ELF segment virtual addr != physical addr\n"); + lszz_offs = MAX( lszz_offs, elf_offs + phdr[i].p_offset + phdr[i].p_filesz ); + if( !s ) + continue; + if( ofmem_claim( phdr[i].p_vaddr, phdr[i].p_memsz, 0 ) == -1 ) + fatal_error("Claim failed!\n"); + + addr = (char*)phdr[i].p_vaddr; + if( read_io(fd, addr, s) != s ) + fatal_error("read failed\n"); + + /* patch CODE segment */ + if( *entry >= phdr[i].p_vaddr && *entry < phdr[i].p_vaddr + s ) { + patch_newworld_rom( (char*)phdr[i].p_vaddr, s ); + newworld_timer_hack( (char*)phdr[i].p_vaddr, s ); + } + flush_icache_range( addr, addr+s ); + + /* printk("ELF ROM-section loaded at %08lX (size %08lX)\n", + (unsigned long)phdr[i].p_vaddr, (unsigned long)phdr[i].p_memsz );*/ + } + free( phdr ); + return lszz_offs; +} + + +/************************************************************************/ +/* newworld ROM loading */ +/************************************************************************/ + +#define ROM_BASE 0x1100000 /* where we decide to put things */ + +/* fix bug present in the 2.4 and the 3.0 Apple ROM */ +static void +patch_newworld_rom( char *start, size_t size ) +{ + int s; + unsigned long mark[] = { 0x7c7d1b78, /* mr r29,r3 */ + 0x7c9c2378, /* mr r28,r4 */ + 0x7cc33378, /* mr r3,r6 */ + 0x7c864214, /* add r4,r6,r8 <------ BUG -- */ + 0x80b10000, /* lwz r5,0(r17) */ + 0x38a500e8 }; /* addi r5,r5,232 */ + + /* Correcting add r4,r6,r8 ----> addi r4,r6,8 */ + for( s=0; s<size-sizeof(mark); s+=4 ) + if( memcmp( start+s, mark, sizeof(mark)) == 0 ) { + printk("FIXING ROM BUG @ %X!\n", s+12); + ((unsigned long*)(start+s))[3] = 0x38860008; /* addi r4,r6,8 */ + } +} + +/* This hack is only needed on machines with a timebase slower than 12.5 MHz + * (50 MHz bus frequency). Typically only old, accelerated machines fall + * into this category. The cause of the problem is an overflow in Apple's + * calibration routine. + */ +static void +newworld_timer_hack( char *start, size_t size ) +{ + int s; + unsigned long mark[] = { 0x7d0000a6, 0x5507045e, 0x7ce00124, 0x4c00012c, + 0x38e00000, 0x3c80000f, 0x6084ffff, 0x98830c00, + 0x7c0006ac, 0x98830a00, 0x7c0006ac, 0x7c9603a6, + 0x4c00012c, 0x7cb602a6, 0x2c050000, 0x4181fff8, + 0x7c0004ac, 0x88830a00, 0x7c0006ac, 0x88a30800, + 0x7c0006ac, 0x88c30a00, 0x7c0006ac, 0x7c043040, + 0x40a2ffe4, 0x5085442e, 0x7ca500d0, 0x54a5043e, + 0x7c053840, 0x7ca72b78, 0x4082ff9c, 0x7ca32b78, + 0x7d000124, 0x4c00012c, 0x4e800020 + }; + + /* return #via ticks corresponding to 0xfffff DEC ticks (VIA frequency == 47/60 MHz) */ + for( s=0; s < size-sizeof(mark); s+=4 ) { + if( !memcmp( start+s, mark, sizeof(mark)) ) { + extern char timer_calib_start[], timer_calib_end[]; + extern unsigned long nw_dec_calibration; + int hz = OSI_UsecsToMticks(1000); + nw_dec_calibration = OSI_MticksToUsecs(0xfffff*47)/60; + memcpy( start + s, timer_calib_start, timer_calib_end - timer_calib_start ); + + printk("Timer calibration fix: %d.%02d MHz [%ld]\n", + hz/1000, (hz/10)%100, nw_dec_calibration ); + break; + } + } +} + +static unsigned long +load_newworld_rom( int fd ) +{ + int lszz_offs, lszz_size; + unsigned long entry, data[2]; + phandle_t ph; + + lszz_offs = load_elf_rom( &entry, fd ); + seek_io( fd, -1 ); + lszz_size = tell(fd) - lszz_offs; + seek_io( fd, lszz_offs ); + + /* printk("Compressed ROM image: offset %08X, size %08X loaded at %08x\n", + lszz_offs, lszz_size, ROM_BASE ); */ + + if( ofmem_claim(ROM_BASE, lszz_size, 0) == -1 ) + fatal_error("Claim failure (lszz)!\n"); + + read_io( fd, (char*)ROM_BASE, lszz_size ); + + /* Fix the /rom/macos/AAPL,toolbox-image,lzss property (phys, size) */ +#if 0 + if( (ph=prom_create_node("/rom/macos/")) == -1 ) + fatal_error("Failed creating /rom/macos/"); +#else + ph = find_dev("/rom/macos"); +#endif + data[0] = ROM_BASE; + data[1] = lszz_size; + set_property( ph, "AAPL,toolbox-image,lzss", (char*)data, sizeof(data) ); + + /* The 7.8 rom (MacOS 9.2) uses AAPL,toolbox-parcels instead of + * AAPL,toolbox-image,lzss. It probably doesn't hurt to have it + * always present (we don't have an easy way to determine ROM version...) + */ + set_property( ph, "AAPL,toolbox-parcels", (char*)data, sizeof(data) ); + return entry; +} + +static int +search_nwrom( int fd, int fast ) +{ + char *s, buf[128]; + int found = 0; + + if( fast ) { + int ind; + found = !reopen( fd, "\\\\:tbxi" ); + for( ind=0; !found && (s=BootHGetStrResInd("macos_rompath", buf, sizeof(buf), ind++, 0)) ; ) + found = !reopen( fd, s ); + for( ind=0; !found && (s=BootHGetStrResInd("macos_rompath_", buf, sizeof(buf), ind++, 0)) ; ) + found = !reopen( fd, s ); + } else { + printk("Searching %s for a 'Mac OS ROM' file\n", get_volume_name(fd) ); + if( !(found=reopen_nwrom(fd)) ) { + printk(" \n**** HINT ***************************************************\n"); + printk("* The booting can be speeded up by adding the line\n"); + printk("* macos_rompath: '%s'\n", get_file_path(fd) ); + printk("* to the /etc/mol/molrc.macos (recommended).\n"); + printk("*************************************************************\n \n"); + } + } + return found; +} + +static void +encode_bootpath( const char *spec, const char *args ) +{ + phandle_t chosen_ph = find_dev("/chosen"); + set_property( chosen_ph, "bootpath", spec, strlen(spec)+1 ); + set_property( chosen_ph, "bootargs", args, strlen(args)+1 ); +} + +static char * +newworld_load( const char *node_path, const char *spec, int do_search ) +{ + char *p, *entry, buf[80]; + int fd, len; + + if( (fd=open_io(spec)) == -1 ) + return NULL; + + if( !search_nwrom(fd, do_search) ) { + close_io(fd); + return NULL; + } + printk("Boot Disk: %s [%s]\n", spec, get_fstype(fd) ); + + entry = (char*)load_newworld_rom( fd ); + +#if 1 + PUSH_ih( get_ih_from_fd(fd) ); + fword("get-instance-path"); + len = POP(); + p = (char*)POP(); + buf[0] = 0; + if( len < sizeof(buf) ) { + memcpy( buf, p, len ); + buf[len] =0; + } + strcat( buf, "/x@:" ); + printk("boot_path: %s\n", buf ); + encode_bootpath( buf, "" ); +#endif + close_io( fd ); + return entry; +} + +static void +newworld_startup( void ) +{ + int i, j, bootunit, type, fd; + ablk_disk_info_t info; + char *entry = NULL; + char spec[80]; + phandle_t ph; + + char path[]="/pci/pci-bridge/mol-blk"; + if( !(ph=find_dev(path)) ) + fatal_error("MOLBlockDriver node not found\n"); + + /* user-specified newworld ROMs take precedence */ + if( (fd=open_io("pseudo:,nwrom")) >= 0 ) { + entry = (char*)load_newworld_rom( fd ); + close_io( fd ); + } + + /* determine boot volume */ + for( bootunit=-1, type=0; bootunit==-1 && type<3 ; type++ ) { + for( i=0; !OSI_ABlkDiskInfo(0, i, &info) ; i++ ) { + if( type<=1 && !(info.flags & ABLK_BOOT_HINT) ) + continue; + if( type>1 && (info.flags & ABLK_BOOT_HINT) ) + continue; + + for( j=0; !entry && j<32; j++ ) { + snprintf( spec, sizeof(spec), "%s/disk@%x:%d", + path, i, j ); + entry = newworld_load( path, spec, (!type || type==2) ); + } + if( entry ) { + bootunit = i; + break; + } + } + } + + if( entry ) { + OSI_ABlkBlessDisk( 0 /*channel*/, bootunit ); + + update_nvram(); + transfer_control_to_elf( (unsigned long)entry ); + /* won't come here */ + return; + } + + printk("\n--- No bootable disk was found! -----------------------------\n"); + printk("If this is an oldworld machine, try booting from the MacOS\n"); + printk("install CD and install MacOS from within MOL.\n"); + printk("-------------------------------------------------------------\n"); + exit(1); +} + + +/************************************************************************/ +/* yaboot booting */ +/************************************************************************/ + +static void +yaboot_startup( void ) +{ + const char *paths[] = { "pseudo:,ofclient", "pseudo:,yaboot", NULL }; + unsigned long entry; + int i, fd; + + for( i=0; paths[i]; i++ ) { + if( (fd=open_io(paths[i])) == -1 ) + continue; + (void) load_elf_rom( &entry, fd ); + close_io( fd ); + encode_bootpath( paths[i], "" ); + + update_nvram(); + transfer_control_to_elf( entry ); + /* won't come here */ + } + printk("*** Boot failure! No secondary bootloader specified ***\n"); + exit(1); +} + + +/************************************************************************/ +/* entry */ +/************************************************************************/ + +void +boot( void ) +{ + fword("update-chosen"); + if( find_dev("/mol-platform") ) + yaboot_startup(); + else + newworld_startup(); +} diff --git a/qemu/roms/openbios/arch/ppc/mol/methods.c b/qemu/roms/openbios/arch/ppc/mol/methods.c new file mode 100644 index 000000000..bfaf51506 --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/mol/methods.c @@ -0,0 +1,470 @@ +/* + * Creation Date: <2003/10/18 13:24:29 samuel> + * Time-stamp: <2004/03/27 02:00:30 samuel> + * + * <methods.c> + * + * Misc device node methods + * + * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#include "config.h" +#include "libopenbios/bindings.h" +#include "libc/string.h" +#include "mol/mol.h" +#include "libopenbios/ofmem.h" +#include "mol/prom.h" +#include "osi_calls.h" +#include "kbd_sh.h" + +/************************************************************************/ +/* Power Management */ +/************************************************************************/ + +DECLARE_NODE( powermgt, INSTALL_OPEN, 0, "/pci/pci-bridge/mac-io/power-mgt" ); + +/* ( -- ) */ +static void +set_hybernot_flag( void ) +{ +} + +NODE_METHODS( powermgt ) = { + { "set-hybernot-flag", set_hybernot_flag }, +}; + + +/************************************************************************/ +/* RTAS (run-time abstraction services) */ +/************************************************************************/ + +DECLARE_NODE( rtas, INSTALL_OPEN, 0, "+/rtas" ); + +/* ( physbase -- rtas_callback ) */ +static void +rtas_instantiate( void ) +{ + int physbase = POP(); + int s=0x1000, size = (int)of_rtas_end - (int)of_rtas_start; + unsigned long virt; + + while( s < size ) + s += 0x1000; + virt = ofmem_claim_virt( 0, s, 0x1000 ); + ofmem_map( physbase, virt, s, -1 ); + memcpy( (char*)virt, of_rtas_start, size ); + + printk("RTAS instantiated at %08x\n", physbase ); + flush_icache_range( (char*)virt, (char*)virt + size ); + + PUSH( physbase ); +} + +NODE_METHODS( rtas ) = { + { "instantiate", rtas_instantiate }, + { "instantiate-rtas", rtas_instantiate }, +}; + + + +/************************************************************************/ +/* stdout */ +/************************************************************************/ + +DECLARE_NODE( video_stdout, INSTALL_OPEN, 0, "Tdisplay" ); + +/* ( addr len -- actual ) */ +static void +stdout_write( void ) +{ + int len = POP(); + char *addr = (char*)POP(); + + /* printk( "%s", s ); */ + console_draw_fstr(addr, len); + + PUSH( len ); +} + +NODE_METHODS( video_stdout ) = { + { "write", stdout_write }, +}; + + +/************************************************************************/ +/* tty */ +/************************************************************************/ + +DECLARE_NODE( tty, INSTALL_OPEN, 0, "+/mol/mol-tty" ); + +/* ( addr len -- actual ) */ +static void +tty_read( void ) +{ + int ch, len = POP(); + char *p = (char*)POP(); + int ret=0; + + if( len > 0 ) { + ret = 1; + ch = OSI_TTYGetc(); + if( ch >= 0 ) { + *p = ch; + } else { + ret = 0; + OSI_USleep(1); + } + } + PUSH( ret ); +} + +/* ( addr len -- actual ) */ +static void +tty_write( void ) +{ + int i, len = POP(); + char *p = (char*)POP(); + for( i=0; i<len; i++ ) + OSI_TTYPutc( *p++ ); + RET( len ); +} + +NODE_METHODS( tty ) = { + { "read", tty_read }, + { "write", tty_write }, +}; + + +/************************************************************************/ +/* keyboard */ +/************************************************************************/ + +typedef struct { + int cntrl; + int shift; + int meta; + int alt; + int save_key; + char keytable[32]; +} kbd_state_t; + +static const unsigned char adb_ascii_table[128] = + /* 0x00 */ "asdfhgzxcv`bqwer" + /* 0x10 */ "yt123465=97-80]o" + /* 0x20 */ "u[ip\nlj'k;\\,/nm." + /* 0x30 */ "\t <\b \e " + /* 0x40 */ " . * + / - " + /* 0x50 */ " =01234567 89 " + /* 0x60 */ " " + /* 0x70 */ " "; + +static const unsigned char adb_shift_table[128] = + /* 0x00 */ "ASDFHGZXCV~BQWER" + /* 0x10 */ "YT!@#$^%+(&_*)}O" + /* 0x20 */ "U{IP\nLJ\"K:|<?NM>" + /* 0x30 */ "\t <\b \e " + /* 0x40 */ " . * + / - " + /* 0x50 */ " =01234567 89 " + /* 0x60 */ " " + /* 0x70 */ " "; + +DECLARE_NODE( kbd, INSTALL_OPEN, sizeof(kbd_state_t), + "/psuedo-hid/keyboard", + "/mol/mol-keyboard", + "/mol/keyboard" +); + +/* ( -- keymap ) (?) */ +/* should return a pointer to an array with 32 bytes (256 bits) */ +static void +kbd_get_key_map( kbd_state_t *ks ) +{ + /* printk("met_kbd_get_key_map\n"); */ + + /* keytable[5] = 0x40; */ + PUSH( (int)ks->keytable ); +} + +/* ( buf len --- actlen ) */ +static void +kbd_read( kbd_state_t *ks ) +{ + int ret=0, len = POP(); + char *p = (char*)POP(); + int key; + + if( !p || !len ) { + PUSH( -1 ); + return; + } + + if( ks->save_key ) { + *p = ks->save_key; + ks->save_key = 0; + RET( 1 ); + } + OSI_USleep(1); /* be nice */ + + for( ; (key=OSI_GetAdbKey()) >= 0 ; ) { + int code = (key & 0x7f); + int down = !(key & 0x80); + + if( code == 0x36 /* ctrl */ ) { + ks->cntrl = down; + continue; + } + if( code == 0x38 /* shift */ || code == 0x7b) { + ks->shift = down; + continue; + } + if( code == 0x37 /* command */ ) { + ks->meta = down; + continue; + } + if( code == 0x3a /* alt */ ) { + ks->alt = down; + continue; + } + if( !down ) + continue; + + ret = 1; + if( ks->shift ) + key = adb_shift_table[ key & 0x7f ]; + else + key = adb_ascii_table[ key & 0x7f ]; + + if( ks->meta ) { + ks->save_key = key; + key = 27; + } else if( ks->cntrl ) { + key = key - 'a' + 1; + } + *p = key; + if( !*p ) + *p = 'x'; + break; + } + PUSH( ret ); +} + +NODE_METHODS( kbd ) = { + { "read", kbd_read }, + { "get-key-map", kbd_get_key_map }, +}; + + +/************************************************************************/ +/* client interface 'quiesce' */ +/************************************************************************/ + +DECLARE_NODE( ciface, 0, 0, "/packages/client-iface" ); + +/* ( -- ) */ +static void +ciface_quiesce( unsigned long args[], unsigned long ret[] ) +{ +#if 0 + unsigned long msr; + /* This seems to be the correct thing to do - but I'm not sure */ + asm volatile("mfmsr %0" : "=r" (msr) : ); + msr &= ~(MSR_IR | MSR_DR); + asm volatile("mtmsr %0" :: "r" (msr) ); +#endif + printk("=============================================================\n\n"); + prom_close(); + + OSI_KbdCntrl( kKbdCntrlSuspend ); +} + +/* ( -- ms ) */ +static void +ciface_milliseconds( unsigned long args[], unsigned long ret[] ) +{ + static unsigned long mticks=0, usecs=0; + unsigned long t; + + asm volatile("mftb %0" : "=r" (t) : ); + if( mticks ) + usecs += OSI_MticksToUsecs( t-mticks ); + mticks = t; + + PUSH( usecs/1000 ); +} + + +NODE_METHODS( ciface ) = { + { "quiesce", ciface_quiesce }, + { "milliseconds", ciface_milliseconds }, +}; + + +/************************************************************************/ +/* MMU/memory methods */ +/************************************************************************/ + +DECLARE_NODE( memory, INSTALL_OPEN, 0, "/memory" ); +DECLARE_NODE( mmu, INSTALL_OPEN, 0, "/cpus/@0" ); +DECLARE_NODE( mmu_ciface, 0, 0, "/packages/client-iface" ); + + +/* ( phys size align --- base ) */ +static void +mem_claim( void ) +{ + ucell align = POP(); + ucell size = POP(); + ucell phys = POP(); + ucell ret = ofmem_claim_phys( phys, size, align ); + + if( ret == -1 ) { + printk("MEM: claim failure\n"); + throw( -13 ); + return; + } + PUSH( ret ); +} + +/* ( phys size --- ) */ +static void +mem_release( void ) +{ + POP(); POP(); +} + +/* ( phys size align --- base ) */ +static void +mmu_claim( void ) +{ + ucell align = POP(); + ucell size = POP(); + ucell phys = POP(); + ucell ret = ofmem_claim_virt( phys, size, align ); + + if( ret == -1 ) { + printk("MMU: CLAIM failure\n"); + throw( -13 ); + return; + } + PUSH( ret ); +} + +/* ( phys size --- ) */ +static void +mmu_release( void ) +{ + POP(); POP(); +} + +/* ( phys virt size mode -- [ret???] ) */ +static void +mmu_map( void ) +{ + ucell mode = POP(); + ucell size = POP(); + ucell virt = POP(); + ucell phys = POP(); + ucell ret; + + /* printk("mmu_map: %x %x %x %x\n", phys, virt, size, mode ); */ + ret = ofmem_map( phys, virt, size, mode ); + + if( ret ) { + printk("MMU: map failure\n"); + throw( -13 ); + return; + } +} + +/* ( virt size -- ) */ +static void +mmu_unmap( void ) +{ + POP(); POP(); +} + +/* ( virt -- false | phys mode true ) */ +static void +mmu_translate( void ) +{ + ucell mode; + ucell virt = POP(); + ucell phys = ofmem_translate( virt, &mode ); + + if( phys == -1 ) { + PUSH( 0 ); + } else { + PUSH( phys ); + PUSH( mode ); + PUSH( -1 ); + } +} + +/* ( virt size align -- baseaddr|-1 ) */ +static void +ciface_claim( void ) +{ + ucell align = POP(); + ucell size = POP(); + ucell virt = POP(); + ucell ret = ofmem_claim( virt, size, align ); + + /* printk("ciface_claim: %08x %08x %x\n", virt, size, align ); */ + PUSH( ret ); +} + +/* ( virt size -- ) */ +static void +ciface_release( void ) +{ + POP(); + POP(); +} + + +NODE_METHODS( memory ) = { + { "claim", mem_claim }, + { "release", mem_release }, +}; + +NODE_METHODS( mmu ) = { + { "claim", mmu_claim }, + { "release", mmu_release }, + { "map", mmu_map }, + { "unmap", mmu_unmap }, + { "translate", mmu_translate }, +}; + +NODE_METHODS( mmu_ciface ) = { + { "cif-claim", ciface_claim }, + { "cif-release", ciface_release }, +}; + + +/************************************************************************/ +/* init */ +/************************************************************************/ + +void +node_methods_init( void ) +{ + REGISTER_NODE( rtas ); + REGISTER_NODE( powermgt ); + REGISTER_NODE( kbd ); + REGISTER_NODE( video_stdout ); + REGISTER_NODE( ciface ); + REGISTER_NODE( memory ); + REGISTER_NODE( mmu ); + REGISTER_NODE( mmu_ciface ); + + if( OSI_CallAvailable(OSI_TTY_GETC) ) + REGISTER_NODE( tty ); + + OSI_KbdCntrl( kKbdCntrlActivate ); +} diff --git a/qemu/roms/openbios/arch/ppc/mol/mol.c b/qemu/roms/openbios/arch/ppc/mol/mol.c new file mode 100644 index 000000000..86b3b66bf --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/mol/mol.c @@ -0,0 +1,165 @@ +/* + * Creation Date: <2003/12/19 18:46:21 samuel> + * Time-stamp: <2004/04/12 16:27:12 samuel> + * + * <mol.c> + * + * + * + * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#include "config.h" +#include "kernel/kernel.h" +#include "arch/common/nvram.h" +#include "libc/vsprintf.h" +#include "libc/string.h" +#include "mol/mol.h" +#include "osi_calls.h" +#include <stdarg.h> + +void +exit( int status ) +{ + OSI_Exit(); +} + +void +fatal_error( const char *err ) +{ + printk("Fatal error: %s\n", err ); + OSI_Exit(); +} + +void +panic( const char *err ) +{ + printk("Panic: %s\n", err ); + OSI_Exit(); + + /* won't come here... this keeps the gcc happy */ + for( ;; ) + ; +} + + +/************************************************************************/ +/* print using OSI interface */ +/************************************************************************/ + +static int do_indent; + +int +printk( const char *fmt, ... ) +{ + char *p, buf[1024]; + va_list args; + int i; + + va_start(args, fmt); + i = vnsprintf(buf, sizeof(buf), fmt, args); + va_end(args); + + for( p=buf; *p; p++ ) { + if( *p == '\n' ) + do_indent = 0; + if( do_indent++ == 1 ) { + OSI_PutC( '>' ); + OSI_PutC( '>' ); + OSI_PutC( ' ' ); + } + OSI_PutC( *p ); + } + return i; +} + + +/************************************************************************/ +/* TTY iface */ +/************************************************************************/ + +static int ttychar = -1; + +static int +tty_avail( void ) +{ + return OSI_CallAvailable( OSI_TTY_GETC ); +} + +int +availchar( void ) +{ + if( !tty_avail() ) + return 0; + + if( ttychar < 0 ) + ttychar = OSI_TTYGetc(); + if( ttychar < 0 ) + OSI_USleep(1); + return (ttychar >= 0); +} + +int +getchar( void ) +{ + int ch; + + if( !tty_avail() ) + return 0; + + if( ttychar < 0 ) + return OSI_TTYGetc(); + ch = ttychar; + ttychar = -1; + return ch; +} + +int +putchar( int c ) +{ + printk("%c", c ); + + if( tty_avail() ) + OSI_TTYPutc( c ); + return c; +} + + +/************************************************************************/ +/* MOL specific stuff */ +/************************************************************************/ + +int +arch_nvram_size( void ) +{ + return OSI_NVRamSize(); +} + +void +arch_nvram_put( char *buf ) +{ + int i, size = arch_nvram_size(); + + for( i=0; i<size; i++ ) + OSI_WriteNVRamByte( i, buf[i] ); +} + +void +arch_nvram_get( char *buf ) +{ + int i, size = arch_nvram_size(); + + /* support for zapping the nvram */ + if( get_bool_res("zap_nvram") == 1 ) { + memset( buf, 0, size ); + return; + } + + for( i=0; i<size; i++ ) + buf[i] = OSI_ReadNVRamByte( i ); +} diff --git a/qemu/roms/openbios/arch/ppc/mol/mol.fs b/qemu/roms/openbios/arch/ppc/mol/mol.fs new file mode 100644 index 000000000..10c99bd79 --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/mol/mol.fs @@ -0,0 +1,107 @@ + + +\ ------------------------------------------------------------------------- +\ initialization +\ ------------------------------------------------------------------------- + +: make-openable ( path ) + find-dev if + begin ?dup while + \ install trivial open and close methods + dup active-package! is-open + parent + repeat + then +; + +: preopen ( chosen-str node-path ) + 2dup make-openable + + " /chosen" find-device + open-dev ?dup if + encode-int 2swap property + else + 2drop + then +; + +\ preopen device nodes (and store the ihandles under /chosen) +:noname + " memory" " /memory" preopen + " mmu" " /cpus/@0" preopen + " stdout" " /packages/mol-stdout" preopen + " stdin" " keyboard" preopen + " nvram" " /pci/pci-bridge/mac-io/nvram" preopen + " nvram" " /mol/nvram" preopen + +; SYSTEM-initializer + + +\ ------------------------------------------------------------------------- +\ device tree fixing +\ ------------------------------------------------------------------------- + +\ add decode-address methods +: (make-decodable) ( phandle -- ) + + dup " #address-cells" rot get-package-property 0= if + decode-int nip nip + over " decode-unit" rot find-method if 2drop else + ( save phandle ncells ) + + over active-package! + case + 1 of ['] parse-hex " decode-unit" is-xt-func endof + 3 of + " bus-range" active-package get-package-property 0= if + decode-int nip nip + ['] encode-unit-pci " encode-unit" is-xt-func + " decode-unit" is-func-begin + ['] (lit) , , + ['] decode-unit-pci-bus , + is-func-end + then + endof + endcase + then + then + drop +; + +: tree-fixes ( -- ) + active-package + + iterate-tree-begin + begin ?dup while + + dup (make-decodable) + + iterate-tree + repeat + + active-package! +; + +\ use the tty interface if available +: activate-tty-interface + " /mol/mol-tty" find-dev if drop + " /mol/mol-tty" " input-device" $setenv + " /mol/mol-tty" " output-device" $setenv + then +; + +:noname + " keyboard" input +; CONSOLE-IN-initializer + + +\ ------------------------------------------------------------------------- +\ pre-booting +\ ------------------------------------------------------------------------- + +: update-chosen + " /chosen" find-device + stdin @ encode-int " stdin" property + stdout @ encode-int " stdout" property + device-end +; diff --git a/qemu/roms/openbios/arch/ppc/mol/mol.h b/qemu/roms/openbios/arch/ppc/mol/mol.h new file mode 100644 index 000000000..cea15a350 --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/mol/mol.h @@ -0,0 +1,44 @@ +/* + * Creation Date: <2003/12/20 00:20:12 samuel> + * Time-stamp: <2004/03/27 01:52:50 samuel> + * + * <mol.h> + * + * + * + * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#ifndef _H_MOL +#define _H_MOL + +/* video.c */ +extern void init_video( void ); +extern int video_get_res( int *w, int *h ); +extern void draw_pixel( int x, int y, int colind ); +extern void set_color( int index, unsigned long color ); + +/* console.c */ +extern int console_draw_fstr(const char *str, int len); +extern void console_close( void ); + +/* pseudodisk.c */ +extern void pseudodisk_init( void ); + +/* osi-blk.c */ +extern void osiblk_init( void ); + +/* osi-scsi.c */ +extern void osiscsi_init( void ); + +/* pseudofs.c */ +extern void pseudofs_init( void ); + +#include "../kernel.h" + +#endif /* _H_MOL */ diff --git a/qemu/roms/openbios/arch/ppc/mol/osi-blk.c b/qemu/roms/openbios/arch/ppc/mol/osi-blk.c new file mode 100644 index 000000000..4ed1b5ab3 --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/mol/osi-blk.c @@ -0,0 +1,119 @@ +/* + * Creation Date: <2003/12/07 19:08:33 samuel> + * Time-stamp: <2004/01/07 19:38:36 samuel> + * + * <osi-blk.c> + * + * OSI-block interface + * + * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#include "config.h" +#include "libopenbios/bindings.h" +#include "mol/mol.h" +#include "osi_calls.h" + +typedef struct { + int unit; + int channel; +} osiblk_data_t; + + +DECLARE_NODE( osiblk, INSTALL_OPEN, sizeof(osiblk_data_t), + "/pci/pci-bridge/mol-blk/disk", "/mol/mol-blk" ); + + +static void +osiblk_open( osiblk_data_t *pb ) +{ + phandle_t ph; + + fword("my-unit"); + pb->unit = POP(); + pb->channel = 0; /* FIXME */ + + selfword("open-deblocker"); + + /* interpose disk-label */ + ph = find_dev("/packages/disk-label"); + fword("my-args"); + PUSH_ph( ph ); + fword("interpose"); + + /* printk("osi-blk: open %d\n", pb->unit ); */ + PUSH( -1 ); +} + +static void +osiblk_close( osiblk_data_t *pb ) +{ + selfword("close-deblocker"); +} + + +/* ( buf blk nblks -- actual ) */ +static void +osiblk_read_blocks( osiblk_data_t *pb ) +{ + int i, n = POP(); + int blk = POP(); + char *dest = (char*)POP(); + + /* printk("osiblk_read_blocks %x block=%d n=%d\n", (int)dest, blk, n ); */ + + for( i=0; i<n; ) { + char buf[4096]; + int m = MIN( n-i, sizeof(buf)/512 ); + + if( OSI_ABlkSyncRead(pb->channel, pb->unit, blk+i, (int)buf, m*512) < 0 ) { + printk("SyncRead: error\n"); + RET(0); + } + memcpy( dest, buf, m * 512 ); + i += m; + dest += m * 512; + } + PUSH( n ); +} + +/* ( -- bs ) */ +static void +osiblk_block_size( osiblk_data_t *pb ) +{ + PUSH( 512 ); +} + +/* ( -- maxbytes ) */ +static void +osiblk_max_transfer( osiblk_data_t *pb ) +{ + PUSH( 1024*1024 ); +} + +static void +osiblk_initialize( osiblk_data_t *pb ) +{ + fword("is-deblocker"); +} + + +NODE_METHODS( osiblk ) = { + { NULL, osiblk_initialize }, + { "open", osiblk_open }, + { "close", osiblk_close }, + { "read-blocks", osiblk_read_blocks }, + { "block-size", osiblk_block_size }, + { "max-transfer", osiblk_max_transfer }, +}; + +void +osiblk_init( void ) +{ + REGISTER_NODE( osiblk ); +} diff --git a/qemu/roms/openbios/arch/ppc/mol/osi-scsi.c b/qemu/roms/openbios/arch/ppc/mol/osi-scsi.c new file mode 100644 index 000000000..18f3dc577 --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/mol/osi-scsi.c @@ -0,0 +1,271 @@ +/* + * Creation Date: <2003/12/11 21:23:54 samuel> + * Time-stamp: <2004/01/07 19:38:45 samuel> + * + * <osi-scsi.c> + * + * SCSI device node + * + * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#include "config.h" +#include "libopenbios/bindings.h" +#include "mol/mol.h" +#include "scsi_sh.h" +#include "osi_calls.h" + +#define MAX_TARGETS 32 + +typedef struct { + int probed; + int valid; /* a useable device found */ + + int is_cd; + int blocksize; +} target_info_t; + +static target_info_t scsi_devs[ MAX_TARGETS ]; + +typedef struct { + int target; + target_info_t *info; +} instance_data_t; + + +DECLARE_NODE( scsi, INSTALL_OPEN, sizeof(instance_data_t), + "/pci/pci-bridge/mol-scsi/sd", "/mol/mol-scsi/sd" ); + + +static int +scsi_cmd_( instance_data_t *sd, const char *cmd, int cmdlen, char *dest, + int len, int prelen, int postlen ) +{ + char prebuf[4096], postbuf[4096]; + scsi_req_t r[2]; /* the [2] is a hack to get space for the sg-list */ + char sb[32]; + + /* memset( dest, 0, len ); */ + + if( (unsigned int)prelen > sizeof(prebuf) || (unsigned int)postlen > sizeof(postbuf) ) { + printk("bad pre/post len %d %d\n", prelen, postlen ); + return 1; + } + + memset( r, 0, sizeof(r[0]) ); + r->lun = 0; + r->target = sd->target; + r->is_write = 0; + memcpy( r->cdb, cmd, cmdlen ); + r->client_addr = (int)&r; + r->cdb_len = cmdlen; + r->sense[0].base = (int)&sb; + r->sense[0].size = sizeof(sb); + r->size = prelen + len + postlen; + r->n_sg = 3; + r->sglist.n_el = 3; + r->sglist.vec[0].base = (int)prebuf; + r->sglist.vec[0].size = prelen; + r->sglist.vec[1].base = (int)dest; + r->sglist.vec[1].size = len; + r->sglist.vec[2].base = (int)postbuf; + r->sglist.vec[2].size = postlen; + + if( OSI_SCSISubmit((int)&r) ) { + printk("OSI_SCSISubmit: error!\n"); + return 1; + } + while( !OSI_SCSIAck() ) + OSI_USleep( 10 ); + + if( r->adapter_status ) + return -1; + if( r->scsi_status ) + return ((sb[2] & 0xf) << 16) | (sb[12] << 8) | sb[13]; + return 0; +} + +static int +scsi_cmd( instance_data_t *sd, const char *cmd, int cmdlen ) +{ + return scsi_cmd_( sd, cmd, cmdlen, NULL, 0, 0, 0 ); +} + +/* ( buf blk nblks -- actual ) */ +static void +scsi_read_blocks( instance_data_t *sd ) +{ + int nblks = POP(); + int blk = POP(); + char *dest = (char*)POP(); + unsigned char cmd[10]; + int len = nblks * sd->info->blocksize; + + memset( dest, 0, len ); + + /* printk("READ: blk: %d length %d\n", blk, len ); */ + memset( cmd, 0, sizeof(cmd) ); + cmd[0] = 0x28; /* READ_10 */ + cmd[2] = blk >> 24; + cmd[3] = blk >> 16; + cmd[4] = blk >> 8; + cmd[5] = blk; + cmd[7] = nblks >> 8; + cmd[8] = nblks; + + if( scsi_cmd_(sd, cmd, 10, dest, len, 0, 0) ) { + printk("read: scsi_cmd failed\n"); + RET( -1 ); + } + PUSH( nblks ); +} + +static int +inquiry( instance_data_t *sd ) +{ + char inquiry_cmd[6] = { 0x12, 0, 0, 0, 32, 0 }; + char start_stop_unit_cmd[6] = { 0x1b, 0, 0, 0, 1, 0 }; + char test_unit_ready_cmd[6] = { 0x00, 0, 0, 0, 0, 0 }; + char prev_allow_medium_removal[6] = { 0x1e, 0, 0, 0, 1, 0 }; + char set_cd_speed_cmd[12] = { 0xbb, 0, 0xff, 0xff, 0xff, 0xff, + 0, 0, 0, 0, 0, 0 }; + target_info_t *info = &scsi_devs[sd->target]; + char ret[32]; + int i, sense; + + if( sd->target >= MAX_TARGETS ) + return -1; + sd->info = info; + + if( info->probed ) + return info->valid ? 0:-1; + info->probed = 1; + + if( (sense=scsi_cmd_(sd, inquiry_cmd, 6, ret, 2, 0, 0)) ) { + if( sense < 0 ) + return -1; + printk("INQUIRY failed\n"); + return -1; + } + + /* medium present? */ + if( (scsi_cmd(sd, test_unit_ready_cmd, 6) >> 8) == 0x23a ) { + printk("no media\n"); + return -1; + } + + info->is_cd = 0; + info->blocksize = 512; + + if( ret[0] == 5 /* CD/DVD */ ) { + info->blocksize = 2048; + info->is_cd = 1; + + scsi_cmd( sd, prev_allow_medium_removal, 6 ); + scsi_cmd( sd, set_cd_speed_cmd, 12 ); + scsi_cmd( sd, start_stop_unit_cmd, 6 ); + + } else if( ret[0] == 0 /* DISK */ ) { + scsi_cmd( sd, test_unit_ready_cmd, 6 ); + scsi_cmd( sd, start_stop_unit_cmd, 6 ); + } else { + /* don't boot from this device (could be a scanner :-)) */ + return -1; + } + + /* wait for spin-up (or whatever) to complete */ + for( i=0; ; i++ ) { + if( i > 300 ) { + printk("SCSI timeout (sense %x)\n", sense ); + return -1; + } + sense = scsi_cmd( sd, test_unit_ready_cmd, 6 ); + if( (sense & 0xf0000) == 0x20000 ) { + OSI_USleep( 10000 ); + continue; + } + break; + } + + info->valid = 1; + return 0; +} + +/* ( -- success? ) */ +static void +scsi_open( instance_data_t *sd ) +{ + static int once = 0; + phandle_t ph; + + fword("my-unit"); + sd->target = POP(); + + if( !once ) { + once++; + OSI_SCSIControl( SCSI_CTRL_INIT, 0 ); + } + + /* obtiain device information */ + if( inquiry(sd) ) + RET(0); + + selfword("open-deblocker"); + + /* interpose disk-label */ + ph = find_dev("/packages/disk-label"); + fword("my-args"); + PUSH_ph( ph ); + fword("interpose"); + + PUSH( -1 ); +} + +/* ( -- ) */ +static void +scsi_close( instance_data_t *pb ) +{ + selfword("close-deblocker"); +} + + +/* ( -- bs ) */ +static void +scsi_block_size( instance_data_t *sd ) +{ + PUSH( sd->info->blocksize ); +} + +/* ( -- maxbytes ) */ +static void +scsi_max_transfer( instance_data_t *sd ) +{ + PUSH( 1024*1024 ); +} + +static void +scsi_initialize( instance_data_t *sd ) +{ + fword("is-deblocker"); +} + + +NODE_METHODS( scsi ) = { + { NULL, scsi_initialize }, + { "open", scsi_open }, + { "close", scsi_close }, + { "read-blocks", scsi_read_blocks }, + { "block-size", scsi_block_size }, + { "max-transfer", scsi_max_transfer }, +}; + +void +osiscsi_init( void ) +{ + REGISTER_NODE( scsi ); +} diff --git a/qemu/roms/openbios/arch/ppc/mol/prom.c b/qemu/roms/openbios/arch/ppc/mol/prom.c new file mode 100644 index 000000000..0bc8bcfbc --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/mol/prom.c @@ -0,0 +1,175 @@ +/* + * Creation Date: <2002/10/03 20:55:02 samuel> + * Time-stamp: <2002/10/29 13:00:23 samuel> + * + * <prom.c> + * + * oftree interface + * + * Copyright (C) 2002, 2003 Samuel Rydh (samuel@ibrium.se) + * + * 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 + * + */ + +#include "config.h" +#include "osi_calls.h" +#include "mol/prom.h" + +/* OSI_PromClose (free linux side device tree) */ +int +prom_close( void ) +{ + return OSI_PromIface( kPromClose, 0 ); +} + +/* ret: 0 no more peers, -1 if error */ +mol_phandle_t +prom_peer( mol_phandle_t phandle ) +{ + return OSI_PromIface( kPromPeer, phandle ); +} + +/* ret: 0 no child, -1 if error */ +mol_phandle_t +prom_child( mol_phandle_t phandle ) +{ + return OSI_PromIface( kPromChild, phandle ); +} + +/* ret: 0 if root node, -1 if error */ +mol_phandle_t +prom_parent( mol_phandle_t phandle ) +{ + return OSI_PromIface( kPromParent, phandle ); +} + +/* ret: -1 error */ +int +prom_package_to_path( mol_phandle_t phandle, char *buf, long buflen ) +{ + return OSI_PromIface2( kPromPackageToPath, phandle, (int)buf, buflen ); +} + +/* ret: -1 error */ +int +prom_get_prop_len( mol_phandle_t phandle, const char *name ) +{ + return OSI_PromIface1( kPromGetPropLen, phandle, (int)name ); +} + +/* ret: prop len or -1 if error */ +int +prom_get_prop( mol_phandle_t phandle, const char *name, char *buf, long buflen ) +{ + return OSI_PromIface3( kPromGetProp, phandle, (int)name, (int)buf, buflen ); +} + +/* ret: prop len or -1 if error */ +int +prom_get_prop_by_path( const char *path, const char *name, char *buf, long buflen ) +{ + mol_phandle_t ph = prom_find_device(path); + return (ph != -1)? prom_get_prop( ph, name, buf, buflen) : -1; +} + +/* ret: -1 error, 0 last prop, 1 otherwise */ +int +prom_next_prop( mol_phandle_t phandle, const char *prev, char *buf ) +{ + return OSI_PromIface2( kPromNextProp, phandle, (int)prev, (int)buf ); +} + +/* ret: -1 if error */ +int +prom_set_prop( mol_phandle_t phandle, const char *name, char *buf, long buflen ) +{ + return OSI_PromIface3( kPromSetProp, phandle, (int)name, (int)buf, buflen ); +} + +/* ret: -1 if error */ +mol_phandle_t +prom_create_node( const char *path ) +{ + return OSI_PromPathIface( kPromCreateNode, path ); +} + +/* ret: -1 if not found */ +mol_phandle_t +prom_find_device( const char *path ) +{ + mol_phandle_t ph; + char buf2[256], ch, *p; + + if( !path ) + return -1; + + if( (ph=OSI_PromPathIface( kPromFindDevice, path )) != -1 ) + return ph; + else if( path[0] == '/' ) + return -1; + + /* might be an alias */ + if( !(p=strpbrk(path, "@:/")) ) + p = (char*)path + strlen(path); + + ch = *p; + *p = 0; + if( (ph=prom_get_prop(prom_find_device("/aliases"), path, buf2, sizeof(buf2))) == -1 ) + return -1; + *p = ch; + strncat( buf2, p, sizeof(buf2) ); + + if( buf2[0] != '/' ) { + printk("Error: aliases must be absolute!\n"); + return -1; + } + ph = OSI_PromPathIface( kPromFindDevice, buf2 ); + return ph; +} + + + +/************************************************************************/ +/* search the tree for nodes with matching device_type */ +/************************************************************************/ + +static mol_phandle_t +prom_find_device_type_( mol_phandle_t ph, const char *type, int *icount, int index ) +{ + char buf[64]; + int ph2; + + if( ph == -1 || !ph ) + return -1; + if( prom_get_prop( ph, "device_type", buf, sizeof(buf)) > 0 ) + if( !strcmp(buf, type) ) + if( (*icount)++ == index ) + return ph; + if( (ph2=prom_find_device_type_( prom_peer(ph), type, icount, index )) != -1 ) + return ph2; + if( (ph2=prom_find_device_type_( prom_child(ph), type, icount, index )) != -1 ) + return ph2; + return -1; +} + +mol_phandle_t +prom_find_device_type( const char *type, int index ) +{ + int count = 0; + return prom_find_device_type_( prom_peer(0), type, &count, index ); +} + + +/************************************************************************/ +/* device tree tweaking */ +/************************************************************************/ + +/* -1 if error */ +int +prom_change_phandle( mol_phandle_t old_ph, mol_phandle_t new_ph ) +{ + return OSI_PromIface1( kPromChangePHandle, old_ph, (int)new_ph ); +} diff --git a/qemu/roms/openbios/arch/ppc/mol/prom.h b/qemu/roms/openbios/arch/ppc/mol/prom.h new file mode 100644 index 000000000..54a856c27 --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/mol/prom.h @@ -0,0 +1,47 @@ +/* + * Creation Date: <2002/10/03 21:07:27 samuel> + * Time-stamp: <2003/10/22 22:45:26 samuel> + * + * <prom.h> + * + * device tree interface + * + * Copyright (C) 2002, 2003 Samuel Rydh (samuel@ibrium.se) + * + * 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 + * + */ + +#ifndef _H_PROM +#define _H_PROM + +/* Note 1: MOL uses -1 as the invalid phandle while OpenFirmware uses 0 as the + * invalid phandle (it is also the root node). + * + * Note 2: phandles might be negative. For instance, phandles originating from + * a real Open Firmware tree might look like 0xff123000 (a ROM address)... + */ + +typedef enum { kGetRootPhandle=0 } mol_phandle_t; /* must promote to int */ + +extern int prom_close( void ); + +extern mol_phandle_t prom_peer( mol_phandle_t phandle ); +extern mol_phandle_t prom_child( mol_phandle_t phandle ); +extern mol_phandle_t prom_parent( mol_phandle_t phandle ); +extern int prom_package_to_path( mol_phandle_t phandle, char *buf, long buflen ); +extern int prom_get_prop_len( mol_phandle_t phandle, const char *name ); +extern int prom_get_prop( mol_phandle_t phandle, const char *name, char *buf, long buflen ); +extern int prom_get_prop_by_path( const char *path, const char *name, char *buf, long buflen ); +extern int prom_next_prop( mol_phandle_t phandle, const char *prev, char *buf ); +extern int prom_set_prop( mol_phandle_t phandle, const char *name, char *buf, long buflen ); +extern mol_phandle_t prom_create_node( const char *path ); +extern mol_phandle_t prom_find_device( const char *path ); + +extern mol_phandle_t prom_find_device_type( const char *type, int index ); + +extern int prom_change_phandle( mol_phandle_t old_ph, mol_phandle_t new_ph ); + +#endif /* _H_PROM */ diff --git a/qemu/roms/openbios/arch/ppc/mol/pseudodisk.c b/qemu/roms/openbios/arch/ppc/mol/pseudodisk.c new file mode 100644 index 000000000..a98e54845 --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/mol/pseudodisk.c @@ -0,0 +1,178 @@ +/* + * Creation Date: <2003/11/26 16:55:47 samuel> + * Time-stamp: <2004/01/07 19:41:54 samuel> + * + * <pseudodisk.c> + * + * pseudodisk (contains files exported from linux) + * + * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#include "config.h" +#include "libopenbios/bindings.h" +#include "osi_calls.h" +#include "libc/string.h" +#include "libopenbios/ofmem.h" +#include "mol/prom.h" +#include "mol/mol.h" +#include "osi_calls.h" +#include "pseudofs_sh.h" + +typedef struct { + int seekpos; + int fd; + char *myargs; + char *name; + int size; +} pdisk_data_t; + + +DECLARE_NODE( pdisk, INSTALL_OPEN, sizeof(pdisk_data_t), "/mol/pseudo-disk/disk" ); + +static void +pdisk_open( pdisk_data_t *pb ) +{ + char *ep, *name = NULL; + int part; + + pb->myargs = my_args_copy(); + /* printk("pdisk-open: %s\n", pb->myargs ); */ + + part = strtol( pb->myargs, &ep, 10 ); + if( *ep ) { + if( (name=strchr(pb->myargs, ',')) ) { + *name = 0; + name++; + } else { + name = pb->myargs; + } + } + if( part ) + goto err; + + if( !name || !strlen(name) ) + pb->fd = -1; + else { + if( (pb->fd=PseudoFSOpen(name)) < 0 ) + goto err; + pb->size = PseudoFSGetSize( pb->fd ); + } + pb->name = name; + RET( -1 ); + err: + free( pb->myargs ); + RET(0); +} + +/* ( addr len -- actual ) */ +static void +pdisk_read( pdisk_data_t *pb ) +{ + int len = POP(); + char *dest = (char*)POP(); + int cnt; + + if( pb->fd < 0 ) { + memset( dest, 0, len ); + PUSH(len); + return; + } + /* dest is not "mol-DMA" safe (might have a nontrivial mapping) */ + for( cnt=0; cnt<len; ) { + char buf[2048]; + int n = MIN( len-cnt, sizeof(buf) ); + + n = PseudoFSRead( pb->fd, pb->seekpos, buf, n ); + if( n <= 0 ) + break; + + memcpy( dest+cnt, buf, n ); + cnt += n; + pb->seekpos += n; + } + PUSH( cnt ); +} + +/* ( addr len -- actual ) */ +static void +pdisk_write( pdisk_data_t *pb ) +{ + POP(); POP(); PUSH(-1); + printk("pdisk write\n"); +} + +/* ( pos.lo pos.hi -- status ) */ +static void +pdisk_seek( pdisk_data_t *pb ) +{ + int pos_lo; + POP(); + pos_lo = POP(); + + if( pb->fd >= 0 ) { + if( pos_lo == -1 ) + pos_lo = pb->size; + } + + pb->seekpos = pos_lo; + + PUSH(0); /* ??? */ +} + +/* ( -- pos.d ) */ +static void +pdisk_tell( pdisk_data_t *pb ) +{ + DPUSH( pb->seekpos ); +} + +/* ( -- cstr ) */ +static void +pdisk_get_path( pdisk_data_t *pb ) +{ + PUSH( (int)pb->name ); +} + +/* ( -- cstr ) */ +static void +pdisk_get_fstype( pdisk_data_t *pb ) +{ + PUSH( (int)"PSEUDO" ); +} + +/* ( -- cstr ) */ +static void +pdisk_volume_name( pdisk_data_t *pb ) +{ + PUSH( (int)"Virtual Volume" ); +} + +static void +pdisk_block_size( pdisk_data_t *pb ) +{ + PUSH(1); +} + +NODE_METHODS( pdisk ) = { + { "open", pdisk_open }, + { "read", pdisk_read }, + { "write", pdisk_write }, + { "seek", pdisk_seek }, + { "tell", pdisk_tell }, + { "block-size", pdisk_block_size }, + { "get-path", pdisk_get_path }, + { "get-fstype", pdisk_get_fstype }, + { "volume-name", pdisk_volume_name }, +}; + +void +pseudodisk_init( void ) +{ + REGISTER_NODE( pdisk ); +} diff --git a/qemu/roms/openbios/arch/ppc/mol/tree.c b/qemu/roms/openbios/arch/ppc/mol/tree.c new file mode 100644 index 000000000..b82c8c2c8 --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/mol/tree.c @@ -0,0 +1,165 @@ +/* + * Creation Date: <2003/11/18 14:55:05 samuel> + * Time-stamp: <2004/03/27 02:03:55 samuel> + * + * <tree.c> + * + * device tree setup + * + * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#include "config.h" +#include "libopenbios/bindings.h" +#include "mol/mol.h" +#include "mol/prom.h" + + +/************************************************************************/ +/* copy device tree */ +/************************************************************************/ + +static void +copy_node( mol_phandle_t molph ) +{ + char name[40], path[80]; + int exists; + phandle_t ph; + + if( !molph ) + return; + + prom_package_to_path( molph, path, sizeof(path) ); + + /* don't copy /options node */ + if( !strcmp("/options", path) ) { + copy_node( prom_peer(molph) ); + return; + } + + exists = 1; + if( !(ph=find_dev(path)) ) { + exists = 0; + fword("new-device"); + ph = get_cur_dev(); + } + activate_dev( ph ); + + name[0] = 0; + while( prom_next_prop(molph, name, name) > 0 ) { + int len = prom_get_prop_len( molph, name ); + char *p; +#if 0 + if( len > 0x1000 ) { + printk("prop to large (%d)\n", len ); + continue; + } +#endif + /* don't copy /chosen/{stdin,stdout} (XXX: ugly hack...) */ + if( !strcmp("/chosen", path) ) + if( !strcmp("stdio", name) || !strcmp("stdout", name) ) + continue; + + p = malloc( len ); + prom_get_prop( molph, name, p, len ); + set_property( ph, name, p, len ); + free( p ); + } + + set_int_property( ph, "MOL,phandle", molph ); + copy_node( prom_child(molph) ); + + if( !exists ) + fword("finish-device"); + else + activate_device(".."); + + copy_node( prom_peer(molph) ); +} + + + +/************************************************************************/ +/* device tree cloning and tweaking */ +/************************************************************************/ + +static phandle_t +translate_molph( mol_phandle_t molph ) +{ + static mol_phandle_t cached_molph; + static phandle_t cached_ph; + phandle_t ph=0; + + if( cached_molph == molph ) + return cached_ph; + + while( (ph=dt_iterate(ph)) ) + if( get_int_property(ph, "MOL,phandle", NULL) == molph ) + break; + cached_molph = molph; + cached_ph = ph; + + if( !ph ) + printk("failed to translate molph\n"); + return ph; +} + +static void +fix_phandles( void ) +{ + static char *pnames[] = { "interrupt-parent", "interrupt-controller", NULL } ; + int len, *map; + phandle_t ph=0; + char **pp; + + while( (ph=dt_iterate(ph)) ) { + for( pp=pnames; *pp; pp++ ) { + phandle_t *p = (phandle_t*)get_property( ph, *pp, &len ); + if( len == 4 ) + *p = translate_molph( *(int*)p ); + } + + /* need to fix interrupt map properties too */ + if( (map=(int*)get_property(ph, "interrupt-map", &len)) ) { + int i, acells = get_int_property(ph, "#address-cells", NULL); + int icells = get_int_property(ph, "#interrupt-cells", NULL); + + len /= sizeof(int); + for( i=0; i<len; i++ ) { + phandle_t ch_ph; + int ch_acells, ch_icells; + + i += acells + icells; + if( !(ch_ph=translate_molph(map[i])) ) + break; + map[i] = (int)ch_ph; + ch_acells = get_int_property(ch_ph, "#address-cells", NULL); + ch_icells = get_int_property(ch_ph, "#interrupt-cells", NULL); + i += ch_acells + icells; + } + if( i != len ) + printk("interrupt map fixing failure\n"); + } + } + /* delete MOL,phandle properties */ + for( ph=0; (ph=dt_iterate(ph)) ; ) { + push_str("MOL,phandle"); + PUSH_ph(ph); + fword("(delete-property)"); + } + fword("device-end"); +} + +void +devtree_init( void ) +{ + activate_device("/"); + copy_node( prom_peer(0) ); + fix_phandles(); + fword("tree-fixes"); +} diff --git a/qemu/roms/openbios/arch/ppc/mol/tree.fs b/qemu/roms/openbios/arch/ppc/mol/tree.fs new file mode 100644 index 000000000..228163ffc --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/mol/tree.fs @@ -0,0 +1,103 @@ + +: int-property ( val name -- ) + rot encode-int 2swap property +; + + +\ ------------------------------------------------------------- +\ device-tree +\ ------------------------------------------------------------- + +" /" find-device + + " device-tree" device-name + " bootrom" device-type + +\ ------------------------------------------------------------- +\ /memory +\ ------------------------------------------------------------- + +new-device + " memory" device-name + \ 12230 encode-int " reg" property + external + : open true ; + : close ; + \ claim ( phys size align -- base ) + \ release ( phys size -- ) +finish-device + +\ ------------------------------------------------------------- +\ /mol/ +\ ------------------------------------------------------------- + +new-device + " mol" device-name + 1 " #address-cells" int-property + 0 " #size-cells" int-property + + external + : open true ; + : close ; + +new-device + " test" device-name + + external + : open + ." /mol/test opened" cr + " argument-str" " ipose" find-package drop interpose + true + ; +finish-device +finish-device + +\ ------------------------------------------------------------- +\ /cpus/ +\ ------------------------------------------------------------- + +new-device + " cpus" device-name + 1 " #address-cells" int-property + 0 " #size-cells" int-property + + external + : open true ; + : close ; + : decode-unit parse-hex ; + +finish-device + +\ ------------------------------------------------------------- +\ /packages +\ ------------------------------------------------------------- + +" /packages" find-device + + " packages" device-name + external + \ allow packages to be opened with open-dev + : open true ; + : close ; + +\ /packages/mol-stdout +new-device + " mol-stdout" device-name + external + : open true ; + : close ; + : write ( addr len -- actual ) + dup -rot type + ; +finish-device + +\ XXXXXXXXXXXXXXXXXXXXXXX TESTING +" /" find-device +new-device + " test" device-name +finish-device + +\ ------------------------------------------------------------- +\ The END +\ ------------------------------------------------------------- +device-end diff --git a/qemu/roms/openbios/arch/ppc/ofmem.c b/qemu/roms/openbios/arch/ppc/ofmem.c new file mode 100644 index 000000000..c9b066ed6 --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/ofmem.c @@ -0,0 +1,308 @@ +/* + * Creation Date: <1999/11/07 19:02:11 samuel> + * Time-stamp: <2004/01/07 19:42:36 samuel> + * + * <ofmem.c> + * + * OF Memory manager + * + * Copyright (C) 1999-2004 Samuel Rydh (samuel@ibrium.se) + * Copyright (C) 2004 Stefan Reinauer + * + * 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 + * + */ + +/* TODO: Clean up MOLisms in a decent way */ + +#include "config.h" +#include "libopenbios/bindings.h" +#include "libc/string.h" +#include "libopenbios/ofmem.h" +#include "kernel.h" +#ifdef I_WANT_MOLISMS +#include "mol/prom.h" +#include "mol/mol.h" +#endif +#include "mmutypes.h" +#include "asm/processor.h" +#ifdef I_WANT_MOLISMS +#include "osi_calls.h" +#endif + +#define BIT(n) (1U<<(31-(n))) + +/* called from assembly */ +extern void dsi_exception( void ); +extern void isi_exception( void ); +extern void setup_mmu( unsigned long code_base, unsigned long code_size, unsigned long ramsize ); + +/**************************************************************** + * Memory usage (before of_quiesce is called) + * + * Physical + * + * 0x00000000 Exception vectors + * 0x00004000 Free space + * 0x01e00000 Open Firmware (us) + * 0x01f00000 OF allocations + * 0x01ff0000 PTE Hash + * 0x02000000- Free space + * + * Allocations grow downwards from 0x01e00000 + * + ****************************************************************/ + +#define HASH_SIZE (2 << 15) +#define SEGR_BASE 0x400 /* segment number range to use */ + +#define FREE_BASE_1 0x00004000 +#define OF_CODE_START 0x01e00000 +/* #define OF_MALLOC_BASE 0x01f00000 */ +extern char _end[]; +#define OF_MALLOC_BASE _end + +#define HASH_BASE (0x02000000 - HASH_SIZE) +#define FREE_BASE_2 0x02000000 + +#define RAMSIZE 0x02000000 /* XXXXXXXXXXXXXXXXXXX FIXME XXXXXXXXXXXXXXX */ + +static ofmem_t s_ofmem; + +#define IO_BASE 0x80000000 +#define OFMEM (&s_ofmem) + +static inline unsigned long +get_hash_base( void ) +{ + return HASH_BASE; +} + +static inline unsigned long +get_hash_size( void ) +{ + return HASH_SIZE; +} + +static ucell get_heap_top( void ) +{ + return HASH_BASE; +} + +static inline size_t ALIGN_SIZE(size_t x, size_t a) +{ + return (x + a - 1) & ~(a-1); +} + +ofmem_t* ofmem_arch_get_private(void) +{ + return OFMEM; +} + +void* ofmem_arch_get_malloc_base(void) +{ + return OF_MALLOC_BASE; +} + +ucell ofmem_arch_get_heap_top(void) +{ + return get_heap_top(); +} + +ucell ofmem_arch_get_virt_top(void) +{ + return IO_BASE; +} + +void ofmem_arch_unmap_pages(ucell virt, ucell size) +{ + /* kill page mappings in provided range */ +} + +void ofmem_arch_map_pages(ucell phys, ucell virt, ucell size, ucell mode) +{ + /* none yet */ +} + +/************************************************************************/ +/* OF private allocations */ +/************************************************************************/ + +void * +malloc( int size ) +{ + return ofmem_malloc(size); +} + +void +free( void *ptr ) +{ + return ofmem_free(ptr); +} + +void * +realloc( void *ptr, size_t size ) +{ + return ofmem_realloc(ptr, size); +} + + +/************************************************************************/ +/* misc */ +/************************************************************************/ + +ucell ofmem_arch_default_translation_mode( ucell phys ) +{ + /* XXX: Guard bit not set as it should! */ + if( phys < IO_BASE || phys >= 0xffc00000 ) + return 0x02; /*0xa*/ /* wim GxPp */ + return 0x6a; /* WIm GxPp, I/O */ +} + + +/************************************************************************/ +/* page fault handler */ +/************************************************************************/ + +static ucell +ea_to_phys( ucell ea, ucell *mode ) +{ + ucell phys; + + /* hardcode our translation needs */ + if( ea >= OF_CODE_START && ea < FREE_BASE_2 ) { + *mode = ofmem_arch_default_translation_mode( ea ); + return ea; + } + + phys = ofmem_translate(ea, mode); + if( phys == (ucell)-1 ) { +#ifdef I_WANT_MOLISMS + if( ea != 0x80816c00 ) + printk("ea_to_phys: no translation for %08lx, using 1-1\n", ea ); +#endif + phys = ea; + *mode = ofmem_arch_default_translation_mode( phys ); + +#ifdef I_WANT_MOLISMS + forth_segv_handler( (char*)ea ); + OSI_Debugger(1); +#endif + /* print_virt_range(); */ + /* print_phys_range(); */ + /* print_trans(); */ + } + return phys; +} + +static void +hash_page( ucell ea, ucell phys, ucell mode ) +{ + static int next_grab_slot=0; + unsigned long *upte, cmp, hash1; + int i, vsid, found; + mPTE_t *pp; + + vsid = (ea>>28) + SEGR_BASE; + cmp = BIT(0) | (vsid << 7) | ((ea & 0x0fffffff) >> 22); + + hash1 = vsid; + hash1 ^= (ea >> 12) & 0xffff; + hash1 &= (get_hash_size() - 1) >> 6; + + pp = (mPTE_t*)(get_hash_base() + (hash1 << 6)); + upte = (unsigned long*)pp; + + /* replace old translation */ + for( found=0, i=0; !found && i<8; i++ ) + if( cmp == upte[i*2] ) + found=1; + + /* otherwise use a free slot */ + for( i=0; !found && i<8; i++ ) + if( !pp[i].v ) + found=1; + + /* out of slots, just evict one */ + if( !found ) { + i = next_grab_slot + 1; + next_grab_slot = (next_grab_slot + 1) % 8; + } + i--; + upte[i*2] = cmp; + upte[i*2+1] = (phys & ~0xfff) | mode; + + asm volatile( "tlbie %0" :: "r"(ea) ); +} + +void +dsi_exception( void ) +{ + unsigned long dar, dsisr; + ucell mode; + ucell phys; + + asm volatile("mfdar %0" : "=r" (dar) : ); + asm volatile("mfdsisr %0" : "=r" (dsisr) : ); + + //printk("dsi-exception @ %08lx <%08lx>\n", dar, dsisr ); + + phys = ea_to_phys(dar, &mode); + hash_page( dar, phys, mode ); +} + +void +isi_exception( void ) +{ + unsigned long nip, srr1; + ucell mode; + ucell phys; + + asm volatile("mfsrr0 %0" : "=r" (nip) : ); + asm volatile("mfsrr1 %0" : "=r" (srr1) : ); + + //printk("isi-exception @ %08lx <%08lx>\n", nip, srr1 ); + + phys = ea_to_phys(nip, &mode); + hash_page( nip, phys, mode ); +} + + +/************************************************************************/ +/* init / cleanup */ +/************************************************************************/ + +void +setup_mmu( unsigned long code_base, unsigned long code_size, unsigned long ramsize ) +{ + unsigned long sdr1 = HASH_BASE | ((HASH_SIZE-1) >> 16); + unsigned long sr_base = (0x20 << 24) | SEGR_BASE; + unsigned long msr; + int i; + + asm volatile("mtsdr1 %0" :: "r" (sdr1) ); + for( i=0; i<16; i++ ) { + int j = i << 28; + asm volatile("mtsrin %0,%1" :: "r" (sr_base + i), "r" (j) ); + } + asm volatile("mfmsr %0" : "=r" (msr) : ); + msr |= MSR_IR | MSR_DR; + asm volatile("mtmsr %0" :: "r" (msr) ); +} + +void +ofmem_init( void ) +{ + ofmem_t *ofmem = OFMEM; + /* In case we can't rely on memory being zero initialized */ + memset(ofmem, 0, sizeof(ofmem)); + + ofmem->ramsize = RAMSIZE; + + ofmem_claim_phys( 0, FREE_BASE_1, 0 ); + ofmem_claim_virt( 0, FREE_BASE_1, 0 ); + ofmem_claim_phys( OF_CODE_START, FREE_BASE_2 - OF_CODE_START, 0 ); + ofmem_claim_virt( OF_CODE_START, FREE_BASE_2 - OF_CODE_START, 0 ); +} diff --git a/qemu/roms/openbios/arch/ppc/osi.h b/qemu/roms/openbios/arch/ppc/osi.h new file mode 100644 index 000000000..3baae1575 --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/osi.h @@ -0,0 +1,170 @@ +/* + * Creation Date: <1999/03/18 03:19:43 samuel> + * Time-stamp: <2003/12/26 16:58:19 samuel> + * + * <os_interface.h> + * + * This file includes definitions for drivers + * running in the "emulated" OS. (Mainly the 'sc' + * mechanism of communicating) + * + * Copyright (C) 1999, 2000, 2001, 2002, 2003 Samuel Rydh (samuel@ibrium.se) + * + * 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 + * + */ + +#ifndef _H_OSI +#define _H_OSI + +/* Magic register values loaded into r3 and r4 before the 'sc' assembly instruction */ +#define OSI_SC_MAGIC_R3 0x113724FA +#define OSI_SC_MAGIC_R4 0x77810F9B + + +/************************************************************************/ +/* Selectors (passed in r5) */ +/************************************************************************/ + +#define OSI_CALL_AVAILABLE 0 +#define OSI_DEBUGGER 1 /* enter debugger */ +/* obsolete OSI_LOG_STR 3 */ +#define OSI_CMOUNT_DRV_VOL 4 /* conditionally mount driver volume */ +/* obsolete OSI_SCSI_xxx 5-6 */ +#define OSI_GET_GMT_TIME 7 +#define OSI_MOUSE_CNTRL 8 +#define OSI_GET_LOCALTIME 9 /* return time in secs from 01/01/04 */ + +#define OSI_ENET_OPEN 10 +#define OSI_ENET_CLOSE 11 +#define OSI_ENET_GET_ADDR 12 +#define OSI_ENET_GET_STATUS 13 +#define OSI_ENET_CONTROL 14 +#define OSI_ENET_ADD_MULTI 16 +#define OSI_ENET_DEL_MULTI 17 +#define OSI_ENET_GET_PACKET 18 +#define OSI_ENET_SEND_PACKET 19 + +#define OSI_OF_INTERFACE 20 +#define OSI_OF_TRAP 21 +#define OSI_OF_RTAS 22 + +#define OSI_SCSI_CNTRL 23 +#define OSI_SCSI_SUBMIT 24 +#define OSI_SCSI_ACK 25 + +#define OSI_GET_MOUSE 26 /* -- r3 status, r4-r8 mouse data */ +#define OSI_ACK_MOUSE_IRQ 27 /* -- int */ + +#define OSI_SET_VMODE 28 /* modeID, depth -- error */ +#define OSI_GET_VMODE_INFO 29 /* mode, depth -- r3 status, r4-r9 pb */ +#define OSI_GET_MOUSE_DPI 30 /* -- mouse_dpi */ + +#define OSI_SET_VIDEO_POWER 31 +#define OSI_GET_FB_INFO 32 /* void -- r3 status, r4-r8 video data */ + +#define OSI_SOUND_WRITE 33 +/* #define OSI_SOUND_FORMAT 34 */ +#define OSI_SOUND_SET_VOLUME 35 +#define OSI_SOUND_CNTL 36 +/* obsolete OSI_SOUND call 37 */ + +#define OSI_VIDEO_ACK_IRQ 38 +#define OSI_VIDEO_CNTRL 39 + +#define OSI_SOUND_IRQ_ACK 40 +#define OSI_SOUND_START_STOP 41 + +#define OSI_REGISTER_IRQ 42 /* reg_property[0] appl_int -- irq_cookie */ +/* obsolete OSI_IRQ 43-46 */ + +#define OSI_LOG_PUTC 47 /* char -- */ + +#define OSI_KBD_CNTRL 50 +#define OSI_GET_ADB_KEY 51 /* -- adb_keycode (keycode | keycode_id in r4) */ + +#define OSI_WRITE_NVRAM_BYTE 52 /* offs, byte -- */ +#define OSI_READ_NVRAM_BYTE 53 /* offs -- byte */ + +#define OSI_EXIT 54 + +#define OSI_KEYCODE_TO_ADB 55 /* (keycode | keycode_id) -- adb_keycode */ +#define OSI_MAP_ADB_KEY 56 /* keycode, adbcode -- */ +#define OSI_SAVE_KEYMAPPING 57 /* -- */ +#define OSI_USLEEP 58 /* usecs -- */ +#define OSI_SET_COLOR 59 /* index value -- */ + +#define OSI_PIC_MASK_IRQ 60 /* irq -- */ +#define OSI_PIC_UNMASK_IRQ 61 /* irq -- */ +#define OSI_PIC_ACK_IRQ 62 /* irq mask_flag -- */ +#define OSI_PIC_GET_ACTIVE_IRQ 63 + +#define OSI_GET_COLOR 64 /* index -- value */ + +/* 65-67 old ablk implementation */ +#define OSI_IRQTEST 65 + +#define OSI_ENET2_OPEN 68 +#define OSI_ENET2_CLOSE 69 +#define OSI_ENET2_CNTRL 70 +#define OSI_ENET2_RING_SETUP 71 +#define OSI_ENET2_KICK 72 +#define OSI_ENET2_GET_HWADDR 73 +#define OSI_ENET2_IRQ_ACK 74 + +#define OSI_PROM_IFACE 76 +#define kPromClose 0 +#define kPromPeer 1 +#define kPromChild 2 +#define kPromParent 3 +#define kPromPackageToPath 4 +#define kPromGetPropLen 5 +#define kPromGetProp 6 +#define kPromNextProp 7 +#define kPromSetProp 8 +#define kPromChangePHandle 9 + +#define OSI_PROM_PATH_IFACE 77 +#define kPromCreateNode 16 +#define kPromFindDevice 17 + +#define OSI_BOOT_HELPER 78 +#define kBootHAscii2Unicode 32 +#define kBootHUnicode2Ascii 33 +#define kBootHGetStrResInd 34 /* key, buf, len -- buf */ +#define kBootHGetRAMSize 35 /* -- ramsize */ + +#define OSI_ABLK_RING_SETUP 79 +#define OSI_ABLK_CNTRL 80 +#define OSI_ABLK_DISK_INFO 81 +#define OSI_ABLK_KICK 82 +#define OSI_ABLK_IRQ_ACK 83 +#define OSI_ABLK_SYNC_READ 84 +#define OSI_ABLK_SYNC_WRITE 85 +#define OSI_ABLK_BLESS_DISK 86 + +#define OSI_EMUACCEL 89 /* EMULATE_xxx, nip -- index */ +#define OSI_MAPIN_MREGS 90 /* mphys */ +#define OSI_NVRAM_SIZE 91 + +#define OSI_MTICKS_TO_USECS 92 +#define OSI_USECS_TO_MTICKS 93 + +/* obsolete OSI_BLK 94-95 */ + +#define OSI_PSEUDO_FS 96 +#define kPseudoFSOpen 1 +#define kPseudoFSClose 2 +#define kPseudoFSGetSize 3 +#define kPseudoFSRead 4 +#define kPseudoFSIndex2Name 5 + +#define OSI_TTY_PUTC 97 +#define OSI_TTY_GETC 98 +#define OSI_TTY_IRQ_ACK 99 + +#define NUM_OSI_SELECTORS 100 /* remember to increase this... */ + +#endif /* _H_OSI */ diff --git a/qemu/roms/openbios/arch/ppc/osi_calls.h b/qemu/roms/openbios/arch/ppc/osi_calls.h new file mode 100644 index 000000000..1d6b3dc5e --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/osi_calls.h @@ -0,0 +1,454 @@ +/* + * Creation Date: <2002/06/16 01:40:57 samuel> + * Time-stamp: <2003/12/26 17:02:09 samuel> + * + * <osi_calls.h> + * + * OSI call inlines + * + * Copyright (C) 2002, 2003 Samuel Rydh (samuel@ibrium.se) + * + * 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 + * + */ + +#ifndef _H_OSI_CALLS +#define _H_OSI_CALLS + +#include "osi.h" + +/* Old gcc versions have a limit on the number of registers used. + * Newer gcc versions (gcc 3.3) require that the clobber list does + * not overlap declared registers. + */ +#if __GNUC__ == 2 || ( __GNUC__ == 3 && __GNUC_MINOR__ < 3 ) +#define SHORT_REGLIST +#endif + + +/************************************************************************/ +/* OSI call instantiation macros */ +/************************************************************************/ + +#define dreg(n) __oc_##n __asm__ (#n) +#define ir(n) "r" (__oc_##n) +#define rr(n) "=r" (__oc_##n) + +#define _oc_head( input_regs... ) \ +{ \ + int _ret=0; \ + { \ + register unsigned long dreg(r3); \ + register unsigned long dreg(r4); \ + register unsigned long dreg(r5) \ + ,##input_regs ; + +#define _oc_syscall( number, extra_ret_regs... ) \ + __oc_r3 = OSI_SC_MAGIC_R3; \ + __oc_r4 = OSI_SC_MAGIC_R4; \ + __oc_r5 = number; \ + __asm__ __volatile__ ( \ + "sc " : rr(r3) ,## extra_ret_regs + +#define _oc_input( regs... ) \ + : ir(r3), ir(r4), ir(r5) \ + , ## regs \ + : "memory" ); + +/* the tail memory clobber is necessary since we violate the strict + * aliasing rules when we return structs through the registers. + */ +#define _oc_tail \ + asm volatile ( "" : : : "memory" ); \ + _ret = __oc_r3; \ + } \ + return _ret; \ +} + + +/************************************************************************/ +/* Alternatives */ +/************************************************************************/ + +#ifdef SHORT_REGLIST +#define _oc_syscall_r10w6( number, inputregs... ) \ + __oc_r3 = OSI_SC_MAGIC_R3; \ + __oc_r4 = OSI_SC_MAGIC_R4; \ + __oc_r5 = number; \ + __asm__ __volatile__ ( \ + "sc \n" \ + "stw 4,0(10) \n" \ + "stw 5,4(10) \n" \ + "stw 6,8(10) \n" \ + "stw 7,12(10) \n" \ + "stw 8,16(10) \n" \ + "stw 9,20(10) \n" \ + : rr(r3) \ + : ir(r3), ir(r4), ir(r5), ir(r10) \ + ,## inputregs \ + : "memory", \ + "r4", "r5", "r6", "r7", "r8", "r9" ); +#endif + + +/************************************************************************/ +/* Common helper functions */ +/************************************************************************/ + +#define _osi_call0( type, name, number ) \ +type name( void ) \ + _oc_head() \ + _oc_syscall( number ) \ + _oc_input() \ + _oc_tail + +#define _osi_call1( type, name, number, type1, arg1 ) \ +type name( type1 arg1 ) \ + _oc_head( dreg(r6) ) \ + __oc_r6 = (unsigned long)arg1; \ + _oc_syscall( number ) \ + _oc_input( ir(r6) ) \ + _oc_tail + +#define _osi_call2( type, name, number, t1, a1, t2, a2 ) \ +type name( t1 a1, t2 a2 ) \ + _oc_head( dreg(r6), dreg(r7) ) \ + __oc_r6 = (unsigned long)a1; \ + __oc_r7 = (unsigned long)a2; \ + _oc_syscall( number ) \ + _oc_input( ir(r6), ir(r7) ) \ + _oc_tail + +#define _osi_call3( type, name, number, t1, a1, t2, a2, t3, a3 ) \ +type name( t1 a1, t2 a2, t3 a3 ) \ + _oc_head( dreg(r6), dreg(r7), dreg(r8) ) \ + __oc_r6 = (unsigned long)a1; \ + __oc_r7 = (unsigned long)a2; \ + __oc_r8 = (unsigned long)a3; \ + _oc_syscall( number ) \ + _oc_input( ir(r6), ir(r7), ir(r8) ) \ + _oc_tail + +#define _osi_call4( type, name, number, t1, a1, t2, a2, t3, a3, t4, a4 ) \ +type name( t1 a1, t2 a2, t3 a3, t4 a4 ) \ + _oc_head( dreg(r6), dreg(r7), dreg(r8), dreg(r9) ) \ + __oc_r6 = (unsigned long)a1; \ + __oc_r7 = (unsigned long)a2; \ + __oc_r8 = (unsigned long)a3; \ + __oc_r9 = (unsigned long)a4; \ + _oc_syscall( number ) \ + _oc_input( ir(r6), ir(r7), ir(r8), ir(r9) ) \ + _oc_tail + +#define _osi_call5( type, name, number, t1, a1, t2, a2, t3, a3, t4, a4, t5, a5 ) \ +type name( t1 a1, t2 a2, t3 a3, t4 a4, t5 a5 ) \ + _oc_head( dreg(r6), dreg(r7), dreg(r8), dreg(r9), dreg(r10) ) \ + __oc_r6 = (unsigned long)a1; \ + __oc_r7 = (unsigned long)a2; \ + __oc_r8 = (unsigned long)a3; \ + __oc_r9 = (unsigned long)a4; \ + __oc_r10 = (unsigned long)a5; \ + _oc_syscall( number ) \ + _oc_input( ir(r6), ir(r7), ir(r8), ir(r9), ir(r10) ) \ + _oc_tail + +#define _osi_call6( type, name, number, t1, a1, t2, a2, t3, a3, t4, a4, t5, a5, t6, a6 ) \ +type name( t1 a1, t2 a2, t3 a3, t4 a4, t5 a5, t6 a6 ) \ + _oc_head( dreg(r6), dreg(r7), dreg(r8), dreg(r9), dreg(r10), dreg(r11) )\ + __oc_r6 = (unsigned long)a1; \ + __oc_r7 = (unsigned long)a2; \ + __oc_r8 = (unsigned long)a3; \ + __oc_r9 = (unsigned long)a4; \ + __oc_r10 = (unsigned long)a5; \ + __oc_r11 = (unsigned long)a6; \ + _oc_syscall( number ) \ + _oc_input( ir(r6), ir(r7), ir(r8), ir(r9), ir(r10), ir(r11) ) \ + _oc_tail + + +/************************************************************************/ +/* Special */ +/************************************************************************/ + +/* r4 returned in retarg1 pointer */ +#define _osi_call0_w1( type, name, number, type1, retarg1 ) \ +type name( type1 retarg1 ) \ + _oc_head() \ + _oc_syscall( number, rr(r4) ) \ + _oc_input() \ + *retarg1 = __oc_r4; \ + _oc_tail + +#define _osi_call0_w2( type, name, number, type1, retarg1 ) \ +type name( type1 retarg1 ) \ + _oc_head() \ + _oc_syscall( number, rr(r4), rr(r5) ) \ + _oc_input() \ + ((unsigned long*)retarg1)[0] = __oc_r4; \ + ((unsigned long*)retarg1)[1] = __oc_r5; \ + _oc_tail + +/* r4-r8 returned in retarg1 pointer */ +#define _osi_call0_w5( type, name, number, type1, retarg1 ) \ +type name( type1 retarg1 ) \ + _oc_head( dreg(r6), dreg(r7), dreg(r8) ) \ + _oc_syscall( number, \ + rr(r4), rr(r5), rr(r6), rr(r7), rr(r8) ) \ + _oc_input() \ + ((unsigned long*)retarg1)[0] = __oc_r4; \ + ((unsigned long*)retarg1)[1] = __oc_r5; \ + ((unsigned long*)retarg1)[2] = __oc_r6; \ + ((unsigned long*)retarg1)[3] = __oc_r7; \ + ((unsigned long*)retarg1)[4] = __oc_r8; \ + _oc_tail + +/* r4 returned in retarg pointer */ +#define _osi_call1_w1( type, name, number, t1, a1, t2, retarg ) \ +type name( t1 a1, t2 retarg ) \ + _oc_head( dreg(r6) ) \ + __oc_r6 = (unsigned long)a1; \ + _oc_syscall( number, rr(r4) ) \ + _oc_input( ir(r6) ) \ + ((unsigned long*)retarg)[0] = __oc_r4; \ + _oc_tail + +/* r4,r5 returned in retarg1, retarg2 */ +#define _osi_call1_w1w1( type, name, number, t1, a1, t2, retarg1, t3, retarg2 ) \ +type name( t1 a1, t2 retarg1, t3 retarg2 ) \ + _oc_head( dreg(r6) ) \ + __oc_r6 = (unsigned long)a1; \ + _oc_syscall( number, rr(r4), rr(r5) ) \ + _oc_input( ir(r6) ) \ + ((unsigned long*)retarg1)[0] = __oc_r4; \ + ((unsigned long*)retarg2)[0] = __oc_r5; \ + _oc_tail + +/* r4,r5 returned in retarg1, retarg2, retarg3 */ +#define _osi_call1_w1w1w1( type, name, number, t1, a1, t2, retarg1, t3, retarg2, t4, retarg3 ) \ +type name( t1 a1, t2 retarg1, t3 retarg2, t4 retarg3 ) \ + _oc_head( dreg(r6) ) \ + __oc_r6 = (unsigned long)a1; \ + _oc_syscall( number, rr(r4), rr(r5), rr(r6) ) \ + _oc_input( ir(r6) ) \ + ((unsigned long*)retarg1)[0] = __oc_r4; \ + ((unsigned long*)retarg2)[0] = __oc_r5; \ + ((unsigned long*)retarg3)[0] = __oc_r6; \ + _oc_tail + +/* r4,r5 returned in retarg pointer */ +#define _osi_call1_w2( type, name, number, t1, a1, t2, retarg ) \ +type name( t1 a1, t2 retarg ) \ + _oc_head( dreg(r6) ) \ + __oc_r6 = (unsigned long)a1; \ + _oc_syscall( number, rr(r4), rr(r5) ) \ + _oc_input( ir(r6) ) \ + ((unsigned long*)retarg)[0] = __oc_r4; \ + ((unsigned long*)retarg)[1] = __oc_r5; \ + _oc_tail + +/* r4-r7 returned in retarg pointer */ +#define _osi_call1_w4( type, name, number, t1, a1, t2, retarg ) \ +type name( t1 a1, t2 retarg ) \ + _oc_head( dreg(r6), dreg(r7) ) \ + __oc_r6 = (unsigned long)a1; \ + _oc_syscall( number, rr(r4), rr(r5), rr(r6), rr(r7) ) \ + _oc_input( ir(r6) ) \ + ((unsigned long*)retarg)[0] = __oc_r4; \ + ((unsigned long*)retarg)[1] = __oc_r5; \ + ((unsigned long*)retarg)[2] = __oc_r6; \ + ((unsigned long*)retarg)[3] = __oc_r7; \ + _oc_tail + + +/* r4-r5 returned in retarg pointer */ +#define _osi_call2_w2( type, name, number, t1, a1, t2, a2, t3, retarg ) \ +type name( t1 a1, t2 a2, t3 retarg ) \ + _oc_head( dreg(r6), dreg(r7) ) \ + __oc_r6 = (unsigned long)a1; \ + __oc_r7 = (unsigned long)a2; \ + _oc_syscall( number, rr(r4), rr(r5) ) \ + _oc_input( ir(r6), ir(r7) ) \ + ((unsigned long*)retarg)[0] = __oc_r4; \ + ((unsigned long*)retarg)[1] = __oc_r5; \ + _oc_tail + +/* r4-r7 returned in retarg pointer */ +#define _osi_call2_w4( type, name, number, t1, a1, t2, a2, t3, retarg ) \ +type name( t1 a1, t2 a2, t3 retarg ) \ + _oc_head( dreg(r6), dreg(r7) ) \ + __oc_r6 = (unsigned long)a1; \ + __oc_r7 = (unsigned long)a2; \ + _oc_syscall( number, rr(r4), rr(r5), rr(r6), rr(r7) ) \ + _oc_input( ir(r6), ir(r7) ) \ + ((unsigned long*)retarg)[0] = __oc_r4; \ + ((unsigned long*)retarg)[1] = __oc_r5; \ + ((unsigned long*)retarg)[2] = __oc_r6; \ + ((unsigned long*)retarg)[3] = __oc_r7; \ + _oc_tail + +#ifdef SHORT_REGLIST +/* r4-r9 returned in retarg pointer */ +#define _osi_call2_w6( type, name, number, t1, a1, t2, a2, t3, retarg ) \ +type name( t1 a1, t2 a2, t3 retarg ) \ + _oc_head( dreg(r6), dreg(r7), dreg(r10) ) \ + __oc_r6 = (unsigned long)a1; \ + __oc_r7 = (unsigned long)a2; \ + __oc_r10 = (unsigned long)retarg; \ + _oc_syscall_r10w6( number, ir(r6), ir(r7) ) \ + _oc_tail + +#else /* SHORT_REGLIST */ + +/* r4-r9 returned in retarg pointer */ +#define _osi_call2_w6( type, name, number, t1, a1, t2, a2, t3, retarg ) \ +type name( t1 a1, t2 a2, t3 retarg ) \ + _oc_head( dreg(r6), dreg(r7), dreg(r8), dreg(r9) ) \ + __oc_r6 = (unsigned long)a1; \ + __oc_r7 = (unsigned long)a2; \ + _oc_syscall( number, rr(r4), rr(r5), rr(r6), rr(r7), rr(r8), rr(r9) ) \ + _oc_input( ir(r6), ir(r7) ) \ + ((unsigned long*)retarg)[0] = __oc_r4; \ + ((unsigned long*)retarg)[1] = __oc_r5; \ + ((unsigned long*)retarg)[2] = __oc_r6; \ + ((unsigned long*)retarg)[3] = __oc_r7; \ + ((unsigned long*)retarg)[4] = __oc_r8; \ + ((unsigned long*)retarg)[5] = __oc_r9; \ + _oc_tail + +#endif /* SHORT_REGLIST */ + + +/************************************************************************/ +/* OSI call inlines */ +/************************************************************************/ + +static inline _osi_call1( int, OSI_CallAvailable, OSI_CALL_AVAILABLE, int, osi_num ); + +static inline _osi_call1( int, OSI_PutC, OSI_LOG_PUTC, int, ch ); + +static inline _osi_call1( int, OSI_Debugger, OSI_DEBUGGER, int, num ); +static inline _osi_call0( int, OSI_Exit, OSI_EXIT ); + +/* misc */ +static inline _osi_call0( unsigned long, OSI_GetLocalTime, OSI_GET_LOCALTIME ); +static inline _osi_call0( unsigned long, OSI_GetGMTTime, OSI_GET_GMT_TIME ); +static inline _osi_call1( int, OSI_USleep, OSI_USLEEP, int, usecs ); + +/* NVRAM */ +static inline _osi_call0( int, OSI_NVRamSize, OSI_NVRAM_SIZE ); +static inline _osi_call1( int, OSI_ReadNVRamByte, OSI_READ_NVRAM_BYTE, int, offs ); +static inline _osi_call2( int, OSI_WriteNVRamByte, OSI_WRITE_NVRAM_BYTE, int, offs, + unsigned char, ch ); + +/* keyboard stuff */ +static inline _osi_call0_w1( int, OSI_GetAdbKey2, OSI_GET_ADB_KEY, int *, raw_key ); +static inline _osi_call1( int, OSI_KbdCntrl, OSI_KBD_CNTRL, int, cmd ); + +static inline int OSI_GetAdbKey( void ) + { int dummy_raw_key; return OSI_GetAdbKey2( &dummy_raw_key ); } +static inline _osi_call2( int, OSI_MapAdbKey, OSI_MAP_ADB_KEY, int, keycode, int, adbkey ) +static inline _osi_call1( int, OSI_KeycodeToAdb, OSI_KEYCODE_TO_ADB, int, keycode ); +static inline _osi_call0( int, OSI_SaveKeymapping, OSI_SAVE_KEYMAPPING ); + +/* mouse support */ +struct osi_mouse; +static inline _osi_call0_w5( int, OSI_GetMouse, OSI_GET_MOUSE, struct osi_mouse *, ret ); +static inline _osi_call0( int, OSI_GetMouseDPI, OSI_GET_MOUSE_DPI ); + +/* video */ +static inline _osi_call2( int, OSI_SetVMode_, OSI_SET_VMODE, int, mode, int, depth_mode ); +struct osi_get_vmode_info; +static inline _osi_call2_w6( int, OSI_GetVModeInfo_, OSI_GET_VMODE_INFO, int, mode, int, depth_mode, + struct osi_get_vmode_info *, ret ); +static inline _osi_call1( int, OSI_SetVPowerState, OSI_SET_VIDEO_POWER, int, power_state ); +static inline _osi_call2( int, OSI_SetColor, OSI_SET_COLOR, int, index, int, rgb ); +static inline _osi_call0_w1( int, OSI_VideoAckIRQ, OSI_VIDEO_ACK_IRQ, int *, events ); + +static inline void OSI_RefreshPalette( void ) { OSI_SetColor(-1,0); } + +/* PIC (mac-io replacement) */ +static inline _osi_call1( int, OSI_PICMaskIRQ, OSI_PIC_MASK_IRQ, int, irq ); +static inline _osi_call1( int, OSI_PICUnmaskIRQ, OSI_PIC_UNMASK_IRQ, int, irq ); +static inline _osi_call2( int, OSI_PICAckIRQ, OSI_PIC_ACK_IRQ, int, irq, int, mask_it ); +static inline _osi_call0( int, OSI_PICGetActiveIRQ, OSI_PIC_GET_ACTIVE_IRQ ); + +/* sound */ +static inline _osi_call1( int, OSI_SoundCntl, OSI_SOUND_CNTL, int, cmd ); +static inline _osi_call2( int, OSI_SoundCntl1, OSI_SOUND_CNTL, int, cmd, int, p1 ); +static inline _osi_call3( int, OSI_SoundCntl2, OSI_SOUND_CNTL, int, cmd, int, p1, int, p2 ); +static inline _osi_call0_w2( int, OSI_SoundIRQAck, OSI_SOUND_IRQ_ACK, unsigned long *, timestamp ); +static inline _osi_call3( int, OSI_SoundWrite, OSI_SOUND_WRITE, int, physbuf, int, len, int, restart ); +static inline _osi_call3( int, OSI_SoundSetVolume, OSI_SOUND_SET_VOLUME, int, hwvol, int, speakervol, int, mute ); + +/* async block driver */ +struct ablk_disk_info; +static inline _osi_call2_w4( int, OSI_ABlkDiskInfo, OSI_ABLK_DISK_INFO, int, channel, int, unit, + struct ablk_disk_info *, retinfo ); +static inline _osi_call1( int, OSI_ABlkKick, OSI_ABLK_KICK, int, channel ); +static inline _osi_call1_w1w1w1( int, OSI_ABlkIRQAck, OSI_ABLK_IRQ_ACK, int, channel, int *, req_count, + int *, active, int *, events ); +static inline _osi_call3( int, OSI_ABlkRingSetup, OSI_ABLK_RING_SETUP, int, channel, int, mphys, int, n_el ); +static inline _osi_call2( int, OSI_ABlkCntrl, OSI_ABLK_CNTRL, int, channel, int, cmd ); +static inline _osi_call3( int, OSI_ABlkCntrl1, OSI_ABLK_CNTRL, int, channel, int, cmd, int, param ); +static inline _osi_call5( int, OSI_ABlkSyncRead, OSI_ABLK_SYNC_READ, int, channel, int, unit, + int, blk, unsigned long, mphys, int, size ); +static inline _osi_call5( int, OSI_ABlkSyncWrite, OSI_ABLK_SYNC_WRITE, int, channel, int, unit, + int, blk, unsigned long, mphys, int, size ); +static inline _osi_call2( int, OSI_ABlkBlessDisk, OSI_ABLK_BLESS_DISK, int, channel, int, unit ); + +static inline _osi_call0( int, OSI_CMountDrvVol, OSI_CMOUNT_DRV_VOL ); + +/* enet2 */ +static inline _osi_call0( int, OSI_Enet2Open, OSI_ENET2_OPEN ); +static inline _osi_call0( int, OSI_Enet2Close, OSI_ENET2_CLOSE ); +static inline _osi_call3( int, OSI_Enet2RingSetup, OSI_ENET2_RING_SETUP, int, which_ring, + int, ring_mphys, int, n_el ); +static inline _osi_call2( int, OSI_Enet2Cntrl1, OSI_ENET2_CNTRL, int, cmd, int, param ); +static inline _osi_call1( int, OSI_Enet2Cntrl, OSI_ENET2_CNTRL, int, cmd ); +static inline _osi_call0( int, OSI_Enet2Kick, OSI_ENET2_KICK ); + +static inline _osi_call0_w2( int, OSI_Enet2GetHWAddr__, OSI_ENET2_GET_HWADDR, unsigned long *, retbuf ); +static inline int OSI_Enet2GetHWAddr( unsigned char *addr ) { + int ret; + unsigned long buf[2]; + + ret = OSI_Enet2GetHWAddr__( buf ); + + ((unsigned long*)addr)[0] = buf[0]; + ((unsigned short*)addr)[2] = (buf[1] >> 16); + return ret; +} +static inline _osi_call2( int, OSI_Enet2IRQAck, OSI_ENET2_IRQ_ACK, int, irq_enable, int, rx_head ); + +/* PROM (device-tree) */ +static inline _osi_call2( int, OSI_PromIface, OSI_PROM_IFACE, int, what, int, ph ); +static inline _osi_call3( int, OSI_PromIface1, OSI_PROM_IFACE, int, what, int, ph, int, p1 ); +static inline _osi_call4( int, OSI_PromIface2, OSI_PROM_IFACE, int, what, int, ph, int, p1, int, p2 ); +static inline _osi_call5( int, OSI_PromIface3, OSI_PROM_IFACE, int, what, int, ph, int, p1, int, p2, int, p3 ); +static inline _osi_call2( int, OSI_PromPathIface, OSI_PROM_PATH_IFACE, int, what, const char *, p ); + +/* emulation acceleration */ +static inline _osi_call1( int, OSI_MapinMregs, OSI_MAPIN_MREGS, unsigned long, mphys ); +static inline _osi_call3( int, OSI_EmuAccel, OSI_EMUACCEL, int, emuaccel_flags, int, param, int, inst_addr ); + +/* timer frequency */ +static inline _osi_call1( int, OSI_MticksToUsecs, OSI_MTICKS_TO_USECS, unsigned long, mticks ); +static inline _osi_call1( int, OSI_UsecsToMticks, OSI_USECS_TO_MTICKS, unsigned long, usecs ); + +/* fb info */ +struct osi_fb_info; +static inline _osi_call0_w5( int, OSI_GetFBInfo, OSI_GET_FB_INFO, struct osi_fb_info *, retinfo ); + +/* SCSI */ +static inline _osi_call0( int, OSI_SCSIAck, OSI_SCSI_ACK ); +static inline _osi_call1( int, OSI_SCSISubmit, OSI_SCSI_SUBMIT, int, req_mphys ); +static inline _osi_call2( int, OSI_SCSIControl, OSI_SCSI_CNTRL, int, sel, int, param ); + +/* TTY */ +static inline _osi_call0( int, OSI_TTYGetc, OSI_TTY_GETC ); +static inline _osi_call1( int, OSI_TTYPutc, OSI_TTY_PUTC, int, ch ); +static inline _osi_call0( int, OSI_TTYIRQAck, OSI_TTY_IRQ_ACK ); + +#endif /* _H_OSI_CALLS */ diff --git a/qemu/roms/openbios/arch/ppc/pearpc/console.c b/qemu/roms/openbios/arch/ppc/pearpc/console.c new file mode 100644 index 000000000..3869cbab5 --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/pearpc/console.c @@ -0,0 +1,43 @@ + +/* + * <console.c> + * + * Simple text console + * + * Copyright (C) 2005 Stefan Reinauer <stepan@openbios.org> + * + * 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 + * + */ + +#include "config.h" +#include "libopenbios/bindings.h" +#include "libc/diskio.h" +#include "libopenbios/ofmem.h" +#include "pearpc/pearpc.h" + + +typedef struct osi_fb_info { + unsigned long mphys; + int rb, w, h, depth; +} osi_fb_info_t; + + +int PearPC_GetFBInfo( osi_fb_info_t *fb ) +{ + + fb->w=1024; + fb->h=768; + fb->depth=15; + fb->rb=2048; + fb->mphys=0x84000000; + + return 0; +} + +#define openbios_GetFBInfo(x) PearPC_GetFBInfo(x) + +#include "../../../packages/video.c" +#include "../../../libopenbios/console_common.c" diff --git a/qemu/roms/openbios/arch/ppc/pearpc/init.c b/qemu/roms/openbios/arch/ppc/pearpc/init.c new file mode 100644 index 000000000..ca6da0a44 --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/pearpc/init.c @@ -0,0 +1,136 @@ +/* + * Creation Date: <2004/08/28 18:38:22 greg> + * Time-stamp: <2004/08/28 18:38:22 greg> + * + * <init.c> + * + * Initialization for pearpc + * + * Copyright (C) 2004 Greg Watson + * Copyright (C) 2005 Stefan Reinauer + * + * based on mol/init.c: + * + * Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 Samuel & David Rydh + * (samuel@ibrium.se, dary@lindesign.se) + * + * 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 + * + */ + +#include "config.h" +#include "libopenbios/openbios.h" +#include "libopenbios/bindings.h" +#include "arch/common/nvram.h" +#include "pearpc/pearpc.h" +#include "libopenbios/ofmem.h" +#include "openbios-version.h" + +extern void unexpected_excep( int vector ); +extern void ob_pci_init( void ); +extern void ob_adb_init( void ); +extern void setup_timers( void ); + +#if 0 +int +get_bool_res( const char *res ) +{ + char buf[8], *p; + + p = BootHGetStrRes( res, buf, sizeof(buf) ); + if( !p ) + return -1; + if( !strcasecmp(p,"true") || !strcasecmp(p,"yes") || !strcasecmp(p,"1") ) + return 1; + return 0; +} +#endif + +void +unexpected_excep( int vector ) +{ + printk("openbios panic: Unexpected exception %x\n", vector ); + for( ;; ) + ; +} + +unsigned long isa_io_base; + +void +entry( void ) +{ + isa_io_base = 0x80000000; + + printk("\n"); + printk("=============================================================\n"); + printk(PROGRAM_NAME " " OPENBIOS_VERSION_STR " [%s]\n", + OPENBIOS_BUILD_DATE); + + ofmem_init(); + initialize_forth(); + /* won't return */ + + printk("of_startup returned!\n"); + for( ;; ) + ; +} + +static void +setenv( char *env, char *value ) +{ + push_str( value ); + push_str( env ); + fword("$setenv"); +} + +void +arch_of_init( void ) +{ +#if CONFIG_RTAS + phandle_t ph; +#endif + int autoboot; + + devtree_init(); + nvram_init("/pci/mac-io/nvram"); + openbios_init(); + modules_init(); + setup_timers(); +#ifdef CONFIG_DRIVER_PCI + ob_pci_init(); +#endif + node_methods_init(); + init_video(); + +#if CONFIG_RTAS + if( !(ph=find_dev("/rtas")) ) + printk("Warning: No /rtas node\n"); + else { + unsigned long size = 0x1000; + while( size < (unsigned long)of_rtas_end - (unsigned long)of_rtas_start ) + size *= 2; + set_property( ph, "rtas-size", (char*)&size, sizeof(size) ); + } +#endif + +#if 0 + /* tweak boot settings */ + autoboot = !!get_bool_res("autoboot"); +#endif + autoboot = 0; + if( !autoboot ) + printk("Autobooting disabled - dropping into OpenFirmware\n"); + setenv("auto-boot?", autoboot ? "true" : "false" ); + setenv("boot-command", "pearpcboot"); + +#if 0 + if( get_bool_res("tty-interface") == 1 ) +#endif + fword("activate-tty-interface"); + + /* hack */ + device_end(); + bind_func("pearpcboot", boot ); +} diff --git a/qemu/roms/openbios/arch/ppc/pearpc/kernel.c b/qemu/roms/openbios/arch/ppc/pearpc/kernel.c new file mode 100644 index 000000000..6408e421e --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/pearpc/kernel.c @@ -0,0 +1,16 @@ +/* + * Creation Date: <2004/08/28 18:03:25 stepan> + * Time-stamp: <2004/08/28 18:03:25 stepan> + * + * <pearpc/kernel.c> + * + * Copyright (C) 2005 Stefan Reinauer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#include "pearpc-dict.h" +#include "../kernel.c" diff --git a/qemu/roms/openbios/arch/ppc/pearpc/main.c b/qemu/roms/openbios/arch/ppc/pearpc/main.c new file mode 100644 index 000000000..085494e56 --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/pearpc/main.c @@ -0,0 +1,145 @@ +/* + * Creation Date: <2004/08/28 18:38:22 greg> + * Time-stamp: <2004/08/28 18:38:22 greg> + * + * <main.c> + * + * Copyright (C) 2004 Greg Watson + * + * Based on MOL specific code which is + * Copyright (C) 2002, 2003, 2004 Samuel Rydh (samuel@ibrium.se) + * + * 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 + * + */ + + +#include "config.h" +#include "libopenbios/bindings.h" +#include "libopenbios/elfload.h" +#include "arch/common/nvram.h" +#include "libc/diskio.h" +#include "libc/vsprintf.h" +#include "pearpc/pearpc.h" +#include "libopenbios/ofmem.h" + +static void +transfer_control_to_elf( unsigned long entry ) +{ + extern void call_elf( unsigned long entry ); + printk("Starting ELF image at 0x%08lX\n", entry); + call_elf( 0x400000 ); + //call_elf( entry ); + + fatal_error("call_elf returned unexpectedly\n"); +} + +static int +load_elf_rom( unsigned long *entry, int fd ) +{ + int i, lszz_offs, elf_offs; + char buf[128], *addr; + Elf_ehdr ehdr; + Elf_phdr *phdr; + size_t s; + + printk("Loading '%s'\n", get_file_path(fd)); + + /* the ELF-image (usually) starts at offset 0x4000 */ + if( (elf_offs=find_elf(fd)) < 0 ) { + printk("----> %s is not an ELF image\n", buf ); + exit(1); + } + if( !(phdr=elf_readhdrs(fd, elf_offs, &ehdr)) ) + fatal_error("elf_readhdrs failed\n"); + + *entry = ehdr.e_entry; + + /* load segments. Compressed ROM-image assumed to be located immediately + * after the last segment */ + lszz_offs = elf_offs; + for( i=0; i<ehdr.e_phnum; i++ ) { + /* p_memsz, p_flags */ + s = MIN( phdr[i].p_filesz, phdr[i].p_memsz ); + seek_io( fd, elf_offs + phdr[i].p_offset ); + + /* printk("filesz: %08lX memsz: %08lX p_offset: %08lX p_vaddr %08lX\n", + phdr[i].p_filesz, phdr[i].p_memsz, phdr[i].p_offset, + phdr[i].p_vaddr ); */ + + if( phdr[i].p_vaddr != phdr[i].p_paddr ) + printk("WARNING: ELF segment virtual addr != physical addr\n"); + lszz_offs = MAX( lszz_offs, elf_offs + phdr[i].p_offset + phdr[i].p_filesz ); + if( !s ) + continue; + if( ofmem_claim( phdr[i].p_vaddr, phdr[i].p_memsz, 0 ) == -1 ) + fatal_error("Claim failed!\n"); + + addr = (char*)phdr[i].p_vaddr; + if( read_io(fd, addr, s) != s ) + fatal_error("read failed\n"); + +#if 0 + /* patch CODE segment */ + if( *entry >= phdr[i].p_vaddr && *entry < phdr[i].p_vaddr + s ) { + patch_newworld_rom( (char*)phdr[i].p_vaddr, s ); + newworld_timer_hack( (char*)phdr[i].p_vaddr, s ); + } +#endif + flush_icache_range( addr, addr+s ); + + /*printk("ELF ROM-section loaded at %08lX (size %08lX)\n", + (unsigned long)phdr[i].p_vaddr, (unsigned long)phdr[i].p_memsz );*/ + } + free( phdr ); + return lszz_offs; +} + + +static void +encode_bootpath( const char *spec, const char *args ) +{ + phandle_t chosen_ph = find_dev("/chosen"); + set_property( chosen_ph, "bootpath", spec, strlen(spec)+1 ); + set_property( chosen_ph, "bootargs", args, strlen(args)+1 ); +} + +/************************************************************************/ +/* pearpc booting */ +/************************************************************************/ + +static void +pearpc_startup( void ) +{ + const char *paths[] = { "hd:0,\\zImage.chrp", NULL }; + const char *args[] = { "root=/dev/hda2 console=ttyS0,115200", NULL }; + unsigned long entry; + int i, fd; + + for( i=0; paths[i]; i++ ) { + if( (fd=open_io(paths[i])) == -1 ) + continue; + (void) load_elf_rom( &entry, fd ); + close_io( fd ); + encode_bootpath( paths[i], args[i] ); + + update_nvram(); + transfer_control_to_elf( entry ); + /* won't come here */ + } + printk("*** Boot failure! No secondary bootloader specified ***\n"); +} + + +/************************************************************************/ +/* entry */ +/************************************************************************/ + +void +boot( void ) +{ + fword("update-chosen"); + pearpc_startup(); +} diff --git a/qemu/roms/openbios/arch/ppc/pearpc/methods.c b/qemu/roms/openbios/arch/ppc/pearpc/methods.c new file mode 100644 index 000000000..f505b6cea --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/pearpc/methods.c @@ -0,0 +1,329 @@ +/* + * Creation Date: <2004/08/28 18:38:22 greg> + * Time-stamp: <2004/08/28 18:38:22 greg> + * + * <methods.c> + * + * Misc device node methods + * + * Copyright (C) 2004 Greg Watson + * + * Based on MOL specific code which is + * + * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#include "config.h" +#include "libopenbios/bindings.h" +#include "libc/string.h" +#include "pearpc/pearpc.h" +#include "libopenbios/ofmem.h" + +/************************************************************************/ +/* RTAS (run-time abstraction services) */ +/************************************************************************/ + +#ifdef CONFIG_RTAS +DECLARE_NODE( rtas, INSTALL_OPEN, 0, "+/rtas" ); + +/* ( physbase -- rtas_callback ) */ +static void +rtas_instantiate( void ) +{ + int physbase = POP(); + int s=0x1000, size = (int)of_rtas_end - (int)of_rtas_start; + unsigned long virt; + + while( s < size ) + s += 0x1000; + virt = ofmem_claim_virt( 0, s, 0x1000 ); + ofmem_map( physbase, virt, s, -1 ); + memcpy( (char*)virt, of_rtas_start, size ); + + printk("RTAS instantiated at %08x\n", physbase ); + flush_icache_range( (char*)virt, (char*)virt + size ); + + PUSH( physbase ); +} + +NODE_METHODS( rtas ) = { + { "instantiate", rtas_instantiate }, + { "instantiate-rtas", rtas_instantiate }, +}; +#endif + + +/************************************************************************/ +/* stdout */ +/************************************************************************/ + +DECLARE_NODE( video_stdout, INSTALL_OPEN, 0, "Tdisplay" ); + +/* ( addr len -- actual ) */ +static void +stdout_write( void ) +{ + int len = POP(); + char *addr = (char*)POP(); + + printk( "%s", s ); + //vfd_draw_str( s ); + console_draw_fstr(addr, len); + + PUSH( len ); +} + +NODE_METHODS( video_stdout ) = { + { "write", stdout_write }, +}; + + +/************************************************************************/ +/* tty */ +/************************************************************************/ + +DECLARE_NODE( tty, INSTALL_OPEN, 0, "/packages/terminal-emulator" ); + +/* ( addr len -- actual ) */ +static void +tty_read( void ) +{ + int ch, len = POP(); + char *p = (char*)POP(); + int ret=0; + + if( len > 0 ) { + ret = 1; + ch = getchar(); + if( ch >= 0 ) { + *p = ch; + } else { + ret = 0; + } + } + PUSH( ret ); +} + +/* ( addr len -- actual ) */ +static void +tty_write( void ) +{ + int i, len = POP(); + char *p = (char*)POP(); + for( i=0; i<len; i++ ) + putchar( *p++ ); + RET( len ); +} + +NODE_METHODS( tty ) = { + { "read", tty_read }, + { "write", tty_write }, +}; + +/************************************************************************/ +/* client interface 'quiesce' */ +/************************************************************************/ + +DECLARE_NODE( ciface, 0, 0, "/packages/client-iface" ); + +/* ( -- ) */ +static void +ciface_quiesce( unsigned long args[], unsigned long ret[] ) +{ +#if 0 + unsigned long msr; + /* This seems to be the correct thing to do - but I'm not sure */ + asm volatile("mfmsr %0" : "=r" (msr) : ); + msr &= ~(MSR_IR | MSR_DR); + asm volatile("mtmsr %0" :: "r" (msr) ); +#endif + printk("=============================================================\n\n"); +} + +/* ( -- ms ) */ +static void +ciface_milliseconds( unsigned long args[], unsigned long ret[] ) +{ + extern unsigned long get_timer_freq(); + static unsigned long mticks=0, usecs=0; + unsigned long t; + + asm volatile("mftb %0" : "=r" (t) : ); + if( mticks ) + usecs += get_timer_freq() / 1000000 * ( t-mticks ); + mticks = t; + + PUSH( usecs/1000 ); +} + + +NODE_METHODS( ciface ) = { + { "quiesce", ciface_quiesce }, + { "milliseconds", ciface_milliseconds }, +}; + + +/************************************************************************/ +/* MMU/memory methods */ +/************************************************************************/ + +DECLARE_NODE( memory, INSTALL_OPEN, 0, "/memory" ); +DECLARE_NODE( mmu, INSTALL_OPEN, 0, "/cpu@0" ); +DECLARE_NODE( mmu_ciface, 0, 0, "/packages/client-iface" ); + + +/* ( phys size align --- base ) */ +static void +mem_claim( void ) +{ + ucell align = POP(); + ucell size = POP(); + ucell phys = POP(); + ucell ret = ofmem_claim_phys( phys, size, align ); + + if( ret == (ucell)-1 ) { + printk("MEM: claim failure\n"); + throw( -13 ); + return; + } + PUSH( ret ); +} + +/* ( phys size --- ) */ +static void +mem_release( void ) +{ + POP(); POP(); +} + +/* ( phys size align --- base ) */ +static void +mmu_claim( void ) +{ + ucell align = POP(); + ucell size = POP(); + ucell phys = POP(); + ucell ret = ofmem_claim_virt( phys, size, align ); + + if( ret == -1 ) { + printk("MMU: CLAIM failure\n"); + throw( -13 ); + return; + } + PUSH( ret ); +} + +/* ( phys size --- ) */ +static void +mmu_release( void ) +{ + POP(); POP(); +} + +/* ( phys virt size mode -- [ret???] ) */ +static void +mmu_map( void ) +{ + ucell mode = POP(); + ucell size = POP(); + ucell virt = POP(); + ucell phys = POP(); + ucell ret; + + /* printk("mmu_map: %x %x %x %x\n", phys, virt, size, mode ); */ + ret = ofmem_map( phys, virt, size, mode ); + + if( ret ) { + printk("MMU: map failure\n"); + throw( -13 ); + return; + } +} + +/* ( virt size -- ) */ +static void +mmu_unmap( void ) +{ + POP(); POP(); +} + +/* ( virt -- false | phys mode true ) */ +static void +mmu_translate( void ) +{ + ucell mode; + ucell virt = POP(); + ucell phys = ofmem_translate( virt, &mode ); + + if( phys == -1 ) { + PUSH( 0 ); + } else { + PUSH( phys ); + PUSH( mode ); + PUSH( -1 ); + } +} + +/* ( virt size align -- baseaddr|-1 ) */ +static void +ciface_claim( void ) +{ + ucell align = POP(); + ucell size = POP(); + ucell virt = POP(); + ucell ret = ofmem_claim( virt, size, align ); + + /* printk("ciface_claim: %08x %08x %x\n", virt, size, align ); */ + PUSH( ret ); +} + +/* ( virt size -- ) */ +static void +ciface_release( void ) +{ + POP(); + POP(); +} + + +NODE_METHODS( memory ) = { + { "claim", mem_claim }, + { "release", mem_release }, +}; + +NODE_METHODS( mmu ) = { + { "claim", mmu_claim }, + { "release", mmu_release }, + { "map", mmu_map }, + { "unmap", mmu_unmap }, + { "translate", mmu_translate }, +}; + +NODE_METHODS( mmu_ciface ) = { + { "cif-claim", ciface_claim }, + { "cif-release", ciface_release }, +}; + + +/************************************************************************/ +/* init */ +/************************************************************************/ + +void +node_methods_init( void ) +{ +#ifdef CONFIG_RTAS + REGISTER_NODE( rtas ); +#endif + REGISTER_NODE( video_stdout ); + REGISTER_NODE( ciface ); + REGISTER_NODE( memory ); + REGISTER_NODE( mmu ); + REGISTER_NODE( mmu_ciface ); + REGISTER_NODE( tty ); +} diff --git a/qemu/roms/openbios/arch/ppc/pearpc/pearpc.c b/qemu/roms/openbios/arch/ppc/pearpc/pearpc.c new file mode 100644 index 000000000..234052ce4 --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/pearpc/pearpc.c @@ -0,0 +1,206 @@ +/* + * Creation Date: <2004/08/28 18:38:22 greg> + * Time-stamp: <2004/08/28 18:38:22 greg> + * + * <pearpc.c> + * + * Copyright (C) 2004, Greg Watson + * + * derived from mol.c + * + * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#include "config.h" +#include "kernel/kernel.h" +#include "arch/common/nvram.h" +#include "libc/vsprintf.h" +#include "libc/string.h" +#include "pearpc/pearpc.h" +#include <stdarg.h> + +#define UART_BASE 0x3f8 + +// FIXME +unsigned long virt_offset = 0; + + +void +exit( int status ) +{ + for (;;); +} + +void +fatal_error( const char *err ) +{ + printk("Fatal error: %s\n", err ); + exit(0); +} + +void +panic( const char *err ) +{ + printk("Panic: %s\n", err ); + exit(0); + + /* won't come here... this keeps the gcc happy */ + for( ;; ) + ; +} + + +/************************************************************************/ +/* print using OSI interface */ +/************************************************************************/ + +static int do_indent; + +int +printk( const char *fmt, ... ) +{ + char *p, buf[1024]; + va_list args; + int i; + + va_start(args, fmt); + i = vsnprintf(buf, sizeof(buf), fmt, args); + va_end(args); + + for( p=buf; *p; p++ ) { + if( *p == '\n' ) + do_indent = 0; + if( do_indent++ == 1 ) { + putchar( '>' ); + putchar( '>' ); + putchar( ' ' ); + } + putchar( *p ); + } + return i; +} + + +/************************************************************************/ +/* TTY iface */ +/************************************************************************/ + +static int ttychar = -1; + +static int +tty_avail( void ) +{ + return 1; +} + +static int +tty_putchar( int c ) +{ + if( tty_avail() ) { + while (!(inb(UART_BASE + 0x05) & 0x20)) + ; + outb(c, UART_BASE); + while (!(inb(UART_BASE + 0x05) & 0x40)) + ; + } + return c; +} + +int +availchar( void ) +{ + if( !tty_avail() ) + return 0; + + if( ttychar < 0 ) + ttychar = inb(UART_BASE); + return (ttychar >= 0); +} + +int +getchar( void ) +{ + int ch; + + if( !tty_avail() ) + return 0; + + if( ttychar < 0 ) + return inb(UART_BASE); + ch = ttychar; + ttychar = -1; + return ch; +} + +int +putchar( int c ) +{ + if (c == '\n') + tty_putchar('\r'); + return tty_putchar(c); +} + + +/************************************************************************/ +/* briQ specific stuff */ +/************************************************************************/ + +#define IO_NVRAM_PA_START 0x80860000 +#define IO_NVRAM_PA_END 0x80880000 + +static char *nvram=(char *)IO_NVRAM_PA_START; + +void +dump_nvram(void) +{ + static char hexdigit[] = "0123456789abcdef"; + int i; + for (i = 0; i < 16*4; i++) + { + printk ("%c", hexdigit[nvram[i<<4] >> 4]); + printk ("%c", hexdigit[nvram[i<<4] % 16]); + if (!((i + 1) % 16)) + { + printk ("\n"); + } + else + { + printk (" "); + } + } +} + + +int +arch_nvram_size( void ) +{ + return (IO_NVRAM_PA_END-IO_NVRAM_PA_START)>>4; +} + +void +arch_nvram_put( char *buf ) +{ + int i; + for (i=0; i<(IO_NVRAM_PA_END-IO_NVRAM_PA_START)>>4; i++) + nvram[i<<4]=buf[i]; + // memcpy(nvram, buf, IO_NVRAM_PA_END-IO_NVRAM_PA_START); + printk("new nvram:\n"); + dump_nvram(); +} + +void +arch_nvram_get( char *buf ) +{ + int i; + for (i=0; i<(IO_NVRAM_PA_END-IO_NVRAM_PA_START)>>4; i++) + buf[i]=nvram[i<<4]; + + //memcpy(buf, nvram, IO_NVRAM_PA_END-IO_NVRAM_PA_START); + printk("current nvram:\n"); + dump_nvram(); +} diff --git a/qemu/roms/openbios/arch/ppc/pearpc/pearpc.fs b/qemu/roms/openbios/arch/ppc/pearpc/pearpc.fs new file mode 100644 index 000000000..0d018b1c3 --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/pearpc/pearpc.fs @@ -0,0 +1,116 @@ +\ pearpc specific initialization code +\ +\ Copyright (C) 2005 Stefan Reinauer +\ +\ 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 +\ + + +\ ------------------------------------------------------------------------- +\ initialization +\ ------------------------------------------------------------------------- + +: make-openable ( path ) + find-dev if + begin ?dup while + \ install trivial open and close methods + dup active-package! is-open + parent + repeat + then +; + +: preopen ( chosen-str node-path ) + 2dup make-openable + + " /chosen" find-device + open-dev ?dup if + encode-int 2swap property + else + 2drop + then +; + +\ preopen device nodes (and store the ihandles under /chosen) +:noname + " rtc" " /pci/isa/rtc" preopen + " memory" " /memory" preopen + " mmu" " /cpu@0" preopen + \ " stdout" " /packages/terminal-emulator" preopen + " stdout" " /pci/pci6666,6666" preopen + " stdin" " /pci/via-cuda/adb" preopen + +; SYSTEM-initializer + + +\ ------------------------------------------------------------------------- +\ device tree fixing +\ ------------------------------------------------------------------------- + +\ add decode-address methods +: (make-decodable) ( phandle -- ) + + dup " #address-cells" rot get-package-property 0= if + decode-int nip nip + over " decode-unit" rot find-method if 2drop else + ( save phandle ncells ) + + over active-package! + case + 1 of ['] parse-hex " decode-unit" is-xt-func endof + 3 of + " bus-range" active-package get-package-property 0= if + decode-int nip nip + ['] encode-unit-pci " encode-unit" is-xt-func + " decode-unit" is-func-begin + ['] (lit) , , + ['] decode-unit-pci-bus , + is-func-end + then + endof + endcase + then + then + drop +; + +: init-pearpc-tree ( -- ) + active-package + + iterate-tree-begin + begin ?dup while + + dup (make-decodable) + + iterate-tree + repeat + + active-package! +; + +\ use the tty interface if available +: activate-tty-interface + " /packages/terminal-emulator" find-dev if drop + " /pci/via-cuda/adb" " input-device" $setenv + " /pci/pci6666,6666" " output-device" $setenv + then +; + +:noname + " keyboard" input +; CONSOLE-IN-initializer + + +\ ------------------------------------------------------------------------- +\ pre-booting +\ ------------------------------------------------------------------------- + +: update-chosen + " /chosen" find-device + stdin @ encode-int " stdin" property + stdout @ encode-int " stdout" property + " /pci/isa/interrupt-controller" find-dev if encode-int " interrupt-controller" property then + device-end +; diff --git a/qemu/roms/openbios/arch/ppc/pearpc/pearpc.h b/qemu/roms/openbios/arch/ppc/pearpc/pearpc.h new file mode 100644 index 000000000..44497d79e --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/pearpc/pearpc.h @@ -0,0 +1,26 @@ +/* + * Creation Date: <2004/08/28 17:50:12 stepan> + * Time-stamp: <2004/08/28 17:50:12 stepan> + * + * <pearpc.h> + * + * Copyright (C) 2005 Stefan Reinauer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#ifndef _H_PEARPC +#define _H_PEARPC + +/* vfd.c */ +extern int vfd_draw_str( const char *str ); +extern void vfd_close( void ); + +extern int console_draw_fstr(const char *str, int len); + +#include "kernel.h" + +#endif /* _H_PEARPC */ diff --git a/qemu/roms/openbios/arch/ppc/pearpc/tree.c b/qemu/roms/openbios/arch/ppc/pearpc/tree.c new file mode 100644 index 000000000..abd1bf024 --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/pearpc/tree.c @@ -0,0 +1,23 @@ +/* + * Creation Date: <2004/08/28 18:38:22 greg> + * Time-stamp: <2004/08/28 18:38:22 greg> + * + * <tree.c> + * + * device tree setup + * + * Copyright (C) 2004 Greg Watson + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#include "config.h" +#include "libopenbios/bindings.h" + +void devtree_init( void ) +{ + fword("init-pearpc-tree"); +} diff --git a/qemu/roms/openbios/arch/ppc/pearpc/tree.fs b/qemu/roms/openbios/arch/ppc/pearpc/tree.fs new file mode 100644 index 000000000..d19b485f8 --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/pearpc/tree.fs @@ -0,0 +1,305 @@ +\ PearPC specific initialization code +\ +\ Copyright (C) 2005 Stefan Reinauer +\ +\ 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 +\ + +\ ------------------------------------------------------------- +\ device-tree +\ ------------------------------------------------------------- + +" /" find-device + +" chrp" device-type +" OpenSource,PEARPC" model +h# 80000000 encode-int " isa-io-base" property +1 encode-int " #interrupt-cells" property +1 encode-int " #size-cells" property + +new-device + " memory" device-name + " memory" device-type + 0 encode-int h# 1E00000 encode-int encode+ + h# 2000000 encode-int encode+ h# 40000000 encode-int encode+ + " available" property + 0 h# 40000000 reg + external + : open true ; + : close ; +finish-device + +new-device + " cpu" device-name + " cpu" device-type + " " encode-string " translations" property + 0 encode-phys h# 8000000 encode-int encode+ " available" property + d# 32 encode-int " d-cache-block-size" property + 8 encode-int " d-cache-sets" property + d# 32768 encode-int " d-cache-size" property + d# 32 encode-int " i-cache-block-size" property + 8 encode-int " i-cache-sets" property + d# 32768 encode-int " i-cache-size" property + " " encode-string " cache-unified" property + 2 encode-int " i-tlb-sets" property + d# 128 encode-int " i-tlb-size" property + 2 encode-int " d-tlb-sets" property + d# 128 encode-int " d-tlb-size" property + " " encode-string " tlb-split" property + 2 encode-int " tlb-sets" property + d# 256 encode-int " tlb-size" property + " " encode-string " performance-monitor" property + " " encode-string " graphics" property + 4 encode-int " reservation-granule-size" property + d# 25000000 encode-int " timebase-frequency" property + d# 300000000 encode-int " clock-frequency" property + d# 66000000 encode-int " bus-frequency" property + h# 88201 encode-int " cpu-version" property + 0 encode-int " reg" property +finish-device + +" /pci" find-device + h# 01000000 encode-int 0 encode-int encode+ 0 encode-int encode+ + h# 80000000 encode-int encode+ 0 encode-int encode+ + h# 01000000 encode-int encode+ + h# 02000000 encode-int encode+ 0 encode-int encode+ 0 encode-int encode+ + h# C0000000 encode-int encode+ 0 encode-int encode+ + h# 08000000 encode-int encode+ + " ranges" property + " IBM,CPC710" model + h# FF5F7700 encode-int " 8259-interrupt-acknowledge" property + h# 0000F800 encode-int 0 encode-int encode+ 0 encode-int encode+ + 7 encode-int encode+ + " interrupt-map-mask" property + 1 encode-int " #interrupt-cells" property + h# 80000000 encode-int " system-dma-base" property + d# 33333333 encode-int " clock-frequency" property + " " encode-string " primary-bridge" property + 0 encode-int " pci-bridge-number" property + h# FEC00000 encode-int h# 100000 encode-int encode+ " reg" property + 0 encode-int 0 encode-int encode+ " bus-range" property + +new-device + " isa" device-name + " isa" device-type + 2 encode-int " #address-cells" property + 1 encode-int " #size-cells" property + + external + : open true ; + : close ; + +finish-device + +: ?devalias ( alias-str alias-len device-str device-len -- + \ alias-str alias-len false | true ) + active-package >r + " /aliases" find-device + \ 2dup ." Checking " type + 2dup find-dev if \ check if device exists + drop + 2over find-dev if \ do we already have an alias? + \ ." alias exists" cr + drop 2drop false + else + \ ." device exists" cr + encode-string + 2swap property + true + then + else + \ ." device doesn't exist" cr + 2drop false + then + r> active-package! + ; + +:noname + " hd" + " /pci/pci-ata/ata-1/disk@0" ?devalias not if + " /pci/pci-ata/ata-1/disk@1" ?devalias not if + " /pci/pci-ata/ata-2/disk@0" ?devalias not if + " /pci/pci-ata/ata-2/disk@1" ?devalias not if + 2drop ." No disk found." cr + then + then + then + then + + " cdrom" + " /pci/pci-ata/ata-1/cdrom@0" ?devalias not if + " /pci/pci-ata/ata-1/cdrom@1" ?devalias not if + " /pci/pci-ata/ata-2/cdrom@0" ?devalias not if + " /pci/pci-ata/ata-2/cdrom@1" ?devalias not if + 2drop ." No cdrom found" cr + then + then + then + then +; SYSTEM-initializer + +new-device + " ide" device-name + " ide" device-type + " WINBOND,82C553" model + h# 28 encode-int " max-latency" property + h# 2 encode-int " min-grant" property + h# 1 encode-int " devsel-speed" property + h# 0 encode-int " subsystem-vendor-id" property + h# 0 encode-int " subsystem-id" property + h# 1018A encode-int " class-code" property + h# 5 encode-int " revision-id" property + h# 105 encode-int " device-id" property + h# 10AD encode-int " vendor-id" property + h# 1003110 encode-int 0 encode-int encode+ h# 10020 encode-int encode+ + h# 10 encode-int encode+ 0 encode-int encode+ + h# 1003114 encode-int 0 encode-int encode+ h# 10030 encode-int encode+ + h# 4 encode-int encode+ 0 encode-int encode+ + h# 1003118 encode-int 0 encode-int encode+ h# 10040 encode-int encode+ + h# 10 encode-int encode+ 0 encode-int encode+ + h# 100311C encode-int 0 encode-int encode+ h# 10034 encode-int encode+ + h# 4 encode-int encode+ 0 encode-int encode+ + h# 1003120 encode-int 0 encode-int encode+ h# 10050 encode-int encode+ + h# 10 encode-int encode+ 0 encode-int encode+ + h# 1003124 encode-int 0 encode-int encode+ h# 10060 encode-int encode+ + h# 10 encode-int encode+ 0 encode-int encode+ + " assigned-addresses" property + h# 3100 encode-int 0 encode-int encode+ 0 encode-int encode+ + 0 encode-int encode+ 0 encode-int encode+ + h# 1003110 encode-int 0 encode-int encode+ h# 0 encode-int encode+ + h# 10 encode-int encode+ 0 encode-int encode+ + h# 1003114 encode-int 0 encode-int encode+ h# 0 encode-int encode+ + h# 4 encode-int encode+ 0 encode-int encode+ + h# 1003118 encode-int 0 encode-int encode+ h# 0 encode-int encode+ + h# 10 encode-int encode+ 0 encode-int encode+ + h# 100311C encode-int 0 encode-int encode+ h# 0 encode-int encode+ + h# 4 encode-int encode+ 0 encode-int encode+ + h# 1003120 encode-int 0 encode-int encode+ h# 0 encode-int encode+ + h# 10 encode-int encode+ 0 encode-int encode+ + h# 1003124 encode-int 0 encode-int encode+ h# 0 encode-int encode+ + h# 10 encode-int encode+ 0 encode-int encode+ + " reg" property +finish-device + +new-device + " ethernet" device-name + " network" device-type + " AMD,79C973" model + h# 3800 encode-int 0 encode-int encode+ 0 encode-int encode+ + 0 encode-int encode+ 0 encode-int encode+ + " reg" property +finish-device + +" /pci/isa" find-device + 0 0 " assigned-addresses" property + 0 0 " ranges" property + 0 encode-int " slot-names" property + d# 8333333 encode-int " clock-frequency" property + 0 encode-int " eisa-slots" property + 2 encode-int " #interrupt-cells" property + " W83C553F" encode-string " compatible" property + " WINBOND,82C553" model + 0 encode-int " max-latency" property + 0 encode-int " min-grant" property + 1 encode-int " devsel-speed" property + 0 encode-int " subsystem-vendor-id" property + 0 encode-int " subsystem-id" property + h# 60100 encode-int " class-code" property + h# 10 encode-int " revision-id" property + h# 565 encode-int " device-id" property + h# 10AD encode-int " vendor-id" property + h# 3000 encode-int 0 encode-int encode+ 0 encode-int encode+ + 0 encode-int encode+ 0 encode-int encode+ " reg" property + +new-device + " rtc" device-name + " rtc" device-type + " DS17285S" model + " MC146818" encode-string + " DS17285S" encode-string encode+ + " pnpPNP,b00" encode-string encode+ " compatible" property + 8 encode-int 0 encode-int encode+ " interrupts" property + h# 70 encode-int 1 encode-int encode+ + 2 encode-int encode+ " reg" property +finish-device + +new-device + " interrupt-controller" device-name + " interrupt-controller" device-type + " 8259" model + " " encode-string " interrupt-controller" property + 2 encode-int " #interrupt-cells" property + 1 encode-int + 2 encode-int encode+ + 3 encode-int encode+ + 6 encode-int encode+ + " reserved-interrupts" property + " 8259" encode-string + " chrp,iic" encode-string encode+ + " compatible" property + h# 20 encode-int 1 encode-int encode+ + 2 encode-int encode+ " reg" property +finish-device + +new-device + " serial" device-name + " serial" device-type + " no" encode-string " ctsrts" property + " no" encode-string " xon" property + " no" encode-string " parity" property + d# 115200 encode-int " bps" property + 1 encode-int " stop-bits" property + 8 encode-int " data-bits" property + h# 70800 encode-int " divisor" property + h# 708000 encode-int " clock-frequency" property + 4 encode-int 0 encode-int encode+ " interrupts" property + h# 3F8 encode-int 1 encode-int encode+ + 8 encode-int encode+ " reg" property +finish-device + +" /pci" find-device + " /pci/isa/interrupt-controller" find-dev if + encode-int " interrupt-parent" property + then + h# 3800 encode-int 0 encode-int encode+ + 0 encode-int encode+ 1 encode-int encode+ + " /pci/isa/interrupt-controller" find-dev if + encode-int encode+ + then + h# 0C encode-int encode+ 1 encode-int encode+ + " interrupt-map" property + +" /pci/isa" find-device + " /pci/isa/interrupt-controller" find-dev if + encode-int " interrupt-parent" property + then + +\ ------------------------------------------------------------- +\ /packages +\ ------------------------------------------------------------- + +" /packages" find-device + + " packages" device-name + external + \ allow packages to be opened with open-dev + : open true ; + : close ; + +\ /packages/terminal-emulator +new-device + " terminal-emulator" device-name + external + : open true ; + : close ; + \ : write ( addr len -- actual ) + \ dup -rot type + \ ; +finish-device + +\ ------------------------------------------------------------- +\ The END +\ ------------------------------------------------------------- +device-end diff --git a/qemu/roms/openbios/arch/ppc/pearpc/vfd.c b/qemu/roms/openbios/arch/ppc/pearpc/vfd.c new file mode 100644 index 000000000..06485f2dc --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/pearpc/vfd.c @@ -0,0 +1,42 @@ +/* + * Creation Date: <2004/08/28 17:29:43 greg> + * Time-stamp: <2004/08/28 17:29:43 greg> + * + * <vfd.c> + * + * Simple text console + * + * Copyright (C) 2004 Greg Watson + * + * 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 + * + */ + +#include "config.h" +#include "libopenbios/bindings.h" +#include "pearpc/pearpc.h" + +static int vfd_is_open; + +static int +vfd_init( void ) +{ + vfd_is_open = 1; + return 0; +} + +void +vfd_close( void ) +{ +} + +int +vfd_draw_str( const char *str ) +{ + if (!vfd_is_open) + vfd_init(); + + return 0; +} diff --git a/qemu/roms/openbios/arch/ppc/ppc.fs b/qemu/roms/openbios/arch/ppc/ppc.fs new file mode 100644 index 000000000..0414f22c4 --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/ppc.fs @@ -0,0 +1,68 @@ +include config.fs + +\ ------------------------------------------------------------------------- +\ registers +\ ------------------------------------------------------------------------- + +0 value %cr +0 value %ctr +0 value %lr +0 value %msr +0 value %srr0 +0 value %srr1 +0 value %pc \ should be an alias for %srr0 + +0 value %r0 +0 value %r1 +0 value %r2 +0 value %r3 +0 value %r4 +0 value %r5 +0 value %r6 +0 value %r7 +0 value %r8 +0 value %r9 +0 value %r10 +0 value %r11 +0 value %r12 +0 value %r13 +0 value %r14 +0 value %r15 +0 value %r16 +0 value %r17 +0 value %r18 +0 value %r19 +0 value %r20 +0 value %r21 +0 value %r22 +0 value %r23 +0 value %r24 +0 value %r25 +0 value %r26 +0 value %r27 +0 value %r28 +0 value %r29 +0 value %r30 +0 value %r31 + +0 value %xer +0 value %sprg0 +0 value %sprg1 +0 value %sprg2 +0 value %sprg3 + +\ ------------------------------------------------------------------------- +\ Load VGA FCode driver blob +\ ------------------------------------------------------------------------- + +[IFDEF] CONFIG_DRIVER_VGA + -1 value vga-driver-fcode + " QEMU,VGA.bin" $encode-file to vga-driver-fcode +[THEN] + +\ ------------------------------------------------------------------------- +\ other +\ ------------------------------------------------------------------------- + +\ Set by BootX when booting Mac OS X +defer spin diff --git a/qemu/roms/openbios/arch/ppc/qemu/console.c b/qemu/roms/openbios/arch/ppc/qemu/console.c new file mode 100644 index 000000000..53a321525 --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/qemu/console.c @@ -0,0 +1,88 @@ +/* + * <console.c> + * + * Simple text console + * + * Copyright (C) 2005 Stefan Reinauer <stepan@openbios.org> + * + * 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 + * + */ + +#include "config.h" +#include "libopenbios/bindings.h" +#include "libopenbios/console.h" +#include "drivers/drivers.h" + +#ifdef CONFIG_DEBUG_CONSOLE +/* ****************************************************************** + * common functions, implementing simple concurrent console + * ****************************************************************** */ + +static int mac_putchar(int c) +{ +#ifdef CONFIG_DEBUG_CONSOLE_SERIAL + escc_uart_putchar(c & 0xff); +#endif + return c; +} + +static int mac_availchar(void) +{ +#ifdef CONFIG_DEBUG_CONSOLE_SERIAL + if (escc_uart_charav(CONFIG_SERIAL_PORT)) + return 1; +#endif + return 0; +} + +static int mac_getchar(void) +{ +#ifdef CONFIG_DEBUG_CONSOLE_SERIAL + if (escc_uart_charav(CONFIG_SERIAL_PORT)) + return (escc_uart_getchar(CONFIG_SERIAL_PORT)); +#endif + return 0; +} + +struct _console_ops mac_console_ops = { + .putchar = mac_putchar, + .availchar = mac_availchar, + .getchar = mac_getchar +}; + +static int prep_putchar(int c) +{ +#ifdef CONFIG_DEBUG_CONSOLE_SERIAL + uart_putchar(c & 0xff); +#endif + return c; +} + +static int prep_availchar(void) +{ +#ifdef CONFIG_DEBUG_CONSOLE_SERIAL + if (uart_charav(CONFIG_SERIAL_PORT)) + return 1; +#endif + return 0; +} + +static int prep_getchar(void) +{ +#ifdef CONFIG_DEBUG_CONSOLE_SERIAL + if (uart_charav(CONFIG_SERIAL_PORT)) + return (uart_getchar(CONFIG_SERIAL_PORT)); +#endif + return 0; +} + +struct _console_ops prep_console_ops = { + .putchar = prep_putchar, + .availchar = prep_availchar, + .getchar = prep_getchar +}; + +#endif // CONFIG_DEBUG_CONSOLE diff --git a/qemu/roms/openbios/arch/ppc/qemu/init.c b/qemu/roms/openbios/arch/ppc/qemu/init.c new file mode 100644 index 000000000..4fe8b7220 --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/qemu/init.c @@ -0,0 +1,951 @@ +/* + * Creation Date: <2004/08/28 18:38:22 greg> + * Time-stamp: <2004/08/28 18:38:22 greg> + * + * <init.c> + * + * Initialization for qemu + * + * Copyright (C) 2004 Greg Watson + * Copyright (C) 2005 Stefan Reinauer + * + * based on mol/init.c: + * + * Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 Samuel & David Rydh + * (samuel@ibrium.se, dary@lindesign.se) + * + * 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 + * + */ + +#include "config.h" +#include "libopenbios/openbios.h" +#include "libopenbios/bindings.h" +#include "libopenbios/console.h" +#include "drivers/pci.h" +#include "arch/common/nvram.h" +#include "drivers/drivers.h" +#include "qemu/qemu.h" +#include "libopenbios/ofmem.h" +#include "openbios-version.h" +#include "libc/byteorder.h" +#include "libc/vsprintf.h" +#define NO_QEMU_PROTOS +#include "arch/common/fw_cfg.h" +#include "arch/ppc/processor.h" + +#define UUID_FMT "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x" + +struct cpudef { + unsigned int iu_version; + const char *name; + int icache_size, dcache_size; + int icache_sets, dcache_sets; + int icache_block_size, dcache_block_size; + int tlb_sets, tlb_size; + void (*initfn)(const struct cpudef *cpu); +}; + +static uint16_t machine_id = 0; + +extern void unexpected_excep(int vector); + +void +unexpected_excep(int vector) +{ + printk("openbios panic: Unexpected exception %x\n", vector); + for (;;) { + } +} + +extern void __divide_error(void); + +void +__divide_error(void) +{ + return; +} + +enum { + ARCH_PREP = 0, + ARCH_MAC99, + ARCH_HEATHROW, + ARCH_MAC99_U3, +}; + +int is_apple(void) +{ + return is_oldworld() || is_newworld(); +} + +int is_oldworld(void) +{ + return machine_id == ARCH_HEATHROW; +} + +int is_newworld(void) +{ + return (machine_id == ARCH_MAC99) || + (machine_id == ARCH_MAC99_U3); +} + +static const pci_arch_t known_arch[] = { + [ARCH_PREP] = { + .name = "PREP", + .vendor_id = PCI_VENDOR_ID_MOTOROLA, + .device_id = PCI_DEVICE_ID_MOTOROLA_RAVEN, + .cfg_addr = 0x80000cf8, + .cfg_data = 0x80000cfc, + .cfg_base = 0x80000000, + .cfg_len = 0x00100000, + .host_pci_base = 0xc0000000, + .pci_mem_base = 0x100000, /* avoid VGA at 0xa0000 */ + .mem_len = 0x10000000, + .io_base = 0x80000000, + .io_len = 0x00010000, + .rbase = 0x00000000, + .rlen = 0x00400000, + .irqs = { 9, 11, 9, 11 } + }, + [ARCH_MAC99] = { + .name = "MAC99", + .vendor_id = PCI_VENDOR_ID_APPLE, + .device_id = PCI_DEVICE_ID_APPLE_UNI_N_PCI, + .cfg_addr = 0xf2800000, + .cfg_data = 0xf2c00000, + .cfg_base = 0xf2000000, + .cfg_len = 0x02000000, + .host_pci_base = 0x0, + .pci_mem_base = 0x80000000, + .mem_len = 0x10000000, + .io_base = 0xf2000000, + .io_len = 0x00800000, + .rbase = 0x00000000, + .rlen = 0x01000000, + .irqs = { 0x1b, 0x1c, 0x1d, 0x1e } + }, + [ARCH_MAC99_U3] = { + .name = "MAC99_U3", + .vendor_id = PCI_VENDOR_ID_APPLE, + .device_id = PCI_DEVICE_ID_APPLE_U3_AGP, + .cfg_addr = 0xf0800000, + .cfg_data = 0xf0c00000, + .cfg_base = 0xf0000000, + .cfg_len = 0x02000000, + .host_pci_base = 0x0, + .pci_mem_base = 0x80000000, + .mem_len = 0x10000000, + .io_base = 0xf2000000, + .io_len = 0x00800000, + .rbase = 0x00000000, + .rlen = 0x01000000, + .irqs = { 0x1b, 0x1c, 0x1d, 0x1e } + }, + [ARCH_HEATHROW] = { + .name = "HEATHROW", + .vendor_id = PCI_VENDOR_ID_MOTOROLA, + .device_id = PCI_DEVICE_ID_MOTOROLA_MPC106, + .cfg_addr = 0xfec00000, + .cfg_data = 0xfee00000, + .cfg_base = 0x80000000, + .cfg_len = 0x7f000000, + .host_pci_base = 0x0, + .pci_mem_base = 0x80000000, + .mem_len = 0x10000000, + .io_base = 0xfe000000, + .io_len = 0x00800000, + .rbase = 0xfd000000, + .rlen = 0x01000000, + .irqs = { 21, 22, 23, 24 } + }, +}; +unsigned long isa_io_base; + +extern struct _console_ops mac_console_ops, prep_console_ops; + +void +entry(void) +{ + uint32_t temp = 0; + char buf[5]; + + arch = &known_arch[ARCH_HEATHROW]; + + fw_cfg_init(); + + fw_cfg_read(FW_CFG_SIGNATURE, buf, 4); + buf[4] = '\0'; + if (strncmp(buf, "QEMU", 4) == 0) { + temp = fw_cfg_read_i32(FW_CFG_ID); + if (temp == 1) { + machine_id = fw_cfg_read_i16(FW_CFG_MACHINE_ID); + arch = &known_arch[machine_id]; + } + } + + isa_io_base = arch->io_base; + +#ifdef CONFIG_DEBUG_CONSOLE + if (is_apple()) { + init_console(mac_console_ops); + } else { + init_console(prep_console_ops); + } +#endif + + if (temp != 1) { + printk("Incompatible configuration device version, freezing\n"); + for (;;) { + } + } + + ofmem_init(); + initialize_forth(); + /* won't return */ + + printk("of_startup returned!\n"); + for (;;) { + } +} + +/* -- phys.lo ... phys.hi */ +static void +push_physaddr(phys_addr_t value) +{ + PUSH(value); +#ifdef CONFIG_PPC64 + PUSH(value >> 32); +#endif +} + +/* From drivers/timer.c */ +extern unsigned long timer_freq; + +static void +cpu_generic_init(const struct cpudef *cpu) +{ + push_str("/cpus"); + fword("find-device"); + + fword("new-device"); + + push_str(cpu->name); + fword("device-name"); + + push_str("cpu"); + fword("device-type"); + + PUSH(mfpvr()); + fword("encode-int"); + push_str("cpu-version"); + fword("property"); + + PUSH(cpu->dcache_size); + fword("encode-int"); + push_str("d-cache-size"); + fword("property"); + + PUSH(cpu->icache_size); + fword("encode-int"); + push_str("i-cache-size"); + fword("property"); + + PUSH(cpu->dcache_sets); + fword("encode-int"); + push_str("d-cache-sets"); + fword("property"); + + PUSH(cpu->icache_sets); + fword("encode-int"); + push_str("i-cache-sets"); + fword("property"); + + PUSH(cpu->dcache_block_size); + fword("encode-int"); + push_str("d-cache-block-size"); + fword("property"); + + PUSH(cpu->icache_block_size); + fword("encode-int"); + push_str("i-cache-block-size"); + fword("property"); + + PUSH(cpu->tlb_sets); + fword("encode-int"); + push_str("tlb-sets"); + fword("property"); + + PUSH(cpu->tlb_size); + fword("encode-int"); + push_str("tlb-size"); + fword("property"); + + timer_freq = fw_cfg_read_i32(FW_CFG_PPC_TBFREQ); + PUSH(timer_freq); + fword("encode-int"); + push_str("timebase-frequency"); + fword("property"); + + PUSH(fw_cfg_read_i32(FW_CFG_PPC_CLOCKFREQ)); + fword("encode-int"); + push_str("clock-frequency"); + fword("property"); + + PUSH(fw_cfg_read_i32(FW_CFG_PPC_BUSFREQ)); + fword("encode-int"); + push_str("bus-frequency"); + fword("property"); + + push_str("running"); + fword("encode-string"); + push_str("state"); + fword("property"); +} + +static void +cpu_add_pir_property(void) +{ + unsigned long pir; + + asm("mfspr %0, 1023\n" + : "=r"(pir) :); + PUSH(pir); + fword("encode-int"); + push_str("reg"); + fword("property"); +} + +static void +cpu_604_init(const struct cpudef *cpu) +{ + cpu_generic_init(cpu); + cpu_add_pir_property(); + + fword("finish-device"); +} + +static void +cpu_750_init(const struct cpudef *cpu) +{ + cpu_generic_init(cpu); + + PUSH(0); + fword("encode-int"); + push_str("reg"); + fword("property"); + + fword("finish-device"); +} + +static void +cpu_g4_init(const struct cpudef *cpu) +{ + cpu_generic_init(cpu); + cpu_add_pir_property(); + + fword("finish-device"); +} + +#ifdef CONFIG_PPC_64BITSUPPORT +/* In order to get 64 bit aware handlers that rescue all our + GPRs from getting truncated to 32 bits, we need to patch the + existing handlers so they jump to our 64 bit aware ones. */ +static void +ppc64_patch_handlers(void) +{ + uint32_t *dsi = (uint32_t *)0x300UL; + uint32_t *isi = (uint32_t *)0x400UL; + + // Patch the first DSI handler instruction to: ba 0x2000 + *dsi = 0x48002002; + + // Patch the first ISI handler instruction to: ba 0x2200 + *isi = 0x48002202; + + // Invalidate the cache lines + asm ("icbi 0, %0" : : "r"(dsi)); + asm ("icbi 0, %0" : : "r"(isi)); +} +#endif + +static void +cpu_970_init(const struct cpudef *cpu) +{ + cpu_generic_init(cpu); + + PUSH(0); + fword("encode-int"); + push_str("reg"); + fword("property"); + + PUSH(0); + PUSH(0); + fword("encode-bytes"); + push_str("64-bit"); + fword("property"); + + fword("finish-device"); + +#ifdef CONFIG_PPC_64BITSUPPORT + /* The 970 is a PPC64 CPU, so we need to activate + * 64bit aware interrupt handlers */ + + ppc64_patch_handlers(); +#endif + + /* The 970 also implements the HIOR which we need to set to 0 */ + + mtspr(S_HIOR, 0); +} + +static const struct cpudef ppc_defs[] = { + { + .iu_version = 0x00040000, + .name = "PowerPC,604", + .icache_size = 0x4000, + .dcache_size = 0x4000, + .icache_sets = 0x80, + .dcache_sets = 0x80, + .icache_block_size = 0x20, + .dcache_block_size = 0x20, + .tlb_sets = 0x40, + .tlb_size = 0x80, + .initfn = cpu_604_init, + }, + { // XXX find out real values + .iu_version = 0x00090000, + .name = "PowerPC,604e", + .icache_size = 0x4000, + .dcache_size = 0x4000, + .icache_sets = 0x80, + .dcache_sets = 0x80, + .icache_block_size = 0x20, + .dcache_block_size = 0x20, + .tlb_sets = 0x40, + .tlb_size = 0x80, + .initfn = cpu_604_init, + }, + { // XXX find out real values + .iu_version = 0x000a0000, + .name = "PowerPC,604r", + .icache_size = 0x4000, + .dcache_size = 0x4000, + .icache_sets = 0x80, + .dcache_sets = 0x80, + .icache_block_size = 0x20, + .dcache_block_size = 0x20, + .tlb_sets = 0x40, + .tlb_size = 0x80, + .initfn = cpu_604_init, + }, + { // XXX find out real values + .iu_version = 0x80040000, + .name = "PowerPC,MPC86xx", + .icache_size = 0x8000, + .dcache_size = 0x8000, + .icache_sets = 0x80, + .dcache_sets = 0x80, + .icache_block_size = 0x20, + .dcache_block_size = 0x20, + .tlb_sets = 0x40, + .tlb_size = 0x80, + .initfn = cpu_750_init, + }, + { + .iu_version = 0x000080000, + .name = "PowerPC,750", + .icache_size = 0x8000, + .dcache_size = 0x8000, + .icache_sets = 0x80, + .dcache_sets = 0x80, + .icache_block_size = 0x20, + .dcache_block_size = 0x20, + .tlb_sets = 0x40, + .tlb_size = 0x80, + .initfn = cpu_750_init, + }, + { // XXX find out real values + .iu_version = 0x10080000, + .name = "PowerPC,750", + .icache_size = 0x8000, + .dcache_size = 0x8000, + .icache_sets = 0x80, + .dcache_sets = 0x80, + .icache_block_size = 0x20, + .dcache_block_size = 0x20, + .tlb_sets = 0x40, + .tlb_size = 0x80, + .initfn = cpu_750_init, + }, + { // XXX find out real values + .iu_version = 0x70000000, + .name = "PowerPC,750", + .icache_size = 0x8000, + .dcache_size = 0x8000, + .icache_sets = 0x80, + .dcache_sets = 0x80, + .icache_block_size = 0x20, + .dcache_block_size = 0x20, + .tlb_sets = 0x40, + .tlb_size = 0x80, + .initfn = cpu_750_init, + }, + { // XXX find out real values + .iu_version = 0x70020000, + .name = "PowerPC,750", + .icache_size = 0x8000, + .dcache_size = 0x8000, + .icache_sets = 0x80, + .dcache_sets = 0x80, + .icache_block_size = 0x20, + .dcache_block_size = 0x20, + .tlb_sets = 0x40, + .tlb_size = 0x80, + .initfn = cpu_750_init, + }, + { // XXX find out real values + .iu_version = 0x800c0000, + .name = "PowerPC,74xx", + .icache_size = 0x8000, + .dcache_size = 0x8000, + .icache_sets = 0x80, + .dcache_sets = 0x80, + .icache_block_size = 0x20, + .dcache_block_size = 0x20, + .tlb_sets = 0x40, + .tlb_size = 0x80, + .initfn = cpu_750_init, + }, + { + .iu_version = 0x0000c0000, + .name = "PowerPC,G4", + .icache_size = 0x8000, + .dcache_size = 0x8000, + .icache_sets = 0x80, + .dcache_sets = 0x80, + .icache_block_size = 0x20, + .dcache_block_size = 0x20, + .tlb_sets = 0x40, + .tlb_size = 0x80, + .initfn = cpu_g4_init, + }, + { + .iu_version = 0x00390000, + .name = "PowerPC,970", + .icache_size = 0x10000, + .dcache_size = 0x8000, + .icache_sets = 0x200, + .dcache_sets = 0x80, + .icache_block_size = 0x80, + .dcache_block_size = 0x80, + .tlb_sets = 0x100, + .tlb_size = 0x1000, + .initfn = cpu_970_init, + }, + { // XXX find out real values + .iu_version = 0x003C0000, + .name = "PowerPC,970FX", + .icache_size = 0x10000, + .dcache_size = 0x8000, + .icache_sets = 0x80, + .dcache_sets = 0x80, + .icache_block_size = 0x80, + .dcache_block_size = 0x80, + .tlb_sets = 0x100, + .tlb_size = 0x1000, + .initfn = cpu_970_init, + }, + { + .iu_version = 0x00350000, + .name = "PowerPC,POWER4", + .icache_size = 0x10000, + .dcache_size = 0x8000, + .icache_sets = 0x100, + .dcache_sets = 0x40, + .icache_block_size = 0x80, + .dcache_block_size = 0x80, + .tlb_sets = 0x100, + .tlb_size = 0x1000, + .initfn = cpu_970_init, + }, +}; + +static const struct cpudef * +id_cpu(void) +{ + unsigned int iu_version; + unsigned int i; + + iu_version = mfpvr() & 0xffff0000; + + for (i = 0; i < sizeof(ppc_defs) / sizeof(struct cpudef); i++) { + if (iu_version == ppc_defs[i].iu_version) + return &ppc_defs[i]; + } + printk("Unknown cpu (pvr %x), freezing!\n", iu_version); + for (;;) { + } +} + +static void go(void); + +static void +go(void) +{ + ucell addr; + + feval("saved-program-state >sps.entry @"); + addr = POP(); + + call_elf(0, 0, addr); +} + +static void kvm_of_init(void) +{ + char hypercall[4 * 4]; + uint32_t *hc32; + + /* Don't expose /hypervisor when not in KVM */ + if (!fw_cfg_read_i32(FW_CFG_PPC_IS_KVM)) + return; + + push_str("/"); + fword("find-device"); + + fword("new-device"); + + push_str("hypervisor"); + fword("device-name"); + + push_str("hypervisor"); + fword("device-type"); + + /* compatible */ + + push_str("linux,kvm"); + fword("encode-string"); + push_str("epapr,hypervisor-0.2"); + fword("encode-string"); + fword("encode+"); + push_str("compatible"); + fword("property"); + + /* Tell the guest about the hypercall instructions */ + fw_cfg_read(FW_CFG_PPC_KVM_HC, hypercall, 4 * 4); + hc32 = (uint32_t*)hypercall; + PUSH(hc32[0]); + fword("encode-int"); + PUSH(hc32[1]); + fword("encode-int"); + fword("encode+"); + PUSH(hc32[2]); + fword("encode-int"); + fword("encode+"); + PUSH(hc32[3]); + fword("encode-int"); + fword("encode+"); + push_str("hcall-instructions"); + fword("property"); + + /* ePAPR requires us to provide a unique guest id */ + PUSH(fw_cfg_read_i32(FW_CFG_PPC_KVM_PID)); + fword("encode-int"); + push_str("guest-id"); + fword("property"); + + /* ePAPR requires us to provide a guest name */ + push_str("KVM guest"); + fword("encode-string"); + push_str("guest-name"); + fword("property"); + + fword("finish-device"); +} + +/* + * filll ( addr bytes quad -- ) + */ + +static void ffilll(void) +{ + const u32 longval = POP(); + u32 bytes = POP(); + u32 *laddr = (u32 *)cell2pointer(POP()); + u32 len; + + for (len = 0; len < bytes / sizeof(u32); len++) { + *laddr++ = longval; + } +} + +void +arch_of_init(void) +{ +#ifdef CONFIG_RTAS + phandle_t ph; +#endif + uint64_t ram_size; + const struct cpudef *cpu; + char buf[64], qemu_uuid[16]; + const char *stdin_path, *stdout_path, *boot_path; + uint32_t temp = 0; + char *boot_device; + ofmem_t *ofmem = ofmem_arch_get_private(); + + openbios_init(); + modules_init(); + setup_timers(); +#ifdef CONFIG_DRIVER_PCI + ob_pci_init(); +#endif + + printk("\n"); + printk("=============================================================\n"); + printk(PROGRAM_NAME " " OPENBIOS_VERSION_STR " [%s]\n", + OPENBIOS_BUILD_DATE); + + fw_cfg_read(FW_CFG_SIGNATURE, buf, 4); + buf[4] = '\0'; + printk("Configuration device id %s", buf); + + temp = fw_cfg_read_i32(FW_CFG_ID); + printk(" version %d machine id %d\n", temp, machine_id); + + temp = fw_cfg_read_i32(FW_CFG_NB_CPUS); + + printk("CPUs: %x\n", temp); + + ram_size = ofmem->ramsize; + + printk("Memory: %lldM\n", ram_size / 1024 / 1024); + + fw_cfg_read(FW_CFG_UUID, qemu_uuid, 16); + + printk("UUID: " UUID_FMT "\n", qemu_uuid[0], qemu_uuid[1], qemu_uuid[2], + qemu_uuid[3], qemu_uuid[4], qemu_uuid[5], qemu_uuid[6], + qemu_uuid[7], qemu_uuid[8], qemu_uuid[9], qemu_uuid[10], + qemu_uuid[11], qemu_uuid[12], qemu_uuid[13], qemu_uuid[14], + qemu_uuid[15]); + + /* set device tree root info */ + + push_str("/"); + fword("find-device"); + + switch(machine_id) { + case ARCH_HEATHROW: /* OldWorld */ + + /* model */ + + push_str("Power Macintosh"); + fword("model"); + + /* compatible */ + + push_str("AAPL,PowerMac G3"); + fword("encode-string"); + push_str("MacRISC"); + fword("encode-string"); + fword("encode+"); + push_str("compatible"); + fword("property"); + + /* misc */ + + push_str("device-tree"); + fword("encode-string"); + push_str("AAPL,original-name"); + fword("property"); + + PUSH(0); + fword("encode-int"); + push_str("AAPL,cpu-id"); + fword("property"); + + PUSH(66 * 1000 * 1000); + fword("encode-int"); + push_str("clock-frequency"); + fword("property"); + break; + + case ARCH_MAC99: + case ARCH_MAC99_U3: + case ARCH_PREP: + default: + + /* model */ + + push_str("PowerMac3,1"); + fword("model"); + + /* compatible */ + + push_str("PowerMac3,1"); + fword("encode-string"); + push_str("MacRISC"); + fword("encode-string"); + fword("encode+"); + push_str("MacRISC2"); + fword("encode-string"); + fword("encode+"); + push_str("Power Macintosh"); + fword("encode-string"); + fword("encode+"); + push_str("compatible"); + fword("property"); + + /* misc */ + + push_str("bootrom"); + fword("device-type"); + + PUSH(100 * 1000 * 1000); + fword("encode-int"); + push_str("clock-frequency"); + fword("property"); + break; + } + + /* Perhaps we can store UUID here ? */ + + push_str("0000000000000"); + fword("encode-string"); + push_str("system-id"); + fword("property"); + + /* memory info */ + + push_str("/memory"); + fword("find-device"); + + /* all memory */ + + push_physaddr(0); + fword("encode-phys"); + /* This needs adjusting if #size-cells gets increased. + Alternatively use multiple (address, size) tuples. */ + PUSH(ram_size & 0xffffffff); + fword("encode-int"); + fword("encode+"); + push_str("reg"); + fword("property"); + + cpu = id_cpu(); + cpu->initfn(cpu); + printk("CPU type %s\n", cpu->name); + + snprintf(buf, sizeof(buf), "/cpus/%s", cpu->name); + ofmem_register(find_dev("/memory"), find_dev(buf)); + node_methods_init(buf); + +#ifdef CONFIG_RTAS + /* OldWorld Macs don't have an /rtas node. */ + switch (machine_id) { + case ARCH_MAC99: + case ARCH_MAC99_U3: + if (!(ph = find_dev("/rtas"))) { + printk("Warning: No /rtas node\n"); + } else { + unsigned long size = 0x1000; + while (size < (unsigned long)of_rtas_end - (unsigned long)of_rtas_start) + size *= 2; + set_property(ph, "rtas-size", (char*)&size, sizeof(size)); + set_int_property(ph, "rtas-version", is_apple() ? 0x41 : 1); + } + break; + } +#endif + + if (fw_cfg_read_i16(FW_CFG_NOGRAPHIC)) { + if (is_apple()) { + if (CONFIG_SERIAL_PORT) { + stdin_path = "scca"; + stdout_path = "scca"; + } else { + stdin_path = "sccb"; + stdout_path = "sccb"; + } + } else { + stdin_path = "ttya"; + stdout_path = "ttya"; + } + + /* Some bootloaders force the output to the screen device, so + let's create a screen alias for the serial device too */ + + push_str("/aliases"); + fword("find-device"); + + push_str(stdout_path); + fword("pathres-resolve-aliases"); + fword("encode-string"); + push_str("screen"); + fword("property"); + } else { + if (is_apple()) { + stdin_path = "adb-keyboard"; + stdout_path = "screen"; + } else { + stdin_path = "keyboard"; + stdout_path = "screen"; + } + } + + kvm_of_init(); + + /* Setup nvram variables */ + push_str("/options"); + fword("find-device"); + + /* Setup default boot devices (not overriding user settings) */ + fword("boot-device"); + boot_device = pop_fstr_copy(); + if (boot_device && strcmp(boot_device, "disk") == 0) { + switch (fw_cfg_read_i16(FW_CFG_BOOT_DEVICE)) { + case 'c': + boot_path = "hd"; + break; + default: + case 'd': + boot_path = "cd"; + break; + } + + snprintf(buf, sizeof(buf), "%s:,\\\\:tbxi %s:,\\ppc\\bootinfo.txt %s:,%%BOOT", boot_path, boot_path, boot_path); + push_str(buf); + fword("encode-string"); + push_str("boot-device"); + fword("property"); + } + free(boot_device); + + /* Set up other properties */ + + push_str("/chosen"); + fword("find-device"); + + push_str(stdin_path); + fword("pathres-resolve-aliases"); + push_str("input-device"); + fword("$setenv"); + + push_str(stdout_path); + fword("pathres-resolve-aliases"); + push_str("output-device"); + fword("$setenv"); + +#if 0 + if(getbool("tty-interface?") == 1) +#endif + fword("activate-tty-interface"); + + device_end(); + + /* Implementation of filll word (required by BootX) */ + bind_func("filll", ffilll); + + bind_func("platform-boot", boot); + bind_func("(go)", go); +} diff --git a/qemu/roms/openbios/arch/ppc/qemu/kernel.c b/qemu/roms/openbios/arch/ppc/qemu/kernel.c new file mode 100644 index 000000000..b26fba5f7 --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/qemu/kernel.c @@ -0,0 +1,115 @@ +/* + * Creation Date: <2003/10/25 14:07:17 samuel> + * Time-stamp: <2004/08/28 17:48:19 stepan> + * + * <kernel.c> + * + * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se) + * Copyright (C) 2003, 2004 Stefan Reinauer + * + * Based upon unix.c (from OpenBIOS): + * + * Copyright (C) 2003 Patrick Mauritz, Stefan Reinauer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#include "config.h" +#include "dict.h" +#include "libopenbios/bindings.h" +#include "kernel/stack.h" +#include "kernel/kernel.h" +#include "libc/string.h" +#include "kernel.h" + +#define MEMORY_SIZE (256*1024) /* 256K ram for hosted system */ +/* 512K for the dictionary */ +#define DICTIONARY_SIZE (512 * 1024 / sizeof(ucell)) +#ifdef __powerpc64__ +#define DICTIONARY_BASE 0xfff08000 /* this must match the value in ldscript! */ +#define DICTIONARY_SECTION __attribute__((section(".data.dict"))) +#else +#define DICTIONARY_BASE ((ucell)((char *)&forth_dictionary)) +#define DICTIONARY_SECTION +#endif + +static ucell forth_dictionary[DICTIONARY_SIZE] DICTIONARY_SECTION = { +#include "qemu-dict.h" +}; + +static ucell *memory; + +/************************************************************************/ +/* F U N C T I O N S */ +/************************************************************************/ + +int +forth_segv_handler( char *segv_addr ) +{ + ucell addr = 0xdeadbeef; + + if( PC >= pointer2cell(dict) && PC <= pointer2cell(dict) + dicthead ) + addr = *(ucell *)cell2pointer(PC); + + printk("panic: segmentation violation at 0x%p\n", segv_addr); + printk("dict=0x%p here=0x%p(dict+0x%x) pc=0x%x(dict+0x%x)\n", + dict, (char*)dict + dicthead, dicthead, + PC, PC - pointer2cell(dict)); + printk("dstackcnt=%d rstackcnt=%d instruction=%x\n", + dstackcnt, rstackcnt, addr); + +#ifdef DEBUG_DSTACK + printdstack(); +#endif +#ifdef DEBUG_RSTACK + printrstack(); +#endif + return -1; +} + +/* + * allocate memory and prepare engine for memory management. + */ + +static void +init_memory( void ) +{ + memory = malloc(MEMORY_SIZE); + if( !memory ) + panic("panic: not enough memory on host system.\n"); + + /* we push start and end of memory to the stack + * so that it can be used by the forth word QUIT + * to initialize the memory allocator + */ + + PUSH( pointer2cell(memory) ); + PUSH( pointer2cell(memory) + MEMORY_SIZE ); +} + +int +initialize_forth( void ) +{ + dict = (unsigned char *)forth_dictionary; + dicthead = (ucell)FORTH_DICTIONARY_END; + last = (ucell *)((unsigned char *)forth_dictionary + + FORTH_DICTIONARY_LAST); + dictlimit = sizeof(forth_dictionary); + + forth_init(); + + PUSH_xt( bind_noname_func(arch_of_init) ); + fword("PREPOST-initializer"); + + PC = (ucell)findword("initialize-of"); + if( PC ) { + init_memory(); + enterforth((xt_t)PC); + free( memory ); + } + free( dict ); + return 0; +} diff --git a/qemu/roms/openbios/arch/ppc/qemu/kernel.h b/qemu/roms/openbios/arch/ppc/qemu/kernel.h new file mode 100644 index 000000000..fe9be83d9 --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/qemu/kernel.h @@ -0,0 +1,42 @@ +/* + * Creation Date: <2004/08/28 17:50:12 stepan> + * Time-stamp: <2004/08/28 17:50:12 stepan> + * + * <kernel.h> + * + * Copyright (C) 2004 Stefan Reinauer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#ifndef __KERNEL_H__ +#define __KERNEL_H__ + +/* misc.c */ +extern void fatal_error( const char *str ); +extern void exit( int status ) __attribute__ ((noreturn)); + +/* start.S */ +extern void flush_icache_range( char *start, char *stop ); +extern char of_rtas_start[], of_rtas_end[]; +extern void call_elf( unsigned long arg1, unsigned long arg2, unsigned long elf_entry ); + +/* methods.c */ +extern void node_methods_init( const char *cpuname ); + +/* main.c */ +extern void boot( void ); + +/* init.c */ +extern void entry( void ); +extern void arch_of_init( void ); +extern int get_bool_res( const char *str ); + +/* tree.c */ +extern void devtree_init( void ); + + +#endif /* __KERNEL_H__ */ diff --git a/qemu/roms/openbios/arch/ppc/qemu/ldscript b/qemu/roms/openbios/arch/ppc/qemu/ldscript new file mode 100644 index 000000000..8027b39db --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/qemu/ldscript @@ -0,0 +1,68 @@ +OUTPUT_FORMAT(elf32-powerpc) +OUTPUT_ARCH(powerpc:common) + +/* Initial load address + */ +BASE_ADDR = 0xfff00000; + +/* As NVRAM is at 0xfff04000, the .text needs to be after that + */ +TEXT_ADDR = 0xfff08000; + +/* Hard reset vector address + */ +HRESET_ADDR = 0xfffffffc; + +CSTACK_SIZE = 32768; /* client stack size */ + +SECTIONS +{ + . = BASE_ADDR; + + _start = BASE_ADDR + 0x0100; + .text.vectors ALIGN(4096): { + *(.text.vectors) + } + + . = TEXT_ADDR; + /* Normal sections */ + .text ALIGN(4096): { + *(.text) + *(.text.*) + } + + .rodata ALIGN(4096): { + _rodata = .; + *(.rodata) + *(.rodata.*) + *(.note.ELFBoot) + } + .data ALIGN(4096): { + _data = .; + *(.data) + *(.data.*) + _edata = .; + } + + .bss ALIGN(4096): { + _bss = .; + *(.sbss) + *(.sbss.*) + *(.bss) + *(.bss.*) + *(COMMON) + _ebss = .; + } + + . = HRESET_ADDR; + + .romentry : { *(.romentry) } + + . = ALIGN(4096); + _end = .; + + /* We discard .note sections other than .note.ELFBoot, + * because some versions of GCC generates useless ones. */ + + /DISCARD/ : { *(.comment*) *(.note.*) } +} diff --git a/qemu/roms/openbios/arch/ppc/qemu/main.c b/qemu/roms/openbios/arch/ppc/qemu/main.c new file mode 100644 index 000000000..44b16666b --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/qemu/main.c @@ -0,0 +1,85 @@ +/* + * Creation Date: <2002/10/02 22:24:24 samuel> + * Time-stamp: <2004/03/27 01:57:55 samuel> + * + * <main.c> + * + * + * + * Copyright (C) 2002, 2003, 2004 Samuel Rydh (samuel@ibrium.se) + * + * 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 + * + */ + +#include "config.h" +#include "libopenbios/bindings.h" +#include "libopenbios/elf_load.h" +#include "arch/common/nvram.h" +#include "packages/nvram.h" +#include "libc/diskio.h" +#include "libc/vsprintf.h" +#include "kernel.h" +#include "drivers/drivers.h" +#include "libopenbios/ofmem.h" +#define NO_QEMU_PROTOS +#include "arch/common/fw_cfg.h" + +//#define DEBUG_QEMU + +#ifdef DEBUG_QEMU +#define SUBSYS_DPRINTF(subsys, fmt, args...) \ + do { printk("%s - %s: " fmt, subsys, __func__ , ##args); } while (0) +#else +#define SUBSYS_DPRINTF(subsys, fmt, args...) \ + do { } while (0) +#endif +#define CHRP_DPRINTF(fmt, args...) SUBSYS_DPRINTF("CHRP", fmt, ##args) +#define ELF_DPRINTF(fmt, args...) SUBSYS_DPRINTF("ELF", fmt, ##args) +#define NEWWORLD_DPRINTF(fmt, args...) SUBSYS_DPRINTF("NEWWORLD", fmt, ##args) + +static void check_preloaded_kernel(void) +{ + unsigned long kernel_image, kernel_size; + unsigned long initrd_image, initrd_size; + const char * kernel_cmdline; + + kernel_size = fw_cfg_read_i32(FW_CFG_KERNEL_SIZE); + if (kernel_size) { + kernel_image = fw_cfg_read_i32(FW_CFG_KERNEL_ADDR); + kernel_cmdline = (const char *)(uintptr_t) fw_cfg_read_i32(FW_CFG_KERNEL_CMDLINE); + initrd_image = fw_cfg_read_i32(FW_CFG_INITRD_ADDR); + initrd_size = fw_cfg_read_i32(FW_CFG_INITRD_SIZE); + printk("[ppc] Kernel already loaded (0x%8.8lx + 0x%8.8lx) " + "(initrd 0x%8.8lx + 0x%8.8lx)\n", + kernel_image, kernel_size, initrd_image, initrd_size); + if (kernel_cmdline) { + phandle_t ph; + printk("[ppc] Kernel command line: %s\n", kernel_cmdline); + ph = find_dev("/chosen"); + set_property(ph, "bootargs", strdup(kernel_cmdline), strlen(kernel_cmdline) + 1); + } + call_elf(initrd_image, initrd_size, kernel_image); + } +} + +/************************************************************************/ +/* entry */ +/************************************************************************/ + +void +boot( void ) +{ + uint16_t boot_device = fw_cfg_read_i16(FW_CFG_BOOT_DEVICE); + + fword("update-chosen"); + if (boot_device == 'm') { + check_preloaded_kernel(); + } + + if (is_apple()) { + update_nvram(); + } +} diff --git a/qemu/roms/openbios/arch/ppc/qemu/methods.c b/qemu/roms/openbios/arch/ppc/qemu/methods.c new file mode 100644 index 000000000..fd993daa9 --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/qemu/methods.c @@ -0,0 +1,327 @@ +/* + * Creation Date: <2004/08/28 18:38:22 greg> + * Time-stamp: <2004/08/28 18:38:22 greg> + * + * <methods.c> + * + * Misc device node methods + * + * Copyright (C) 2004 Greg Watson + * + * Based on MOL specific code which is + * + * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#include "config.h" +#include "libopenbios/bindings.h" +#include "drivers/drivers.h" +#include "libc/string.h" +#include "qemu/qemu.h" +#include "libopenbios/ofmem.h" +#include "arch/ppc/processor.h" +#include "drivers/usb.h" + +/************************************************************************/ +/* RTAS (run-time abstraction services) */ +/************************************************************************/ + +#ifdef CONFIG_RTAS +DECLARE_NODE( rtas, INSTALL_OPEN, 0, "+/rtas" ); + +/* ( physbase -- rtas_callback ) */ +static void +rtas_instantiate( void ) +{ + ucell physbase = POP(); + ucell s=0x1000, size = (ucell)of_rtas_end - (ucell)of_rtas_start; + unsigned long virt; + + while( s < size ) + s += 0x1000; + virt = ofmem_claim_virt( 0, s, 0x1000 ); + ofmem_map( physbase, virt, s, -1 ); + memcpy( (char*)virt, of_rtas_start, size ); + + printk("RTAS instantiated at %08x\n", physbase ); + flush_icache_range( (char*)virt, (char*)virt + size ); + + PUSH( physbase ); +} + +NODE_METHODS( rtas ) = { + { "instantiate", rtas_instantiate }, + { "instantiate-rtas", rtas_instantiate }, +}; +#endif + + +/************************************************************************/ +/* tty */ +/************************************************************************/ + +DECLARE_NODE( tty, INSTALL_OPEN, 0, "/packages/terminal-emulator" ); + +/* ( addr len -- actual ) */ +static void +tty_read( void ) +{ + int ch, len = POP(); + char *p = (char*)cell2pointer(POP()); + int ret=0; + + if( len > 0 ) { + ret = 1; + ch = getchar(); + if( ch >= 0 ) { + *p = ch; + } else { + ret = 0; + } + } + PUSH( ret ); +} + +/* ( addr len -- actual ) */ +static void +tty_write( void ) +{ + int i, len = POP(); + char *p = (char*)cell2pointer(POP()); + for( i=0; i<len; i++ ) + putchar( *p++ ); + RET( len ); +} + +NODE_METHODS( tty ) = { + { "read", tty_read }, + { "write", tty_write }, +}; + +/************************************************************************/ +/* client interface 'quiesce' */ +/************************************************************************/ + +DECLARE_NODE( ciface, 0, 0, "+/openprom/client-services" ); + +/* ( -- ) */ +static void +ciface_quiesce( unsigned long args[], unsigned long ret[] ) +{ + usb_exit(); +#if 0 + unsigned long msr; + /* This seems to be the correct thing to do - but I'm not sure */ + asm volatile("mfmsr %0" : "=r" (msr) : ); + msr &= ~(MSR_IR | MSR_DR); + asm volatile("mtmsr %0" :: "r" (msr) ); +#endif +} + +/* ( -- ms ) */ +#define TIMER_FREQUENCY 16600000ULL + +static void +ciface_milliseconds( unsigned long args[], unsigned long ret[] ) +{ + unsigned long tbu, tbl, temp; + unsigned long long ticks, msecs; + + asm volatile( + "1:\n" + "mftbu %2\n" + "mftb %0\n" + "mftbu %1\n" + "cmpw %2,%1\n" + "bne 1b\n" + : "=r"(tbl), "=r"(tbu), "=r"(temp) + : + : "cc"); + + ticks = (((unsigned long long)tbu) << 32) | (unsigned long long)tbl; + msecs = (1000 * ticks) / TIMER_FREQUENCY; + PUSH( msecs ); +} + + +NODE_METHODS( ciface ) = { + { "quiesce", ciface_quiesce }, + { "milliseconds", ciface_milliseconds }, +}; + + +/************************************************************************/ +/* MMU/memory methods */ +/************************************************************************/ + +DECLARE_NODE( memory, INSTALL_OPEN, 0, "/memory" ); +DECLARE_UNNAMED_NODE( mmu, INSTALL_OPEN, 0 ); +DECLARE_NODE( mmu_ciface, 0, 0, "+/openprom/client-services" ); + + +/* ( phys size align --- base ) */ +static void +mem_claim( void ) +{ + ucell align = POP(); + ucell size = POP(); + ucell phys = POP(); + ucell ret = ofmem_claim_phys( phys, size, align ); + + if( ret == -1 ) { + printk("MEM: claim failure\n"); + throw( -13 ); + return; + } + PUSH( ret ); +} + +/* ( phys size --- ) */ +static void +mem_release( void ) +{ + POP(); POP(); +} + +/* ( phys size align --- base ) */ +static void +mmu_claim( void ) +{ + ucell align = POP(); + ucell size = POP(); + ucell phys = POP(); + ucell ret = ofmem_claim_virt( phys, size, align ); + + if( ret == -1 ) { + printk("MMU: CLAIM failure\n"); + throw( -13 ); + return; + } + PUSH( ret ); +} + +/* ( phys size --- ) */ +static void +mmu_release( void ) +{ + POP(); POP(); +} + +/* ( phys virt size mode -- [ret???] ) */ +static void +mmu_map( void ) +{ + ucell mode = POP(); + ucell size = POP(); + ucell virt = POP(); + ucell phys = POP(); + ucell ret; + + /* printk("mmu_map: %x %x %x %x\n", phys, virt, size, mode ); */ + ret = ofmem_map( phys, virt, size, mode ); + + if( ret ) { + printk("MMU: map failure\n"); + throw( -13 ); + return; + } +} + +/* ( virt size -- ) */ +static void +mmu_unmap( void ) +{ + POP(); POP(); +} + +/* ( virt -- false | phys mode true ) */ +static void +mmu_translate( void ) +{ + ucell mode; + ucell virt = POP(); + ucell phys = ofmem_translate( virt, &mode ); + + if( phys == -1 ) { + PUSH( 0 ); + } else { + PUSH( phys ); + PUSH( mode ); + PUSH( -1 ); + } +} + +/* ( virt size align -- baseaddr|-1 ) */ +static void +ciface_claim( void ) +{ + ucell align = POP(); + ucell size = POP(); + ucell virt = POP(); + ucell ret = ofmem_claim( virt, size, align ); + + /* printk("ciface_claim: %08x %08x %x\n", virt, size, align ); */ + PUSH( ret ); +} + +/* ( virt size -- ) */ +static void +ciface_release( void ) +{ + ucell size = POP(); + ucell virt = POP(); + ofmem_release(virt, size); +} + + +NODE_METHODS( memory ) = { + { "claim", mem_claim }, + { "release", mem_release }, +}; + +NODE_METHODS( mmu ) = { + { "claim", mmu_claim }, + { "release", mmu_release }, + { "map", mmu_map }, + { "unmap", mmu_unmap }, + { "translate", mmu_translate }, +}; + +NODE_METHODS( mmu_ciface ) = { + { "cif-claim", ciface_claim }, + { "cif-release", ciface_release }, +}; + + +/************************************************************************/ +/* init */ +/************************************************************************/ + +void +node_methods_init( const char *cpuname ) +{ + phandle_t chosen, ph; +#ifdef CONFIG_RTAS + if (is_newworld()) { + REGISTER_NODE( rtas ); + } +#endif + REGISTER_NODE( ciface ); + REGISTER_NODE( memory ); + REGISTER_NODE_METHODS( mmu, cpuname ); + REGISTER_NODE( mmu_ciface ); + REGISTER_NODE( tty ); + + chosen = find_dev("/chosen"); + if (chosen) { + push_str(cpuname); + fword("open-dev"); + ph = POP(); + set_int_property(chosen, "mmu", ph); + } +} diff --git a/qemu/roms/openbios/arch/ppc/qemu/mmutypes.h b/qemu/roms/openbios/arch/ppc/qemu/mmutypes.h new file mode 100644 index 000000000..512c23d0e --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/qemu/mmutypes.h @@ -0,0 +1,97 @@ +/* + * Creation Date: <2002/01/13 13:53:14 samuel> + * Time-stamp: <2002/01/27 19:56:11 samuel> + * + * <mmutypes.h> + * + * MMU definitions + * + * Most of these declarations originate from the Linux Kernel + * + * Copyright (C) 2002 Samuel Rydh (samuel@ibrium.se) + * + * 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 + * + */ + +#ifndef _H_MMUTYPES +#define _H_MMUTYPES + +/* Hardware Page Table Entry */ +typedef struct mPTE { + unsigned long v:1; /* Entry is valid */ + unsigned long vsid:24; /* Virtual segment identifier */ + unsigned long h:1; /* Hash algorithm indicator */ + unsigned long api:6; /* Abbreviated page index */ + + unsigned long rpn:20; /* Real (physical) page number */ + unsigned long :3; /* Unused */ + unsigned long r:1; /* Referenced */ + unsigned long c:1; /* Changed */ + unsigned long w:1; /* Write-thru cache mode */ + unsigned long i:1; /* Cache inhibited */ + unsigned long m:1; /* Memory coherence */ + unsigned long g:1; /* Guarded */ + unsigned long :1; /* Unused */ + unsigned long pp:2; /* Page protection */ +} mPTE_t; + +typedef struct mPTE_64 { + uint32_t avpn_low; /* Abbreviated Virtual Page Number (unused) */ + uint32_t avpn:25; /* Abbreviated Virtual Page Number */ + uint32_t sw:4; /* Software Use */ + uint32_t :1; /* Reserved */ + uint32_t h:1; /* Hash algorithm indicator */ + uint32_t v:1; /* Entry is valid */ + + uint32_t rpn_low; /* Real (physical) page number (unused) */ + uint32_t rpn:20; /* Real (physical) page number */ + uint32_t :2; /* Reserved */ + uint32_t ac:1; /* Address Compare*/ + uint32_t r:1; /* Referenced */ + uint32_t c:1; /* Changed */ + uint32_t w:1; /* Write-thru cache mode */ + uint32_t i:1; /* Cache inhibited */ + uint32_t m:1; /* Memory coherence */ + uint32_t g:1; /* Guarded */ + uint32_t n:1; /* No-Execute */ + uint32_t pp:2; /* Page protection */ +} mPTE_64_t; + +typedef struct _mBATU { /* Upper part of BAT (all except 601) */ + unsigned long bepi:15; /* Effective page index (virtual address) */ + unsigned long :4; /* Unused */ + unsigned long bl:11; /* Block size mask */ + unsigned long vs:1; /* Supervisor valid */ + unsigned long vp:1; /* User valid */ +} mBATU; + +typedef struct _mBATL { /* Lower part of BAT (all except 601) */ + unsigned long brpn:15; /* Real page index (physical address) */ + unsigned long :10; /* Unused */ + unsigned long w:1; /* Write-thru cache */ + unsigned long i:1; /* Cache inhibit */ + unsigned long m:1; /* Memory coherence */ + unsigned long g:1; /* Guarded (MBZ in IBAT) */ + unsigned long :1; /* Unused */ + unsigned long pp:2; /* Page access protections */ +} mBATL; + +typedef struct _mBAT { + mBATU batu; /* Upper register */ + mBATL batl; /* Lower register */ +} mBAT; + +typedef struct _mSEGREG { + unsigned long t:1; /* Normal or I/O type */ + unsigned long ks:1; /* Supervisor 'key' (normally 0) */ + unsigned long kp:1; /* User 'key' (normally 1) */ + unsigned long n:1; /* No-execute */ + unsigned long :4; /* Unused */ + unsigned long vsid:24; /* Virtual Segment Identifier */ +} mSEGREG; + + +#endif /* _H_MMUTYPES */ diff --git a/qemu/roms/openbios/arch/ppc/qemu/ofmem.c b/qemu/roms/openbios/arch/ppc/qemu/ofmem.c new file mode 100644 index 000000000..6f346a3d4 --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/qemu/ofmem.c @@ -0,0 +1,563 @@ +/* + * Creation Date: <1999/11/07 19:02:11 samuel> + * Time-stamp: <2004/01/07 19:42:36 samuel> + * + * <ofmem.c> + * + * OF Memory manager + * + * Copyright (C) 1999-2004 Samuel Rydh (samuel@ibrium.se) + * Copyright (C) 2004 Stefan Reinauer + * + * 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 + * + */ + +#include "config.h" +#include "libopenbios/bindings.h" +#include "libc/string.h" +#include "libopenbios/ofmem.h" +#include "kernel.h" +#include "mmutypes.h" +#include "asm/processor.h" + +#define BIT(n) (1U << (31 - (n))) + +#define SLB_VSID_SHIFT 12 + +/* called from assembly */ +extern void dsi_exception(void); +extern void isi_exception(void); +extern void setup_mmu(unsigned long code_base); + +/* + * From Apple's BootX source comments: + * + * 96 MB map (currently unused - 4363357 tracks re-adoption) + * 00000000 - 00003FFF : Exception Vectors + * 00004000 - 03FFFFFF : Kernel Image, Boot Struct and Drivers (~64 MB) + * 04000000 - 04FFFFFF : File Load Area (16 MB) [80 MB] + * 05000000 - 053FFFFF : FS Cache (4 MB) [84 MB] + * 05400000 - 055FFFFF : Malloc Zone (2 MB) [86 MB] + * 05600000 - 057FFFFF : BootX Image (2 MB) [88 MB] + * 05800000 - 05FFFFFF : Unused/OF (8 MB) [96 MB] + * + */ + +#define FREE_BASE 0x00004000UL +#define OF_CODE_START 0xfff00000UL +#define OF_CODE_SIZE 0x00100000 +#define IO_BASE 0x80000000UL + +#ifdef __powerpc64__ +#define HASH_BITS 18 +#else +#define HASH_BITS 15 +#endif +#define HASH_SIZE (2 << HASH_BITS) +#define OFMEM_SIZE (1 * 1024 * 1024 + 512 * 1024) + +#define SEGR_USER BIT(2) +#define SEGR_BASE 0x0400 + +static inline unsigned long +get_hash_base(void) +{ + return (mfsdr1() & SDR1_HTABORG_MASK); +} + +static inline unsigned long +get_rom_base(void) +{ + ofmem_t *ofmem = ofmem_arch_get_private(); + return ofmem->ramsize - OF_CODE_SIZE; +} + +static unsigned long +get_ram_top(void) +{ + return get_hash_base() - (32 + 64 + 64) * 1024 - OFMEM_SIZE; +} + +static unsigned long +get_ram_bottom(void) +{ + return FREE_BASE; +} + +static unsigned long get_heap_top(void) +{ + return get_hash_base() - (32 + 64 + 64) * 1024; +} + +static inline size_t ALIGN_SIZE(size_t x, size_t a) +{ + return (x + a - 1) & ~(a - 1); +} + +ofmem_t* ofmem_arch_get_private(void) +{ + return (ofmem_t*)cell2pointer(get_heap_top() - OFMEM_SIZE); +} + +void* ofmem_arch_get_malloc_base(void) +{ + return (char*)ofmem_arch_get_private() + ALIGN_SIZE(sizeof(ofmem_t), 4); +} + +ucell ofmem_arch_get_heap_top(void) +{ + return get_heap_top(); +} + +ucell ofmem_arch_get_virt_top(void) +{ + return IO_BASE; +} + +void ofmem_arch_unmap_pages(ucell virt, ucell size) +{ + /* kill page mappings in provided range */ +} + +void ofmem_arch_map_pages(phys_addr_t phys, ucell virt, ucell size, ucell mode) +{ + /* none yet */ +} + +ucell ofmem_arch_get_iomem_base(void) +{ + /* Currently unused */ + return 0; +} + +ucell ofmem_arch_get_iomem_top(void) +{ + /* Currently unused */ + return 0; +} + +retain_t *ofmem_arch_get_retained(void) +{ + /* not implemented */ + return NULL; +} + +int ofmem_arch_get_physaddr_cellsize(void) +{ +#ifdef CONFIG_PPC64 + return 2; +#else + return 1; +#endif +} + +int ofmem_arch_encode_physaddr(ucell *p, phys_addr_t value) +{ + int n = 0; +#ifdef CONFIG_PPC64 + p[n++] = value >> 32; +#endif + p[n++] = value; + return n; +} + +/* Return size of a single MMU package translation property entry in cells */ +int ofmem_arch_get_translation_entry_size(void) +{ + return 3 + ofmem_arch_get_physaddr_cellsize(); +} + +/* Generate translation property entry for PPC. + * According to the platform bindings for PPC + * (http://www.openfirmware.org/1275/bindings/ppc/release/ppc-2_1.html#REF34579) + * a translation property entry has the following layout: + * + * virtual address + * length + * physical address + * mode + */ +void ofmem_arch_create_translation_entry(ucell *transentry, translation_t *t) +{ + int i = 0; + + transentry[i++] = t->virt; + transentry[i++] = t->size; + i += ofmem_arch_encode_physaddr(&transentry[i], t->phys); + transentry[i++] = t->mode; +} + +/* Return the size of a memory available entry given the phandle in cells */ +int ofmem_arch_get_available_entry_size(phandle_t ph) +{ + if (ph == s_phandle_memory) { + return 1 + ofmem_arch_get_physaddr_cellsize(); + } else { + return 1 + 1; + } +} + +/* Generate memory available property entry for PPC */ +void ofmem_arch_create_available_entry(phandle_t ph, ucell *availentry, phys_addr_t start, ucell size) +{ + int i = 0; + + if (ph == s_phandle_memory) { + i += ofmem_arch_encode_physaddr(availentry, start); + } else { + availentry[i++] = start; + } + + availentry[i] = size; +} + +/************************************************************************/ +/* OF private allocations */ +/************************************************************************/ + +/* Private functions for mapping between physical/virtual addresses */ +phys_addr_t +va2pa(unsigned long va) +{ + if (va >= OF_CODE_START && va < OF_CODE_START + OF_CODE_SIZE) { + return (phys_addr_t)get_rom_base() - OF_CODE_START + va; + } else { + return (phys_addr_t)va; + } +} + +unsigned long +pa2va(phys_addr_t pa) +{ + if ((pa - get_rom_base() + OF_CODE_START >= OF_CODE_START) && + (pa - get_rom_base() + OF_CODE_START < OF_CODE_START + OF_CODE_SIZE)) + return (unsigned long)pa - get_rom_base() + OF_CODE_START; + else + return (unsigned long)pa; +} + +void * +malloc(int size) +{ + return ofmem_malloc(size); +} + +void +free(void *ptr) +{ + ofmem_free(ptr); +} + +void * +realloc(void *ptr, size_t size) +{ + return ofmem_realloc(ptr, size); +} + + +/************************************************************************/ +/* misc */ +/************************************************************************/ + +ucell ofmem_arch_default_translation_mode(phys_addr_t phys) +{ + /* XXX: Guard bit not set as it should! */ + if (phys < IO_BASE) + return 0x02; /*0xa*/ /* wim GxPp */ + return 0x6a; /* WIm GxPp, I/O */ +} + +ucell ofmem_arch_io_translation_mode(phys_addr_t phys) +{ + return 0x6a; /* WIm GxPp, I/O */ +} + +/************************************************************************/ +/* page fault handler */ +/************************************************************************/ + +static phys_addr_t +ea_to_phys(unsigned long ea, ucell *mode) +{ + phys_addr_t phys; + + if (ea >= OF_CODE_START && ea <= 0xffffffffUL) { + /* ROM into RAM */ + ea -= OF_CODE_START; + phys = get_rom_base() + ea; + *mode = 0x02; + return phys; + } + + phys = ofmem_translate(ea, mode); + if (phys == -1) { + phys = ea; + *mode = ofmem_arch_default_translation_mode(phys); + + /* print_virt_range(); */ + /* print_phys_range(); */ + /* print_trans(); */ + } + return phys; +} + +/* Converts a global variable (from .data or .bss) into a pointer that + can be accessed from real mode */ +static void * +global_ptr_real(void *p) +{ + return (void*)((uintptr_t)p - OF_CODE_START + get_rom_base()); +} + +/* Return the next slot to evict, in the range of [0..7] */ +static int +next_evicted_slot(void) +{ + static int next_grab_slot; + int *next_grab_slot_va; + int r; + + next_grab_slot_va = global_ptr_real(&next_grab_slot); + r = *next_grab_slot_va; + *next_grab_slot_va = (r + 1) % 8; + + return r; +} + +static void +hash_page_64(unsigned long ea, phys_addr_t phys, ucell mode) +{ + uint64_t vsid_mask, page_mask, pgidx, hash; + uint64_t htab_mask, mask, avpn; + unsigned long pgaddr; + int i, found; + unsigned int vsid, vsid_sh, sdr, sdr_sh, sdr_mask; + mPTE_64_t *pp; + + vsid = (ea >> 28) + SEGR_BASE; + vsid_sh = 7; + vsid_mask = 0x00003FFFFFFFFF80ULL; + sdr = mfsdr1(); + sdr_sh = 18; + sdr_mask = 0x3FF80; + page_mask = 0x0FFFFFFF; // XXX correct? + pgidx = (ea & page_mask) >> PAGE_SHIFT; + avpn = (vsid << 12) | ((pgidx >> 4) & 0x0F80);; + + hash = ((vsid ^ pgidx) << vsid_sh) & vsid_mask; + htab_mask = 0x0FFFFFFF >> (28 - (sdr & 0x1F)); + mask = (htab_mask << sdr_sh) | sdr_mask; + pgaddr = sdr | (hash & mask); + pp = (mPTE_64_t *)pgaddr; + + /* replace old translation */ + for (found = 0, i = 0; !found && i < 8; i++) + if (pp[i].avpn == avpn) + found = 1; + + /* otherwise use a free slot */ + for (i = 0; !found && i < 8; i++) + if (!pp[i].v) + found = 1; + + /* out of slots, just evict one */ + if (!found) + i = next_evicted_slot() + 1; + i--; + { + mPTE_64_t p = { + // .avpn_low = avpn, + .avpn = avpn >> 7, + .h = 0, + .v = 1, + + .rpn = (phys & ~0xfffUL) >> 12, + .r = mode & (1 << 8) ? 1 : 0, + .c = mode & (1 << 7) ? 1 : 0, + .w = mode & (1 << 6) ? 1 : 0, + .i = mode & (1 << 5) ? 1 : 0, + .m = mode & (1 << 4) ? 1 : 0, + .g = mode & (1 << 3) ? 1 : 0, + .n = mode & (1 << 2) ? 1 : 0, + .pp = mode & 3, + }; + pp[i] = p; + } + + asm volatile("tlbie %0" :: "r"(ea)); +} + +static void +hash_page_32(unsigned long ea, phys_addr_t phys, ucell mode) +{ +#ifndef __powerpc64__ + unsigned long *upte, cmp, hash1; + int i, vsid, found; + mPTE_t *pp; + + vsid = (ea >> 28) + SEGR_BASE; + cmp = BIT(0) | (vsid << 7) | ((ea & 0x0fffffff) >> 22); + + hash1 = vsid; + hash1 ^= (ea >> 12) & 0xffff; + hash1 &= (((mfsdr1() & 0x1ff) << 16) | 0xffff) >> 6; + + pp = (mPTE_t*)(get_hash_base() + (hash1 << 6)); + upte = (unsigned long*)pp; + + /* replace old translation */ + for (found = 0, i = 0; !found && i < 8; i++) + if (cmp == upte[i*2]) + found = 1; + + /* otherwise use a free slot */ + for (i = 0; !found && i < 8; i++) + if (!pp[i].v) + found = 1; + + /* out of slots, just evict one */ + if (!found) + i = next_evicted_slot() + 1; + i--; + upte[i * 2] = cmp; + upte[i * 2 + 1] = (phys & ~0xfff) | mode; + + asm volatile("tlbie %0" :: "r"(ea)); +#endif +} + +static int is_ppc64(void) +{ +#ifdef __powerpc64__ + return 1; +#elif defined(CONFIG_PPC_64BITSUPPORT) + unsigned int pvr = mfpvr(); + return ((pvr >= 0x330000) && (pvr < 0x70330000)); +#else + return 0; +#endif +} + +/* XXX Remove these ugly constructs when legacy 64-bit support is dropped. */ +static void hash_page(unsigned long ea, phys_addr_t phys, ucell mode) +{ + if (is_ppc64()) + hash_page_64(ea, phys, mode); + else + hash_page_32(ea, phys, mode); +} + +void +dsi_exception(void) +{ + unsigned long dar, dsisr; + ucell mode; + phys_addr_t phys; + + asm volatile("mfdar %0" : "=r" (dar) : ); + asm volatile("mfdsisr %0" : "=r" (dsisr) : ); + + phys = ea_to_phys(dar, &mode); + hash_page(dar, phys, mode); +} + +void +isi_exception(void) +{ + unsigned long nip, srr1; + ucell mode; + phys_addr_t phys; + + asm volatile("mfsrr0 %0" : "=r" (nip) : ); + asm volatile("mfsrr1 %0" : "=r" (srr1) : ); + + phys = ea_to_phys(nip, &mode); + hash_page(nip, phys, mode); +} + + +/************************************************************************/ +/* init / cleanup */ +/************************************************************************/ + +void +setup_mmu(unsigned long ramsize) +{ + ofmem_t *ofmem; +#ifndef __powerpc64__ + unsigned long sr_base; +#endif + unsigned long hash_base; + unsigned long hash_mask = ~0x000fffffUL; /* alignment for ppc64 */ + int i; + + /* SDR1: Storage Description Register 1 */ + + hash_base = (ramsize - OF_CODE_SIZE - HASH_SIZE) & hash_mask; + memset((void *)hash_base, 0, HASH_SIZE); + if (is_ppc64()) + mtsdr1(hash_base | MAX(HASH_BITS - 18, 0)); + else + mtsdr1(hash_base | ((HASH_SIZE - 1) >> 16)); + +#ifdef __powerpc64__ + + /* Segment Lookaside Buffer */ + + slbia(); /* Invalidate all SLBs except SLB 0 */ + for (i = 0; i < 16; i++) { + unsigned long rs = (0x400 + i) << SLB_VSID_SHIFT; + unsigned long rb = ((unsigned long)i << 28) | (1 << 27) | i; + slbmte(rs, rb); + } + +#else + + /* Segment Register */ + + sr_base = SEGR_USER | SEGR_BASE ; + for (i = 0; i < 16; i++) { + int j = i << 28; + asm volatile("mtsrin %0,%1" :: "r" (sr_base + i), "r" (j)); + } + +#endif + + ofmem = ofmem_arch_get_private(); + memset(ofmem, 0, sizeof(ofmem_t)); + ofmem->ramsize = ramsize; + + memcpy((void *)get_rom_base(), (void *)OF_CODE_START, OF_CODE_SIZE); + + /* Enable MMU */ + + mtmsr(mfmsr() | MSR_IR | MSR_DR); +} + +void +ofmem_init(void) +{ + ofmem_t *ofmem = ofmem_arch_get_private(); + + /* Map the memory (don't map page 0 to allow catching of NULL dereferences) */ + ofmem_claim_phys(PAGE_SIZE, get_ram_bottom() - PAGE_SIZE, 0); + ofmem_claim_virt(PAGE_SIZE, get_ram_bottom() - PAGE_SIZE, 0); + ofmem_map(PAGE_SIZE, PAGE_SIZE, get_ram_bottom() - PAGE_SIZE, 0); + + /* Mark the first page as non-free */ + ofmem_claim_phys(0, PAGE_SIZE, 0); + ofmem_claim_virt(0, PAGE_SIZE, 0); + + /* Map everything at the top of physical RAM 1:1, minus the OpenBIOS ROM in RAM copy */ + ofmem_claim_phys(get_ram_top(), get_hash_base() + HASH_SIZE - get_ram_top(), 0); + ofmem_claim_virt(get_ram_top(), get_hash_base() + HASH_SIZE - get_ram_top(), 0); + ofmem_map(get_ram_top(), get_ram_top(), get_hash_base() + HASH_SIZE - get_ram_top(), 0); + + /* Map the OpenBIOS ROM in RAM copy */ + ofmem_claim_phys(ofmem->ramsize - OF_CODE_SIZE, OF_CODE_SIZE, 0); + ofmem_claim_virt(OF_CODE_START, OF_CODE_SIZE, 0); + ofmem_map(ofmem->ramsize - OF_CODE_SIZE, OF_CODE_START, OF_CODE_SIZE, 0); +} diff --git a/qemu/roms/openbios/arch/ppc/qemu/qemu.c b/qemu/roms/openbios/arch/ppc/qemu/qemu.c new file mode 100644 index 000000000..381affb77 --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/qemu/qemu.c @@ -0,0 +1,106 @@ +/* + * Creation Date: <2004/08/28 18:38:22 greg> + * Time-stamp: <2004/08/28 18:38:22 greg> + * + * <qemu.c> + * + * Copyright (C) 2004, Greg Watson + * + * derived from mol.c + * + * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#include "config.h" +#include "kernel/kernel.h" +#include "arch/common/nvram.h" +#include "libopenbios/bindings.h" +#include "drivers/drivers.h" +#include "libc/vsprintf.h" +#include "libc/string.h" +#include "libc/byteorder.h" +#include "qemu/qemu.h" +#include <stdarg.h> + +//#define DUMP_NVRAM + +unsigned long virt_offset = 0; + +void +exit( int status __attribute__ ((unused))) +{ + for (;;); +} + +void +fatal_error( const char *err ) +{ + printk("Fatal error: %s\n", err ); + exit(0); +} + +void +panic( const char *err ) +{ + printk("Panic: %s\n", err ); + exit(0); +} + +static int do_indent; + +int +printk( const char *fmt, ... ) +{ + char *p, buf[1024]; + va_list args; + int i; + + va_start(args, fmt); + i = vsnprintf(buf, sizeof(buf), fmt, args); + va_end(args); + + for( p=buf; *p; p++ ) { + if( *p == '\n' ) + do_indent = 0; + if( do_indent++ == 1 ) { + putchar( '>' ); + putchar( '>' ); + putchar( ' ' ); + } + putchar( *p ); + } + return i; +} + +int arch_nvram_size(void) +{ + if (is_apple()) { + return macio_get_nvram_size(); + } else { + // not implemented + } + return 0; +} + +void arch_nvram_put(char *buf) +{ + if (is_apple()) { + macio_nvram_put(buf); + } else { + // not implemented + } +} + +void arch_nvram_get(char *buf) +{ + if (is_apple()) { + macio_nvram_get(buf); + } else { + // not implemented + } +} diff --git a/qemu/roms/openbios/arch/ppc/qemu/qemu.fs b/qemu/roms/openbios/arch/ppc/qemu/qemu.fs new file mode 100644 index 000000000..458af1bc7 --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/qemu/qemu.fs @@ -0,0 +1,95 @@ +\ qemu specific initialization code +\ +\ Copyright (C) 2005 Stefan Reinauer +\ +\ 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 +\ + + +\ ------------------------------------------------------------------------- +\ initialization +\ ------------------------------------------------------------------------- + +: make-openable ( path ) + find-dev if + begin ?dup while + \ install trivial open and close methods + dup active-package! is-open + parent + repeat + then +; + +: preopen ( chosen-str node-path ) + 2dup make-openable + + " /chosen" find-device + open-dev ?dup if + encode-int 2swap property + else + 2drop + then +; + +\ preopen device nodes (and store the ihandles under /chosen) +:noname + " rtc" " rtc" preopen + " memory" " /memory" preopen +; SYSTEM-initializer + + +\ use the tty interface if available +: activate-tty-interface + " /packages/terminal-emulator" find-dev if drop + then +; + +variable keyboard-phandle 0 keyboard-phandle ! + +: (find-keyboard-device) ( phandle -- ) + recursive + keyboard-phandle @ 0= if \ Return first match + >dn.child @ + begin ?dup while + dup dup " device_type" rot get-package-property 0= if + drop dup cstrlen + " keyboard" strcmp 0= if + dup to keyboard-phandle + then + then + (find-keyboard-device) + >dn.peer @ + repeat + else + drop + then +; + +\ create the keyboard devalias +:noname + device-tree @ (find-keyboard-device) + keyboard-phandle @ if + active-package + " /aliases" find-device + keyboard-phandle @ get-package-path + encode-string " keyboard" property + active-package! + then +; SYSTEM-initializer + +\ ------------------------------------------------------------------------- +\ pre-booting +\ ------------------------------------------------------------------------- + +: update-chosen + " /chosen" find-device + stdin @ encode-int " stdin" property + stdout @ encode-int " stdout" property + device-end +; + +:noname + set-defaults +; PREPOST-initializer diff --git a/qemu/roms/openbios/arch/ppc/qemu/qemu.h b/qemu/roms/openbios/arch/ppc/qemu/qemu.h new file mode 100644 index 000000000..6edf4d451 --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/qemu/qemu.h @@ -0,0 +1,24 @@ +/* + * Creation Date: <2004/08/28 17:50:12 stepan> + * Time-stamp: <2004/08/28 17:50:12 stepan> + * + * <qemu.h> + * + * Copyright (C) 2005 Stefan Reinauer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#ifndef _H_QEMU +#define _H_QEMU + +/* vfd.c */ +extern int vfd_draw_str( const char *str ); +extern void vfd_close( void ); + +#include "kernel.h" + +#endif /* _H_QEMU */ diff --git a/qemu/roms/openbios/arch/ppc/qemu/start.S b/qemu/roms/openbios/arch/ppc/qemu/start.S new file mode 100644 index 000000000..ae2fd53dc --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/qemu/start.S @@ -0,0 +1,729 @@ +/* + * Creation Date: <2001/06/16 21:30:18 samuel> + * Time-stamp: <2003/04/04 16:32:06 samuel> + * + * <init.S> + * + * Asm glue for ELF images + * + * Copyright (C) 2001, 2002, 2003 Samuel Rydh (samuel@ibrium.se) + * + * 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 + * + */ + +#include "autoconf.h" +#include "asm/asmdefs.h" +#include "asm/processor.h" + +/************************************************************************/ +/* Macros */ +/************************************************************************/ + +#define ILLEGAL_VECTOR( v ) .org __vectors + v ; vector__##v: bl trap_error ; +#define VECTOR( v, dummystr ) .org __vectors + v ; vector__##v + +#ifdef CONFIG_PPC_64BITSUPPORT + +/* We're trying to use the same code for the ppc32 and ppc64 handlers here. + * On ppc32 we only save/restore the registers, C considers volatile. + * + * On ppc64 on the other hand, we have to save/restore all registers, because + * all OF code is 32 bits, which only saves/restores the low 32 bits of the + * registers it clobbers. + */ + +#define EXCEPTION_PREAMBLE_TEMPLATE \ + mtsprg1 r1 ; /* scratch */ \ + mfcr r1 ; \ + mtsprg2 r1 ; /* scratch */ \ + lis r1, 0x8000 ; /* r1=0x80000000 */ \ + add. r1,r1,r1 ; /* r1=r1+r1 (high 32bit !0) */ \ + beq 1f; \ + \ + mfmsr r1 ; /* unset MSR_SF */ \ + clrldi r1,r1,1 ; \ + mtmsrd r1 ; \ +1: \ + mfsprg0 r1 ; /* exception stack in sprg0 */ \ +.ifc ULONG_SIZE, 8 ; \ + addi r1,r1,-(40 * ULONG_SIZE) ; /* push exception frame */ \ +.else ; \ + addi r1,r1,-(20 * ULONG_SIZE) ; /* push exception frame */ \ +.endif ; \ + \ + stl r0,(0 * ULONG_SIZE)(r1) ; /* save r0 */ \ + mfsprg1 r0 ; \ + stl r0,(1 * ULONG_SIZE)(r1) ; /* save r1 */ \ + stl r2,(2 * ULONG_SIZE)(r1) ; /* save r2 */ \ + stl r3,(3 * ULONG_SIZE)(r1) ; /* save r3 */ \ + stl r4,(4 * ULONG_SIZE)(r1) ; \ + stl r5,(5 * ULONG_SIZE)(r1) ; \ + stl r6,(6 * ULONG_SIZE)(r1) ; \ + stl r7,(7 * ULONG_SIZE)(r1) ; \ + stl r8,(8 * ULONG_SIZE)(r1) ; \ + stl r9,(9 * ULONG_SIZE)(r1) ; \ + stl r10,(10 * ULONG_SIZE)(r1) ; \ + stl r11,(11 * ULONG_SIZE)(r1) ; \ + stl r12,(12 * ULONG_SIZE)(r1) ; \ +.ifc ULONG_SIZE, 8 ; \ + stl r13,(17 * ULONG_SIZE)(r1) ; \ + stl r14,(18 * ULONG_SIZE)(r1) ; \ + stl r15,(19 * ULONG_SIZE)(r1) ; \ + stl r16,(20 * ULONG_SIZE)(r1) ; \ + stl r17,(21 * ULONG_SIZE)(r1) ; \ + stl r18,(22 * ULONG_SIZE)(r1) ; \ + stl r19,(23 * ULONG_SIZE)(r1) ; \ + stl r20,(24 * ULONG_SIZE)(r1) ; \ + stl r21,(25 * ULONG_SIZE)(r1) ; \ + stl r22,(26 * ULONG_SIZE)(r1) ; \ + stl r23,(27 * ULONG_SIZE)(r1) ; \ + stl r24,(28 * ULONG_SIZE)(r1) ; \ + stl r25,(29 * ULONG_SIZE)(r1) ; \ + stl r26,(30 * ULONG_SIZE)(r1) ; \ + stl r27,(31 * ULONG_SIZE)(r1) ; \ + stl r28,(32 * ULONG_SIZE)(r1) ; \ + stl r29,(33 * ULONG_SIZE)(r1) ; \ + stl r30,(34 * ULONG_SIZE)(r1) ; \ + stl r31,(35 * ULONG_SIZE)(r1) ; \ +.endif ; \ + \ + mflr r0 ; \ + stl r0,(13 * ULONG_SIZE)(r1) ; \ + mfsprg2 r0 ; \ + stl r0,(14 * ULONG_SIZE)(r1) ; \ + mfctr r0 ; \ + stl r0,(15 * ULONG_SIZE)(r1) ; \ + mfxer r0 ; \ + stl r0,(16 * ULONG_SIZE)(r1) ; \ + \ + /* 76(r1) unused */ \ + addi r1,r1,-16 ; /* C ABI uses 0(r1) and 4(r1)... */ + +#define EXCEPTION_EPILOGUE_TEMPLATE \ + addi r1,r1,16 ; /* pop ABI frame */ \ +\ + ll r0,(13 * ULONG_SIZE)(r1) ; \ + mtlr r0 ; \ + ll r0,(14 * ULONG_SIZE)(r1) ; \ + mtcr r0 ; \ + ll r0,(15 * ULONG_SIZE)(r1) ; \ + mtctr r0 ; \ + ll r0,(16 * ULONG_SIZE)(r1) ; \ + mtxer r0 ; \ +\ + ll r0,(0 * ULONG_SIZE)(r1) ; \ + ll r2,(2 * ULONG_SIZE)(r1) ; \ + ll r3,(3 * ULONG_SIZE)(r1) ; \ + ll r4,(4 * ULONG_SIZE)(r1) ; \ + ll r5,(5 * ULONG_SIZE)(r1) ; \ + ll r6,(6 * ULONG_SIZE)(r1) ; \ + ll r7,(7 * ULONG_SIZE)(r1) ; \ + ll r8,(8 * ULONG_SIZE)(r1) ; \ + ll r9,(9 * ULONG_SIZE)(r1) ; \ + ll r10,(10 * ULONG_SIZE)(r1) ; \ + ll r11,(11 * ULONG_SIZE)(r1) ; \ + ll r12,(12 * ULONG_SIZE)(r1) ; \ +.ifc ULONG_SIZE, 8 ; \ + ll r13,(17 * ULONG_SIZE)(r1) ; \ + ll r14,(18 * ULONG_SIZE)(r1) ; \ + ll r15,(19 * ULONG_SIZE)(r1) ; \ + ll r16,(20 * ULONG_SIZE)(r1) ; \ + ll r17,(21 * ULONG_SIZE)(r1) ; \ + ll r18,(22 * ULONG_SIZE)(r1) ; \ + ll r19,(23 * ULONG_SIZE)(r1) ; \ + ll r20,(24 * ULONG_SIZE)(r1) ; \ + ll r21,(25 * ULONG_SIZE)(r1) ; \ + ll r22,(26 * ULONG_SIZE)(r1) ; \ + ll r23,(27 * ULONG_SIZE)(r1) ; \ + ll r24,(28 * ULONG_SIZE)(r1) ; \ + ll r25,(29 * ULONG_SIZE)(r1) ; \ + ll r26,(30 * ULONG_SIZE)(r1) ; \ + ll r27,(31 * ULONG_SIZE)(r1) ; \ + ll r28,(32 * ULONG_SIZE)(r1) ; \ + ll r29,(33 * ULONG_SIZE)(r1) ; \ + ll r30,(34 * ULONG_SIZE)(r1) ; \ + ll r31,(35 * ULONG_SIZE)(r1) ; \ +.endif ; \ + ll r1,(1 * ULONG_SIZE)(r1) ; /* restore stack at last */ \ + rfi + +// PPC32 + +#define ULONG_SIZE 4 +#define stl stw +#define ll lwz + +.macro EXCEPTION_PREAMBLE + EXCEPTION_PREAMBLE_TEMPLATE +.endm + +.macro EXCEPTION_EPILOGUE + EXCEPTION_EPILOGUE_TEMPLATE +.endm + +#undef ULONG_SIZE +#undef stl +#undef ll + +// PPC64 + +#define ULONG_SIZE 8 +#define stl std +#define ll ld + +.macro EXCEPTION_PREAMBLE_64 + EXCEPTION_PREAMBLE_TEMPLATE +.endm + +.macro EXCEPTION_EPILOGUE_64 + EXCEPTION_EPILOGUE_TEMPLATE +.endm + +#undef ULONG_SIZE +#undef stl +#undef ll + +#define ULONG_SIZE 4 +#define STACKFRAME_MINSIZE 16 + +#else /* !CONFIG_PPC_64BITSUPPORT */ + +#ifdef __powerpc64__ + +#define ULONG_SIZE 8 +#define STACKFRAME_MINSIZE 48 +#define stl std +#define ll ld + +#else + +#define ULONG_SIZE 4 +#define STACKFRAME_MINSIZE 16 +#define stl stw +#define ll lwz + +#endif + +.macro EXCEPTION_PREAMBLE + mtsprg1 r1 /* scratch */ + mfsprg0 r1 /* exception stack in sprg0 */ + addi r1, r1, -(20 * ULONG_SIZE) /* push exception frame */ + + stl r0, ( 0 * ULONG_SIZE)(r1) /* save r0 */ + mfsprg1 r0 + stl r0, ( 1 * ULONG_SIZE)(r1) /* save r1 */ + stl r2, ( 2 * ULONG_SIZE)(r1) /* save r2 */ + stl r3, ( 3 * ULONG_SIZE)(r1) /* save r3 */ + stl r4, ( 4 * ULONG_SIZE)(r1) + stl r5, ( 5 * ULONG_SIZE)(r1) + stl r6, ( 6 * ULONG_SIZE)(r1) + stl r7, ( 7 * ULONG_SIZE)(r1) + stl r8, ( 8 * ULONG_SIZE)(r1) + stl r9, ( 9 * ULONG_SIZE)(r1) + stl r10, (10 * ULONG_SIZE)(r1) + stl r11, (11 * ULONG_SIZE)(r1) + stl r12, (12 * ULONG_SIZE)(r1) + + mflr r0 + stl r0, (13 * ULONG_SIZE)(r1) + mfcr r0 + stl r0, (14 * ULONG_SIZE)(r1) + mfctr r0 + stl r0, (15 * ULONG_SIZE)(r1) + mfxer r0 + stl r0, (16 * ULONG_SIZE)(r1) + + addi r1, r1, -STACKFRAME_MINSIZE /* C ABI saves LR and SP */ +.endm + +.macro EXCEPTION_EPILOGUE + addi r1, r1, STACKFRAME_MINSIZE /* pop ABI frame */ + + ll r0, (13 * ULONG_SIZE)(r1) + mtlr r0 + ll r0, (14 * ULONG_SIZE)(r1) + mtcr r0 + ll r0, (15 * ULONG_SIZE)(r1) + mtctr r0 + ll r0, (16 * ULONG_SIZE)(r1) + mtxer r0 + + ll r0, ( 0 * ULONG_SIZE)(r1) + ll r2, ( 2 * ULONG_SIZE)(r1) + ll r3, ( 3 * ULONG_SIZE)(r1) + ll r4, ( 4 * ULONG_SIZE)(r1) + ll r5, ( 5 * ULONG_SIZE)(r1) + ll r6, ( 6 * ULONG_SIZE)(r1) + ll r7, ( 7 * ULONG_SIZE)(r1) + ll r8, ( 8 * ULONG_SIZE)(r1) + ll r9, ( 9 * ULONG_SIZE)(r1) + ll r10, (10 * ULONG_SIZE)(r1) + ll r11, (11 * ULONG_SIZE)(r1) + ll r12, (12 * ULONG_SIZE)(r1) + + ll r1, ( 1 * ULONG_SIZE)(r1) /* restore stack at last */ + RFI +.endm + +#endif /* !CONFIG_PPC_64BITSUPPORT */ + +/************************************************************************/ +/* vectors */ +/************************************************************************/ + + .section .text.vectors, "ax" +GLOBL(__vectors): + nop // NULL-jmp trap +1: nop // + b 1b + +VECTOR( 0x100, "SRE" ): + b _entry + +trap_error: + lis r1, 0x8000 /* r1=0x80000000 */ + add. r1,r1,r1 /* r1=r1+r1 (high 32bit !0) */ + beq 1f + + mfmsr r1 /* unset MSR_SF */ + clrldi r1,r1,1 + mtmsrd r1 +1: + mflr r3 + LOAD_REG_FUNC(r4, unexpected_excep) + mtctr r4 + bctr + +ILLEGAL_VECTOR( 0x200 ) + +VECTOR( 0x300, "DSI" ): + b real_dsi + +ILLEGAL_VECTOR( 0x380 ) + +VECTOR( 0x400, "ISI" ): + b real_isi + +ILLEGAL_VECTOR( 0x480 ) + + ILLEGAL_VECTOR( 0x500 ) + ILLEGAL_VECTOR( 0x600 ) + ILLEGAL_VECTOR( 0x700 ) + +VECTOR( 0x800, "FPU" ): + mtsprg1 r3 + mfsrr1 r3 + ori r3,r3,0x2000 + mtsrr1 r3 + mfsprg1 r3 + RFI + +ILLEGAL_VECTOR( 0x900 ) +ILLEGAL_VECTOR( 0xa00 ) +ILLEGAL_VECTOR( 0xb00 ) +ILLEGAL_VECTOR( 0xc00 ) +ILLEGAL_VECTOR( 0xd00 ) +ILLEGAL_VECTOR( 0xe00 ) +ILLEGAL_VECTOR( 0xf00 ) +ILLEGAL_VECTOR( 0xf20 ) +ILLEGAL_VECTOR( 0x1000 ) +ILLEGAL_VECTOR( 0x1100 ) +ILLEGAL_VECTOR( 0x1200 ) +ILLEGAL_VECTOR( 0x1300 ) +ILLEGAL_VECTOR( 0x1400 ) +ILLEGAL_VECTOR( 0x1500 ) +ILLEGAL_VECTOR( 0x1600 ) +ILLEGAL_VECTOR( 0x1700 ) + +#ifdef CONFIG_PPC_64BITSUPPORT + +VECTOR( 0x2000, "DSI_64" ): + EXCEPTION_PREAMBLE_64 + LOAD_REG_IMMEDIATE(r3, dsi_exception) + mtctr r3 + bctrl + EXCEPTION_EPILOGUE_64 + +VECTOR( 0x2200, "ISI_64" ): + EXCEPTION_PREAMBLE_64 + LOAD_REG_IMMEDIATE(r3, isi_exception) + mtctr r3 + bctrl + EXCEPTION_EPILOGUE_64 + +#endif + +real_dsi: + EXCEPTION_PREAMBLE + LOAD_REG_FUNC(r3, dsi_exception) + mtctr r3 + bctrl + b exception_return + +real_isi: + EXCEPTION_PREAMBLE + LOAD_REG_FUNC(r3, isi_exception) + mtctr r3 + bctrl + b exception_return + +exception_return: + EXCEPTION_EPILOGUE + +GLOBL(__vectors_end): + +/************************************************************************/ +/* entry */ +/************************************************************************/ + +GLOBL(_entry): + +#ifdef CONFIG_PPC_64BITSUPPORT + li r0,0 + + lis r3, 0x8000 /* r1=0x80000000 */ + add. r3,r3,r3 /* r1=r1+r1 (high 32bit !0) */ + beq no_64bit /* only true when !MSR_SF */ + + /* clear MSR, disable MMU, SF */ + mtmsrd r0 + b real_entry + +no_64bit: + /* clear MSR, disable MMU */ + mtmsr r0 + +real_entry: +#endif + + /* copy exception vectors */ + + LOAD_REG_IMMEDIATE(r3, __vectors) + li r4,0 + li r5,__vectors_end - __vectors + 16 + rlwinm r5,r5,0,0,28 +1: lwz r6,0(r3) + lwz r7,4(r3) + lwz r8,8(r3) + lwz r9,12(r3) + stw r6,0(r4) + stw r7,4(r4) + stw r8,8(r4) + stw r9,12(r4) + dcbst 0,r4 + sync + icbi 0,r4 + sync + addi r5,r5,-16 + addi r3,r3,16 + addi r4,r4,16 + cmpwi r5,0 + bgt 1b + isync + + bl compute_ramsize + + /* Memory map: + * + * Top +-------------------------+ + * | | + * | ROM into RAM (1 MB) | + * | | + * +-------------------------+ + * | | + * | MMU Hash Table (64 kB) | + * | | + * +-------------------------+ + * | | + * | Exception Stack (32 kB) | + * | | + * +-------------------------+ + * | | + * | Stack (64 kB) | + * | | + * +-------------------------+ + * | | + * | Client Stack (64 kB) | + * | | + * +-------------------------+ + * | | + * | Malloc Zone (2 MiB) | + * | | + * +-------------------------+ + * : : + * Bottom + */ + + addis r1, r3, -16 /* ramsize - 1MB */ + + /* setup hash table */ + + addis r1, r1, -1 /* - 64 kB */ + clrrwi r1, r1, 5*4 /* & ~0xfffff */ + + /* setup exception stack */ + + mtsprg0 r1 + + /* setup stack */ + + addi r1, r1, -32768 /* - 32 kB */ + + /* save memory size in stack */ + +#ifdef __powerpc64__ + /* set up TOC pointer */ + + LOAD_REG_IMMEDIATE(r2, setup_mmu) + ld r2, 8(r2) +#endif + + bl BRANCH_LABEL(setup_mmu) + bl BRANCH_LABEL(entry) +1: nop + b 1b + + + /* According to IEEE 1275, PPC bindings: + * + * MSR = FP, ME + (DR|IR) + * r1 = stack (32 K + 32 bytes link area above) + * r5 = client interface handler + * r6 = address of client program arguments (unused) + * r7 = length of client program arguments (unused) + * + * Yaboot and Linux use r3 and r4 for initrd address and size + */ + .data +saved_stack: + DATA_LONG(0) + .previous + /* void call_elf( arg1, arg2, entry ) */ +_GLOBAL(call_elf): + mflr r0 + PPC_STLU r1, -STACKFRAME_MINSIZE(r1) + PPC_STL r0, (STACKFRAME_MINSIZE + PPC_LR_STKOFF)(r1) + mtlr r5 + LOAD_REG_IMMEDIATE(r8, saved_stack) // save our stack pointer + PPC_STL r1,0(r8) + mfsdr1 r1 + addi r1, r1, -32768 /* - 32 KiB exception stack */ + addis r1, r1, -1 /* - 64 KiB stack */ + LOAD_REG_IMMEDIATE(r5, of_client_callback) // r5 = callback + li r6,0 // r6 = address of client program arguments (unused) + li r7,0 // r7 = length of client program arguments (unused) + li r0,MSR_FP | MSR_ME | MSR_DR | MSR_IR + MTMSRD(r0) + blrl + +#ifdef CONFIG_PPC64 + /* Restore SF bit */ + LOAD_REG_IMMEDIATE(r0, MSR_SF | MSR_FP | MSR_ME | MSR_DR | MSR_IR) + MTMSRD(r0) +#endif + LOAD_REG_IMMEDIATE(r8, saved_stack) // restore stack pointer + mr r1,r8 + PPC_LL r0, (STACKFRAME_MINSIZE + PPC_LR_STKOFF)(r1) + mtlr r0 + addi r1, r1, STACKFRAME_MINSIZE + // XXX: should restore r12-r31 etc.. + // we should not really come here though + blr + +#ifdef __powerpc64__ +#define STKOFF STACKFRAME_MINSIZE +#define SAVE_SPACE 320 +#else +#define STKOFF 8 +#define SAVE_SPACE 144 +#endif +GLOBL(of_client_callback): + +#ifdef CONFIG_PPC64 + PPC_STLU r1, -(STACKFRAME_MINSIZE + 16)(r1) +#else + PPC_STLU r1, -STACKFRAME_MINSIZE(r1) /* fits within alignment */ +#endif + + /* save r4 */ + + PPC_STL r4, STKOFF(r1) + + /* save lr */ + + mflr r4 + PPC_STL r4, PPC_LR_STKOFF(r1) + + /* restore OF stack */ + + LOAD_REG_IMMEDIATE(r4, saved_stack) + PPC_LL r4, 0(r4) + + PPC_STLU r4,-SAVE_SPACE(r4) + PPC_STL r1,(STKOFF)(r4) // save caller stack + mr r1,r4 + + PPC_STL r2, (STKOFF + 1 * ULONG_SIZE)(r1) + PPC_STL r0, (STKOFF + 2 * ULONG_SIZE)(r1) + + /* save ctr, cr and xer */ + + mfctr r2 + PPC_STL r2, (STKOFF + 3 * ULONG_SIZE)(r1) + mfcr r2 + PPC_STL r2, (STKOFF + 4 * ULONG_SIZE)(r1) + mfxer r2 + PPC_STL r2, (STKOFF + 5 * ULONG_SIZE)(r1) + + /* save r5 - r31 */ + + PPC_STL r5, (STKOFF + 6 * ULONG_SIZE)(r1) + PPC_STL r6, (STKOFF + 7 * ULONG_SIZE)(r1) + PPC_STL r7, (STKOFF + 8 * ULONG_SIZE)(r1) + PPC_STL r8, (STKOFF + 9 * ULONG_SIZE)(r1) + PPC_STL r9, (STKOFF + 10 * ULONG_SIZE)(r1) + PPC_STL r10, (STKOFF + 11 * ULONG_SIZE)(r1) + PPC_STL r11, (STKOFF + 12 * ULONG_SIZE)(r1) + PPC_STL r12, (STKOFF + 13 * ULONG_SIZE)(r1) + PPC_STL r13, (STKOFF + 14 * ULONG_SIZE)(r1) + PPC_STL r14, (STKOFF + 15 * ULONG_SIZE)(r1) + PPC_STL r15, (STKOFF + 16 * ULONG_SIZE)(r1) + PPC_STL r16, (STKOFF + 17 * ULONG_SIZE)(r1) + PPC_STL r17, (STKOFF + 18 * ULONG_SIZE)(r1) + PPC_STL r18, (STKOFF + 19 * ULONG_SIZE)(r1) + PPC_STL r19, (STKOFF + 20 * ULONG_SIZE)(r1) + PPC_STL r20, (STKOFF + 21 * ULONG_SIZE)(r1) + PPC_STL r21, (STKOFF + 22 * ULONG_SIZE)(r1) + PPC_STL r22, (STKOFF + 23 * ULONG_SIZE)(r1) + PPC_STL r23, (STKOFF + 24 * ULONG_SIZE)(r1) + PPC_STL r24, (STKOFF + 25 * ULONG_SIZE)(r1) + PPC_STL r25, (STKOFF + 26 * ULONG_SIZE)(r1) + PPC_STL r26, (STKOFF + 27 * ULONG_SIZE)(r1) + PPC_STL r27, (STKOFF + 28 * ULONG_SIZE)(r1) + PPC_STL r28, (STKOFF + 29 * ULONG_SIZE)(r1) + PPC_STL r29, (STKOFF + 30 * ULONG_SIZE)(r1) + PPC_STL r30, (STKOFF + 31 * ULONG_SIZE)(r1) + PPC_STL r31, (STKOFF + 32 * ULONG_SIZE)(r1) + +#ifdef CONFIG_PPC64 + LOAD_REG_IMMEDIATE(r2, of_client_interface) + ld r2, 8(r2) +#endif + bl BRANCH_LABEL(of_client_interface) + + /* restore r5 - r31 */ + + PPC_LL r5, (STKOFF + 6 * ULONG_SIZE)(r1) + PPC_LL r6, (STKOFF + 7 * ULONG_SIZE)(r1) + PPC_LL r7, (STKOFF + 8 * ULONG_SIZE)(r1) + PPC_LL r8, (STKOFF + 9 * ULONG_SIZE)(r1) + PPC_LL r9, (STKOFF + 10 * ULONG_SIZE)(r1) + PPC_LL r10, (STKOFF + 11 * ULONG_SIZE)(r1) + PPC_LL r11, (STKOFF + 12 * ULONG_SIZE)(r1) + PPC_LL r12, (STKOFF + 13 * ULONG_SIZE)(r1) + PPC_LL r13, (STKOFF + 14 * ULONG_SIZE)(r1) + PPC_LL r14, (STKOFF + 15 * ULONG_SIZE)(r1) + PPC_LL r15, (STKOFF + 16 * ULONG_SIZE)(r1) + PPC_LL r16, (STKOFF + 17 * ULONG_SIZE)(r1) + PPC_LL r17, (STKOFF + 18 * ULONG_SIZE)(r1) + PPC_LL r18, (STKOFF + 19 * ULONG_SIZE)(r1) + PPC_LL r19, (STKOFF + 20 * ULONG_SIZE)(r1) + PPC_LL r20, (STKOFF + 21 * ULONG_SIZE)(r1) + PPC_LL r21, (STKOFF + 22 * ULONG_SIZE)(r1) + PPC_LL r22, (STKOFF + 23 * ULONG_SIZE)(r1) + PPC_LL r23, (STKOFF + 24 * ULONG_SIZE)(r1) + PPC_LL r24, (STKOFF + 25 * ULONG_SIZE)(r1) + PPC_LL r25, (STKOFF + 26 * ULONG_SIZE)(r1) + PPC_LL r26, (STKOFF + 27 * ULONG_SIZE)(r1) + PPC_LL r27, (STKOFF + 28 * ULONG_SIZE)(r1) + PPC_LL r28, (STKOFF + 29 * ULONG_SIZE)(r1) + PPC_LL r29, (STKOFF + 30 * ULONG_SIZE)(r1) + PPC_LL r30, (STKOFF + 31 * ULONG_SIZE)(r1) + PPC_LL r31, (STKOFF + 32 * ULONG_SIZE)(r1) + + /* restore ctr, cr and xer */ + + PPC_LL r2, (STKOFF + 3 * ULONG_SIZE)(r1) + mtctr r2 + PPC_LL r2, (STKOFF + 4 * ULONG_SIZE)(r1) + mtcr r2 + PPC_LL r2, (STKOFF + 5 * ULONG_SIZE)(r1) + mtxer r2 + + /* restore r0 and r2 */ + + PPC_LL r2, (STKOFF + 1 * ULONG_SIZE)(r1) + PPC_LL r0, (STKOFF + 2 * ULONG_SIZE)(r1) + + /* restore caller stack */ + + PPC_LL r1, (STKOFF)(r1) + + PPC_LL r4, PPC_LR_STKOFF(r1) + mtlr r4 + PPC_LL r4, STKOFF(r1) + PPC_LL r1, 0(r1) + + blr + + /* rtas glue (must be reloctable) */ +GLOBL(of_rtas_start): + /* r3 = argument buffer, r4 = of_rtas_start */ + /* according to the CHRP standard, cr must be preserved (cr0/cr1 too?) */ + blr +GLOBL(of_rtas_end): + + +#define CACHE_LINE_SIZE 32 +#define LG_CACHE_LINE_SIZE 5 + +/* flush_icache_range( unsigned long start, unsigned long stop) */ +_GLOBAL(flush_icache_range): + li r5,CACHE_LINE_SIZE-1 + andc r3,r3,r5 + subf r4,r3,r4 + add r4,r4,r5 + srwi. r4,r4,LG_CACHE_LINE_SIZE + beqlr + mtctr r4 + mr r6,r3 +1: dcbst 0,r3 + addi r3,r3,CACHE_LINE_SIZE + bdnz 1b + sync /* wait for dcbst's to get to ram */ + mtctr r4 +2: icbi 0,r6 + addi r6,r6,CACHE_LINE_SIZE + bdnz 2b + sync /* additional sync needed on g4 */ + isync + blr + + /* Get RAM size from QEMU configuration device */ + +#define CFG_ADDR 0xf0000510 +#define FW_CFG_RAM_SIZE 0x03 + +compute_ramsize: + LOAD_REG_IMMEDIATE(r9, CFG_ADDR) + li r0,FW_CFG_RAM_SIZE + sth r0,0(r9) + LOAD_REG_IMMEDIATE(r9, CFG_ADDR + 2) + lbz r1,0(r9) + lbz r0,0(r9) + slwi r0,r0,8 + or r1,r1,r0 + lbz r0,0(r9) + slwi r0,r0,16 + or r1,r1,r0 + lbz r0,0(r9) + slwi r0,r0,24 + or r3,r1,r0 + blr + + /* Hard reset vector */ + .section .romentry,"ax" + bl _entry diff --git a/qemu/roms/openbios/arch/ppc/qemu/tree.fs b/qemu/roms/openbios/arch/ppc/qemu/tree.fs new file mode 100644 index 000000000..1ed838397 --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/qemu/tree.fs @@ -0,0 +1,71 @@ +\ QEMU specific initialization code +\ +\ 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 +\ + +include config.fs + +\ ------------------------------------------------------------- +\ device-tree +\ ------------------------------------------------------------- + +" /" find-device +\ Apple calls the root node device-tree +" device-tree" device-name +[IFDEF] CONFIG_PPC64 2 [ELSE] 1 [THEN] encode-int " #address-cells" property +1 encode-int " #size-cells" property +h# 05f5e100 encode-int " clock-frequency" property + +new-device + " cpus" device-name + 1 encode-int " #address-cells" property + 0 encode-int " #size-cells" property + external + + : encode-unit ( unit -- str len ) + pocket tohexstr + ; + + : decode-unit ( str len -- unit ) + parse-hex + ; + +finish-device + +new-device + " memory" device-name + " memory" device-type + external + : open true ; + : close ; +finish-device + +\ ------------------------------------------------------------- +\ /packages +\ ------------------------------------------------------------- + +" /packages" find-device + + " packages" device-name + external + \ allow packages to be opened with open-dev + : open true ; + : close ; + +\ /packages/terminal-emulator +new-device + " terminal-emulator" device-name + external + : open true ; + : close ; + \ : write ( addr len -- actual ) + \ dup -rot type + \ ; +finish-device + +\ ------------------------------------------------------------- +\ The END +\ ------------------------------------------------------------- +device-end diff --git a/qemu/roms/openbios/arch/ppc/qemu/vfd.c b/qemu/roms/openbios/arch/ppc/qemu/vfd.c new file mode 100644 index 000000000..308d0e338 --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/qemu/vfd.c @@ -0,0 +1,42 @@ +/* + * Creation Date: <2004/08/28 17:29:43 greg> + * Time-stamp: <2004/08/28 17:29:43 greg> + * + * <vfd.c> + * + * Simple text console + * + * Copyright (C) 2004 Greg Watson + * + * 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 + * + */ + +#include "config.h" +#include "libopenbios/bindings.h" +#include "qemu/qemu.h" + +static int vfd_is_open; + +static int +vfd_init( void ) +{ + vfd_is_open = 1; + return 0; +} + +void +vfd_close( void ) +{ +} + +int +vfd_draw_str( const char *str ) +{ + if (!vfd_is_open) + vfd_init(); + + return 0; +} diff --git a/qemu/roms/openbios/arch/ppc/start.S b/qemu/roms/openbios/arch/ppc/start.S new file mode 100644 index 000000000..40ee08963 --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/start.S @@ -0,0 +1,335 @@ +/* + * Creation Date: <2001/06/16 21:30:18 samuel> + * Time-stamp: <2003/04/04 16:32:06 samuel> + * + * <init.S> + * + * Asm glue for ELF images run inside MOL + * + * Copyright (C) 2001, 2002, 2003 Samuel Rydh (samuel@ibrium.se) + * + * 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 + * + */ + +#include "asm/asmdefs.h" +#include "asm/processor.h" +#include "osi.h" + +/************************************************************************/ +/* Macros */ +/************************************************************************/ + +#define ILLEGAL_VECTOR( v ) .org __vectors + v ; bl trap_error ; +#define VECTOR( v, dummystr ) .org __vectors + v ; vector__##v + +#define EXCEPTION_PREAMBLE \ + mtsprg1 r1 ; /* scratch */ \ + mfsprg0 r1 ; /* exception stack in sprg0 */ \ + addi r1,r1,-80 ; /* push exception frame */ \ + \ + stw r0,0(r1) ; /* save r0 */ \ + mfsprg1 r0 ; \ + stw r0,4(r1) ; /* save r1 */ \ + stw r2,8(r1) ; /* save r2 */ \ + stw r3,12(r1) ; /* save r3 */ \ + stw r4,16(r1) ; \ + stw r5,20(r1) ; \ + stw r6,24(r1) ; \ + stw r7,28(r1) ; \ + stw r8,32(r1) ; \ + stw r9,36(r1) ; \ + stw r10,40(r1) ; \ + stw r11,44(r1) ; \ + stw r12,48(r1) ; \ + \ + mflr r0 ; \ + stw r0,52(r1) ; \ + mfcr r0 ; \ + stw r0,56(r1) ; \ + mfctr r0 ; \ + stw r0,60(r1) ; \ + mfxer r0 ; \ + stw r0,64(r1) ; \ + \ + /* 76(r1) unused */ \ + addi r1,r1,-16 ; /* call conventions uses 0(r1) and 4(r1)... */ + + +/************************************************************************/ +/* stack space */ +/************************************************************************/ + + .section .bss + .balign 32 + .space 32*1024 // 32 K client stack +client_stack: + .space 128 + + .space 64*1024 // 64 K stack +stack: .space 64 + + .space 32*1024 // 32 K exception stack +estack: .space 128 + + +/************************************************************************/ +/* entry */ +/************************************************************************/ + + .text +GLOBL(_start): + li r0,0 + mtmsr r0 + + lis r1,HA(estack) + addi r1,r1,LO(estack) + mtsprg0 r1 // setup exception stack + lis r1,HA(stack) + addi r1,r1,LO(stack) + + // copy exception vectors + lis r3,HA(__vectors) + addi r3,r3,LO(__vectors) + li r4,0 + li r5,__vectors_end - __vectors + 16 + rlwinm r5,r5,0,0,28 +1: lwz r6,0(r3) + lwz r7,4(r3) + lwz r8,8(r3) + lwz r9,12(r3) + stw r6,0(r4) + stw r7,4(r4) + stw r8,8(r4) + stw r9,12(r4) + dcbst 0,r4 + sync + icbi 0,r4 + sync + addi r5,r5,-16 + addi r3,r3,16 + addi r4,r4,16 + cmpwi r5,0 + bgt 1b + isync + + bl setup_mmu + bl entry +1: nop + b 1b + + + /* According to IEEE 1275, PPC bindings: + * + * MSR = FP, ME + (DR|IR) + * r1 = stack (32 K + 32 bytes link area above) + * r5 = clint interface handler + * r6 = address of client program arguments (unused) + * r7 = length of client program arguments (unsed) + */ +saved_stack: + .long 0 + /* void call_elf( entry ) */ +GLOBL(call_elf): + mflr r0 + stwu r1,-16(r1) + stw r0,20(r1) + mtlr r3 + lis r8,HA(saved_stack) + addi r8,r8,LO(saved_stack) // save our stack pointer + stw r1,0(r8) + lis r1,HA(client_stack) + addi r1,r1,LO(client_stack) + lis r5,HA(of_client_callback) + addi r5,r5,LO(of_client_callback) // r5 = callback + li r6,0 // r6 = address of client program arguments (unused) + li r7,0 // r7 = length of client program arguments (unused) + li r0,MSR_FP | MSR_ME | MSR_DR | MSR_IR + mtmsr r0 + blrl + + lis r8,HA(saved_stack) + addi r8,r8,LO(saved_stack) // restore stack pointer + mr r1,r8 + lwz r0,20(r1) + mtlr r0 + addi r1,r1,16 + // XXX: should restore r12-r31 etc.. + // we should not really come here though + blr + +GLOBL(of_client_callback): + lis r4,HA(saved_stack) + addi r4,r4,LO(saved_stack) + lwz r4,0(r4) + stwu r4,-32(r4) + mflr r5 + stw r5,32+4(r4) + stw r1,8(r4) // save caller stack + mr r1,r4 + stw r2,12(r1) + stw r0,16(r1) + mfctr r2 + stw r2,20(r1) + mfcr r2 + stw r2,24(r1) + mfxer r2 + stw r2,28(r1) + // do we need to save more registers? + bl of_client_interface + lwz r4,32+4(r1) + mtlr r4 + lwz r2,20(r1) + mtctr r2 + lwz r2,24(r1) + mtcr r2 + lwz r2,28(r1) + mtxer r2 + lwz r2,12(r1) + lwz r0,16(r1) + lwz r1,8(r1) // restore caller stack + blr + + /* rtas glue (must be reloctable) */ +GLOBL(of_rtas_start): + /* r3 = argument buffer, r4 = of_rtas_start */ + /* according to the CHRP standard, cr must be preserved (cr0/cr1 too?) */ + mr r6,r3 + lis r3,HA(OSI_SC_MAGIC_R3) + addi r3,r3,LO(OSI_SC_MAGIC_R3) + lis r4,HA(OSI_SC_MAGIC_R4) + addi r4,r4,LO(OSI_SC_MAGIC_R4) + li r5,OSI_OF_RTAS + sc + blr +GLOBL(of_rtas_end): + + + /* used in a hack to the newworld calibration */ +GLOBL(nw_dec_calibration): + .long 0 +GLOBL(timer_calib_start): + lis r3,HA(nw_dec_calibration) + addi r3,r3,LO(nw_dec_calibration) + lwz r3,0(r3) + blr +GLOBL(timer_calib_end): + + +/************************************************************************/ +/* vectors */ +/************************************************************************/ + +GLOBL(__vectors): + nop // NULL-jmp trap +1: nop // + b 1b + +exception_return: + addi r1,r1,16 // pop ABI frame + + lwz r0,52(r1) + mtlr r0 + lwz r0,56(r1) + mtcr r0 + lwz r0,60(r1) + mtctr r0 + lwz r0,64(r1) + mtxer r0 + + lwz r0,0(r1) // restore r0 + lwz r2,8(r1) // restore r2 + lwz r3,12(r1) // restore r3 + lwz r4,16(r1) + lwz r5,20(r1) + lwz r6,24(r1) + lwz r7,28(r1) + lwz r8,32(r1) + lwz r9,36(r1) + lwz r10,40(r1) + lwz r11,44(r1) + lwz r12,48(r1) + lwz r1,4(r1) // restore r1 + rfi + +trap_error: + mflr r3 + b unexpected_excep + +ILLEGAL_VECTOR( 0x100 ) +ILLEGAL_VECTOR( 0x200 ) + +VECTOR( 0x300, "DSI" ): + EXCEPTION_PREAMBLE + lis r3,HA(dsi_exception) + addi r3,r3,LO(dsi_exception) + mtctr r3 + bctrl + b exception_return + +VECTOR( 0x400, "ISI" ): + EXCEPTION_PREAMBLE + lis r3,HA(isi_exception) + addi r3,r3,LO(isi_exception) + mtctr r3 + bctrl + b exception_return + + ILLEGAL_VECTOR( 0x500 ) + ILLEGAL_VECTOR( 0x600 ) + ILLEGAL_VECTOR( 0x700 ) + +VECTOR( 0x800, "FPU" ): + mtsprg1 r3 + mfsrr1 r3 + ori r3,r3,0x2000 + mtsrr1 r3 + mfsprg1 r3 + rfi + +ILLEGAL_VECTOR( 0x900 ) +ILLEGAL_VECTOR( 0xa00 ) +ILLEGAL_VECTOR( 0xb00 ) +ILLEGAL_VECTOR( 0xc00 ) +ILLEGAL_VECTOR( 0xd00 ) +ILLEGAL_VECTOR( 0xe00 ) +ILLEGAL_VECTOR( 0xf00 ) +ILLEGAL_VECTOR( 0xf20 ) +ILLEGAL_VECTOR( 0x1000 ) +ILLEGAL_VECTOR( 0x1100 ) +ILLEGAL_VECTOR( 0x1200 ) +ILLEGAL_VECTOR( 0x1300 ) +ILLEGAL_VECTOR( 0x1400 ) +ILLEGAL_VECTOR( 0x1500 ) +ILLEGAL_VECTOR( 0x1600 ) +ILLEGAL_VECTOR( 0x1700 ) + +GLOBL(__vectors_end): + + +#define CACHE_LINE_SIZE 32 +#define LG_CACHE_LINE_SIZE 5 + +/* flush_icache_range( unsigned long start, unsigned long stop) */ +GLOBL(flush_icache_range): + li r5,CACHE_LINE_SIZE-1 + andc r3,r3,r5 + subf r4,r3,r4 + add r4,r4,r5 + srwi. r4,r4,LG_CACHE_LINE_SIZE + beqlr + mtctr r4 + mr r6,r3 +1: dcbst 0,r3 + addi r3,r3,CACHE_LINE_SIZE + bdnz 1b + sync /* wait for dcbst's to get to ram */ + mtctr r4 +2: icbi 0,r6 + addi r6,r6,CACHE_LINE_SIZE + bdnz 2b + sync /* additional sync needed on g4 */ + isync + blr diff --git a/qemu/roms/openbios/arch/ppc/timebase.S b/qemu/roms/openbios/arch/ppc/timebase.S new file mode 100644 index 000000000..19faed49d --- /dev/null +++ b/qemu/roms/openbios/arch/ppc/timebase.S @@ -0,0 +1,33 @@ +#include "asm/asmdefs.h" +#include "asm/processor.h" + +/* + * unsigned long long _get_ticks(void); + */ +_GLOBAL(_get_ticks): +1: mftbu r3 + mftb r4 + mftbu r5 + cmpw 0,r3,r5 + bne 1b + blr + +/* + * Delay for a number of ticks + */ +_GLOBAL(_wait_ticks): + mflr r8 /* save link register */ + mr r7, r3 /* save tick count */ + bl BRANCH_LABEL(_get_ticks) /* Get start time */ + + /* Calculate end time */ + addc r7, r4, r7 /* Compute end time lower */ + addze r6, r3 /* and end time upper */ + +1: bl BRANCH_LABEL(_get_ticks) /* Get current time */ + subfc r4, r4, r7 /* Subtract current time from end time */ + subfe. r3, r3, r6 + bge 1b /* Loop until time expired */ + + mtlr r8 /* restore link register */ + blr diff --git a/qemu/roms/openbios/arch/ppc64/qemu/ldscript b/qemu/roms/openbios/arch/ppc64/qemu/ldscript new file mode 100644 index 000000000..fbbcc546f --- /dev/null +++ b/qemu/roms/openbios/arch/ppc64/qemu/ldscript @@ -0,0 +1,85 @@ +OUTPUT_FORMAT(elf64-powerpc) +OUTPUT_ARCH(powerpc:common64) + +/* Initial load address + */ +BASE_ADDR = 0xfff00000; + +/* As NVRAM is at 0xfff04000, the .text needs to be after that + * The value in arch/ppc/qemu/kernel.c must match this value! + */ +TEXT_ADDR = 0xfff08000; + +/* Hard reset vector address + */ +HRESET_ADDR = 0xfffffffc; + +CSTACK_SIZE = 32768; /* client stack size */ + +SECTIONS +{ + . = BASE_ADDR; + + _start = BASE_ADDR + 0x0100; + .text.vectors ALIGN(4096): { + *(.text.vectors) + } + + . = TEXT_ADDR; + /* Normal sections */ + .data.dict ALIGN(4096): { + _dict_start = .; + *(.data.dict) + _dict_end = .; + } + + .text ALIGN(4096): { + *(.text) + *(.text.*) + } + + .rodata ALIGN(4096): { + _rodata = .; + *(.rodata) + *(.rodata.*) + *(.note.ELFBoot) + } + .data ALIGN(4096): { + _data = .; + *(.data) + *(.data.*) + *(.toc1) + *(.branch_lt) + _edata = .; + } + .opd : { + *(.opd) + } + .got : { + __toc_start = .; + *(.got) + *(.toc) + } + + .bss ALIGN(4096): { + _bss = .; + *(.sbss) + *(.sbss.*) + *(.bss) + *(.bss.*) + *(COMMON) + _ebss = .; + } + + . = HRESET_ADDR; + + .romentry : { *(.romentry) } + + . = ALIGN(4096); + _end = .; + + /* We discard .note sections other than .note.ELFBoot, + * because some versions of GCC generates useless ones. */ + + /DISCARD/ : { *(.comment*) *(.note.*) } +} diff --git a/qemu/roms/openbios/arch/sparc32/boot.c b/qemu/roms/openbios/arch/sparc32/boot.c new file mode 100644 index 000000000..49ec4cfb3 --- /dev/null +++ b/qemu/roms/openbios/arch/sparc32/boot.c @@ -0,0 +1,261 @@ +/* + * + */ +#undef BOOTSTRAP +#include "config.h" +#include "libopenbios/bindings.h" +#include "arch/common/nvram.h" +#include "drivers/drivers.h" +#include "libc/diskio.h" +#include "libc/vsprintf.h" +#include "libopenbios/ofmem.h" +#include "libopenbios/sys_info.h" +#include "openprom.h" +#include "boot.h" +#include "context.h" + +uint32_t kernel_image; +uint32_t kernel_size; +uint32_t qemu_cmdline; +uint32_t cmdline_size; +char boot_device; +const void *romvec; + +static struct linux_mlist_v0 *totphyslist, *availlist, *prommaplist; + +static void setup_romvec(void) +{ + /* SPARC32 is slightly unusual in that before invoking any loaders, a romvec array + needs to be set up to pass certain parameters using a C struct. Hence this function + extracts the relevant boot information and places it in obp_arg. */ + + int intprop, proplen, target, device, i; + unsigned int *intprop_ptr; + phandle_t chosen; + char *prop, *id, *name; + static char bootpathbuf[128], bootargsbuf[128], buf[128]; + struct linux_mlist_v0 **pp; + + /* Get the stdin and stdout paths */ + chosen = find_dev("/chosen"); + intprop = get_int_property(chosen, "stdin", &proplen); + PUSH(intprop); + fword("get-instance-path"); + ((struct linux_romvec *)romvec)->pv_stdin = pop_fstr_copy(); + + intprop = get_int_property(chosen, "stdout", &proplen); + PUSH(intprop); + fword("get-instance-path"); + ((struct linux_romvec *)romvec)->pv_stdout = pop_fstr_copy(); + + /* Get the name of the selected boot device, along with the device and unit number */ + prop = get_property(chosen, "bootpath", &proplen); + strncpy(bootpathbuf, prop, proplen); + prop = get_property(chosen, "bootargs", &proplen); + strncpy(bootargsbuf, prop, proplen); + + /* Set bootpath pointer used in romvec table to the bootpath */ + push_str(bootpathbuf); + fword("pathres-resolve-aliases"); + bootpath = pop_fstr_copy(); + printk("bootpath: %s\n", bootpath); + + /* Now do some work to get hold of the target, partition etc. */ + push_str(bootpathbuf); + feval("open-dev"); + feval("ihandle>boot-device-handle drop to my-self"); + push_str("name"); + fword("get-my-property"); + POP(); + name = pop_fstr_copy(); + + if (!strncmp(name, "sd", 2)) { + + /* + Old-style SunOS disk paths are given in the form: + + sd(c,t,d):s + + where: + c = controller (Nth controller in system, usually 0) + t = target (my-unit phys.hi) + d = device/LUN (my-unit phys.lo) + s = slice/partition (my-args) + */ + + /* Controller currently always 0 */ + obp_arg.boot_dev_ctrl = 0; + + /* Get the target, device and slice */ + fword("my-unit"); + target = POP(); + device = POP(); + + fword("my-args"); + id = pop_fstr_copy(); + + if (id != NULL) { + snprintf(buf, sizeof(buf), "sd(0,%d,%d):%c", target, device, id[0]); + obp_arg.dev_partition = id[0] - 'a'; + } else { + snprintf(buf, sizeof(buf), "sd(0,%d,%d)", target, device); + obp_arg.dev_partition = 0; + } + + obp_arg.boot_dev_unit = target; + + obp_arg.boot_dev[0] = buf[0]; + obp_arg.boot_dev[1] = buf[1]; + obp_arg.argv[0] = buf; + obp_arg.argv[1] = bootargsbuf; + + } else if (!strncmp(name, "SUNW,fdtwo", 10)) { + + obp_arg.boot_dev_ctrl = 0; + obp_arg.boot_dev_unit = 0; + obp_arg.dev_partition = 0; + + strcpy(buf, "fd()"); + + obp_arg.boot_dev[0] = buf[0]; + obp_arg.boot_dev[1] = buf[1]; + obp_arg.argv[0] = buf; + obp_arg.argv[1] = bootargsbuf; + + } else if (!strncmp(name, "le", 2)) { + + obp_arg.boot_dev_ctrl = 0; + obp_arg.boot_dev_unit = 0; + obp_arg.dev_partition = 0; + + strcpy(buf, "le()"); + + obp_arg.boot_dev[0] = buf[0]; + obp_arg.boot_dev[1] = buf[1]; + obp_arg.argv[0] = buf; + obp_arg.argv[1] = bootargsbuf; + + } + + /* Generate the totphys (total memory available) list */ + prop = get_property(s_phandle_memory, "reg", &proplen); + intprop_ptr = (unsigned int *)prop; + + for (pp = &totphyslist, i = 0; i < (proplen / sizeof(int)); pp = &(**pp).theres_more, i+=3) { + *pp = (struct linux_mlist_v0 *)malloc(sizeof(struct linux_mlist_v0)); + (**pp).theres_more = NULL; + (**pp).start_adr = (char *)intprop_ptr[1]; + (**pp).num_bytes = intprop_ptr[2]; + + intprop_ptr += 3; + } + + /* Generate the avail (physical memory available) list */ + prop = get_property(s_phandle_memory, "available", &proplen); + intprop_ptr = (unsigned int *)prop; + + for (pp = &availlist, i = 0; i < (proplen / sizeof(int)); pp = &(**pp).theres_more, i+=3) { + *pp = (struct linux_mlist_v0 *)malloc(sizeof(struct linux_mlist_v0)); + (**pp).theres_more = NULL; + (**pp).start_adr = (char *)intprop_ptr[1]; + (**pp).num_bytes = intprop_ptr[2]; + + intprop_ptr += 3; + } + + /* Generate the prommap (taken virtual memory) list from inverse of available */ + prop = get_property(s_phandle_mmu, "available", &proplen); + intprop_ptr = (unsigned int *)prop; + + for (pp = &prommaplist, i = 0; i < (proplen / sizeof(int)); pp = &(**pp).theres_more, i+=3) { + *pp = (struct linux_mlist_v0 *)malloc(sizeof(struct linux_mlist_v0)); + (**pp).theres_more = NULL; + (**pp).start_adr = (char *)(intprop_ptr[1] + intprop_ptr[2]); + + if (i + 3 < (proplen / sizeof(int))) { + /* Size from next entry */ + (**pp).num_bytes = (intprop_ptr[4] + intprop_ptr[5]) - (intprop_ptr[1] + intprop_ptr[2]); + } else { + /* Tail (size from top of virtual memory) */ + (**pp).num_bytes = 0xffffffffUL - (intprop_ptr[1] + intprop_ptr[2]) + 1; + } + + intprop_ptr += 3; + } + + /* Finally set the memory properties */ + ((struct linux_romvec *)romvec)->pv_v0mem.v0_totphys = &totphyslist; + ((struct linux_romvec *)romvec)->pv_v0mem.v0_available = &availlist; + ((struct linux_romvec *)romvec)->pv_v0mem.v0_prommap = &prommaplist; +} + + +void go(void) +{ + ucell address, type, size; + int image_retval = 0; + + /* Get the entry point and the type (see forth/debugging/client.fs) */ + feval("saved-program-state >sps.entry @"); + address = POP(); + feval("saved-program-state >sps.file-type @"); + type = POP(); + feval("saved-program-state >sps.file-size @"); + size = POP(); + + setup_romvec(); + + printk("\nJumping to entry point " FMT_ucellx " for type " FMT_ucellx "...\n", address, type); + + switch (type) { + case 0x0: + /* Start ELF boot image */ + image_retval = start_elf((unsigned long)address, + (unsigned long)romvec); + + break; + + case 0x1: + /* Start ELF image */ + image_retval = start_elf((unsigned long)address, + (unsigned long)romvec); + + break; + + case 0x5: + /* Start a.out image */ + image_retval = start_elf((unsigned long)address, + (unsigned long)romvec); + + break; + + case 0x10: + /* Start Fcode image */ + printk("Evaluating FCode...\n"); + PUSH(address); + PUSH(1); + fword("byte-load"); + image_retval = 0; + break; + + case 0x11: + /* Start Forth image */ + PUSH(address); + PUSH(size); + fword("eval2"); + image_retval = 0; + break; + } + + printk("Image returned with return value %#x\n", image_retval); +} + + +void boot(void) +{ + /* Boot preloaded kernel */ + if (kernel_size) { + printk("[sparc] Kernel already loaded\n"); + start_elf(kernel_image, (unsigned long)romvec); + } +} diff --git a/qemu/roms/openbios/arch/sparc32/boot.h b/qemu/roms/openbios/arch/sparc32/boot.h new file mode 100644 index 000000000..55e391ac5 --- /dev/null +++ b/qemu/roms/openbios/arch/sparc32/boot.h @@ -0,0 +1,41 @@ +/* tag: openbios loader prototypes for sparc32 + * + * Copyright (C) 2004 Stefan Reinauer + * + * See the file "COPYING" for further information about + * the copyright and warranty status of this work. + */ + +// linux_load.c +int linux_load(struct sys_info *info, const char *file, const char *cmdline); + +// context.c +extern struct context *__context; +unsigned int start_elf(unsigned long entry_point, unsigned long param); + +// boot.c +extern const char *bootpath; +extern void boot(void); +extern void go(void); + +// sys_info.c +extern unsigned int qemu_mem_size; +extern void collect_sys_info(struct sys_info *info); + +// romvec.c +extern struct linux_arguments_v0 obp_arg; +extern const void *romvec; +extern const char *obp_stdin_path, *obp_stdout_path; +extern char obp_stdin, obp_stdout; + +// openbios.c +extern int qemu_machine_type; + +// arch/sparc32/lib.c +struct linux_mlist_v0; +extern struct linux_mlist_v0 *ptphys; +extern struct linux_mlist_v0 *ptmap; +extern struct linux_mlist_v0 *ptavail; + +void ob_init_mmu(void); +void init_mmu_swift(void); diff --git a/qemu/roms/openbios/arch/sparc32/build.xml b/qemu/roms/openbios/arch/sparc32/build.xml new file mode 100644 index 000000000..81c3586e0 --- /dev/null +++ b/qemu/roms/openbios/arch/sparc32/build.xml @@ -0,0 +1,74 @@ +<build condition="SPARC32"> + + <dictionary name="openbios-sparc32" init="openbios"> + <object source="tree.fs" target="forth"/> + <object source="init.fs" target="forth"/> + <object source="QEMU,tcx.bin" target="fcode" condition="DRIVER_SBUS"/> + <object source="QEMU,cgthree.bin" target="fcode" condition="DRIVER_SBUS"/> + </dictionary> + + <library name="sparc32" type="static" target="target"> + <object source="openbios.c"/> + <object source="console.c"/> + <object source="lib.c"/> + <object source="boot.c"/> + <object source="context.c"/> + <object source="switch.S"/> + <object source="udiv.S"/> + <object source="linux_load.c"/> + <object source="sys_info.c"/> + <object source="ofmem_sparc32.c"/> + <object source="romvec.c"/> + <object source="call-romvec.S"/> + <object source="entry.S"/> + <object source="vectors.S"/> + </library> + + <executable name="openbios-plain.elf" target="target" condition="IMAGE_ELF"> + <rule> + $(call quiet-command,$(LD) --warn-common -N -T $(SRCDIR)/arch/sparc32/ldscript -o $@.nostrip --whole-archive $^," LINK $(TARGET_DIR)$@") + $(call quiet-command,$(NM) $@.nostrip | sort > $(ODIR)/openbios-plain.syms," GEN $(TARGET_DIR)$@.syms") + $(call quiet-command,$(STRIP) $@.nostrip -o $@," STRIP $(TARGET_DIR)$@")</rule> + <object source="plainboot.c"/> + <external-object source="libsparc32.a"/> + <external-object source="libbootstrap.a"/> + <external-object source="libopenbios.a"/> + <external-object source="libpackages.a"/> + <external-object source="libdrivers.a"/> + <external-object source="libfs.a"/> + <external-object source="liblibc.a"/> + <external-object source="libgcc.a"/> + </executable> + + <!-- HACK ALERT --> + + <executable name="target/include/static-dict.h" target="target" condition="IMAGE_ELF_EMBEDDED"> + <rule><![CDATA[ + $(call quiet-command,$(ODIR)/forthstrap -x -D $@ -d $< </dev/null, " GEN $(TARGET_DIR)$@")]]></rule> + <external-object source="openbios-sparc32.dict"/> + </executable> + + <executable name="target/arch/sparc32/builtin.o" target="target" condition="IMAGE_ELF_EMBEDDED"> + <rule><![CDATA[ $(SRCDIR)/arch/sparc32/builtin.c $(ODIR)/target/include/static-dict.h + $(call quiet-command,$(CC) $$EXTRACFLAGS $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/arch/sparc32/builtin.c, " CC $(TARGET_DIR)$@")]]></rule> + </executable> + + <!-- END OF HACK ALERT --> + + <executable name="openbios-builtin.elf" target="target" condition="IMAGE_ELF_EMBEDDED"> + <rule> + $(call quiet-command,$(LD) --warn-common -N -T $(SRCDIR)/arch/sparc32/ldscript -o $@.nostrip --whole-archive $^," LINK $(TARGET_DIR)$@") + $(call quiet-command,$(NM) $@.nostrip | sort > $(ODIR)/openbios-builtin.syms," GEN $(TARGET_DIR)$@.syms") + $(call quiet-command,$(STRIP) $@.nostrip -o $@," STRIP $(TARGET_DIR)$@")</rule> + <external-object source="target/arch/sparc32/builtin.o"/> + <external-object source="libsparc32.a"/> + <external-object source="libbootstrap.a"/> + <external-object source="libopenbios.a"/> + <external-object source="libpackages.a"/> + <external-object source="libdrivers.a"/> + <external-object source="libfs.a"/> + <external-object source="liblibc.a"/> + <external-object source="libgcc.a"/> + </executable> + +</build> diff --git a/qemu/roms/openbios/arch/sparc32/builtin.c b/qemu/roms/openbios/arch/sparc32/builtin.c new file mode 100644 index 000000000..971a4009d --- /dev/null +++ b/qemu/roms/openbios/arch/sparc32/builtin.c @@ -0,0 +1,33 @@ +/* tag: openbios forth starter for builtin dictionary for sparc32 + * + * Copyright (C) 2003 Stefan Reinauer + * + * See the file "COPYING" for further information about + * the copyright and warranty status of this work. + */ + +#include "config.h" +#include "asm/types.h" +#include "libopenbios/sys_info.h" + +/* + * wrap an array around the hex'ed dictionary file + */ + +/* 256K for the dictionary */ +#define DICTIONARY_SIZE (256 * 1024 / sizeof(ucell)) +#define DICTIONARY_BASE ((ucell)((char *)&forth_dictionary)) + +static ucell forth_dictionary[DICTIONARY_SIZE] = { +#include "static-dict.h" +}; + +void collect_multiboot_info(struct sys_info *info); +void collect_multiboot_info(struct sys_info *info) +{ + info->dict_start=(unsigned long *)forth_dictionary; + info->dict_end = (unsigned long *)FORTH_DICTIONARY_END; + info->dict_last = (ucell *)((unsigned char *)forth_dictionary + + FORTH_DICTIONARY_LAST); + info->dict_limit = sizeof(forth_dictionary); +} diff --git a/qemu/roms/openbios/arch/sparc32/call-romvec.S b/qemu/roms/openbios/arch/sparc32/call-romvec.S new file mode 100644 index 000000000..be77b232e --- /dev/null +++ b/qemu/roms/openbios/arch/sparc32/call-romvec.S @@ -0,0 +1,94 @@ +#define __ASSEMBLY +#include "psr.h" +#include "asm/asi.h" + + .text + .align 4 + +#define STACKFRAME_SZ 0x60 + +/* These are just handy. */ +#define _SV save %sp, -STACKFRAME_SZ, %sp +#define _RS restore + +#define FLUSH_ALL_KERNEL_WINDOWS \ + _SV; _SV; _SV; _SV; _SV; _SV; _SV; \ + _RS; _RS; _RS; _RS; _RS; _RS; _RS; + +/* Macro for romvec handlers */ +#define ROMVEC_HANDLER(type) \ + \ + .globl type##_handler; \ + \ +type##_handler: \ + \ + FLUSH_ALL_KERNEL_WINDOWS; \ + \ + save %sp, -STACKFRAME_SZ - 0x20, %sp; \ + \ + st %g1, [ %sp + STACKFRAME_SZ + 0x0]; \ + st %g2, [ %sp + STACKFRAME_SZ + 0x4]; \ + st %g3, [ %sp + STACKFRAME_SZ + 0x8]; \ + st %g4, [ %sp + STACKFRAME_SZ + 0xc]; \ + st %g5, [ %sp + STACKFRAME_SZ + 0x10]; \ + st %g6, [ %sp + STACKFRAME_SZ + 0x14]; \ + st %g7, [ %sp + STACKFRAME_SZ + 0x18]; \ + \ + mov %i0, %o0; \ + mov %i1, %o1; \ + mov %i2, %o2; \ + mov %i3, %o3; \ + mov %i4, %o4; \ + mov %i5, %o5; \ + \ + call type; \ + nop; \ + \ + mov %o0, %i0; \ + \ + ld [ %sp + STACKFRAME_SZ + 0x0], %g1; \ + ld [ %sp + STACKFRAME_SZ + 0x4], %g2; \ + ld [ %sp + STACKFRAME_SZ + 0x8], %g3; \ + ld [ %sp + STACKFRAME_SZ + 0xc], %g4; \ + ld [ %sp + STACKFRAME_SZ + 0x10], %g5; \ + ld [ %sp + STACKFRAME_SZ + 0x14], %g6; \ + ld [ %sp + STACKFRAME_SZ + 0x18], %g7; \ + \ + ret; \ + restore; \ + + +/* Generate handlers which are proxy functions to the + real C functions that correctly save the globals + and stack */ +ROMVEC_HANDLER(obp_devopen) +ROMVEC_HANDLER(obp_devclose) +ROMVEC_HANDLER(obp_rdblkdev) +ROMVEC_HANDLER(obp_nbgetchar) +ROMVEC_HANDLER(obp_nbputchar) +ROMVEC_HANDLER(obp_putstr) +ROMVEC_HANDLER(obp_printf) +ROMVEC_HANDLER(obp_reboot) +ROMVEC_HANDLER(obp_abort) +ROMVEC_HANDLER(obp_halt) +ROMVEC_HANDLER(obp_fortheval_v2) +ROMVEC_HANDLER(obp_inst2pkg) +ROMVEC_HANDLER(obp_dumb_memalloc) +ROMVEC_HANDLER(obp_dumb_memfree) +ROMVEC_HANDLER(obp_dumb_mmap) +ROMVEC_HANDLER(obp_dumb_munmap) +ROMVEC_HANDLER(obp_devread) +ROMVEC_HANDLER(obp_devwrite) +ROMVEC_HANDLER(obp_devseek) +ROMVEC_HANDLER(obp_cpustart) +ROMVEC_HANDLER(obp_cpustop) +ROMVEC_HANDLER(obp_cpuidle) +ROMVEC_HANDLER(obp_cpuresume) +ROMVEC_HANDLER(obp_nextnode) +ROMVEC_HANDLER(obp_child) +ROMVEC_HANDLER(obp_proplen) +ROMVEC_HANDLER(obp_getprop) +ROMVEC_HANDLER(obp_setprop) +ROMVEC_HANDLER(obp_nextprop) +ROMVEC_HANDLER(obp_memalloc) + diff --git a/qemu/roms/openbios/arch/sparc32/console.c b/qemu/roms/openbios/arch/sparc32/console.c new file mode 100644 index 000000000..61c2e238e --- /dev/null +++ b/qemu/roms/openbios/arch/sparc32/console.c @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2003, 2004 Stefan Reinauer + * + * See the file "COPYING" for further information about + * the copyright and warranty status of this work. + */ + +#include "config.h" +#include "kernel/kernel.h" +#include "drivers/drivers.h" +#include "openbios.h" +#include "libopenbios/console.h" +#include "libopenbios/ofmem.h" +#include "libopenbios/video.h" + +#ifdef CONFIG_DEBUG_CONSOLE + +/* ****************************************************************** + * common functions, implementing simple concurrent console + * ****************************************************************** */ + +static int arch_putchar(int c) +{ +#ifdef CONFIG_DEBUG_CONSOLE_SERIAL + escc_uart_putchar(c); +#endif + return c; +} + +static int arch_availchar(void) +{ +#ifdef CONFIG_DEBUG_CONSOLE_SERIAL + if (escc_uart_charav(CONFIG_SERIAL_PORT)) + return 1; +#endif +#ifdef CONFIG_DEBUG_CONSOLE_VIDEO + if (keyboard_dataready()) + return 1; +#endif + return 0; +} + +static int arch_getchar(void) +{ +#ifdef CONFIG_DEBUG_CONSOLE_SERIAL + if (escc_uart_charav(CONFIG_SERIAL_PORT)) + return (escc_uart_getchar(CONFIG_SERIAL_PORT)); +#endif +#ifdef CONFIG_DEBUG_CONSOLE_VIDEO + if (keyboard_dataready()) + return (keyboard_readdata()); +#endif + return 0; +} + +struct _console_ops arch_console_ops = { + .putchar = arch_putchar, + .availchar = arch_availchar, + .getchar = arch_getchar +}; + +#endif // CONFIG_DEBUG_CONSOLE diff --git a/qemu/roms/openbios/arch/sparc32/context.c b/qemu/roms/openbios/arch/sparc32/context.c new file mode 100644 index 000000000..d4d8530d4 --- /dev/null +++ b/qemu/roms/openbios/arch/sparc32/context.c @@ -0,0 +1,113 @@ +/* + * context switching + * 2003-10 by SONE Takeshi + */ + +#include "config.h" +#include "kernel/kernel.h" +#include "context.h" +#include "libopenbios/sys_info.h" +#include "boot.h" +#include "openbios.h" + +#define MAIN_STACK_SIZE 16384 +#define IMAGE_STACK_SIZE 4096*2 + +#define debug printk + +static void start_main(void); /* forward decl. */ +void __exit_context(void); /* assembly routine */ + +/* + * Main context structure + * It is placed at the bottom of our stack, and loaded by assembly routine + * to start us up. + */ +static struct context main_ctx = { + .regs[REG_SP] = (uint32_t) &_estack - 96, + .pc = (uint32_t) start_main, + .npc = (uint32_t) start_main + 4, + .return_addr = (uint32_t) __exit_context, +}; + +/* This is used by assembly routine to load/store the context which + * it is to switch/switched. */ +struct context *__context = &main_ctx; + +/* Stack for loaded ELF image */ +static uint8_t image_stack[IMAGE_STACK_SIZE]; + +/* Pointer to startup context (physical address) */ +unsigned long __boot_ctx; + +/* + * Main starter + * This is the C function that runs first. + */ +static void start_main(void) +{ + /* Save startup context, so we can refer to it later. + * We have to keep it in physical address since we will relocate. */ + __boot_ctx = virt_to_phys(__context); + + /* Start the real fun */ + openbios(); + + /* Returning from here should jump to __exit_context */ + __context = boot_ctx; +} + +/* Setup a new context using the given stack. + */ +struct context * +init_context(uint8_t *stack, uint32_t stack_size, int num_params) +{ + struct context *ctx; + + ctx = (struct context *) + (stack + stack_size - (sizeof(*ctx) + num_params*sizeof(uint32_t))); + memset(ctx, 0, sizeof(*ctx)); + + /* Fill in reasonable default for flat memory model */ + ctx->regs[REG_SP] = virt_to_phys(SP_LOC(ctx)); + ctx->return_addr = virt_to_phys(__exit_context); + + return ctx; +} + +/* Switch to another context. */ +struct context *switch_to(struct context *ctx) +{ + volatile struct context *save; + struct context *ret; + + debug("switching to new context:\n"); + save = __context; + __context = ctx; + asm __volatile__ ("\n\tcall __switch_context" + "\n\tnop" ::: "g1", "g2", "g3", "g4", "g5", "g6", "g7", + "o0", "o1", "o2", "o3", "o4", "o5", "sp", "o7", + "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7", + "i0", "i1", "i2", "i3", "i4", "i5", "i7", + "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", + "f10", "f11", "f12", "f13", "f14", "f15", "f16", "f17", "f18", "f19", + "f20", "f21", "f22", "f23", "f24", "f25", "f26", "f27", "f28", "f29", + "f30", "f31", + "memory"); + ret = __context; + __context = (struct context *)save; + return ret; +} + +/* Start ELF Boot image */ +unsigned int start_elf(unsigned long entry_point, unsigned long param) +{ + struct context *ctx; + + ctx = init_context(image_stack, sizeof image_stack, 1); + ctx->pc = entry_point; + ctx->param[0] = param; + + ctx = switch_to(ctx); + return ctx->regs[REG_O0]; +} diff --git a/qemu/roms/openbios/arch/sparc32/context.h b/qemu/roms/openbios/arch/sparc32/context.h new file mode 100644 index 000000000..8689d563e --- /dev/null +++ b/qemu/roms/openbios/arch/sparc32/context.h @@ -0,0 +1,31 @@ +#ifndef SPARC32_CONTEXT_H +#define SPARC32_CONTEXT_H + +struct context { + /* General registers */ + uint32_t regs[32]; + uint32_t pc; + uint32_t npc; +#define REG_O0 8 +#define REG_SP 14 +#define SP_LOC(ctx) (&(ctx)->regs[REG_SP]) + /* Flags */ + /* Optional stack contents */ + uint32_t return_addr; + uint32_t param[0]; +}; + +/* Create a new context in the given stack */ +struct context * +init_context(uint8_t *stack, uint32_t stack_size, int num_param); + +/* Switch context */ +struct context *switch_to(struct context *); + +/* Holds physical address of boot context */ +extern unsigned long __boot_ctx; + +/* This can always be safely used to refer to the boot context */ +#define boot_ctx ((struct context *) phys_to_virt(__boot_ctx)) + +#endif /* SPARC32_CONTEXT_H */ diff --git a/qemu/roms/openbios/arch/sparc32/crs.h b/qemu/roms/openbios/arch/sparc32/crs.h new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/qemu/roms/openbios/arch/sparc32/crs.h diff --git a/qemu/roms/openbios/arch/sparc32/entry.S b/qemu/roms/openbios/arch/sparc32/entry.S new file mode 100644 index 000000000..72cb33863 --- /dev/null +++ b/qemu/roms/openbios/arch/sparc32/entry.S @@ -0,0 +1,532 @@ +/** + ** Standalone startup code for Linux PROM emulator. + ** Copyright 1999 Pete A. Zaitcev + ** This code is licensed under GNU General Public License. + **/ +/* + * $Id: head.S,v 1.12 2002/07/23 05:47:09 zaitcev Exp $ + */ + +#define __ASSEMBLY +#include "psr.h" +#include "asm/asi.h" +#include "asm/crs.h" +#define NO_QEMU_PROTOS +#define NO_OPENBIOS_PROTOS +#include "arch/common/fw_cfg.h" + +#define CFG_ADDR 0x00000510 +#define CFG_ASI 0x2d + +#define PHYS_JJ_INTR0 0x71E00000 /* CPU0 interrupt control registers */ + +#define PHYS_SS10_INTR0 0xf1400000 + +#define PHYS_SS2_INTR0 0xf5000000 +#define SER_ADDR2 0xf1000004 + +#define PHYS_SS1000_SBI 0x02800000 +#define SER_ADDR1000 0x00200004 + +#define WRITE_PAUSE nop; nop; nop; /* Have to do this after %wim/%psr chg */ + + .globl entry, _entry + + .section ".text", "ax" + .align 8 + + /* Memory map: + * + * Top +-------------------------+ + * | SMP CPU table | + * | s + 0x1f00 ... 0x1f0f | + * | s + 0x1f0c valid | + * | s + 0x1f08 entry | + * | s + 0x1f04 ctxtbl | + * | s + 0x1f00 ctx | + * +-------------------------+ + * | Bootstrap | + * | MMU L3 tables 8 * 0x100 | + * | s + 0xa00 ... 0x11ff | + * +-------------------------+ + * | Bootstrap | + * | MMU L2 tables 2 * 0x100 | + * | s + 0x800 ... 0x9ff | + * +-------------------------+ + * | Bootstrap | + * | MMU L1 table 0x400 | + * | s + 0x400 ... 0x7ff | + * +-------------------------+ + * | Bootstrap | + * | MMU L0/ctx table 0x400 | + * | s + 0x000 ... 0x3ff | + * +-------------------------+ + * | | + * | ROM into RAM | + * | | + * +-------------------------+ + * : : + * Bottom + */ + +/* + * Entry point + * We start execution from here. + */ +_entry: +entry: + /* Switch to our main context. + * Main context is statically defined in C. + */ + + ! Check signature "QEMU" + set CFG_ADDR, %g5 + mov FW_CFG_SIGNATURE, %g2 + stha %g2, [%g5] CFG_ASI + add %g5, 2, %g5 + lduba [%g5] CFG_ASI, %g2 + cmp %g2, 'Q' + bne bad_conf + nop + lduba [%g5] CFG_ASI, %g2 + cmp %g2, 'E' + bne bad_conf + nop + lduba [%g5] CFG_ASI, %g2 + cmp %g2, 'M' + bne bad_conf + nop + lduba [%g5] CFG_ASI, %g2 + cmp %g2, 'U' + bne bad_conf + nop + + ! Get memory size from configuration device + ! NB: little endian format + mov FW_CFG_RAM_SIZE, %g2 + sub %g5, 2, %g5 + stha %g2, [%g5] CFG_ASI + add %g5, 2, %g5 + lduba [%g5] CFG_ASI, %g4 + + lduba [%g5] CFG_ASI, %g3 + sll %g3, 8, %g3 + or %g3, %g4, %g4 + + lduba [%g5] CFG_ASI, %g3 + sll %g3, 16, %g3 + or %g3, %g4, %g4 + + lduba [%g5] CFG_ASI, %g3 + sll %g3, 24, %g3 + or %g3, %g4, %g1 + ! %g1 contains end of memory + + ! Get kernel address from configuration device + ! NB: little endian format + mov FW_CFG_KERNEL_ADDR, %g2 + sub %g5, 2, %g5 + stha %g2, [%g5] CFG_ASI + add %g5, 2, %g5 + lduba [%g5] CFG_ASI, %g4 + + lduba [%g5] CFG_ASI, %g3 + sll %g3, 8, %g3 + or %g3, %g4, %g4 + + lduba [%g5] CFG_ASI, %g3 + sll %g3, 16, %g3 + or %g3, %g4, %g4 + + lduba [%g5] CFG_ASI, %g3 + sll %g3, 24, %g3 + or %g3, %g4, %g4 + + ! If kernel address is set, don't clear from base of RAM in order to + ! leave the kernel image intact + mov 0, %g6 + cmp %g4, 0 + beq clear_mem + nop + + ! Start from 16M + set 0x1000000, %g6 + +clear_mem: + sta %g0, [%g6] ASI_M_BYPASS + add %g6, 0x4, %g6 + cmp %g6, %g1 + bl clear_mem + nop + +clear_done: + ! Start of private memory in %g6 + set 0x2000, %g3 + sub %g1, %g3, %g6 + + ! Check if this is the boot CPU and skip SMP table check if yes + ! XXX: not all CPUs should have MXCC + set 0x1c00f00, %g2 + ldda [%g2] ASI_CONTROL, %g2 + srl %g3, 24, %g7 + sub %g7, 8, %g7 + tst %g7 + bz skip_table + nop + + ! Calculate SMP table location + set 0x1f0c, %g2 + add %g6, %g2, %g2 ! valid? + lda [%g2] ASI_M_BYPASS, %g7 + sta %g0, [%g2] ASI_M_BYPASS + +skip_table: + ! Get machine ID from configuration device + mov FW_CFG_MACHINE_ID, %g2 + sub %g5, 2, %g5 + stha %g2, [%g5] CFG_ASI + add %g5, 2, %g5 + lduba [%g5] CFG_ASI, %g4 + + lduba [%g5] CFG_ASI, %g3 + sll %g3, 8, %g3 + or %g3, %g4, %g4 + mov %g4, %y + + cmp %g4, 96 + bgeu ss1000 + cmp %g4, 64 + bgeu ss10 + cmp %g4, 32 + blu ss2 + nop + + ! Ok, this is SS-5 + + tst %g7 + bz first_cpu + nop + + ! Clear softints used for SMP CPU startup + set PHYS_JJ_INTR0 + 0x04, %g1 + sll %g2, 12, %g2 + add %g1, %g2, %g2 + set 0xffffffff, %g1 + sta %g1, [%g2] ASI_M_BYPASS ! clear softints + add %g2, 4, %g2 + sta %g0, [%g2] ASI_M_BYPASS ! clear softints + +load_ctx: + ! SMP init, jump to user specified address + set 0x1f04, %g5 + add %g6, %g5, %g5 ! ctxtbl + lda [%g5] ASI_M_BYPASS, %g2 + sta %g0, [%g5] ASI_M_BYPASS + set AC_M_CTPR, %g1 + sta %g2, [%g1] ASI_M_MMUREGS ! set ctx table ptr + set 0x1f00, %g5 + add %g6, %g5, %g5 ! ctx + lda [%g5] ASI_M_BYPASS, %g2 + sta %g0, [%g5] ASI_M_BYPASS + set AC_M_CXR, %g1 + sta %g2, [%g1] ASI_M_MMUREGS ! set context + set 0x1f08, %g5 + add %g6, %g5, %g5 ! entry + lda [%g5] ASI_M_BYPASS, %g2 + sta %g0, [%g5] ASI_M_BYPASS + set 1, %g1 + jmp %g2 ! jump to kernel + sta %g1, [%g0] ASI_M_MMUREGS ! enable mmu + +ss10: + ! Ok, this is SS-10 or SS-600MP + tst %g7 + bz first_cpu + nop + + ! Clear softints used for SMP CPU startup + set PHYS_SS10_INTR0 + 0x04, %g1 + sll %g2, 12, %g2 + add %g1, %g2, %g2 + set 0xffffffff, %g1 + sta %g1, [%g2] ASI_M_CTL ! clear softints + add %g2, 4, %g2 + b load_ctx + sta %g0, [%g2] ASI_M_CTL ! clear softints + +ss2: + ! Ok, this is SS-2 + set ss2_error, %o2 + b ss2_ss1000_halt + nop + +ss1000: + ! Ok, this is SS-1000 or SS-2000 + set ss1000_error, %o2 + b ss2_ss1000_halt + nop + +first_cpu: + /* Create temporary page tables and map the ROM area to end of + RAM. This will be done properly in iommu.c later. */ + ! Calculate start of page tables etc. to %g6 + set 0x2000, %g4 + sub %g1, %g4, %g6 ! start of private memory + + mov %g6, %g2 ! ctx table at s+0x0 + add %g2, 0x400, %g3 ! l1 table at s+0x400 + srl %g3, 0x4, %g3 + or %g3, 0x1, %g3 + sta %g3, [%g2] ASI_M_BYPASS + add %g2, 0x400, %g2 ! s+0x400 + add %g2, 0x400, %g3 ! l2 table for ram (00xxxxxx) at s+0x800 + srl %g3, 0x4, %g3 + or %g3, 0x1, %g3 + sta %g3, [%g2] ASI_M_BYPASS + add %g2, 0x500, %g3 ! l2 table for rom (ffxxxxxx) at s+0x900 + add %g2, 0x3fc, %g2 ! s+0x7fc + srl %g3, 0x4, %g3 + or %g3, 0x1, %g3 + sta %g3, [%g2] ASI_M_BYPASS + add %g2, 0x4, %g2 ! s+0x800 +#if 0 + set 0x40, %g6 + set ((7 << 2) | 2), %g3 ! 7 = U: --- S: RWX (main memory) +1: sta %g3, [%g2] ASI_M_BYPASS + add %g2, 4, %g2 + deccc %g6 + bne 1b + nop +#else + add %g2, 0x100, %g2 +#endif + ! s+0x900 + add %g2, 0xa00 - 0x900, %g3 ! l3 table for rom at s+0xa00 + add %g2, 0x0d0, %g2 ! s+0x9d0 + srl %g3, 0x4, %g3 + or %g3, 0x1, %g3 + sta %g3, [%g2] ASI_M_BYPASS + add %g2, 4, %g2 ! s+0x9d4 + add %g2, 0xb00 - 0x9d4, %g3 ! 2nd l3 table for rom at s+0xb00 + srl %g3, 0x4, %g3 + or %g3, 0x1, %g3 + sta %g3, [%g2] ASI_M_BYPASS + add %g2, 4, %g2 ! s+0x9d8 + add %g2, 0xc00 - 0x9d8, %g3 ! 3rd l3 table for rom at s+0xc00 + srl %g3, 0x4, %g3 + or %g3, 0x1, %g3 + sta %g3, [%g2] ASI_M_BYPASS + add %g2, 4, %g2 ! s+0x9dc + add %g2, 0xd00 - 0x9dc, %g3 ! 4th l3 table for rom at s+0xd00 + srl %g3, 0x4, %g3 + or %g3, 0x1, %g3 + sta %g3, [%g2] ASI_M_BYPASS + add %g2, 4, %g2 ! s+0x9e0 + add %g2, 0xe00 - 0x9e0, %g3 ! 5th l3 table for rom at s+0xe00 + srl %g3, 0x4, %g3 + or %g3, 0x1, %g3 + sta %g3, [%g2] ASI_M_BYPASS + add %g2, 4, %g2 ! s+0x9e4 + add %g2, 0xf00 - 0x9e4, %g3 ! 6th l3 table for rom at s+0xf00 + srl %g3, 0x4, %g3 + or %g3, 0x1, %g3 + sta %g3, [%g2] ASI_M_BYPASS + add %g2, 4, %g2 ! s+0x9e8 + add %g2, 0x1000 - 0x9e8, %g3 ! 7th l3 table for rom at s+0x1000 + srl %g3, 0x4, %g3 + or %g3, 0x1, %g3 + sta %g3, [%g2] ASI_M_BYPASS + add %g2, 4, %g2 ! s+0x9ec + add %g2, 0x1100 - 0x9ec, %g3 ! 8th l3 table for rom at s+0x1100 + srl %g3, 0x4, %g3 + or %g3, 0x1, %g3 + sta %g3, [%g2] ASI_M_BYPASS + add %g2, 0xa00-0x9ec, %g2 ! s+0xa00 + + /* Use end of ram for code, rodata, data, and bss + sections. SunOS wants to write to trap table... */ + set _end, %g6 + set _start, %g4 + sub %g6, %g4, %g6 + sub %g1, %g6, %g3 + set 0x1000, %g5 + sub %g3, %g5, %g3 + sub %g3, %g5, %g3 ! start of ROM copy + mov %g3, %g7 ! save in %g7 + srl %g6, 12, %g6 ! # of all pages +1: srl %g3, 0x4, %g4 + or %g4, ((7 << 2) | 2), %g4 ! 7 = U: --- S: RWX + sta %g4, [%g2] ASI_M_BYPASS + add %g2, 4, %g2 + add %g3, %g5, %g3 + deccc %g6 + bne 1b + nop + + mov %g1, %g6 ! %g6 = memory size + + /* Copy the code, rodata and data sections from ROM. */ + sub %g7, 4, %g3 + set _start - 4, %g4 ! First address of TEXT - 4 + set _bss, %g5 ! Last address of DATA + ba 2f + nop +1: + lda [%g4] ASI_M_KERNELTXT, %g1 + sta %g1, [%g3] ASI_M_BYPASS +2: + cmp %g4, %g5 + add %g3, 0x4, %g3 + bl 1b + add %g4, 0x4, %g4 + + set 0x2000, %g3 + sub %g6, %g3, %g7 ! ctx table at s+0x0 + set AC_M_CTPR, %g2 + srl %g7, 4, %g7 + sta %g7, [%g2] ASI_M_MMUREGS ! set ctx table ptr + set AC_M_CXR, %g2 + sta %g0, [%g2] ASI_M_MMUREGS ! context 0 + set highmem, %g2 + set 1, %g1 + jmp %g2 + sta %g1, [%g0] ASI_M_MMUREGS ! enable mmu +highmem: + /* + * The code which enables traps is a simplified version of + * kernel head.S. + * + * We know number of windows as 8 so we do not calculate them. + * The deadwood is here for any case. + */ + + /* Turn on Supervisor, EnableFloating, and all the PIL bits. + * Also puts us in register window zero with traps off. + */ + set (PSR_PS | PSR_S | PSR_PIL | PSR_EF), %g2 + wr %g2, 0x0, %psr + WRITE_PAUSE + + /* Zero out our BSS section. */ + set _bss - 4, %o0 ! First address of BSS + set _estack - 4, %o1 ! Last address of BSS + ba 2f + nop +1: + st %g0, [%o0] +2: + subcc %o0, %o1, %g0 + bl 1b + add %o0, 0x4, %o0 + + set trap_table, %g1 + wr %g1, 0x0, %tbr + + set qemu_mem_size, %g1 + st %g6, [%g1] + + set _end, %o0 ! Store va->pa conversion factor + set _start, %o2 + sub %o0, %o2, %o0 + sub %g6, %o0, %o0 + set 0x2000, %o1 + sub %o0, %o1, %o0 ! start of ROM copy + sub %o2, %o0, %o0 ! start of ROM copy + set va_shift, %g1 + st %o0, [%g1] + + set qemu_machine_type, %g1 + mov %y, %g2 + st %g2, [%g1] + + /* Compute NWINDOWS and stash it away. Now uses %wim trick explained + * in the V8 manual. Ok, this method seems to work, Sparc is cool... + * No, it doesn't work, have to play the save/readCWP/restore trick. + */ + + wr %g0, 0x0, %wim ! so we do not get a trap + WRITE_PAUSE + + save + + rd %psr, %g3 + + restore + + and %g3, 0x1f, %g3 + add %g3, 0x1, %g3 + + mov 2, %g1 + wr %g1, 0x0, %wim ! make window 1 invalid + WRITE_PAUSE + + cmp %g3, 0x7 + bne 1f + nop + + /* Adjust our window handling routines to + * do things correctly on 7 window Sparcs. + */ +#define PATCH_INSN(src, dest) \ + set src, %g5; \ + set dest, %g2; \ + ld [%g5], %g4; \ + st %g4, [%g2]; + + /* Patch for window spills... */ + PATCH_INSN(spnwin_patch1_7win, spnwin_patch1) + PATCH_INSN(spnwin_patch2_7win, spnwin_patch2) + + /* Patch for window fills... */ + PATCH_INSN(fnwin_patch1_7win, fnwin_patch1) + PATCH_INSN(fnwin_patch2_7win, fnwin_patch2) + +1: + /* Finally, turn on traps so that we can call c-code. */ + rd %psr, %g3 + wr %g3, 0x0, %psr + WRITE_PAUSE + + wr %g3, PSR_ET, %psr + WRITE_PAUSE + + set 0, %fp + call __switch_context_nosave + nop + + /* We get here when the main context switches back to + * the boot context. + * Return to previous bootloader. + */ + ret + nop + +ss2_ss1000_halt: + set SER_ADDR2, %o0 + set SER_ADDR1000, %o1 + mov 0x05, %o3 /* Reg 5, TXCTRL2 */ + stba %o3, [%o0] ASI_M_BYPASS + stba %o3, [%o1] ASI_M_CTL + mov 0x68, %o3 /* 8 bits, Tx enabled */ + stba %o3, [%o0] ASI_M_BYPASS + stba %o3, [%o1] ASI_M_CTL + add %o0, 2, %o0 + add %o1, 2, %o1 + +1: lduba [%o2] ASI_M_KERNELTXT, %o3 + cmp %o3, 0 + be 2f + nop + stba %o3, [%o0] ASI_M_BYPASS + stba %o3, [%o1] ASI_M_CTL + b 1b + inc %o2 +bad_conf: +2: b 2b + nop + + .section .rodata +ss2_error: + .string "Sun4c machines are not supported by OpenBIOS yet, freezing\r\n" +ss1000_error: + .string "Sun4d machines are not supported by OpenBIOS yet, freezing\r\n" diff --git a/qemu/roms/openbios/arch/sparc32/init.fs b/qemu/roms/openbios/arch/sparc32/init.fs new file mode 100644 index 000000000..814c720c9 --- /dev/null +++ b/qemu/roms/openbios/arch/sparc32/init.fs @@ -0,0 +1,83 @@ +:noname + ." Type 'help' for detailed information" cr + \ ." boot secondary slave cdrom: " cr + \ ." 0 > boot hd:2,\boot\vmlinuz root=/dev/hda2" cr + ; DIAG-initializer + +: make-openable ( path ) + find-dev if + begin ?dup while + \ install trivial open and close methods + dup active-package! is-open + parent + repeat + then +; + +: preopen ( chosen-str node-path ) + 2dup make-openable + + " /chosen" find-device + open-dev ?dup if + encode-int 2swap property + else + 2drop + then +; + +:noname + set-defaults +; PREPOST-initializer + +\ preopen device nodes (and store the ihandles under /chosen) +:noname + " memory" " /memory" preopen + " mmu" " /virtual-memory" preopen +; SYSTEM-initializer + +device-end + +: rmap@ ( virt -- rmentry ) + drop 0 + ; + +\ D5.3 SBus specific on-board memory address space +: obmem ( -- space ) + 0 + ; + +\ (peek) and (poke) implementation +defer sfsr@ +defer ignore-dfault + +:noname + \ ( addr xt -- false | value true ) + sfsr@ drop \ Clear any existing MMU fault status + + -1 ignore-dfault ! \ Disable data fault trap + execute + 0 ignore-dfault ! \ Enable data fault trap + + sfsr@ 0= if + true + else + drop false \ Failed, drop the read value + then +; to (peek) + +:noname + \ ( value addr xt -- okay? ) + sfsr@ drop \ Clear any existing MMU fault status + + -1 ignore-dfault ! \ Disable data fault trap + execute + 0 ignore-dfault ! \ Enable data fault trap + + sfsr@ 0= \ true if no fault +; to (poke) + +\ Load TCX FCode driver blob +[IFDEF] CONFIG_DRIVER_SBUS + -1 value tcx-driver-fcode + " QEMU,tcx.bin" $encode-file to tcx-driver-fcode +[THEN] diff --git a/qemu/roms/openbios/arch/sparc32/ldscript b/qemu/roms/openbios/arch/sparc32/ldscript new file mode 100644 index 000000000..b543c1599 --- /dev/null +++ b/qemu/roms/openbios/arch/sparc32/ldscript @@ -0,0 +1,73 @@ +OUTPUT_FORMAT(elf32-sparc) +OUTPUT_ARCH(sparc) + +/* QEMU ELF loader can't handle very complex files, so we put ELFBoot +info to rodata and put initctx to data.*/ + +ENTRY(trap_table) + +/* Initial load address + */ +BASE_ADDR = 0xffd00000; + +/* 16KB stack */ +STACK_SIZE = 16384; +VMEM_SIZE = 128 * 1024; +IOMEM_SIZE = 256 * 1024 + 768 * 1024; + +SECTIONS +{ + . = BASE_ADDR; + + /* Start of the program. + * Now the version string is in the note, we must include it + * in the program. Otherwise we lose the string after relocation. */ + _start = .; + + /* Normal sections */ + .text ALIGN(4096): { + *(.text.vectors) + *(.text) + *(.text.*) + } + .rodata ALIGN(4096): { + _rodata = .; + sound_drivers_start = .; + *(.rodata.sound_drivers) + sound_drivers_end = .; + *(.rodata) + *(.rodata.*) + *(.note.ELFBoot) + } + .data ALIGN(4096): { + _data = .; + *(.data) + *(.data.*) + } + + .bss ALIGN(4096): { + _bss = .; + *(.bss) + *(.bss.*) + *(COMMON) + + . = ALIGN(4096); + _vmem = .; + . += VMEM_SIZE; + _evmem = .; + + _stack = .; + . += STACK_SIZE; + . = ALIGN(16); + _estack = .; + } + + . = ALIGN(4096); + _end = .; + _iomem = _end + IOMEM_SIZE; + + /* We discard .note sections other than .note.ELFBoot, + * because some versions of GCC generates useless ones. */ + + /DISCARD/ : { *(.comment*) *(.note.*) } +} diff --git a/qemu/roms/openbios/arch/sparc32/lib.c b/qemu/roms/openbios/arch/sparc32/lib.c new file mode 100644 index 000000000..d27b604c9 --- /dev/null +++ b/qemu/roms/openbios/arch/sparc32/lib.c @@ -0,0 +1,397 @@ +/* lib.c + * tag: simple function library + * + * Copyright (C) 2003 Stefan Reinauer + * + * See the file "COPYING" for further information about + * the copyright and warranty status of this work. + */ + +#include "libc/vsprintf.h" +#include "libopenbios/bindings.h" +#include "arch/sparc32/ofmem_sparc32.h" +#include "asm/asi.h" +#include "pgtsrmmu.h" +#include "openprom.h" +#include "libopenbios/sys_info.h" +#include "boot.h" +#include "romvec.h" + +#define NCTX_SWIFT 0x100 +#define LOWMEMSZ 32 * 1024 * 1024 + +#ifdef CONFIG_DEBUG_MEM +#define DPRINTF(fmt, args...) \ + do { printk(fmt , ##args); } while (0) +#else +#define DPRINTF(fmt, args...) +#endif + +/* Format a string and print it on the screen, just like the libc + * function printf. + */ +int printk( const char *fmt, ... ) +{ + char *p, buf[512]; + va_list args; + int i; + + va_start(args, fmt); + i = vsnprintf(buf, sizeof(buf), fmt, args); + va_end(args); + + for( p=buf; *p; p++ ) + putchar(*p); + return i; +} + +/* + * Allocatable memory chunk. + */ +struct mem { + char *start, *uplim; + char *curp; +}; + +struct mem cdvmem; /* Current device virtual memory space */ + +unsigned int va_shift; +unsigned long *l1; +static unsigned long *context_table; + +struct linux_mlist_v0 *ptphys; +struct linux_mlist_v0 *ptmap; +struct linux_mlist_v0 *ptavail; + +/* Private functions for mapping between physical/virtual addresses */ +phys_addr_t +va2pa(unsigned long va) +{ + if ((va >= (unsigned long)&_start) && + (va < (unsigned long)&_end)) + return va - va_shift; + else + return va; +} + +unsigned long +pa2va(phys_addr_t pa) +{ + if ((pa + va_shift >= (unsigned long)&_start) && + (pa + va_shift < (unsigned long)&_end)) + return pa + va_shift; + else + return pa; +} + +void * +malloc(int size) +{ + return ofmem_malloc(size); +} + +void * +realloc( void *ptr, size_t size ) +{ + return ofmem_realloc(ptr, size); +} + +void +free(void *ptr) +{ + ofmem_free(ptr); +} + +/* + * Allocate memory. This is reusable. + */ +void +mem_init(struct mem *t, char *begin, char *limit) +{ + t->start = begin; + t->uplim = limit; + t->curp = begin; +} + +void * +mem_alloc(struct mem *t, int size, int align) +{ + char *p; + unsigned long pa; + + // The alignment restrictions refer to physical, not virtual + // addresses + pa = va2pa((unsigned long)t->curp) + (align - 1); + pa &= ~(align - 1); + p = (char *)pa2va(pa); + + if ((unsigned long)p >= (unsigned long)t->uplim || + (unsigned long)p + size > (unsigned long)t->uplim) + return NULL; + t->curp = p + size; + + return p; +} + +/* + * D5.3 pgmap@ ( va -- pte ) + */ +static void +pgmap_fetch(void) +{ + uint32_t pte; + unsigned long va, pa; + + va = POP(); + + pa = find_pte(va, 0); + if (pa == 1 || pa == 2) + goto error; + pte = *(uint32_t *)pa; + DPRINTF("pgmap@: va 0x%lx pa 0x%lx pte 0x%x\n", va, pa, pte); + + PUSH(pte); + return; + error: + PUSH(0); +} + +/* + * D5.3 pgmap! ( pte va -- ) + */ +static void +pgmap_store(void) +{ + uint32_t pte; + unsigned long va, pa; + + va = POP(); + pte = POP(); + + pa = find_pte(va, 1); + *(uint32_t *)pa = pte; + DPRINTF("pgmap!: va 0x%lx pa 0x%lx pte 0x%x\n", va, pa, pte); +} + +/* + * D5.3 map-pages ( pa space va size -- ) + */ +static void +ob_map_pages(void) +{ + unsigned long va; + int size; + uint64_t pa; + + size = POP(); + va = POP(); + pa = POP(); + pa <<= 32; + pa |= POP() & 0xffffffff; + + ofmem_arch_map_pages(pa, va, size, ofmem_arch_default_translation_mode(pa)); +} + +char *obp_dumb_mmap(char *va, int which_io, unsigned int pa, + unsigned int size) +{ + uint64_t mpa = ((uint64_t)which_io << 32) | (uint64_t)pa; + + ofmem_arch_map_pages(mpa, (unsigned long)va, size, ofmem_arch_default_translation_mode(mpa)); + return va; +} + +void obp_dumb_munmap(__attribute__((unused)) char *va, + __attribute__((unused)) unsigned int size) +{ + DPRINTF("obp_dumb_munmap: virta 0x%x, sz %d\n", (unsigned int)va, size); +} + +char *obp_memalloc(char *va, unsigned int size, unsigned int align) +{ + phys_addr_t phys; + ucell virt; + + DPRINTF("obp_memalloc: virta 0x%x, sz %d, align %d\n", (unsigned int)va, size, align); + + /* Claim physical memory */ + phys = ofmem_claim_phys(-1, size, align); + + /* Claim virtual memory */ + virt = ofmem_claim_virt(pointer2cell(va), size, 0); + + /* Map the memory */ + ofmem_map(phys, virt, size, ofmem_arch_default_translation_mode(phys)); + + return cell2pointer(virt); +} + +char *obp_dumb_memalloc(char *va, unsigned int size) +{ + unsigned long align = size; + phys_addr_t phys; + ucell virt; + + DPRINTF("obp_dumb_memalloc: virta 0x%x, sz %d\n", (unsigned int)va, size); + + /* Solaris seems to assume that the returned value is physically aligned to size. + e.g. it is used for setting up page tables. */ + + /* Claim physical memory */ + phys = ofmem_claim_phys(-1, size, align); + + /* Claim virtual memory - if va == NULL then we choose va address */ + if (va == NULL) { + virt = ofmem_claim_virt((ucell)-1, size, align); + } else { + virt = ofmem_claim_virt(pointer2cell(va), size, 0); + } + + /* Map the memory */ + ofmem_map(phys, virt, size, ofmem_arch_default_translation_mode(phys)); + + return cell2pointer(virt); +} + +void obp_dumb_memfree(char *va, unsigned size) +{ + phys_addr_t phys; + ucell cellmode; + + DPRINTF("obp_dumb_memfree: virta 0x%x, sz %d\n", (unsigned int)va, size); + + phys = ofmem_translate(pointer2cell(va), &cellmode); + + ofmem_unmap(pointer2cell(va), size); + ofmem_release_virt(pointer2cell(va), size); + ofmem_release_phys(phys, size); +} + +/* Data fault handling routines */ + +extern unsigned int ignore_dfault; + +/* ( -- reg ) */ +static void srmmu_get_sfsr(void) +{ + PUSH(srmmu_get_fstatus()); +} + +/* ( -- addr ) */ +static void ignore_dfault_addr(void) +{ + PUSH(pointer2cell(&ignore_dfault)); +} + +void +ob_init_mmu(void) +{ + ucell *memreg; + ucell *virtreg; + phys_addr_t virtregsize; + ofmem_t *ofmem = ofmem_arch_get_private(); + + /* Find the phandles for the /memory and /virtual-memory nodes */ + push_str("/memory"); + fword("find-package"); + POP(); + s_phandle_memory = POP(); + + push_str("/virtual-memory"); + fword("find-package"); + POP(); + s_phandle_mmu = POP(); + + ofmem_register(s_phandle_memory, s_phandle_mmu); + + /* Setup /memory:reg (totphys) property */ + memreg = malloc(3 * sizeof(ucell)); + ofmem_arch_encode_physaddr(memreg, 0); /* physical base */ + memreg[2] = (ucell)ofmem->ramsize; /* size */ + + push_str("/memory"); + fword("find-device"); + PUSH(pointer2cell(memreg)); + PUSH(3 * sizeof(ucell)); + push_str("reg"); + PUSH_ph(s_phandle_memory); + fword("encode-property"); + + /* Setup /virtual-memory:reg property */ + virtregsize = ((phys_addr_t)((ucell)-1) + 1) / 2; + + virtreg = malloc(6 * sizeof(ucell)); + ofmem_arch_encode_physaddr(virtreg, 0); + virtreg[2] = virtregsize; + ofmem_arch_encode_physaddr(&virtreg[3], virtregsize); + virtreg[5] = virtregsize; + + push_str("/virtual-memory"); + fword("find-device"); + PUSH(pointer2cell(virtreg)); + PUSH(6 * sizeof(ucell)); + push_str("reg"); + PUSH_ph(s_phandle_mmu); + fword("encode-property"); + + PUSH(0); + fword("active-package!"); + bind_func("pgmap@", pgmap_fetch); + bind_func("pgmap!", pgmap_store); + bind_func("map-pages", ob_map_pages); + + /* Install data fault handler words for cpeek etc. */ + PUSH_xt(bind_noname_func(srmmu_get_sfsr)); + feval("to sfsr@"); + PUSH_xt(bind_noname_func(ignore_dfault_addr)); + feval("to ignore-dfault"); +} + +/* + * Switch page tables. + */ +void +init_mmu_swift(void) +{ + unsigned int addr, i; + unsigned long pa, va; + int size; + + ofmem_posix_memalign((void *)&context_table, NCTX_SWIFT * sizeof(int), + NCTX_SWIFT * sizeof(int)); + ofmem_posix_memalign((void *)&l1, 256 * sizeof(int), 256 * sizeof(int)); + + context_table[0] = (((unsigned long)va2pa((unsigned long)l1)) >> 4) | + SRMMU_ET_PTD; + + for (i = 1; i < NCTX_SWIFT; i++) { + context_table[i] = SRMMU_ET_INVALID; + } + for (i = 0; i < 256; i++) { + l1[i] = SRMMU_ET_INVALID; + } + + // text, rodata, data, and bss mapped to end of RAM + va = (unsigned long)&_start; + size = (unsigned long)&_end - (unsigned long)&_start; + pa = va2pa(va); + ofmem_arch_map_pages(pa, va, size, ofmem_arch_default_translation_mode(pa)); + ofmem_map_page_range(pa, va, size, ofmem_arch_default_translation_mode(pa)); + + // 1:1 mapping for RAM (don't map page 0 to allow catching of NULL dereferences) + ofmem_arch_map_pages(PAGE_SIZE, PAGE_SIZE, LOWMEMSZ - PAGE_SIZE, ofmem_arch_default_translation_mode(0)); + ofmem_map_page_range(PAGE_SIZE, PAGE_SIZE, LOWMEMSZ - PAGE_SIZE, ofmem_arch_default_translation_mode(0)); + + /* + * Flush cache + */ + for (addr = 0; addr < 0x2000; addr += 0x10) { + __asm__ __volatile__ ("sta %%g0, [%0] %1\n\t" : : + "r" (addr), "i" (ASI_M_DATAC_TAG)); + __asm__ __volatile__ ("sta %%g0, [%0] %1\n\t" : : + "r" (addr<<1), "i" (ASI_M_TXTC_TAG)); + } + srmmu_set_context(0); + srmmu_set_ctable_ptr(va2pa((unsigned long)context_table)); + srmmu_flush_whole_tlb(); +} diff --git a/qemu/roms/openbios/arch/sparc32/linux_load.c b/qemu/roms/openbios/arch/sparc32/linux_load.c new file mode 100644 index 000000000..26f7fc6bb --- /dev/null +++ b/qemu/roms/openbios/arch/sparc32/linux_load.c @@ -0,0 +1,648 @@ +/* + * Linux/i386 loader + * Supports bzImage, zImage and Image format. + * + * Based on work by Steve Gehlbach. + * Portions are taken from mkelfImage. + * + * 2003-09 by SONE Takeshi + */ + +#include "config.h" +#include "kernel/kernel.h" +#include "libopenbios/bindings.h" +#include "libopenbios/sys_info.h" +#include "context.h" +#include "libc/diskio.h" +#include "boot.h" + +#define printf printk +#define debug printk +#define strtoull_with_suffix strtol + +#define LINUX_PARAM_LOC 0x90000 +#define COMMAND_LINE_LOC 0x91000 +#define GDT_LOC 0x92000 +#define STACK_LOC 0x93000 + +#define E820MAX 32 /* number of entries in E820MAP */ +struct e820entry { + unsigned long long addr; /* start of memory segment */ + unsigned long long size; /* size of memory segment */ + unsigned long type; /* type of memory segment */ +#define E820_RAM 1 +#define E820_RESERVED 2 +#define E820_ACPI 3 /* usable as RAM once ACPI tables have been read */ +#define E820_NVS 4 +}; + +/* The header of Linux/i386 kernel */ +struct linux_header { + uint8_t reserved1[0x1f1]; /* 0x000 */ + uint8_t setup_sects; /* 0x1f1 */ + uint16_t root_flags; /* 0x1f2 */ + uint8_t reserved2[6]; /* 0x1f4 */ + uint16_t vid_mode; /* 0x1fa */ + uint16_t root_dev; /* 0x1fc */ + uint16_t boot_sector_magic; /* 0x1fe */ + /* 2.00+ */ + uint8_t reserved3[2]; /* 0x200 */ + uint8_t header_magic[4]; /* 0x202 */ + uint16_t protocol_version; /* 0x206 */ + uint32_t realmode_swtch; /* 0x208 */ + uint16_t start_sys; /* 0x20c */ + uint16_t kver_addr; /* 0x20e */ + uint8_t type_of_loader; /* 0x210 */ + uint8_t loadflags; /* 0x211 */ + uint16_t setup_move_size; /* 0x212 */ + uint32_t code32_start; /* 0x214 */ + uint32_t ramdisk_image; /* 0x218 */ + uint32_t ramdisk_size; /* 0x21c */ + uint8_t reserved4[4]; /* 0x220 */ + /* 2.01+ */ + uint16_t heap_end_ptr; /* 0x224 */ + uint8_t reserved5[2]; /* 0x226 */ + /* 2.02+ */ + uint32_t cmd_line_ptr; /* 0x228 */ + /* 2.03+ */ + uint32_t initrd_addr_max; /* 0x22c */ +} __attribute__ ((packed)); + + +/* Paramters passed to 32-bit part of Linux + * This is another view of the structure above.. */ +struct linux_params { + uint8_t orig_x; /* 0x00 */ + uint8_t orig_y; /* 0x01 */ + uint16_t ext_mem_k; /* 0x02 -- EXT_MEM_K sits here */ + uint16_t orig_video_page; /* 0x04 */ + uint8_t orig_video_mode; /* 0x06 */ + uint8_t orig_video_cols; /* 0x07 */ + uint16_t unused2; /* 0x08 */ + uint16_t orig_video_ega_bx; /* 0x0a */ + uint16_t unused3; /* 0x0c */ + uint8_t orig_video_lines; /* 0x0e */ + uint8_t orig_video_isVGA; /* 0x0f */ + uint16_t orig_video_points; /* 0x10 */ + + /* VESA graphic mode -- linear frame buffer */ + uint16_t lfb_width; /* 0x12 */ + uint16_t lfb_height; /* 0x14 */ + uint16_t lfb_depth; /* 0x16 */ + uint32_t lfb_base; /* 0x18 */ + uint32_t lfb_size; /* 0x1c */ + uint16_t cl_magic; /* 0x20 */ +#define CL_MAGIC_VALUE 0xA33F + uint16_t cl_offset; /* 0x22 */ + uint16_t lfb_linelength; /* 0x24 */ + uint8_t red_size; /* 0x26 */ + uint8_t red_pos; /* 0x27 */ + uint8_t green_size; /* 0x28 */ + uint8_t green_pos; /* 0x29 */ + uint8_t blue_size; /* 0x2a */ + uint8_t blue_pos; /* 0x2b */ + uint8_t rsvd_size; /* 0x2c */ + uint8_t rsvd_pos; /* 0x2d */ + uint16_t vesapm_seg; /* 0x2e */ + uint16_t vesapm_off; /* 0x30 */ + uint16_t pages; /* 0x32 */ + uint8_t reserved4[12]; /* 0x34 -- 0x3f reserved for future expansion */ + + //struct apm_bios_info apm_bios_info; /* 0x40 */ + uint8_t apm_bios_info[0x40]; + //struct drive_info_struct drive_info; /* 0x80 */ + uint8_t drive_info[0x20]; + //struct sys_desc_table sys_desc_table; /* 0xa0 */ + uint8_t sys_desc_table[0x140]; + uint32_t alt_mem_k; /* 0x1e0 */ + uint8_t reserved5[4]; /* 0x1e4 */ + uint8_t e820_map_nr; /* 0x1e8 */ + uint8_t reserved6[9]; /* 0x1e9 */ + uint16_t mount_root_rdonly; /* 0x1f2 */ + uint8_t reserved7[4]; /* 0x1f4 */ + uint16_t ramdisk_flags; /* 0x1f8 */ +#define RAMDISK_IMAGE_START_MASK 0x07FF +#define RAMDISK_PROMPT_FLAG 0x8000 +#define RAMDISK_LOAD_FLAG 0x4000 + uint8_t reserved8[2]; /* 0x1fa */ + uint16_t orig_root_dev; /* 0x1fc */ + uint8_t reserved9[1]; /* 0x1fe */ + uint8_t aux_device_info; /* 0x1ff */ + uint8_t reserved10[2]; /* 0x200 */ + uint8_t param_block_signature[4]; /* 0x202 */ + uint16_t param_block_version; /* 0x206 */ + uint8_t reserved11[8]; /* 0x208 */ + uint8_t loader_type; /* 0x210 */ +#define LOADER_TYPE_LOADLIN 1 +#define LOADER_TYPE_BOOTSECT_LOADER 2 +#define LOADER_TYPE_SYSLINUX 3 +#define LOADER_TYPE_ETHERBOOT 4 +#define LOADER_TYPE_KERNEL 5 + uint8_t loader_flags; /* 0x211 */ + uint8_t reserved12[2]; /* 0x212 */ + uint32_t kernel_start; /* 0x214 */ + uint32_t initrd_start; /* 0x218 */ + uint32_t initrd_size; /* 0x21c */ + uint8_t reserved12_5[8]; /* 0x220 */ + uint32_t cmd_line_ptr; /* 0x228 */ + uint8_t reserved13[164]; /* 0x22c */ + struct e820entry e820_map[E820MAX]; /* 0x2d0 */ + uint8_t reserved16[688]; /* 0x550 */ +#define COMMAND_LINE_SIZE 256 + /* Command line is copied here by 32-bit i386/kernel/head.S. + * So I will follow the boot protocol, rather than putting it + * directly here. --ts1 */ + uint8_t command_line[COMMAND_LINE_SIZE]; /* 0x800 */ + uint8_t reserved17[1792]; /* 0x900 - 0x1000 */ +}; + +static uint64_t forced_memsize; +static int fd; + +static unsigned long file_size(void) +{ + long long fpos, fsize; + + /* Save current position */ + fpos = tell(fd); + + /* Go to end of file and get position */ + seek_io(fd, -1); + fsize = tell(fd); + + /* Go back to old position */ + seek_io(fd, 0); + seek_io(fd, fpos); + + return fsize; +} + +/* Load the first part the file and check if it's Linux */ +static uint32_t load_linux_header(struct linux_header *hdr) +{ + int load_high; + uint32_t kern_addr; + + if (read_io(fd, hdr, sizeof *hdr) != sizeof *hdr) { + debug("Can't read Linux header\n"); + return 0; + } + if (hdr->boot_sector_magic != 0xaa55) { + debug("Not a Linux kernel image\n"); + return 0; + } + + /* Linux is found. Print some information */ + if (memcmp(hdr->header_magic, "HdrS", 4) != 0) { + /* This may be floppy disk image or something. + * Perform a simple (incomplete) sanity check. */ + if (hdr->setup_sects >= 16 + || file_size() - (hdr->setup_sects<<9) >= 512<<10) { + debug("This looks like a bootdisk image but not like Linux...\n"); + return 0; + } + + printf("Possible very old Linux"); + /* This kernel does not even have a protocol version. + * Force the value. */ + hdr->protocol_version = 0; /* pre-2.00 */ + } else + printf("Found Linux"); + if (hdr->protocol_version >= 0x200 && hdr->kver_addr) { + char kver[256]; + seek_io(fd, hdr->kver_addr + 0x200); + if (read_io(fd, kver, sizeof kver) != 0) { + kver[255] = 0; + printf(" version %s", kver); + } + } + debug(" (protocol %#x)", hdr->protocol_version); + load_high = 0; + if (hdr->protocol_version >= 0x200) { + debug(" (loadflags %#x)", hdr->loadflags); + load_high = hdr->loadflags & 1; + } + if (load_high) { + printf(" bzImage"); + kern_addr = 0x100000; + } else { + printf(" zImage or Image"); + kern_addr = 0x1000; + } + printf(".\n"); + + return kern_addr; +} + +/* Set up parameters for 32-bit kernel */ +static void +init_linux_params(struct linux_params *params, struct linux_header *hdr) +{ + debug("Setting up paramters at %#lx\n", virt_to_phys(params)); + memset(params, 0, sizeof *params); + + /* Copy some useful values from header */ + params->mount_root_rdonly = hdr->root_flags; + params->orig_root_dev = hdr->root_dev; + + /* Video parameters. + * This assumes we have VGA in standard 80x25 text mode, + * just like our vga.c does. + * Cursor position is filled later to allow some more printf's. */ + params->orig_video_mode = 3; + params->orig_video_cols = 80; + params->orig_video_lines = 25; + params->orig_video_isVGA = 1; + params->orig_video_points = 16; + + params->loader_type = 0xff; /* Unregistered Linux loader */ +} + +/* Memory map */ +static void +set_memory_size(struct linux_params *params, struct sys_info *info) +{ + int i; + uint64_t end; + uint32_t ramtop = 0; + struct e820entry *linux_map; + struct memrange *filo_map; + + linux_map = params->e820_map; + filo_map = info->memrange; + for (i = 0; i < info->n_memranges; i++, linux_map++, filo_map++) { + if (i < E820MAX) { + /* Convert to BIOS e820 style */ + linux_map->addr = filo_map->base; + linux_map->size = filo_map->size; + linux_map->type = E820_RAM; + debug("%016Lx - %016Lx\n", linux_map->addr, + linux_map->addr + linux_map->size); + params->e820_map_nr = i+1; + } + + /* Find out top of RAM. XXX This ignores hole above 1MB */ + end = filo_map->base + filo_map->size; + if (end < (1ULL << 32)) { /* don't count memory above 4GB */ + if (end > ramtop) + ramtop = (uint32_t) end; + } + } + debug("ramtop=%#x\n", ramtop); + /* Size of memory above 1MB in KB */ + params->alt_mem_k = (ramtop - (1<<20)) >> 10; + /* old style, 64MB max */ + if (ramtop >= (64<<20)) + params->ext_mem_k = (63<<10); + else + params->ext_mem_k = params->alt_mem_k; + debug("ext_mem_k=%d, alt_mem_k=%d\n", params->ext_mem_k, params->alt_mem_k); +} + +/* + * Parse command line + * Some parameters, like initrd=<file>, are not passed to kernel, + * we are responsible to process them. + * Parameters for kernel are copied to kern_cmdline. Returns name of initrd. + */ +static char *parse_command_line(const char *orig_cmdline, char *kern_cmdline) +{ + const char *start, *sep, *end, *val; + char name[64]; + unsigned long len; + int k_len; + int to_kern; + char *initrd = NULL; + int toolong = 0; + + forced_memsize = 0; + + if (!orig_cmdline) { + *kern_cmdline = '\0'; + return NULL; + } + + k_len = 0; + debug("original command line: \"%s\"\n", orig_cmdline); + debug("kernel command line at %#lx\n", virt_to_phys(kern_cmdline)); + + start = orig_cmdline; + while (*start == ' ') + start++; + while (*start) { + end = strchr(start, ' '); + if (!end) + end = start + strlen(start); + sep = strchr(start, '='); + if (!sep || sep > end) + sep = end; + len = sep - start; + if (len >= sizeof(name)) + len = sizeof(name) - 1; + memcpy(name, start, len); + name[len] = 0; + + if (*sep == '=') { + val = sep + 1; + len = end - val; + } else { + val = NULL; + len = 0; + } + + /* Only initrd= and mem= are handled here. vga= is not, + * which I believe is a paramter to the realmode part of Linux, + * which we don't execute. */ + if (strcmp(name, "initrd") == 0) { + if (!val) + printf("Missing filename to initrd parameter\n"); + else { + initrd = malloc(len + 1); + memcpy(initrd, val, len); + initrd[len] = 0; + debug("initrd=%s\n", initrd); + } + /* Don't pass this to kernel */ + to_kern = 0; + } else if (strcmp(name, "mem") == 0) { + if (!val) + printf("Missing value for mem parameter\n"); + else { + forced_memsize = strtoull_with_suffix(val, (char**)&val, 0); + if (forced_memsize == 0) + printf("Invalid mem option, ignored\n"); + if (val != end) { + printf("Garbage after mem=<size>, ignored\n"); + forced_memsize = 0; + } + debug("mem=%Lu\n", forced_memsize); + } + /* mem= is for both loader and kernel */ + to_kern = 1; + } else + to_kern = 1; + + if (to_kern) { + /* Copy to kernel command line buffer */ + if (k_len != 0) + kern_cmdline[k_len++] = ' '; /* put separator */ + len = end - start; + if (k_len + len >= COMMAND_LINE_SIZE) { + len = COMMAND_LINE_SIZE - k_len - 1; + if (!toolong) { + printf("Kernel command line is too long; truncated to " + "%d bytes\n", COMMAND_LINE_SIZE-1); + toolong = 1; + } + } + memcpy(kern_cmdline + k_len, start, len); + k_len += len; + } + + start = end; + while (*start == ' ') + start++; + } + kern_cmdline[k_len] = 0; + debug("kernel command line (%d bytes): \"%s\"\n", k_len, kern_cmdline); + + return initrd; +} + +/* Set command line location */ +static void set_command_line_loc(struct linux_params *params, + struct linux_header *hdr) +{ + if (hdr->protocol_version >= 0x202) { + /* new style */ + params->cmd_line_ptr = COMMAND_LINE_LOC; + } else { + /* old style */ + params->cl_magic = CL_MAGIC_VALUE; + params->cl_offset = COMMAND_LINE_LOC - LINUX_PARAM_LOC; + } +} + +/* Load 32-bit part of kernel */ +static int load_linux_kernel(struct linux_header *hdr, uint32_t kern_addr) +{ + uint32_t kern_offset, kern_size; + + if (hdr->setup_sects == 0) + hdr->setup_sects = 4; + kern_offset = (hdr->setup_sects + 1) * 512; + seek_io(fd, kern_offset); + kern_size = file_size() - kern_offset; + debug("offset=%#x addr=%#x size=%#x\n", kern_offset, kern_addr, kern_size); + +#if 0 + if (using_devsize) { + printf("Attempt to load up to end of device as kernel; " + "specify the image size\n"); + return 0; + } +#endif + + printf("Loading kernel... "); + if ((uint32_t)read_io(fd, phys_to_virt(kern_addr), kern_size) != kern_size) { + printf("Can't read kernel\n"); + return 0; + } + printf("ok\n"); + + return kern_size; +} + +static int load_initrd(struct linux_header *hdr, uint32_t kern_end, + struct linux_params *params, const char *initrd_file) +{ + uint32_t max; + uint32_t start, end, size; + uint64_t forced; + + fd = open_io(initrd_file); + if (fd == -1) { + printf("Can't open initrd: %s\n", initrd_file); + return -1; + } + +#if 0 + if (using_devsize) { + printf("Attempt to load up to end of device as initrd; " + "specify the image size\n"); + return -1; + } +#endif + + size = file_size(); + + + /* Find out the kernel's restriction on how high the initrd can be + * placed */ + if (hdr->protocol_version >= 0x203) + max = hdr->initrd_addr_max; + else + max = 0x38000000; /* Hardcoded value for older kernels */ + + /* FILO itself is at the top of RAM. (relocated) + * So, try putting initrd just below us. */ + end = virt_to_phys(_start); + if (end > max) + end = max; + + /* If "mem=" option is given, we have to put the initrd within + * the specified range. */ + if (forced_memsize) { + forced = forced_memsize; + if (forced > max) + forced = max; + /* If the "mem=" is lower, it's easy */ + if (forced <= end) + end = forced; + else { + /* Otherwise, see if we can put it above us */ + if (virt_to_phys(_end) + size <= forced) + end = forced; /* Ok */ + } + } + + start = end - size; + start &= ~0xfff; /* page align */ + end = start + size; + + debug("start=%#x end=%#x\n", start, end); + + if (start < kern_end) { + printf("Initrd is too big to fit in memory\n"); + return -1; + } + + printf("Loading initrd... "); + if ((uint32_t)read_io(fd, phys_to_virt(start), size) != size) { + printf("Can't read initrd\n"); + return -1; + } + printf("ok\n"); + + params->initrd_start = start; + params->initrd_size = size; + + close_io(fd); + + return 0; +} + +static void hardware_setup(void) +{ + /* Disable nmi */ + outb(0x80, 0x70); + + /* Make sure any coprocessor is properly reset.. */ + outb(0, 0xf0); + outb(0, 0xf1); + + /* we're getting screwed again and again by this problem of the 8259. + * so we're going to leave this lying around for inclusion into + * crt0.S on an as-needed basis. + * + * well, that went ok, I hope. Now we have to reprogram the interrupts :-( + * we put them right after the intel-reserved hardware interrupts, at + * int 0x20-0x2F. There they won't mess up anything. Sadly IBM really + * messed this up with the original PC, and they haven't been able to + * rectify it afterwards. Thus the bios puts interrupts at 0x08-0x0f, + * which is used for the internal hardware interrupts as well. We just + * have to reprogram the 8259's, and it isn't fun. + */ + + outb(0x11, 0x20); /* initialization sequence to 8259A-1 */ + outb(0x11, 0xA0); /* and to 8259A-2 */ + + outb(0x20, 0x21); /* start of hardware int's (0x20) */ + outb(0x28, 0xA1); /* start of hardware int's 2 (0x28) */ + + outb(0x04, 0x21); /* 8259-1 is master */ + outb(0x02, 0xA1); /* 8259-2 is slave */ + + outb(0x01, 0x21); /* 8086 mode for both */ + outb(0x01, 0xA1); + + outb(0xFF, 0xA1); /* mask off all interrupts for now */ + outb(0xFB, 0x21); /* mask all irq's but irq2 which is cascaded */ +} + +/* Start Linux */ +static int start_linux(uint32_t kern_addr) +{ + struct context *ctx; + //extern int cursor_x, cursor_y; + + ctx = init_context(phys_to_virt(STACK_LOC), 4096, 0); + + /* Entry point */ + ctx->pc = kern_addr; + ctx->npc = kern_addr + 4; + + debug("pc=%#x\n", kern_addr); + printf("Jumping to entry point...\n"); + +#ifdef VGA_CONSOLE + /* Update VGA cursor position. + * This must be here because the printf changes the value! */ + params->orig_x = cursor_x; + params->orig_y = cursor_y; +#endif + + /* Go... */ + ctx = switch_to(ctx); + + /* It's impossible but... */ + printf("Returned with o0=%#x\n", ctx->regs[REG_O0]); + + return ctx->regs[REG_O0]; +} + +int linux_load(struct sys_info *info, const char *file, const char *cmdline) +{ + struct linux_header hdr; + struct linux_params *params; + uint32_t kern_addr, kern_size; + char *initrd_file = NULL; + + fd = open_io(file); + if (fd == -1) { + return -1; + } + + kern_addr = load_linux_header(&hdr); + if (kern_addr == 0) { + close_io(fd); + return LOADER_NOT_SUPPORT; + } + + params = phys_to_virt(LINUX_PARAM_LOC); + init_linux_params(params, &hdr); + set_memory_size(params, info); + initrd_file = parse_command_line(cmdline, phys_to_virt(COMMAND_LINE_LOC)); + set_command_line_loc(params, &hdr); + + kern_size = load_linux_kernel(&hdr, kern_addr); + if (kern_size == 0) { + if (initrd_file) + free(initrd_file); + return -1; + } + + if (initrd_file) { + if (load_initrd(&hdr, kern_addr+kern_size, params, initrd_file) + != 0) { + free(initrd_file); + return -1; + } + free(initrd_file); + } + + hardware_setup(); + + start_linux(kern_addr); + return 0; +} diff --git a/qemu/roms/openbios/arch/sparc32/multiboot.c b/qemu/roms/openbios/arch/sparc32/multiboot.c new file mode 100644 index 000000000..8514ca0a4 --- /dev/null +++ b/qemu/roms/openbios/arch/sparc32/multiboot.c @@ -0,0 +1,125 @@ +/* Support for Multiboot */ + +#include "config.h" +#include "asm/io.h" +#include "libopenbios/sys_info.h" +#include "multiboot.h" + +#define printf printk +#ifdef CONFIG_DEBUG_BOOT +#define debug printk +#else +#define debug(x...) +#endif + +struct mbheader { + unsigned int magic, flags, checksum; +}; +const struct mbheader multiboot_header + __attribute__((section (".hdr"))) = +{ + MULTIBOOT_HEADER_MAGIC, + MULTIBOOT_HEADER_FLAGS, + -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS) +}; + +/* Multiboot information structure, provided by loader to us */ + +struct multiboot_mmap { + unsigned entry_size; + unsigned base_lo, base_hi; + unsigned size_lo, size_hi; + unsigned type; +}; + +#define MULTIBOOT_MEM_VALID 0x01 +#define MULTIBOOT_BOOT_DEV_VALID 0x02 +#define MULTIBOOT_CMDLINE_VALID 0x04 +#define MULTIBOOT_MODS_VALID 0x08 +#define MULTIBOOT_AOUT_SYMS_VALID 0x10 +#define MULTIBOOT_ELF_SYMS_VALID 0x20 +#define MULTIBOOT_MMAP_VALID 0x40 + +void collect_multiboot_info(struct sys_info *info); +void collect_multiboot_info(struct sys_info *info) +{ + struct multiboot_info *mbinfo; + struct multiboot_mmap *mbmem; + unsigned mbcount, mbaddr; + unsigned int i; + struct memrange *mmap; + int mmap_count; + module_t *mod; + + if (info->boot_type != 0x2BADB002) + return; + + debug("Using Multiboot information at %#lx\n", info->boot_data); + + mbinfo = phys_to_virt(info->boot_data); + + if (mbinfo->mods_count != 1) { + printf("Multiboot: no dictionary\n"); + return; + } + + mod = (module_t *) mbinfo->mods_addr; + info->dict_start=(unsigned long *)mod->mod_start; + info->dict_end=(unsigned long *)mod->mod_end; + + if (mbinfo->flags & MULTIBOOT_MMAP_VALID) { + /* convert mmap records */ + mbmem = phys_to_virt(mbinfo->mmap_addr); + mbcount = mbinfo->mmap_length / (mbmem->entry_size + 4); + mmap = malloc(mbcount * sizeof(struct memrange)); + mmap_count = 0; + mbaddr = mbinfo->mmap_addr; + for (i = 0; i < mbcount; i++) { + mbmem = phys_to_virt(mbaddr); + debug("%08x%08x %08x%08x (%d)\n", + mbmem->base_hi, + mbmem->base_lo, + mbmem->size_hi, + mbmem->size_lo, + mbmem->type); + if (mbmem->type == 1) { /* Only normal RAM */ + mmap[mmap_count].base = mbmem->base_lo + + (((unsigned long long) mbmem->base_hi) << 32); + mmap[mmap_count].size = mbmem->size_lo + + (((unsigned long long) mbmem->size_hi) << 32); + mmap_count++; + } + mbaddr += mbmem->entry_size + 4; + if (mbaddr >= mbinfo->mmap_addr + mbinfo->mmap_length) + break; + } + /* simple sanity check - there should be at least 2 RAM segments + * (base 640k and extended) */ + if (mmap_count >= 2) + goto got_it; + + printf("Multiboot mmap is broken\n"); + free(mmap); + /* fall back to mem_lower/mem_upper */ + } + + if (mbinfo->flags & MULTIBOOT_MEM_VALID) { + /* use mem_lower and mem_upper */ + mmap_count = 2; + mmap = malloc(2 * sizeof(*mmap)); + mmap[0].base = 0; + mmap[0].size = mbinfo->mem_lower << 10; + mmap[1].base = 1 << 20; /* 1MB */ + mmap[1].size = mbinfo->mem_upper << 10; + goto got_it; + } + + printf("Can't get memory information from Multiboot\n"); + return; + +got_it: + info->memrange = mmap; + info->n_memranges = mmap_count; + + return; +} diff --git a/qemu/roms/openbios/arch/sparc32/multiboot.h b/qemu/roms/openbios/arch/sparc32/multiboot.h new file mode 100644 index 000000000..17cf202ec --- /dev/null +++ b/qemu/roms/openbios/arch/sparc32/multiboot.h @@ -0,0 +1,96 @@ +/* multiboot.h + * tag: header for multiboot + * + * Copyright (C) 2003-2004 Stefan Reinauer + * + * See the file "COPYING" for further information about + * the copyright and warranty status of this work. + */ + +/* magic number for multiboot header */ +#define MULTIBOOT_HEADER_MAGIC 0x1BADB002 + +/* flags for multiboot header */ +#define MULTIBOOT_HEADER_FLAGS 0x00010003 + +/* magic number passed by multiboot-compliant boot loader. */ +#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002 + +/* The size of our stack (8KB). */ +#define STACK_SIZE 0x2000 + +/* C symbol format. HAVE_ASM_USCORE is defined by configure. */ +#ifdef HAVE_ASM_USCORE +# define EXT_C(sym) _ ## sym +#else +# define EXT_C(sym) sym +#endif + +#ifndef ASM +/* We don't want these declarations in boot.S */ + +/* multiboot header */ +typedef struct multiboot_header { + unsigned long magic; + unsigned long flags; + unsigned long checksum; + unsigned long header_addr; + unsigned long load_addr; + unsigned long load_end_addr; + unsigned long bss_end_addr; + unsigned long entry_addr; +} multiboot_header_t; + +/* symbol table for a.out */ +typedef struct aout_symbol_table { + unsigned long tabsize; + unsigned long strsize; + unsigned long addr; + unsigned long reserved; +} aout_symbol_table_t; + +/* section header table for ELF */ +typedef struct elf_section_header_table { + unsigned long num; + unsigned long size; + unsigned long addr; + unsigned long shndx; +} elf_section_header_table_t; + +/* multiboot information */ +typedef struct multiboot_info { + unsigned long flags; + unsigned long mem_lower; + unsigned long mem_upper; + unsigned long boot_device; + unsigned long cmdline; + unsigned long mods_count; + unsigned long mods_addr; + union { + aout_symbol_table_t aout_sym; + elf_section_header_table_t elf_sec; + } u; + unsigned long mmap_length; + unsigned long mmap_addr; +} multiboot_info_t; + +/* module structure */ +typedef struct module { + unsigned long mod_start; + unsigned long mod_end; + unsigned long string; + unsigned long reserved; +} module_t; + +/* memory map. Be careful that the offset 0 is base_addr_low + but no size. */ +typedef struct memory_map { + unsigned long size; + unsigned long base_addr_low; + unsigned long base_addr_high; + unsigned long length_low; + unsigned long length_high; + unsigned long type; +} memory_map_t; + +#endif /* ! ASM */ diff --git a/qemu/roms/openbios/arch/sparc32/ofmem_sparc32.c b/qemu/roms/openbios/arch/sparc32/ofmem_sparc32.c new file mode 100644 index 000000000..f7af75366 --- /dev/null +++ b/qemu/roms/openbios/arch/sparc32/ofmem_sparc32.c @@ -0,0 +1,253 @@ +/* + * <ofmem_sparc32.c> + * + * OF Memory manager + * + * Copyright (C) 1999-2004 Samuel Rydh (samuel@ibrium.se) + * Copyright (C) 2004 Stefan Reinauer + * + * 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 + * + */ + +#include "config.h" +#include "libopenbios/bindings.h" +#include "libc/string.h" +#include "arch/sparc32/ofmem_sparc32.h" +#include "asm/asi.h" +#include "pgtsrmmu.h" + +#define OF_MALLOC_BASE ((char*)OFMEM + ALIGN_SIZE(sizeof(ofmem_t), 8)) + +#define MEMSIZE (256 * 1024) +static union { + char memory[MEMSIZE]; + ofmem_t ofmem; +} s_ofmem_data; + +#define OFMEM (&s_ofmem_data.ofmem) +#define TOP_OF_RAM (s_ofmem_data.memory + MEMSIZE) + +#define OFMEM_PHYS_RESERVED 0x1000000 + +translation_t **g_ofmem_translations = &s_ofmem_data.ofmem.trans; + +extern uint32_t qemu_mem_size; + +static inline size_t ALIGN_SIZE(size_t x, size_t a) +{ + return (x + a - 1) & ~(a-1); +} + +static ucell get_heap_top( void ) +{ + return (ucell)TOP_OF_RAM; +} + +ofmem_t* ofmem_arch_get_private(void) +{ + return OFMEM; +} + +void* ofmem_arch_get_malloc_base(void) +{ + return OF_MALLOC_BASE; +} + +ucell ofmem_arch_get_heap_top(void) +{ + return get_heap_top(); +} + +ucell ofmem_arch_get_virt_top(void) +{ + return (ucell)OFMEM_VIRT_TOP; +} + +ucell ofmem_arch_get_iomem_base(void) +{ + return pointer2cell(&_end); +} + +ucell ofmem_arch_get_iomem_top(void) +{ + return pointer2cell(&_iomem); +} + +retain_t *ofmem_arch_get_retained(void) +{ + /* Not used */ + return 0; +} + +int ofmem_arch_get_physaddr_cellsize(void) +{ + return 2; +} + +int ofmem_arch_encode_physaddr(ucell *p, phys_addr_t value) +{ + int n = 0; + + p[n++] = value >> 32; + p[n++] = value; + + return n; +} + +int ofmem_arch_get_translation_entry_size(void) +{ + /* Return size of a single MMU package translation property entry in cells */ + return 3; +} + +void ofmem_arch_create_translation_entry(ucell *transentry, translation_t *t) +{ + /* Generate translation property entry for SPARC. While there is no + formal documentation for this, both Linux kernel and OpenSolaris sources + expect a translation property entry to have the following layout: + + virtual address + length + mode + */ + + transentry[0] = t->virt; + transentry[1] = t->size; + transentry[2] = t->mode; +} + +/* Return the size of a memory available entry given the phandle in cells */ +int ofmem_arch_get_available_entry_size(phandle_t ph) +{ + return 1 + ofmem_arch_get_physaddr_cellsize(); +} + +/* Generate memory available property entry for Sparc32 */ +void ofmem_arch_create_available_entry(phandle_t ph, ucell *availentry, phys_addr_t start, ucell size) +{ + int i = 0; + + i += ofmem_arch_encode_physaddr(availentry, start); + availentry[i] = size; +} + +/* Unmap a set of pages */ +void ofmem_arch_unmap_pages(ucell virt, ucell size) +{ + unsigned long pa; + ucell i; + + for (i = 0; i < size; i += PAGE_SIZE) { + pa = find_pte(virt, 0); + *(uint32_t *)pa = 0; + virt += PAGE_SIZE; + } + + srmmu_flush_whole_tlb(); +} + +/* Map a set of pages */ +void ofmem_arch_map_pages(phys_addr_t phys, ucell virt, ucell size, ucell mode) +{ + unsigned long npages, off; + uint32_t pte; + unsigned long pa; + + off = phys & (PAGE_SIZE - 1); + npages = (off + (size - 1) + (PAGE_SIZE - 1)) / PAGE_SIZE; + phys &= ~(uint64_t)(PAGE_SIZE - 1); + + while (npages-- != 0) { + pa = find_pte(virt, 1); + + pte = SRMMU_ET_PTE | ((phys & PAGE_MASK) >> 4); + pte |= mode; + + *(uint32_t *)pa = pte; + + virt += PAGE_SIZE; + phys += PAGE_SIZE; + } +} + +/* Architecture-specific OFMEM helpers */ +unsigned long +find_pte(unsigned long va, int alloc) +{ + uint32_t pte; + void *p; + unsigned long pa; + int ret; + + pte = l1[(va >> SRMMU_PGDIR_SHIFT) & (SRMMU_PTRS_PER_PGD - 1)]; + if ((pte & SRMMU_ET_MASK) == SRMMU_ET_INVALID) { + if (alloc) { + ret = ofmem_posix_memalign(&p, SRMMU_PTRS_PER_PMD * sizeof(int), + SRMMU_PTRS_PER_PMD * sizeof(int)); + if (ret != 0) + return ret; + pte = SRMMU_ET_PTD | ((va2pa((unsigned long)p)) >> 4); + l1[(va >> SRMMU_PGDIR_SHIFT) & (SRMMU_PTRS_PER_PGD - 1)] = pte; + /* barrier() */ + } else { + return -1; + } + } + + pa = (pte & 0xFFFFFFF0) << 4; + pa += ((va >> SRMMU_PMD_SHIFT) & (SRMMU_PTRS_PER_PMD - 1)) << 2; + pte = *(uint32_t *)pa2va(pa); + if ((pte & SRMMU_ET_MASK) == SRMMU_ET_INVALID) { + if (alloc) { + ret = ofmem_posix_memalign(&p, SRMMU_PTRS_PER_PTE * sizeof(void *), + SRMMU_PTRS_PER_PTE * sizeof(void *)); + if (ret != 0) + return ret; + pte = SRMMU_ET_PTD | ((va2pa((unsigned int)p)) >> 4); + *(uint32_t *)pa2va(pa) = pte; + } else { + return -2; + } + } + + pa = (pte & 0xFFFFFFF0) << 4; + pa += ((va >> PAGE_SHIFT) & (SRMMU_PTRS_PER_PTE - 1)) << 2; + + return pa2va(pa); +} + +/************************************************************************/ +/* misc */ +/************************************************************************/ + +ucell ofmem_arch_default_translation_mode( phys_addr_t phys ) +{ + return SRMMU_REF | SRMMU_CACHE | SRMMU_PRIV; +} + +ucell ofmem_arch_io_translation_mode( phys_addr_t phys ) +{ + return SRMMU_REF | SRMMU_PRIV; +} + +/************************************************************************/ +/* init / cleanup */ +/************************************************************************/ + +void ofmem_init( void ) +{ + memset(&s_ofmem_data, 0, sizeof(s_ofmem_data)); + s_ofmem_data.ofmem.ramsize = qemu_mem_size; + + /* Mark the first page as non-free */ + ofmem_claim_virt(0, PAGE_SIZE, 0); + + /* Claim reserved physical addresses at top of RAM */ + ofmem_claim_phys(s_ofmem_data.ofmem.ramsize - OFMEM_PHYS_RESERVED, OFMEM_PHYS_RESERVED, 0); + + /* Claim OpenBIOS reserved space */ + ofmem_claim_virt(0xffd00000, 0x200000, 0); +} diff --git a/qemu/roms/openbios/arch/sparc32/openbios.c b/qemu/roms/openbios/arch/sparc32/openbios.c new file mode 100644 index 000000000..6f4ee454e --- /dev/null +++ b/qemu/roms/openbios/arch/sparc32/openbios.c @@ -0,0 +1,1005 @@ +/* tag: openbios forth environment, executable code + * + * Copyright (C) 2003 Patrick Mauritz, Stefan Reinauer + * + * See the file "COPYING" for further information about + * the copyright and warranty status of this work. + */ + +#include "config.h" +#include "libopenbios/openbios.h" +#include "libopenbios/bindings.h" +#include "libopenbios/console.h" +#include "drivers/drivers.h" +#include "asm/types.h" +#include "dict.h" +#include "kernel/kernel.h" +#include "kernel/stack.h" +#include "arch/common/nvram.h" +#include "packages/nvram.h" +#include "../../drivers/timer.h" // XXX +#include "libopenbios/sys_info.h" +#include "openbios.h" +#include "boot.h" +#include "romvec.h" +#include "openprom.h" +#include "psr.h" +#include "libopenbios/video.h" +#define NO_QEMU_PROTOS +#include "arch/common/fw_cfg.h" +#include "arch/sparc32/ofmem_sparc32.h" + +#define MEMORY_SIZE (128*1024) /* 128K ram for hosted system */ +#define UUID_FMT "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x" +#define FW_CFG_SUN4M_DEPTH (FW_CFG_ARCH_LOCAL + 0x00) + +int qemu_machine_type; + +struct hwdef { + uint64_t iommu_base, slavio_base; + uint64_t intctl_base, counter_base, nvram_base, ms_kb_base, serial_base; + unsigned long fd_offset, counter_offset, intr_offset; + unsigned long aux1_offset, aux2_offset; + uint64_t dma_base, esp_base, le_base; + uint64_t tcx_base; + int intr_ncpu; + int mid_offset; + int machine_id_low, machine_id_high; +}; + +static const struct hwdef hwdefs[] = { + /* SS-5 */ + { + .iommu_base = 0x10000000, + .tcx_base = 0x50000000, + .slavio_base = 0x71000000, + .ms_kb_base = 0x71000000, + .serial_base = 0x71100000, + .nvram_base = 0x71200000, + .fd_offset = 0x00400000, + .counter_offset = 0x00d00000, + .intr_offset = 0x00e00000, + .intr_ncpu = 1, + .aux1_offset = 0x00900000, + .aux2_offset = 0x00910000, + .dma_base = 0x78400000, + .esp_base = 0x78800000, + .le_base = 0x78c00000, + .mid_offset = 0, + .machine_id_low = 32, + .machine_id_high = 63, + }, + /* SS-10, SS-20 */ + { + .iommu_base = 0xfe0000000ULL, + .tcx_base = 0xe20000000ULL, + .slavio_base = 0xff1000000ULL, + .ms_kb_base = 0xff1000000ULL, + .serial_base = 0xff1100000ULL, + .nvram_base = 0xff1200000ULL, + .fd_offset = 0x00700000, // 0xff1700000ULL, + .counter_offset = 0x00300000, // 0xff1300000ULL, + .intr_offset = 0x00400000, // 0xff1400000ULL, + .intr_ncpu = 4, + .aux1_offset = 0x00800000, // 0xff1800000ULL, + .aux2_offset = 0x00a01000, // 0xff1a01000ULL, + .dma_base = 0xef0400000ULL, + .esp_base = 0xef0800000ULL, + .le_base = 0xef0c00000ULL, + .mid_offset = 8, + .machine_id_low = 64, + .machine_id_high = 65, + }, + /* SS-600MP */ + { + .iommu_base = 0xfe0000000ULL, + .tcx_base = 0xe20000000ULL, + .slavio_base = 0xff1000000ULL, + .ms_kb_base = 0xff1000000ULL, + .serial_base = 0xff1100000ULL, + .nvram_base = 0xff1200000ULL, + .fd_offset = -1, + .counter_offset = 0x00300000, // 0xff1300000ULL, + .intr_offset = 0x00400000, // 0xff1400000ULL, + .intr_ncpu = 4, + .aux1_offset = 0x00800000, // 0xff1800000ULL, + .aux2_offset = 0x00a01000, // 0xff1a01000ULL, XXX should not exist + .dma_base = 0xef0081000ULL, + .esp_base = 0xef0080000ULL, + .le_base = 0xef0060000ULL, + .mid_offset = 8, + .machine_id_low = 66, + .machine_id_high = 66, + }, +}; + +static const struct hwdef *hwdef; + +void setup_timers(void) +{ +} + +void udelay(unsigned int usecs) +{ +} + +void mdelay(unsigned int msecs) +{ +} + +static void mb86904_init(void) +{ + PUSH(32); + fword("encode-int"); + push_str("cache-line-size"); + fword("property"); + + PUSH(512); + fword("encode-int"); + push_str("cache-nlines"); + fword("property"); + + PUSH(0x23); + fword("encode-int"); + push_str("mask_rev"); + fword("property"); +} + +static void tms390z55_init(void) +{ + push_str(""); + fword("encode-string"); + push_str("ecache-parity?"); + fword("property"); + + push_str(""); + fword("encode-string"); + push_str("bfill?"); + fword("property"); + + push_str(""); + fword("encode-string"); + push_str("bcopy?"); + fword("property"); + + push_str(""); + fword("encode-string"); + push_str("cache-physical?"); + fword("property"); + + PUSH(0xf); + fword("encode-int"); + PUSH(0xf8fffffc); + fword("encode-int"); + fword("encode+"); + PUSH(4); + fword("encode-int"); + fword("encode+"); + + PUSH(0xf); + fword("encode-int"); + fword("encode+"); + PUSH(0xf8c00000); + fword("encode-int"); + fword("encode+"); + PUSH(0x1000); + fword("encode-int"); + fword("encode+"); + + PUSH(0xf); + fword("encode-int"); + fword("encode+"); + PUSH(0xf8000000); + fword("encode-int"); + fword("encode+"); + PUSH(0x1000); + fword("encode-int"); + fword("encode+"); + + PUSH(0xf); + fword("encode-int"); + fword("encode+"); + PUSH(0xf8800000); + fword("encode-int"); + fword("encode+"); + PUSH(0x1000); + fword("encode-int"); + fword("encode+"); + push_str("reg"); + fword("property"); +} + +static void rt625_init(void) +{ + PUSH(32); + fword("encode-int"); + push_str("cache-line-size"); + fword("property"); + + PUSH(512); + fword("encode-int"); + push_str("cache-nlines"); + fword("property"); + +} + +static void bad_cpu_init(void) +{ + printk("This CPU is not supported yet, freezing.\n"); + for(;;); +} + +struct cpudef { + unsigned long iu_version; + const char *name; + int psr_impl, psr_vers, impl, vers; + int dcache_line_size, dcache_lines, dcache_assoc; + int icache_line_size, icache_lines, icache_assoc; + int ecache_line_size, ecache_lines, ecache_assoc; + int mmu_nctx; + void (*initfn)(void); +}; + +static const struct cpudef sparc_defs[] = { + { + .iu_version = 0x00 << 24, /* Impl 0, ver 0 */ + .name = "FMI,MB86900", + .initfn = bad_cpu_init, + }, + { + .iu_version = 0x04 << 24, /* Impl 0, ver 4 */ + .name = "FMI,MB86904", + .psr_impl = 0, + .psr_vers = 4, + .impl = 0, + .vers = 4, + .dcache_line_size = 0x10, + .dcache_lines = 0x200, + .dcache_assoc = 1, + .icache_line_size = 0x20, + .icache_lines = 0x200, + .icache_assoc = 1, + .ecache_line_size = 0x20, + .ecache_lines = 0x4000, + .ecache_assoc = 1, + .mmu_nctx = 0x100, + .initfn = mb86904_init, + }, + { + .iu_version = 0x05 << 24, /* Impl 0, ver 5 */ + .name = "FMI,MB86907", + .psr_impl = 0, + .psr_vers = 5, + .impl = 0, + .vers = 5, + .dcache_line_size = 0x20, + .dcache_lines = 0x200, + .dcache_assoc = 1, + .icache_line_size = 0x20, + .icache_lines = 0x200, + .icache_assoc = 1, + .ecache_line_size = 0x20, + .ecache_lines = 0x4000, + .ecache_assoc = 1, + .mmu_nctx = 0x100, + .initfn = mb86904_init, + }, + { + .iu_version = 0x10 << 24, /* Impl 1, ver 0 */ + .name = "LSI,L64811", + .initfn = bad_cpu_init, + }, + { + .iu_version = 0x11 << 24, /* Impl 1, ver 1 */ + .name = "CY,CY7C601", + .psr_impl = 1, + .psr_vers = 1, + .impl = 1, + .vers = 1, + .mmu_nctx = 0x10, + .initfn = bad_cpu_init, + }, + { + .iu_version = 0x13 << 24, /* Impl 1, ver 3 */ + .name = "CY,CY7C611", + .initfn = bad_cpu_init, + }, + { + .iu_version = 0x40000000, + .name = "TI,TMS390Z55", + .psr_impl = 4, + .psr_vers = 0, + .impl = 0, + .vers = 4, + .dcache_line_size = 0x20, + .dcache_lines = 0x80, + .dcache_assoc = 4, + .icache_line_size = 0x40, + .icache_lines = 0x40, + .icache_assoc = 5, + .ecache_line_size = 0x20, + .ecache_lines = 0x8000, + .ecache_assoc = 1, + .mmu_nctx = 0x10000, + .initfn = tms390z55_init, + }, + { + .iu_version = 0x41000000, + .name = "TI,TMS390S10", + .psr_impl = 4, + .psr_vers = 1, + .impl = 4, + .vers = 1, + .dcache_line_size = 0x10, + .dcache_lines = 0x80, + .dcache_assoc = 4, + .icache_line_size = 0x20, + .icache_lines = 0x80, + .icache_assoc = 5, + .ecache_line_size = 0x20, + .ecache_lines = 0x8000, + .ecache_assoc = 1, + .mmu_nctx = 0x10000, + .initfn = tms390z55_init, + }, + { + .iu_version = 0x42000000, + .name = "TI,TMS390S10", + .psr_impl = 4, + .psr_vers = 2, + .impl = 4, + .vers = 2, + .dcache_line_size = 0x10, + .dcache_lines = 0x80, + .dcache_assoc = 4, + .icache_line_size = 0x20, + .icache_lines = 0x80, + .icache_assoc = 5, + .ecache_line_size = 0x20, + .ecache_lines = 0x8000, + .ecache_assoc = 1, + .mmu_nctx = 0x10000, + .initfn = tms390z55_init, + }, + { + .iu_version = 0x43000000, + .name = "TI,TMS390S10", + .psr_impl = 4, + .psr_vers = 3, + .impl = 4, + .vers = 3, + .dcache_line_size = 0x10, + .dcache_lines = 0x80, + .dcache_assoc = 4, + .icache_line_size = 0x20, + .icache_lines = 0x80, + .icache_assoc = 5, + .ecache_line_size = 0x20, + .ecache_lines = 0x8000, + .ecache_assoc = 1, + .mmu_nctx = 0x10000, + .initfn = tms390z55_init, + }, + { + .iu_version = 0x44000000, + .name = "TI,TMS390S10", + .psr_impl = 4, + .psr_vers = 4, + .impl = 4, + .vers = 4, + .dcache_line_size = 0x10, + .dcache_lines = 0x80, + .dcache_assoc = 4, + .icache_line_size = 0x20, + .icache_lines = 0x80, + .icache_assoc = 5, + .ecache_line_size = 0x20, + .ecache_lines = 0x8000, + .ecache_assoc = 1, + .mmu_nctx = 0x10000, + .initfn = tms390z55_init, + }, + { + .iu_version = 0x1e000000, + .name = "Ross,RT625", + .psr_impl = 1, + .psr_vers = 14, + .impl = 1, + .vers = 7, + .dcache_line_size = 0x20, + .dcache_lines = 0x80, + .dcache_assoc = 4, + .icache_line_size = 0x40, + .icache_lines = 0x40, + .icache_assoc = 5, + .ecache_line_size = 0x20, + .ecache_lines = 0x8000, + .ecache_assoc = 1, + .mmu_nctx = 0x10000, + .initfn = rt625_init, + }, + { + .iu_version = 0x1f000000, + .name = "Ross,RT620", + .psr_impl = 1, + .psr_vers = 15, + .impl = 1, + .vers = 7, + .dcache_line_size = 0x20, + .dcache_lines = 0x80, + .dcache_assoc = 4, + .icache_line_size = 0x40, + .icache_lines = 0x40, + .icache_assoc = 5, + .ecache_line_size = 0x20, + .ecache_lines = 0x8000, + .ecache_assoc = 1, + .mmu_nctx = 0x10000, + .initfn = rt625_init, + }, + { + .iu_version = 0x20000000, + .name = "BIT,B5010", + .initfn = bad_cpu_init, + }, + { + .iu_version = 0x50000000, + .name = "MC,MN10501", + .initfn = bad_cpu_init, + }, + { + .iu_version = 0x90 << 24, /* Impl 9, ver 0 */ + .name = "Weitek,W8601", + .initfn = bad_cpu_init, + }, + { + .iu_version = 0xf2000000, + .name = "GR,LEON2", + .initfn = bad_cpu_init, + }, + { + .iu_version = 0xf3000000, + .name = "GR,LEON3", + .initfn = bad_cpu_init, + }, +}; + +static const struct cpudef * +id_cpu(void) +{ + unsigned long iu_version; + unsigned int i; + + asm("rd %%psr, %0\n" + : "=r"(iu_version) :); + iu_version &= 0xff000000; + + for (i = 0; i < sizeof(sparc_defs)/sizeof(struct cpudef); i++) { + if (iu_version == sparc_defs[i].iu_version) + return &sparc_defs[i]; + } + printk("Unknown cpu (psr %lx), freezing!\n", iu_version); + for (;;); +} + +static void setup_cpu(int mid_offset) +{ + uint32_t temp; + unsigned int i; + const struct cpudef *cpu; + + // Add cpus + temp = fw_cfg_read_i32(FW_CFG_NB_CPUS); + + printk("CPUs: %x", temp); + cpu = id_cpu(); + printk(" x %s\n", cpu->name); + for (i = 0; i < temp; i++) { + push_str("/"); + fword("find-device"); + + fword("new-device"); + + push_str(cpu->name); + fword("device-name"); + + push_str("cpu"); + fword("device-type"); + + PUSH(cpu->psr_impl); + fword("encode-int"); + push_str("psr-implementation"); + fword("property"); + + PUSH(cpu->psr_vers); + fword("encode-int"); + push_str("psr-version"); + fword("property"); + + PUSH(cpu->impl); + fword("encode-int"); + push_str("implementation"); + fword("property"); + + PUSH(cpu->vers); + fword("encode-int"); + push_str("version"); + fword("property"); + + PUSH(4096); + fword("encode-int"); + push_str("page-size"); + fword("property"); + + PUSH(cpu->dcache_line_size); + fword("encode-int"); + push_str("dcache-line-size"); + fword("property"); + + PUSH(cpu->dcache_lines); + fword("encode-int"); + push_str("dcache-nlines"); + fword("property"); + + PUSH(cpu->dcache_assoc); + fword("encode-int"); + push_str("dcache-associativity"); + fword("property"); + + PUSH(cpu->icache_line_size); + fword("encode-int"); + push_str("icache-line-size"); + fword("property"); + + PUSH(cpu->icache_lines); + fword("encode-int"); + push_str("icache-nlines"); + fword("property"); + + PUSH(cpu->icache_assoc); + fword("encode-int"); + push_str("icache-associativity"); + fword("property"); + + PUSH(cpu->ecache_line_size); + fword("encode-int"); + push_str("ecache-line-size"); + fword("property"); + + PUSH(cpu->ecache_lines); + fword("encode-int"); + push_str("ecache-nlines"); + fword("property"); + + PUSH(cpu->ecache_assoc); + fword("encode-int"); + push_str("ecache-associativity"); + fword("property"); + + PUSH(2); + fword("encode-int"); + push_str("ncaches"); + fword("property"); + + PUSH(cpu->mmu_nctx); + fword("encode-int"); + push_str("mmu-nctx"); + fword("property"); + + PUSH(8); + fword("encode-int"); + push_str("sparc-version"); + fword("property"); + + push_str(""); + fword("encode-string"); + push_str("cache-coherence?"); + fword("property"); + + PUSH(i + mid_offset); + fword("encode-int"); + push_str("mid"); + fword("property"); + + cpu->initfn(); + + fword("finish-device"); + } +} + +static void dummy_mach_init(uint64_t base) +{ +} + +struct machdef { + uint16_t machine_id; + const char *banner_name; + const char *model; + const char *name; + void (*initfn)(uint64_t base); +}; + +static const struct machdef sun4m_defs[] = { + { + .machine_id = 32, + .banner_name = "SPARCstation 5", + .model = "SUNW,501-3059", + .name = "SUNW,SPARCstation-5", + .initfn = ss5_init, + }, + { + .machine_id = 33, + .banner_name = "SPARCstation Voyager", + .model = "SUNW,501-2581", + .name = "SUNW,SPARCstation-Voyager", + .initfn = dummy_mach_init, + }, + { + .machine_id = 34, + .banner_name = "SPARCstation LX", + .model = "SUNW,501-2031", + .name = "SUNW,SPARCstation-LX", + .initfn = dummy_mach_init, + }, + { + .machine_id = 35, + .banner_name = "SPARCstation 4", + .model = "SUNW,501-2572", + .name = "SUNW,SPARCstation-4", + .initfn = ss5_init, + }, + { + .machine_id = 36, + .banner_name = "SPARCstation Classic", + .model = "SUNW,501-2326", + .name = "SUNW,SPARCstation-Classic", + .initfn = dummy_mach_init, + }, + { + .machine_id = 37, + .banner_name = "Tadpole S3 GX", + .model = "S3", + .name = "Tadpole_S3GX", + .initfn = ss5_init, + }, + { + .machine_id = 64, + .banner_name = "SPARCstation 10 (1 X 390Z55)", + .model = "SUNW,S10,501-2365", + .name = "SUNW,SPARCstation-10", + .initfn = ob_eccmemctl_init, + }, + { + .machine_id = 65, + .banner_name = "SPARCstation 20 (1 X 390Z55)", + .model = "SUNW,S20,501-2324", + .name = "SUNW,SPARCstation-20", + .initfn = ob_eccmemctl_init, + }, + { + .machine_id = 66, + .banner_name = "SPARCsystem 600(1 X 390Z55)", + .model = NULL, + .name = "SUNW,SPARCsystem-600", + .initfn = ob_eccmemctl_init, + }, +}; + +static const struct machdef * +id_machine(uint16_t machine_id) +{ + unsigned int i; + + for (i = 0; i < sizeof(sun4m_defs)/sizeof(struct machdef); i++) { + if (machine_id == sun4m_defs[i].machine_id) + return &sun4m_defs[i]; + } + printk("Unknown machine (ID %d), freezing!\n", machine_id); + for (;;); +} + +static void setup_machine(uint64_t base) +{ + uint16_t machine_id; + const struct machdef *mach; + + machine_id = fw_cfg_read_i16(FW_CFG_MACHINE_ID); + mach = id_machine(machine_id); + + push_str("/"); + fword("find-device"); + push_str(mach->banner_name); + fword("encode-string"); + push_str("banner-name"); + fword("property"); + + if (mach->model) { + push_str(mach->model); + fword("encode-string"); + push_str("model"); + fword("property"); + } + push_str(mach->name); + fword("encode-string"); + push_str("name"); + fword("property"); + + mach->initfn(base); +} + +/* Add /uuid */ +static void setup_uuid(void) +{ + static uint8_t qemu_uuid[16]; + + fw_cfg_read(FW_CFG_UUID, (char *)qemu_uuid, 16); + + printk("UUID: " UUID_FMT "\n", qemu_uuid[0], qemu_uuid[1], qemu_uuid[2], + qemu_uuid[3], qemu_uuid[4], qemu_uuid[5], qemu_uuid[6], + qemu_uuid[7], qemu_uuid[8], qemu_uuid[9], qemu_uuid[10], + qemu_uuid[11], qemu_uuid[12], qemu_uuid[13], qemu_uuid[14], + qemu_uuid[15]); + + push_str("/"); + fword("find-device"); + + PUSH((long)&qemu_uuid); + PUSH(16); + fword("encode-bytes"); + push_str("uuid"); + fword("property"); +} + +static void setup_stdio(void) +{ + char nographic; + const char *stdin, *stdout; + + fw_cfg_read(FW_CFG_NOGRAPHIC, &nographic, 1); + if (nographic) { + obp_stdin = PROMDEV_TTYA; + obp_stdout = PROMDEV_TTYA; + stdin = "ttya"; + stdout = "ttya"; + } else { + obp_stdin = PROMDEV_KBD; + obp_stdout = PROMDEV_SCREEN; + stdin = "keyboard"; + stdout = "screen"; + } + + push_str(stdin); + push_str("input-device"); + fword("$setenv"); + + push_str(stdout); + push_str("output-device"); + fword("$setenv"); + + obp_stdin_path = stdin; + obp_stdout_path = stdout; +} + +static void init_memory(void) +{ + phys_addr_t phys; + ucell virt; + + /* Claim the memory from OFMEM */ + phys = ofmem_claim_phys(-1, MEMORY_SIZE, PAGE_SIZE); + if (!phys) + printk("panic: not enough physical memory on host system.\n"); + + virt = ofmem_claim_virt(OF_CODE_START - MEMORY_SIZE, MEMORY_SIZE, 0); + if (!virt) + printk("panic: not enough virtual memory on host system.\n"); + + /* Generate the mapping (and lock translation into the TLBs) */ + ofmem_map(phys, virt, MEMORY_SIZE, ofmem_arch_default_translation_mode(phys)); + + /* we push start and end of memory to the stack + * so that it can be used by the forth word QUIT + * to initialize the memory allocator + */ + + PUSH(virt); + PUSH(virt + MEMORY_SIZE); +} + +static void +arch_init( void ) +{ + char *cmdline; + const char *kernel_cmdline; + uint32_t temp; + uint16_t machine_id; + char buf[256]; + unsigned long mem_size; + + fw_cfg_init(); + + fw_cfg_read(FW_CFG_SIGNATURE, buf, 4); + buf[4] = '\0'; + + printk("Configuration device id %s", buf); + + temp = fw_cfg_read_i32(FW_CFG_ID); + machine_id = fw_cfg_read_i16(FW_CFG_MACHINE_ID); + + printk(" version %d machine id %d\n", temp, machine_id); + + if (temp != 1) { + printk("Incompatible configuration device version, freezing\n"); + for(;;); + } + + graphic_depth = fw_cfg_read_i16(FW_CFG_SUN4M_DEPTH); + + openbios_init(); + modules_init(); + ob_init_mmu(); + ob_init_iommu(hwdef->iommu_base); +#ifdef CONFIG_DRIVER_OBIO + mem_size = fw_cfg_read_i32(FW_CFG_RAM_SIZE); + ob_obio_init(hwdef->slavio_base, hwdef->fd_offset, + hwdef->counter_offset, hwdef->intr_offset, hwdef->intr_ncpu, + hwdef->aux1_offset, hwdef->aux2_offset, + mem_size); + + setup_machine(hwdef->slavio_base); + + nvconf_init(); +#endif +#ifdef CONFIG_DRIVER_SBUS +#ifdef CONFIG_DEBUG_CONSOLE_VIDEO + setup_video(); +#endif + ob_sbus_init(hwdef->iommu_base + 0x1000ULL, qemu_machine_type); +#endif + device_end(); + + setup_cpu(hwdef->mid_offset); + + setup_stdio(); + /* Initialiase openprom romvec */ + romvec = init_openprom(); + + kernel_size = fw_cfg_read_i32(FW_CFG_KERNEL_SIZE); + if (kernel_size) { + kernel_image = fw_cfg_read_i32(FW_CFG_KERNEL_ADDR); + + /* Mark the kernel memory as in use */ + ofmem_claim_phys(PAGE_ALIGN(kernel_image), PAGE_ALIGN(kernel_size), 0); + ofmem_claim_virt(PAGE_ALIGN(kernel_image), PAGE_ALIGN(kernel_size), 0); + } + + kernel_cmdline = (const char *) fw_cfg_read_i32(FW_CFG_KERNEL_CMDLINE); + if (kernel_cmdline) { + cmdline = strdup(kernel_cmdline); + obp_arg.argv[1] = cmdline; + } else { + cmdline = strdup(""); + } + qemu_cmdline = (uint32_t)cmdline; + + /* Setup nvram variables */ + push_str("/options"); + fword("find-device"); + push_str(cmdline); + fword("encode-string"); + push_str("boot-file"); + fword("property"); + + boot_device = fw_cfg_read_i16(FW_CFG_BOOT_DEVICE); + + switch (boot_device) { + case 'a': + push_str("floppy"); + break; + case 'c': + push_str("disk"); + break; + default: + case 'd': + push_str("cdrom:d cdrom"); + break; + case 'n': + push_str("net"); + break; + } + + fword("encode-string"); + push_str("boot-device"); + fword("property"); + + device_end(); + + bind_func("platform-boot", boot ); + bind_func("(go)", go ); + + /* Set up other properties */ + push_str("/chosen"); + fword("find-device"); + + setup_uuid(); + + /* Enable interrupts */ + temp = get_psr(); + temp = (temp & ~PSR_PIL) | (13 << 8); /* Enable CPU timer interrupt (level 14) */ + put_psr(temp); +} + +extern struct _console_ops arch_console_ops; + +int openbios(void) +{ + unsigned int i; + + for (i = 0; i < sizeof(hwdefs) / sizeof(struct hwdef); i++) { + if (hwdefs[i].machine_id_low <= qemu_machine_type && + hwdefs[i].machine_id_high >= qemu_machine_type) { + hwdef = &hwdefs[i]; + break; + } + } + if (!hwdef) + for(;;); // Internal inconsistency, hang + +#ifdef CONFIG_DEBUG_CONSOLE + init_console(arch_console_ops); +#endif + /* Make sure we setup OFMEM before the MMU as we need malloc() to setup page tables */ + ofmem_init(); + +#ifdef CONFIG_DRIVER_SBUS + init_mmu_swift(); +#endif +#ifdef CONFIG_DEBUG_CONSOLE +#ifdef CONFIG_DEBUG_CONSOLE_SERIAL + escc_uart_init(hwdef->serial_base | (CONFIG_SERIAL_PORT? 0ULL: 4ULL), + CONFIG_SERIAL_SPEED); +#endif +#ifdef CONFIG_DEBUG_CONSOLE_VIDEO + kbd_init(hwdef->ms_kb_base); +#endif +#endif + + collect_sys_info(&sys_info); + + dict = (unsigned char *)sys_info.dict_start; + dicthead = (cell)sys_info.dict_end; + last = sys_info.dict_last; + dictlimit = sys_info.dict_limit; + + forth_init(); + +#ifdef CONFIG_DEBUG_BOOT + printk("forth started.\n"); + printk("initializing memory..."); +#endif + + init_memory(); + +#ifdef CONFIG_DEBUG_BOOT + printk("done\n"); +#endif + + PUSH_xt( bind_noname_func(arch_init) ); + fword("PREPOST-initializer"); + + PC = (ucell)findword("initialize-of"); + + if (!PC) { + printk("panic: no dictionary entry point.\n"); + return -1; + } +#ifdef CONFIG_DEBUG_DICTIONARY + printk("done (%d bytes).\n", dicthead); + printk("Jumping to dictionary...\n"); +#endif + + enterforth((xt_t)PC); + + free(dict); + return 0; +} diff --git a/qemu/roms/openbios/arch/sparc32/openbios.h b/qemu/roms/openbios/arch/sparc32/openbios.h new file mode 100644 index 000000000..f7d47eab4 --- /dev/null +++ b/qemu/roms/openbios/arch/sparc32/openbios.h @@ -0,0 +1,28 @@ +/* + * Creation Date: <2004/01/15 16:14:05 samuel> + * Time-stamp: <2004/01/15 16:14:05 samuel> + * + * <openbios.h> + * + * + * + * Copyright (C) 2004 Samuel Rydh (samuel@ibrium.se) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#ifndef _H_OPENBIOS +#define _H_OPENBIOS + +int openbios(void); + +/* console.c */ +extern unsigned char *vmem; +#ifdef CONFIG_DEBUG_CONSOLE +extern void video_init(void); +#endif + +#endif /* _H_OPENBIOS */ diff --git a/qemu/roms/openbios/arch/sparc32/openprom.h b/qemu/roms/openbios/arch/sparc32/openprom.h new file mode 100644 index 000000000..0676be843 --- /dev/null +++ b/qemu/roms/openbios/arch/sparc32/openprom.h @@ -0,0 +1,260 @@ +#ifndef __SPARC_OPENPROM_H +#define __SPARC_OPENPROM_H + +/* openprom.h: Prom structures and defines for access to the OPENBOOT + * prom routines and data areas. + * + * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + */ + +// #include <asm/vaddrs.h> + +/* Empirical constants... */ +#define LINUX_OPPROM_MAGIC 0x10010407 + +#ifndef __ASSEMBLY__ +/* V0 prom device operations. */ +struct linux_dev_v0_funcs { + int (*v0_devopen)(char *device_str); + int (*v0_devclose)(int dev_desc); + int (*v0_rdblkdev)(int dev_desc, int num_blks, int blk_st, char *buf); + int (*v0_wrblkdev)(int dev_desc, int num_blks, int blk_st, char *buf); + int (*v0_wrnetdev)(int dev_desc, int num_bytes, char *buf); + int (*v0_rdnetdev)(int dev_desc, int num_bytes, char *buf); + int (*v0_rdchardev)(int dev_desc, int num_bytes, int dummy, char *buf); + int (*v0_wrchardev)(int dev_desc, int num_bytes, int dummy, char *buf); + int (*v0_seekdev)(int dev_desc, long logical_offst, int from); +}; + +/* V2 and later prom device operations. */ +struct linux_dev_v2_funcs { + int (*v2_inst2pkg)(int d); /* Convert ihandle to phandle */ + char * (*v2_dumb_mem_alloc)(char *va, unsigned sz); + void (*v2_dumb_mem_free)(char *va, unsigned sz); + + /* To map devices into virtual I/O space. */ + char * (*v2_dumb_mmap)(char *virta, int which_io, unsigned paddr, unsigned sz); + void (*v2_dumb_munmap)(char *virta, unsigned size); + + int (*v2_dev_open)(char *devpath); + void (*v2_dev_close)(int d); + int (*v2_dev_read)(int d, char *buf, int nbytes); + int (*v2_dev_write)(int d, char *buf, int nbytes); + int (*v2_dev_seek)(int d, int hi, int lo); + + /* Never issued (multistage load support) */ + void (*v2_wheee2)(void); + void (*v2_wheee3)(void); +}; + +struct linux_mlist_v0 { + struct linux_mlist_v0 *theres_more; + char *start_adr; + unsigned num_bytes; +}; + +struct linux_mem_v0 { + struct linux_mlist_v0 * const *v0_totphys; + struct linux_mlist_v0 * const *v0_prommap; + struct linux_mlist_v0 * const *v0_available; /* What we can use */ +}; + +/* Arguments sent to the kernel from the boot prompt. */ +struct linux_arguments_v0 { + const char *argv[8]; + char args[100]; + char boot_dev[2]; + int boot_dev_ctrl; + int boot_dev_unit; + int dev_partition; + const char *kernel_file_name; + void *aieee1; /* XXX */ +}; + +/* V2 and up boot things. */ +struct linux_bootargs_v2 { + const char **bootpath; + const char **bootargs; + const int *fd_stdin; + const int *fd_stdout; +}; + +/* The top level PROM vector. */ +struct linux_romvec { + /* Version numbers. */ + unsigned int pv_magic_cookie; + unsigned int pv_romvers; + unsigned int pv_plugin_revision; + unsigned int pv_printrev; + + /* Version 0 memory descriptors. */ + struct linux_mem_v0 pv_v0mem; + + /* Node operations. */ + const struct linux_nodeops *pv_nodeops; + + char **pv_bootstr; + struct linux_dev_v0_funcs pv_v0devops; + + const char *pv_stdin; + const char *pv_stdout; +#define PROMDEV_KBD 0 /* input from keyboard */ +#define PROMDEV_SCREEN 0 /* output to screen */ +#define PROMDEV_TTYA 1 /* in/out to ttya */ +#define PROMDEV_TTYB 2 /* in/out to ttyb */ + + /* Blocking getchar/putchar. NOT REENTRANT! (grr) */ + int (*pv_getchar)(void); + void (*pv_putchar)(int ch); + + /* Non-blocking variants. */ + int (*pv_nbgetchar)(void); + int (*pv_nbputchar)(int ch); + + void (*pv_putstr)(char *str, int len); + + /* Miscellany. */ + void (*pv_reboot)(char *bootstr); + void (*pv_printf)(__const__ char *fmt, ...); + void (*pv_abort)(void); + __volatile__ unsigned int *pv_ticks; + void (*pv_halt)(void); + void (**pv_synchook)(void); + + /* Evaluate a forth string, not different proto for V0 and V2->up. */ + union { + void (*v0_eval)(int len, char *str); + void (*v2_eval)(char *str, int arg0, int arg1, int arg2, int arg3, int arg4); + } pv_fortheval; + + const struct linux_arguments_v0 * const *pv_v0bootargs; + + /* Get ether address. */ + unsigned int (*pv_enaddr)(int d, char *enaddr); + + struct linux_bootargs_v2 pv_v2bootargs; + struct linux_dev_v2_funcs pv_v2devops; + + /* Prom version 3 memory allocation */ + char * (*v3_memalloc)(char *va, unsigned int size, unsigned int align); + + int filler[14]; + + /* This one is sun4c/sun4 only. */ + void (*pv_setctxt)(int ctxt, char *va, int pmeg); + + /* Prom version 3 Multiprocessor routines. This stuff is crazy. + * No joke. Calling these when there is only one cpu probably + * crashes the machine, have to test this. :-) + */ + + /* v3_cpustart() will start the cpu 'whichcpu' in mmu-context + * 'thiscontext' executing at address 'prog_counter' + */ + int (*v3_cpustart)(unsigned int whichcpu, int ctxtbl_ptr, + int thiscontext, char *prog_counter); + + /* v3_cpustop() will cause cpu 'whichcpu' to stop executing + * until a resume cpu call is made. + */ + int (*v3_cpustop)(unsigned int whichcpu); + + /* v3_cpuidle() will idle cpu 'whichcpu' until a stop or + * resume cpu call is made. + */ + int (*v3_cpuidle)(unsigned int whichcpu); + + /* v3_cpuresume() will resume processor 'whichcpu' executing + * starting with whatever 'pc' and 'npc' were left at the + * last 'idle' or 'stop' call. + */ + int (*v3_cpuresume)(unsigned int whichcpu); +}; + +/* Routines for traversing the prom device tree. */ +struct linux_nodeops { + int (*no_nextnode)(int node); + int (*no_child)(int node); + int (*no_proplen)(int node, const char *name); + int (*no_getprop)(int node, const char *name, char *val); + int (*no_setprop)(int node, const char *name, char *val, int len); + const char * (*no_nextprop)(int node, const char *name); +}; + +/* More fun PROM structures for device probing. */ +#define PROMREG_MAX 16 +#define PROMVADDR_MAX 16 +#define PROMINTR_MAX 15 + +struct linux_prom_registers { + unsigned int which_io; /* is this in OBIO space? */ + unsigned int phys_addr; /* The physical address of this register */ + unsigned int reg_size; /* How many bytes does this register take up? */ +}; + +struct linux_prom_irqs { + int pri; /* IRQ priority */ + int vector; /* This is foobar, what does it do? */ +}; + +/* Element of the "ranges" vector */ +struct linux_prom_ranges { + unsigned int ot_child_space; + unsigned int ot_child_base; /* Bus feels this */ + unsigned int ot_parent_space; + unsigned int ot_parent_base; /* CPU looks from here */ + unsigned int or_size; +}; + +/* Ranges and reg properties are a bit different for PCI. */ +struct linux_prom_pci_registers { + /* + * We don't know what information this field contain. + * We guess, PCI device function is in bits 15:8 + * So, ... + */ + unsigned int which_io; /* Let it be which_io */ + + unsigned int phys_hi; + unsigned int phys_lo; + + unsigned int size_hi; + unsigned int size_lo; +}; + +struct linux_prom_pci_ranges { + unsigned int child_phys_hi; /* Only certain bits are encoded here. */ + unsigned int child_phys_mid; + unsigned int child_phys_lo; + + unsigned int parent_phys_hi; + unsigned int parent_phys_lo; + + unsigned int size_hi; + unsigned int size_lo; +}; + +struct linux_prom_pci_assigned_addresses { + unsigned int which_io; + + unsigned int phys_hi; + unsigned int phys_lo; + + unsigned int size_hi; + unsigned int size_lo; +}; + +struct linux_prom_ebus_ranges { + unsigned int child_phys_hi; + unsigned int child_phys_lo; + + unsigned int parent_phys_hi; + unsigned int parent_phys_mid; + unsigned int parent_phys_lo; + + unsigned int size; +}; + +#endif /* !(__ASSEMBLY__) */ + +#endif /* !(__SPARC_OPENPROM_H) */ diff --git a/qemu/roms/openbios/arch/sparc32/pgtsrmmu.h b/qemu/roms/openbios/arch/sparc32/pgtsrmmu.h new file mode 100644 index 000000000..64dbaa657 --- /dev/null +++ b/qemu/roms/openbios/arch/sparc32/pgtsrmmu.h @@ -0,0 +1,223 @@ +/* + * Taken from kernel for decoupling from <asm/page.h>. --zaitcev + * + * $Id: pgtsrmmu.h,v 1.2 1999/04/19 01:04:31 zaitcev Exp $ + * pgtsrmmu.h: SRMMU page table defines and code. + * + * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + */ + +#ifndef _PGTSRMMU_H +#define _PGTSRMMU_H + +/* PMD_SHIFT determines the size of the area a second-level page table can map */ +#define SRMMU_PMD_SHIFT 18 +#define SRMMU_PMD_SIZE (1UL << SRMMU_PMD_SHIFT) +#define SRMMU_PMD_MASK (~(SRMMU_PMD_SIZE-1)) +#define SRMMU_PMD_ALIGN(addr) (((addr)+SRMMU_PMD_SIZE-1)&SRMMU_PMD_MASK) + +/* PGDIR_SHIFT determines what a third-level page table entry can map */ +#define SRMMU_PGDIR_SHIFT 24 +#define SRMMU_PGDIR_SIZE (1UL << SRMMU_PGDIR_SHIFT) +#define SRMMU_PGDIR_MASK (~(SRMMU_PGDIR_SIZE-1)) +#define SRMMU_PGDIR_ALIGN(addr) (((addr)+SRMMU_PGDIR_SIZE-1)&SRMMU_PGDIR_MASK) + +#define SRMMU_PTRS_PER_PTE 64 +#define SRMMU_PTRS_PER_PMD 64 +#define SRMMU_PTRS_PER_PGD 256 + +#define SRMMU_PTE_TABLE_SIZE 0x100 /* 64 entries, 4 bytes a piece */ +#define SRMMU_PMD_TABLE_SIZE 0x100 /* 64 entries, 4 bytes a piece */ +#define SRMMU_PGD_TABLE_SIZE 0x400 /* 256 entries, 4 bytes a piece */ + +#define SRMMU_VMALLOC_START (0xfe300000) +#define SRMMU_VMALLOC_END ~0x0UL + +/* Definition of the values in the ET field of PTD's and PTE's */ +#define SRMMU_ET_MASK 0x3 +#define SRMMU_ET_INVALID 0x0 +#define SRMMU_ET_PTD 0x1 +#define SRMMU_ET_PTE 0x2 +#define SRMMU_ET_REPTE 0x3 /* AIEEE, SuperSparc II reverse endian page! */ + +/* Physical page extraction from PTP's and PTE's. */ +#define SRMMU_CTX_PMASK 0xfffffff0 +#define SRMMU_PTD_PMASK 0xfffffff0 +#define SRMMU_PTE_PMASK 0xffffff00 + +/* The pte non-page bits. Some notes: + * 1) cache, dirty, valid, and ref are frobbable + * for both supervisor and user pages. + * 2) exec and write will only give the desired effect + * on user pages + * 3) use priv and priv_readonly for changing the + * characteristics of supervisor ptes + */ +#define SRMMU_CACHE 0x80 +#define SRMMU_DIRTY 0x40 +#define SRMMU_REF 0x20 +#define SRMMU_EXEC 0x08 +#define SRMMU_WRITE 0x04 +#define SRMMU_VALID 0x02 /* SRMMU_ET_PTE */ +#define SRMMU_PRIV 0x1c +#define SRMMU_PRIV_RDONLY 0x18 + +#define SRMMU_CHG_MASK (0xffffff00 | SRMMU_REF | SRMMU_DIRTY) + +/* SRMMU Register addresses in ASI 0x4. These are valid for all + * current SRMMU implementations that exist. + */ +#define SRMMU_CTRL_REG 0x00000000 +#define SRMMU_CTXTBL_PTR 0x00000100 +#define SRMMU_CTX_REG 0x00000200 +#define SRMMU_FAULT_STATUS 0x00000300 +#define SRMMU_FAULT_ADDR 0x00000400 + +#ifndef __ASSEMBLY__ + +/* Accessing the MMU control register. */ +static __inline__ unsigned int srmmu_get_mmureg(void) +{ + unsigned int retval; + __asm__ __volatile__("lda [%%g0] %1, %0\n\t" : + "=r" (retval) : + "i" (ASI_M_MMUREGS)); + return retval; +} + +static __inline__ void srmmu_set_mmureg(unsigned long regval) +{ + __asm__ __volatile__("sta %0, [%%g0] %1\n\t" : : + "r" (regval), "i" (ASI_M_MMUREGS) : "memory"); + +} + +static __inline__ void srmmu_set_ctable_ptr(unsigned long paddr) +{ + paddr = ((paddr >> 4) & SRMMU_CTX_PMASK); + __asm__ __volatile__("sta %0, [%1] %2\n\t" : : + "r" (paddr), "r" (SRMMU_CTXTBL_PTR), + "i" (ASI_M_MMUREGS) : + "memory"); +} + +static __inline__ unsigned long srmmu_get_ctable_ptr(void) +{ + unsigned int retval; + + __asm__ __volatile__("lda [%1] %2, %0\n\t" : + "=r" (retval) : + "r" (SRMMU_CTXTBL_PTR), + "i" (ASI_M_MMUREGS)); + return (retval & SRMMU_CTX_PMASK) << 4; +} + +static __inline__ void srmmu_set_context(int context) +{ + __asm__ __volatile__("sta %0, [%1] %2\n\t" : : + "r" (context), "r" (SRMMU_CTX_REG), + "i" (ASI_M_MMUREGS) : "memory"); +} + +static __inline__ int srmmu_get_context(void) +{ + register int retval; + __asm__ __volatile__("lda [%1] %2, %0\n\t" : + "=r" (retval) : + "r" (SRMMU_CTX_REG), + "i" (ASI_M_MMUREGS)); + return retval; +} + +static __inline__ unsigned int srmmu_get_fstatus(void) +{ + unsigned int retval; + + __asm__ __volatile__("lda [%1] %2, %0\n\t" : + "=r" (retval) : + "r" (SRMMU_FAULT_STATUS), "i" (ASI_M_MMUREGS)); + return retval; +} + +static __inline__ unsigned int srmmu_get_faddr(void) +{ + unsigned int retval; + + __asm__ __volatile__("lda [%1] %2, %0\n\t" : + "=r" (retval) : + "r" (SRMMU_FAULT_ADDR), "i" (ASI_M_MMUREGS)); + return retval; +} + +/* This is guaranteed on all SRMMU's. */ +static __inline__ void srmmu_flush_whole_tlb(void) +{ + __asm__ __volatile__("sta %%g0, [%0] %1\n\t": : + "r" (0x400), /* Flush entire TLB!! */ + "i" (ASI_M_FLUSH_PROBE) : "memory"); + +} + +/* These flush types are not available on all chips... */ +static __inline__ void srmmu_flush_tlb_ctx(void) +{ + __asm__ __volatile__("sta %%g0, [%0] %1\n\t": : + "r" (0x300), /* Flush TLB ctx.. */ + "i" (ASI_M_FLUSH_PROBE) : "memory"); + +} + +static __inline__ void srmmu_flush_tlb_region(unsigned long addr) +{ + addr &= SRMMU_PGDIR_MASK; + __asm__ __volatile__("sta %%g0, [%0] %1\n\t": : + "r" (addr | 0x200), /* Flush TLB region.. */ + "i" (ASI_M_FLUSH_PROBE) : "memory"); + +} + + +static __inline__ void srmmu_flush_tlb_segment(unsigned long addr) +{ + addr &= SRMMU_PMD_MASK; + __asm__ __volatile__("sta %%g0, [%0] %1\n\t": : + "r" (addr | 0x100), /* Flush TLB segment.. */ + "i" (ASI_M_FLUSH_PROBE) : "memory"); + +} + +static __inline__ void srmmu_flush_tlb_page(unsigned long page) +{ + page &= PAGE_MASK; + __asm__ __volatile__("sta %%g0, [%0] %1\n\t": : + "r" (page), /* Flush TLB page.. */ + "i" (ASI_M_FLUSH_PROBE) : "memory"); + +} + +static __inline__ unsigned long srmmu_hwprobe(unsigned long vaddr) +{ + unsigned long retval; + + vaddr &= PAGE_MASK; + __asm__ __volatile__("lda [%1] %2, %0\n\t" : + "=r" (retval) : + "r" (vaddr | 0x400), "i" (ASI_M_FLUSH_PROBE)); + + return retval; +} + +static __inline__ int +srmmu_get_pte (unsigned long addr) +{ + register unsigned long entry; + + __asm__ __volatile__("\n\tlda [%1] %2,%0\n\t" : + "=r" (entry): + "r" ((addr & 0xfffff000) | 0x400), "i" (ASI_M_FLUSH_PROBE)); + return entry; +} + +#endif /* !(__ASSEMBLY__) */ + +#endif /* !(_SPARC_PGTSRMMU_H) */ diff --git a/qemu/roms/openbios/arch/sparc32/plainboot.c b/qemu/roms/openbios/arch/sparc32/plainboot.c new file mode 100644 index 000000000..08dab2d12 --- /dev/null +++ b/qemu/roms/openbios/arch/sparc32/plainboot.c @@ -0,0 +1,21 @@ +/* tag: openbios fixed address forth starter + * + * Copyright (C) 2003 Stefan Reinauer + * + * See the file "COPYING" for further information about + * the copyright and warranty status of this work. + */ + +#include "config.h" +#include "libopenbios/sys_info.h" +#include "multiboot.h" + +#define FIXED_DICTSTART 0xfffe0000 +#define FIXED_DICTEND 0xfffeffff + +void collect_multiboot_info(struct sys_info *info); +void collect_multiboot_info(struct sys_info *info) +{ + info->dict_start=(unsigned long *)FIXED_DICTSTART; + info->dict_end=(unsigned long *)FIXED_DICTEND; +} diff --git a/qemu/roms/openbios/arch/sparc32/psr.h b/qemu/roms/openbios/arch/sparc32/psr.h new file mode 100644 index 000000000..0f6cfabb5 --- /dev/null +++ b/qemu/roms/openbios/arch/sparc32/psr.h @@ -0,0 +1,88 @@ +/* $Id: psr.h,v 1.1 2002/07/12 17:12:03 zaitcev Exp $ + * psr.h: This file holds the macros for masking off various parts of + * the processor status register on the Sparc. This is valid + * for Version 8. On the V9 this is renamed to the PSTATE + * register and its members are accessed as fields like + * PSTATE.PRIV for the current CPU privilege level. + * + * Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu) + */ + +#ifndef __LINUX_SPARC_PSR_H +#define __LINUX_SPARC_PSR_H + +/* The Sparc PSR fields are laid out as the following: + * + * ------------------------------------------------------------------------ + * | impl | vers | icc | resv | EC | EF | PIL | S | PS | ET | CWP | + * | 31-28 | 27-24 | 23-20 | 19-14 | 13 | 12 | 11-8 | 7 | 6 | 5 | 4-0 | + * ------------------------------------------------------------------------ + */ +#define PSR_CWP 0x0000001f /* current window pointer */ +#define PSR_ET 0x00000020 /* enable traps field */ +#define PSR_PS 0x00000040 /* previous privilege level */ +#define PSR_S 0x00000080 /* current privilege level */ +#define PSR_PIL 0x00000f00 /* processor interrupt level */ +#define PSR_EF 0x00001000 /* enable floating point */ +#define PSR_EC 0x00002000 /* enable co-processor */ +#define PSR_LE 0x00008000 /* SuperSparcII little-endian */ +#define PSR_ICC 0x00f00000 /* integer condition codes */ +#define PSR_C 0x00100000 /* carry bit */ +#define PSR_V 0x00200000 /* overflow bit */ +#define PSR_Z 0x00400000 /* zero bit */ +#define PSR_N 0x00800000 /* negative bit */ +#define PSR_VERS 0x0f000000 /* cpu-version field */ +#define PSR_IMPL 0xf0000000 /* cpu-implementation field */ + +#ifndef __ASSEMBLY +/* Get the %psr register. */ +static __inline__ unsigned int get_psr(void) +{ + unsigned int psr; + __asm__ __volatile__( + "rd %%psr, %0\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + : "=r" (psr) + : /* no inputs */ + : "memory"); + + return psr; +} + +static __inline__ void put_psr(unsigned int new_psr) +{ + __asm__ __volatile__( + "wr %0, 0x0, %%psr\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + : /* no outputs */ + : "r" (new_psr) + : "memory", "cc"); +} + +/* Get the %fsr register. Be careful, make sure the floating point + * enable bit is set in the %psr when you execute this or you will + * incur a trap. + */ + +static unsigned int fsr_storage; + +static __inline__ unsigned int get_fsr(void) +{ + unsigned int fsr = 0; + + __asm__ __volatile__( + "st %%fsr, %1\n\t" + "ld %1, %0\n\t" + : "=r" (fsr) + : "m" (fsr_storage)); + + return fsr; +} + +#endif /* !(__ASSEMBLY__) */ + +#endif /* !(__LINUX_SPARC_PSR_H) */ diff --git a/qemu/roms/openbios/arch/sparc32/romvec.c b/qemu/roms/openbios/arch/sparc32/romvec.c new file mode 100644 index 000000000..8757c28f2 --- /dev/null +++ b/qemu/roms/openbios/arch/sparc32/romvec.c @@ -0,0 +1,524 @@ +/* + * PROM interface support + * Copyright 1996 The Australian National University. + * Copyright 1996 Fujitsu Laboratories Limited + * Copyright 1999 Pete A. Zaitcev + * This software may be distributed under the terms of the Gnu + * Public License version 2 or later + */ + +#include <stdarg.h> + +#include "openprom.h" +#include "config.h" +#include "libopenbios/bindings.h" +#include "drivers/drivers.h" +#include "libopenbios/sys_info.h" +#include "boot.h" +#include "romvec.h" + +#ifdef CONFIG_DEBUG_OBP +#define DPRINTF(fmt, args...) \ + do { printk(fmt , ##args); } while (0) +#else +#define DPRINTF(fmt, args...) +#endif + +char obp_stdin, obp_stdout; +const char *obp_stdin_path, *obp_stdout_path; + +struct linux_arguments_v0 obp_arg; +const char *bootpath; +static const struct linux_arguments_v0 * const obp_argp = &obp_arg; + +static void (*sync_hook)(void); + +static struct linux_romvec romvec0; + +static void doublewalk(__attribute__((unused)) unsigned int ptab1, + __attribute__((unused)) unsigned int va) +{ +} + +int obp_nextnode(int node) +{ + int peer; + + PUSH(node); + fword("peer"); + peer = POP(); + DPRINTF("obp_nextnode(0x%x) = 0x%x\n", node, peer); + + return peer; +} + +int obp_child(int node) +{ + int child; + + PUSH(node); + fword("child"); + child = POP(); + DPRINTF("obp_child(0x%x) = 0x%x\n", node, child); + + return child; +} + +int obp_proplen(int node, const char *name) +{ + int notfound; + + if (!node) { + DPRINTF("obp_proplen(0x0, %s) = -1\n", name); + return -1; + } + + push_str(name); + PUSH(node); + fword("get-package-property"); + notfound = POP(); + + if (notfound) { + DPRINTF("obp_proplen(0x%x, %s) (not found)\n", node, name); + + return -1; + } else { + int len; + + len = POP(); + (void) POP(); + DPRINTF("obp_proplen(0x%x, %s) = %d\n", node, name, len); + + return len; + } +} + +#ifdef CONFIG_DEBUG_OBP +static int looks_like_string(const char *str, int len) +{ + int i; + int ret = (str[len-1] == '\0'); + for (i = 0; i < len-1 && ret; i++) + { + int ch = str[i] & 0xFF; + if (ch < 0x20 || ch > 0x7F) + ret = 0; + } + return ret; +} +#endif + +int obp_getprop(int node, const char *name, char *value) +{ + int notfound, found; + int len; + const char *str; + + if (!node) { + DPRINTF("obp_getprop(0x0, %s) = -1\n", name); + return -1; + } + + if (!name) { + // NULL name means get first property + push_str(""); + PUSH(node); + fword("next-property"); + found = POP(); + if (found) { + len = POP(); + str = (char *) POP(); + DPRINTF("obp_getprop(0x%x, NULL) = %s\n", node, str); + + return (int)str; + } + DPRINTF("obp_getprop(0x%x, NULL) (not found)\n", node); + + return -1; + } else { + push_str(name); + PUSH(node); + fword("get-package-property"); + notfound = POP(); + } + if (notfound) { + DPRINTF("obp_getprop(0x%x, %s) (not found)\n", node, name); + + return -1; + } else { + len = POP(); + str = (char *) POP(); + if (len > 0) + memcpy(value, str, len); + else + str = "NULL"; + +#ifdef CONFIG_DEBUG_OBP + if (looks_like_string(str, len)) { + DPRINTF("obp_getprop(0x%x, %s) = %s\n", node, name, str); + } else { + int i; + DPRINTF("obp_getprop(0x%x, %s) = ", node, name); + for (i = 0; i < len; i++) { + DPRINTF("%02x%s", str[i] & 0xFF, + (len == 4 || i == len-1) ? "" : " "); + } + DPRINTF("\n"); + } +#endif + + return len; + } +} + +const char *obp_nextprop(int node, const char *name) +{ + int found; + + if (!name || *name == '\0') { + // NULL name means get first property + push_str(""); + name = "NULL"; + } else { + push_str(name); + } + PUSH(node); + fword("next-property"); + found = POP(); + if (!found) { + DPRINTF("obp_nextprop(0x%x, %s) (not found)\n", node, name); + + return ""; + } else { + char *str; + + POP(); /* len */ + str = (char *) POP(); + + DPRINTF("obp_nextprop(0x%x, %s) = %s\n", node, name, str); + + return str; + } +} + +int obp_setprop(__attribute__((unused)) int node, + __attribute__((unused)) const char *name, + __attribute__((unused)) char *value, + __attribute__((unused)) int len) +{ + DPRINTF("obp_setprop(0x%x, %s) = %s (%d)\n", node, name, value, len); + + return -1; +} + +static const struct linux_nodeops nodeops0 = { + obp_nextnode_handler, /* int (*no_nextnode)(int node); */ + obp_child_handler, /* int (*no_child)(int node); */ + obp_proplen_handler, /* int (*no_proplen)(int node, char *name); */ + obp_getprop_handler, /* int (*no_getprop)(int node,char *name,char *val); */ + obp_setprop_handler, /* int (*no_setprop)(int node, char *name, + char *val, int len); */ + obp_nextprop_handler /* char * (*no_nextprop)(int node, char *name); */ +}; + +int obp_nbgetchar(void) +{ + return getchar(); +} + +int obp_nbputchar(int ch) +{ + putchar(ch); + + return 0; +} + +void obp_putstr(char *str, int len) +{ + PUSH(pointer2cell(str)); + PUSH(len); + fword("type"); +} + +void obp_printf(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + printk(fmt, ap); + va_end(ap); +} + +void obp_reboot(char *str) +{ + printk("rebooting (%s)\n", str); + *reset_reg = 1; + printk("reboot failed\n"); + for (;;) {} +} + +void obp_abort(void) +{ + printk("abort, power off\n"); + *power_reg = 1; + printk("power off failed\n"); + for (;;) {} +} + +void obp_halt(void) +{ + printk("halt, power off\n"); + *power_reg = 1; + printk("power off failed\n"); + for (;;) {} +} + +int obp_devopen(char *str) +{ + int ret; + + push_str(str); + fword("open-dev"); + ret = POP(); + DPRINTF("obp_devopen(%s) = 0x%x\n", str, ret); + + return ret; +} + +int obp_devclose(int dev_desc) +{ + int ret = 1; + + PUSH(dev_desc); + fword("close-dev"); + + DPRINTF("obp_devclose(0x%x) = %d\n", dev_desc, ret); + + return ret; +} + +int obp_rdblkdev(int dev_desc, int num_blks, int offset, char *buf) +{ + int ret, hi, lo, bs; + + bs = 512; + hi = ((uint64_t)offset * bs) >> 32; + lo = ((uint64_t)offset * bs) & 0xffffffff; + + ret = obp_devseek(dev_desc, hi, lo); + + ret = obp_devread(dev_desc, buf, num_blks * bs) / bs; + + DPRINTF("obp_rdblkdev(fd 0x%x, num_blks %d, offset %d (hi %d lo %d), buf 0x%x) = %d\n", dev_desc, num_blks, offset, hi, lo, (int)buf, ret); + + return ret; +} + +int obp_devread(int dev_desc, char *buf, int nbytes) +{ + int ret; + + PUSH((int)buf); + PUSH(nbytes); + push_str("read"); + PUSH(dev_desc); + fword("$call-method"); + ret = POP(); + + DPRINTF("obp_devread(fd 0x%x, buf 0x%x, nbytes %d) = %d\n", dev_desc, (int)buf, nbytes, ret); + + return ret; +} + +int obp_devwrite(int dev_desc, char *buf, int nbytes) +{ +#ifdef CONFIG_DEBUG_OBP_DEVWRITE /* disabled, makes too much noise */ + int ret; +#endif + + PUSH((int)buf); + PUSH(nbytes); + push_str("write"); + PUSH(dev_desc); + fword("$call-method"); +#ifdef CONFIG_DEBUG_OBP_DEVWRITE + ret = POP(); + DPRINTF("obp_devwrite(fd 0x%x, buf %s, nbytes %d) = %d\n", dev_desc, buf, nbytes, ret); +#else + POP(); +#endif + + return nbytes; +} + +int obp_devseek(int dev_desc, int hi, int lo) +{ + int ret; + + PUSH(lo); + PUSH(hi); + push_str("seek"); + PUSH(dev_desc); + fword("$call-method"); + ret = POP(); + + DPRINTF("obp_devseek(fd 0x%x, hi %d, lo %d) = %d\n", dev_desc, hi, lo, ret); + + return ret; +} + +int obp_inst2pkg(int dev_desc) +{ + int ret; + + PUSH(dev_desc); + fword("ihandle>non-interposed-phandle"); + ret = POP(); + + DPRINTF("obp_inst2pkg(fd 0x%x) = 0x%x\n", dev_desc, ret); + + return ret; +} + +int obp_cpustart(__attribute__((unused))unsigned int whichcpu, + __attribute__((unused))int ctxtbl_ptr, + __attribute__((unused))int thiscontext, + __attribute__((unused))char *prog_counter) +{ + int cpu, found; + struct linux_prom_registers *smp_ctable = (void *)ctxtbl_ptr; + + DPRINTF("obp_cpustart: cpu %d, ctxptr 0x%x, ctx %d, pc 0x%x\n", whichcpu, + smp_ctable->phys_addr, thiscontext, (unsigned int)prog_counter); + + found = obp_getprop(whichcpu, "mid", (char *)&cpu); + if (found == -1) + return -1; + DPRINTF("cpu found, id %d -> cpu %d\n", whichcpu, cpu); + + return start_cpu((unsigned int)prog_counter, ((unsigned int)smp_ctable->phys_addr) >> 4, + thiscontext, cpu); +} + +int obp_cpustop(__attribute__((unused)) unsigned int whichcpu) +{ + DPRINTF("obp_cpustop: cpu %d\n", whichcpu); + + return 0; +} + +int obp_cpuidle(__attribute__((unused)) unsigned int whichcpu) +{ + DPRINTF("obp_cpuidle: cpu %d\n", whichcpu); + + return 0; +} + +int obp_cpuresume(__attribute__((unused)) unsigned int whichcpu) +{ + DPRINTF("obp_cpuresume: cpu %d\n", whichcpu); + + return 0; +} + +void obp_fortheval_v2(char *str, int arg0, int arg1, int arg2, int arg3, int arg4) +{ + int dstacktmp = 0; + + // It seems Solaris passes up to 5 arguments which should be pushed onto the Forth + // stack for execution. However the API doesn't provide for a way to specify the number + // of arguments actually being passed. Hence we preserve the state of the Forth stack + // before, push all the arguments, execute the Forth, then restore the stack to its + // previous state. This enables us to have a variable number of arguments and still + // preserve stack state between subsequent calls. + + // Preserve stack state + dstacktmp = dstackcnt; + + PUSH(arg4); + PUSH(arg3); + PUSH(arg2); + PUSH(arg1); + PUSH(arg0); + + DPRINTF("obp_fortheval_v2(%x %x %x %x %x %s)\n", arg4, arg3, arg2, arg1, arg0, str); + push_str(str); + fword("eval"); + + // Restore stack state + dstackcnt = dstacktmp; +} + +volatile uint32_t *obp_ticks; + +void * +init_openprom(void) +{ + /* Setup the openprom vector. Note that all functions should be invoked + via their handler (see call-romvec.S) which acts as a proxy to save + the globals and setup the stack correctly */ + + // Linux wants a R/W romvec table + romvec0.pv_magic_cookie = LINUX_OPPROM_MAGIC; + romvec0.pv_romvers = 3; + romvec0.pv_plugin_revision = 2; + romvec0.pv_printrev = 0x20019; + romvec0.pv_v0mem.v0_totphys = NULL; + romvec0.pv_v0mem.v0_prommap = NULL; + romvec0.pv_v0mem.v0_available = NULL; + romvec0.pv_nodeops = &nodeops0; + romvec0.pv_bootstr = (void *)doublewalk; + romvec0.pv_v0devops.v0_devopen = &obp_devopen_handler; + romvec0.pv_v0devops.v0_devclose = &obp_devclose_handler; + romvec0.pv_v0devops.v0_rdblkdev = &obp_rdblkdev_handler; + romvec0.pv_stdin = &obp_stdin; + romvec0.pv_stdout = &obp_stdout; + romvec0.pv_getchar = obp_nbgetchar_handler; + romvec0.pv_putchar = (void (*)(int))obp_nbputchar_handler; + romvec0.pv_nbgetchar = obp_nbgetchar_handler; + romvec0.pv_nbputchar = obp_nbputchar_handler; + romvec0.pv_putstr = obp_putstr_handler; + romvec0.pv_reboot = obp_reboot_handler; + romvec0.pv_printf = obp_printf_handler; + romvec0.pv_abort = obp_abort_handler; + + /* Point to the Forth obp-ticks variable and reset */ + fword("obp-ticks"); + obp_ticks = cell2pointer(POP()); + *obp_ticks = 0; + romvec0.pv_ticks = obp_ticks; + + romvec0.pv_halt = obp_halt_handler; + romvec0.pv_synchook = &sync_hook; + romvec0.pv_v0bootargs = &obp_argp; + romvec0.pv_fortheval.v2_eval = obp_fortheval_v2_handler; + romvec0.pv_v2devops.v2_inst2pkg = obp_inst2pkg_handler; + romvec0.pv_v2devops.v2_dumb_mem_alloc = obp_dumb_memalloc_handler; + romvec0.pv_v2devops.v2_dumb_mem_free = obp_dumb_memfree_handler; + romvec0.pv_v2devops.v2_dumb_mmap = obp_dumb_mmap_handler; + romvec0.pv_v2devops.v2_dumb_munmap = obp_dumb_munmap_handler; + romvec0.pv_v2devops.v2_dev_open = obp_devopen_handler; + romvec0.pv_v2devops.v2_dev_close = (void (*)(int))obp_devclose_handler; + romvec0.pv_v2devops.v2_dev_read = obp_devread_handler; + romvec0.pv_v2devops.v2_dev_write = obp_devwrite_handler; + romvec0.pv_v2devops.v2_dev_seek = obp_devseek_handler; + + romvec0.pv_v2bootargs.bootpath = &bootpath; + + romvec0.pv_v2bootargs.bootargs = &obp_arg.argv[1]; + + /* Point fd_stdin/fd_stdout to the Forth stdin/stdout variables */ + fword("stdin"); + romvec0.pv_v2bootargs.fd_stdin = cell2pointer(POP()); + fword("stdout"); + romvec0.pv_v2bootargs.fd_stdout = cell2pointer(POP()); + + romvec0.v3_memalloc = obp_memalloc_handler; + + romvec0.v3_cpustart = obp_cpustart_handler; + romvec0.v3_cpustop = obp_cpustop_handler; + romvec0.v3_cpuidle = obp_cpuidle_handler; + romvec0.v3_cpuresume = obp_cpuresume_handler; + + return &romvec0; +} diff --git a/qemu/roms/openbios/arch/sparc32/romvec.h b/qemu/roms/openbios/arch/sparc32/romvec.h new file mode 100644 index 000000000..4375f06f3 --- /dev/null +++ b/qemu/roms/openbios/arch/sparc32/romvec.h @@ -0,0 +1,79 @@ +/* + * romvec main C function and handler declarations + */ + +extern volatile uint32_t *obp_ticks; +void *init_openprom(void); + +int obp_devopen(char *str); +int obp_devopen_handler(char *str); +int obp_devclose(int dev_desc); +int obp_devclose_handler(int dev_desc); +int obp_rdblkdev(int dev_desc, int num_blks, int offset, char *buf); +int obp_rdblkdev_handler(int dev_desc, int num_blks, int offset, char *buf); +int obp_nbgetchar(void); +int obp_nbgetchar_handler(void); +int obp_nbputchar(int ch); +int obp_nbputchar_handler(int ch); +void obp_putstr(char *str, int len); +void obp_putstr_handler(char *str, int len); +void obp_printf(__const__ char *fmt, ...); +void obp_printf_handler(__const__ char *fmt, ...); +void obp_reboot(char *str); +void obp_reboot_handler(char *str); +void obp_abort(void); +void obp_abort_handler(void); +void obp_halt(void); +void obp_halt_handler(void); +void obp_fortheval_v2(char *str, int arg0, int arg1, int arg2, int arg3, int arg4); +void obp_fortheval_v2_handler(char *str, int arg0, int arg1, int arg2, int arg3, int arg4); +int obp_inst2pkg(int dev_desc); +int obp_inst2pkg_handler(int dev_desc); +char *obp_dumb_memalloc(char *va, unsigned int size); +char *obp_dumb_memalloc_handler(char *va, unsigned int size); +void obp_dumb_memfree(char *va, unsigned size); +void obp_dumb_memfree_handler(char *va, unsigned size); +char *obp_dumb_mmap(char *va, int which_io, unsigned int pa, unsigned int size); +char *obp_dumb_mmap_handler(char *va, int which_io, unsigned int pa, unsigned int size); +void obp_dumb_munmap(__attribute__((unused)) char *va, __attribute__((unused)) unsigned int size); +void obp_dumb_munmap_handler(__attribute__((unused)) char *va, __attribute__((unused)) unsigned int size); +int obp_devread(int dev_desc, char *buf, int nbytes); +int obp_devread_handler(int dev_desc, char *buf, int nbytes); +int obp_devwrite(int dev_desc, char *buf, int nbytes); +int obp_devwrite_handler(int dev_desc, char *buf, int nbytes); +int obp_devseek(int dev_desc, int hi, int lo); +int obp_devseek_handler(int dev_desc, int hi, int lo); +int obp_cpustart(__attribute__((unused))unsigned int whichcpu, + __attribute__((unused))int ctxtbl_ptr, + __attribute__((unused))int thiscontext, + __attribute__((unused))char *prog_counter); +int obp_cpustart_handler(__attribute__((unused))unsigned int whichcpu, + __attribute__((unused))int ctxtbl_ptr, + __attribute__((unused))int thiscontext, + __attribute__((unused))char *prog_counter); +int obp_cpustop(__attribute__((unused)) unsigned int whichcpu); +int obp_cpustop_handler(__attribute__((unused)) unsigned int whichcpu); +int obp_cpuidle(__attribute__((unused)) unsigned int whichcpu); +int obp_cpuidle_handler(__attribute__((unused)) unsigned int whichcpu); +int obp_cpuresume(__attribute__((unused)) unsigned int whichcpu); +int obp_cpuresume_handler(__attribute__((unused)) unsigned int whichcpu); +int obp_nextnode(int node); +int obp_nextnode_handler(int node); +int obp_child(int node); +int obp_child_handler(int node); +int obp_proplen(int node, const char *name); +int obp_proplen_handler(int node, const char *name); +int obp_getprop(int node, const char *name, char *value); +int obp_getprop_handler(int node, const char *name, char *value); +int obp_setprop(__attribute__((unused)) int node, + __attribute__((unused)) const char *name, + __attribute__((unused)) char *value, + __attribute__((unused)) int len); +int obp_setprop_handler(__attribute__((unused)) int node, + __attribute__((unused)) const char *name, + __attribute__((unused)) char *value, + __attribute__((unused)) int len); +const char *obp_nextprop(int node, const char *name); +const char *obp_nextprop_handler(int node, const char *name); +char *obp_memalloc(char *va, unsigned int size, unsigned int align); +char *obp_memalloc_handler(char *va, unsigned int size, unsigned int align); diff --git a/qemu/roms/openbios/arch/sparc32/switch.S b/qemu/roms/openbios/arch/sparc32/switch.S new file mode 100644 index 000000000..d5b1b659d --- /dev/null +++ b/qemu/roms/openbios/arch/sparc32/switch.S @@ -0,0 +1,154 @@ +#define __ASSEMBLY +#include "psr.h" +#include "asm/asi.h" +#define ASI_BP ASI_M_BYPASS +#define REGWIN_SZ 0x40 + + .globl __switch_context, __switch_context_nosave, __exit_context, halt + + .text + .align 4 + +#define STACKFRAME_SZ 0x60 + +/* These are just handy. */ +#define _SV save %sp, -STACKFRAME_SZ, %sp +#define _RS restore + +#define FLUSH_ALL_KERNEL_WINDOWS \ + _SV; _SV; _SV; _SV; _SV; _SV; _SV; \ + _RS; _RS; _RS; _RS; _RS; _RS; _RS; + +/* + * Switch execution context + * This saves registers in the stack, then + * switches the stack, and restores everything from the new stack. + * This function takes no argument. New stack pointer is + * taken from global variable __context, and old stack pointer + * is also saved to __context. This way we can just jump to + * this routine to get back to the original context. + */ + +__switch_context: + FLUSH_ALL_KERNEL_WINDOWS + /* Save everything in stack */ + st %fp, [%fp + 120 -144] + add %fp, -144, %fp + st %g1, [%fp + 4] + st %g2, [%fp + 8] + st %g3, [%fp + 12] + st %g4, [%fp + 16] + st %g5, [%fp + 20] + st %g6, [%fp + 24] + st %g7, [%fp + 28] + + st %o0, [%fp + 32] + st %o1, [%fp + 36] + st %o2, [%fp + 40] + st %o3, [%fp + 44] + st %o4, [%fp + 48] + st %o5, [%fp + 52] + st %sp, [%fp + 56] + st %o7, [%fp + 60] + + st %l0, [%fp + 64] + st %l1, [%fp + 68] + st %l2, [%fp + 72] + st %l3, [%fp + 76] + st %l4, [%fp + 80] + st %l5, [%fp + 84] + st %l6, [%fp + 88] + st %l7, [%fp + 92] + + st %i0, [%fp + 96] + st %i1, [%fp + 100] + st %i2, [%fp + 104] + st %i3, [%fp + 108] + st %i4, [%fp + 112] + st %i5, [%fp + 116] + st %i7, [%fp + 124] + + /* ctx->return_address: Return to caller */ + st %o7, [%fp + 128] + + /* Interrupts are not allowed... */ + + /* Turn on Supervisor, EnableFloating, and all the PIL bits. + * Also puts us in register window zero with traps off. + */ +#if 0 + set (PSR_PS | PSR_S | PSR_PIL | PSR_EF), %g2 + wr %g2, 0x0, %psr +#endif + set __context, %g1 + /* Swap ctx pointer with %fp and jump*/ + ba __set_context + swap [%g1], %fp +__switch_context_nosave: + set __context, %g1 + /* load %fp from ctx pointer */ + ld [%g1], %fp +__set_context: + /* Load all registers */ + /* offset 0: %g0, no need to load */ + ld [%fp + 4], %g1 + ld [%fp + 8], %g2 + ld [%fp + 12], %g3 + ld [%fp + 16], %g4 + ld [%fp + 20], %g5 + ld [%fp + 24], %g6 + ld [%fp + 28], %g7 + + /* offset 32: %o0, loaded from ctx->param */ + ld [%fp + 36], %o1 + ld [%fp + 40], %o2 + ld [%fp + 44], %o3 + ld [%fp + 48], %o4 + ld [%fp + 52], %o5 + ld [%fp + 56], %sp + /* offset 60: %o7, loaded from ctx->return_addr */ + + ld [%fp + 64], %l0 + ld [%fp + 68], %l1 + ld [%fp + 72], %l2 + ld [%fp + 76], %l3 + ld [%fp + 80], %l4 + ld [%fp + 84], %l5 + ld [%fp + 88], %l6 + ld [%fp + 92], %l7 + + ld [%fp + 96], %i0 + ld [%fp + 100], %i1 + ld [%fp + 104], %i2 + ld [%fp + 108], %i3 + ld [%fp + 112], %i4 + ld [%fp + 116], %i5 + ld [%fp + 124], %i7 + + /* ctx->return_addr */ + ld [%fp + 136], %o7 + + /* ctx->param */ + ld [%fp + 140], %o0 + + /* ctx->pc, save %g1 to %y and load to %g1 */ + mov %g1, %y + ld [%fp + 128], %g1 + /* %fp last */ + ld [%fp + 120], %fp + /* Finally, get the new %pc from %g1 and restore %g1*/ + jmp %g1 + mov %y, %g1 + + FLUSH_ALL_KERNEL_WINDOWS +__exit_context: + /* Get back to the original context */ + call __switch_context + nop + + /* We get here if the other context attempt to switch to this + * dead context. This should not happen. */ + +halt: + b halt + nop diff --git a/qemu/roms/openbios/arch/sparc32/sys_info.c b/qemu/roms/openbios/arch/sparc32/sys_info.c new file mode 100644 index 000000000..719537d47 --- /dev/null +++ b/qemu/roms/openbios/arch/sparc32/sys_info.c @@ -0,0 +1,58 @@ +#include "config.h" +#include "kernel/kernel.h" +#include "arch/common/elf_boot.h" +#include "libopenbios/sys_info.h" +#include "context.h" +#include "boot.h" + +#define printf printk +#ifdef CONFIG_DEBUG_BOOT +#define debug printk +#else +#define debug(x...) +#endif + +unsigned int qemu_mem_size; + +void collect_multiboot_info(struct sys_info *); + +void collect_sys_info(struct sys_info *info) +{ + int i; + unsigned long long total = 0; + struct memrange *mmap; + + /* Pick up paramters given by bootloader to us */ + //info->boot_type = boot_ctx->eax; + //info->boot_data = boot_ctx->ebx; + info->boot_arg = boot_ctx->param[0]; + //debug("boot eax = %#lx\n", info->boot_type); + //debug("boot ebx = %#lx\n", info->boot_data); + info->boot_type = ELF_BHDR_MAGIC; + info->boot_data = virt_to_phys(&elf_image_notes); + debug("boot arg = %#lx\n", info->boot_arg); + + collect_elfboot_info(info); +#ifdef CONFIG_LINUXBIOS + collect_linuxbios_info(info); +#endif +#ifdef CONFIG_IMAGE_ELF_MULTIBOOT + collect_multiboot_info(info); +#endif + + if (!info->memrange) { + info->n_memranges = 1; + info->memrange = malloc(1 * sizeof(struct memrange)); + info->memrange[0].base = 0; + info->memrange[0].size = qemu_mem_size; + } + + debug("\n"); + mmap=info->memrange; + for (i = 0; i < info->n_memranges; i++) { + debug("%08lx-", (long)mmap[i].base); + debug("%08lx\n", (long)mmap[i].base + (long)mmap[i].size); + total += mmap[i].size; + } + debug("RAM %ld MB\n", (long)total >> 20); +} diff --git a/qemu/roms/openbios/arch/sparc32/tree.fs b/qemu/roms/openbios/arch/sparc32/tree.fs new file mode 100644 index 000000000..c82bb1718 --- /dev/null +++ b/qemu/roms/openbios/arch/sparc32/tree.fs @@ -0,0 +1,114 @@ +include config.fs + +" /" find-device + 2 encode-int " #address-cells" property + 1 encode-int " #size-cells" property + + " sun4m" encode-string " compatible" property + h# 0a21fe80 encode-int " clock-frequency" property + + : encode-unit encode-unit-sbus ; + : decode-unit decode-unit-sbus ; + +new-device + " memory" device-name + external + : open true ; + : close ; + \ claim ( phys size align -- base ) + \ release ( phys size -- ) +finish-device + +new-device + " virtual-memory" device-name + external + : open true ; + : close ; + \ claim ( phys size align -- base ) + \ release ( phys size -- ) +finish-device + +new-device + " iommu" device-name + 2 encode-int " #address-cells" property + 1 encode-int " #size-cells" property + h# 1000 encode-int " page-size" property + 0 encode-int " cache-coherence?" property + external + : open ( cr ." opening iommu" cr) true ; + : close ; + : encode-unit encode-unit-sbus ; + : decode-unit decode-unit-sbus ; +finish-device + +" /iommu" find-device +new-device + " sbus" device-name + " hierarchical" device-type + 2 encode-int " #address-cells" property + 1 encode-int " #size-cells" property + h# 01443fd0 encode-int " clock-frequency" property + h# 1c encode-int " slot-address-bits" property + h# 3f encode-int " burst-sizes" property + external + : open ( cr ." opening SBus" cr) true ; + : close ; + : encode-unit encode-unit-sbus ; + : decode-unit decode-unit-sbus ; + : map-in map-in-sbus ; + : map-out map-out-sbus ; +finish-device + +[IFDEF] CONFIG_BPP +" /iommu/sbus" find-device +new-device + " SUNW,bpp" device-name + h# 4 encode-int h# 0c800000 encode-int encode+ h# 0000001c encode-int encode+ " reg" property + h# 33 encode-int 0 encode-int encode+ " intr" property +finish-device +[THEN] + +" /iommu/sbus" find-device +new-device + " espdma" device-name + external + : encode-unit encode-unit-sbus ; + : decode-unit decode-unit-sbus ; +finish-device + +" /iommu/sbus" find-device +new-device + " ledma" device-name + h# 3f encode-int " burst-sizes" property + external + : encode-unit encode-unit-sbus ; + : decode-unit decode-unit-sbus ; +finish-device + +" /iommu/sbus/ledma" find-device +new-device + " le" device-name + " network" device-type + h# 7 encode-int " busmaster-regval" property + h# 26 encode-int 0 encode-int encode+ " intr" property +finish-device + +\ obio (on-board IO) +" /" find-device +new-device + " obio" device-name + " hierarchical" device-type + 2 encode-int " #address-cells" property + 1 encode-int " #size-cells" property + external + : open ( cr ." opening obio" cr) true ; + : close ; + : encode-unit encode-unit-sbus ; + : decode-unit decode-unit-sbus ; +finish-device + +" /options" find-device + " disk" encode-string " boot-from" property + +" /openprom" find-device + 0 0 " aligned-allocator" property diff --git a/qemu/roms/openbios/arch/sparc32/udiv.S b/qemu/roms/openbios/arch/sparc32/udiv.S new file mode 100644 index 000000000..327534187 --- /dev/null +++ b/qemu/roms/openbios/arch/sparc32/udiv.S @@ -0,0 +1,357 @@ +/* $Id: udiv.S,v 1.4 1996/09/30 02:22:38 davem Exp $ + * udiv.S: This routine was taken from glibc-1.09 and is covered + * by the GNU Library General Public License Version 2. + */ + + +/* This file is generated from divrem.m4; DO NOT EDIT! */ +/* + * Division and remainder, from Appendix E of the Sparc Version 8 + * Architecture Manual, with fixes from Gordon Irlam. + */ + +/* + * Input: dividend and divisor in %o0 and %o1 respectively. + * + * m4 parameters: + * .udiv name of function to generate + * div div=div => %o0 / %o1; div=rem => %o0 % %o1 + * false false=true => signed; false=false => unsigned + * + * Algorithm parameters: + * N how many bits per iteration we try to get (4) + * WORDSIZE total number of bits (32) + * + * Derived constants: + * TOPBITS number of bits in the top decade of a number + * + * Important variables: + * Q the partial quotient under development (initially 0) + * R the remainder so far, initially the dividend + * ITER number of main division loop iterations required; + * equal to ceil(log2(quotient) / N). Note that this + * is the log base (2^N) of the quotient. + * V the current comparand, initially divisor*2^(ITER*N-1) + * + * Cost: + * Current estimate for non-large dividend is + * ceil(log2(quotient) / N) * (10 + 7N/2) + C + * A large dividend is one greater than 2^(31-TOPBITS) and takes a + * different path, as the upper bits of the quotient must be developed + * one bit at a time. + */ + + + .globl .udiv + .globl _Udiv +.udiv: +_Udiv: /* needed for export */ + + ! Ready to divide. Compute size of quotient; scale comparand. + orcc %o1, %g0, %o5 + bne 1f + mov %o0, %o3 + + ! Divide by zero trap. If it returns, return 0 (about as + ! wrong as possible, but that is what SunOS does...). + ta 0x2 + retl + clr %o0 + +1: + cmp %o3, %o5 ! if %o1 exceeds %o0, done + blu Lgot_result ! (and algorithm fails otherwise) + clr %o2 + + sethi %hi(1 << (32 - 4 - 1)), %g1 + + cmp %o3, %g1 + blu Lnot_really_big + clr %o4 + + ! Here the dividend is >= 2**(31-N) or so. We must be careful here, + ! as our usual N-at-a-shot divide step will cause overflow and havoc. + ! The number of bits in the result here is N*ITER+SC, where SC <= N. + ! Compute ITER in an unorthodox manner: know we need to shift V into + ! the top decade: so do not even bother to compare to R. + 1: + cmp %o5, %g1 + bgeu 3f + mov 1, %g7 + + sll %o5, 4, %o5 + + b 1b + add %o4, 1, %o4 + + ! Now compute %g7. + 2: + addcc %o5, %o5, %o5 + bcc Lnot_too_big + add %g7, 1, %g7 + + ! We get here if the %o1 overflowed while shifting. + ! This means that %o3 has the high-order bit set. + ! Restore %o5 and subtract from %o3. + sll %g1, 4, %g1 ! high order bit + srl %o5, 1, %o5 ! rest of %o5 + add %o5, %g1, %o5 + + b Ldo_single_div + sub %g7, 1, %g7 + + Lnot_too_big: + 3: + cmp %o5, %o3 + blu 2b + nop + + be Ldo_single_div + nop + /* NB: these are commented out in the V8-Sparc manual as well */ + /* (I do not understand this) */ + ! %o5 > %o3: went too far: back up 1 step + ! srl %o5, 1, %o5 + ! dec %g7 + ! do single-bit divide steps + ! + ! We have to be careful here. We know that %o3 >= %o5, so we can do the + ! first divide step without thinking. BUT, the others are conditional, + ! and are only done if %o3 >= 0. Because both %o3 and %o5 may have the high- + ! order bit set in the first step, just falling into the regular + ! division loop will mess up the first time around. + ! So we unroll slightly... + Ldo_single_div: + subcc %g7, 1, %g7 + bl Lend_regular_divide + nop + + sub %o3, %o5, %o3 + mov 1, %o2 + + b Lend_single_divloop + nop + Lsingle_divloop: + sll %o2, 1, %o2 + bl 1f + srl %o5, 1, %o5 + ! %o3 >= 0 + sub %o3, %o5, %o3 + b 2f + add %o2, 1, %o2 + 1: ! %o3 < 0 + add %o3, %o5, %o3 + sub %o2, 1, %o2 + 2: + Lend_single_divloop: + subcc %g7, 1, %g7 + bge Lsingle_divloop + tst %o3 + + b,a Lend_regular_divide + +Lnot_really_big: +1: + sll %o5, 4, %o5 + + cmp %o5, %o3 + bleu 1b + addcc %o4, 1, %o4 + + be Lgot_result + sub %o4, 1, %o4 + + tst %o3 ! set up for initial iteration +Ldivloop: + sll %o2, 4, %o2 + ! depth 1, accumulated bits 0 + bl L.1.16 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 2, accumulated bits 1 + bl L.2.17 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 3, accumulated bits 3 + bl L.3.19 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 4, accumulated bits 7 + bl L.4.23 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (7*2+1), %o2 + +L.4.23: + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (7*2-1), %o2 + +L.3.19: + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 4, accumulated bits 5 + bl L.4.21 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (5*2+1), %o2 + +L.4.21: + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (5*2-1), %o2 + +L.2.17: + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 3, accumulated bits 1 + bl L.3.17 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 4, accumulated bits 3 + bl L.4.19 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (3*2+1), %o2 + +L.4.19: + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (3*2-1), %o2 + +L.3.17: + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 4, accumulated bits 1 + bl L.4.17 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (1*2+1), %o2 + +L.4.17: + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (1*2-1), %o2 + +L.1.16: + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 2, accumulated bits -1 + bl L.2.15 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 3, accumulated bits -1 + bl L.3.15 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 4, accumulated bits -1 + bl L.4.15 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (-1*2+1), %o2 + +L.4.15: + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (-1*2-1), %o2 + +L.3.15: + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 4, accumulated bits -3 + bl L.4.13 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (-3*2+1), %o2 + +L.4.13: + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (-3*2-1), %o2 + +L.2.15: + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 3, accumulated bits -3 + bl L.3.13 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 4, accumulated bits -5 + bl L.4.11 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (-5*2+1), %o2 + +L.4.11: + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (-5*2-1), %o2 + +L.3.13: + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 4, accumulated bits -7 + bl L.4.9 + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (-7*2+1), %o2 + +L.4.9: + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (-7*2-1), %o2 + + 9: +Lend_regular_divide: + subcc %o4, 1, %o4 + bge Ldivloop + tst %o3 + + bl,a Lgot_result + ! non-restoring fixup here (one instruction only!) + sub %o2, 1, %o2 + +Lgot_result: + + retl + mov %o2, %o0 + + .globl .udiv_patch +.udiv_patch: + wr %g0, 0x0, %y + nop + nop + retl + udiv %o0, %o1, %o0 + nop diff --git a/qemu/roms/openbios/arch/sparc32/vectors.S b/qemu/roms/openbios/arch/sparc32/vectors.S new file mode 100644 index 000000000..e812cecb9 --- /dev/null +++ b/qemu/roms/openbios/arch/sparc32/vectors.S @@ -0,0 +1,254 @@ +/* + * <vectors.S> + * + * Sparc V9 Trap Table(s) with SpitFire/Cheetah extensions. + * + * Copyright (C) 1996, 2001 David S. Miller (davem@caip.rutgers.edu) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License V2 + * as published by the Free Software Foundation + */ + +#define __ASSEMBLY +#include "psr.h" +#include "asm/asi.h" +#define SER_ADDR5 0x71100004 +#define SER_ADDR10 0xf1100004 + + .section ".text.vectors", "ax" + .align 4 /* Should be 16384, but alignment is handled by the ldscript */ +/* Sparc32 trap table */ + .globl trap_table, t_zero, t_wovf, t_wunf, __divide_error +trap_table: + +#define WINDOW_SPILL \ + rd %psr, %l0; rd %wim, %l3; b spill_window_entry; nop; + +#define WINDOW_FILL \ + rd %psr, %l0; rd %wim, %l3; b fill_window_entry; nop; + +#define TRAP_DFAULT(lvl) \ + rd %psr, %l0; rd %wim, %l3; b handle_dfault; mov lvl, %l7; + +#define BTRAP(lvl) ba bug; mov lvl, %g1; nop; nop; +#define BTRAPS(x) BTRAP(x) BTRAP(x+1) BTRAP(x+2) BTRAP(x+3) BTRAP(x+4) BTRAP(x+5) BTRAP(x+6) BTRAP(x+7) +#define TRAP_ENTRY_INTERRUPT(int_level) \ + sethi %hi(irq_entry ## int_level), %l7; \ + or %l7, %lo(irq_entry ## int_level), %l7; \ + jmp %l7; \ + nop + +t_zero: b entry; nop; nop; nop; + BTRAP(0x1) BTRAP(0x2) BTRAP(0x3) BTRAP(0x4) +t_wovf: WINDOW_SPILL /* Window Overflow */ +t_wunf: WINDOW_FILL /* Window Underflow */ + BTRAP(0x7) + BTRAP(0x8) + TRAP_DFAULT(0x9) + BTRAP(0xa) BTRAP(0xb) BTRAP(0xc) BTRAP(0xd) BTRAP(0xe) BTRAP(0xf) +#if 0 + BAD_TRAP(0x10) +t_irq1: TRAP_ENTRY_INTERRUPT(1) /* IRQ Software/SBUS Level 1 */ +t_irq2: TRAP_ENTRY_INTERRUPT(2) /* IRQ SBUS Level 2 */ +t_irq3: TRAP_ENTRY_INTERRUPT(3) /* IRQ SCSI/DMA/SBUS Level 3 */ +t_irq4: TRAP_ENTRY_INTERRUPT(4) /* IRQ Software Level 4 */ +t_irq5: TRAP_ENTRY_INTERRUPT(5) /* IRQ SBUS/Ethernet Level 5 */ +t_irq6: TRAP_ENTRY_INTERRUPT(6) /* IRQ Software Level 6 */ +t_irq7: TRAP_ENTRY_INTERRUPT(7) /* IRQ Video/SBUS Level 5 */ +t_irq8: TRAP_ENTRY_INTERRUPT(8) /* IRQ SBUS Level 6 */ +t_irq9: TRAP_ENTRY_INTERRUPT(9) /* IRQ SBUS Level 7 */ +t_irq10: TRAP_ENTRY_INTERRUPT(10) /* IRQ Timer #1 (one we use) */ +t_irq11: TRAP_ENTRY_INTERRUPT(11) /* IRQ Floppy Intr. */ +t_irq12: TRAP_ENTRY_INTERRUPT(12) /* IRQ Zilog serial chip */ +t_irq13: TRAP_ENTRY_INTERRUPT(13) /* IRQ Audio Intr. */ +t_irq14: TRAP_ENTRY_INTERRUPT(14) /* IRQ Timer #2 */ +t_nmi: BAD_TRAP(0x1f) /* Level 15 (NMI) */ +#else + BTRAPS(0x10) + BTRAP(0x18) BTRAP(0x19) +t_irq10: TRAP_ENTRY_INTERRUPT(10) /* IRQ Timer #1 (one we use) */ + BTRAP(0x1b) BTRAP(0x1c) BTRAP(0x1d) +t_irq14: TRAP_ENTRY_INTERRUPT(14) /* IRQ Timer #2 */ + BTRAP(0x1f) +#endif + BTRAPS(0x20) + BTRAP(0x28) + TRAP_DFAULT(0x29) + BTRAP(0x2a) BTRAP(0x2b) BTRAP(0x2c) BTRAP(0x2d) BTRAP(0x2e) BTRAP(0x2f) + BTRAPS(0x30) BTRAPS(0x38) + BTRAPS(0x40) BTRAPS(0x48) + BTRAPS(0x50) BTRAPS(0x58) + BTRAPS(0x60) BTRAPS(0x68) + BTRAPS(0x70) BTRAPS(0x78) + BTRAPS(0x80) BTRAPS(0x88) + BTRAPS(0x90) BTRAPS(0x98) + BTRAPS(0xa0) BTRAPS(0xa8) + BTRAPS(0xb0) BTRAPS(0xb8) + BTRAPS(0xc0) BTRAPS(0xc8) + BTRAPS(0xd0) BTRAPS(0xd8) + BTRAPS(0xe0) BTRAPS(0xe8) + BTRAPS(0xf0) BTRAPS(0xf8) + + .section ".text", "ax" + .align 4 +__divide_error: +bug: + /* Dump the exception and its context */ + ! Set up CPU state + rd %psr, %g2 + andn %g2, PSR_ET, %g2 + wr %g2, %psr + ! Disable mmu, re-enable boot mode + set _start, %g3 + set dump_exception, %g2 + sub %g2, %g3, %g3 + set 3 << 13, %g2 + jmp %g3 + sta %g2, [%g0] ASI_M_MMUREGS + +outstr: + /* void outstr (unsigned long port5, unsigned long port10, + * const unsigned char *str); + * Writes a string on an IO port. + */ +1: lduba [%o2] ASI_M_KERNELTXT, %o3 + cmp %o3, 0 + be 2f + nop + stba %o3, [%o0] ASI_M_BYPASS + stba %o3, [%o1] ASI_M_CTL + b 1b + inc %o2 +2: retl + nop + +outhex: + /* void outhex (unsigned long port5, unsigned long port10, + * uint32_t value); + * Dumps a 32 bits hex number on serial port + */ + mov %o2, %o4 + set 28, %o3 + srl %o4, %o3, %o2 +1: and %o2, 0xf, %o2 + cmp %o2, 9 + bgt 2f + nop + b 3f + add %o2, '0', %o2 +2: add %o2, 'a' - 10, %o2 +3: stba %o2, [%o0] ASI_M_BYPASS + stba %o2, [%o1] ASI_M_CTL + subcc %o3, 4, %o3 + bge 1b + srl %o4, %o3, %o2 + retl + nop + + /* void dump_exception (); + * + * Dump a message when catching an exception + */ +dump_exception: + set SER_ADDR5 + 2, %o0 + set SER_ADDR10 + 2, %o1 + set (_BUG_message_0), %o2 + call outstr + nop + + call outhex + mov %g1, %o2 + + set (_BUG_message_1), %o2 + call outstr + nop + + call outhex + mov %l1, %o2 + + set (_BUG_message_2), %o2 + call outstr + nop + + call outhex + mov %l2, %o2 + + set (_BUG_message_3), %o2 + call outstr + nop +_forever: + /* Loop forever */ + b _forever ; + nop + +irq_entry10: + sethi %hi(counter_regs), %l7 + ld [%l7 + %lo(counter_regs)], %l7 + sethi 0x10000, %l6 + ld [%l7 + %l6], %g0 + jmp %l1 + rett %l2 + +irq_entry14: + sethi %hi(counter_regs), %l7 + ld [%l7 + %lo(counter_regs)], %l7 + ld [%l7], %g0 + sethi %hi(obp_ticks), %l7 + ld [%l7 + %lo(obp_ticks)], %l7 + ld [%l7], %l6 + add %l6, 10, %l6 + st %l6, [%l7] + jmp %l1 + rett %l2 + +/* Register window handlers */ +#include "wof.S" +#include "wuf.S" + +/* Data fault handler */ + .data + .align 4 + .global ignore_dfault + +ignore_dfault: + .word 0 + + .text + .align 4 + +handle_dfault: + /* If ignore_dfault is 0, fall through to normal exception handler */ + sethi %hi(ignore_dfault), %l4 + ld [%l4 + %lo(ignore_dfault)], %l4 + tst %l4 + bz,a bug + mov %l7, %g1 + + /* Otherwise skip the faulting instruction and return */ + jmp %l2 + rett %l2 + 4 + + + .section .rodata +_BUG_message_0: + .string "Unhandled Exception 0x" +_BUG_message_1: + .string "\r\nPC = 0x" +_BUG_message_2: + .string " NPC = 0x" +_BUG_message_3: + .string "\r\nStopping execution\r\n" diff --git a/qemu/roms/openbios/arch/sparc32/wof.S b/qemu/roms/openbios/arch/sparc32/wof.S new file mode 100644 index 000000000..8d6bb7314 --- /dev/null +++ b/qemu/roms/openbios/arch/sparc32/wof.S @@ -0,0 +1,133 @@ +/* + * Proll takes this from Sparclinux kernel, ruthlessly truncated + * because we have no user windows. + * + * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License V2 + * as published by the Free Software Foundation + */ + +// #include <asm/winmacro.h> +// #include <asm/asmmacro.h> + +/* Reg_window offsets */ +#define RW_L0 0x00 +#define RW_L1 0x04 +#define RW_L2 0x08 +#define RW_L3 0x0c +#define RW_L4 0x10 +#define RW_L5 0x14 +#define RW_L6 0x18 +#define RW_L7 0x1c +#define RW_I0 0x20 +#define RW_I1 0x24 +#define RW_I2 0x28 +#define RW_I3 0x2c +#define RW_I4 0x30 +#define RW_I5 0x34 +#define RW_I6 0x38 +#define RW_I7 0x3c + +/* Store the register window onto the 8-byte aligned area starting + * at %reg. It might be %sp, it might not, we don't care. + */ +#define STORE_WINDOW(reg) \ + std %l0, [%reg + RW_L0]; \ + std %l2, [%reg + RW_L2]; \ + std %l4, [%reg + RW_L4]; \ + std %l6, [%reg + RW_L6]; \ + std %i0, [%reg + RW_I0]; \ + std %i2, [%reg + RW_I2]; \ + std %i4, [%reg + RW_I4]; \ + std %i6, [%reg + RW_I6]; + +/* We define macro's for registers which have a fixed + * meaning throughout this entire routine. The 'T' in + * the comments mean that the register can only be + * accessed when in the 'trap' window, 'G' means + * accessible in any window. Do not change these registers + * after they have been set, until you are ready to return + * from the trap. + */ +#define t_psr l0 /* %psr at trap time T */ +#define t_pc l1 /* PC for trap return T */ +#define t_npc l2 /* NPC for trap return T */ +#define t_wim l3 /* %wim at trap time T */ +#define saved_g5 l5 /* Global save register T */ +#define saved_g6 l6 /* Global save register T */ + +/* Now registers whose values can change within the handler. */ +#define twin_tmp l4 /* Temp reg, only usable in trap window T */ +#define glob_tmp g5 /* Global temporary reg, usable anywhere G */ + + .text + .align 4 + + /* BEGINNING OF PATCH INSTRUCTIONS */ + /* On a 7-window Sparc the boot code patches spnwin_* + * instructions with the following ones. + */ + .globl spnwin_patch1_7win, spnwin_patch2_7win, spnwin_patch3_7win +spnwin_patch1_7win: sll %t_wim, 6, %glob_tmp +spnwin_patch2_7win: and %glob_tmp, 0x7f, %glob_tmp +spnwin_patch3_7win: and %twin_tmp, 0x7f, %twin_tmp + /* END OF PATCH INSTRUCTIONS */ + + /* The trap entry point has done the following: + * + * rd %psr, %l0 + * rd %wim, %l3 + * b spill_window_entry + * nop + */ + + .globl spill_window_entry + .globl spnwin_patch1, spnwin_patch2 +spill_window_entry: + /* LOCATION: Trap Window */ + + mov %g5, %saved_g5 ! save away global temp register + mov %g6, %saved_g6 ! save away 'current' ptr register + + /* Compute what the new %wim will be if we save the + * window properly in this trap handler. + * + * newwim = ((%wim>>1) | (%wim<<(nwindows - 1))); + */ + srl %t_wim, 0x1, %twin_tmp +spnwin_patch1: sll %t_wim, 7, %glob_tmp + or %glob_tmp, %twin_tmp, %glob_tmp +spnwin_patch2: and %glob_tmp, 0xff, %glob_tmp + + /* Save into the window which must be saved and do it. + */ + save %g0, %g0, %g0 ! save into the window to stash away + wr %glob_tmp, 0x0, %wim ! set new %wim, this is safe now + + /* LOCATION: Window to be saved */ + + STORE_WINDOW(sp) ! stash the window + restore %g0, %g0, %g0 ! go back into trap window + + /* LOCATION: Trap window */ + mov %saved_g5, %g5 ! restore %glob_tmp + mov %saved_g6, %g6 ! restore %curptr + wr %t_psr, 0x0, %psr ! restore condition codes in %psr + nop; nop; nop ! waste some time + jmp %t_pc ! Return from trap + rett %t_npc ! we are done diff --git a/qemu/roms/openbios/arch/sparc32/wuf.S b/qemu/roms/openbios/arch/sparc32/wuf.S new file mode 100644 index 000000000..853fc7322 --- /dev/null +++ b/qemu/roms/openbios/arch/sparc32/wuf.S @@ -0,0 +1,154 @@ +/* + * Window fill (underflow) trap, based on code from Sparclinux. + * + * Copyright (C) 1995 David S. Miller + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +// #include <psr.h> +// #include <asi.h> + +/* Reg_window offsets */ +#define RW_L0 0x00 +#define RW_L1 0x04 +#define RW_L2 0x08 +#define RW_L3 0x0c +#define RW_L4 0x10 +#define RW_L5 0x14 +#define RW_L6 0x18 +#define RW_L7 0x1c +#define RW_I0 0x20 +#define RW_I1 0x24 +#define RW_I2 0x28 +#define RW_I3 0x2c +#define RW_I4 0x30 +#define RW_I5 0x34 +#define RW_I6 0x38 +#define RW_I7 0x3c + +/* Load a register window from the area beginning at %reg. */ +#define LOAD_WINDOW(reg) \ + ldd [%reg + RW_L0], %l0; \ + ldd [%reg + RW_L2], %l2; \ + ldd [%reg + RW_L4], %l4; \ + ldd [%reg + RW_L6], %l6; \ + ldd [%reg + RW_I0], %i0; \ + ldd [%reg + RW_I2], %i2; \ + ldd [%reg + RW_I4], %i4; \ + ldd [%reg + RW_I6], %i6; + +#define WRITE_PAUSE nop; nop; nop; /* Have to do this after %wim/%psr chg */ + +/* Just like the overflow handler we define macros for registers + * with fixed meanings in this routine. + */ +#define t_psr l0 +#define t_pc l1 +#define t_npc l2 +#define t_wim l3 +/* Don't touch the above registers or else you die horribly... */ + +/* Now macros for the available scratch registers in this routine. */ +#define twin_tmp1 l4 +#define twin_tmp2 l5 + + .text + .align 4 + + /* The trap entry point has executed the following: + * + * rd %psr, %l0 + * rd %wim, %l3 + * b fill_window_entry + * andcc %l0, PSR_PS, %g0 + */ + + /* To get an idea of what has just happened to cause this + * trap take a look at this diagram: + * + * 1 2 3 4 <-- Window number + * ---------- + * T O W I <-- Symbolic name + * + * O == the window that execution was in when + * the restore was attempted + * + * T == the trap itself has save'd us into this + * window + * + * W == this window is the one which is now invalid + * and must be made valid plus loaded from the + * stack + * + * I == this window will be the invalid one when we + * are done and return from trap if successful + */ + + /* BEGINNING OF PATCH INSTRUCTIONS */ + + /* On 7-window Sparc the boot code patches fnwin_patch1 + * with the following instruction. + */ + .globl fnwin_patch1_7win, fnwin_patch2_7win +fnwin_patch1_7win: srl %t_wim, 6, %twin_tmp2 +fnwin_patch2_7win: and %twin_tmp1, 0x7f, %twin_tmp1 + /* END OF PATCH INSTRUCTIONS */ + + + .globl fill_window_entry, fnwin_patch1, fnwin_patch2 +fill_window_entry: + /* LOCATION: Window 'T' */ + + /* Compute what the new %wim is going to be if we retrieve + * the proper window off of the stack. + */ + sll %t_wim, 1, %twin_tmp1 +fnwin_patch1: srl %t_wim, 7, %twin_tmp2 + or %twin_tmp1, %twin_tmp2, %twin_tmp1 +fnwin_patch2: and %twin_tmp1, 0xff, %twin_tmp1 + + wr %twin_tmp1, 0x0, %wim /* Make window 'I' invalid */ + + restore %g0, %g0, %g0 /* Restore to window 'O' */ + + /* Trapped from kernel, we trust that the kernel does not + * 'over restore' sorta speak and just grab the window + * from the stack and return. Easy enough. + */ + /* LOCATION: Window 'O' */ + + restore %g0, %g0, %g0 + WRITE_PAUSE + + /* LOCATION: Window 'W' */ + + LOAD_WINDOW(sp) /* Load it up */ + + /* Spin the wheel... */ + save %g0, %g0, %g0 + save %g0, %g0, %g0 + /* I'd like to buy a vowel please... */ + + /* LOCATION: Window 'T' */ + + /* Now preserve the condition codes in %psr, pause, and + * return from trap. This is the simplest case of all. + */ + wr %t_psr, 0x0, %psr + WRITE_PAUSE + + jmp %t_pc + rett %t_npc diff --git a/qemu/roms/openbios/arch/sparc64/boot.c b/qemu/roms/openbios/arch/sparc64/boot.c new file mode 100644 index 000000000..5107be6ca --- /dev/null +++ b/qemu/roms/openbios/arch/sparc64/boot.c @@ -0,0 +1,130 @@ +/* + * + */ +#undef BOOTSTRAP +#include "config.h" +#include "libopenbios/bindings.h" +#include "arch/common/nvram.h" +#include "libc/diskio.h" +#include "libc/vsprintf.h" +#include "libopenbios/sys_info.h" +#include "boot.h" + +uint64_t kernel_image; +uint64_t kernel_size; +uint64_t qemu_cmdline; +uint64_t cmdline_size; +char boot_device; + +extern int sparc64_of_client_interface( int *params ); + + +void go(void) +{ + ucell address, type, size; + int image_retval = 0; + + /* Get the entry point and the type (see forth/debugging/client.fs) */ + feval("saved-program-state >sps.entry @"); + address = POP(); + feval("saved-program-state >sps.file-type @"); + type = POP(); + feval("saved-program-state >sps.file-size @"); + size = POP(); + + printk("\nJumping to entry point " FMT_ucellx " for type " FMT_ucellx "...\n", address, type); + + switch (type) { + case 0x0: + /* Start ELF boot image */ + image_retval = start_elf(address, (uint64_t)&elf_boot_notes); + break; + + case 0x1: + /* Start ELF image */ + image_retval = start_client_image(address, (uint64_t)&sparc64_of_client_interface); + break; + + case 0x5: + /* Start a.out image */ + image_retval = start_client_image(address, (uint64_t)&sparc64_of_client_interface); + break; + + case 0x10: + /* Start Fcode image */ + printk("Evaluating FCode...\n"); + PUSH(address); + PUSH(1); + fword("byte-load"); + image_retval = 0; + break; + + case 0x11: + /* Start Forth image */ + PUSH(address); + PUSH(size); + fword("eval2"); + image_retval = 0; + break; + } + + printk("Image returned with return value %#x\n", image_retval); +} + +/* ( path len -- path len ) */ + +void boot(void) +{ + char *path, *param; + + /* Copy the incoming path */ + fword("2dup"); + path = pop_fstr_copy(); + + /* Boot preloaded kernel */ + if (kernel_size) { + void (*entry)(unsigned long p1, unsigned long p2, unsigned long p3, + unsigned long p4, unsigned long p5); + + printk("[sparc64] Kernel already loaded\n"); + entry = (void *) (unsigned long)kernel_image; + entry(0, 0, 0, 0, (unsigned long)&sparc64_of_client_interface); + } + + /* Invoke Linux directly -- probably not supported */ + if(!path) { + /* No path specified, so grab defaults from /chosen */ + push_str("bootpath"); + push_str("/chosen"); + fword("(find-dev)"); + POP(); + fword("get-package-property"); + POP(); + /* Update our local copy of path as well as the one on the stack */ + fword("2dup"); + path = pop_fstr_copy(); + } + + if (path) { + param = strchr(path, ' '); + if(param) { + *param = '\0'; + param++; + } else if (cmdline_size) { + param = (char *)qemu_cmdline; + } else { + push_str("boot-args"); + push_str("/options"); + fword("(find-dev)"); + POP(); + fword("get-package-property"); + POP(); + param = pop_fstr_copy(); + } + + /* Invoke platform-specific Linux loader */ + linux_load(&sys_info, path, param); + + free(path); + } +} diff --git a/qemu/roms/openbios/arch/sparc64/boot.h b/qemu/roms/openbios/arch/sparc64/boot.h new file mode 100644 index 000000000..3ab05e0a3 --- /dev/null +++ b/qemu/roms/openbios/arch/sparc64/boot.h @@ -0,0 +1,35 @@ +/* tag: openbios loader prototypes for sparc64 + * + * Copyright (C) 2004 Stefan Reinauer + * + * See the file "COPYING" for further information about + * the copyright and warranty status of this work. + */ + +// linux_load.c +int linux_load(struct sys_info *info, const char *file, const char *cmdline); + +// context.c +extern struct context * volatile __context; +uint64_t start_elf(uint64_t entry_point, uint64_t param); +uint64_t start_client_image(uint64_t entry_point, uint64_t cif_handler); + +// boot.c +extern uint64_t kernel_image; +extern uint64_t kernel_size; +extern uint64_t qemu_cmdline; +extern uint64_t cmdline_size; +extern char boot_device; +extern void boot(void); +extern void go(void); + +// sys_info.c +extern uint64_t qemu_mem_size; +extern void collect_sys_info(struct sys_info *info); + +// console.c +void ob_su_init(uint64_t base, uint64_t offset, int intr); +void cls(void); + +// lib.c +void ob_mmu_init(const char *cpuname, uint64_t ram_size); diff --git a/qemu/roms/openbios/arch/sparc64/build.xml b/qemu/roms/openbios/arch/sparc64/build.xml new file mode 100644 index 000000000..3a1cd346a --- /dev/null +++ b/qemu/roms/openbios/arch/sparc64/build.xml @@ -0,0 +1,72 @@ +<build condition="SPARC64"> + + <dictionary name="openbios-sparc64" init="openbios"> + <object source="tree.fs" target="forth"/> + <object source="init.fs" target="forth"/> + <object source="QEMU,VGA.bin" target="fcode" condition="DRIVER_VGA"/> + </dictionary> + + <library name="sparc64" type="static" target="target"> + <object source="openbios.c"/> + <object source="console.c"/> + <object source="lib.c"/> + <object source="boot.c"/> + <object source="context.c"/> + <object source="switch.S"/> + <object source="linux_load.c"/> + <object source="sys_info.c"/> + <object source="ofmem_sparc64.c"/> + <object source="entry.S"/> + <object source="vectors.S"/> + <object source="call-client.S"/> + </library> + + <executable name="openbios-plain.elf" target="target" condition="IMAGE_ELF"> + <rule> + $(call quiet-command,$(LD) --warn-common -T $(SRCDIR)/arch/sparc64/ldscript -o $@.nostrip --whole-archive $^," LINK $(TARGET_DIR)$@") + $(call quiet-command,$(NM) $@.nostrip | sort > $(ODIR)/openbios-plain.syms," GEN $(TARGET_DIR)$@.syms") + $(call quiet-command,$(STRIP) $@.nostrip -o $@," STRIP $(TARGET_DIR)$@")</rule> + <object source="plainboot.c"/> + <external-object source="libsparc64.a"/> + <external-object source="libbootstrap.a"/> + <external-object source="libopenbios.a"/> + <external-object source="libpackages.a"/> + <external-object source="libdrivers.a"/> + <external-object source="libfs.a"/> + <external-object source="liblibc.a"/> + <external-object source="libgcc.a"/> + </executable> + + <!-- HACK ALERT --> + + <executable name="target/include/static-dict.h" target="target" condition="IMAGE_ELF_EMBEDDED"> + <rule><![CDATA[ + $(call quiet-command,$(ODIR)/forthstrap -x -D $@ -d $< </dev/null, " GEN $(TARGET_DIR)$@")]]></rule> + <external-object source="openbios-sparc64.dict"/> + </executable> + + <executable name="target/arch/sparc64/builtin.o" target="target" condition="IMAGE_ELF_EMBEDDED"> + <rule><![CDATA[ $(SRCDIR)/arch/sparc64/builtin.c $(ODIR)/target/include/static-dict.h + $(call quiet-command,$(CC) $$EXTRACFLAGS $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/arch/sparc64/builtin.c, " CC $(TARGET_DIR)$@")]]></rule> + </executable> + + <!-- END OF HACK ALERT --> + + <executable name="openbios-builtin.elf" target="target" condition="IMAGE_ELF_EMBEDDED"> + <!-- We use -N to reduce the file size by 1M --> + <rule> + $(call quiet-command,$(LD) --warn-common -N -T $(SRCDIR)/arch/sparc64/ldscript -o $@.nostrip --whole-archive $^," LINK $(TARGET_DIR)$@") + $(call quiet-command,$(NM) $@.nostrip | sort > $(ODIR)/openbios-builtin.syms," GEN $(TARGET_DIR)$@.syms") + $(call quiet-command,$(STRIP) $@.nostrip -o $@," STRIP $(TARGET_DIR)$@")</rule> + <external-object source="target/arch/sparc64/builtin.o"/> + <external-object source="libsparc64.a"/> + <external-object source="libbootstrap.a"/> + <external-object source="libopenbios.a"/> + <external-object source="libpackages.a"/> + <external-object source="libdrivers.a"/> + <external-object source="libfs.a"/> + <external-object source="liblibc.a"/> + <external-object source="libgcc.a"/> + </executable> + +</build> diff --git a/qemu/roms/openbios/arch/sparc64/builtin.c b/qemu/roms/openbios/arch/sparc64/builtin.c new file mode 100644 index 000000000..864da7971 --- /dev/null +++ b/qemu/roms/openbios/arch/sparc64/builtin.c @@ -0,0 +1,33 @@ +/* tag: openbios forth starter for builtin dictionary for sparc64 + * + * Copyright (C) 2003 Stefan Reinauer + * + * See the file "COPYING" for further information about + * the copyright and warranty status of this work. + */ + +#include "config.h" +#include "asm/types.h" +#include "libopenbios/sys_info.h" + +/* + * wrap an array around the hex'ed dictionary file + */ + +/* 512K for the dictionary */ +#define DICTIONARY_SIZE (512 * 1024 / sizeof(ucell)) +#define DICTIONARY_BASE ((ucell)((char *)&forth_dictionary)) + +static ucell forth_dictionary[DICTIONARY_SIZE] = { +#include "static-dict.h" +}; + +void collect_multiboot_info(struct sys_info *info); +void collect_multiboot_info(struct sys_info *info) +{ + info->dict_start=(unsigned long *)forth_dictionary; + info->dict_end = (unsigned long *)FORTH_DICTIONARY_END; + info->dict_last = (ucell *)((unsigned char *)forth_dictionary + + FORTH_DICTIONARY_LAST); + info->dict_limit = sizeof(forth_dictionary); +} diff --git a/qemu/roms/openbios/arch/sparc64/call-client.S b/qemu/roms/openbios/arch/sparc64/call-client.S new file mode 100644 index 000000000..f365e3cb1 --- /dev/null +++ b/qemu/roms/openbios/arch/sparc64/call-client.S @@ -0,0 +1,236 @@ + .globl sparc64_of_client_interface, client_tba + + +/* + * SAVE_WINDOW_STATE and RESTORE_WINDOW_STATE are used to ensure + * that the CPU window state is preserved across CIF calls. This is + * to workaround a *BSD restriction that window fill/spill traps must + * be minimised during trap table takeover, and likely emulates the + * behaviour of OBP. + */ + +#define SAVE_WINDOW_STATE(type) \ + setx client_window, %g6, %g1; \ + rdpr %cwp, %g7; \ + stx %g7, [%g1]; \ + rdpr %cansave, %g7; \ + stx %g7, [%g1 + 0x8]; \ + rdpr %canrestore, %g7; \ + stx %g7, [%g1 + 0x10]; \ + rdpr %otherwin, %g7; \ + stx %g7, [%g1 + 0x18]; \ + rdpr %wstate, %g7; \ + stx %g7, [%g1 + 0x20]; \ + rdpr %cleanwin, %g7; \ + stx %g7, [%g1 + 0x28]; \ + \ + stx %o0, [%g1 + 0x30]; \ + stx %o1, [%g1 + 0x38]; \ + stx %o2, [%g1 + 0x40]; \ + stx %o3, [%g1 + 0x48]; \ + stx %o4, [%g1 + 0x50]; \ + stx %o5, [%g1 + 0x58]; \ + stx %o6, [%g1 + 0x60]; \ + stx %o7, [%g1 + 0x68]; \ + \ + rdpr %pstate, %g7; \ + stx %g7, [%g1 + 0x70]; \ + rd %y, %g7; \ + stx %g7, [%g1 + 0x78]; \ + rd %fprs, %g7; \ + stx %g7, [%g1 + 0x80]; \ + \ + /* Now iterate through all of the windows saving all l and i registers */ \ + add %g1, 0x90, %g5; \ + \ + /* Get the number of windows in %g6 */ \ + rdpr %ver, %g6; \ + and %g6, 0xf, %g6; \ + inc %g6; \ + \ +save_cpu_window_##type: \ + deccc %g6; \ + wrpr %g6, %cwp; \ + stx %l0, [%g5]; \ + stx %l1, [%g5 + 0x8]; \ + stx %l2, [%g5 + 0x10]; \ + stx %l3, [%g5 + 0x18]; \ + stx %l4, [%g5 + 0x20]; \ + stx %l5, [%g5 + 0x28]; \ + stx %l6, [%g5 + 0x30]; \ + stx %l7, [%g5 + 0x38]; \ + stx %i0, [%g5 + 0x40]; \ + stx %i1, [%g5 + 0x48]; \ + stx %i2, [%g5 + 0x50]; \ + stx %i3, [%g5 + 0x58]; \ + stx %i4, [%g5 + 0x60]; \ + stx %i5, [%g5 + 0x68]; \ + stx %i6, [%g5 + 0x70]; \ + stx %i7, [%g5 + 0x78]; \ + bne save_cpu_window_##type; \ + add %g5, 0x80, %g5; \ + \ + /* For 8 windows with 16 registers to save in the window, memory required \ + is 16*8*8 = 0x400 bytes */ \ + \ + /* Now we should be in window 0 so update the other window registers */ \ + rdpr %ver, %g6; \ + and %g6, 0xf, %g6; \ + dec %g6; \ + wrpr %g6, %cansave; \ + \ + wrpr %g0, %cleanwin; \ + wrpr %g0, %canrestore; \ + wrpr %g0, %otherwin; + + +#define RESTORE_WINDOW_STATE(type) \ + setx client_window, %g6, %g1; \ + \ + /* Get the number of windows in %g6 */ \ + rdpr %ver, %g6; \ + and %g6, 0xf, %g6; \ + inc %g6; \ + \ + /* Now iterate through all of the windows restoring all l and i registers */ \ + add %g1, 0x90, %g5; \ + \ +restore_cpu_window_##type: \ + deccc %g6; \ + wrpr %g6, %cwp; \ + ldx [%g5], %l0; \ + ldx [%g5 + 0x8], %l1; \ + ldx [%g5 + 0x10], %l2; \ + ldx [%g5 + 0x18], %l3; \ + ldx [%g5 + 0x20], %l4; \ + ldx [%g5 + 0x28], %l5; \ + ldx [%g5 + 0x30], %l6; \ + ldx [%g5 + 0x38], %l7; \ + ldx [%g5 + 0x40], %i0; \ + ldx [%g5 + 0x48], %i1; \ + ldx [%g5 + 0x50], %i2; \ + ldx [%g5 + 0x58], %i3; \ + ldx [%g5 + 0x60], %i4; \ + ldx [%g5 + 0x68], %i5; \ + ldx [%g5 + 0x70], %i6; \ + ldx [%g5 + 0x78], %i7; \ + bne restore_cpu_window_##type; \ + add %g5, 0x80, %g5; \ + \ + /* Restore the window registers to their original value */ \ + ldx [%g1], %g7; \ + wrpr %g7, %cwp; \ + ldx [%g1 + 0x8], %g7; \ + wrpr %g7, %cansave; \ + ldx [%g1 + 0x10], %g7; \ + wrpr %g7, %canrestore; \ + ldx [%g1 + 0x18], %g7; \ + wrpr %g7, %otherwin; \ + ldx [%g1 + 0x20], %g7; \ + wrpr %g7, %wstate; \ + ldx [%g1 + 0x28], %g7; \ + wrpr %g7, %cleanwin; \ + \ + ldx [%g1 + 0x30], %o0; \ + ldx [%g1 + 0x38], %o1; \ + ldx [%g1 + 0x40], %o2; \ + ldx [%g1 + 0x48], %o3; \ + ldx [%g1 + 0x50], %o4; \ + ldx [%g1 + 0x58], %o5; \ + ldx [%g1 + 0x60], %o6; \ + ldx [%g1 + 0x68], %o7; \ + \ + ldx [%g1 + 0x70], %g7; \ + wrpr %g7, %pstate; \ + ldx [%g1 + 0x78], %g7; \ + wr %g7, 0, %y; \ + ldx [%g1 + 0x80], %g7; \ + wr %g7, 0, %fprs + + + .data + .align 8 + + .skip 16384 +openbios_stack: + +client_stack: + .xword 0 +client_tba: + .xword 0 +client_window: + .skip 2048 + + + .text + .align 4 + .register %g2, #scratch + .register %g3, #scratch + .register %g6, #scratch + .register %g7, #scratch +/* + make some more space on stack since linux kernel only provides 128 bytes + without memory to spill registers (used by gcc in -O0 mode) +*/ + +sparc64_of_client_interface: + + /* Save globals on callers stack */ + add %sp, -56, %sp + + stx %g1, [%sp + 2047 + 0] + stx %g2, [%sp + 2047 + 8] + stx %g3, [%sp + 2047 + 16] + stx %g4, [%sp + 2047 + 24] + stx %g5, [%sp + 2047 + 32] + stx %g6, [%sp + 2047 + 40] + stx %g7, [%sp + 2047 + 48] + + /* Save client trap table */ + setx client_tba, %g6, %g7 + rdpr %tba, %g6 + stx %g6, [%g7] + + /* Save existing stack */ + setx client_stack, %g6, %g7 + stx %sp, [%g7] + + /* Save windows */ + SAVE_WINDOW_STATE(cif) + + /* Move to OpenBIOS stack */ + setx openbios_stack - 2047 - 192, %g6, %g7 + mov %g7, %sp + + /* Call client inteface */ + call of_client_interface + ldx [%g1 + 0x30], %o0 + + setx client_window, %g6, %g1 + stx %o0, [%g1 + 0x30] + + /* Restore windows */ + RESTORE_WINDOW_STATE(cif) + + /* Restore stack */ + setx client_stack, %g6, %g7 + ldx [%g7], %sp + + /* Restore client trap table */ + setx client_tba, %g6, %g7 + ldx [%g7], %g6 + wrpr %g6, %tba + + /* Restore globals */ + ldx [%sp + 2047 + 0], %g1 + ldx [%sp + 2047 + 8], %g2 + ldx [%sp + 2047 + 16], %g3 + ldx [%sp + 2047 + 24], %g4 + ldx [%sp + 2047 + 32], %g5 + ldx [%sp + 2047 + 40], %g6 + ldx [%sp + 2047 + 48], %g7 + + add %sp, 56, %sp + + jmp %o7+8 + nop diff --git a/qemu/roms/openbios/arch/sparc64/console.c b/qemu/roms/openbios/arch/sparc64/console.c new file mode 100644 index 000000000..6ab5cba4d --- /dev/null +++ b/qemu/roms/openbios/arch/sparc64/console.c @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2003, 2004 Stefan Reinauer + * + * See the file "COPYING" for further information about + * the copyright and warranty status of this work. + */ + +#include "config.h" +#include "libopenbios/bindings.h" +#include "libopenbios/console.h" +#include "kernel/kernel.h" +#include "drivers/drivers.h" +#include "libopenbios/fontdata.h" +#include "openbios.h" +#include "libc/vsprintf.h" +#include "libopenbios/sys_info.h" +#include "boot.h" + +/* ****************************************************************** + * simple polling video/keyboard console functions + * ****************************************************************** */ + +#ifdef CONFIG_DEBUG_CONSOLE +/* ****************************************************************** + * common functions, implementing simple concurrent console + * ****************************************************************** */ + +static int arch_putchar(int c) +{ +#ifdef CONFIG_DEBUG_CONSOLE_SERIAL + uart_putchar(c); +#endif + return c; +} + +static int arch_availchar(void) +{ +#ifdef CONFIG_DEBUG_CONSOLE_SERIAL + if (uart_charav(CONFIG_SERIAL_PORT)) + return 1; +#endif +#ifdef CONFIG_DEBUG_CONSOLE_VGA + if (pc_kbd_dataready()) + return 1; +#endif + return 0; +} + +static int arch_getchar(void) +{ +#ifdef CONFIG_DEBUG_CONSOLE_SERIAL + if (uart_charav(CONFIG_SERIAL_PORT)) + return (uart_getchar(CONFIG_SERIAL_PORT)); +#endif +#ifdef CONFIG_DEBUG_CONSOLE_VGA + if (pc_kbd_dataready()) + return (pc_kbd_readdata()); +#endif + return 0; +} + +struct _console_ops arch_console_ops = { + .putchar = arch_putchar, + .availchar = arch_availchar, + .getchar = arch_getchar +}; + +#endif // CONFIG_DEBUG_CONSOLE diff --git a/qemu/roms/openbios/arch/sparc64/const.h b/qemu/roms/openbios/arch/sparc64/const.h new file mode 100644 index 000000000..8ad902b2c --- /dev/null +++ b/qemu/roms/openbios/arch/sparc64/const.h @@ -0,0 +1,19 @@ +/* const.h: Macros for dealing with constants. */ + +#ifndef _SPARC64_CONST_H +#define _SPARC64_CONST_H + +/* Some constant macros are used in both assembler and + * C code. Therefore we cannot annotate them always with + * 'UL' and other type specificers unilaterally. We + * use the following macros to deal with this. + */ + +#ifdef __ASSEMBLY__ +#define _AC(X,Y) X +#else +#define _AC(X,Y) (X##Y) +#endif + + +#endif /* !(_SPARC64_CONST_H) */ diff --git a/qemu/roms/openbios/arch/sparc64/context.c b/qemu/roms/openbios/arch/sparc64/context.c new file mode 100644 index 000000000..2e7668958 --- /dev/null +++ b/qemu/roms/openbios/arch/sparc64/context.c @@ -0,0 +1,129 @@ +/* + * context switching + * 2003-10 by SONE Takeshi + */ + +#include "config.h" +#include "kernel/kernel.h" +#include "context.h" +#include "libopenbios/sys_info.h" +#include "boot.h" +#include "openbios.h" + +#define MAIN_STACK_SIZE 16384 +#define IMAGE_STACK_SIZE 4096*4 + +#define debug printk + +static void start_main(void); /* forward decl. */ +void __exit_context(void); /* assembly routine */ + +/* + * Main context structure + * It is placed at the bottom of our stack, and loaded by assembly routine + * to start us up. + */ +static struct context main_ctx = { + .regs[REG_SP] = (uint64_t) &_estack - STACK_BIAS - 96, + .pc = (uint64_t) start_main, + .npc = (uint64_t) start_main + 4, + .return_addr = (uint64_t) __exit_context, +}; + +/* This is used by assembly routine to load/store the context which + * it is to switch/switched. */ +struct context * volatile __context = &main_ctx; + +/* Stack for loaded ELF image */ +static uint8_t image_stack[IMAGE_STACK_SIZE]; + +/* Pointer to startup context (physical address) */ +unsigned long __boot_ctx; + +/* + * Main starter + * This is the C function that runs first. + */ +static void start_main(void) +{ + /* Save startup context, so we can refer to it later. + * We have to keep it in physical address since we will relocate. */ + __boot_ctx = virt_to_phys(__context); + + /* Start the real fun */ + openbios(); + + /* Returning from here should jump to __exit_context */ + __context = boot_ctx; +} + +static uint64_t ALIGN_SIZE(uint64_t x, uint64_t a) +{ + return (x + a - 1) & ~(a-1); +} + +/* Setup a new context using the given stack. + */ +struct context * +init_context(uint8_t *stack, uint64_t stack_size, int num_params) +{ + struct context *ctx; + uint8_t *stack_top = stack + stack_size; + + ctx = (struct context *) + (stack_top - ALIGN_SIZE(sizeof(*ctx) + num_params*sizeof(uint64_t), sizeof(uint64_t))); + memset(ctx, 0, sizeof(*ctx)); + + /* Fill in reasonable default for flat memory model */ + ctx->regs[REG_SP] = virt_to_phys(stack_top - STACK_BIAS - 192); + ctx->return_addr = virt_to_phys(__exit_context); + + return ctx; +} + +/* Switch to another context. */ +struct context *switch_to(struct context *ctx) +{ + struct context *save, *ret; + + debug("switching to new context: entry point %#llx stack 0x%016llx\n", ctx->pc, ctx->regs[REG_SP]); + save = __context; + __context = ctx; + //asm ("pushl %cs; call __switch_context"); + asm ("call __switch_context_nosave; nop"); + ret = __context; + __context = save; + return ret; +} + +/* Start ELF Boot image */ +uint64_t start_elf(uint64_t entry_point, uint64_t param) +{ + struct context *ctx; + + ctx = init_context(image_stack, sizeof image_stack, 1); + ctx->pc = entry_point; + ctx->param[0] = param; + //ctx->eax = 0xe1fb007; + //ctx->ebx = param; + + ctx = switch_to(ctx); + //return ctx->eax; + return 0; +} + +/* Start client image */ +uint64_t start_client_image(uint64_t entry_point, uint64_t cif_handler) +{ + struct context *ctx; + + ctx = init_context(image_stack, sizeof image_stack, 0); + ctx->pc = entry_point; + ctx->npc = entry_point+4; + ctx->regs[REG_O0] = 0; + ctx->regs[REG_O0+4] = cif_handler; + + ctx = switch_to(ctx); + + return 0; +} diff --git a/qemu/roms/openbios/arch/sparc64/context.h b/qemu/roms/openbios/arch/sparc64/context.h new file mode 100644 index 000000000..2756fa15f --- /dev/null +++ b/qemu/roms/openbios/arch/sparc64/context.h @@ -0,0 +1,33 @@ +#ifndef SPARC64_CONTEXT_H +#define SPARC64_CONTEXT_H + +#define STACK_BIAS 2047 + +struct context { + /* General registers */ + uint64_t regs[32]; + uint64_t pc; + uint64_t npc; +#define REG_O0 8 +#define REG_SP 14 +#define SP_LOC(ctx) (&(ctx)->regs[REG_SP]) + /* Flags */ + /* Optional stack contents */ + uint64_t return_addr; + uint64_t param[0]; +}; + +/* Create a new context in the given stack */ +struct context * +init_context(uint8_t *stack, uint64_t stack_size, int num_param); + +/* Switch context */ +struct context *switch_to(struct context *); + +/* Holds physical address of boot context */ +extern unsigned long __boot_ctx; + +/* This can always be safely used to refer to the boot context */ +#define boot_ctx ((struct context *) phys_to_virt(__boot_ctx)) + +#endif /* SPARC64_CONTEXT_H */ diff --git a/qemu/roms/openbios/arch/sparc64/entry.S b/qemu/roms/openbios/arch/sparc64/entry.S new file mode 100644 index 000000000..d03128af5 --- /dev/null +++ b/qemu/roms/openbios/arch/sparc64/entry.S @@ -0,0 +1,287 @@ +/** + ** Standalone startup code for Linux PROM emulator. + ** Copyright 1999 Pete A. Zaitcev + ** This code is licensed under GNU General Public License. + **/ +/* + * $Id: head.S,v 1.12 2002/07/23 05:47:09 zaitcev Exp $ + */ + +#define __ASSEMBLY__ +#include <asm/asi.h> +#include "pstate.h" +#include "lsu.h" +#define NO_QEMU_PROTOS +#define NO_OPENBIOS_PROTOS +#include "arch/common/fw_cfg.h" + +#define PROM_ADDR 0x1fff0000000 +#define CFG_ADDR 0x1fe02000510 +#define HZ 1 * 1000 * 1000 +#define TICK_INT_DIS 0x8000000000000000 + + .globl entry, _entry + + .section ".text", "ax" + .align 8 + .register %g2, #scratch + .register %g3, #scratch + .register %g6, #scratch + .register %g7, #scratch + +/* + * Entry point + * We start execution from here. + */ +_entry: +entry: + ! Set up CPU state + wrpr %g0, PSTATE_PRIV, %pstate + wr %g0, 0, %fprs + wrpr %g0, 0x0, %tl + + ! Extract NWINDOWS from %ver + rdpr %ver, %g1 + and %g1, 0xf, %g1 + dec %g1 + wrpr %g1, 0, %cleanwin + wrpr %g1, 0, %cansave + wrpr %g0, 0, %canrestore + wrpr %g0, 0, %otherwin + wrpr %g0, 0, %wstate + ! disable timer now + setx TICK_INT_DIS, %g2, %g1 + wr %g1, 0, %tick_cmpr + + ! Disable I/D MMUs and caches + stxa %g0, [%g0] ASI_LSU_CONTROL + + ! Check signature "QEMU" + setx CFG_ADDR, %g2, %g5 + mov FW_CFG_SIGNATURE, %g2 + stha %g2, [%g5] ASI_PHYS_BYPASS_EC_E_L + inc %g5 + lduba [%g5] ASI_PHYS_BYPASS_EC_E, %g2 + cmp %g2, 'Q' + bne bad_conf + nop + lduba [%g5] ASI_PHYS_BYPASS_EC_E, %g2 + cmp %g2, 'E' + bne bad_conf + nop + lduba [%g5] ASI_PHYS_BYPASS_EC_E, %g2 + cmp %g2, 'M' + bne bad_conf + nop + lduba [%g5] ASI_PHYS_BYPASS_EC_E, %g2 + cmp %g2, 'U' + bne bad_conf + nop + + ! Clear ITLB + mov 6 << 3, %g1 + stxa %g0, [%g1] ASI_IMMU + stxa %g0, [%g1] ASI_DMMU + mov 63 << 3, %g1 +1: stxa %g0, [%g1] ASI_ITLB_DATA_ACCESS + subcc %g1, 1 << 3, %g1 + bpos 1b + nop + + ! Clear DTLB + mov 63 << 3, %g1 +1: stxa %g0, [%g1] ASI_DTLB_DATA_ACCESS + subcc %g1, 1 << 3, %g1 + bpos 1b + nop + + ! Get memory size from configuration device + ! NB: little endian format + mov FW_CFG_RAM_SIZE, %g2 + dec %g5 + stha %g2, [%g5] ASI_PHYS_BYPASS_EC_E_L + inc %g5 + lduba [%g5] ASI_PHYS_BYPASS_EC_E, %g4 + + lduba [%g5] ASI_PHYS_BYPASS_EC_E, %g3 + sllx %g3, 8, %g3 + or %g3, %g4, %g4 + + lduba [%g5] ASI_PHYS_BYPASS_EC_E, %g3 + sllx %g3, 16, %g3 + or %g3, %g4, %g4 + + lduba [%g5] ASI_PHYS_BYPASS_EC_E, %g3 + sllx %g3, 24, %g3 + or %g3, %g4, %g4 + + lduba [%g5] ASI_PHYS_BYPASS_EC_E, %g3 + sllx %g3, 32, %g3 + or %g3, %g4, %g4 + + lduba [%g5] ASI_PHYS_BYPASS_EC_E, %g3 + sllx %g3, 40, %g3 + or %g3, %g4, %g4 + + lduba [%g5] ASI_PHYS_BYPASS_EC_E, %g3 + sllx %g3, 48, %g3 + or %g3, %g4, %g4 + + lduba [%g5] ASI_PHYS_BYPASS_EC_E, %g3 + sllx %g3, 56, %g3 + or %g3, %g4, %g1 + ! %g1 contains end of memory + + setx _end, %g7, %g3 + set 0x7ffff, %g2 + add %g3, %g2, %g3 + andn %g3, %g2, %g3 + setx _data, %g7, %g2 + sub %g3, %g2, %g2 + sub %g1, %g2, %g2 ! %g2 = start of private memory + mov %g2, %l0 + + ! setup .data & .bss + setx _data, %g7, %g4 + sub %g3, %g4, %g5 + srlx %g5, 19, %g6 ! %g6 = # of 512k .bss pages + set 0xc0000000, %g3 + sllx %g3, 32, %g3 + or %g3, 0x76, %g3 + ! valid, 512k, locked, cacheable(I/E/C), priv, writable + set 48, %g7 +1: stxa %g4, [%g7] ASI_DMMU ! vaddr = _data + N * 0x80000, ctx=0 + or %g2, %g3, %g5 + ! paddr = start_mem + N * 0x80000 + stxa %g5, [%g0] ASI_DTLB_DATA_IN + set 0x80000, %g5 + add %g2, %g5, %g2 + add %g4, %g5, %g4 + deccc %g6 + bne 1b + nop + + ! setup .rodata, also make .text readable + setx _data, %g7, %g5 + setx _start, %g7, %g4 + sub %g5, %g4, %g5 + srlx %g5, 19, %g6 ! %g6 = # of 512k .rodata pages + set 48, %g7 + set 0x80000, %g5 + setx PROM_ADDR, %l1, %l2 +1: stxa %g4, [%g7] ASI_DMMU ! vaddr = _rodata, ctx=0 + set 0xc0000000, %g3 + sllx %g3, 32, %g3 + or %g3, 0x74, %g3 + or %l2, %g3, %g3 + ! valid, 512k, locked, cacheable(I/E/C), priv + ! paddr = _rodata + N * 0x10000 + stxa %g3, [%g0] ASI_DTLB_DATA_IN + add %g4, %g5, %g4 + deccc %g6 + bne 1b + add %l2, %g5, %l2 + + membar #Sync + + setx _start, %g7, %g4 + setx _rodata, %g7, %g5 + sub %g5, %g4, %g5 + set 0x7ffff, %g7 + add %g5, %g7, %g5 ! round to 512k + srlx %g5, 19, %g6 ! %g6 = # of 512k .text pages + set 0x80000, %g5 + set 48, %g7 + setx PROM_ADDR, %l1, %l2 +1: stxa %g4, [%g7] ASI_IMMU ! vaddr = _start, ctx=0 + set 0xc0000000, %g3 + sllx %g3, 32, %g3 + or %g3, 0x74, %g3 + or %l2, %g3, %g3 + ! valid, 512k, locked, cacheable(I/E/C), priv + ! paddr = _start + N * 0x80000 + stxa %g3, [%g0] ASI_ITLB_DATA_IN + add %g4, %g5, %g4 + deccc %g6 + bne 1b + add %l2, %g5, %l2 + + flush %g4 + + mov %g1, %g3 + + set 8, %g2 + sta %g0, [%g2] ASI_DMMU ! set primary ctx=0 + + ! Enable I/D MMUs and caches + setx lowmem, %g2, %g1 + set LSU_CONTROL_DM|LSU_CONTROL_IM|LSU_CONTROL_DC|LSU_CONTROL_IC, %g2 + jmp %g1 + stxa %g2, [%g0] ASI_LSU_CONTROL + +lowmem: + /* Copy the DATA section from ROM. */ + setx _data - 8, %o7, %o0 ! First address of DATA + setx _bss, %o7, %o1 ! Last address of DATA + setx _start, %o7, %o2 + sub %o0, %o2, %o2 ! _data - _start + setx PROM_ADDR, %o7, %o3 + add %o3, %o2, %o2 ! PROM_ADDR + (_data - _start) + ba 2f + nop +1: + ldxa [%o2] ASI_PHYS_BYPASS_EC_E, %g1 + stx %g1, [%o0] +2: + add %o2, 0x8, %o2 + subcc %o0, %o1, %g0 + bl 1b + add %o0, 0x8, %o0 + + /* Zero out our BSS section. */ + setx _bss - 8, %o7, %o0 ! First address of BSS + setx _end - 8, %o7, %o1 ! Last address of BSS + ba 2f + nop +1: + stx %g0, [%o0] +2: + subcc %o0, %o1, %g0 + bl 1b + add %o0, 0x8, %o0 + + setx trap_table, %g2, %g1 + wrpr %g1, %tba + + setx qemu_mem_size, %g7, %g1 + stx %g3, [%g1] + + setx _data, %g7, %g1 ! Store va->pa conversion factor + sub %g1, %l0, %g2 + setx va_shift, %g7, %g1 + stx %g2, [%g1] + + /* Finally, turn on traps so that we can call c-code. */ + wrpr %g0, (PSTATE_PRIV|PSTATE_PEF|PSTATE_IE), %pstate + + ! 100 Hz timer + setx TICK_INT_DIS, %g2, %g1 + rd %tick, %g2 + andn %g2, %g1, %g2 + set HZ, %g1 + add %g1, %g2, %g1 + wr %g1, 0, %tick_cmpr + + /* Switch to our main context. + * Main context is statically defined in C. + */ + + call __switch_context_nosave + nop + + /* We get here when the main context switches back to + * the boot context. + */ +bad_conf: + b bad_conf + nop diff --git a/qemu/roms/openbios/arch/sparc64/init.fs b/qemu/roms/openbios/arch/sparc64/init.fs new file mode 100644 index 000000000..eb6c9da52 --- /dev/null +++ b/qemu/roms/openbios/arch/sparc64/init.fs @@ -0,0 +1,61 @@ +\ va>tte-data defer MMU virtual to physical address hook for Solaris +\ We need to make sure this is in the global wordlist +active-package 0 active-package! +defer va>tte-data +0 to va>tte-data +active-package! + +:noname + ." Type 'help' for detailed information" cr + \ ." boot secondary slave cdrom: " cr + \ ." 0 > boot hd:2,\boot\vmlinuz root=/dev/hda2" cr + ; DIAG-initializer + +: make-openable ( path ) + find-dev if + begin ?dup while + \ install trivial open and close methods + dup active-package! is-open + parent + repeat + then +; + +: preopen ( chosen-str node-path ) + 2dup make-openable + + " /chosen" find-device + open-dev ?dup if + encode-int 2swap property + else + 2drop + then +; + +:noname + set-defaults +; PREPOST-initializer + +\ preopen device nodes (and store the ihandles under /chosen) +:noname + " memory" " /memory" preopen + +; SYSTEM-initializer + +\ use the tty interface if available +: activate-tty-interface + " /packages/terminal-emulator" find-dev if drop + then +; + +device-end + +: rmap@ ( virt -- rmentry ) + drop 0 + ; + +\ Load VGA FCode driver blob +[IFDEF] CONFIG_DRIVER_VGA + -1 value vga-driver-fcode + " QEMU,VGA.bin" $encode-file to vga-driver-fcode +[THEN] diff --git a/qemu/roms/openbios/arch/sparc64/ldscript b/qemu/roms/openbios/arch/sparc64/ldscript new file mode 100644 index 000000000..54288e825 --- /dev/null +++ b/qemu/roms/openbios/arch/sparc64/ldscript @@ -0,0 +1,67 @@ +OUTPUT_FORMAT(elf64-sparc) +OUTPUT_ARCH(sparc:v9) + +/* QEMU ELF loader can't handle very complex files, so we put ELFBoot +info to rodata and put initctx to data.*/ + +ENTRY(trap_table) + +/* Initial load address + */ +BASE_ADDR = 0x00000000ffd00000; + +/* 16KB stack */ +STACK_SIZE = 16384; +IOMEM_SIZE = 256 * 1024 + 768 * 1024; + +SECTIONS +{ + . = BASE_ADDR; + + /* Start of the program. + * Now the version string is in the note, we must include it + * in the program. Otherwise we lose the string after relocation. */ + _start = .; + + /* Normal sections */ + .text ALIGN(524288): { + *(.text.vectors) + *(.text) + *(.text.*) + } + .rodata ALIGN(524288): { + _rodata = .; + sound_drivers_start = .; + *(.rodata.sound_drivers) + sound_drivers_end = .; + *(.rodata) + *(.rodata.*) + *(.note.ELFBoot) + } + .data ALIGN(524288): { + _data = .; + *(.data) + *(.data.*) + } + + .bss ALIGN(4096): { + _bss = .; + *(.bss) + *(.bss.*) + *(COMMON) + + _stack = .; + . += STACK_SIZE; + . = ALIGN(16); + _estack = .; + } + + . = ALIGN(4096); + _end = .; + _iomem = _end + IOMEM_SIZE; + + /* We discard .note sections other than .note.ELFBoot, + * because some versions of GCC generates useless ones. */ + + /DISCARD/ : { *(.comment*) *(.note.*) } +} diff --git a/qemu/roms/openbios/arch/sparc64/lib.c b/qemu/roms/openbios/arch/sparc64/lib.c new file mode 100644 index 000000000..e9101af52 --- /dev/null +++ b/qemu/roms/openbios/arch/sparc64/lib.c @@ -0,0 +1,508 @@ +/* lib.c + * tag: simple function library + * + * Copyright (C) 2003 Stefan Reinauer + * + * See the file "COPYING" for further information about + * the copyright and warranty status of this work. + */ + +#include "config.h" +#include "libc/vsprintf.h" +#include "libopenbios/bindings.h" +#include "spitfire.h" +#include "libopenbios/sys_info.h" +#include "boot.h" + +#include "arch/sparc64/ofmem_sparc64.h" + +/* Format a string and print it on the screen, just like the libc + * function printf. + */ +int printk( const char *fmt, ... ) +{ + char *p, buf[512]; + va_list args; + int i; + + va_start(args, fmt); + i = vsnprintf(buf, sizeof(buf), fmt, args); + va_end(args); + + for( p=buf; *p; p++ ) + putchar(*p); + return i; +} + +/* Private functions for mapping between physical/virtual addresses */ +phys_addr_t +va2pa(unsigned long va) +{ + if ((va >= (unsigned long)&_start) && + (va < (unsigned long)&_end)) + return va - va_shift; + else + return va; +} + +unsigned long +pa2va(phys_addr_t pa) +{ + if ((pa + va_shift >= (unsigned long)&_start) && + (pa + va_shift < (unsigned long)&_end)) + return pa + va_shift; + else + return pa; +} + +void *malloc(int size) +{ + return ofmem_malloc(size); +} + +void* realloc( void *ptr, size_t size ) +{ + return ofmem_realloc(ptr, size); +} + +void free(void *ptr) +{ + ofmem_free(ptr); +} + +static void +mmu_open(void) +{ + RET(-1); +} + +static void +mmu_close(void) +{ +} + +void ofmem_walk_boot_map(translation_entry_cb cb) +{ + unsigned long phys, virt, size, mode, data, mask; + unsigned int i; + + for (i = 0; i < 64; i++) { + data = spitfire_get_dtlb_data(i); + if (data & SPITFIRE_TTE_VALID) { + switch ((data >> 61) & 3) { + default: + case 0x0: /* 8k */ + mask = 0xffffffffffffe000ULL; + size = PAGE_SIZE_8K; + break; + case 0x1: /* 64k */ + mask = 0xffffffffffff0000ULL; + size = PAGE_SIZE_64K; + break; + case 0x2: /* 512k */ + mask = 0xfffffffffff80000ULL; + size = PAGE_SIZE_512K; + break; + case 0x3: /* 4M */ + mask = 0xffffffffffc00000ULL; + size = PAGE_SIZE_4M; + break; + } + + virt = spitfire_get_dtlb_tag(i); + virt &= mask; + + /* extract 41bit physical address */ + phys = data & 0x000001fffffff000ULL; + phys &= mask; + + mode = data & 0xfff; + + cb(phys, virt, size, mode); + } + } +} + +/* + 3.6.5 translate + ( virt -- false | phys.lo ... phys.hi mode true ) +*/ +static void +mmu_translate(void) +{ + ucell virt, mode; + phys_addr_t phys; + + virt = POP(); + + phys = ofmem_translate(virt, &mode); + + if (phys != -1UL) { + PUSH(phys & 0xffffffff); + PUSH(phys >> 32); + PUSH(mode); + PUSH(-1); + } + else { + PUSH(0); + } +} + +/* + * D5.3 pgmap@ ( va -- tte ) + */ +static void +pgmap_fetch(void) +{ + unsigned long va, tte_data; + + va = POP(); + + tte_data = find_tte(va); + if (tte_data == -1) + goto error; + + /* return tte_data */ + PUSH(tte_data); + return; + +error: + /* If we get here, there was no entry */ + PUSH(0); +} + +/* + ( index tte_data vaddr -- ? ) +*/ +static void +dtlb_load(void) +{ + unsigned long vaddr, tte_data, idx; + + vaddr = POP(); + tte_data = POP(); + idx = POP(); + dtlb_load3(vaddr, tte_data, idx); +} + +/* MMU D-TLB miss handler */ +void +dtlb_miss_handler(void) +{ + unsigned long faultva, tte_data = 0; + + /* Grab fault address from MMU and round to nearest 8k page */ + faultva = dtlb_faultva(); + faultva >>= 13; + faultva <<= 13; + + /* If a valid va>tte-data routine has been set, invoke that Forth xt instead */ + if (va2ttedata && *va2ttedata != 0) { + + /* va>tte-data ( addr cnum -- false | tte-data true ) */ + PUSH(faultva); + PUSH(0); + enterforth(*va2ttedata); + + /* Check the result first... */ + tte_data = POP(); + if (!tte_data) { + bug(); + } else { + /* Grab the real data */ + tte_data = POP(); + } + } else { + /* Search the ofmem linked list for this virtual address */ + tte_data = find_tte(faultva); + } + + if (tte_data) { + /* Update MMU */ + dtlb_load2(faultva, tte_data); + } else { + /* If we got here, there was no translation so fail */ + bug(); + } + +} + +/* + ( index tte_data vaddr -- ? ) +*/ +static void +itlb_load(void) +{ + unsigned long vaddr, tte_data, idx; + + vaddr = POP(); + tte_data = POP(); + idx = POP(); + itlb_load3(vaddr, tte_data, idx); +} + +/* MMU I-TLB miss handler */ +void +itlb_miss_handler(void) +{ + unsigned long faultva, tte_data = 0; + + /* Grab fault address from MMU and round to nearest 8k page */ + faultva = itlb_faultva(); + faultva >>= 13; + faultva <<= 13; + + /* If a valid va>tte-data routine has been set, invoke that Forth xt instead */ + if (va2ttedata && *va2ttedata != 0) { + + /* va>tte-data ( addr cnum -- false | tte-data true ) */ + PUSH(faultva); + PUSH(0); + enterforth(*va2ttedata); + + /* Check the result first... */ + tte_data = POP(); + if (!tte_data) { + bug(); + } else { + /* Grab the real data */ + tte_data = POP(); + } + } else { + /* Search the ofmem linked list for this virtual address */ + tte_data = find_tte(faultva); + } + + if (tte_data) { + /* Update MMU */ + itlb_load2(faultva, tte_data); + } else { + /* If we got here, there was no translation so fail */ + bug(); + } +} + +/* + 3.6.5 map + ( phys.lo ... phys.hi virt size mode -- ) +*/ +static void +mmu_map(void) +{ + ucell virt, size, mode; + phys_addr_t phys; + + mode = POP(); + size = POP(); + virt = POP(); + phys = POP(); + phys <<= 32; + phys |= POP(); + + ofmem_map(phys, virt, size, mode); +} + +/* + 3.6.5 unmap + ( virt size -- ) +*/ +static void +mmu_unmap(void) +{ + ucell virt, size; + + size = POP(); + virt = POP(); + ofmem_unmap(virt, size); +} + +/* + 3.6.5 claim + ( virt size align -- base ) +*/ +static void +mmu_claim(void) +{ + ucell virt=-1UL, size, align; + + align = POP(); + size = POP(); + if (!align) { + virt = POP(); + } + + virt = ofmem_claim_virt(virt, size, align); + + PUSH(virt); +} + +/* + 3.6.5 release + ( virt size -- ) +*/ +static void +mmu_release(void) +{ + ucell virt, size; + + size = POP(); + virt = POP(); + + ofmem_release_virt(virt, size); +} + +/* ( phys size align --- base ) */ +static void +mem_claim( void ) +{ + ucell size, align; + phys_addr_t phys=-1UL; + + align = POP(); + size = POP(); + if (!align) { + phys = POP(); + phys <<= 32; + phys |= POP(); + } + + phys = ofmem_claim_phys(phys, size, align); + + PUSH(phys & 0xffffffffUL); + PUSH(phys >> 32); +} + +/* ( phys size --- ) */ +static void +mem_release( void ) +{ + phys_addr_t phys; + ucell size; + + size = POP(); + phys = POP(); + phys <<= 32; + phys |= POP(); + + ofmem_release_phys(phys, size); +} + +/* ( name-cstr phys size align --- phys ) */ +static void +mem_retain ( void ) +{ + ucell size, align; + phys_addr_t phys=-1UL; + + align = POP(); + size = POP(); + if (!align) { + phys = POP(); + phys <<= 32; + phys |= POP(); + } + + /* Currently do nothing with the name */ + POP(); + + phys = ofmem_retain(phys, size, align); + + PUSH(phys & 0xffffffffUL); + PUSH(phys >> 32); +} + +/* ( virt size align -- baseaddr|-1 ) */ +static void +ciface_claim( void ) +{ + ucell align = POP(); + ucell size = POP(); + ucell virt = POP(); + ucell ret = ofmem_claim( virt, size, align ); + + /* printk("ciface_claim: %08x %08x %x\n", virt, size, align ); */ + PUSH( ret ); +} + +/* ( virt size -- ) */ +static void +ciface_release( void ) +{ + ucell size = POP(); + ucell virt = POP(); + ofmem_release(virt, size); +} + +DECLARE_NODE(memory, INSTALL_OPEN, 0, "/memory"); + +NODE_METHODS( memory ) = { + { "claim", mem_claim }, + { "release", mem_release }, + { "SUNW,retain", mem_retain }, +}; + +DECLARE_NODE(mmu, INSTALL_OPEN, 0, "/virtual-memory"); + +NODE_METHODS(mmu) = { + { "open", mmu_open }, + { "close", mmu_close }, + { "translate", mmu_translate }, + { "SUNW,dtlb-load", dtlb_load }, + { "SUNW,itlb-load", itlb_load }, + { "map", mmu_map }, + { "unmap", mmu_unmap }, + { "claim", mmu_claim }, + { "release", mmu_release }, +}; + +void ob_mmu_init(const char *cpuname, uint64_t ram_size) +{ + /* memory node */ + REGISTER_NODE_METHODS(memory, "/memory"); + + /* MMU node */ + REGISTER_NODE_METHODS(mmu, "/virtual-memory"); + + ofmem_register(find_dev("/memory"), find_dev("/virtual-memory")); + + push_str("/chosen"); + fword("find-device"); + + push_str("/virtual-memory"); + fword("open-dev"); + fword("encode-int"); + push_str("mmu"); + fword("property"); + + push_str("/memory"); + fword("find-device"); + + /* All memory: 0 to RAM_size */ + PUSH(0); + fword("encode-int"); + PUSH(0); + fword("encode-int"); + fword("encode+"); + PUSH((int)(ram_size >> 32)); + fword("encode-int"); + fword("encode+"); + PUSH((int)(ram_size & 0xffffffff)); + fword("encode-int"); + fword("encode+"); + push_str("reg"); + fword("property"); + + push_str("/openprom/client-services"); + fword("find-device"); + bind_func("cif-claim", ciface_claim); + bind_func("cif-release", ciface_release); + + /* Other MMU functions */ + PUSH(0); + fword("active-package!"); + bind_func("pgmap@", pgmap_fetch); + + /* Find address of va2ttedata defer word contents for MMU miss handlers */ + va2ttedata = (ucell *)findword("va>tte-data"); + va2ttedata++; +} diff --git a/qemu/roms/openbios/arch/sparc64/linux_load.c b/qemu/roms/openbios/arch/sparc64/linux_load.c new file mode 100644 index 000000000..e3afc2db8 --- /dev/null +++ b/qemu/roms/openbios/arch/sparc64/linux_load.c @@ -0,0 +1,653 @@ +/* + * Linux/i386 loader + * Supports bzImage, zImage and Image format. + * + * Based on work by Steve Gehlbach. + * Portions are taken from mkelfImage. + * + * 2003-09 by SONE Takeshi + */ + +#include "config.h" +#include "kernel/kernel.h" +#include "libopenbios/bindings.h" +#include "libopenbios/sys_info.h" +#include "context.h" +#include "libc/diskio.h" +#include "boot.h" + +#define printf printk +#define debug printk +#define strtoull_with_suffix strtol + +#define LINUX_PARAM_LOC 0x90000 +#define COMMAND_LINE_LOC 0x91000 +#define GDT_LOC 0x92000 +#define STACK_LOC 0x93000 + +#define E820MAX 32 /* number of entries in E820MAP */ +struct e820entry { + unsigned long long addr; /* start of memory segment */ + unsigned long long size; /* size of memory segment */ + unsigned long type; /* type of memory segment */ +#define E820_RAM 1 +#define E820_RESERVED 2 +#define E820_ACPI 3 /* usable as RAM once ACPI tables have been read */ +#define E820_NVS 4 +}; + +/* The header of Linux/i386 kernel */ +struct linux_header { + uint8_t reserved1[0x1f1]; /* 0x000 */ + uint8_t setup_sects; /* 0x1f1 */ + uint16_t root_flags; /* 0x1f2 */ + uint8_t reserved2[6]; /* 0x1f4 */ + uint16_t vid_mode; /* 0x1fa */ + uint16_t root_dev; /* 0x1fc */ + uint16_t boot_sector_magic; /* 0x1fe */ + /* 2.00+ */ + uint8_t reserved3[2]; /* 0x200 */ + uint8_t header_magic[4]; /* 0x202 */ + uint16_t protocol_version; /* 0x206 */ + uint32_t realmode_swtch; /* 0x208 */ + uint16_t start_sys; /* 0x20c */ + uint16_t kver_addr; /* 0x20e */ + uint8_t type_of_loader; /* 0x210 */ + uint8_t loadflags; /* 0x211 */ + uint16_t setup_move_size; /* 0x212 */ + uint32_t code32_start; /* 0x214 */ + uint32_t ramdisk_image; /* 0x218 */ + uint32_t ramdisk_size; /* 0x21c */ + uint8_t reserved4[4]; /* 0x220 */ + /* 2.01+ */ + uint16_t heap_end_ptr; /* 0x224 */ + uint8_t reserved5[2]; /* 0x226 */ + /* 2.02+ */ + uint32_t cmd_line_ptr; /* 0x228 */ + /* 2.03+ */ + uint32_t initrd_addr_max; /* 0x22c */ +} __attribute__ ((packed)); + + +/* Paramters passed to 32-bit part of Linux + * This is another view of the structure above.. */ +struct linux_params { + uint8_t orig_x; /* 0x00 */ + uint8_t orig_y; /* 0x01 */ + uint16_t ext_mem_k; /* 0x02 -- EXT_MEM_K sits here */ + uint16_t orig_video_page; /* 0x04 */ + uint8_t orig_video_mode; /* 0x06 */ + uint8_t orig_video_cols; /* 0x07 */ + uint16_t unused2; /* 0x08 */ + uint16_t orig_video_ega_bx; /* 0x0a */ + uint16_t unused3; /* 0x0c */ + uint8_t orig_video_lines; /* 0x0e */ + uint8_t orig_video_isVGA; /* 0x0f */ + uint16_t orig_video_points; /* 0x10 */ + + /* VESA graphic mode -- linear frame buffer */ + uint16_t lfb_width; /* 0x12 */ + uint16_t lfb_height; /* 0x14 */ + uint16_t lfb_depth; /* 0x16 */ + uint32_t lfb_base; /* 0x18 */ + uint32_t lfb_size; /* 0x1c */ + uint16_t cl_magic; /* 0x20 */ +#define CL_MAGIC_VALUE 0xA33F + uint16_t cl_offset; /* 0x22 */ + uint16_t lfb_linelength; /* 0x24 */ + uint8_t red_size; /* 0x26 */ + uint8_t red_pos; /* 0x27 */ + uint8_t green_size; /* 0x28 */ + uint8_t green_pos; /* 0x29 */ + uint8_t blue_size; /* 0x2a */ + uint8_t blue_pos; /* 0x2b */ + uint8_t rsvd_size; /* 0x2c */ + uint8_t rsvd_pos; /* 0x2d */ + uint16_t vesapm_seg; /* 0x2e */ + uint16_t vesapm_off; /* 0x30 */ + uint16_t pages; /* 0x32 */ + uint8_t reserved4[12]; /* 0x34 -- 0x3f reserved for future expansion */ + + //struct apm_bios_info apm_bios_info; /* 0x40 */ + uint8_t apm_bios_info[0x40]; + //struct drive_info_struct drive_info; /* 0x80 */ + uint8_t drive_info[0x20]; + //struct sys_desc_table sys_desc_table; /* 0xa0 */ + uint8_t sys_desc_table[0x140]; + uint32_t alt_mem_k; /* 0x1e0 */ + uint8_t reserved5[4]; /* 0x1e4 */ + uint8_t e820_map_nr; /* 0x1e8 */ + uint8_t reserved6[9]; /* 0x1e9 */ + uint16_t mount_root_rdonly; /* 0x1f2 */ + uint8_t reserved7[4]; /* 0x1f4 */ + uint16_t ramdisk_flags; /* 0x1f8 */ +#define RAMDISK_IMAGE_START_MASK 0x07FF +#define RAMDISK_PROMPT_FLAG 0x8000 +#define RAMDISK_LOAD_FLAG 0x4000 + uint8_t reserved8[2]; /* 0x1fa */ + uint16_t orig_root_dev; /* 0x1fc */ + uint8_t reserved9[1]; /* 0x1fe */ + uint8_t aux_device_info; /* 0x1ff */ + uint8_t reserved10[2]; /* 0x200 */ + uint8_t param_block_signature[4]; /* 0x202 */ + uint16_t param_block_version; /* 0x206 */ + uint8_t reserved11[8]; /* 0x208 */ + uint8_t loader_type; /* 0x210 */ +#define LOADER_TYPE_LOADLIN 1 +#define LOADER_TYPE_BOOTSECT_LOADER 2 +#define LOADER_TYPE_SYSLINUX 3 +#define LOADER_TYPE_ETHERBOOT 4 +#define LOADER_TYPE_KERNEL 5 + uint8_t loader_flags; /* 0x211 */ + uint8_t reserved12[2]; /* 0x212 */ + uint32_t kernel_start; /* 0x214 */ + uint32_t initrd_start; /* 0x218 */ + uint32_t initrd_size; /* 0x21c */ + uint8_t reserved12_5[8]; /* 0x220 */ + uint32_t cmd_line_ptr; /* 0x228 */ + uint8_t reserved13[164]; /* 0x22c */ + struct e820entry e820_map[E820MAX]; /* 0x2d0 */ + uint8_t reserved16[688]; /* 0x550 */ +#define COMMAND_LINE_SIZE 256 + /* Command line is copied here by 32-bit i386/kernel/head.S. + * So I will follow the boot protocol, rather than putting it + * directly here. --ts1 */ + uint8_t command_line[COMMAND_LINE_SIZE]; /* 0x800 */ + uint8_t reserved17[1792]; /* 0x900 - 0x1000 */ +}; + +static uint64_t forced_memsize; +static int fd; + +static unsigned long file_size(void) +{ + long long fpos, fsize; + + /* Save current position */ + fpos = tell(fd); + + /* Go to end of file and get position */ + seek_io(fd, -1); + fsize = tell(fd); + + /* Go back to old position */ + seek_io(fd, 0); + seek_io(fd, fpos); + + return fsize; +} + +/* Load the first part the file and check if it's Linux */ +static uint32_t load_linux_header(struct linux_header *hdr) +{ + int load_high; + uint32_t kern_addr; + + if (read_io(fd, hdr, sizeof *hdr) != sizeof *hdr) { + debug("Can't read Linux header\n"); + return 0; + } + if (hdr->boot_sector_magic != 0xaa55) { + debug("Not a Linux kernel image\n"); + return 0; + } + + /* Linux is found. Print some information */ + if (memcmp(hdr->header_magic, "HdrS", 4) != 0) { + /* This may be floppy disk image or something. + * Perform a simple (incomplete) sanity check. */ + if (hdr->setup_sects >= 16 + || file_size() - (hdr->setup_sects<<9) >= 512<<10) { + debug("This looks like a bootdisk image but not like Linux...\n"); + return 0; + } + + printf("Possible very old Linux"); + /* This kernel does not even have a protocol version. + * Force the value. */ + hdr->protocol_version = 0; /* pre-2.00 */ + } else + printf("Found Linux"); + if (hdr->protocol_version >= 0x200 && hdr->kver_addr) { + char kver[256]; + seek_io(fd, hdr->kver_addr + 0x200); + if (read_io(fd, kver, sizeof kver) != 0) { + kver[255] = 0; + printf(" version %s", kver); + } + } + debug(" (protocol %#x)", hdr->protocol_version); + load_high = 0; + if (hdr->protocol_version >= 0x200) { + debug(" (loadflags %#x)", hdr->loadflags); + load_high = hdr->loadflags & 1; + } + if (load_high) { + printf(" bzImage"); + kern_addr = 0x100000; + } else { + printf(" zImage or Image"); + kern_addr = 0x1000; + } + printf(".\n"); + + return kern_addr; +} + +/* Set up parameters for 32-bit kernel */ +static void +init_linux_params(struct linux_params *params, struct linux_header *hdr) +{ + debug("Setting up paramters at %#lx\n", virt_to_phys(params)); + memset(params, 0, sizeof *params); + + /* Copy some useful values from header */ + params->mount_root_rdonly = hdr->root_flags; + params->orig_root_dev = hdr->root_dev; + + /* Video parameters. + * This assumes we have VGA in standard 80x25 text mode, + * just like our vga.c does. + * Cursor position is filled later to allow some more printf's. */ + params->orig_video_mode = 3; + params->orig_video_cols = 80; + params->orig_video_lines = 25; + params->orig_video_isVGA = 1; + params->orig_video_points = 16; + + params->loader_type = 0xff; /* Unregistered Linux loader */ +} + +/* Memory map */ +static void +set_memory_size(struct linux_params *params, struct sys_info *info) +{ + int i; + uint64_t end; + uint32_t ramtop = 0; + struct e820entry *linux_map; + struct memrange *filo_map; + + linux_map = params->e820_map; + filo_map = info->memrange; + for (i = 0; i < info->n_memranges; i++, linux_map++, filo_map++) { + if (i < E820MAX) { + /* Convert to BIOS e820 style */ + linux_map->addr = filo_map->base; + linux_map->size = filo_map->size; + linux_map->type = E820_RAM; + debug("%016Lx - %016Lx\n", linux_map->addr, + linux_map->addr + linux_map->size); + params->e820_map_nr = i+1; + } + + /* Find out top of RAM. XXX This ignores hole above 1MB */ + end = filo_map->base + filo_map->size; + if (end < (1ULL << 32)) { /* don't count memory above 4GB */ + if (end > ramtop) + ramtop = (uint32_t) end; + } + } + debug("ramtop=%#x\n", ramtop); + /* Size of memory above 1MB in KB */ + params->alt_mem_k = (ramtop - (1<<20)) >> 10; + /* old style, 64MB max */ + if (ramtop >= (64<<20)) + params->ext_mem_k = (63<<10); + else + params->ext_mem_k = params->alt_mem_k; + debug("ext_mem_k=%d, alt_mem_k=%d\n", params->ext_mem_k, params->alt_mem_k); +} + +/* + * Parse command line + * Some parameters, like initrd=<file>, are not passed to kernel, + * we are responsible to process them. + * Parameters for kernel are copied to kern_cmdline. Returns name of initrd. + */ +static char *parse_command_line(const char *orig_cmdline, char *kern_cmdline) +{ + const char *start, *sep, *end, *val; + char name[64]; + unsigned long len; + int k_len; + int to_kern; + char *initrd = NULL; + int toolong = 0; + + forced_memsize = 0; + + if (!orig_cmdline) { + *kern_cmdline = '\0'; + return NULL; + } + + k_len = 0; + debug("original command line: \"%s\"\n", orig_cmdline); + debug("kernel command line at %#lx\n", virt_to_phys(kern_cmdline)); + + start = orig_cmdline; + while (*start == ' ') + start++; + while (*start) { + end = strchr(start, ' '); + if (!end) + end = start + strlen(start); + sep = strchr(start, '='); + if (!sep || sep > end) + sep = end; + len = sep - start; + if (len >= sizeof(name)) + len = sizeof(name) - 1; + memcpy(name, start, len); + name[len] = 0; + + if (*sep == '=') { + val = sep + 1; + len = end - val; + } else { + val = NULL; + len = 0; + } + + /* Only initrd= and mem= are handled here. vga= is not, + * which I believe is a paramter to the realmode part of Linux, + * which we don't execute. */ + if (strcmp(name, "initrd") == 0) { + if (!val) + printf("Missing filename to initrd parameter\n"); + else { + initrd = malloc(len + 1); + memcpy(initrd, val, len); + initrd[len] = 0; + debug("initrd=%s\n", initrd); + } + /* Don't pass this to kernel */ + to_kern = 0; + } else if (strcmp(name, "mem") == 0) { + if (!val) + printf("Missing value for mem parameter\n"); + else { + forced_memsize = strtoull_with_suffix(val, (char**)&val, 0); + if (forced_memsize == 0) + printf("Invalid mem option, ignored\n"); + if (val != end) { + printf("Garbage after mem=<size>, ignored\n"); + forced_memsize = 0; + } + debug("mem=%llu\n", (unsigned long long)forced_memsize); + } + /* mem= is for both loader and kernel */ + to_kern = 1; + } else + to_kern = 1; + + if (to_kern) { + /* Copy to kernel command line buffer */ + if (k_len != 0) + kern_cmdline[k_len++] = ' '; /* put separator */ + len = end - start; + if (k_len + len >= COMMAND_LINE_SIZE) { + len = COMMAND_LINE_SIZE - k_len - 1; + if (!toolong) { + printf("Kernel command line is too long; truncated to " + "%d bytes\n", COMMAND_LINE_SIZE-1); + toolong = 1; + } + } + memcpy(kern_cmdline + k_len, start, len); + k_len += len; + } + + start = end; + while (*start == ' ') + start++; + } + kern_cmdline[k_len] = 0; + debug("kernel command line (%d bytes): \"%s\"\n", k_len, kern_cmdline); + + return initrd; +} + +/* Set command line location */ +static void set_command_line_loc(struct linux_params *params, + struct linux_header *hdr) +{ + if (hdr->protocol_version >= 0x202) { + /* new style */ + params->cmd_line_ptr = COMMAND_LINE_LOC; + } else { + /* old style */ + params->cl_magic = CL_MAGIC_VALUE; + params->cl_offset = COMMAND_LINE_LOC - LINUX_PARAM_LOC; + } +} + +/* Load 32-bit part of kernel */ +static int load_linux_kernel(struct linux_header *hdr, uint32_t kern_addr) +{ + uint32_t kern_offset, kern_size; + + if (hdr->setup_sects == 0) + hdr->setup_sects = 4; + kern_offset = (hdr->setup_sects + 1) * 512; + seek_io(fd, kern_offset); + kern_size = file_size() - kern_offset; + debug("offset=%#x addr=%#x size=%#x\n", kern_offset, kern_addr, kern_size); + +#if 0 + if (using_devsize) { + printf("Attempt to load up to end of device as kernel; " + "specify the image size\n"); + return 0; + } +#endif + + printf("Loading kernel... "); + if ((uint32_t)read_io(fd, phys_to_virt(kern_addr), kern_size) != kern_size) { + printf("Can't read kernel\n"); + return 0; + } + printf("ok\n"); + + return kern_size; +} + +static int load_initrd(struct linux_header *hdr, uint32_t kern_end, + struct linux_params *params, const char *initrd_file) +{ + uint32_t max; + uint32_t start, end, size; + uint64_t forced; + + fd = open_io(initrd_file); + if (fd == -1) { + printf("Can't open initrd: %s\n", initrd_file); + return -1; + } + +#if 0 + if (using_devsize) { + printf("Attempt to load up to end of device as initrd; " + "specify the image size\n"); + return -1; + } +#endif + + size = file_size(); + + + /* Find out the kernel's restriction on how high the initrd can be + * placed */ + if (hdr->protocol_version >= 0x203) + max = hdr->initrd_addr_max; + else + max = 0x38000000; /* Hardcoded value for older kernels */ + + /* FILO itself is at the top of RAM. (relocated) + * So, try putting initrd just below us. */ + end = virt_to_phys(_start); + if (end > max) + end = max; + + /* If "mem=" option is given, we have to put the initrd within + * the specified range. */ + if (forced_memsize) { + forced = forced_memsize; + if (forced > max) + forced = max; + /* If the "mem=" is lower, it's easy */ + if (forced <= end) + end = forced; + else { + /* Otherwise, see if we can put it above us */ + if (virt_to_phys(_end) + size <= forced) + end = forced; /* Ok */ + } + } + + start = end - size; + start &= ~0xfff; /* page align */ + end = start + size; + + debug("start=%#x end=%#x\n", start, end); + + if (start < kern_end) { + printf("Initrd is too big to fit in memory\n"); + return -1; + } + + printf("Loading initrd... "); + if ((uint32_t)read_io(fd, phys_to_virt(start), size) != size) { + printf("Can't read initrd\n"); + return -1; + } + printf("ok\n"); + + params->initrd_start = start; + params->initrd_size = size; + + close_io(fd); + + return 0; +} + +static void hardware_setup(void) +{ + /* Disable nmi */ + outb(0x80, 0x70); + + /* Make sure any coprocessor is properly reset.. */ + outb(0, 0xf0); + outb(0, 0xf1); + + /* we're getting screwed again and again by this problem of the 8259. + * so we're going to leave this lying around for inclusion into + * crt0.S on an as-needed basis. + * + * well, that went ok, I hope. Now we have to reprogram the interrupts :-( + * we put them right after the intel-reserved hardware interrupts, at + * int 0x20-0x2F. There they won't mess up anything. Sadly IBM really + * messed this up with the original PC, and they haven't been able to + * rectify it afterwards. Thus the bios puts interrupts at 0x08-0x0f, + * which is used for the internal hardware interrupts as well. We just + * have to reprogram the 8259's, and it isn't fun. + */ + + outb(0x11, 0x20); /* initialization sequence to 8259A-1 */ + outb(0x11, 0xA0); /* and to 8259A-2 */ + + outb(0x20, 0x21); /* start of hardware int's (0x20) */ + outb(0x28, 0xA1); /* start of hardware int's 2 (0x28) */ + + outb(0x04, 0x21); /* 8259-1 is master */ + outb(0x02, 0xA1); /* 8259-2 is slave */ + + outb(0x01, 0x21); /* 8086 mode for both */ + outb(0x01, 0xA1); + + outb(0xFF, 0xA1); /* mask off all interrupts for now */ + outb(0xFB, 0x21); /* mask all irq's but irq2 which is cascaded */ +} + +/* Start Linux */ +static int start_linux(uint32_t kern_addr) +{ + struct context *ctx; + //extern int cursor_x, cursor_y; + + ctx = init_context(phys_to_virt(STACK_LOC), 4096, 0); + + /* Entry point */ + ctx->pc = kern_addr; + ctx->npc = kern_addr + 4; + + debug("pc=%#x\n", kern_addr); + printf("Jumping to entry point...\n"); + +#ifdef VGA_CONSOLE + /* Update VGA cursor position. + * This must be here because the printf changes the value! */ + params->orig_x = cursor_x; + params->orig_y = cursor_y; +#endif + + /* Go... */ + ctx = switch_to(ctx); + + /* It's impossible but... */ + printf("Returned with o0=%#llx\n", ctx->regs[REG_O0]); + + return ctx->regs[REG_O0]; +} + +int linux_load(struct sys_info *info, const char *file, const char *cmdline) +{ + struct linux_header hdr; + struct linux_params *params; + uint32_t kern_addr, kern_size; + char *initrd_file = NULL; + + fd = open_io(file); + if (fd == -1) + return -1; + + kern_addr = load_linux_header(&hdr); + if (kern_addr == 0) { + close_io(fd); + return LOADER_NOT_SUPPORT; + } + + debug("[sparc64] Booting kernel '%s' ", file); + if (cmdline) + debug("with parameters '%s'\n", cmdline); + else + debug("without parameters.\n"); + + params = phys_to_virt(LINUX_PARAM_LOC); + init_linux_params(params, &hdr); + set_memory_size(params, info); + initrd_file = parse_command_line(cmdline, phys_to_virt(COMMAND_LINE_LOC)); + set_command_line_loc(params, &hdr); + + kern_size = load_linux_kernel(&hdr, kern_addr); + if (kern_size == 0) { + if (initrd_file) + free(initrd_file); + return -1; + } + + if (initrd_file) { + if (load_initrd(&hdr, kern_addr+kern_size, params, initrd_file) + != 0) { + free(initrd_file); + return -1; + } + free(initrd_file); + } + + hardware_setup(); + + start_linux(kern_addr); + return 0; +} diff --git a/qemu/roms/openbios/arch/sparc64/lsu.h b/qemu/roms/openbios/arch/sparc64/lsu.h new file mode 100644 index 000000000..d85c33f24 --- /dev/null +++ b/qemu/roms/openbios/arch/sparc64/lsu.h @@ -0,0 +1,20 @@ +/* $Id: lsu.h,v 1.2 1997/04/04 00:50:22 davem Exp $ */ +#ifndef _SPARC64_LSU_H +#define _SPARC64_LSU_H + +#include "const.h" + +/* LSU Control Register */ +#define LSU_CONTROL_PM _AC(0x000001fe00000000,UL) /* Phys-watchpoint byte mask*/ +#define LSU_CONTROL_VM _AC(0x00000001fe000000,UL) /* Virt-watchpoint byte mask*/ +#define LSU_CONTROL_PR _AC(0x0000000001000000,UL) /* Phys-rd watchpoint enable*/ +#define LSU_CONTROL_PW _AC(0x0000000000800000,UL) /* Phys-wr watchpoint enable*/ +#define LSU_CONTROL_VR _AC(0x0000000000400000,UL) /* Virt-rd watchpoint enable*/ +#define LSU_CONTROL_VW _AC(0x0000000000200000,UL) /* Virt-wr watchpoint enable*/ +#define LSU_CONTROL_FM _AC(0x00000000000ffff0,UL) /* Parity mask enables. */ +#define LSU_CONTROL_DM _AC(0x0000000000000008,UL) /* Data MMU enable. */ +#define LSU_CONTROL_IM _AC(0x0000000000000004,UL) /* Instruction MMU enable. */ +#define LSU_CONTROL_DC _AC(0x0000000000000002,UL) /* Data cache enable. */ +#define LSU_CONTROL_IC _AC(0x0000000000000001,UL) /* Instruction cache enable.*/ + +#endif /* !(_SPARC64_LSU_H) */ diff --git a/qemu/roms/openbios/arch/sparc64/multiboot.c b/qemu/roms/openbios/arch/sparc64/multiboot.c new file mode 100644 index 000000000..8514ca0a4 --- /dev/null +++ b/qemu/roms/openbios/arch/sparc64/multiboot.c @@ -0,0 +1,125 @@ +/* Support for Multiboot */ + +#include "config.h" +#include "asm/io.h" +#include "libopenbios/sys_info.h" +#include "multiboot.h" + +#define printf printk +#ifdef CONFIG_DEBUG_BOOT +#define debug printk +#else +#define debug(x...) +#endif + +struct mbheader { + unsigned int magic, flags, checksum; +}; +const struct mbheader multiboot_header + __attribute__((section (".hdr"))) = +{ + MULTIBOOT_HEADER_MAGIC, + MULTIBOOT_HEADER_FLAGS, + -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS) +}; + +/* Multiboot information structure, provided by loader to us */ + +struct multiboot_mmap { + unsigned entry_size; + unsigned base_lo, base_hi; + unsigned size_lo, size_hi; + unsigned type; +}; + +#define MULTIBOOT_MEM_VALID 0x01 +#define MULTIBOOT_BOOT_DEV_VALID 0x02 +#define MULTIBOOT_CMDLINE_VALID 0x04 +#define MULTIBOOT_MODS_VALID 0x08 +#define MULTIBOOT_AOUT_SYMS_VALID 0x10 +#define MULTIBOOT_ELF_SYMS_VALID 0x20 +#define MULTIBOOT_MMAP_VALID 0x40 + +void collect_multiboot_info(struct sys_info *info); +void collect_multiboot_info(struct sys_info *info) +{ + struct multiboot_info *mbinfo; + struct multiboot_mmap *mbmem; + unsigned mbcount, mbaddr; + unsigned int i; + struct memrange *mmap; + int mmap_count; + module_t *mod; + + if (info->boot_type != 0x2BADB002) + return; + + debug("Using Multiboot information at %#lx\n", info->boot_data); + + mbinfo = phys_to_virt(info->boot_data); + + if (mbinfo->mods_count != 1) { + printf("Multiboot: no dictionary\n"); + return; + } + + mod = (module_t *) mbinfo->mods_addr; + info->dict_start=(unsigned long *)mod->mod_start; + info->dict_end=(unsigned long *)mod->mod_end; + + if (mbinfo->flags & MULTIBOOT_MMAP_VALID) { + /* convert mmap records */ + mbmem = phys_to_virt(mbinfo->mmap_addr); + mbcount = mbinfo->mmap_length / (mbmem->entry_size + 4); + mmap = malloc(mbcount * sizeof(struct memrange)); + mmap_count = 0; + mbaddr = mbinfo->mmap_addr; + for (i = 0; i < mbcount; i++) { + mbmem = phys_to_virt(mbaddr); + debug("%08x%08x %08x%08x (%d)\n", + mbmem->base_hi, + mbmem->base_lo, + mbmem->size_hi, + mbmem->size_lo, + mbmem->type); + if (mbmem->type == 1) { /* Only normal RAM */ + mmap[mmap_count].base = mbmem->base_lo + + (((unsigned long long) mbmem->base_hi) << 32); + mmap[mmap_count].size = mbmem->size_lo + + (((unsigned long long) mbmem->size_hi) << 32); + mmap_count++; + } + mbaddr += mbmem->entry_size + 4; + if (mbaddr >= mbinfo->mmap_addr + mbinfo->mmap_length) + break; + } + /* simple sanity check - there should be at least 2 RAM segments + * (base 640k and extended) */ + if (mmap_count >= 2) + goto got_it; + + printf("Multiboot mmap is broken\n"); + free(mmap); + /* fall back to mem_lower/mem_upper */ + } + + if (mbinfo->flags & MULTIBOOT_MEM_VALID) { + /* use mem_lower and mem_upper */ + mmap_count = 2; + mmap = malloc(2 * sizeof(*mmap)); + mmap[0].base = 0; + mmap[0].size = mbinfo->mem_lower << 10; + mmap[1].base = 1 << 20; /* 1MB */ + mmap[1].size = mbinfo->mem_upper << 10; + goto got_it; + } + + printf("Can't get memory information from Multiboot\n"); + return; + +got_it: + info->memrange = mmap; + info->n_memranges = mmap_count; + + return; +} diff --git a/qemu/roms/openbios/arch/sparc64/multiboot.h b/qemu/roms/openbios/arch/sparc64/multiboot.h new file mode 100644 index 000000000..17cf202ec --- /dev/null +++ b/qemu/roms/openbios/arch/sparc64/multiboot.h @@ -0,0 +1,96 @@ +/* multiboot.h + * tag: header for multiboot + * + * Copyright (C) 2003-2004 Stefan Reinauer + * + * See the file "COPYING" for further information about + * the copyright and warranty status of this work. + */ + +/* magic number for multiboot header */ +#define MULTIBOOT_HEADER_MAGIC 0x1BADB002 + +/* flags for multiboot header */ +#define MULTIBOOT_HEADER_FLAGS 0x00010003 + +/* magic number passed by multiboot-compliant boot loader. */ +#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002 + +/* The size of our stack (8KB). */ +#define STACK_SIZE 0x2000 + +/* C symbol format. HAVE_ASM_USCORE is defined by configure. */ +#ifdef HAVE_ASM_USCORE +# define EXT_C(sym) _ ## sym +#else +# define EXT_C(sym) sym +#endif + +#ifndef ASM +/* We don't want these declarations in boot.S */ + +/* multiboot header */ +typedef struct multiboot_header { + unsigned long magic; + unsigned long flags; + unsigned long checksum; + unsigned long header_addr; + unsigned long load_addr; + unsigned long load_end_addr; + unsigned long bss_end_addr; + unsigned long entry_addr; +} multiboot_header_t; + +/* symbol table for a.out */ +typedef struct aout_symbol_table { + unsigned long tabsize; + unsigned long strsize; + unsigned long addr; + unsigned long reserved; +} aout_symbol_table_t; + +/* section header table for ELF */ +typedef struct elf_section_header_table { + unsigned long num; + unsigned long size; + unsigned long addr; + unsigned long shndx; +} elf_section_header_table_t; + +/* multiboot information */ +typedef struct multiboot_info { + unsigned long flags; + unsigned long mem_lower; + unsigned long mem_upper; + unsigned long boot_device; + unsigned long cmdline; + unsigned long mods_count; + unsigned long mods_addr; + union { + aout_symbol_table_t aout_sym; + elf_section_header_table_t elf_sec; + } u; + unsigned long mmap_length; + unsigned long mmap_addr; +} multiboot_info_t; + +/* module structure */ +typedef struct module { + unsigned long mod_start; + unsigned long mod_end; + unsigned long string; + unsigned long reserved; +} module_t; + +/* memory map. Be careful that the offset 0 is base_addr_low + but no size. */ +typedef struct memory_map { + unsigned long size; + unsigned long base_addr_low; + unsigned long base_addr_high; + unsigned long length_low; + unsigned long length_high; + unsigned long type; +} memory_map_t; + +#endif /* ! ASM */ diff --git a/qemu/roms/openbios/arch/sparc64/ofmem_sparc64.c b/qemu/roms/openbios/arch/sparc64/ofmem_sparc64.c new file mode 100644 index 000000000..bdfaf5636 --- /dev/null +++ b/qemu/roms/openbios/arch/sparc64/ofmem_sparc64.c @@ -0,0 +1,381 @@ +/* + * <ofmem_sparc64.c> + * + * OF Memory manager + * + * Copyright (C) 1999-2004 Samuel Rydh (samuel@ibrium.se) + * Copyright (C) 2004 Stefan Reinauer + * + * 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 + * + */ + +#include "config.h" +#include "libopenbios/bindings.h" +#include "libc/string.h" +#include "arch/sparc64/ofmem_sparc64.h" +#include "spitfire.h" + +#define OF_MALLOC_BASE ((char*)OFMEM + ALIGN_SIZE(sizeof(ofmem_t), 8)) + +#define MEMSIZE (128 * 1024) +static union { + char memory[MEMSIZE]; + ofmem_t ofmem; +} s_ofmem_data; + +#define OFMEM (&s_ofmem_data.ofmem) +#define TOP_OF_RAM (s_ofmem_data.memory + MEMSIZE) + +static retain_t s_retained; +translation_t **g_ofmem_translations = &s_ofmem_data.ofmem.trans; + +ucell *va2ttedata = 0; +extern uint64_t qemu_mem_size; + +static inline size_t ALIGN_SIZE(size_t x, size_t a) +{ + return (x + a - 1) & ~(a-1); +} + +static ucell get_heap_top( void ) +{ + return (ucell)TOP_OF_RAM; +} + +ofmem_t* ofmem_arch_get_private(void) +{ + return OFMEM; +} + +void* ofmem_arch_get_malloc_base(void) +{ + return OF_MALLOC_BASE; +} + +ucell ofmem_arch_get_heap_top(void) +{ + return get_heap_top(); +} + +ucell ofmem_arch_get_virt_top(void) +{ + return (ucell)TOP_OF_RAM; +} + +ucell ofmem_arch_get_iomem_base(void) +{ + /* Currently unused */ + return 0; +} + +ucell ofmem_arch_get_iomem_top(void) +{ + /* Currently unused */ + return 0; +} + +retain_t *ofmem_arch_get_retained(void) +{ + return (&s_retained); +} + +int ofmem_arch_get_translation_entry_size(void) +{ + /* Return size of a single MMU package translation property entry in cells */ + return 3; +} + +void ofmem_arch_create_translation_entry(ucell *transentry, translation_t *t) +{ + /* Generate translation property entry for SPARC. While there is no + formal documentation for this, both Linux kernel and OpenSolaris sources + expect a translation property entry to have the following layout: + + virtual address + length + mode (valid TTE for start of translation region) + */ + + transentry[0] = t->virt; + transentry[1] = t->size; + transentry[2] = t->phys | t->mode | SPITFIRE_TTE_VALID; +} + +/* Return the size of a memory available entry given the phandle in cells */ +int ofmem_arch_get_available_entry_size(phandle_t ph) +{ + if (ph == s_phandle_memory) { + return 1 + ofmem_arch_get_physaddr_cellsize(); + } else { + return 1 + 1; + } +} + +/* Generate memory available property entry for Sparc64 */ +void ofmem_arch_create_available_entry(phandle_t ph, ucell *availentry, phys_addr_t start, ucell size) +{ + int i = 0; + + if (ph == s_phandle_memory) { + i += ofmem_arch_encode_physaddr(availentry, start); + } else { + availentry[i++] = start; + } + + availentry[i] = size; +} + +/* Unmap a set of pages */ +void ofmem_arch_unmap_pages(ucell virt, ucell size) +{ + ucell va; + + /* align address to 8k */ + virt &= ~PAGE_MASK_8K; + + /* align size to 8k */ + size = (size + PAGE_MASK_8K) & ~PAGE_MASK_8K; + + for (va = virt; va < virt + size; va += PAGE_SIZE_8K) { + itlb_demap(va); + dtlb_demap(va); + } +} + +/* Map a set of pages */ +void ofmem_arch_map_pages(phys_addr_t phys, ucell virt, ucell size, ucell mode) +{ + unsigned long tte_data, currsize; + + /* Install locked tlb entries now */ + if (mode & SPITFIRE_TTE_LOCKED) { + + /* aligned to 8k page */ + size = (size + PAGE_MASK_8K) & ~PAGE_MASK_8K; + + while (size > 0) { + currsize = size; + if (currsize >= PAGE_SIZE_4M && + (virt & PAGE_MASK_4M) == 0 && + (phys & PAGE_MASK_4M) == 0) { + currsize = PAGE_SIZE_4M; + tte_data = 6ULL << 60; + } else if (currsize >= PAGE_SIZE_512K && + (virt & PAGE_MASK_512K) == 0 && + (phys & PAGE_MASK_512K) == 0) { + currsize = PAGE_SIZE_512K; + tte_data = 4ULL << 60; + } else if (currsize >= PAGE_SIZE_64K && + (virt & PAGE_MASK_64K) == 0 && + (phys & PAGE_MASK_64K) == 0) { + currsize = PAGE_SIZE_64K; + tte_data = 2ULL << 60; + } else { + currsize = PAGE_SIZE_8K; + tte_data = 0; + } + + tte_data |= phys | mode | SPITFIRE_TTE_VALID; + + itlb_load2(virt, tte_data); + dtlb_load2(virt, tte_data); + + size -= currsize; + phys += currsize; + virt += currsize; + } + } +} + +/************************************************************************/ +/* misc */ +/************************************************************************/ + +int ofmem_arch_get_physaddr_cellsize(void) +{ + return 1; +} + +int ofmem_arch_encode_physaddr(ucell *p, phys_addr_t value) +{ + p[0] = value; + return 1; +} + +ucell ofmem_arch_default_translation_mode( phys_addr_t phys ) +{ + /* Writable, cacheable */ + /* Privileged and not locked */ + return SPITFIRE_TTE_CP | SPITFIRE_TTE_CV | SPITFIRE_TTE_WRITABLE | SPITFIRE_TTE_PRIVILEGED; +} + +ucell ofmem_arch_io_translation_mode( phys_addr_t phys ) +{ + /* Writable, privileged and not locked */ + return SPITFIRE_TTE_CV | SPITFIRE_TTE_WRITABLE | SPITFIRE_TTE_PRIVILEGED; +} + +/* Architecture-specific OFMEM helpers */ +unsigned long +find_tte(unsigned long va) +{ + translation_t *t = *g_ofmem_translations; + unsigned long tte_data; + + /* Search the ofmem linked list for this virtual address */ + while (t != NULL) { + /* Find the correct range */ + if (va >= t->virt && va < (t->virt + t->size)) { + + /* valid tte, 8k size */ + tte_data = SPITFIRE_TTE_VALID; + + /* mix in phys address mode */ + tte_data |= t->mode; + + /* mix in page physical address = t->phys + offset */ + tte_data |= t->phys + (va - t->virt); + + /* return tte_data */ + return tte_data; + } + t = t->next; + } + + /* Couldn't find tte */ + return -1; +} + +/* ITLB handlers */ +void +itlb_load2(unsigned long vaddr, unsigned long tte_data) +{ + asm("stxa %0, [%1] %2\n" + "stxa %3, [%%g0] %4\n" + : : "r" (vaddr), "r" (48), "i" (ASI_IMMU), + "r" (tte_data), "i" (ASI_ITLB_DATA_IN)); +} + +void +itlb_load3(unsigned long vaddr, unsigned long tte_data, + unsigned long tte_index) +{ + asm("stxa %0, [%1] %2\n" + "stxa %3, [%4] %5\n" + : : "r" (vaddr), "r" (48), "i" (ASI_IMMU), + "r" (tte_data), "r" (tte_index << 3), "i" (ASI_ITLB_DATA_ACCESS)); +} + +unsigned long +itlb_faultva(void) +{ + unsigned long faultva; + + asm("ldxa [%1] %2, %0\n" + : "=r" (faultva) + : "r" (48), "i" (ASI_IMMU)); + + return faultva; +} + +void +itlb_demap(unsigned long vaddr) +{ + asm("stxa %0, [%0] %1\n" + : : "r" (vaddr), "i" (ASI_IMMU_DEMAP)); +} + +/* DTLB handlers */ +void +dtlb_load2(unsigned long vaddr, unsigned long tte_data) +{ + asm("stxa %0, [%1] %2\n" + "stxa %3, [%%g0] %4\n" + : : "r" (vaddr), "r" (48), "i" (ASI_DMMU), + "r" (tte_data), "i" (ASI_DTLB_DATA_IN)); +} + +void +dtlb_load3(unsigned long vaddr, unsigned long tte_data, + unsigned long tte_index) +{ + asm("stxa %0, [%1] %2\n" + "stxa %3, [%4] %5\n" + : : "r" (vaddr), "r" (48), "i" (ASI_DMMU), + "r" (tte_data), "r" (tte_index << 3), "i" (ASI_DTLB_DATA_ACCESS)); +} + +unsigned long +dtlb_faultva(void) +{ + unsigned long faultva; + + asm("ldxa [%1] %2, %0\n" + : "=r" (faultva) + : "r" (48), "i" (ASI_DMMU)); + + return faultva; +} + +void +dtlb_demap(unsigned long vaddr) +{ + asm("stxa %0, [%0] %1\n" + : : "r" (vaddr), "i" (ASI_DMMU_DEMAP)); +} + +/************************************************************************/ +/* init / cleanup */ +/************************************************************************/ + +static int remap_page_range( phys_addr_t phys, ucell virt, ucell size, ucell mode ) +{ + ofmem_claim_phys(phys, size, 0); + ofmem_claim_virt(virt, size, 0); + ofmem_map_page_range(phys, virt, size, mode); + if (!(mode & SPITFIRE_TTE_LOCKED)) { + OFMEM_TRACE("remap_page_range clearing translation " FMT_ucellx + " -> " FMT_ucellx " " FMT_ucellx " mode " FMT_ucellx "\n", + virt, phys, size, mode ); + ofmem_arch_unmap_pages(virt, size); + } + return 0; +} + +#define RETAIN_MAGIC 0x1100220033004400 + +void ofmem_init( void ) +{ + retain_t *retained = ofmem_arch_get_retained(); + int i; + + memset(&s_ofmem_data, 0, sizeof(s_ofmem_data)); + s_ofmem_data.ofmem.ramsize = qemu_mem_size; + + /* inherit translations set up by entry.S */ + ofmem_walk_boot_map(remap_page_range); + + /* Map the memory */ + ofmem_map_page_range(PAGE_SIZE, PAGE_SIZE, 0x800000, 0x36); + + if (!(retained->magic == RETAIN_MAGIC)) { + OFMEM_TRACE("ofmem_init: no retained magic found, creating\n"); + retained->magic = RETAIN_MAGIC; + retained->numentries = 0; + } else { + OFMEM_TRACE("ofmem_init: retained magic found, total %lld mappings\n", retained->numentries); + + /* Mark physical addresses as used so they are not reallocated */ + for (i = 0; i < retained->numentries; i++) { + ofmem_claim_phys(retained->retain_phys_range[i].start, + retained->retain_phys_range[i].size, 0); + } + + /* Reset retained area for next reset */ + retained->magic = RETAIN_MAGIC; + retained->numentries = 0; + } +} diff --git a/qemu/roms/openbios/arch/sparc64/openbios.c b/qemu/roms/openbios/arch/sparc64/openbios.c new file mode 100644 index 000000000..4557f7f9f --- /dev/null +++ b/qemu/roms/openbios/arch/sparc64/openbios.c @@ -0,0 +1,664 @@ +/* tag: openbios forth environment, executable code + * + * Copyright (C) 2003 Patrick Mauritz, Stefan Reinauer + * + * See the file "COPYING" for further information about + * the copyright and warranty status of this work. + */ + +#include "config.h" +#include "libopenbios/openbios.h" +#include "libopenbios/bindings.h" +#include "libopenbios/console.h" +#include "drivers/drivers.h" +#include "dict.h" +#include "arch/common/nvram.h" +#include "packages/nvram.h" +#include "libopenbios/sys_info.h" +#include "openbios.h" +#include "drivers/pci.h" +#include "asm/pci.h" +#include "boot.h" +#include "../../drivers/timer.h" // XXX +#define NO_QEMU_PROTOS +#include "arch/common/fw_cfg.h" +#include "arch/sparc64/ofmem_sparc64.h" +#include "spitfire.h" + +#define UUID_FMT "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x" + +#define APB_SPECIAL_BASE 0x1fe00000000ULL +#define APB_MEM_BASE 0x1ff00000000ULL + +#define MEMORY_SIZE (512*1024) /* 512K ram for hosted system */ + +// XXX +#define NVRAM_BASE 0x2000 +#define NVRAM_SIZE 0x2000 +#define NVRAM_IDPROM 0x1fd8 +#define NVRAM_IDPROM_SIZE 32 +#define NVRAM_OB_START (0) +#define NVRAM_OB_SIZE ((NVRAM_IDPROM - NVRAM_OB_START) & ~15) + +static uint8_t idprom[NVRAM_IDPROM_SIZE]; + +struct hwdef { + pci_arch_t pci; + uint16_t machine_id_low, machine_id_high; +}; + +static const struct hwdef hwdefs[] = { + { + .pci = { + .name = "SUNW,sabre", + .vendor_id = PCI_VENDOR_ID_SUN, + .device_id = PCI_DEVICE_ID_SUN_SABRE, + .cfg_addr = APB_SPECIAL_BASE + 0x1000000ULL, // PCI bus configuration space + .cfg_data = APB_MEM_BASE, // PCI bus memory space + .cfg_base = APB_SPECIAL_BASE, + .cfg_len = 0x2000000, + .host_pci_base = APB_MEM_BASE, + .pci_mem_base = 0x100000, /* avoid VGA at 0xa0000 */ + .mem_len = 0x10000000, + .io_base = APB_SPECIAL_BASE + 0x2000000ULL, // PCI Bus I/O space + .io_len = 0x10000, + .irqs = { 0, 1, 2, 3 }, + }, + .machine_id_low = 0, + .machine_id_high = 255, + }, +}; + +struct cpudef { + unsigned long iu_version; + const char *name; + unsigned long ecache_associativity; + unsigned long ecache_line_size; + unsigned long ecache_size; + unsigned long num_dtlb_entries; + unsigned long dcache_associativity; + unsigned long dcache_line_size; + unsigned long dcache_size; + unsigned long num_itlb_entries; + unsigned long icache_associativity; + unsigned long icache_line_size; + unsigned long icache_size; +}; + +/* + ( addr -- ? ) +*/ + +extern volatile uint64_t client_tba; + +static void +set_trap_table(void) +{ + unsigned long addr; + + addr = POP(); + + /* Update client_tba to be updated on CIF exit */ + client_tba = addr; +} + +/* Reset control register is defined in 17.2.7.3 of US IIi User Manual */ +static void +sparc64_reset_all(void) +{ + unsigned long addr = 0x1fe0000f020ULL; + unsigned long val = 1 << 29; + + asm("stxa %0, [%1] 0x15\n\t" + : : "r" (val), "r" (addr) : "memory"); +} + +/* PCI Target Address Space Register (see UltraSPARC IIi User's Manual + section 19.3.0.4) */ +#define PBM_PCI_TARGET_AS 0x2028 +#define PBM_PCI_TARGET_AS_CD_ENABLE 0x40 + +static void +sparc64_set_tas_register(unsigned long val) +{ + unsigned long addr = APB_SPECIAL_BASE + PBM_PCI_TARGET_AS; + + asm("stxa %0, [%1] 0x15\n\t" + : : "r" (val), "r" (addr) : "memory"); +} + +static void cpu_generic_init(const struct cpudef *cpu, uint32_t clock_frequency) +{ + unsigned long iu_version; + + push_str("/"); + fword("find-device"); + + fword("new-device"); + + push_str(cpu->name); + fword("device-name"); + + push_str("cpu"); + fword("device-type"); + + asm("rdpr %%ver, %0\n" + : "=r"(iu_version) :); + + PUSH((iu_version >> 48) & 0xff); + fword("encode-int"); + push_str("manufacturer#"); + fword("property"); + + PUSH((iu_version >> 32) & 0xff); + fword("encode-int"); + push_str("implementation#"); + fword("property"); + + PUSH((iu_version >> 24) & 0xff); + fword("encode-int"); + push_str("mask#"); + fword("property"); + + PUSH(9); + fword("encode-int"); + push_str("sparc-version"); + fword("property"); + + PUSH(0); + fword("encode-int"); + push_str("cpuid"); + fword("property"); + + PUSH(0); + fword("encode-int"); + push_str("upa-portid"); + fword("property"); + + PUSH(clock_frequency); + fword("encode-int"); + push_str("clock-frequency"); + fword("property"); + + PUSH(cpu->ecache_associativity); + fword("encode-int"); + push_str("ecache-associativity"); + fword("property"); + + PUSH(cpu->ecache_line_size); + fword("encode-int"); + push_str("ecache-line-size"); + fword("property"); + + PUSH(cpu->ecache_size); + fword("encode-int"); + push_str("ecache-size"); + fword("property"); + + PUSH(cpu->dcache_associativity); + fword("encode-int"); + push_str("dcache-associativity"); + fword("property"); + + PUSH(cpu->dcache_line_size); + fword("encode-int"); + push_str("dcache-line-size"); + fword("property"); + + PUSH(cpu->dcache_size); + fword("encode-int"); + push_str("dcache-size"); + fword("property"); + + PUSH(cpu->icache_associativity); + fword("encode-int"); + push_str("icache-associativity"); + fword("property"); + + PUSH(cpu->ecache_line_size); + fword("encode-int"); + push_str("icache-line-size"); + fword("property"); + + PUSH(cpu->ecache_size); + fword("encode-int"); + push_str("icache-size"); + fword("property"); + + PUSH(cpu->num_itlb_entries); + fword("encode-int"); + push_str("#itlb-entries"); + fword("property"); + + PUSH(cpu->num_dtlb_entries); + fword("encode-int"); + push_str("#dtlb-entries"); + fword("property"); + + fword("finish-device"); + + // Trap table + push_str("/openprom/client-services"); + fword("find-device"); + bind_func("SUNW,set-trap-table", set_trap_table); + + // Reset + bind_func("sparc64-reset-all", sparc64_reset_all); + push_str("' sparc64-reset-all to reset-all"); + fword("eval"); +} + +static const struct cpudef sparc_defs[] = { + { + .iu_version = (0x04ULL << 48) | (0x02ULL << 32), + .name = "FJSV,GP", + }, + { + .iu_version = (0x04ULL << 48) | (0x03ULL << 32), + .name = "FJSV,GPUSK", + }, + { + .iu_version = (0x04ULL << 48) | (0x04ULL << 32), + .name = "FJSV,GPUSC", + }, + { + .iu_version = (0x04ULL << 48) | (0x05ULL << 32), + .name = "FJSV,GPUZC", + }, + { + .iu_version = (0x17ULL << 48) | (0x10ULL << 32), + .name = "SUNW,UltraSPARC", + .ecache_associativity = 1, .ecache_line_size = 0x40, .ecache_size = 0x100000, + .dcache_associativity = 1, .dcache_line_size = 0x20, .dcache_size = 0x4000, + .icache_associativity = 2, .icache_line_size = 0x20, .icache_size = 0x4000, + .num_dtlb_entries = 0x40, .num_itlb_entries = 0x40, + }, + { + .iu_version = (0x17ULL << 48) | (0x11ULL << 32), + .name = "SUNW,UltraSPARC-II", + .ecache_associativity = 1, .ecache_line_size = 0x40, .ecache_size = 0x100000, + .dcache_associativity = 1, .dcache_line_size = 0x20, .dcache_size = 0x4000, + .icache_associativity = 2, .icache_line_size = 0x20, .icache_size = 0x4000, + .num_dtlb_entries = 0x40, .num_itlb_entries = 0x40, + }, + { + .iu_version = (0x17ULL << 48) | (0x12ULL << 32), + .name = "SUNW,UltraSPARC-IIi", + .ecache_associativity = 1, .ecache_line_size = 0x40, .ecache_size = 0x40000, + .dcache_associativity = 1, .dcache_line_size = 0x20, .dcache_size = 0x4000, + .icache_associativity = 2, .icache_line_size = 0x20, .icache_size = 0x4000, + .num_dtlb_entries = 0x40, .num_itlb_entries = 0x40, + }, + { + .iu_version = (0x17ULL << 48) | (0x13ULL << 32), + .name = "SUNW,UltraSPARC-IIe", + }, + { + .iu_version = (0x3eULL << 48) | (0x14ULL << 32), + .name = "SUNW,UltraSPARC-III", + }, + { + .iu_version = (0x3eULL << 48) | (0x15ULL << 32), + .name = "SUNW,UltraSPARC-III+", + }, + { + .iu_version = (0x3eULL << 48) | (0x16ULL << 32), + .name = "SUNW,UltraSPARC-IIIi", + }, + { + .iu_version = (0x3eULL << 48) | (0x18ULL << 32), + .name = "SUNW,UltraSPARC-IV", + }, + { + .iu_version = (0x3eULL << 48) | (0x19ULL << 32), + .name = "SUNW,UltraSPARC-IV+", + }, + { + .iu_version = (0x3eULL << 48) | (0x22ULL << 32), + .name = "SUNW,UltraSPARC-IIIi+", + }, + { + .iu_version = (0x3eULL << 48) | (0x23ULL << 32), + .name = "SUNW,UltraSPARC-T1", + }, + { + .iu_version = (0x3eULL << 48) | (0x24ULL << 32), + .name = "SUNW,UltraSPARC-T2", + }, + { + .iu_version = (0x22ULL << 48) | (0x10ULL << 32), + .name = "SUNW,UltraSPARC", + }, +}; + +static const struct cpudef * +id_cpu(void) +{ + unsigned long iu_version; + unsigned int i; + + asm("rdpr %%ver, %0\n" + : "=r"(iu_version) :); + iu_version &= 0xffffffff00000000ULL; + + for (i = 0; i < sizeof(sparc_defs)/sizeof(struct cpudef); i++) { + if (iu_version == sparc_defs[i].iu_version) + return &sparc_defs[i]; + } + printk("Unknown cpu (psr %lx), freezing!\n", iu_version); + for (;;); +} + +static void nvram_read(uint16_t offset, char *buf, unsigned int nbytes) +{ + unsigned int i; + + for (i = 0; i < nbytes; i++) { + buf[i] = inb(NVRAM_BASE + offset + i); + } +} + +static void nvram_write(uint16_t offset, const char *buf, unsigned int nbytes) +{ + unsigned int i; + + for (i = 0; i < nbytes; i++) { + outb(buf[i], NVRAM_BASE + offset + i); + } +} + +static uint8_t qemu_uuid[16]; + +void arch_nvram_get(char *data) +{ + char *obio_cmdline; + uint32_t size = 0; + const struct cpudef *cpu; + char buf[256]; + uint32_t temp; + uint64_t ram_size; + uint32_t clock_frequency; + uint16_t machine_id; + const char *stdin_path, *stdout_path; + + fw_cfg_init(); + + fw_cfg_read(FW_CFG_SIGNATURE, buf, 4); + buf[4] = '\0'; + + printk("Configuration device id %s", buf); + + temp = fw_cfg_read_i32(FW_CFG_ID); + machine_id = fw_cfg_read_i16(FW_CFG_MACHINE_ID); + + printk(" version %d machine id %d\n", temp, machine_id); + + if (temp != 1) { + printk("Incompatible configuration device version, freezing\n"); + for(;;); + } + + kernel_size = fw_cfg_read_i32(FW_CFG_KERNEL_SIZE); + if (kernel_size) + kernel_image = fw_cfg_read_i64(FW_CFG_KERNEL_ADDR); + + size = fw_cfg_read_i32(FW_CFG_CMDLINE_SIZE); + if (size) { + obio_cmdline = (char *)malloc(size + 1); + fw_cfg_read(FW_CFG_CMDLINE_DATA, obio_cmdline, size); + obio_cmdline[size] = '\0'; + } else { + obio_cmdline = strdup(""); + } + qemu_cmdline = (uint64_t)obio_cmdline; + cmdline_size = size; + boot_device = fw_cfg_read_i16(FW_CFG_BOOT_DEVICE); + + if (kernel_size) + printk("kernel addr %llx size %llx\n", kernel_image, kernel_size); + if (size) + printk("kernel cmdline %s\n", obio_cmdline); + + nvram_read(NVRAM_OB_START, data, NVRAM_OB_SIZE); + + temp = fw_cfg_read_i32(FW_CFG_NB_CPUS); + + printk("CPUs: %x", temp); + + clock_frequency = 100000000; + + cpu = id_cpu(); + //cpu->initfn(); + cpu_generic_init(cpu, clock_frequency); + printk(" x %s\n", cpu->name); + + // Add /uuid + fw_cfg_read(FW_CFG_UUID, (char *)qemu_uuid, 16); + + printk("UUID: " UUID_FMT "\n", qemu_uuid[0], qemu_uuid[1], qemu_uuid[2], + qemu_uuid[3], qemu_uuid[4], qemu_uuid[5], qemu_uuid[6], + qemu_uuid[7], qemu_uuid[8], qemu_uuid[9], qemu_uuid[10], + qemu_uuid[11], qemu_uuid[12], qemu_uuid[13], qemu_uuid[14], + qemu_uuid[15]); + + push_str("/"); + fword("find-device"); + + PUSH((long)&qemu_uuid); + PUSH(16); + fword("encode-bytes"); + push_str("uuid"); + fword("property"); + + // Add /idprom + nvram_read(NVRAM_IDPROM, (char *)idprom, NVRAM_IDPROM_SIZE); + + PUSH((long)&idprom); + PUSH(32); + fword("encode-bytes"); + push_str("idprom"); + fword("property"); + + PUSH(500 * 1000 * 1000); + fword("encode-int"); + push_str("clock-frequency"); + fword("property"); + + ram_size = fw_cfg_read_i64(FW_CFG_RAM_SIZE); + + ob_mmu_init(cpu->name, ram_size); + + /* Setup nvram variables */ + push_str("/options"); + fword("find-device"); + + switch (boot_device) { + case 'a': + push_str("/obio/SUNW,fdtwo"); + break; + case 'c': + push_str("disk:a"); + break; + default: + case 'd': + push_str("cdrom:f cdrom"); + break; + case 'n': + push_str("net"); + break; + } + + fword("encode-string"); + push_str("boot-device"); + fword("property"); + + push_str(obio_cmdline); + fword("encode-string"); + push_str("boot-file"); + fword("property"); + + /* Set up other properties */ + push_str("/chosen"); + fword("find-device"); + + if (fw_cfg_read_i16(FW_CFG_NOGRAPHIC)) { + stdin_path = stdout_path = "ttya"; + } else { + stdin_path = "keyboard"; + stdout_path = "screen"; + } + + push_str(stdin_path); + push_str("input-device"); + fword("$setenv"); + + push_str(stdout_path); + push_str("output-device"); + fword("$setenv"); +} + +void arch_nvram_put(char *data) +{ + nvram_write(0, data, NVRAM_OB_SIZE); +} + +int arch_nvram_size(void) +{ + return NVRAM_OB_SIZE; +} + +void setup_timers(void) +{ +} + +void udelay(unsigned int usecs) +{ + volatile int i; + + for (i = 0; i < usecs * 100; i++); +} + +static void init_memory(void) +{ + phys_addr_t phys; + ucell virt; + + /* Claim the memory from OFMEM (align to 512K so we only take 1 TLB slot) */ + phys = ofmem_claim_phys(-1, MEMORY_SIZE, PAGE_SIZE_512K); + if (!phys) + printk("panic: not enough physical memory on host system.\n"); + + virt = ofmem_claim_virt(-1, MEMORY_SIZE, PAGE_SIZE_512K); + if (!virt) + printk("panic: not enough virtual memory on host system.\n"); + + /* Generate the mapping (and lock translation into the TLBs) */ + ofmem_map(phys, virt, MEMORY_SIZE, ofmem_arch_default_translation_mode(phys) | SPITFIRE_TTE_LOCKED); + + /* we push start and end of memory to the stack + * so that it can be used by the forth word QUIT + * to initialize the memory allocator + */ + + PUSH(virt); + PUSH(virt + MEMORY_SIZE); +} + +extern volatile uint64_t *obp_ticks_pointer; + +static void +arch_init( void ) +{ + openbios_init(); + modules_init(); +#ifdef CONFIG_DRIVER_PCI + ob_pci_init(); + + /* Set TAS register to match the virtual-dma properties + set during sabre configure */ + sparc64_set_tas_register(PBM_PCI_TARGET_AS_CD_ENABLE); +#endif + nvconf_init(); + device_end(); + + /* Point to the Forth obp-ticks variable */ + fword("obp-ticks"); + obp_ticks_pointer = cell2pointer(POP()); + + bind_func("platform-boot", boot ); + bind_func("(go)", go); +} + +unsigned long isa_io_base; + +extern struct _console_ops arch_console_ops; + +int openbios(void) +{ + unsigned int i; + uint16_t machine_id; + const struct hwdef *hwdef = NULL; + + + for (i = 0; i < sizeof(hwdefs) / sizeof(struct hwdef); i++) { + isa_io_base = hwdefs[i].pci.io_base; + machine_id = fw_cfg_read_i16(FW_CFG_MACHINE_ID); + if (hwdefs[i].machine_id_low <= machine_id && + hwdefs[i].machine_id_high >= machine_id) { + hwdef = &hwdefs[i]; + arch = &hwdefs[i].pci; + break; + } + } + if (!hwdef) + for(;;); // Internal inconsistency, hang + +#ifdef CONFIG_DEBUG_CONSOLE + init_console(arch_console_ops); +#ifdef CONFIG_DEBUG_CONSOLE_SERIAL + uart_init(CONFIG_SERIAL_PORT, CONFIG_SERIAL_SPEED); +#endif + printk("OpenBIOS for Sparc64\n"); +#endif + + ofmem_init(); + + collect_sys_info(&sys_info); + + dict = (unsigned char *)sys_info.dict_start; + dicthead = (cell)sys_info.dict_end; + last = sys_info.dict_last; + dictlimit = sys_info.dict_limit; + + forth_init(); + +#ifdef CONFIG_DEBUG_BOOT + printk("forth started.\n"); + printk("initializing memory..."); +#endif + + init_memory(); + +#ifdef CONFIG_DEBUG_BOOT + printk("done\n"); +#endif + + PUSH_xt( bind_noname_func(arch_init) ); + fword("PREPOST-initializer"); + + PC = (ucell)findword("initialize-of"); + + if (!PC) { + printk("panic: no dictionary entry point.\n"); + return -1; + } +#ifdef CONFIG_DEBUG_DICTIONARY + printk("done (%d bytes).\n", dicthead); + printk("Jumping to dictionary...\n"); +#endif + + enterforth((xt_t)PC); + printk("falling off...\n"); + free(dict); + return 0; +} diff --git a/qemu/roms/openbios/arch/sparc64/openbios.h b/qemu/roms/openbios/arch/sparc64/openbios.h new file mode 100644 index 000000000..2146300d9 --- /dev/null +++ b/qemu/roms/openbios/arch/sparc64/openbios.h @@ -0,0 +1,27 @@ +/* + * Creation Date: <2004/01/15 16:14:05 samuel> + * Time-stamp: <2004/01/15 16:14:05 samuel> + * + * <openbios.h> + * + * + * + * Copyright (C) 2004 Samuel Rydh (samuel@ibrium.se) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#ifndef _H_OPENBIOS +#define _H_OPENBIOS + +int openbios(void); + +/* console.c */ +#ifdef CONFIG_DEBUG_CONSOLE +extern void video_init(void); +#endif + +#endif /* _H_OPENBIOS */ diff --git a/qemu/roms/openbios/arch/sparc64/openprom.h b/qemu/roms/openbios/arch/sparc64/openprom.h new file mode 100644 index 000000000..0a336901d --- /dev/null +++ b/qemu/roms/openbios/arch/sparc64/openprom.h @@ -0,0 +1,281 @@ +/* $Id: openprom.h,v 1.9 2001/03/16 10:22:02 davem Exp $ */ +#ifndef __SPARC64_OPENPROM_H +#define __SPARC64_OPENPROM_H + +/* openprom.h: Prom structures and defines for access to the OPENBOOT + * prom routines and data areas. + * + * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) + */ + +#ifndef __ASSEMBLY__ +/* V0 prom device operations. */ +struct linux_dev_v0_funcs { + int (*v0_devopen)(char *device_str); + int (*v0_devclose)(int dev_desc); + int (*v0_rdblkdev)(int dev_desc, int num_blks, int blk_st, char *buf); + int (*v0_wrblkdev)(int dev_desc, int num_blks, int blk_st, char *buf); + int (*v0_wrnetdev)(int dev_desc, int num_bytes, char *buf); + int (*v0_rdnetdev)(int dev_desc, int num_bytes, char *buf); + int (*v0_rdchardev)(int dev_desc, int num_bytes, int dummy, char *buf); + int (*v0_wrchardev)(int dev_desc, int num_bytes, int dummy, char *buf); + int (*v0_seekdev)(int dev_desc, long logical_offst, int from); +}; + +/* V2 and later prom device operations. */ +struct linux_dev_v2_funcs { + int (*v2_inst2pkg)(int d); /* Convert ihandle to phandle */ + char * (*v2_dumb_mem_alloc)(char *va, unsigned sz); + void (*v2_dumb_mem_free)(char *va, unsigned sz); + + /* To map devices into virtual I/O space. */ + char * (*v2_dumb_mmap)(char *virta, int which_io, unsigned paddr, unsigned sz); + void (*v2_dumb_munmap)(char *virta, unsigned size); + + int (*v2_dev_open)(char *devpath); + void (*v2_dev_close)(int d); + int (*v2_dev_read)(int d, char *buf, int nbytes); + int (*v2_dev_write)(int d, char *buf, int nbytes); + int (*v2_dev_seek)(int d, int hi, int lo); + + /* Never issued (multistage load support) */ + void (*v2_wheee2)(void); + void (*v2_wheee3)(void); +}; + +struct linux_mlist_v0 { + struct linux_mlist_v0 *theres_more; + unsigned start_adr; + unsigned num_bytes; +}; + +struct linux_mem_v0 { + struct linux_mlist_v0 **v0_totphys; + struct linux_mlist_v0 **v0_prommap; + struct linux_mlist_v0 **v0_available; /* What we can use */ +}; + +/* Arguments sent to the kernel from the boot prompt. */ +struct linux_arguments_v0 { + char *argv[8]; + char args[100]; + char boot_dev[2]; + int boot_dev_ctrl; + int boot_dev_unit; + int dev_partition; + char *kernel_file_name; + void *aieee1; /* XXX */ +}; + +/* V2 and up boot things. */ +struct linux_bootargs_v2 { + char **bootpath; + char **bootargs; + int *fd_stdin; + int *fd_stdout; +}; + +/* The top level PROM vector. */ +struct linux_romvec { + /* Version numbers. */ + unsigned int pv_magic_cookie; + unsigned int pv_romvers; + unsigned int pv_plugin_revision; + unsigned int pv_printrev; + + /* Version 0 memory descriptors. */ + struct linux_mem_v0 pv_v0mem; + + /* Node operations. */ + struct linux_nodeops *pv_nodeops; + + char **pv_bootstr; + struct linux_dev_v0_funcs pv_v0devops; + + char *pv_stdin; + char *pv_stdout; +#define PROMDEV_KBD 0 /* input from keyboard */ +#define PROMDEV_SCREEN 0 /* output to screen */ +#define PROMDEV_TTYA 1 /* in/out to ttya */ +#define PROMDEV_TTYB 2 /* in/out to ttyb */ + + /* Blocking getchar/putchar. NOT REENTRANT! (grr) */ + int (*pv_getchar)(void); + void (*pv_putchar)(int ch); + + /* Non-blocking variants. */ + int (*pv_nbgetchar)(void); + int (*pv_nbputchar)(int ch); + + void (*pv_putstr)(char *str, int len); + + /* Miscellany. */ + void (*pv_reboot)(char *bootstr); + void (*pv_printf)(__const__ char *fmt, ...); + void (*pv_abort)(void); + __volatile__ int *pv_ticks; + void (*pv_halt)(void); + void (**pv_synchook)(void); + + /* Evaluate a forth string, not different proto for V0 and V2->up. */ + union { + void (*v0_eval)(int len, char *str); + void (*v2_eval)(char *str); + } pv_fortheval; + + struct linux_arguments_v0 **pv_v0bootargs; + + /* Get ether address. */ + unsigned int (*pv_enaddr)(int d, char *enaddr); + + struct linux_bootargs_v2 pv_v2bootargs; + struct linux_dev_v2_funcs pv_v2devops; + + int filler[15]; + + /* This one is sun4c/sun4 only. */ + void (*pv_setctxt)(int ctxt, char *va, int pmeg); + + /* Prom version 3 Multiprocessor routines. This stuff is crazy. + * No joke. Calling these when there is only one cpu probably + * crashes the machine, have to test this. :-) + */ + + /* v3_cpustart() will start the cpu 'whichcpu' in mmu-context + * 'thiscontext' executing at address 'prog_counter' + */ + int (*v3_cpustart)(unsigned int whichcpu, int ctxtbl_ptr, + int thiscontext, char *prog_counter); + + /* v3_cpustop() will cause cpu 'whichcpu' to stop executing + * until a resume cpu call is made. + */ + int (*v3_cpustop)(unsigned int whichcpu); + + /* v3_cpuidle() will idle cpu 'whichcpu' until a stop or + * resume cpu call is made. + */ + int (*v3_cpuidle)(unsigned int whichcpu); + + /* v3_cpuresume() will resume processor 'whichcpu' executing + * starting with whatever 'pc' and 'npc' were left at the + * last 'idle' or 'stop' call. + */ + int (*v3_cpuresume)(unsigned int whichcpu); +}; + +/* Routines for traversing the prom device tree. */ +struct linux_nodeops { + int (*no_nextnode)(int node); + int (*no_child)(int node); + int (*no_proplen)(int node, char *name); + int (*no_getprop)(int node, char *name, char *val); + int (*no_setprop)(int node, char *name, char *val, int len); + char * (*no_nextprop)(int node, char *name); +}; + +/* More fun PROM structures for device probing. */ +#define PROMREG_MAX 16 +#define PROMVADDR_MAX 16 +#define PROMINTR_MAX 15 + +struct linux_prom_registers { + unsigned which_io; /* hi part of physical address */ + unsigned phys_addr; /* The physical address of this register */ + int reg_size; /* How many bytes does this register take up? */ +}; + +struct linux_prom64_registers { + long phys_addr; + long reg_size; +}; + +struct linux_prom_irqs { + int pri; /* IRQ priority */ + int vector; /* This is foobar, what does it do? */ +}; + +/* Element of the "ranges" vector */ +struct linux_prom_ranges { + unsigned int ot_child_space; + unsigned int ot_child_base; /* Bus feels this */ + unsigned int ot_parent_space; + unsigned int ot_parent_base; /* CPU looks from here */ + unsigned int or_size; +}; + +struct linux_prom64_ranges { + unsigned long ot_child_base; /* Bus feels this */ + unsigned long ot_parent_base; /* CPU looks from here */ + unsigned long or_size; +}; + +/* Ranges and reg properties are a bit different for PCI. */ +struct linux_prom_pci_registers { + unsigned int phys_hi; + unsigned int phys_mid; + unsigned int phys_lo; + + unsigned int size_hi; + unsigned int size_lo; +}; + +struct linux_prom_pci_ranges { + unsigned int child_phys_hi; /* Only certain bits are encoded here. */ + unsigned int child_phys_mid; + unsigned int child_phys_lo; + + unsigned int parent_phys_hi; + unsigned int parent_phys_lo; + + unsigned int size_hi; + unsigned int size_lo; +}; + +struct linux_prom_pci_intmap { + unsigned int phys_hi; + unsigned int phys_mid; + unsigned int phys_lo; + + unsigned int interrupt; + + int cnode; + unsigned int cinterrupt; +}; + +struct linux_prom_pci_intmask { + unsigned int phys_hi; + unsigned int phys_mid; + unsigned int phys_lo; + unsigned int interrupt; +}; + +struct linux_prom_ebus_ranges { + unsigned int child_phys_hi; + unsigned int child_phys_lo; + + unsigned int parent_phys_hi; + unsigned int parent_phys_mid; + unsigned int parent_phys_lo; + + unsigned int size; +}; + +struct linux_prom_ebus_intmap { + unsigned int phys_hi; + unsigned int phys_lo; + + unsigned int interrupt; + + int cnode; + unsigned int cinterrupt; +}; + +struct linux_prom_ebus_intmask { + unsigned int phys_hi; + unsigned int phys_lo; + unsigned int interrupt; +}; +#endif /* !(__ASSEMBLY__) */ + +#endif /* !(__SPARC64_OPENPROM_H) */ diff --git a/qemu/roms/openbios/arch/sparc64/plainboot.c b/qemu/roms/openbios/arch/sparc64/plainboot.c new file mode 100644 index 000000000..08dab2d12 --- /dev/null +++ b/qemu/roms/openbios/arch/sparc64/plainboot.c @@ -0,0 +1,21 @@ +/* tag: openbios fixed address forth starter + * + * Copyright (C) 2003 Stefan Reinauer + * + * See the file "COPYING" for further information about + * the copyright and warranty status of this work. + */ + +#include "config.h" +#include "libopenbios/sys_info.h" +#include "multiboot.h" + +#define FIXED_DICTSTART 0xfffe0000 +#define FIXED_DICTEND 0xfffeffff + +void collect_multiboot_info(struct sys_info *info); +void collect_multiboot_info(struct sys_info *info) +{ + info->dict_start=(unsigned long *)FIXED_DICTSTART; + info->dict_end=(unsigned long *)FIXED_DICTEND; +} diff --git a/qemu/roms/openbios/arch/sparc64/pstate.h b/qemu/roms/openbios/arch/sparc64/pstate.h new file mode 100644 index 000000000..f32d6f7db --- /dev/null +++ b/qemu/roms/openbios/arch/sparc64/pstate.h @@ -0,0 +1,90 @@ +/* $Id: pstate.h,v 1.6 1997/06/25 07:39:45 jj Exp $ */ +#ifndef _SPARC64_PSTATE_H +#define _SPARC64_PSTATE_H + +#include "const.h" + +/* The V9 PSTATE Register (with SpitFire extensions). + * + * ----------------------------------------------------------------------- + * | Resv | IG | MG | CLE | TLE | MM | RED | PEF | AM | PRIV | IE | AG | + * ----------------------------------------------------------------------- + * 63 12 11 10 9 8 7 6 5 4 3 2 1 0 + */ +#define PSTATE_IG _AC(0x0000000000000800,UL) /* Interrupt Globals. */ +#define PSTATE_MG _AC(0x0000000000000400,UL) /* MMU Globals. */ +#define PSTATE_CLE _AC(0x0000000000000200,UL) /* Current Little Endian.*/ +#define PSTATE_TLE _AC(0x0000000000000100,UL) /* Trap Little Endian. */ +#define PSTATE_MM _AC(0x00000000000000c0,UL) /* Memory Model. */ +#define PSTATE_TSO _AC(0x0000000000000000,UL) /* MM: TotalStoreOrder */ +#define PSTATE_PSO _AC(0x0000000000000040,UL) /* MM: PartialStoreOrder */ +#define PSTATE_RMO _AC(0x0000000000000080,UL) /* MM: RelaxedMemoryOrder*/ +#define PSTATE_RED _AC(0x0000000000000020,UL) /* Reset Error Debug. */ +#define PSTATE_PEF _AC(0x0000000000000010,UL) /* Floating Point Enable.*/ +#define PSTATE_AM _AC(0x0000000000000008,UL) /* Address Mask. */ +#define PSTATE_PRIV _AC(0x0000000000000004,UL) /* Privilege. */ +#define PSTATE_IE _AC(0x0000000000000002,UL) /* Interrupt Enable. */ +#define PSTATE_AG _AC(0x0000000000000001,UL) /* Alternate Globals. */ + +/* The V9 TSTATE Register (with SpitFire and Linux extensions). + * + * --------------------------------------------------------------- + * | Resv | CCR | ASI | %pil | PSTATE | Resv | CWP | + * --------------------------------------------------------------- + * 63 40 39 32 31 24 23 20 19 8 7 5 4 0 + */ +#define TSTATE_CCR _AC(0x000000ff00000000,UL) /* Condition Codes. */ +#define TSTATE_XCC _AC(0x000000f000000000,UL) /* Condition Codes. */ +#define TSTATE_XNEG _AC(0x0000008000000000,UL) /* %xcc Negative. */ +#define TSTATE_XZERO _AC(0x0000004000000000,UL) /* %xcc Zero. */ +#define TSTATE_XOVFL _AC(0x0000002000000000,UL) /* %xcc Overflow. */ +#define TSTATE_XCARRY _AC(0x0000001000000000,UL) /* %xcc Carry. */ +#define TSTATE_ICC _AC(0x0000000f00000000,UL) /* Condition Codes. */ +#define TSTATE_INEG _AC(0x0000000800000000,UL) /* %icc Negative. */ +#define TSTATE_IZERO _AC(0x0000000400000000,UL) /* %icc Zero. */ +#define TSTATE_IOVFL _AC(0x0000000200000000,UL) /* %icc Overflow. */ +#define TSTATE_ICARRY _AC(0x0000000100000000,UL) /* %icc Carry. */ +#define TSTATE_ASI _AC(0x00000000ff000000,UL) /* AddrSpace ID. */ +#define TSTATE_PIL _AC(0x0000000000f00000,UL) /* %pil (Linux traps)*/ +#define TSTATE_PSTATE _AC(0x00000000000fff00,UL) /* PSTATE. */ +#define TSTATE_IG _AC(0x0000000000080000,UL) /* Interrupt Globals.*/ +#define TSTATE_MG _AC(0x0000000000040000,UL) /* MMU Globals. */ +#define TSTATE_CLE _AC(0x0000000000020000,UL) /* CurrLittleEndian. */ +#define TSTATE_TLE _AC(0x0000000000010000,UL) /* TrapLittleEndian. */ +#define TSTATE_MM _AC(0x000000000000c000,UL) /* Memory Model. */ +#define TSTATE_TSO _AC(0x0000000000000000,UL) /* MM: TSO */ +#define TSTATE_PSO _AC(0x0000000000004000,UL) /* MM: PSO */ +#define TSTATE_RMO _AC(0x0000000000008000,UL) /* MM: RMO */ +#define TSTATE_RED _AC(0x0000000000002000,UL) /* Reset Error Debug.*/ +#define TSTATE_PEF _AC(0x0000000000001000,UL) /* FPU Enable. */ +#define TSTATE_AM _AC(0x0000000000000800,UL) /* Address Mask. */ +#define TSTATE_PRIV _AC(0x0000000000000400,UL) /* Privilege. */ +#define TSTATE_IE _AC(0x0000000000000200,UL) /* Interrupt Enable. */ +#define TSTATE_AG _AC(0x0000000000000100,UL) /* Alternate Globals.*/ +#define TSTATE_CWP _AC(0x000000000000001f,UL) /* Curr Win-Pointer. */ + +/* Floating-Point Registers State Register. + * + * -------------------------------- + * | Resv | FEF | DU | DL | + * -------------------------------- + * 63 3 2 1 0 + */ +#define FPRS_FEF _AC(0x0000000000000004,UL) /* FPU Enable. */ +#define FPRS_DU _AC(0x0000000000000002,UL) /* Dirty Upper. */ +#define FPRS_DL _AC(0x0000000000000001,UL) /* Dirty Lower. */ + +/* Version Register. + * + * ------------------------------------------------------ + * | MANUF | IMPL | MASK | Resv | MAXTL | Resv | MAXWIN | + * ------------------------------------------------------ + * 63 48 47 32 31 24 23 16 15 8 7 5 4 0 + */ +#define VERS_MANUF _AC(0xffff000000000000,UL) /* Manufacturer. */ +#define VERS_IMPL _AC(0x0000ffff00000000,UL) /* Implementation. */ +#define VERS_MASK _AC(0x00000000ff000000,UL) /* Mask Set Revision.*/ +#define VERS_MAXTL _AC(0x000000000000ff00,UL) /* Max Trap Level. */ +#define VERS_MAXWIN _AC(0x000000000000001f,UL) /* Max RegWindow Idx.*/ + +#endif /* !(_SPARC64_PSTATE_H) */ diff --git a/qemu/roms/openbios/arch/sparc64/spitfire.h b/qemu/roms/openbios/arch/sparc64/spitfire.h new file mode 100644 index 000000000..4a951b1fb --- /dev/null +++ b/qemu/roms/openbios/arch/sparc64/spitfire.h @@ -0,0 +1,510 @@ +/* $Id: spitfire.h,v 1.18 2001/11/29 16:42:10 kanoj Exp $ + * spitfire.h: SpitFire/BlackBird/Cheetah inline MMU operations. + * + * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) + */ + +#ifndef _SPARC64_SPITFIRE_H +#define _SPARC64_SPITFIRE_H + +#include <asm/asi.h> + +/* The following register addresses are accessible via ASI_DMMU + * and ASI_IMMU, that is there is a distinct and unique copy of + * each these registers for each TLB. + */ +#define TSB_TAG_TARGET 0x0000000000000000 /* All chips */ +#define TLB_SFSR 0x0000000000000018 /* All chips */ +#define TSB_REG 0x0000000000000028 /* All chips */ +#define TLB_TAG_ACCESS 0x0000000000000030 /* All chips */ +#define VIRT_WATCHPOINT 0x0000000000000038 /* All chips */ +#define PHYS_WATCHPOINT 0x0000000000000040 /* All chips */ +#define TSB_EXTENSION_P 0x0000000000000048 /* Ultra-III and later */ +#define TSB_EXTENSION_S 0x0000000000000050 /* Ultra-III and later, D-TLB only */ +#define TSB_EXTENSION_N 0x0000000000000058 /* Ultra-III and later */ +#define TLB_TAG_ACCESS_EXT 0x0000000000000060 /* Ultra-III+ and later */ + +/* These registers only exist as one entity, and are accessed + * via ASI_DMMU only. + */ +#define PRIMARY_CONTEXT 0x0000000000000008 +#define SECONDARY_CONTEXT 0x0000000000000010 +#define DMMU_SFAR 0x0000000000000020 +#define VIRT_WATCHPOINT 0x0000000000000038 +#define PHYS_WATCHPOINT 0x0000000000000040 + +#define SPITFIRE_HIGHEST_LOCKED_TLBENT (64 - 1) + +/* translation table entry bits */ +#define SPITFIRE_TTE_WRITABLE 0x02 +#define SPITFIRE_TTE_PRIVILEGED 0x04 +#define SPITFIRE_TTE_CV 0x10 +#define SPITFIRE_TTE_CP 0x20 +#define SPITFIRE_TTE_LOCKED 0x40 +#define SPITFIRE_TTE_VALID 0x8000000000000000ULL + +#ifndef __ASSEMBLY__ + +enum ultra_tlb_layout { + spitfire = 0, + cheetah = 1, + cheetah_plus = 2, +}; + +extern enum ultra_tlb_layout tlb_type; + +#define CHEETAH_HIGHEST_LOCKED_TLBENT (16 - 1) + +#define L1DCACHE_SIZE 0x4000 + +#define sparc64_highest_locked_tlbent() \ + (tlb_type == spitfire ? \ + SPITFIRE_HIGHEST_LOCKED_TLBENT : \ + CHEETAH_HIGHEST_LOCKED_TLBENT) + +static __inline__ unsigned long spitfire_get_isfsr(void) +{ + unsigned long ret; + + __asm__ __volatile__("ldxa [%1] %2, %0" + : "=r" (ret) + : "r" (TLB_SFSR), "i" (ASI_IMMU)); + return ret; +} + +static __inline__ unsigned long spitfire_get_dsfsr(void) +{ + unsigned long ret; + + __asm__ __volatile__("ldxa [%1] %2, %0" + : "=r" (ret) + : "r" (TLB_SFSR), "i" (ASI_DMMU)); + return ret; +} + +static __inline__ unsigned long spitfire_get_sfar(void) +{ + unsigned long ret; + + __asm__ __volatile__("ldxa [%1] %2, %0" + : "=r" (ret) + : "r" (DMMU_SFAR), "i" (ASI_DMMU)); + return ret; +} + +static __inline__ void spitfire_put_isfsr(unsigned long sfsr) +{ + __asm__ __volatile__("stxa %0, [%1] %2\n\t" + "membar #Sync" + : /* no outputs */ + : "r" (sfsr), "r" (TLB_SFSR), "i" (ASI_IMMU)); +} + +static __inline__ void spitfire_put_dsfsr(unsigned long sfsr) +{ + __asm__ __volatile__("stxa %0, [%1] %2\n\t" + "membar #Sync" + : /* no outputs */ + : "r" (sfsr), "r" (TLB_SFSR), "i" (ASI_DMMU)); +} + +static __inline__ unsigned long spitfire_get_primary_context(void) +{ + unsigned long ctx; + + __asm__ __volatile__("ldxa [%1] %2, %0" + : "=r" (ctx) + : "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU)); + return ctx; +} + +static __inline__ void spitfire_set_primary_context(unsigned long ctx) +{ + __asm__ __volatile__("stxa %0, [%1] %2\n\t" + "membar #Sync" + : /* No outputs */ + : "r" (ctx & 0x3ff), + "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU)); + __asm__ __volatile__ ("membar #Sync" : : : "memory"); +} + +static __inline__ unsigned long spitfire_get_secondary_context(void) +{ + unsigned long ctx; + + __asm__ __volatile__("ldxa [%1] %2, %0" + : "=r" (ctx) + : "r" (SECONDARY_CONTEXT), "i" (ASI_DMMU)); + return ctx; +} + +static __inline__ void spitfire_set_secondary_context(unsigned long ctx) +{ + __asm__ __volatile__("stxa %0, [%1] %2\n\t" + "membar #Sync" + : /* No outputs */ + : "r" (ctx & 0x3ff), + "r" (SECONDARY_CONTEXT), "i" (ASI_DMMU)); + __asm__ __volatile__ ("membar #Sync" : : : "memory"); +} + +/* The data cache is write through, so this just invalidates the + * specified line. + */ +static __inline__ void spitfire_put_dcache_tag(unsigned long addr, unsigned long tag) +{ + __asm__ __volatile__("stxa %0, [%1] %2\n\t" + "membar #Sync" + : /* No outputs */ + : "r" (tag), "r" (addr), "i" (ASI_DCACHE_TAG)); + __asm__ __volatile__ ("membar #Sync" : : : "memory"); +} + +/* The instruction cache lines are flushed with this, but note that + * this does not flush the pipeline. It is possible for a line to + * get flushed but stale instructions to still be in the pipeline, + * a flush instruction (to any address) is sufficient to handle + * this issue after the line is invalidated. + */ +static __inline__ void spitfire_put_icache_tag(unsigned long addr, unsigned long tag) +{ + __asm__ __volatile__("stxa %0, [%1] %2\n\t" + "membar #Sync" + : /* No outputs */ + : "r" (tag), "r" (addr), "i" (ASI_IC_TAG)); +} + +static __inline__ unsigned long spitfire_get_dtlb_data(int entry) +{ + unsigned long data; + + __asm__ __volatile__("ldxa [%1] %2, %0" + : "=r" (data) + : "r" (entry << 3), "i" (ASI_DTLB_DATA_ACCESS)); + + /* Clear TTE diag bits. */ + data &= ~0x0003fe0000000000UL; + + return data; +} + +static __inline__ unsigned long spitfire_get_dtlb_tag(int entry) +{ + unsigned long tag; + + __asm__ __volatile__("ldxa [%1] %2, %0" + : "=r" (tag) + : "r" (entry << 3), "i" (ASI_DTLB_TAG_READ)); + return tag; +} + +static __inline__ void spitfire_put_dtlb_data(int entry, unsigned long data) +{ + __asm__ __volatile__("stxa %0, [%1] %2\n\t" + "membar #Sync" + : /* No outputs */ + : "r" (data), "r" (entry << 3), + "i" (ASI_DTLB_DATA_ACCESS)); +} + +static __inline__ unsigned long spitfire_get_itlb_data(int entry) +{ + unsigned long data; + + __asm__ __volatile__("ldxa [%1] %2, %0" + : "=r" (data) + : "r" (entry << 3), "i" (ASI_ITLB_DATA_ACCESS)); + + /* Clear TTE diag bits. */ + data &= ~0x0003fe0000000000UL; + + return data; +} + +static __inline__ unsigned long spitfire_get_itlb_tag(int entry) +{ + unsigned long tag; + + __asm__ __volatile__("ldxa [%1] %2, %0" + : "=r" (tag) + : "r" (entry << 3), "i" (ASI_ITLB_TAG_READ)); + return tag; +} + +static __inline__ void spitfire_put_itlb_data(int entry, unsigned long data) +{ + __asm__ __volatile__("stxa %0, [%1] %2\n\t" + "membar #Sync" + : /* No outputs */ + : "r" (data), "r" (entry << 3), + "i" (ASI_ITLB_DATA_ACCESS)); +} + +/* Spitfire hardware assisted TLB flushes. */ + +/* Context level flushes. */ +static __inline__ void spitfire_flush_dtlb_primary_context(void) +{ + __asm__ __volatile__("stxa %%g0, [%0] %1\n\t" + "membar #Sync" + : /* No outputs */ + : "r" (0x40), "i" (ASI_DMMU_DEMAP)); +} + +static __inline__ void spitfire_flush_itlb_primary_context(void) +{ + __asm__ __volatile__("stxa %%g0, [%0] %1\n\t" + "membar #Sync" + : /* No outputs */ + : "r" (0x40), "i" (ASI_IMMU_DEMAP)); +} + +static __inline__ void spitfire_flush_dtlb_secondary_context(void) +{ + __asm__ __volatile__("stxa %%g0, [%0] %1\n\t" + "membar #Sync" + : /* No outputs */ + : "r" (0x50), "i" (ASI_DMMU_DEMAP)); +} + +static __inline__ void spitfire_flush_itlb_secondary_context(void) +{ + __asm__ __volatile__("stxa %%g0, [%0] %1\n\t" + "membar #Sync" + : /* No outputs */ + : "r" (0x50), "i" (ASI_IMMU_DEMAP)); +} + +static __inline__ void spitfire_flush_dtlb_nucleus_context(void) +{ + __asm__ __volatile__("stxa %%g0, [%0] %1\n\t" + "membar #Sync" + : /* No outputs */ + : "r" (0x60), "i" (ASI_DMMU_DEMAP)); +} + +static __inline__ void spitfire_flush_itlb_nucleus_context(void) +{ + __asm__ __volatile__("stxa %%g0, [%0] %1\n\t" + "membar #Sync" + : /* No outputs */ + : "r" (0x60), "i" (ASI_IMMU_DEMAP)); +} + +/* Page level flushes. */ +static __inline__ void spitfire_flush_dtlb_primary_page(unsigned long page) +{ + __asm__ __volatile__("stxa %%g0, [%0] %1\n\t" + "membar #Sync" + : /* No outputs */ + : "r" (page), "i" (ASI_DMMU_DEMAP)); +} + +static __inline__ void spitfire_flush_itlb_primary_page(unsigned long page) +{ + __asm__ __volatile__("stxa %%g0, [%0] %1\n\t" + "membar #Sync" + : /* No outputs */ + : "r" (page), "i" (ASI_IMMU_DEMAP)); +} + +static __inline__ void spitfire_flush_dtlb_secondary_page(unsigned long page) +{ + __asm__ __volatile__("stxa %%g0, [%0] %1\n\t" + "membar #Sync" + : /* No outputs */ + : "r" (page | 0x10), "i" (ASI_DMMU_DEMAP)); +} + +static __inline__ void spitfire_flush_itlb_secondary_page(unsigned long page) +{ + __asm__ __volatile__("stxa %%g0, [%0] %1\n\t" + "membar #Sync" + : /* No outputs */ + : "r" (page | 0x10), "i" (ASI_IMMU_DEMAP)); +} + +static __inline__ void spitfire_flush_dtlb_nucleus_page(unsigned long page) +{ + __asm__ __volatile__("stxa %%g0, [%0] %1\n\t" + "membar #Sync" + : /* No outputs */ + : "r" (page | 0x20), "i" (ASI_DMMU_DEMAP)); +} + +static __inline__ void spitfire_flush_itlb_nucleus_page(unsigned long page) +{ + __asm__ __volatile__("stxa %%g0, [%0] %1\n\t" + "membar #Sync" + : /* No outputs */ + : "r" (page | 0x20), "i" (ASI_IMMU_DEMAP)); +} + +/* Cheetah has "all non-locked" tlb flushes. */ +static __inline__ void cheetah_flush_dtlb_all(void) +{ + __asm__ __volatile__("stxa %%g0, [%0] %1\n\t" + "membar #Sync" + : /* No outputs */ + : "r" (0x80), "i" (ASI_DMMU_DEMAP)); +} + +static __inline__ void cheetah_flush_itlb_all(void) +{ + __asm__ __volatile__("stxa %%g0, [%0] %1\n\t" + "membar #Sync" + : /* No outputs */ + : "r" (0x80), "i" (ASI_IMMU_DEMAP)); +} + +/* Cheetah has a 4-tlb layout so direct access is a bit different. + * The first two TLBs are fully assosciative, hold 16 entries, and are + * used only for locked and >8K sized translations. One exists for + * data accesses and one for instruction accesses. + * + * The third TLB is for data accesses to 8K non-locked translations, is + * 2 way assosciative, and holds 512 entries. The fourth TLB is for + * instruction accesses to 8K non-locked translations, is 2 way + * assosciative, and holds 128 entries. + * + * Cheetah has some bug where bogus data can be returned from + * ASI_{D,I}TLB_DATA_ACCESS loads, doing the load twice fixes + * the problem for me. -DaveM + */ +static __inline__ unsigned long cheetah_get_ldtlb_data(int entry) +{ + unsigned long data; + + __asm__ __volatile__("ldxa [%1] %2, %%g0\n\t" + "ldxa [%1] %2, %0" + : "=r" (data) + : "r" ((0 << 16) | (entry << 3)), + "i" (ASI_DTLB_DATA_ACCESS)); + + return data; +} + +static __inline__ unsigned long cheetah_get_litlb_data(int entry) +{ + unsigned long data; + + __asm__ __volatile__("ldxa [%1] %2, %%g0\n\t" + "ldxa [%1] %2, %0" + : "=r" (data) + : "r" ((0 << 16) | (entry << 3)), + "i" (ASI_ITLB_DATA_ACCESS)); + + return data; +} + +static __inline__ unsigned long cheetah_get_ldtlb_tag(int entry) +{ + unsigned long tag; + + __asm__ __volatile__("ldxa [%1] %2, %0" + : "=r" (tag) + : "r" ((0 << 16) | (entry << 3)), + "i" (ASI_DTLB_TAG_READ)); + + return tag; +} + +static __inline__ unsigned long cheetah_get_litlb_tag(int entry) +{ + unsigned long tag; + + __asm__ __volatile__("ldxa [%1] %2, %0" + : "=r" (tag) + : "r" ((0 << 16) | (entry << 3)), + "i" (ASI_ITLB_TAG_READ)); + + return tag; +} + +static __inline__ void cheetah_put_ldtlb_data(int entry, unsigned long data) +{ + __asm__ __volatile__("stxa %0, [%1] %2\n\t" + "membar #Sync" + : /* No outputs */ + : "r" (data), + "r" ((0 << 16) | (entry << 3)), + "i" (ASI_DTLB_DATA_ACCESS)); +} + +static __inline__ void cheetah_put_litlb_data(int entry, unsigned long data) +{ + __asm__ __volatile__("stxa %0, [%1] %2\n\t" + "membar #Sync" + : /* No outputs */ + : "r" (data), + "r" ((0 << 16) | (entry << 3)), + "i" (ASI_ITLB_DATA_ACCESS)); +} + +static __inline__ unsigned long cheetah_get_dtlb_data(int entry, int tlb) +{ + unsigned long data; + + __asm__ __volatile__("ldxa [%1] %2, %%g0\n\t" + "ldxa [%1] %2, %0" + : "=r" (data) + : "r" ((tlb << 16) | (entry << 3)), "i" (ASI_DTLB_DATA_ACCESS)); + + return data; +} + +static __inline__ unsigned long cheetah_get_dtlb_tag(int entry, int tlb) +{ + unsigned long tag; + + __asm__ __volatile__("ldxa [%1] %2, %0" + : "=r" (tag) + : "r" ((tlb << 16) | (entry << 3)), "i" (ASI_DTLB_TAG_READ)); + return tag; +} + +static __inline__ void cheetah_put_dtlb_data(int entry, unsigned long data, int tlb) +{ + __asm__ __volatile__("stxa %0, [%1] %2\n\t" + "membar #Sync" + : /* No outputs */ + : "r" (data), + "r" ((tlb << 16) | (entry << 3)), + "i" (ASI_DTLB_DATA_ACCESS)); +} + +static __inline__ unsigned long cheetah_get_itlb_data(int entry) +{ + unsigned long data; + + __asm__ __volatile__("ldxa [%1] %2, %%g0\n\t" + "ldxa [%1] %2, %0" + : "=r" (data) + : "r" ((2 << 16) | (entry << 3)), + "i" (ASI_ITLB_DATA_ACCESS)); + + return data; +} + +static __inline__ unsigned long cheetah_get_itlb_tag(int entry) +{ + unsigned long tag; + + __asm__ __volatile__("ldxa [%1] %2, %0" + : "=r" (tag) + : "r" ((2 << 16) | (entry << 3)), "i" (ASI_ITLB_TAG_READ)); + return tag; +} + +static __inline__ void cheetah_put_itlb_data(int entry, unsigned long data) +{ + __asm__ __volatile__("stxa %0, [%1] %2\n\t" + "membar #Sync" + : /* No outputs */ + : "r" (data), "r" ((2 << 16) | (entry << 3)), + "i" (ASI_ITLB_DATA_ACCESS)); +} + +#endif /* !(__ASSEMBLY__) */ + +#endif /* !(_SPARC64_SPITFIRE_H) */ diff --git a/qemu/roms/openbios/arch/sparc64/switch.S b/qemu/roms/openbios/arch/sparc64/switch.S new file mode 100644 index 000000000..d2cc7bedb --- /dev/null +++ b/qemu/roms/openbios/arch/sparc64/switch.S @@ -0,0 +1,124 @@ +#include "pstate.h" +#include <asm/asi.h> +#define ASI_BP ASI_M_BYPASS +#define REGWIN_SZ 0x40 + + .globl __switch_context, __switch_context_nosave, __exit_context, halt + + .text + .align 4 + .register %g2, #scratch + .register %g3, #scratch + .register %g6, #scratch + .register %g7, #scratch + +/* + * Switch execution context + * This saves registers in the stack, then + * switches the stack, and restores everything from the new stack. + * This function takes no argument. New stack pointer is + * taken from global variable __context, and old stack pointer + * is also saved to __context. This way we can just jump to + * this routine to get back to the original context. + */ + +/* XXX: totally bogus for sparc, need to save and restore all windows */ +__switch_context: + + /* make sure caller's windows are on caller's stack */ + flushw; + + /* Save everything in current stack */ + + setx __context, %g2, %g1 + stx %g3, [%g1 + 24] + stx %g4, [%g1 + 32] + stx %g5, [%g1 + 40] + stx %g6, [%g1 + 48] + stx %g7, [%g1 + 56] + + stx %o0, [%g1 + 64] + stx %o1, [%g1 + 72] + stx %o2, [%g1 + 80] + stx %o3, [%g1 + 88] + stx %o4, [%g1 + 96] + stx %o5, [%g1 + 104] + stx %o6, [%g1 + 112] + stx %o7, [%g1 + 120] + + stx %l0, [%g1 + 128] + stx %l1, [%g1 + 136] + stx %l2, [%g1 + 144] + stx %l3, [%g1 + 152] + stx %l4, [%g1 + 160] + stx %l5, [%g1 + 168] + stx %l6, [%g1 + 176] + stx %l7, [%g1 + 184] + + stx %i0, [%g1 + 192] + stx %i1, [%g1 + 200] + stx %i2, [%g1 + 208] + stx %i3, [%g1 + 216] + stx %i4, [%g1 + 224] + stx %i5, [%g1 + 232] + stx %i6, [%g1 + 240] + stx %i7, [%g1 + 248] + +__switch_context_nosave: + /* Interrupts are not allowed... */ + /* make sure caller's windows are on caller's stack */ + flushw + /* Load all registers + */ + setx __context, %g2, %g1 + ldx [%g1], %g1 + ldx [%g1 + 16], %g2 + ldx [%g1 + 24], %g3 + ldx [%g1 + 32], %g4 + ldx [%g1 + 40], %g5 + ldx [%g1 + 48], %g6 + ldx [%g1 + 56], %g7 + + ldx [%g1 + 64], %o0 + ldx [%g1 + 72], %o1 + ldx [%g1 + 80], %o2 + ldx [%g1 + 88], %o3 + ldx [%g1 + 96], %o4 + ldx [%g1 + 104], %o5 + ldx [%g1 + 112], %o6 + ldx [%g1 + 120], %o7 + + ldx [%g1 + 128], %l0 + ldx [%g1 + 136], %l1 + ldx [%g1 + 144], %l2 + ldx [%g1 + 152], %l3 + ldx [%g1 + 160], %l4 + ldx [%g1 + 168], %l5 + ldx [%g1 + 176], %l6 + ldx [%g1 + 184], %l7 + + ldx [%g1 + 192], %i0 + ldx [%g1 + 200], %i1 + ldx [%g1 + 208], %i2 + ldx [%g1 + 216], %i3 + ldx [%g1 + 224], %i4 + ldx [%g1 + 232], %i5 + ldx [%g1 + 240], %i6 + ldx [%g1 + 248], %i7 + + ldx [%g1 + 256], %g1 + /* Finally, load new %pc */ + jmp %g1 + clr %g1 + +__exit_context: + /* Get back to the original context */ + call __switch_context + nop + + /* We get here if the other context attempt to switch to this + * dead context. This should not happen. */ + +halt: + b halt + nop diff --git a/qemu/roms/openbios/arch/sparc64/sys_info.c b/qemu/roms/openbios/arch/sparc64/sys_info.c new file mode 100644 index 000000000..f70aa0270 --- /dev/null +++ b/qemu/roms/openbios/arch/sparc64/sys_info.c @@ -0,0 +1,59 @@ +#include "config.h" +#include "kernel/kernel.h" +#include "arch/common/elf_boot.h" +#include "libopenbios/sys_info.h" +#include "context.h" +#include "boot.h" + +#define printf printk +#ifdef CONFIG_DEBUG_BOOT +#define debug printk +#else +#define debug(x...) +#endif + +uint64_t qemu_mem_size; +unsigned long va_shift; + +void collect_multiboot_info(struct sys_info *); + +void collect_sys_info(struct sys_info *info) +{ + int i; + unsigned long long total = 0; + struct memrange *mmap; + + /* Pick up paramters given by bootloader to us */ + //info->boot_type = boot_ctx->eax; + //info->boot_data = boot_ctx->ebx; + info->boot_arg = boot_ctx->param[0]; + //debug("boot eax = %#lx\n", info->boot_type); + //debug("boot ebx = %#lx\n", info->boot_data); + info->boot_type = ELF_BHDR_MAGIC; + info->boot_data = virt_to_phys(&elf_image_notes); + debug("boot arg = %#lx\n", info->boot_arg); + + collect_elfboot_info(info); +#ifdef CONFIG_LINUXBIOS + collect_linuxbios_info(info); +#endif +#ifdef CONFIG_IMAGE_ELF_MULTIBOOT + collect_multiboot_info(info); +#endif + + if (!info->memrange) { + info->n_memranges = 1; + info->memrange = malloc(1 * sizeof(struct memrange)); + info->memrange[0].base = 0; + info->memrange[0].size = qemu_mem_size; + } + + debug("\n"); + mmap=info->memrange; + for (i = 0; i < info->n_memranges; i++) { + debug("%08lx-", (long)mmap[i].base); + debug("%08lx\n", (long)mmap[i].base + (long)mmap[i].size); + total += mmap[i].size; + } + debug("RAM %ld MB\n", (long)total >> 20); +} diff --git a/qemu/roms/openbios/arch/sparc64/tree.fs b/qemu/roms/openbios/arch/sparc64/tree.fs new file mode 100644 index 000000000..e034b5931 --- /dev/null +++ b/qemu/roms/openbios/arch/sparc64/tree.fs @@ -0,0 +1,49 @@ +include config.fs + +\ ------------------------------------------------------------------------- +\ UPA encode/decode unit +\ ------------------------------------------------------------------------- + +: decode-unit-upa ( str len -- id lun ) + ascii , left-split + ( addr-R len-R addr-L len-L ) + parse-hex + -rot parse-hex + swap +; + +: encode-unit-upa ( id lun -- str len) + swap + pocket tohexstr + " ," pocket tmpstrcat >r + rot pocket tohexstr r> tmpstrcat drop +; + +" /" find-device + 2 encode-int " #address-cells" property + 2 encode-int " #size-cells" property + " sun4u" encode-string " compatible" property + + : encode-unit encode-unit-upa ; + : decode-unit decode-unit-upa ; + +new-device + " memory" device-name + " memory" device-type + external + : open true ; + : close ; + \ see arch/sparc64/lib.c for methods +finish-device + +new-device + " virtual-memory" device-name + external + \ see arch/sparc64/lib.c for methods +finish-device + +" /options" find-device + " disk" encode-string " boot-from" property + +" /openprom" find-device + " OBP 3.10.24 1999/01/01 01:01" encode-string " version" property diff --git a/qemu/roms/openbios/arch/sparc64/vectors.S b/qemu/roms/openbios/arch/sparc64/vectors.S new file mode 100644 index 000000000..927c1cdc7 --- /dev/null +++ b/qemu/roms/openbios/arch/sparc64/vectors.S @@ -0,0 +1,765 @@ +/* + * <vectors.S> + * + * Sparc V9 Trap Table(s) with SpitFire/Cheetah extensions. + * + * Copyright (C) 1996, 2001 David S. Miller (davem@caip.rutgers.edu) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License V2 + * as published by the Free Software Foundation + */ + +#define __ASSEMBLY__ +#include "pstate.h" +#include <asm/asi.h> +#define ASI_BP ASI_PHYS_BYPASS_EC_E +#define PROM_ADDR 0x1fff0000000 +#define SER_ADDR 0x1fe020003f8 +#define TICK_INT_DIS 0x8000000000000000 +#define TICK_INTERVAL 1*1000*1000 + + .section ".text.vectors", "ax" + .align 16384 +/* Sparc64 trap table */ + .globl trap_table, __divide_error, softint_irq, softint_irq_tl1 + .register %g2, #scratch + .register %g3, #scratch + .register %g6, #scratch + .register %g7, #scratch +trap_table: +#define SPILL_WINDOW \ + btst 1, %sp; \ + be spill_32bit; \ + nop; \ + stx %l0, [%sp + STACK_BIAS + 0x00]; \ + stx %l1, [%sp + STACK_BIAS + 0x08]; \ + stx %l2, [%sp + STACK_BIAS + 0x10]; \ + stx %l3, [%sp + STACK_BIAS + 0x18]; \ + stx %l4, [%sp + STACK_BIAS + 0x20]; \ + stx %l5, [%sp + STACK_BIAS + 0x28]; \ + stx %l6, [%sp + STACK_BIAS + 0x30]; \ + stx %l7, [%sp + STACK_BIAS + 0x38]; \ + stx %i0, [%sp + STACK_BIAS + 0x40]; \ + stx %i1, [%sp + STACK_BIAS + 0x48]; \ + stx %i2, [%sp + STACK_BIAS + 0x50]; \ + stx %i3, [%sp + STACK_BIAS + 0x58]; \ + stx %i4, [%sp + STACK_BIAS + 0x60]; \ + stx %i5, [%sp + STACK_BIAS + 0x68]; \ + stx %i6, [%sp + STACK_BIAS + 0x70]; \ + stx %i7, [%sp + STACK_BIAS + 0x78]; \ + saved; retry; nop; nop; nop; nop; nop; nop; \ + nop; nop; nop; nop; nop; + +#define FILL_WINDOW \ + btst 1, %sp; \ + be fill_32bit; \ + nop; \ + ldx [%sp + STACK_BIAS + 0x00], %l0; \ + ldx [%sp + STACK_BIAS + 0x08], %l1; \ + ldx [%sp + STACK_BIAS + 0x10], %l2; \ + ldx [%sp + STACK_BIAS + 0x18], %l3; \ + ldx [%sp + STACK_BIAS + 0x20], %l4; \ + ldx [%sp + STACK_BIAS + 0x28], %l5; \ + ldx [%sp + STACK_BIAS + 0x30], %l6; \ + ldx [%sp + STACK_BIAS + 0x38], %l7; \ + ldx [%sp + STACK_BIAS + 0x40], %i0; \ + ldx [%sp + STACK_BIAS + 0x48], %i1; \ + ldx [%sp + STACK_BIAS + 0x50], %i2; \ + ldx [%sp + STACK_BIAS + 0x58], %i3; \ + ldx [%sp + STACK_BIAS + 0x60], %i4; \ + ldx [%sp + STACK_BIAS + 0x68], %i5; \ + ldx [%sp + STACK_BIAS + 0x70], %i6; \ + ldx [%sp + STACK_BIAS + 0x78], %i7; \ + restored; retry; nop; nop; nop; nop; nop; nop; \ + nop; nop; nop; nop; nop; + +#define CLEAN_WINDOW \ + rdpr %cleanwin, %l0; add %l0, 1, %l0; \ + wrpr %l0, 0x0, %cleanwin; \ + clr %o0; clr %o1; clr %o2; clr %o3; \ + clr %o4; clr %o5; clr %o6; clr %o7; \ + clr %l0; clr %l1; clr %l2; clr %l3; \ + clr %l4; clr %l5; clr %l6; clr %l7; \ + retry; \ + nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop; + +#define TRAP_IRQ(routine, level) \ + ba routine; mov level, %g1; nop; nop; nop; nop; nop; nop; +#define BTRAP(lvl) \ + ba bug; mov lvl, %g1; nop; nop; nop; nop; nop; nop; +#define BTRAPTL1(lvl) BTRAP(lvl) +#define BTRAPS(x) BTRAP(x) BTRAP(x+1) BTRAP(x+2) BTRAP(x+3) BTRAP(x+4) BTRAP(x+5) BTRAP(x+6) BTRAP(x+7) +#define BTRAPS4(x) BTRAP(x) BTRAP(x+1) BTRAP(x+2) BTRAP(x+3) +#define TRAP_HANDLER(routine) ba routine; nop; nop; nop; nop; nop; nop; nop; + +#define STACK_BIAS 2047 + .globl sparc64_ttable_tl0, sparc64_ttable_tl1 +sparc64_ttable_tl0: + ba entry; nop; nop; nop; nop; nop; nop; nop;! XXX remove + ba entry; nop; nop; nop; nop; nop; nop; nop;! Power-on reset + ba entry; nop; nop; nop; nop; nop; nop; nop;! Watchdog reset + ba entry; nop; nop; nop; nop; nop; nop; nop;! External reset + ba entry; nop; nop; nop; nop; nop; nop; nop;! Software reset + ba entry; nop; nop; nop; nop; nop; nop; nop;! RED state + BTRAP(0x06) BTRAP(0x07) BTRAPS(0x08) + BTRAPS(0x10) BTRAPS(0x18) + BTRAP(0x20) BTRAP(0x21) BTRAP(0x22) BTRAP(0x23) + CLEAN_WINDOW ! 24-27 + BTRAPS(0x28) + BTRAPS(0x30) BTRAPS(0x38) + BTRAP(0x40) BTRAP(0x41) BTRAP(0x42) BTRAP(0x43) +tl0_irq4: TRAP_IRQ(handler_irq, 4) +tl0_irq5: TRAP_IRQ(handler_irq, 5) TRAP_IRQ(handler_irq, 6) +tl0_irq7: TRAP_IRQ(handler_irq, 7) TRAP_IRQ(handler_irq, 8) +tl0_irq9: TRAP_IRQ(handler_irq, 9) TRAP_IRQ(handler_irq, 10) +tl0_irq11: TRAP_IRQ(handler_irq, 11) TRAP_IRQ(handler_irq, 12) +tl0_irq13: TRAP_IRQ(handler_irq, 13) +tl0_irq14: TRAP_IRQ(softint_irq, 14) +tl0_irq15: TRAP_IRQ(handler_irq, 15) + BTRAPS(0x50) BTRAPS(0x58) + BTRAPS4(0x60) + TRAP_HANDLER(reload_IMMU_tlb) ! 0x64 : instruction_access_MMU_miss + TRAP_HANDLER(reload_IMMU_tlb) ! 0x65 : instruction_access_MMU_miss + TRAP_HANDLER(reload_IMMU_tlb) ! 0x66 : instruction_access_MMU_miss + TRAP_HANDLER(reload_IMMU_tlb) ! 0x67 : instruction_access_MMU_miss + TRAP_HANDLER(reload_DMMU_tlb) ! 0x68 : data_access_MMU_miss + TRAP_HANDLER(reload_DMMU_tlb) ! 0x69 : data_access_MMU_miss + TRAP_HANDLER(reload_DMMU_tlb) ! 0x6A : data_access_MMU_miss + TRAP_HANDLER(reload_DMMU_tlb) ! 0x6B : data_access_MMU_miss + BTRAPS4(0x6C) ! data_access_protection + BTRAPS(0x70) BTRAPS(0x78) +tl0_s0n: SPILL_WINDOW +tl0_s1n: SPILL_WINDOW +tl0_s2n: SPILL_WINDOW +tl0_s3n: SPILL_WINDOW +tl0_s4n: SPILL_WINDOW +tl0_s5n: SPILL_WINDOW +tl0_s6n: SPILL_WINDOW +tl0_s7n: SPILL_WINDOW +tl0_s0o: SPILL_WINDOW +tl0_s1o: SPILL_WINDOW +tl0_s2o: SPILL_WINDOW +tl0_s3o: SPILL_WINDOW +tl0_s4o: SPILL_WINDOW +tl0_s5o: SPILL_WINDOW +tl0_s6o: SPILL_WINDOW +tl0_s7o: SPILL_WINDOW +tl0_f0n: FILL_WINDOW +tl0_f1n: FILL_WINDOW +tl0_f2n: FILL_WINDOW +tl0_f3n: FILL_WINDOW +tl0_f4n: FILL_WINDOW +tl0_f5n: FILL_WINDOW +tl0_f6n: FILL_WINDOW +tl0_f7n: FILL_WINDOW +tl0_f0o: FILL_WINDOW +tl0_f1o: FILL_WINDOW +tl0_f2o: FILL_WINDOW +tl0_f3o: FILL_WINDOW +tl0_f4o: FILL_WINDOW +tl0_f5o: FILL_WINDOW +tl0_f6o: FILL_WINDOW +tl0_f7o: FILL_WINDOW +tl0_resv100: BTRAPS(0x100) BTRAPS(0x108) +tl0_resv110: BTRAPS(0x110) BTRAPS(0x118) +tl0_resv120: BTRAPS(0x120) BTRAPS(0x128) +tl0_resv130: BTRAPS(0x130) BTRAPS(0x138) +tl0_resv140: BTRAPS(0x140) BTRAPS(0x148) +tl0_resv150: BTRAPS(0x150) BTRAPS(0x158) +tl0_resv160: BTRAPS(0x160) BTRAPS(0x168) +tl0_resv170: BTRAPS(0x170) BTRAPS(0x178) +tl0_resv180: BTRAPS(0x180) BTRAPS(0x188) +tl0_resv190: BTRAPS(0x190) BTRAPS(0x198) +tl0_resv1a0: BTRAPS(0x1a0) BTRAPS(0x1a8) +tl0_resv1b0: BTRAPS(0x1b0) BTRAPS(0x1b8) +tl0_resv1c0: BTRAPS(0x1c0) BTRAPS(0x1c8) +tl0_resv1d0: BTRAPS(0x1d0) BTRAPS(0x1d8) +tl0_resv1e0: BTRAPS(0x1e0) BTRAPS(0x1e8) +tl0_resv1f0: BTRAPS(0x1f0) BTRAPS(0x1f8) + +#undef BTRAPS +#define BTRAPS(x) BTRAPTL1(x) BTRAPTL1(x+1) BTRAPTL1(x+2) BTRAPTL1(x+3) BTRAPTL1(x+4) BTRAPTL1(x+5) BTRAPTL1(x+6) BTRAPTL1(x+7) + +#define SKIP_IRQ(routine, level) \ + retry; nop; nop; nop; nop; nop; nop; nop; + +sparc64_ttable_tl1: + BTRAPS(0x00) BTRAPS(0x08) + BTRAPS(0x10) BTRAPS(0x18) + BTRAPTL1(0x20) BTRAPTL1(0x21) BTRAPTL1(0x22) BTRAPTL1(0x23) + CLEAN_WINDOW ! 24-27 + BTRAPS(0x28) + BTRAPS(0x30) BTRAPS(0x38) + BTRAPTL1(0x40) BTRAPTL1(0x41) BTRAPTL1(0x42) BTRAPTL1(0x43) +tl1_irq4: TRAP_IRQ(handler_irq, 4) +tl1_irq5: TRAP_IRQ(handler_irq, 5) TRAP_IRQ(handler_irq, 6) +tl1_irq7: TRAP_IRQ(handler_irq, 7) TRAP_IRQ(handler_irq, 8) +tl1_irq9: TRAP_IRQ(handler_irq, 9) TRAP_IRQ(handler_irq, 10) +tl1_irq11: TRAP_IRQ(handler_irq, 11) TRAP_IRQ(handler_irq, 12) +tl1_irq13: TRAP_IRQ(handler_irq, 13) +tl1_irq14: SKIP_IRQ(softint_irq, 14) +tl1_irq15: TRAP_IRQ(handler_irq, 15) + BTRAPS(0x50) BTRAPS(0x58) + BTRAPS4(0x60) + TRAP_HANDLER(reload_IMMU_tlb) ! 0x64 : instruction_access_MMU_miss + TRAP_HANDLER(reload_IMMU_tlb) ! 0x65 : instruction_access_MMU_miss + TRAP_HANDLER(reload_IMMU_tlb) ! 0x66 : instruction_access_MMU_miss + TRAP_HANDLER(reload_IMMU_tlb) ! 0x67 : instruction_access_MMU_miss + TRAP_HANDLER(reload_DMMU_tlb) ! 0x68 : data_access_MMU_miss + TRAP_HANDLER(reload_DMMU_tlb) ! 0x69 : data_access_MMU_miss + TRAP_HANDLER(reload_DMMU_tlb) ! 0x6A : data_access_MMU_miss + TRAP_HANDLER(reload_DMMU_tlb) ! 0x6B : data_access_MMU_miss + BTRAPS4(0x6C) ! data_access_protection + BTRAPS(0x70) BTRAPS(0x78) +tl1_s0n: SPILL_WINDOW +tl1_s1n: SPILL_WINDOW +tl1_s2n: SPILL_WINDOW +tl1_s3n: SPILL_WINDOW +tl1_s4n: SPILL_WINDOW +tl1_s5n: SPILL_WINDOW +tl1_s6n: SPILL_WINDOW +tl1_s7n: SPILL_WINDOW +tl1_s0o: SPILL_WINDOW +tl1_s1o: SPILL_WINDOW +tl1_s2o: SPILL_WINDOW +tl1_s3o: SPILL_WINDOW +tl1_s4o: SPILL_WINDOW +tl1_s5o: SPILL_WINDOW +tl1_s6o: SPILL_WINDOW +tl1_s7o: SPILL_WINDOW +tl1_f0n: FILL_WINDOW +tl1_f1n: FILL_WINDOW +tl1_f2n: FILL_WINDOW +tl1_f3n: FILL_WINDOW +tl1_f4n: FILL_WINDOW +tl1_f5n: FILL_WINDOW +tl1_f6n: FILL_WINDOW +tl1_f7n: FILL_WINDOW +tl1_f0o: FILL_WINDOW +tl1_f1o: FILL_WINDOW +tl1_f2o: FILL_WINDOW +tl1_f3o: FILL_WINDOW +tl1_f4o: FILL_WINDOW +tl1_f5o: FILL_WINDOW +tl1_f6o: FILL_WINDOW +tl1_f7o: FILL_WINDOW +tl1_resv100: BTRAPS(0x100) BTRAPS(0x108) +tl1_resv110: BTRAPS(0x110) BTRAPS(0x118) +tl1_resv120: BTRAPS(0x120) BTRAPS(0x128) +tl1_resv130: BTRAPS(0x130) BTRAPS(0x138) +tl1_resv140: BTRAPS(0x140) BTRAPS(0x148) +tl1_resv150: BTRAPS(0x150) BTRAPS(0x158) +tl1_resv160: BTRAPS(0x160) BTRAPS(0x168) +tl1_resv170: BTRAPS(0x170) BTRAPS(0x178) +tl1_resv180: BTRAPS(0x180) BTRAPS(0x188) +tl1_resv190: BTRAPS(0x190) BTRAPS(0x198) +tl1_resv1a0: BTRAPS(0x1a0) BTRAPS(0x1a8) +tl1_resv1b0: BTRAPS(0x1b0) BTRAPS(0x1b8) +tl1_resv1c0: BTRAPS(0x1c0) BTRAPS(0x1c8) +tl1_resv1d0: BTRAPS(0x1d0) BTRAPS(0x1d8) +tl1_resv1e0: BTRAPS(0x1e0) BTRAPS(0x1e8) +tl1_resv1f0: BTRAPS(0x1f0) BTRAPS(0x1f8) + + .section ".data" + .align 8 + .globl tlb_handler_stack_top, tlb_handler_stack_pointer, obp_ticks_pointer + + ! Stack for the tlb MMU trap handlers +tlb_handler_stack_bottom: + .skip 8192 +tlb_handler_stack_top: + .skip 8 + + ! MMU trap handler stack pointer +tlb_handler_stack_pointer: + .xword tlb_handler_stack_top + + ! Pointer to current tick value +obp_ticks_pointer: + .xword 0 + + .section ".text", "ax" + +spill_32bit: + srl %sp, 0, %sp + stw %l0, [%sp + 0x00] + stw %l1, [%sp + 0x04] + stw %l2, [%sp + 0x08] + stw %l3, [%sp + 0x0c] + stw %l4, [%sp + 0x10] + stw %l5, [%sp + 0x14] + stw %l6, [%sp + 0x18] + stw %l7, [%sp + 0x1c] + stw %i0, [%sp + 0x20] + stw %i1, [%sp + 0x24] + stw %i2, [%sp + 0x28] + stw %i3, [%sp + 0x2c] + stw %i4, [%sp + 0x30] + stw %i5, [%sp + 0x34] + stw %i6, [%sp + 0x38] + stw %i7, [%sp + 0x3c] + saved + retry + +fill_32bit: + srl %sp, 0, %sp + lduw [%sp + 0x00], %l0 + lduw [%sp + 0x04], %l1 + lduw [%sp + 0x08], %l2 + lduw [%sp + 0x0c], %l3 + lduw [%sp + 0x10], %l4 + lduw [%sp + 0x14], %l5 + lduw [%sp + 0x18], %l6 + lduw [%sp + 0x1c], %l7 + lduw [%sp + 0x20], %i0 + lduw [%sp + 0x24], %i1 + lduw [%sp + 0x28], %i2 + lduw [%sp + 0x2c], %i3 + lduw [%sp + 0x30], %i4 + lduw [%sp + 0x34], %i5 + lduw [%sp + 0x38], %i6 + lduw [%sp + 0x3c], %i7 + restored + retry + +/* + * SAVE_CPU_STATE and RESTORE_CPU_STATE are macros used to enable a context switch + * to C to occur within the MMU I/D TLB miss handlers. + * + * Because these handlers are called on a TLB miss, we cannot use flushw to store + * processor window state on the stack, as the memory areas used by each window's + * stack pointer may not be in the TLB, causing recursive TLB miss traps. + * + * For this reason, we save window state by manually rotating the window registers + * and saving their contents (along with other vital registers) into a special + * tlb_handler_stack defined above which is guaranteed to be locked in the TLB, and + * so won't cause issues with trap recursion. + * + * Once this process is complete, we remain in a TL=0, CWP=0 state (with IE=1 to allow + * window fill/spill traps if required), switch to our safe tlb_handler_stack and + * invoke the miss handler. + */ + +#define SAVE_CPU_STATE(type) \ + /* Set up our exception stack pointer in %g1 */ \ + setx tlb_handler_stack_pointer, %g7, %g6; \ + ldx [%g6], %g1; \ + add %g1, -0x510, %g1; \ + \ + /* First save the various state registers */ \ + rdpr %cwp, %g7; \ + stx %g7, [%g1]; \ + rdpr %cansave, %g7; \ + stx %g7, [%g1 + 0x8]; \ + rdpr %canrestore, %g7; \ + stx %g7, [%g1 + 0x10]; \ + rdpr %otherwin, %g7; \ + stx %g7, [%g1 + 0x18]; \ + rdpr %wstate, %g7; \ + stx %g7, [%g1 + 0x20]; \ + rdpr %cleanwin, %g7; \ + stx %g7, [%g1 + 0x28]; \ + rdpr %pstate, %g7; \ + stx %g7, [%g1 + 0x30]; \ + \ + rd %y, %g7; \ + stx %g7, [%g1 + 0x38]; \ + rd %fprs, %g7; \ + stx %g7, [%g1 + 0x40]; \ + \ + rdpr %tl, %g7; \ + stx %g7, [%g1 + 0x48]; \ + \ + /* Trap state */ \ + add %g1, 0x50, %g5; \ + mov 4, %g6; \ + \ +save_trap_state_##type: \ + deccc %g6; \ + wrpr %g6, %tl; \ + rdpr %tpc, %g7; \ + stx %g7, [%g5]; \ + rdpr %tnpc, %g7; \ + stx %g7, [%g5 + 0x8]; \ + rdpr %tstate, %g7; \ + stx %g7, [%g5 + 0x10]; \ + rdpr %tt, %g7; \ + stx %g7, [%g5 + 0x18]; \ + bne save_trap_state_##type; \ + add %g5, 0x20, %g5; \ + \ + /* For 4 trap levels with 4 registers, memory required is + 4*8*4 = 0x80 bytes */ \ + \ + /* Save the o registers */ \ + stx %o0, [%g1 + 0xd0]; \ + stx %o1, [%g1 + 0xd8]; \ + stx %o2, [%g1 + 0xe0]; \ + stx %o3, [%g1 + 0xe8]; \ + stx %o4, [%g1 + 0xf0]; \ + stx %o5, [%g1 + 0xf8]; \ + stx %o6, [%g1 + 0x100]; \ + stx %o7, [%g1 + 0x108]; \ + \ + /* Now iterate through all of the windows saving all l and i registers */ \ + add %g1, 0x110, %g5; \ + \ + /* Get the number of windows in %g6 */ \ + rdpr %ver, %g6; \ + and %g6, 0xf, %g6; \ + inc %g6; \ + \ +save_cpu_window_##type: \ + deccc %g6; \ + wrpr %g6, %cwp; \ + stx %l0, [%g5]; \ + stx %l1, [%g5 + 0x8]; \ + stx %l2, [%g5 + 0x10]; \ + stx %l3, [%g5 + 0x18]; \ + stx %l4, [%g5 + 0x20]; \ + stx %l5, [%g5 + 0x28]; \ + stx %l6, [%g5 + 0x30]; \ + stx %l7, [%g5 + 0x38]; \ + stx %i0, [%g5 + 0x40]; \ + stx %i1, [%g5 + 0x48]; \ + stx %i2, [%g5 + 0x50]; \ + stx %i3, [%g5 + 0x58]; \ + stx %i4, [%g5 + 0x60]; \ + stx %i5, [%g5 + 0x68]; \ + stx %i6, [%g5 + 0x70]; \ + stx %i7, [%g5 + 0x78]; \ + bne save_cpu_window_##type; \ + add %g5, 0x80, %g5; \ + \ + /* For 8 windows with 16 registers to save in the window, memory required + is 16*8*8 = 0x400 bytes */ \ + \ + /* Now we should be in window 0 so update the other window registers */ \ + rdpr %ver, %g6; \ + and %g6, 0xf, %g6; \ + dec %g6; \ + wrpr %g6, %cansave; \ + \ + wrpr %g0, %cleanwin; \ + wrpr %g0, %canrestore; \ + wrpr %g0, %otherwin; \ + \ + /* Update our exception stack pointer */ \ + setx tlb_handler_stack_pointer, %g7, %g6; \ + stx %g1, [%g6]; + + +#define RESTORE_CPU_STATE(type) \ + /* Set up our exception stack pointer in %g1 */ \ + setx tlb_handler_stack_pointer, %g7, %g6; \ + ldx [%g6], %g1; \ + \ + /* Get the number of windows in %g6 */ \ + rdpr %ver, %g6; \ + and %g6, 0xf, %g6; \ + inc %g6; \ + \ + /* Now iterate through all of the windows restoring all l and i registers */ \ + add %g1, 0x110, %g5; \ + \ +restore_cpu_window_##type: \ + deccc %g6; \ + wrpr %g6, %cwp; \ + ldx [%g5], %l0; \ + ldx [%g5 + 0x8], %l1; \ + ldx [%g5 + 0x10], %l2; \ + ldx [%g5 + 0x18], %l3; \ + ldx [%g5 + 0x20], %l4; \ + ldx [%g5 + 0x28], %l5; \ + ldx [%g5 + 0x30], %l6; \ + ldx [%g5 + 0x38], %l7; \ + ldx [%g5 + 0x40], %i0; \ + ldx [%g5 + 0x48], %i1; \ + ldx [%g5 + 0x50], %i2; \ + ldx [%g5 + 0x58], %i3; \ + ldx [%g5 + 0x60], %i4; \ + ldx [%g5 + 0x68], %i5; \ + ldx [%g5 + 0x70], %i6; \ + ldx [%g5 + 0x78], %i7; \ + bne restore_cpu_window_##type; \ + add %g5, 0x80, %g5; \ + \ + /* Restore the window registers to their original value */ \ + ldx [%g1], %g7; \ + wrpr %g7, %cwp; \ + ldx [%g1 + 0x8], %g7; \ + wrpr %g7, %cansave; \ + ldx [%g1 + 0x10], %g7; \ + wrpr %g7, %canrestore; \ + ldx [%g1 + 0x18], %g7; \ + wrpr %g7, %otherwin; \ + ldx [%g1 + 0x20], %g7; \ + wrpr %g7, %wstate; \ + ldx [%g1 + 0x28], %g7; \ + wrpr %g7, %cleanwin; \ + ldx [%g1 + 0x30], %g7; \ + wrpr %g7, %pstate; \ + \ + /* Restore the o registers */ \ + ldx [%g1 + 0xd0], %o0; \ + ldx [%g1 + 0xd8], %o1; \ + ldx [%g1 + 0xe0], %o2; \ + ldx [%g1 + 0xe8], %o3; \ + ldx [%g1 + 0xf0], %o4; \ + ldx [%g1 + 0xf8], %o5; \ + ldx [%g1 + 0x100], %o6; \ + ldx [%g1 + 0x108], %o7; \ + \ + /* Restore the trap state */ \ + add %g1, 0x50, %g5; \ + mov 4, %g6; \ + \ +restore_trap_state_##type: \ + deccc %g6; \ + wrpr %g6, %tl; \ + ldx [%g5], %g7; \ + wrpr %g7, %tpc; \ + ldx [%g5 + 0x8], %g7; \ + wrpr %g7, %tnpc; \ + ldx [%g5 + 0x10], %g7; \ + wrpr %g7, %tstate; \ + ldx [%g5 + 0x18], %g7; \ + wrpr %g7, %tt; \ + bne restore_trap_state_##type; \ + add %g5, 0x20, %g5; \ + \ + ldx [%g1 + 0x38], %g7; \ + wr %g7, 0, %y; \ + ldx [%g1 + 0x40], %g7; \ + wr %g7, 0, %fprs; \ + ldx [%g1 + 0x48], %g7; \ + wrpr %g7, %tl; \ + \ + /* Restore exception stack pointer to previous value */ \ + setx tlb_handler_stack_pointer, %g7, %g6; \ + add %g1, 0x510, %g1; \ + stx %g1, [%g6]; + + + .globl reload_DMMU_tlb, reload_IMMU_tlb, bug + +reload_DMMU_tlb: + + SAVE_CPU_STATE(dtlb) + + /* Switch to TLB locked stack space (note we add an additional 192 bytes required for + gcc to save its arguments when building with -O0) */ + add %g1, -STACK_BIAS - 192, %sp + + /* Enable interrupts for window spill/fill traps */ + rdpr %pstate, %g7 + or %g7, PSTATE_IE, %g7 + wrpr %g7, %pstate + + call dtlb_miss_handler + nop + + /* Disable interrupts */ + rdpr %pstate, %g7 + andn %g7, PSTATE_IE, %g7 + wrpr %g7, %pstate + + RESTORE_CPU_STATE(dtlb) + + retry + +reload_IMMU_tlb: + + SAVE_CPU_STATE(itlb) + + /* Switch to TLB locked stack space (note we add an additional 192 bytes required for + gcc to save its arguments when building with -O0) */ + add %g1, -STACK_BIAS - 192, %sp + + /* Enable interrupts for window spill/fill traps */ + rdpr %pstate, %g7 + or %g7, PSTATE_IE, %g7 + wrpr %g7, %pstate + + call itlb_miss_handler + nop + + /* Disable interrupts */ + rdpr %pstate, %g7 + andn %g7, PSTATE_IE, %g7 + wrpr %g7, %pstate + + RESTORE_CPU_STATE(itlb) + + retry + +softint_irq_tl1: +softint_irq: + mov 1, %g2 + /* clear tick interrupt */ + wr %g2, 0x0, %clear_softint + sll %g2, %g1, %g2 + sra %g2, 0, %g2 + /* clear softint interrupt */ + wr %g2, 0x0, %clear_softint + + setx TICK_INT_DIS, %g2, %g1 + rd %tick, %g2 + and %g1, %g2, %g1 + brnz,pn %g1, tick_compare_disabled + nop + + /* update tick value if pointer set */ + setx obp_ticks_pointer, %g3, %g1 + ldx [%g1], %g3 + brz %g3, tick_rearm + nop + + ldx [%g3], %g1 + add %g1, 10, %g1 ! 100Hz = 10ms + stx %g1, [%g3] + +tick_rearm: + set TICK_INTERVAL, %g1 + add %g1, %g2, %g1 + wr %g1, 0, %tick_cmpr +tick_compare_disabled: + retry + +handler_irq: +__divide_error: +bug: + /* Dump the exception and its context */ + ! Set up CPU state + ! Don't change the global register set or we lose %g1 (exception level) + rdpr %pstate, %g2 + or %g2, PSTATE_PRIV, %g2 + wrpr %g2, %pstate + wr %g0, 0, %fprs + + ! Jump to ROM ... + setx _start, %g2, %g3 + setx highmem, %g2, %g4 + sub %g4, %g3, %g4 + setx PROM_ADDR, %g2, %g3 + add %g4, %g3, %g3 + jmp %g3 + ! ... while disabling I/D MMUs and caches + stxa %g0, [%g0] ASI_LSU_CONTROL + +highmem: + ! Extract NWINDOWS from %ver + rdpr %ver, %g2 + and %g2, 0xf, %g2 + wrpr %g2, 0, %cleanwin + wrpr %g2, 0, %cansave + wrpr %g0, 0, %canrestore + wrpr %g0, 0, %otherwin + wrpr %g0, 0, %wstate + + b dump_exception + nop + +outstr: + /* void outstr (unsigned long port, const unsigned char *str); + * Writes a string on an IO port. + */ +1: ldub [%o1], %o3 + cmp %o3, 0 + be 2f + nop + stba %o3, [%o0] ASI_BP + b 1b + inc %o1 +2: retl + nop + +outdigit: + /* void outdigit (unsigned long port, uint8_t digit); + * Dumps a single digit on serial port. + */ + add %o1, '0', %o1 + retl + stba %o1, [%o0] ASI_BP + +outhex: + /* void outhex (unsigned long port, uint64_t value); + * Dumps a 64 bits hex number on serial port + */ + mov %o1, %o2 + set 60, %o3 + srlx %o2, %o3, %o1 +1: and %o1, 0xf, %o1 + cmp %o1, 9 + bgt 2f + nop + b 3f + add %o1, '0', %o1 +2: add %o1, 'a' - 10, %o1 +3: stba %o1, [%o0] ASI_BP + subcc %o3, 4, %o3 + bge 1b + srlx %o2, %o3, %o1 + retl + nop + + /* void dump_exception (); + * + * Dump a message when catching an exception + */ +dump_exception: + setx SER_ADDR, %o3, %o0 + set _start, %g3 + set (_BUG_message_0), %o1 + sub %o1, %g3, %g4 + setx PROM_ADDR, %g2, %g3 + add %g4, %g3, %g3 + call outstr + mov %g3, %o1 + + call outhex + mov %g1, %o1 + + call outstr + add %g3, (_BUG_message_1 - _BUG_message_0), %o1 + + call outhex + rdpr %tpc, %o1 + + call outstr + add %g3, (_BUG_message_2 - _BUG_message_0), %o1 + + call outhex + rdpr %tnpc, %o1 + + call outstr + add %g3, (_BUG_message_3 - _BUG_message_0), %o1 + +_forever: + /* Loop forever */ + b _forever ; + nop + + .section .rodata +_BUG_message_0: + .string "Unhandled Exception 0x" +_BUG_message_1: + .string "\nPC = 0x" +_BUG_message_2: + .string " NPC = 0x" +_BUG_message_3: + .string "\nStopping execution\n" diff --git a/qemu/roms/openbios/arch/unix/Kconfig b/qemu/roms/openbios/arch/unix/Kconfig new file mode 100644 index 000000000..8faafc0af --- /dev/null +++ b/qemu/roms/openbios/arch/unix/Kconfig @@ -0,0 +1,18 @@ + +config HOST_UNIX + bool "Build Hosted Unix binary" + default y + help + Build a version of the OpenBIOS kernel that runs in a + Unix-like operating system. + +config UNIX_QT + depends HOST_UNIX + bool "QT frontend for Unix binary" + default n + help + Enable this option if you wish to add a graphical user + interface to the openbios hosted unix binary. This option + needs the QT library installed. + +source "arch/unix/plugins/Kconfig" diff --git a/qemu/roms/openbios/arch/unix/Makefile b/qemu/roms/openbios/arch/unix/Makefile new file mode 100644 index 000000000..a8c6565e9 --- /dev/null +++ b/qemu/roms/openbios/arch/unix/Makefile @@ -0,0 +1,29 @@ +# + +include ../../config/Makefile.top + +SUBDIRS-$(CONFIG_PLUGINS) = plugins +SUBDIRS-$(CONFIG_UNIX_QT) = gui_qt + +DICTIONARIES = unix +unix-SRC = tree.fs $(ARCHDICT_SRC) + +PROGRAMS = unix + +unix-OBJS = $(unix-y) +unix-y += blk.o +unix-y += boot.o +unix-y += unix.o +unix-y += $(KOBJS) +unix-y += $(MODULE_LIBS) $(FS_LIBS) $(DRIVER_LIBS) $(LIBC_LIBS) +unix-$(CONFIG_PLUGINS) += plugins.o + +unix-LDFLAGS = $(unix-LDFLAGS-$(CONFIG_PLUGINS)) +unix-LDFLAGS-y = -rdynamic $(LIBDL_LDFLAGS) +unix-LDFLAGS-n = +unix-LDADD = + +INCLUDES = -I../../kernel -I../../kernel/include -DBOOTSTRAP + +include $(rules)/Rules.forth +include $(rules)/Rules.make diff --git a/qemu/roms/openbios/arch/unix/blk.c b/qemu/roms/openbios/arch/unix/blk.c new file mode 100644 index 000000000..d0f5c6a42 --- /dev/null +++ b/qemu/roms/openbios/arch/unix/blk.c @@ -0,0 +1,115 @@ +/* + * <arch/unix/blk.c> + * + * block device emulation for unix hosts + * + * Copyright (C) 2004 Stefan Reinauer <stepan@openbios.org> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#include "config.h" +#include "libopenbios/bindings.h" +#include "blk.h" + +typedef struct { + int unit; + int channel; +} blk_data_t; + + +DECLARE_NODE( blk, INSTALL_OPEN, sizeof(blk_data_t), "+/unix/block/disk" ); + +static void +blk_open( blk_data_t *pb ) +{ + phandle_t ph; + + fword("my-unit"); + + pb->unit = POP(); + pb->channel = 0; /* FIXME */ + + selfword("open-deblocker"); + + /* interpose disk-label */ + ph = find_dev("/packages/disk-label"); + fword("my-args"); + PUSH_ph( ph ); + fword("interpose"); + + /* printk("osi-blk: open %d\n", pb->unit ); */ + + PUSH( -1 ); +} + +static void +blk_close( __attribute__((unused)) blk_data_t *pb ) +{ + selfword("close-deblocker"); +} + + +/* ( buf blk nblks -- actual ) */ +static void +blk_read_blocks( blk_data_t *pb ) +{ + cell i, n = POP(); + cell blk = POP(); + char *dest = (char*)POP(); + + // printk("blk_read_blocks %x block=%d n=%d\n", (ucell)dest, blk, n ); + + for( i=0; i<n; ) { + char buf[4096]; + ucell m = MIN( n-i, sizeof(buf)/512 ); + + if( read_from_disk(pb->channel, pb->unit, blk+i, (ucell)buf, m*512) < 0 ) { + printk("read_from_disk: error\n"); + RET(0); + } + memcpy( dest, buf, m * 512 ); + i += m; + dest += m * 512; + } + PUSH( n ); +} + +/* ( -- bs ) */ +static void +blk_block_size( __attribute__((unused)) blk_data_t *pb ) +{ + PUSH( 512 ); +} + +/* ( -- maxbytes ) */ +static void +blk_max_transfer( __attribute__((unused)) blk_data_t *pb ) +{ + PUSH( 1024*1024 ); +} + +static void +blk_initialize( __attribute__((unused)) blk_data_t *pb ) +{ + fword("is-deblocker"); +} + + +NODE_METHODS( blk ) = { + { NULL, blk_initialize }, + { "open", blk_open }, + { "close", blk_close }, + { "read-blocks", blk_read_blocks }, + { "block-size", blk_block_size }, + { "max-transfer", blk_max_transfer}, +}; + +void +blk_init( void ) +{ + REGISTER_NODE( blk ); +} diff --git a/qemu/roms/openbios/arch/unix/blk.h b/qemu/roms/openbios/arch/unix/blk.h new file mode 100644 index 000000000..aa3b96560 --- /dev/null +++ b/qemu/roms/openbios/arch/unix/blk.h @@ -0,0 +1,8 @@ + +#ifndef _H_BLK +#define _H_BLK + +extern void blk_init( void ); +extern int read_from_disk( int channel, int unit, int blk, unsigned long mphys, int size ); + +#endif /* _H_BLK */ diff --git a/qemu/roms/openbios/arch/unix/boot.c b/qemu/roms/openbios/arch/unix/boot.c new file mode 100644 index 000000000..f4a29428b --- /dev/null +++ b/qemu/roms/openbios/arch/unix/boot.c @@ -0,0 +1,84 @@ +/* + * + */ +#undef BOOTSTRAP +#include "config.h" +#include "libopenbios/bindings.h" +#include "libopenbios/elf_load.h" +#include "arch/common/nvram.h" +#include "libc/diskio.h" + +void boot(void); +void *load_elf(char *spec); + +void +*load_elf(char *spec) +{ +#if 0 + int fd; + void *entry=NULL; + int i, lszz_offs, elf_offs; + char buf[128]; // , *addr; + Elf_ehdr ehdr; + Elf_phdr *phdr; + size_t s; + + if( (fd=open_io(spec)) == -1 ) + return NULL; + + if( (elf_offs=find_elf(fd)) < 0 ) { + printk("----> %s is not an ELF image\n", buf ); + return NULL; + } + + if( !(phdr=elf_readhdrs(fd, 0, &ehdr)) ) { + printk("elf32_readhdrs failed\n"); + return NULL; + } + + (unsigned long long *)entry = ehdr.e_entry; + + lszz_offs = elf_offs; + for( i=0; i<ehdr.e_phnum; i++ ) { + s = MIN( phdr[i].p_filesz, phdr[i].p_memsz ); + seek_io( fd, elf_offs + phdr[i].p_offset ); + /* printk("filesz: %08lX memsz: %08lX p_offset: %08lX p_vaddr %08lX\n", + phdr[i].p_filesz, phdr[i].p_memsz, phdr[i].p_offset, + phdr[i].p_vaddr ); */ + if( phdr[i].p_vaddr != phdr[i].p_paddr ) + printk("WARNING: ELF segment virtual addr != physical addr\n"); + lszz_offs = MAX( lszz_offs, elf_offs + phdr[i].p_offset + phdr[i].p_filesz ); + if( !s ) + continue; + + printk("ELF ROM-section loaded at %08lX (size %08lX)\n", + (unsigned long)phdr[i].p_vaddr, (unsigned long)phdr[i].p_memsz); + } + free( phdr ); + return entry; +#else + return NULL; +#endif +} + +void +boot( void ) +{ + char *path; + void *entry; + + /* Copy the incoming path */ + fword("2dup"); + path = pop_fstr_copy(); + + if(!path) { + printk("[unix] Booting default not supported.\n"); + return; + } + printk("[unix] Booting '%s'\n",path); + entry=load_elf(path); + if(entry) + printk("successfully loaded client at %llx.\n", (unsigned long long)(ucell)entry); + else + printk("failed.\n"); +} diff --git a/qemu/roms/openbios/arch/unix/build.xml b/qemu/roms/openbios/arch/unix/build.xml new file mode 100644 index 000000000..bc0cf9e74 --- /dev/null +++ b/qemu/roms/openbios/arch/unix/build.xml @@ -0,0 +1,23 @@ +<build condition="HOST_UNIX"> + + <dictionary name="openbios-unix" init="openbios" target="forth"> + <object source="tree.fs"/> + </dictionary> + + <executable name="openbios-unix" target="target"> + <rule> + $(call quiet-command,$(CC) $(CFLAGS) -rdynamic $(LIBDL_LDFLAGS) -o $@ $^," LINK $(TARGET_DIR)$@") + </rule> + <object source="unix.c" flags="-DBOOTSTRAP"/> + <object source="boot.c" flags="-DBOOTSTRAP"/> + <object source="blk.c" flags="-DBOOTSTRAP"/> + <object source="plugins.c" flags="-DBOOTSTRAP" condition="PLUGINS"/> + <external-object source="libbootstrap.a"/> + <external-object source="libpackages.a"/> + <external-object source="libopenbios.a"/> + <external-object source="libdrivers.a"/> + <external-object source="libfs.a"/> + <external-object source="liblibc.a"/> + </executable> + +</build> diff --git a/qemu/roms/openbios/arch/unix/gui_qt/Makefile b/qemu/roms/openbios/arch/unix/gui_qt/Makefile new file mode 100644 index 000000000..20eb15809 --- /dev/null +++ b/qemu/roms/openbios/arch/unix/gui_qt/Makefile @@ -0,0 +1,42 @@ +# +# Makefile of QT user interface for OpenBIOS +# +# (C) 2004 Stefan Reinauer <stepan@openbios.org> +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# version 2 +# + +include ../../../config/Makefile.top + +XTARGETS = qt + +qt-OBJS = $(obj-y) +obj-y += gui_qt.o + +QMAKE = qmake +UIDIR = $(shell pwd ) +TOPDIR = $(shell cd $(top_srcdir) ; pwd) +ABSOINC = $(shell cd $(ARCHINCLUDES) 2> /dev/null ; pwd ) + +export UIDIR TOPDIR ABSOINC + +$(ODIR)/makefile.qmake: gui-qt.pro Makefile + @echo "ODIR: $(ODIR)" + @test -d $(ODIR) || $(INSTALL) -d $(ODIR) + @test -d $(ODIR)/qbuild || $(INSTALL) -d $(ODIR)/qbuild + @install -m 644 gui-qt.pro $(ODIR)/ + cd $(ODIR) ; $(QMAKE) -o makefile.qmake + +$(ODIR)/libgui_qt.a: $(ODIR)/makefile.qmake $(wildcard *.cpp) + cd $(ODIR) ; $(MAKE) -f makefile.qmake + @ln -f $(ODIR)/qbuild/libgui_qt.a $@ + +clean-local: + @rm -f $(ODIR)/makefile.qmake + @rm -rf $(QBUILDDIR) + +INCLUDES = -I$(top_srcdir)/include -DBOOTSTRAP + +include $(rules)/Rules.make diff --git a/qemu/roms/openbios/arch/unix/gui_qt/gui-qt.cpp b/qemu/roms/openbios/arch/unix/gui_qt/gui-qt.cpp new file mode 100644 index 000000000..24c084283 --- /dev/null +++ b/qemu/roms/openbios/arch/unix/gui_qt/gui-qt.cpp @@ -0,0 +1,128 @@ +/* tag: qt user interface fb class + * + * Copyright (C) 2003-2004 Stefan Reinauer + * + * See the file "COPYING" for further information about + * the copyright and warranty status of this work. + */ + +#include "gui-qt.h" +#include "logo.xpm" + +#include <iostream> + +static const int sizex=640; +static const int sizey=480; +static const int depth=8; + +static unsigned char color[256][3]={ + { 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0xaa }, + { 0x00, 0xaa, 0x00 }, + { 0x00, 0xaa, 0xaa }, + { 0xaa, 0x00, 0x00 }, + { 0xaa, 0x00, 0xaa }, + { 0xaa, 0x55, 0x00 }, + { 0xaa, 0xaa, 0xaa }, + { 0x55, 0x55, 0x55 }, + { 0x55, 0x55, 0xff }, + { 0x55, 0xff, 0x55 }, + { 0x55, 0xff, 0xff }, + { 0xff, 0x55, 0x55 }, + { 0xff, 0x55, 0xff }, + { 0xff, 0xff, 0x55 }, + { 0xff, 0xff, 0xff }, +}; + +FrameBufferWidget::FrameBufferWidget(QWidget *parent, const char * name) +: QWidget(parent, name, Qt::WType_TopLevel) +{ + setCaption ("OpenBIOS"); + setIcon(QPixmap(logo)); + + QPopupMenu *file = new QPopupMenu (this); + + file->insertItem( "E&xit", this, SLOT(quit()), CTRL+Key_Q ); + + QPopupMenu *help = new QPopupMenu( this ); + help->insertItem("&About OpenBIOS", this, SLOT(about()), CTRL+Key_H ); + help->insertItem( "About &Qt", this, SLOT(aboutQt()) ); + + menu = new QMenuBar( this ); + Q_CHECK_PTR( menu ); + menu->insertItem( "&File", file ); + menu->insertSeparator(); + menu->insertItem( "&Help", help ); + menu->setSeparator( QMenuBar::InWindowsStyle ); + + setFixedSize(sizex,sizey+menu->heightForWidth(sizex)); + + buffer.create(sizex, sizey, depth, 256); + + for (int i=16; i < 256; i++) { + color[i][0]=i; + color[i][1]=i; + color[i][2]=i; + } + + for (int i=0; i< 256; i++) + buffer.setColor(i, qRgb(color[i][0], color[i][1], color[i][2])); + + buffer.fill( 0 ); + + updatetimer=new QTimer(this); + connect( updatetimer, SIGNAL(timeout()), this, SLOT(update()) ); + updatetimer->start(200,FALSE); + + setMouseTracking( TRUE ); +} + +unsigned char * FrameBufferWidget::getFrameBuffer(void) +{ + return buffer.bits(); +} + +void FrameBufferWidget::paintEvent ( QPaintEvent * ) +{ + QPainter p( this ); + p.drawImage(0,menu->heightForWidth(sizex),buffer, 0,0, sizex, sizey); +} + +void FrameBufferWidget::about() +{ + QMessageBox::about( this, "About OpenBIOS", + " Welcome to OpenBIOS 1.01\n" + " IEEE 1275-1994 Open Firmware implementation\n\n" + "written by Stefan Reinauer <stepan@openbios.org>\n\n" + " http://www.openbios.org/\n"); +} + +void FrameBufferWidget::aboutQt() +{ + QMessageBox::aboutQt( this, "OpenBIOS" ); +} + +void FrameBufferWidget::quit() +{ + extern volatile int gui_running; + extern volatile int runforth; + + gui_running=0; + interruptforth=1; + + qApp->quit(); +} + +void FrameBufferWidget::update() +{ + QPainter p( this ); + p.drawImage(0,menu->heightForWidth(sizex),buffer, 0,0, sizex, sizey); +} + +void FrameBufferWidget::keyPressEvent(QKeyEvent * e) +{ + int a=e->ascii(); + if (a) { + std::cout << " key '" << e->text() << "' pressed" << std::endl; + } +} diff --git a/qemu/roms/openbios/arch/unix/gui_qt/gui-qt.h b/qemu/roms/openbios/arch/unix/gui_qt/gui-qt.h new file mode 100644 index 000000000..202619f7e --- /dev/null +++ b/qemu/roms/openbios/arch/unix/gui_qt/gui-qt.h @@ -0,0 +1,44 @@ +/* tag: qt user interface fb class description + * + * Copyright (C) 2003-2004 Stefan Reinauer <stepan@openbios.org> + * + * See the file "COPYING" for further information about + * the copyright and warranty status of this work. + */ + +#ifndef __framebufferwidget_h +#define __framebufferwidget_h + +#include <qapplication.h> +#include <qwidget.h> +#include <qimage.h> +#include <qpainter.h> +#include <qmenubar.h> +#include <qpopupmenu.h> +#include <qmessagebox.h> +#include <qstatusbar.h> +#include <qtimer.h> + +class FrameBufferWidget : public QWidget { + Q_OBJECT + public: + FrameBufferWidget(QWidget *parent=0, const char *name=0); + unsigned char *getFrameBuffer(void); + + public slots: + void quit(); + void about(); + void aboutQt(); + void update(); + + private: + QImage buffer; + QMenuBar *menu; + QStatusBar *status; + QTimer *updatetimer; + void paintEvent ( QPaintEvent * ); + protected: + void keyPressEvent(QKeyEvent * e); +}; + +#endif diff --git a/qemu/roms/openbios/arch/unix/gui_qt/gui-qt.pro b/qemu/roms/openbios/arch/unix/gui_qt/gui-qt.pro new file mode 100644 index 000000000..f58baecff --- /dev/null +++ b/qemu/roms/openbios/arch/unix/gui_qt/gui-qt.pro @@ -0,0 +1,18 @@ +# tag: qmake project file for OpenBIOS QT user interface +# +# Copyright (C) 2003-2004 Stefan Reinauer <stepan@openbios.org> +# +# See the file "COPYING" for further information about +# the copyright and warranty status of this work. +# + +TEMPLATE = lib +CONFIG += qt thread warn_on release staticlib +LIBS = +INCLUDEPATH = qbuild $(ABSOINC) $(TOPDIR)/include +DESTDIR = qbuild +OBJECTS_DIR = qbuild +MOC_DIR = qbuild +TARGET = gui_qt +HEADERS = $(UIDIR)/gui-qt.h +SOURCES = $(UIDIR)/gui-qt.cpp $(UIDIR)/qt-main.cpp diff --git a/qemu/roms/openbios/arch/unix/gui_qt/logo.xpm b/qemu/roms/openbios/arch/unix/gui_qt/logo.xpm new file mode 100644 index 000000000..9e2ac60b4 --- /dev/null +++ b/qemu/roms/openbios/arch/unix/gui_qt/logo.xpm @@ -0,0 +1,132 @@ +/* This logo was created by Stephan Lau, + * created to xpm by Stefan Reinauer + */ +static char *logo[] = { +/* columns rows colors chars-per-pixel */ +"300 80 44 1", +" c #010101", +". c #070709", +"X c #0B0B0B", +"o c #0F0F11", +"O c #121212", +"+ c #1B1B1B", +"@ c #1F1F21", +"# c #232323", +"$ c #262628", +"% c #2B2B2C", +"& c #2E2E30", +"* c #333333", +"= c #373739", +"- c #3B3B3B", +"; c #434343", +": c #464648", +"> c #4B4B4B", +", c #4E4E50", +"< c #535353", +"1 c #5B5B5B", +"2 c #5E5E60", +"3 c #646464", +"4 c #666668", +"5 c #6B6B6B", +"6 c #747474", +"7 c #767678", +"8 c #7B7B7B", +"9 c #838383", +"0 c #8A8A8A", +"q c #939394", +"w c #979799", +"e c #9B9B9B", +"r c #A3A3A3", +"t c #ABABAB", +"y c #B4B4B4", +"u c #BBBBBB", +"i c #C3C3C3", +"p c #CBCBCB", +"a c #D3D3D3", +"s c #DBDBDB", +"d c #E3E3E3", +"f c #EBEBEB", +"g c #F3F3F3", +"h c #FEFEFE", +/* pixels */ +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhgfdssaapuuuytteeewq0009998867666555555555555565666778899000qwwerttyyuuppassdfghhhhhhhhhhgfgggghhhgfgfghhhhggffghhhhggffghhhhgfggghhhhgfggghhhhgfgfghhhhfgfgghhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhfdsapuytrwq0986555554455555555555555555555555555555555555555555555555555555555555555555555555556790qertyiuuuafhhhfpiishhhhfipidhhhhfiiidhhhhdiiifhhhhsiiifhhhhsiipghhhhaiipghhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhgfdaiuttq0976555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555558iuue5579wuuuuiasfduuishhhhduuudhhhhduuudhhhhsuuufhhhhauuughhhhauuughhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhfdaittw086555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555558yuur55549uuiw55569uuutyiadsuuudhhhhsuuudhhhhsuuufhhhhauuughhhhauuughhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhgfapyrw975555555555555555555555555555555555555555555555555555555555555555555555555555555554555555555555555555554455555555555555555555558uuue54559uuuw55559uuuq55550uiutypafduuufhhhhsuuufhhhhsuuufhhhhauuughhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhgdautw965555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555679qqerttuuppaasdddffgghghhhhhhhhhghhggfduuupaappuuuuyeq090uuuq55559uyi05555quuuuadghsuuufhhhhauuufhhhhauuighhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhfsite0655555555555555555555555555555555555555555555555555555555555555555555555455555555555555555690wrtiiaddghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhfuuuahhhhfuuushhhhfuuuaaiittuuuq55550uuu95560tuuudhhhhsuuughhhhauuufhhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhghhhhhhhhhhhhhhhhhgsite955555555555555555555555555455555555555555555555555555555555555555555555555545555555555570wryiadfhhhhhhhhhhhhhhhhhhhhhhhhhhhhghhhhhhhhhhhhhhhhhhhhhhhguuuahhhhfuuuahhhhfuuushhhhduuudfsaiuuuuq5555qiuu99etipuuifhhhhauuughhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhgaut0655555555555555555555555555555555555555555555556555555555555555555555555555555555554559qruisfhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhgdsdfhhhhgdddfhhhhfddsfhhhhgdddfhhhhfddsffspyteeq755559qetisfhgfdddghhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhgsir065555555555555555555555555555455555555555555555554555555555555555555555555555555555580rupsghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhsuudhhhhhhhhhhhhfuuphhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhgspyt085555560tudghhhhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhgaue9555555555555555554<----=---=---==-==<555555---:3:--=--=-*--==--<55555545<;------==->135890phhhhhy009tfq0009009090909wshhhhhhg<;;:;;;:<9fhhhhhhhf$ rhhhhhs3# ;phhhhhhhf0# Owghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdpue0655559wuaghhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhgsue855555455555555555555:O. *5455- *. &44555>O 6ghhh+ 5O ehghhh9 . Xighhhhh9 -gfggf3 +sddffd8O rddffffffffgffffgffffffffggffffffffgffffgffdaute09868eusghhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhfpr955555555555555555555555% .%=************& +2555o +=************% +3343% X-<3568888787884. ;dggq. O19888888888888, 8fgghsO . 1fggghsO ysdfiO 9ttuu> . 1rtuyuuuuuuuuuuuuiuuuuuuuuuuuuuuuuuuuuuuuuuuuiiuuuut06449rpdhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhduw85555555555555555555555555* .,111<1111111111< #113- #<<111111111111< #123- Xtssaaaaaaaaaaaaa <sdf@ Otaaaaasaaaaaaaae 9sdgg, =sdggh< 2ipa0 7etr# <etttuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuighfauw857wudhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhfie7555555555555555555555554555: =1<<<<<<<<<<<<<<& -<<3X X<<><<<<1,,<<<<<& ;7e8 9apiiiiiipiiiiii6 0ia9 8uuuiipipiiiiiii> oyisdt X%% 2iadgy Xrty6 @69& X90e; *3% 49wttuuuuuuuuuuuuuuuuuuuuuuuuuuuyuyyyuuyuuuuuuuuuuihhhhhhgayw86eifhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhar8555555555555555555555555555543. +<,>>>,>><>>>>,,:. O;:<& -:;>>><>,,<><>,:. $eytO -puuyuuuuuuuuuiutX %rytO *ytrtyuuiuuuuuuu9 1ruis%. 108- . 8tisd% <qw9X #tre> *59, -86* O47qetuuuuuuuuuuuuuuuuuuuuuuuuuuuiasddsaiuuuuuuuuuuighhhhhhhhhgatq9tahhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhgiq55555555555555555555555555555555- ;>:>:,<<<,<<<<<<# . %-;: . O:;;;>>,<<>,,<38; 5qr3 eutttuuiiiipiiii1 5wr< qreeryuiipiiipii$ X0wru8 O976& +9wya0 O999O qeq9O >3< +751. &159wtyuuuuuuuuuuuuuuuuuuuuuuuuisfhhhhhhgdpuuuuuiuuihhhhhhhhhhhhhhdierighhhhhhh", +"hhhhhhhhhhhhhhhhhfi05555555555555555555555555555555552 #>;;:,,<<<11<11<> +--;+ ;;--;><<1116qtpy -009 ,ttrrtuppaaaaaaay -q09 ;ewqrtupaaaaaaap9 10qrtX .3754X . >60tuX 387% 3w09: +3<O. 153% O:159wtyuuuuiuuuuuuuuuuuuuuuuuuaghhhhhhhhhhhdiuuuuuuighhhhhhhhhhhhhhhhfaupghhhhh", +"hhhhhhhhhhhhhhhhiq55555555555555555555555555555555555+ X;:;;><<112311212+ .---& $;-;;><138eusddd- X000% oerrrtuaadsdddddd- o090$ Xwqqetypadddsddsao .%q9qr3 $856- +160t5 $761 X9097X ;1& &54< *;159wtyuuuuuuuuuuuuuuuuuuuuuushhhhhhhhhhhhhhdpyuuuuihhhhhhhhhhhhhhhhhhhhgsdhhhh", +"hhhhhhhhhhhhhhsr555555545555555555555555555555555555, %;;-:><123333535> %---O .;--;;<5wifgfgfgt 1w04 2ewerupsffgffggft 1w05 1wqqeyasffgfgggg9 7q0wq 6665 ,360w 666O <999= %32. . <31+. +>>160rtuuuuuuuuuuuuuuuuuuuuuyshhhhhhhhhhhhhhhhfuuuuuighhhhhhhhhhhhhhhhhhhhhhhghh", +"hhhhhhhhhhhhhi05555555555555555555555555555555555555o .X;;-::<1335555454X X:--$ &:--,6rsfghhghgh# Orq0O <<<<156999090999# +rqqO +qqqetisgghhghhha >rqqe* >867# *358e* >76; #9994 . .44- o2<>++++O>><48qrtuuuuuuuuuuuuiuuuuuuuuphhhhhhhhhhhhhhhhhhsyuiuighhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhu65555555555555555555555555555555555555- *;-->>1355555554- *;--. O;-<5rpdfhhhhhhh9 7rq< 6eq, 5w0wtisdgghhhhhh< Oqwqw8 X7773 X45608 X666. 3779% ;55X. %<1356651<<369etyuuuuuuuuuuuuuuuuuuuuudhhhhhhhhhhhhhhhhhhgpyuuighhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhi755555555555555555555555555555555555553. +;--;><2555555553. O:--$ *16qtiafhghhhhhgO *rq9X @,>:><356787888787653rq9X %wqqryadfghhhhhhy 3rqqrO <669O >569q+ <66* =8781 O953 &<24698533359qryuuuuuuuuuuuiuuuuuuuuuphhhhhhhhhhhhhhhhhhhhsyuuihhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhs955555555555555555555555555555555555555% -;;;><1335555555$ -;;* %9wweypdfhhhhhhh4 eeq- 90990rtupaaaaaaaapiutee- 9qqerusfhhhhhhhh# +twqr1 @868= $867q1 @873 o5689O 166; &<36999865690etyyuuuuuuuuuuuuuuuuuuuudhhhhhhhhhhhhhhhhhhhhfiuuighhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhy55555555555555555555555555555555555555< #;--:,<3355555551 #;;-+ Xqwqetisfhghhhhhp 1eq7 >q999qrtuuipipuippuytrr8 :wqqruadfhhhhhhh9 6ewweX 363% #6689qX 276# >769, $867* +13800q9999qrtyuuuuuuuuuuuuuuuuuuuuuufhhhhhhhhhhhhhhhhhhhhhpuuihhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhh955555555555555555555555555555555555555@ .:-;;:<1335555554+ .;:-* 1wqqrupfghhhhhhh; Oeeq$ ..q0990qrtuuuuuuuuuuuuttr& XqqqetpdfghhhhhhfO *tewe> %8869q< *76< O6687X 4669$ .X159qeeeqqqrryuuuuuuuuuuuuuuuuuuuiuuighhhhhhhhhhhhhhhhhhhhhpyuighhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhh55555555555555555555555555555555555555: $;-;;,<335555554: $:-2+ +qqqeyidgghhhhhhr 1rq3 1q000rryuipiiipiiiiiuuu7 1wqwtuadghhhhhhh6 qwww0 =20979q9 X566X <679= . -8680- . >69errtrrrtyyuuuuuuuuuuuuuuuuuuuuuuihhhhhhhhhhhhhhhhhhhhhhpyuighhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhh95555555555555555555555555555555555555O X:--;><2355555553O O:162 3eqerusdghhhhhhf# $tqqO +qqqwrtipaaaaaaaaaaaaapp+ Oeqqetpsgghhhhhhs >ewqr&. ;q0998qe* >86; #7685 O6680e1 *50ettyyyyyuuuuuuuuuuuuuuuuuuuuuuuuuhhhhhhhhhhhhhhhhhhhhhhpuuihhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhht655555555555555555555555555555555555: %;-;:<1335555555& .:500X +eqerypsghhhhhhh6 Oqeq3 1qqwryiasddddddddddddsd7 8wqqtuafghhhhhhh; Oreqw7 -999qw7. +665X 4679@ :789wt6 O50etyyuuuuuuuuuuuuuuuuuuuuuuuuuiuuughhhhhhhhhhhhhhhhhhhhhpyuighhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhs955555555555555555555555555555555555% --;;>1135555553- ,0eq> =wqerisfghhhhhf9 8rwq- 9qqetpsdffgfgffgfdttgfa *rqqryadghhhhhhhq 4rqwrO *-@ 79qeu+ ,76* . *7681 O8680ruy X49etyuuuuuuuuuuuuuuuuuuuuiuuuuuuuuudhhhhhhhhhhhhhhhhhhhhgiuuuhhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhu65555555555555555555555555555555554# .4eew9 X Oqteww= #dgg; 9wqwtisfghhhhhhfX Xewqe3 %63< @70ey5 #961 X6678X 3679ruip& 48wryuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuphhhhhhhhhhhhhhhhhhhhduuuihhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhu7555555555555555554555555555555545,@X . .+>qyrre& X8O O-7utreer9=X ufg5 +ewqruadghhhhhhf; >eqweX . 451> -6qyyO 366# ;769< $769wtpaa3 O36qrtuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuighhhhhhhhhhhhhhhhhhhpyuuighhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhp95455555555555555555555555555555331:;---;><1111111117tutre8 1q999wtipaaasssaaaiutrrrruyrq09qruiasasasasassssddddaitrwetisfhghhhhhhgfautewr; -654% o56eu< =86: . O8687 6669ruada4 @160ryuuuuuuuuuuuuuuuuuuiuuuuuuuuuuuuahhhhhhhhhhhhhhhhhhsuuuuihhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhde555555555555555555555555555555331,;---;;,<<<<<1<<8tutrtt+ Or099qwtuipppppppiiuytrtyiiiteq0qryupppppppppppppssdspurreriafghhhhhhhhgdaueee8 X665< ;38e9 X765X 1679% >669wyadfd5 *150rtuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuushhghhhhhhhhhhhhhgiyuuuighhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhiq555555555555555555555555555533<<:;-;;>>,>,>,,,6ttyttt3 5q9990rttuuuuuuyuuyyttyupaapurewertyyuuuuuuuuuuuipasaputttypsgghhhhhhhggsautrt* ,667# .+159e* >86;. $6695 .8680tisfgd3 X:160rtuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuudhhhhhhhhhhhhhhgiuiuuuighhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhfi055555555555555555555555555332<>>:;:>>>,<>,>6tuuuiiuX *eq00wrryyuuuuyuuuuuyuiiasdsaputrtttuuyuyuuuuyyuupaassaiuyupsfghhhhhhhhhgdaiuy6 O967< 146q3 O865 5679O ,769wuafggfX #:150rtuuuuuuuuuuuuuuuuuuuuuuiuuuuuuuuuuushhhhhhhhhhhhfiuuuuuuighhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhfiq5555555555555555555554555431<<<,<<<<<<<15tippppa<. 0wqqetyippppppppppippaasdfgfdsapiipipppppppppppppaadddsaapasfghhhhhhhhhggfsapi+ 1678O -5589+ 176% -679, +85O rgg0 X-,36qrtuuuuuuuuuuuuiuuuuuuuuuuuuuuuuiuuuuupfghhhhhhhfauuuuuuuuighhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhat85555555555555555555555433221111111113tsssssdr >eqqetupaasaaasaasssasddfgggggfdssasassaassasaasssddffffddddfgghhhhhhhhhhhgfdd8 $878> X55601 $761 X5788o 37- -dfd@ &>,39qryuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuypsdffdspuuuuuuuuuuihhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhfiw6555555555555555555555333332322331efffdffs+ qqwetiadfffdfddfffdfffffgghhhgggfffdfdffdfdfdfdfdfffggfggfggghhhhhhhhhhhhggggp 6666 >6699 676+ >679- =73 .yss8 .O,,159etyuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuyuyuuuuuuuuuuuuihhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhfiw7545555555555555555555545353350dgggghg4 -rqqruadfggghghhggghgghhhhhhhhhhghghhghgghghghghghghhhhhhhhghghhhhhhhhhhhhhhhg< ;669& +666q* -76, . O8686 X66$ <uiuO . -><57qryuuuuuuuuuuuuuuuuuuuuuuuuuiuuuuuuuuiuuuuuuuuuuuuuuuuuuuuuughhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdir955555555555555555555555555uhhhhhhhgfsuteqrtpdfhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhu X7764 . 15696 .766# . <679$. <7< oqty- %<<149etyuuuuuuuuuuuuuiuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuiuuuuuighhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhsue85555455555555555555559dhhhhhhhgfauteeriadghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh* >865X -667q# >765 668= =86% -0q1 +4357qtiasdddddddddddddddsdddddddsddddddsddddddddddddsddddddddddddshhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhfaue755555555555555555ehhhhhhhhgdautrtuadghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhq ;-% +76703 O868: . >>% +975 %2* X6669wuadghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhsit06553555555555phhhhhhhggfaiuuupsfghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhfO . +76680X 3869- . %986> . . X5877qtpsgghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhgaur065455555dhhhhhhhhgfdaapadfghghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh6 . -8767q> *7699* . . -0989; +98669qusfggfffghhhhgfffghhhhgfffghhhhgdfdghhhhgfffghhhhgfffghhhhdfffghhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhgspte955fhhhhhhhhggfddddfghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhs . O3987800 5760e4 O3099997 X;996136qpdfhfuuuahhhhduuushhhhduuudhhhhduuufhhhhsuuufhhhhauuughhhhauuughhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhfahhhhhhhhhhggffggghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh- X%>688780r& ,869qry< #;89999qwr3o O=58887559rdghhguuushhhhfuuishhhhduuudhhhhduuufhhhhsuuufhhhhauuufhhhhauuighhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhgdauq841<15566890ryupute9880ruuur3<;1156889qrtyyr41>,145670979qyfgghfuuuahhhhfuuushhhhdiuudhhhhduuudhhhhsuuufhhhhauiughhhhauuughhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhggdptq8433356789qrupaaite990ruppitq85345790wtypiitw84335680qe0qrugghhfuuushhhhfuuushhhhduuudhhhhsuuudhhhhauuufhhhhsuuufhhhhpuuighhhhhhhhhhhhhghhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhg7-&508666880qrtipssaiyeqqrtpsspue076699qetipsaaurq866790ettwrtphhhhfuuuahhhhfuuudhhhhduuudhhhhduuidhhhhsuuufhhhhauuifsfhhauuughhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhg9O550eqq0qwertuisdffsauyttupsddsayrqqqqrtupaddfdpureq0qeryiprtyahhhhfuuushhhhfuuushhhhfuuudhhhhduuudhhhhsuuufhhhhauuug;0hhauuighhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh;8saiuuttuyuipaddgggfsaiiiasffgfaaiytyuupaddgggfdpuuyyuupadauuuahhhhfiuiahhhhfiuudhhhhduuidhhhhduuufhhhhsiiufhhhhauuug>0hhpiuughhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhO ysaaaOt3 4dggp% %usssu& *ifssaaaasdffghOpggsOtaat- -ufggXahhpOfggOp7 .5fgfgghhhgggf9 6gggOphhhXigg9 6gggX 9gggi* *pghhO; 4@+dhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhp*4tgffdf %&er phh+;yu&&gfg+:uu*%hgffddfffghhh uhgd tdd@%yy:+hhh uhhu hhh **tr ahhhhhhhhhhh 0uut<hhh uhhf uhh 0uut<hhhp*4uufhhh$;uu**hhh *0 7*0hhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh:9hhgghg 3ggh<shh uhhu hgh uhhu hghggghgghhhh<5hhwOggg uhhy hhh thhu hhh 4hhh<shhhhhhhhhhh4 5uhhhhh<5hheOhhh4 5uhhhhhh;0hhhhhh uhhu hhh uu h;0hhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh00phhhhhhhhhhhhhhh90phhhhhhhhhhhhhhh00phhhhhhhhhhhhhh:0hhhhhh uhhhhhhh *;;* hhh *;;* hhhhhhhhhhhhht fh@9hhh uhhu hhh;9hhu hhh uhhhhhhhhhhhhhhhghu< *phhhr fh#0hhhhu< *phhhh;0hhhhhh &>;* hhh uu h>9hhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh 0hhhhhhhhhhhhhhh 0hhhhhhhhhhhhhhh 0hhhhhhhhhhhhhh;0hhhhhh uhhhhhhh 40900hhh 40900hhhhhhhhhhhhhh@0r fhhh uhhu hhh;0hht hhh uhhhhhhhhhhhhhhhhhhhs<#hhhh#0t fhhhhhhs<#hhhh;0hhuhhh 39000hhh uy h9>hhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh00phhhhhhhhhhhhhhh90phhhhhhhhhhhhhhh00phhhhhhhhhhhhhh;9hhhhhh uhhhhhhh@<uuuphhh@1uuuphhhhghhhhhhhhh0O#5hhhh*%uu*&hhh<<u4 hhh uhhhhhhhhhhhhhhhh<tuu0Ohhhh0O#4hhhh<ruu0Ohhhh1<u9 uhh@1uuuphhh uu h0;hhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh<0hhhhhhXphhhhhhhs;. Xhhhs> Ohhhhhhhhhhhhhhg3 shhhhp; ;ahhha+ ;wOhhhXahhhhhhhhhhhhhhhh6 Owhhhhf4 shhhh6 Oqhhhhp$ 6hhhs; OhhhXpaOh0<hhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhghhhhhhhhhhhhhhhhhhhhhhhhhhh3;hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh4;hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhghhhhhhhhhhhhhhhghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh09 uhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhghhhhhhhhhhhhhhhhh09 uhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh<:5hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh<:4hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh" +}; diff --git a/qemu/roms/openbios/arch/unix/gui_qt/qt-main.cpp b/qemu/roms/openbios/arch/unix/gui_qt/qt-main.cpp new file mode 100644 index 000000000..8311fe632 --- /dev/null +++ b/qemu/roms/openbios/arch/unix/gui_qt/qt-main.cpp @@ -0,0 +1,97 @@ +/* tag: openbios qt user interface + * + * Copyright (C) 2003-2004 Stefan Reinauer + * + * See the file "COPYING" for further information about + * the copyright and warranty status of this work. + */ + + +extern "C" { +#include <pthread.h> +#include <unistd.h> +#include "unix/plugins.h" +#include "unix/plugin_pci.h" +} +#include "gui-qt.h" + +#define DEBUG + +volatile unsigned char * fb=0; +volatile int gui_running=0; + +typedef struct { + int argc; + char **argv; +} threaddata; + +void *gui_thread(void *ptr) +{ + threaddata *td=(threaddata *)ptr; + + QApplication a(td->argc, td->argv); + FrameBufferWidget w; + + a.setMainWidget(&w); + w.show(); + + fb=w.getFrameBuffer(); + + gui_running=-1; + a.exec(); + gui_running=0; + + return 0; +} + +extern "C" { +extern int plugin_qt_init(void); +int plugin_qt_init(void) +{ + pthread_t mythread; + char *args[]={ "plugin_qt" }; + threaddata mytd = { 1, args }; + +#ifdef DEBUG + printf("Initializing \"framebuffer\" plugin..."); +#endif + pthread_create(&mythread, NULL, gui_thread, &mytd); + while (!fb) + usleep(20); + +#if 0 + + /* now we have the framebuffer start address. + * updating pci config space to reflect this + */ +#if (BITS > 32) + *(u32 *)(pci_config_space+0x14)=(u32)((unsigned long)fb>>32); +#else + *(u32 *)(pci_config_space+0x14)=0; +#endif + *(u32 *)(pci_config_space+0x10)=(u32)((unsigned long)fb&0xffffffff); + + /* next is to write the rom address. We write that at a random + * address in pci config space for now. + */ +#if (BITS > 32) + *(u32 *)(pci_config_space+0x34)=(u32)((unsigned long)qt_fcode>>32); +#else + *(u32 *)(pci_config_space+0x34)=0; +#endif + *(u32 *)(pci_config_space+0x30)=(u32)((unsigned long)qt_fcode&0xffffffff); + + /* FIXME: we need to put the fcode image for this + * device to the rom resource, once it exists + */ + + /* register pci device to be available to beginagain */ + pci_register_device(0, 2, 0, pci_config_space); +#endif +#ifdef DEBUG + printf("done.\n"); +#endif + return 0; +} + +} diff --git a/qemu/roms/openbios/arch/unix/plugins.c b/qemu/roms/openbios/arch/unix/plugins.c new file mode 100644 index 000000000..855454b0e --- /dev/null +++ b/qemu/roms/openbios/arch/unix/plugins.c @@ -0,0 +1,197 @@ +/* tag: plugin interface for openbios forth kernel + * + * Copyright (C) 2003, 2004 Stefan Reinauer + * + * See the file "COPYING" for further information about + * the copyright and warranty status of this work. + */ + +#include "sysinclude.h" +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <dlfcn.h> + +#include "unix/plugins.h" + +unsigned char *plugindir = "/usr/share/OpenBIOS/plugins"; +#define PLUGINDIR plugindir +#define PATHSIZE 256 + +#define CONFIG_DEBUG_PLUGINS + +typedef struct iorange iorange_t; +struct iorange { + const char *name; + unsigned int start; + unsigned int end; + io_ops_t *ops; + iorange_t *next; +}; + +static iorange_t *ioranges = NULL; + +typedef struct plugin plugin_t; +struct plugin { + const char *name; + plugin_t *next; +}; + +static plugin_t *plugins = NULL; + +io_ops_t *find_iorange(u32 reg) +{ + iorange_t *range = ioranges; + while (range) { + if (range->start <= reg && range->end >= reg) + return range->ops; + range = range->next; + } + return NULL; +} + +int register_iorange(const char *name, io_ops_t * ops, unsigned int rstart, + unsigned int rend) +{ + iorange_t *newrange; + + /* intersection check */ + newrange = ioranges; + while (newrange) { + int fail = 0; + /* new section swallows old section */ + if (newrange->start >= rstart && newrange->end <= rend) + fail = -1; + /* new section start or end point are within range */ + if (newrange->start <= rstart && newrange->end >= rstart) + fail = -1; + if (newrange->start <= rend && newrange->end >= rend) + fail = -1; + if (fail) { + printf("Error: overlapping IO regions: %s and %s\n", + newrange->name, name); + return -1; + } + newrange = newrange->next; + } + + newrange = malloc(sizeof(iorange_t)); + + newrange->name = name; + newrange->ops = ops; + newrange->start = rstart; + newrange->end = rend; + newrange->next = ioranges; + + ioranges = newrange; + + return 0; +} + +int is_loaded(const char *plugin_name) +{ + plugin_t *p = plugins; + while (p) { + if (!strcmp(plugin_name, p->name)) + return -1; + p = p->next; + } + return 0; +} + +int load_plugin(const char *plugin_name) +{ + void *handle; + char *error; + char path[PATHSIZE]; + + int (*init_plugin) (void); + char **deps; + char **plugin_info; + plugin_t *p; + + if (is_loaded(plugin_name)) { + printf("Plugin %s already loaded.\n", plugin_name); + return 0; + } + + strncpy(path, PLUGINDIR, PATHSIZE); + strncat(path, "/plugin_", PATHSIZE); + strncat(path, plugin_name, PATHSIZE); + strncat(path, ".so", PATHSIZE); + +#if DEBUG + printf("Opening plugin %s\n", path); +#endif + + handle = dlopen(path, RTLD_LAZY | RTLD_GLOBAL); + if (!handle) { + error = dlerror(); + printf("Error: Could not open plugin \"%s\": %s\n", + plugin_name, error); + exit(1); + } +#ifdef CONFIG_DEBUG_PLUGINS + plugin_info = dlsym(handle, "plugin_author"); + if ((error = dlerror()) == NULL) + printf("Plugin %s author: %s\n", plugin_name, *plugin_info); + plugin_info = dlsym(handle, "plugin_license"); + if ((error = dlerror()) == NULL) + printf("Plugin %s license: %s\n", plugin_name, *plugin_info); + plugin_info = dlsym(handle, "plugin_description"); + if ((error = dlerror()) == NULL) + printf("Plugin %s descr.: %s\n", plugin_name, *plugin_info); +#endif + p = malloc(sizeof(plugin_t)); + p->next = plugins; + p->name = plugin_name; + plugins = p; + + deps = dlsym(handle, "plugin_deps"); + if ((error = dlerror()) != NULL) + deps = NULL; + + + strncpy(path, "plugin_", PATHSIZE); + strncat(path, plugin_name, PATHSIZE); + strncat(path, "_init", PATHSIZE); + + init_plugin = dlsym(handle, path); + if ((error = dlerror()) != NULL) { + printf("error: %s\n", error); + exit(1); + } + + if (deps) { + int i = 0; + char *walk = deps[0]; +#ifdef CONFIG_DEBUG_PLUGINS + printf("\nPlugin %s dependencies:", plugin_name); +#endif + while (walk) { + printf(" %s", walk); + if (!is_loaded(walk)) { +#ifdef CONFIG_DEBUG_PLUGINS + printf("(loading)\n"); +#endif + load_plugin(walk); + } +#ifdef CONFIG_DEBUG_PLUGINS + else { + printf("(loaded)"); + } +#endif + walk = deps[++i]; + } + } + + printf("\n"); +#if DEBUG + printf("Initializing module:\n"); +#endif + + return init_plugin(); + + // We don't dlclose the handle here since + // we want to keep our symbols for later use. +} diff --git a/qemu/roms/openbios/arch/unix/plugins/Kconfig b/qemu/roms/openbios/arch/unix/plugins/Kconfig new file mode 100644 index 000000000..43237bf99 --- /dev/null +++ b/qemu/roms/openbios/arch/unix/plugins/Kconfig @@ -0,0 +1,16 @@ +config PLUGINS + depends HOST_UNIX + bool "Plugin system (obsolete)" + default n + +config PLUGIN_PCI + depends HOST_UNIX && PLUGINS + bool "PCI Emulation" + default n + +config PLUGIN_QT + bool "QT Display Emulation" + depends HOST_UNIX && PLUGINS && PLUGIN_PCI + default n + help + This plugin needs qt installed. Disable if you don't have qt. diff --git a/qemu/roms/openbios/arch/unix/plugins/Makefile b/qemu/roms/openbios/arch/unix/plugins/Makefile new file mode 100644 index 000000000..c6b9a6519 --- /dev/null +++ b/qemu/roms/openbios/arch/unix/plugins/Makefile @@ -0,0 +1,13 @@ + +include ../../../config/Makefile.top + +SUBDIRS-$(CONFIG_PLUGIN_PCI) += plugin_pci +SUBDIRS-$(CONFIG_PLUGIN_QT) += plugin_qt + +PROGRAMS = # loader +loader-OBJS = loader.o +loader-LDFLAGS = -dynamic $(LIBDL_LDFLAGS) + +INCLUDES = -DBOOTSTRAP + +include $(rules)/Rules.make diff --git a/qemu/roms/openbios/arch/unix/plugins/Rules.plugin b/qemu/roms/openbios/arch/unix/plugins/Rules.plugin new file mode 100644 index 000000000..9e9b6255d --- /dev/null +++ b/qemu/roms/openbios/arch/unix/plugins/Rules.plugin @@ -0,0 +1,15 @@ +# -*- makefile -*- + +INCLUDES = -I$(top_srcdir)/include -DBOOTSTRAP +CFLAGS = -fPIC + +%.so: %.o + $(CC) -shared $(CFLAGS) $(filter %.o,$^) -o $@ + +THISDIR := $(notdir $(shell pwd)) + +all-local: $(addprefix $(ODIR)/../,$(PLUGINS)) + +$(ODIR)/../%.so: $(ODIR)/%.so + install -d ../$(ODIR) + ln -f "../$(THISDIR)"/$< $@ diff --git a/qemu/roms/openbios/arch/unix/plugins/loader.c b/qemu/roms/openbios/arch/unix/plugins/loader.c new file mode 100644 index 000000000..d3781de79 --- /dev/null +++ b/qemu/roms/openbios/arch/unix/plugins/loader.c @@ -0,0 +1,209 @@ +/* tag: openbios plugin loader + * + * Copyright (C) 2003 Stefan Reinauer + * + * See the file "COPYING" for further information about + * the copyright and warranty status of this work. + */ + +/* This is a simple plugin loader. OpenBIOS duplicates some + * of this code in kernel/arch/unix/plugins.c. This code is + * here for reference and simple testing. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <dlfcn.h> +#include <unistd.h> // sleep + +#include "unix/plugins.h" + +#define PLUGINDIR "/usr/share/OpenBIOS/plugins" +#define PATHSIZE 256 + +#define DEBUG_PLUGINS + +typedef struct iorange iorange_t; +struct iorange { + const char *name; + unsigned int start; + unsigned int end; + io_ops_t *ops; + iorange_t *next; +}; + +iorange_t *ioranges = NULL; + +typedef struct plugin plugin_t; +struct plugin { + const char *name; + plugin_t *next; +}; + +plugin_t *plugins = NULL; + +int register_iorange(const char *name, io_ops_t * ops, unsigned int rstart, + unsigned int rend) +{ + iorange_t *newrange; + + /* intersection check */ + newrange = ioranges; + while (newrange) { + int fail = 0; + /* new section swallows old section */ + if (newrange->start >= rstart && newrange->end <= rend) + fail = -1; + /* new section start or end point are within range */ + if (newrange->start <= rstart && newrange->end >= rstart) + fail = -1; + if (newrange->start <= rend && newrange->end >= rend) + fail = -1; + if (fail) { + printf("Error: overlapping IO regions: %s and %s\n", + newrange->name, name); + return -1; + } + newrange = newrange->next; + } + + newrange = malloc(sizeof(iorange_t)); + + newrange->name = name; + newrange->ops = ops; + newrange->start = rstart; + newrange->end = rend; + newrange->next = ioranges; + + ioranges = newrange; + + return 0; +} + +int is_loaded(const char *plugin_name) +{ + plugin_t *p = plugins; + while (p) { + if (!strcmp(plugin_name, p->name)) + return -1; + p = p->next; + } + return 0; +} + +int load_plugin(const char *plugin_name) +{ + void *handle; + char *error; + char path[PATHSIZE]; + + int (*init_plugin) (void); + char **deps; + char **plugin_info; + plugin_t *p; + + if (is_loaded(plugin_name)) { + printf("Plugin %s already loaded.\n", plugin_name); + return 0; + } + + strncpy(path, PLUGINDIR, PATHSIZE); + strncat(path, "/plugin_", PATHSIZE); + strncat(path, plugin_name, PATHSIZE); + strncat(path, ".so", PATHSIZE); + +#if DEBUG + printf("Opening plugin %s\n", path); +#endif + + handle = dlopen(path, RTLD_LAZY | RTLD_GLOBAL); + if (!handle) { + error = dlerror(); + printf("Error: Could not open plugin \"%s\": %s\n", + plugin_name, error); + exit(1); + } +#ifdef DEBUG_PLUGINS + plugin_info = dlsym(handle, "plugin_author"); + if ((error = dlerror()) == NULL) + printf("Plugin %s author: %s\n", plugin_name, *plugin_info); + plugin_info = dlsym(handle, "plugin_license"); + if ((error = dlerror()) == NULL) + printf("Plugin %s license: %s\n", plugin_name, *plugin_info); + plugin_info = dlsym(handle, "plugin_description"); + if ((error = dlerror()) == NULL) + printf("Plugin %s descr.: %s\n", plugin_name, *plugin_info); +#endif + p = malloc(sizeof(plugin_t)); + p->next = plugins; + p->name = plugin_name; + plugins = p; + + deps = dlsym(handle, "plugin_deps"); + if ((error = dlerror()) != NULL) + deps = NULL; + + + strncpy(path, "plugin_", PATHSIZE); + strncat(path, plugin_name, PATHSIZE); + strncat(path, "_init", PATHSIZE); + + init_plugin = dlsym(handle, path); + if ((error = dlerror()) != NULL) { + printf("error: %s\n", error); + exit(1); + } + + if (deps) { + int i = 0; + char *walk = deps[0]; +#ifdef DEBUG_PLUGINS + printf("\nPlugin %s dependencies:", plugin_name); +#endif + while (walk) { + printf(" %s", walk); + if (!is_loaded(walk)) { +#ifdef DEBUG_PLUGINS + printf("(loading)\n"); +#endif + load_plugin(walk); + } +#ifdef DEBUG_PLUGINS + else { + printf("(loaded)"); + } +#endif + walk = deps[++i]; + } + } + + printf("\n"); +#if DEBUG + printf("Initializing module:\n"); +#endif + + return init_plugin(); + + // We don't dlclose the handle here since + // we want to keep our symbols for later use. +} + +int main(void) +{ + iorange_t *r; + + // load_plugin("kbd"); + // load_plugin("pci"); + load_plugin("qt"); + + printf("\nRegistered IO Ranges:\n"); + r = ioranges; + while (r) { + printf(" %s: %x-%x\n", r->name, r->start, r->end); + r = r->next; + } + + sleep(10); + return 0; +} diff --git a/qemu/roms/openbios/arch/unix/plugins/plugin_pci/Makefile b/qemu/roms/openbios/arch/unix/plugins/plugin_pci/Makefile new file mode 100644 index 000000000..e46a6cdae --- /dev/null +++ b/qemu/roms/openbios/arch/unix/plugins/plugin_pci/Makefile @@ -0,0 +1,7 @@ + +include ../../../../config/Makefile.top + +PLUGINS = plugin_pci.so + +include ../Rules.plugin +include $(rules)/Rules.make diff --git a/qemu/roms/openbios/arch/unix/plugins/plugin_pci/Makefile.old b/qemu/roms/openbios/arch/unix/plugins/plugin_pci/Makefile.old new file mode 100644 index 000000000..10d0555d9 --- /dev/null +++ b/qemu/roms/openbios/arch/unix/plugins/plugin_pci/Makefile.old @@ -0,0 +1,21 @@ +# tag: Makefile for OpenBIOS PCI plugin +# +# Copyright (C) 2003 Stefan Reinauer +# +# See the file "COPYING" for further information about +# the copyright and warranty status of this work. +# + +PLUGIN_SOURCES = plugin_pci.c +PLUGIN_NAME = plugin_pci.so + +INCLUDES := -I$(TOPDIR)/include -I$(BUILDDIR) -I.. +VPATH := $(VPATH):. + +all: $(PLUGIN_NAME) + +$(PLUGIN_NAME): $(PLUGIN_SOURCES) + $(CC) -shared -Wall -Os -fPIC $(INCLUDES) $< -o $(BUILDDIR)/$@ + +clean: + rm -f plugin_*.so diff --git a/qemu/roms/openbios/arch/unix/plugins/plugin_pci/plugin_pci.c b/qemu/roms/openbios/arch/unix/plugins/plugin_pci/plugin_pci.c new file mode 100644 index 000000000..586ea2aaf --- /dev/null +++ b/qemu/roms/openbios/arch/unix/plugins/plugin_pci/plugin_pci.c @@ -0,0 +1,221 @@ +/* tag: openbios pci plugin + * + * Copyright (C) 2003 Stefan Reinauer + * + * See the file "COPYING" for further information about + * the copyright and warranty status of this work. + */ + +#include <stdio.h> +#include <stdlib.h> +#include "unix/plugins.h" +#include "unix/plugin_pci.h" + +#define DEBUG + +u32 pci_conf_addr = 0; +pci_dev_t *pci_devices = NULL; + +static pci_dev_t *find_device(u32 conf_addr) +{ + pci_dev_t *devs = pci_devices; + unsigned bus = (conf_addr >> 16) & 0xff; + unsigned dev = (conf_addr >> 11) & 0x1f; + unsigned fn = (conf_addr >> 8) & 0x7; + + // printf("Looking for device %x\n",conf_addr); + + while (devs) { + if (devs->bus == bus && devs->dev == dev && devs->fn == fn) + return devs; + devs = devs->next; + } + return NULL; +} + +/* + * IO functions. These manage all the magic of providing a PCI + * compatible interface to OpenBIOS' unix version of the kernel. + */ + +static u8 pci_inb(u32 reg) +{ + u32 basereg = (reg & 0xfffc); + u32 basepos = (reg & 0x03); + pci_dev_t *dev; + + if (basereg == 0xcf8) { + return (pci_conf_addr >> (basepos << 3)); + } + + /* still here? so we're 0xCFC */ + dev = find_device(pci_conf_addr); + if (!dev || !dev->config) + return 0xff; + + return dev->config[(pci_conf_addr + basepos) & 0xff]; +} + +static u16 pci_inw(u32 reg) +{ + u32 basereg = (reg & 0xfffc); + u32 basepos = (reg & 0x02); + pci_dev_t *dev; + + if (basereg == 0xcf8) { + return (pci_conf_addr >> (basepos << 3)); + } + + /* still here? so we're 0xCFC */ + dev = find_device(pci_conf_addr); + if (!dev || !dev->config) + return 0xffff; + + return *(u16 *) (dev->config + ((pci_conf_addr + basepos) & 0xff)); +} + +static u32 pci_inl(u32 reg) +{ + u32 basereg = (reg & 0xfffc); + pci_dev_t *dev; + + if (basereg == 0xcf8) { + return pci_conf_addr; + } + + /* still here? so we're 0xCFC */ + dev = find_device(pci_conf_addr); + if (!dev || !dev->config) + return 0xffffffff; + + return *(u32 *) (dev->config + (pci_conf_addr & 0xff)); +} + +static void pci_outb(u32 reg, u8 val) +{ + u32 basereg = (reg & 0xfffc); + u32 basepos = (reg & 0x03); + pci_dev_t *dev; + + if (basereg == 0xcf8) { + pci_conf_addr &= (~(0xff << (basepos << 3))); + pci_conf_addr |= (val << (basepos << 3)); + return; + } + + /* still here? so we're 0xCFC */ + dev = find_device(pci_conf_addr); + if (!dev || !dev->config) + return; + + dev->config[pci_conf_addr & 0xff] = val; +} + +static void pci_outw(u32 reg, u16 val) +{ + u32 basereg = (reg & 0xfffc); + u32 basepos = (reg & 0x02); + pci_dev_t *dev; + + if (basereg == 0xcf8) { + pci_conf_addr &= (~(0xffff << (basepos << 3))); + pci_conf_addr |= (val << (basepos << 3)); + return; + } + + /* still here? so we're 0xCFC */ + dev = find_device(pci_conf_addr); + if (!dev || !dev->config) + return; + + *(u16 *) (dev->config + (pci_conf_addr & 0xff)) = val; +} + +static void pci_outl(u32 reg, u32 val) +{ + u32 basereg = (reg & 0xfffc); + pci_dev_t *dev; + + if (basereg == 0xcf8) { + pci_conf_addr = val; + return; + } + + /* still here? so we're 0xCFC */ + dev = find_device(pci_conf_addr); + if (!dev || !dev->config) + return; + + *(u32 *) (dev->config + (pci_conf_addr & 0xff)) = val; +} + +static io_ops_t pci_io_ops = { + inb:pci_inb, + inw:pci_inw, + inl:pci_inl, + outb:pci_outb, + outw:pci_outw, + outl:pci_outl +}; + +/* + * Functions visible to modules depending on this module. + */ + +int pci_register_device(unsigned bus, unsigned dev, unsigned fn, + u8 * config) +{ + pci_dev_t *newdev; + u32 caddr = (1 << 31) | (bus << 16) | (dev << 11) | (fn << 8); + + if (find_device(caddr)) { + printf("Error: pci device %02x:%02x.%01x already exists\n", + bus, dev, fn); + return -1; + } + + newdev = malloc(sizeof(pci_dev_t)); + + if (!newdev) { + printf("Out of memory\n"); + return -1; + } + + newdev->bus = bus; + newdev->dev = dev; + newdev->fn = fn; + newdev->config = config; + newdev->next = pci_devices; + + pci_devices = newdev; + + return 0; +} + +/* + * Initialization is really simple. We just grab the + * PCI conf1 io range for our emulation functions. + */ +extern int plugin_pci_init( void ); + +int plugin_pci_init(void) +{ +#ifdef DEBUG + printf("Plugin \"pci\" initializing... "); +#endif + register_iorange("pci", &pci_io_ops, 0xcf8, 0xcff); +#ifdef DEBUG + printf("done.\n"); +#endif + return 0; +} + +/* plugin meta information available for the plugin loader */ +PLUGIN_AUTHOR ("Stefan Reinauer <stepan@openbios.org>") +PLUGIN_DESCRIPTION ("Generic PCI Device Emulation") +PLUGIN_LICENSE ("GPL v2") + +/* This plugin has no dependencies. Otherwise the following + * macro would be uncommented: + * PLUGIN_DEPENDENCIES ("this", "that") + */ diff --git a/qemu/roms/openbios/arch/unix/plugins/plugin_qt/Makefile b/qemu/roms/openbios/arch/unix/plugins/plugin_qt/Makefile new file mode 100644 index 000000000..371dc2f0b --- /dev/null +++ b/qemu/roms/openbios/arch/unix/plugins/plugin_qt/Makefile @@ -0,0 +1,37 @@ + +include ../../../../config/Makefile.top + +PLUGINS = plugin_qt.so + +QMAKE = qmake +PLUGINDIR = $(shell cd .. ; pwd ) +TOPDIR = $(shell cd $(top_srcdir) ; pwd) +ABSOINC = $(shell cd $(ARCHINCLUDES) 2> /dev/null ; pwd ) + +export PLUGINDIR TOPDIR ABSOINC + +qt_rom.fc: qt_rom.fs + $(TOKE) -v qt_rom.fs + +fcode.h: qt_rom.fc + @echo "static const u8 qt_fcode[] = {" > $@ + @cat $< | hexdump -ve '1/0 "\t" 8/1 "0x%02x, " 1/0 "\n"' \ + | sed 's/0x ,//g' >> $@ + @echo "};" >> $@ + +$(ODIR)/makefile.qmake: plugin_qt.pro Makefile + @test -d $(ODIR) || $(INSTALL) -d $(ODIR) + @test -d $(ODIR)/qbuild || $(INSTALL) -d $(ODIR)/qbuild + @cp plugin_qt.pro $(ODIR)/ + cd $(ODIR) ; $(QMAKE) -o makefile.qmake + +$(ODIR)/plugin_qt.so: fcode.h $(ODIR)/makefile.qmake $(wildcard *.cpp) + cd $(ODIR) ; $(MAKE) -f makefile.qmake + @ln -f $(ODIR)/qbuild/plugin_qt.so $@ + +clean-local: + @rm -f $(ODIR)/makefile.qmake + @rm -rf $(QBUILDDIR) $(ODIR)/*.fc $(ODIR)/fcode.h + +include ../Rules.plugin +include $(rules)/Rules.make diff --git a/qemu/roms/openbios/arch/unix/plugins/plugin_qt/logo.xpm b/qemu/roms/openbios/arch/unix/plugins/plugin_qt/logo.xpm new file mode 100644 index 000000000..9e2ac60b4 --- /dev/null +++ b/qemu/roms/openbios/arch/unix/plugins/plugin_qt/logo.xpm @@ -0,0 +1,132 @@ +/* This logo was created by Stephan Lau, + * created to xpm by Stefan Reinauer + */ +static char *logo[] = { +/* columns rows colors chars-per-pixel */ +"300 80 44 1", +" c #010101", +". c #070709", +"X c #0B0B0B", +"o c #0F0F11", +"O c #121212", +"+ c #1B1B1B", +"@ c #1F1F21", +"# c #232323", +"$ c #262628", +"% c #2B2B2C", +"& c #2E2E30", +"* c #333333", +"= c #373739", +"- c #3B3B3B", +"; c #434343", +": c #464648", +"> c #4B4B4B", +", c #4E4E50", +"< c #535353", +"1 c #5B5B5B", +"2 c #5E5E60", +"3 c #646464", +"4 c #666668", +"5 c #6B6B6B", +"6 c #747474", +"7 c #767678", +"8 c #7B7B7B", +"9 c #838383", +"0 c #8A8A8A", +"q c #939394", +"w c #979799", +"e c #9B9B9B", +"r c #A3A3A3", +"t c #ABABAB", +"y c #B4B4B4", +"u c #BBBBBB", +"i c #C3C3C3", +"p c #CBCBCB", +"a c #D3D3D3", +"s c #DBDBDB", +"d c #E3E3E3", +"f c #EBEBEB", +"g c #F3F3F3", +"h c #FEFEFE", +/* pixels */ +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhgfdssaapuuuytteeewq0009998867666555555555555565666778899000qwwerttyyuuppassdfghhhhhhhhhhgfgggghhhgfgfghhhhggffghhhhggffghhhhgfggghhhhgfggghhhhgfgfghhhhfgfgghhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhfdsapuytrwq0986555554455555555555555555555555555555555555555555555555555555555555555555555555556790qertyiuuuafhhhfpiishhhhfipidhhhhfiiidhhhhdiiifhhhhsiiifhhhhsiipghhhhaiipghhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhgfdaiuttq0976555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555558iuue5579wuuuuiasfduuishhhhduuudhhhhduuudhhhhsuuufhhhhauuughhhhauuughhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhfdaittw086555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555558yuur55549uuiw55569uuutyiadsuuudhhhhsuuudhhhhsuuufhhhhauuughhhhauuughhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhgfapyrw975555555555555555555555555555555555555555555555555555555555555555555555555555555554555555555555555555554455555555555555555555558uuue54559uuuw55559uuuq55550uiutypafduuufhhhhsuuufhhhhsuuufhhhhauuughhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhgdautw965555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555679qqerttuuppaasdddffgghghhhhhhhhhghhggfduuupaappuuuuyeq090uuuq55559uyi05555quuuuadghsuuufhhhhauuufhhhhauuighhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhfsite0655555555555555555555555555555555555555555555555555555555555555555555555455555555555555555690wrtiiaddghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhfuuuahhhhfuuushhhhfuuuaaiittuuuq55550uuu95560tuuudhhhhsuuughhhhauuufhhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhghhhhhhhhhhhhhhhhhgsite955555555555555555555555555455555555555555555555555555555555555555555555555545555555555570wryiadfhhhhhhhhhhhhhhhhhhhhhhhhhhhhghhhhhhhhhhhhhhhhhhhhhhhguuuahhhhfuuuahhhhfuuushhhhduuudfsaiuuuuq5555qiuu99etipuuifhhhhauuughhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhgaut0655555555555555555555555555555555555555555555556555555555555555555555555555555555554559qruisfhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhgdsdfhhhhgdddfhhhhfddsfhhhhgdddfhhhhfddsffspyteeq755559qetisfhgfdddghhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhgsir065555555555555555555555555555455555555555555555554555555555555555555555555555555555580rupsghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhsuudhhhhhhhhhhhhfuuphhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhgspyt085555560tudghhhhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhgaue9555555555555555554<----=---=---==-==<555555---:3:--=--=-*--==--<55555545<;------==->135890phhhhhy009tfq0009009090909wshhhhhhg<;;:;;;:<9fhhhhhhhf$ rhhhhhs3# ;phhhhhhhf0# Owghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdpue0655559wuaghhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhgsue855555455555555555555:O. *5455- *. &44555>O 6ghhh+ 5O ehghhh9 . Xighhhhh9 -gfggf3 +sddffd8O rddffffffffgffffgffffffffggffffffffgffffgffdaute09868eusghhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhfpr955555555555555555555555% .%=************& +2555o +=************% +3343% X-<3568888787884. ;dggq. O19888888888888, 8fgghsO . 1fggghsO ysdfiO 9ttuu> . 1rtuyuuuuuuuuuuuuiuuuuuuuuuuuuuuuuuuuuuuuuuuuiiuuuut06449rpdhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhduw85555555555555555555555555* .,111<1111111111< #113- #<<111111111111< #123- Xtssaaaaaaaaaaaaa <sdf@ Otaaaaasaaaaaaaae 9sdgg, =sdggh< 2ipa0 7etr# <etttuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuighfauw857wudhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhfie7555555555555555555555554555: =1<<<<<<<<<<<<<<& -<<3X X<<><<<<1,,<<<<<& ;7e8 9apiiiiiipiiiiii6 0ia9 8uuuiipipiiiiiii> oyisdt X%% 2iadgy Xrty6 @69& X90e; *3% 49wttuuuuuuuuuuuuuuuuuuuuuuuuuuuyuyyyuuyuuuuuuuuuuihhhhhhgayw86eifhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhar8555555555555555555555555555543. +<,>>>,>><>>>>,,:. O;:<& -:;>>><>,,<><>,:. $eytO -puuyuuuuuuuuuiutX %rytO *ytrtyuuiuuuuuuu9 1ruis%. 108- . 8tisd% <qw9X #tre> *59, -86* O47qetuuuuuuuuuuuuuuuuuuuuuuuuuuuiasddsaiuuuuuuuuuuighhhhhhhhhgatq9tahhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhgiq55555555555555555555555555555555- ;>:>:,<<<,<<<<<<# . %-;: . O:;;;>>,<<>,,<38; 5qr3 eutttuuiiiipiiii1 5wr< qreeryuiipiiipii$ X0wru8 O976& +9wya0 O999O qeq9O >3< +751. &159wtyuuuuuuuuuuuuuuuuuuuuuuuuisfhhhhhhgdpuuuuuiuuihhhhhhhhhhhhhhdierighhhhhhh", +"hhhhhhhhhhhhhhhhhfi05555555555555555555555555555555552 #>;;:,,<<<11<11<> +--;+ ;;--;><<1116qtpy -009 ,ttrrtuppaaaaaaay -q09 ;ewqrtupaaaaaaap9 10qrtX .3754X . >60tuX 387% 3w09: +3<O. 153% O:159wtyuuuuiuuuuuuuuuuuuuuuuuuaghhhhhhhhhhhdiuuuuuuighhhhhhhhhhhhhhhhfaupghhhhh", +"hhhhhhhhhhhhhhhhiq55555555555555555555555555555555555+ X;:;;><<112311212+ .---& $;-;;><138eusddd- X000% oerrrtuaadsdddddd- o090$ Xwqqetypadddsddsao .%q9qr3 $856- +160t5 $761 X9097X ;1& &54< *;159wtyuuuuuuuuuuuuuuuuuuuuuushhhhhhhhhhhhhhdpyuuuuihhhhhhhhhhhhhhhhhhhhgsdhhhh", +"hhhhhhhhhhhhhhsr555555545555555555555555555555555555, %;;-:><123333535> %---O .;--;;<5wifgfgfgt 1w04 2ewerupsffgffggft 1w05 1wqqeyasffgfgggg9 7q0wq 6665 ,360w 666O <999= %32. . <31+. +>>160rtuuuuuuuuuuuuuuuuuuuuuyshhhhhhhhhhhhhhhhfuuuuuighhhhhhhhhhhhhhhhhhhhhhhghh", +"hhhhhhhhhhhhhi05555555555555555555555555555555555555o .X;;-::<1335555454X X:--$ &:--,6rsfghhghgh# Orq0O <<<<156999090999# +rqqO +qqqetisgghhghhha >rqqe* >867# *358e* >76; #9994 . .44- o2<>++++O>><48qrtuuuuuuuuuuuuiuuuuuuuuphhhhhhhhhhhhhhhhhhsyuiuighhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhu65555555555555555555555555555555555555- *;-->>1355555554- *;--. O;-<5rpdfhhhhhhh9 7rq< 6eq, 5w0wtisdgghhhhhh< Oqwqw8 X7773 X45608 X666. 3779% ;55X. %<1356651<<369etyuuuuuuuuuuuuuuuuuuuuudhhhhhhhhhhhhhhhhhhgpyuuighhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhi755555555555555555555555555555555555553. +;--;><2555555553. O:--$ *16qtiafhghhhhhgO *rq9X @,>:><356787888787653rq9X %wqqryadfghhhhhhy 3rqqrO <669O >569q+ <66* =8781 O953 &<24698533359qryuuuuuuuuuuuiuuuuuuuuuphhhhhhhhhhhhhhhhhhhhsyuuihhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhs955555555555555555555555555555555555555% -;;;><1335555555$ -;;* %9wweypdfhhhhhhh4 eeq- 90990rtupaaaaaaaapiutee- 9qqerusfhhhhhhhh# +twqr1 @868= $867q1 @873 o5689O 166; &<36999865690etyyuuuuuuuuuuuuuuuuuuuudhhhhhhhhhhhhhhhhhhhhfiuuighhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhy55555555555555555555555555555555555555< #;--:,<3355555551 #;;-+ Xqwqetisfhghhhhhp 1eq7 >q999qrtuuipipuippuytrr8 :wqqruadfhhhhhhh9 6ewweX 363% #6689qX 276# >769, $867* +13800q9999qrtyuuuuuuuuuuuuuuuuuuuuuufhhhhhhhhhhhhhhhhhhhhhpuuihhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhh955555555555555555555555555555555555555@ .:-;;:<1335555554+ .;:-* 1wqqrupfghhhhhhh; Oeeq$ ..q0990qrtuuuuuuuuuuuuttr& XqqqetpdfghhhhhhfO *tewe> %8869q< *76< O6687X 4669$ .X159qeeeqqqrryuuuuuuuuuuuuuuuuuuuiuuighhhhhhhhhhhhhhhhhhhhhpyuighhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhh55555555555555555555555555555555555555: $;-;;,<335555554: $:-2+ +qqqeyidgghhhhhhr 1rq3 1q000rryuipiiipiiiiiuuu7 1wqwtuadghhhhhhh6 qwww0 =20979q9 X566X <679= . -8680- . >69errtrrrtyyuuuuuuuuuuuuuuuuuuuuuuihhhhhhhhhhhhhhhhhhhhhhpyuighhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhh95555555555555555555555555555555555555O X:--;><2355555553O O:162 3eqerusdghhhhhhf# $tqqO +qqqwrtipaaaaaaaaaaaaapp+ Oeqqetpsgghhhhhhs >ewqr&. ;q0998qe* >86; #7685 O6680e1 *50ettyyyyyuuuuuuuuuuuuuuuuuuuuuuuuuhhhhhhhhhhhhhhhhhhhhhhpuuihhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhht655555555555555555555555555555555555: %;-;:<1335555555& .:500X +eqerypsghhhhhhh6 Oqeq3 1qqwryiasddddddddddddsd7 8wqqtuafghhhhhhh; Oreqw7 -999qw7. +665X 4679@ :789wt6 O50etyyuuuuuuuuuuuuuuuuuuuuuuuuuiuuughhhhhhhhhhhhhhhhhhhhhpyuighhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhs955555555555555555555555555555555555% --;;>1135555553- ,0eq> =wqerisfghhhhhf9 8rwq- 9qqetpsdffgfgffgfdttgfa *rqqryadghhhhhhhq 4rqwrO *-@ 79qeu+ ,76* . *7681 O8680ruy X49etyuuuuuuuuuuuuuuuuuuuuiuuuuuuuuudhhhhhhhhhhhhhhhhhhhhgiuuuhhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhu65555555555555555555555555555555554# .4eew9 X Oqteww= #dgg; 9wqwtisfghhhhhhfX Xewqe3 %63< @70ey5 #961 X6678X 3679ruip& 48wryuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuphhhhhhhhhhhhhhhhhhhhduuuihhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhu7555555555555555554555555555555545,@X . .+>qyrre& X8O O-7utreer9=X ufg5 +ewqruadghhhhhhf; >eqweX . 451> -6qyyO 366# ;769< $769wtpaa3 O36qrtuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuighhhhhhhhhhhhhhhhhhhpyuuighhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhp95455555555555555555555555555555331:;---;><1111111117tutre8 1q999wtipaaasssaaaiutrrrruyrq09qruiasasasasassssddddaitrwetisfhghhhhhhgfautewr; -654% o56eu< =86: . O8687 6669ruada4 @160ryuuuuuuuuuuuuuuuuuuiuuuuuuuuuuuuahhhhhhhhhhhhhhhhhhsuuuuihhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhde555555555555555555555555555555331,;---;;,<<<<<1<<8tutrtt+ Or099qwtuipppppppiiuytrtyiiiteq0qryupppppppppppppssdspurreriafghhhhhhhhgdaueee8 X665< ;38e9 X765X 1679% >669wyadfd5 *150rtuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuushhghhhhhhhhhhhhhgiyuuuighhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhiq555555555555555555555555555533<<:;-;;>>,>,>,,,6ttyttt3 5q9990rttuuuuuuyuuyyttyupaapurewertyyuuuuuuuuuuuipasaputttypsgghhhhhhhggsautrt* ,667# .+159e* >86;. $6695 .8680tisfgd3 X:160rtuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuudhhhhhhhhhhhhhhgiuiuuuighhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhfi055555555555555555555555555332<>>:;:>>>,<>,>6tuuuiiuX *eq00wrryyuuuuyuuuuuyuiiasdsaputrtttuuyuyuuuuyyuupaassaiuyupsfghhhhhhhhhgdaiuy6 O967< 146q3 O865 5679O ,769wuafggfX #:150rtuuuuuuuuuuuuuuuuuuuuuuiuuuuuuuuuuushhhhhhhhhhhhfiuuuuuuighhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhfiq5555555555555555555554555431<<<,<<<<<<<15tippppa<. 0wqqetyippppppppppippaasdfgfdsapiipipppppppppppppaadddsaapasfghhhhhhhhhggfsapi+ 1678O -5589+ 176% -679, +85O rgg0 X-,36qrtuuuuuuuuuuuuiuuuuuuuuuuuuuuuuiuuuuupfghhhhhhhfauuuuuuuuighhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhat85555555555555555555555433221111111113tsssssdr >eqqetupaasaaasaasssasddfgggggfdssasassaassasaasssddffffddddfgghhhhhhhhhhhgfdd8 $878> X55601 $761 X5788o 37- -dfd@ &>,39qryuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuypsdffdspuuuuuuuuuuihhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhfiw6555555555555555555555333332322331efffdffs+ qqwetiadfffdfddfffdfffffgghhhgggfffdfdffdfdfdfdfdfffggfggfggghhhhhhhhhhhhggggp 6666 >6699 676+ >679- =73 .yss8 .O,,159etyuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuyuyuuuuuuuuuuuuihhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhfiw7545555555555555555555545353350dgggghg4 -rqqruadfggghghhggghgghhhhhhhhhhghghhghgghghghghghghhhhhhhhghghhhhhhhhhhhhhhhg< ;669& +666q* -76, . O8686 X66$ <uiuO . -><57qryuuuuuuuuuuuuuuuuuuuuuuuuuiuuuuuuuuiuuuuuuuuuuuuuuuuuuuuuughhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdir955555555555555555555555555uhhhhhhhgfsuteqrtpdfhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhu X7764 . 15696 .766# . <679$. <7< oqty- %<<149etyuuuuuuuuuuuuuiuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuiuuuuuighhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhsue85555455555555555555559dhhhhhhhgfauteeriadghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh* >865X -667q# >765 668= =86% -0q1 +4357qtiasdddddddddddddddsdddddddsddddddsddddddddddddsddddddddddddshhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhfaue755555555555555555ehhhhhhhhgdautrtuadghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhq ;-% +76703 O868: . >>% +975 %2* X6669wuadghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhsit06553555555555phhhhhhhggfaiuuupsfghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhfO . +76680X 3869- . %986> . . X5877qtpsgghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhgaur065455555dhhhhhhhhgfdaapadfghghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh6 . -8767q> *7699* . . -0989; +98669qusfggfffghhhhgfffghhhhgfffghhhhgdfdghhhhgfffghhhhgfffghhhhdfffghhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhgspte955fhhhhhhhhggfddddfghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhs . O3987800 5760e4 O3099997 X;996136qpdfhfuuuahhhhduuushhhhduuudhhhhduuufhhhhsuuufhhhhauuughhhhauuughhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhfahhhhhhhhhhggffggghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh- X%>688780r& ,869qry< #;89999qwr3o O=58887559rdghhguuushhhhfuuishhhhduuudhhhhduuufhhhhsuuufhhhhauuufhhhhauuighhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhgdauq841<15566890ryupute9880ruuur3<;1156889qrtyyr41>,145670979qyfgghfuuuahhhhfuuushhhhdiuudhhhhduuudhhhhsuuufhhhhauiughhhhauuughhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhggdptq8433356789qrupaaite990ruppitq85345790wtypiitw84335680qe0qrugghhfuuushhhhfuuushhhhduuudhhhhsuuudhhhhauuufhhhhsuuufhhhhpuuighhhhhhhhhhhhhghhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhg7-&508666880qrtipssaiyeqqrtpsspue076699qetipsaaurq866790ettwrtphhhhfuuuahhhhfuuudhhhhduuudhhhhduuidhhhhsuuufhhhhauuifsfhhauuughhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhg9O550eqq0qwertuisdffsauyttupsddsayrqqqqrtupaddfdpureq0qeryiprtyahhhhfuuushhhhfuuushhhhfuuudhhhhduuudhhhhsuuufhhhhauuug;0hhauuighhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh;8saiuuttuyuipaddgggfsaiiiasffgfaaiytyuupaddgggfdpuuyyuupadauuuahhhhfiuiahhhhfiuudhhhhduuidhhhhduuufhhhhsiiufhhhhauuug>0hhpiuughhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhO ysaaaOt3 4dggp% %usssu& *ifssaaaasdffghOpggsOtaat- -ufggXahhpOfggOp7 .5fgfgghhhgggf9 6gggOphhhXigg9 6gggX 9gggi* *pghhO; 4@+dhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhp*4tgffdf %&er phh+;yu&&gfg+:uu*%hgffddfffghhh uhgd tdd@%yy:+hhh uhhu hhh **tr ahhhhhhhhhhh 0uut<hhh uhhf uhh 0uut<hhhp*4uufhhh$;uu**hhh *0 7*0hhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh:9hhgghg 3ggh<shh uhhu hgh uhhu hghggghgghhhh<5hhwOggg uhhy hhh thhu hhh 4hhh<shhhhhhhhhhh4 5uhhhhh<5hheOhhh4 5uhhhhhh;0hhhhhh uhhu hhh uu h;0hhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh00phhhhhhhhhhhhhhh90phhhhhhhhhhhhhhh00phhhhhhhhhhhhhh:0hhhhhh uhhhhhhh *;;* hhh *;;* hhhhhhhhhhhhht fh@9hhh uhhu hhh;9hhu hhh uhhhhhhhhhhhhhhhghu< *phhhr fh#0hhhhu< *phhhh;0hhhhhh &>;* hhh uu h>9hhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh 0hhhhhhhhhhhhhhh 0hhhhhhhhhhhhhhh 0hhhhhhhhhhhhhh;0hhhhhh uhhhhhhh 40900hhh 40900hhhhhhhhhhhhhh@0r fhhh uhhu hhh;0hht hhh uhhhhhhhhhhhhhhhhhhhs<#hhhh#0t fhhhhhhs<#hhhh;0hhuhhh 39000hhh uy h9>hhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh00phhhhhhhhhhhhhhh90phhhhhhhhhhhhhhh00phhhhhhhhhhhhhh;9hhhhhh uhhhhhhh@<uuuphhh@1uuuphhhhghhhhhhhhh0O#5hhhh*%uu*&hhh<<u4 hhh uhhhhhhhhhhhhhhhh<tuu0Ohhhh0O#4hhhh<ruu0Ohhhh1<u9 uhh@1uuuphhh uu h0;hhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh<0hhhhhhXphhhhhhhs;. Xhhhs> Ohhhhhhhhhhhhhhg3 shhhhp; ;ahhha+ ;wOhhhXahhhhhhhhhhhhhhhh6 Owhhhhf4 shhhh6 Oqhhhhp$ 6hhhs; OhhhXpaOh0<hhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhghhhhhhhhhhhhhhhhhhhhhhhhhhh3;hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh4;hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhghhhhhhhhhhhhhhhghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh09 uhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhghhhhhhhhhhhhhhhhh09 uhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh<:5hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh<:4hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh" +}; diff --git a/qemu/roms/openbios/arch/unix/plugins/plugin_qt/pciconfig.h b/qemu/roms/openbios/arch/unix/plugins/plugin_qt/pciconfig.h new file mode 100644 index 000000000..88b0e1aa8 --- /dev/null +++ b/qemu/roms/openbios/arch/unix/plugins/plugin_qt/pciconfig.h @@ -0,0 +1,42 @@ +/* tag: pci config space dump for qt plugin's pci device. + * + * Copyright (C) 2003 Stefan Reinauer + * + * See the file "COPYING" for further information about + * the copyright and warranty status of this work. + */ + +static unsigned char pci_config_space[256]={ + 0x02, 0x10, 0x36, 0x43, 0x87, 0x02, 0xb0, 0x02, + 0x00, 0x00, 0x00, 0x03, 0x10, 0x42, 0x00, 0x00, + 0x08, 0x00, 0x00, 0xf0, 0x01, 0xb0, 0x00, 0x00, + 0x00, 0x00, 0x50, 0xe8, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x34, 0x17, 0x0a, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x05, 0x01, 0x08, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x34, 0x17, 0x0a, 0x10, + 0x01, 0x00, 0x02, 0x06, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x50, 0x20, 0x00, 0x07, 0x02, 0x00, 0x2f, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; diff --git a/qemu/roms/openbios/arch/unix/plugins/plugin_qt/plugin_qt.cpp b/qemu/roms/openbios/arch/unix/plugins/plugin_qt/plugin_qt.cpp new file mode 100644 index 000000000..07234dc0a --- /dev/null +++ b/qemu/roms/openbios/arch/unix/plugins/plugin_qt/plugin_qt.cpp @@ -0,0 +1,128 @@ +/* tag: qt plugin framebuffer class + * + * Copyright (C) 2003 Stefan Reinauer + * + * See the file "COPYING" for further information about + * the copyright and warranty status of this work. + */ + +#include "plugin_qt.h" +#include "logo.xpm" + +#include <iostream> + +static const int sizex=640; +static const int sizey=480; +static const int depth=8; + +static unsigned char color[256][3]={ + { 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0xaa }, + { 0x00, 0xaa, 0x00 }, + { 0x00, 0xaa, 0xaa }, + { 0xaa, 0x00, 0x00 }, + { 0xaa, 0x00, 0xaa }, + { 0xaa, 0x55, 0x00 }, + { 0xaa, 0xaa, 0xaa }, + { 0x55, 0x55, 0x55 }, + { 0x55, 0x55, 0xff }, + { 0x55, 0xff, 0x55 }, + { 0x55, 0xff, 0xff }, + { 0xff, 0x55, 0x55 }, + { 0xff, 0x55, 0xff }, + { 0xff, 0xff, 0x55 }, + { 0xff, 0xff, 0xff }, +}; + +FrameBufferWidget::FrameBufferWidget(QWidget *parent, const char * name) +: QWidget(parent, name, Qt::WType_TopLevel) +{ + setCaption ("OpenBIOS"); + setIcon(QPixmap(logo)); + + QPopupMenu *file = new QPopupMenu (this); + + file->insertItem( "E&xit", this, SLOT(quit()), CTRL+Key_Q ); + + QPopupMenu *help = new QPopupMenu( this ); + help->insertItem("&About OpenBIOS", this, SLOT(about()), CTRL+Key_H ); + help->insertItem( "About &Qt", this, SLOT(aboutQt()) ); + + menu = new QMenuBar( this ); + Q_CHECK_PTR( menu ); + menu->insertItem( "&File", file ); + menu->insertSeparator(); + menu->insertItem( "&Help", help ); + menu->setSeparator( QMenuBar::InWindowsStyle ); + + setFixedSize(sizex,sizey+menu->heightForWidth(sizex)); + + buffer.create(sizex, sizey, depth, 256); + + for (int i=16; i < 256; i++) { + color[i][0]=i; + color[i][1]=i; + color[i][2]=i; + } + + for (int i=0; i< 256; i++) + buffer.setColor(i, qRgb(color[i][0], color[i][1], color[i][2])); + + buffer.fill( 0 ); + + updatetimer=new QTimer(this); + connect( updatetimer, SIGNAL(timeout()), this, SLOT(update()) ); + updatetimer->start(200,FALSE); + + setMouseTracking( TRUE ); +} + +unsigned char * FrameBufferWidget::getFrameBuffer(void) +{ + return buffer.bits(); +} + +void FrameBufferWidget::paintEvent ( QPaintEvent * ) +{ + QPainter p( this ); + p.drawImage(0,menu->heightForWidth(sizex),buffer, 0,0, sizex, sizey); +} + +void FrameBufferWidget::about() +{ + QMessageBox::about( this, "About OpenBIOS", + " Welcome to OpenBIOS 1.01\n" + " IEEE 1275-1994 Open Firmware implementation\n\n" + "written by Stefan Reinauer <stepan@openbios.org>\n\n" + " http://www.openbios.org/\n"); +} + +void FrameBufferWidget::aboutQt() +{ + QMessageBox::aboutQt( this, "OpenBIOS" ); +} + +void FrameBufferWidget::quit() +{ + extern volatile int gui_running; + extern volatile int interruptforth; + + gui_running=0; + interruptforth=1; + + qApp->quit(); +} + +void FrameBufferWidget::update() +{ + QPainter p( this ); + p.drawImage(0,menu->heightForWidth(sizex),buffer, 0,0, sizex, sizey); +} + +void FrameBufferWidget::keyPressEvent(QKeyEvent * e) +{ + int a=e->ascii(); + if (a) { + std::cout << " key '" << e->text() << "' pressed" << std::endl; + } +} diff --git a/qemu/roms/openbios/arch/unix/plugins/plugin_qt/plugin_qt.h b/qemu/roms/openbios/arch/unix/plugins/plugin_qt/plugin_qt.h new file mode 100644 index 000000000..a1ed76fe5 --- /dev/null +++ b/qemu/roms/openbios/arch/unix/plugins/plugin_qt/plugin_qt.h @@ -0,0 +1,44 @@ +/* tag: qt plugin framebuffer class description + * + * Copyright (C) 2003 Stefan Reinauer + * + * See the file "COPYING" for further information about + * the copyright and warranty status of this work. + */ + +#ifndef __framebufferwidget_h +#define __framebufferwidget_h + +#include <qapplication.h> +#include <qwidget.h> +#include <qimage.h> +#include <qpainter.h> +#include <qmenubar.h> +#include <qpopupmenu.h> +#include <qmessagebox.h> +#include <qstatusbar.h> +#include <qtimer.h> + +class FrameBufferWidget : public QWidget { + Q_OBJECT + public: + FrameBufferWidget(QWidget *parent=0, const char *name=0); + unsigned char *getFrameBuffer(void); + + public slots: + void quit(); + void about(); + void aboutQt(); + void update(); + + private: + QImage buffer; + QMenuBar *menu; + QStatusBar *status; + QTimer *updatetimer; + void paintEvent ( QPaintEvent * ); + protected: + void keyPressEvent(QKeyEvent * e); +}; + +#endif diff --git a/qemu/roms/openbios/arch/unix/plugins/plugin_qt/plugin_qt.pro b/qemu/roms/openbios/arch/unix/plugins/plugin_qt/plugin_qt.pro new file mode 100644 index 000000000..96accd36b --- /dev/null +++ b/qemu/roms/openbios/arch/unix/plugins/plugin_qt/plugin_qt.pro @@ -0,0 +1,18 @@ +# tag: qmake project file for OpenBIOS QT plugin +# +# Copyright (C) 2003 Stefan Reinauer +# +# See the file "COPYING" for further information about +# the copyright and warranty status of this work. +# + +TEMPLATE = app +CONFIG += qt thread warn_on release +LIBS = -shared +INCLUDEPATH = qbuild $(ABSOINC) $(TOPDIR)/include $(PLUGINDIR)/plugin_pci +DESTDIR = qbuild +OBJECTS_DIR = qbuild +MOC_DIR = qbuild +TARGET = plugin_qt.so +HEADERS = $(PLUGINDIR)/plugin_qt/plugin_qt.h +SOURCES = $(PLUGINDIR)/plugin_qt/plugin_qt.cpp $(PLUGINDIR)/plugin_qt/qt_main.cpp diff --git a/qemu/roms/openbios/arch/unix/plugins/plugin_qt/qt_main.cpp b/qemu/roms/openbios/arch/unix/plugins/plugin_qt/qt_main.cpp new file mode 100644 index 000000000..ea558d319 --- /dev/null +++ b/qemu/roms/openbios/arch/unix/plugins/plugin_qt/qt_main.cpp @@ -0,0 +1,102 @@ +/* tag: openbios qt plugin skeleton + * + * Copyright (C) 2003 Stefan Reinauer + * + * See the file "COPYING" for further information about + * the copyright and warranty status of this work. + */ + + +extern "C" { +#include <pthread.h> +#include <unistd.h> +#include "unix/plugins.h" +#include "unix/plugin_pci.h" +} +#include "plugin_qt.h" +#include "pciconfig.h" +#include "fcode.h" + +#define DEBUG + +volatile unsigned char * fb=0; +volatile int gui_running=0; + +typedef struct { + int argc; + char **argv; +} threaddata; + +void *gui_thread(void *ptr) +{ + threaddata *td=(threaddata *)ptr; + + QApplication a(td->argc, td->argv); + FrameBufferWidget w; + + a.setMainWidget(&w); + w.show(); + + fb=w.getFrameBuffer(); + + gui_running=-1; + a.exec(); + gui_running=0; + + return 0; +} + +extern "C" { +extern int plugin_qt_init(void); +int plugin_qt_init(void) +{ + pthread_t mythread; + char *args[]={ "plugin_qt" }; + threaddata mytd = { 1, args }; + +#ifdef DEBUG + printf("Initializing \"framebuffer\" plugin..."); +#endif + pthread_create(&mythread, NULL, gui_thread, &mytd); + while (!fb) + usleep(20); + + /* now we have the framebuffer start address. + * updating pci config space to reflect this + */ +#if (BITS > 32) + *(u32 *)(pci_config_space+0x14)=(u32)((unsigned long)fb>>32); +#else + *(u32 *)(pci_config_space+0x14)=0; +#endif + *(u32 *)(pci_config_space+0x10)=(u32)((unsigned long)fb&0xffffffff); + + /* next is to write the rom address. We write that at a random + * address in pci config space for now. + */ +#if (BITS > 32) + *(u32 *)(pci_config_space+0x34)=(u32)((unsigned long)qt_fcode>>32); +#else + *(u32 *)(pci_config_space+0x34)=0; +#endif + *(u32 *)(pci_config_space+0x30)=(u32)((unsigned long)qt_fcode&0xffffffff); + + /* FIXME: we need to put the fcode image for this + * device to the rom resource, once it exists + */ + + /* register pci device to be available to beginagain */ + pci_register_device(0, 2, 0, pci_config_space); + +#ifdef DEBUG + printf("done.\n"); +#endif + return 0; +} + +PLUGIN_AUTHOR("Stefan Reinauer <stepan@openbios.org>") +PLUGIN_DESCRIPTION("QT gui plugin emulating framebuffer device") +PLUGIN_LICENSE("GPL v2") +PLUGIN_DEPENDENCIES("pci") + +} diff --git a/qemu/roms/openbios/arch/unix/plugins/plugin_qt/qt_rom.fs b/qemu/roms/openbios/arch/unix/plugins/plugin_qt/qt_rom.fs new file mode 100644 index 000000000..1879c3654 --- /dev/null +++ b/qemu/roms/openbios/arch/unix/plugins/plugin_qt/qt_rom.fs @@ -0,0 +1,85 @@ +\ tag: Property management +\ +\ this code implements an IEEE 1275-1994 fcode driver +\ for the OpenBIOS qt interface +\ +\ Copyright (C) 2003 Stefan Reinauer +\ +\ See the file "COPYING" for further information about +\ the copyright and warranty status of this work. +\ + +hex + +tokenizer[ 1002 4336 0300 23 ]tokenizer ( -- vid did classid revision ) + +pci-revision + +pci-header + +fcode-version2 +headers + +" dev /pci" evaluate +new-device + + " ATY,QTEMU" device-name + " display" device-type + + " iso8859-1" encode-string + " character-set" property + + true encode-int + " iso6429-1983-colors" property + + : qt-open + \ [..] + ." opening framebuffer device." cr + 10 10 " pci-l@" evaluate + /n 8 = if + 10 14 " pci-l@" evaluate + 20 << or + then + ." framebuffer pointer is at 0x" dup . cr + to frame-buffer-adr + default-font set-font + d# 640 d# 480 d# 80 d# 30 fb8-install + true + ; + + : qt-close + ." QT Interface closed." cr + 0 to frame-buffer-adr + ; + + : qt-selftest + ." QT Interface selftest" cr + 0 + ; + + ['] qt-open is-install + ['] qt-close is-remove + ['] qt-selftest is-selftest + + external + +\ the following words will be defined by fb8-install +\ + +\ : open ( -- true ) +\ ; + +\ : write ( addr len -- actual ) +\ ; + +\ : draw-logo ( line# addr width height -- ) +\ ; + +\ : restore ( -- ) +\ ; + +finish-device + +fcode-end + +pci-end diff --git a/qemu/roms/openbios/arch/unix/tree.fs b/qemu/roms/openbios/arch/unix/tree.fs new file mode 100644 index 000000000..a7529b006 --- /dev/null +++ b/qemu/roms/openbios/arch/unix/tree.fs @@ -0,0 +1,116 @@ +:noname + ." Type 'help' for detailed information" cr + ; DIAG-initializer + +" /" find-device + +new-device + " memory" device-name + \ 12230 encode-int " reg" property + external + : open true ; + : close ; + \ claim ( phys size align -- base ) + \ release ( phys size -- ) +finish-device + +new-device + " cpus" device-name + 1 " #address-cells" int-property + 0 " #size-cells" int-property + + external + : open true ; + : close ; + : decode-unit parse-hex ; + +finish-device + +: make-openable ( path ) + find-dev if + begin ?dup while + \ install trivial open and close methods + dup active-package! is-open + parent + repeat + then +; + +: preopen ( chosen-str node-path ) + 2dup make-openable + + " /chosen" find-device + open-dev ?dup if + encode-int 2swap property + else + 2drop + then +; + +:noname + set-defaults +; SYSTEM-initializer + + +\ preopen device nodes (and store the ihandles under /chosen) +:noname + " memory" " /memory" preopen + " mmu" " /cpus/@0" preopen + " stdout" " /builtin/console" preopen + " stdin" " /builtin/console" preopen + device-end +; SYSTEM-initializer + +\ use the tty interface if available +:noname + " /builtin/console" find-dev if drop + " /builtin/console" " input-device" $setenv + " /builtin/console" " output-device" $setenv + then +; SYSTEM-initializer + +:noname + " keyboard" input +; CONSOLE-IN-initializer + +dev / + +\ node suitable for non-PCI devices +new-device + " unix" device-name + 0 encode-int " #address-cells" property + 0 encode-int " #size-cells" property + + external + : open true ; + : close ; + +\ block device node +new-device + " block" device-name + " unix-block" device-type + 1 " #address-cells" int-property + 0 " #size-cells" int-property + + external + : open true ; + : close ; + : decode-unit parse-hex ; + +\ testnode +\ new-device +\ " kappa" device-name +\ +\ 1 encode-int " reg" property +\ external +\ : open true ; +\ : close ; +\ finish-device + +finish-device +finish-device + +dev /aliases +" /unix/block/disk" encode-string " hd" property + +device-end diff --git a/qemu/roms/openbios/arch/unix/unix.c b/qemu/roms/openbios/arch/unix/unix.c new file mode 100644 index 000000000..1f628eb78 --- /dev/null +++ b/qemu/roms/openbios/arch/unix/unix.c @@ -0,0 +1,611 @@ +/* tag: hosted forth environment, executable code + * + * Copyright (C) 2003-2005 Patrick Mauritz, Stefan Reinauer + * + * See the file "COPYING" for further information about + * the copyright and warranty status of this work. + */ + +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <signal.h> +#define __USE_LARGEFILE64 +#include <fcntl.h> +#include <unistd.h> +#include <termios.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <stdarg.h> + +#ifdef __GLIBC__ +#define _GNU_SOURCE +#include <getopt.h> +#endif + +#include "sysinclude.h" +#include "mconfig.h" +#include "config.h" +#include "kernel/kernel.h" +#include "dict.h" +#include "kernel/stack.h" +#include "arch/unix/plugins.h" +#include "libopenbios/bindings.h" +#include "libopenbios/console.h" +#include "libopenbios/openbios.h" +#include "openbios-version.h" + +#include "blk.h" +#include "libopenbios/ofmem.h" + +#define MEMORY_SIZE (4*1024*1024) /* 4M ram for hosted system */ +#define DICTIONARY_SIZE (256*1024) /* 256k for the dictionary */ + +#if defined(_FILE_OFFSET_BITS) && (_FILE_OFFSET_BITS==64) +#define lseek lseek64 +#define __LFS O_LARGEFILE +#else +#define __LFS 0 +#endif + +/* prototypes */ +static void exit_terminal(void); +void boot(void); + +unsigned long virt_offset = 0; + +/* local variables */ + +static ucell *memory; + +static int diskemu; + +static int segfault = 0; +static int verbose = 0; + +#if defined(CONFIG_PPC) || defined(CONFIG_SPARC64) +unsigned long isa_io_base; +#endif + +int errno_int; /* implement for fs drivers, needed to build on Mac OS X */ + +ucell ofmem_claim(ucell addr, ucell size, ucell align) +{ + return 0; +} + +#ifdef CONFIG_PPC +extern void flush_icache_range(char *start, char *stop); + +void flush_icache_range(char *start, char *stop) +{ +} +#endif + +#ifdef CONFIG_PPC +/* Expose system level is_machine helpers to make generic code easier */ + +#include "drivers/drivers.h" +int is_apple(void) +{ + return 0; +} + +int is_oldworld(void) +{ + return 0; +} + +int is_newworld(void) +{ + return 0; +} +#endif + +#if 0 +static void write_dictionary(char *filename) +{ + FILE *f; + xt_t initxt; + + initxt = findword("initialize-of"); + if (!initxt) + printk("warning: dictionary needs word called initialize-of\n"); + + f = fopen(filename, "w"); + if (!f) { + printk("panic: can't open dictionary.\n"); + exit_terminal(); + exit(1); + } + + fwrite(DICTID, 16, 1, f); + fwrite(dict, dicthead, 1, f); + + /* Write start address and last to relocate on load */ + fwrite(&dict, sizeof(ucell), 1, f); + fwrite(&last, sizeof(ucell), 1, f); + + fclose(f); + +#ifdef CONFIG_DEBUG_DICTIONARY + printk("wrote dictionary to file %s.\n", filename); +#endif +} +#endif + +static ucell read_dictionary(char *fil) +{ + int ilen; + ucell ret; + char *mem; + FILE *f; + struct stat finfo; + + if (stat(fil, &finfo)) + return 0; + + ilen = finfo.st_size; + + if ((mem = malloc(ilen)) == NULL) { + printk("panic: not enough memory.\n"); + exit_terminal(); + exit(1); + } + + f = fopen(fil, "r"); + if (!f) { + printk("panic: can't open dictionary.\n"); + exit_terminal(); + exit(1); + } + + if (fread(mem, ilen, 1, f) != 1) { + printk("panic: can't read dictionary.\n"); + fclose(f); + exit_terminal(); + exit(1); + } + fclose(f); + + ret = load_dictionary(mem, ilen); + + free(mem); + return ret; +} + + +/* + * functions used by primitives + */ + +static int unix_availchar(void) +{ + int tmp = getc(stdin); + if (tmp != EOF) { + ungetc(tmp, stdin); + return -1; + } + return 0; +} + +static int unix_putchar(int c) +{ + putc(c, stdout); + return c; +} + +static int unix_getchar(void) +{ + return getc(stdin); +} + +static struct _console_ops unix_console_ops = { + .putchar = unix_putchar, + .availchar = unix_availchar, + .getchar = unix_getchar +}; + +u8 inb(u32 reg) +{ +#ifdef CONFIG_PLUGINS + io_ops_t *ior = find_iorange(reg); + if (ior) + return ior->inb(reg); +#endif + + printk("TRAP: io byte read @0x%x", reg); + return 0xff; +} + +u16 inw(u32 reg) +{ +#ifdef CONFIG_PLUGINS + io_ops_t *ior = find_iorange(reg); + if (ior) + return ior->inw(reg); +#endif + + printk("TRAP: io word read @0x%x", reg); + return 0xffff; +} + +u32 inl(u32 reg) +{ +#ifdef CONFIG_PLUGINS + io_ops_t *ior = find_iorange(reg); + if (ior) + return ior->inl(reg); +#endif + + printk("TRAP: io long read @0x%x", reg); + return 0xffffffff; +} + +void outb(u32 reg, u8 val) +{ +#ifdef CONFIG_PLUGINS + io_ops_t *ior = find_iorange(reg); + if (ior) { + ior->outb(reg, val); + return; + } +#endif + + printk("TRAP: io byte write 0x%x -> 0x%x", val, reg); +} + +void outw(u32 reg, u16 val) +{ +#ifdef CONFIG_PLUGINS + io_ops_t *ior = find_iorange(reg); + if (ior) { + ior->outw(reg, val); + return; + } +#endif + printk("TRAP: io word write 0x%x -> 0x%x", val, reg); +} + +void outl(u32 reg, u32 val) +{ +#ifdef CONFIG_PLUGINS + io_ops_t *ior = find_iorange(reg); + if (ior) { + ior->outl(reg, val); + return; + } +#endif + printk("TRAP: io long write 0x%x -> 0x%x", val, reg); +} + +/* + * terminal initialization and cleanup. + */ + +static struct termios saved_termios; + +static void init_terminal(void) +{ + struct termios termios; + + tcgetattr(0, &saved_termios); + tcgetattr(0, &termios); + termios.c_lflag &= ~(ICANON | ECHO); + termios.c_cc[VMIN] = 1; + termios.c_cc[VTIME] = 3; // 300 ms + tcsetattr(0, 0, &termios); +} + +static void exit_terminal(void) +{ + tcsetattr(0, 0, &saved_termios); +} + +/* + * segmentation fault handler. linux specific? + */ + +static void +segv_handler(int signo __attribute__ ((unused)), + siginfo_t * si, void *context __attribute__ ((unused))) +{ + static int count = 0; + ucell addr = 0xdeadbeef; + + if (count) { + printk("Died while dumping forth dictionary core.\n"); + goto out; + } + + count++; + + if (PC >= (ucell) dict && PC <= (ucell) dict + dicthead) + addr = *(ucell *) PC; + + printk("panic: segmentation violation at %x\n", (ucell)si->si_addr); + printk("dict=0x%x here=0x%x(dict+0x%x) pc=0x%x(dict+0x%x)\n", + (ucell)dict, (ucell)dict + dicthead, dicthead, PC, PC - (ucell) dict); + printk("dstackcnt=%d rstackcnt=%d instruction=%x\n", + dstackcnt, rstackcnt, addr); + +#ifdef CONFIG_DEBUG_DSTACK + printdstack(); +#endif +#ifdef CONFIG_DEBUG_RSTACK + printrstack(); +#endif +#if 0 + printk("Writing dictionary core file\n"); + write_dictionary("forth.dict.core"); +#endif + + out: + exit_terminal(); + exit(1); +} + +/* + * Interrupt handler. linux specific? + * Restore terminal state on ctrl-C. + */ + +static void +int_handler(int signo __attribute__ ((unused)), + siginfo_t * si __attribute__ ((unused)), + void *context __attribute__ ((unused))) +{ + printk("\n"); + exit_terminal(); + exit(1); +} + +/* + * allocate memory and prepare engine for memory management. + */ + +static void init_memory(void) +{ + memory = malloc(MEMORY_SIZE); + if (!memory) { + printk("panic: not enough memory on host system.\n"); + exit_terminal(); + exit(1); + } + + memset (memory, 0, MEMORY_SIZE); + /* we push start and end of memory to the stack + * so that it can be used by the forth word QUIT + * to initialize the memory allocator + */ + + PUSH((ucell) memory); + PUSH((ucell) memory + MEMORY_SIZE); +} + +void exception(__attribute__((unused)) cell no) +{ + /* + * this is a noop since the dictionary has to take care + * itself of errors it generates outside of the bootstrap + */ +} + +static void +arch_init( void ) +{ + openbios_init(); + modules_init(); + if(diskemu!=-1) + blk_init(); + + device_end(); + bind_func("platform-boot", boot); +} + +int +read_from_disk( int channel, int unit, int blk, unsigned long mphys, int size ) +{ + // channels and units not supported yet. + unsigned char *buf=(unsigned char *)mphys; + + if(diskemu==-1) + return -1; + + //printk("read: ch=%d, unit=%d, blk=%ld, phys=%lx, size=%d\n", + // channel, unit, blk, mphys, size); + + lseek(diskemu, (ducell)blk*512, SEEK_SET); + read(diskemu, buf, size); + + return 0; +} + +/* + * main loop + */ + +#define BANNER "OpenBIOS core. (C) 2003-2006 Patrick Mauritz, Stefan Reinauer\n"\ + "This software comes with absolutely no warranty. "\ + "All rights reserved.\n\n" + + +#define USAGE "usage: %s [options] [dictionary file|source file]\n\n" + +int main(int argc, char *argv[]) +{ + struct sigaction sa; +#if 0 + unsigned char *dictname = NULL; +#endif + int c; + + const char *optstring = "VvhsD:P:p:f:?"; + + while (1) { +#ifdef __GLIBC__ + int option_index = 0; + static struct option long_options[] = { + {"version", 0, NULL, 'V'}, + {"verbose", 0, NULL, 'v'}, + {"help", 0, NULL, 'h'}, +// {"dictionary", 1, NULL, 'D'}, + {"segfault", 0, NULL, 's'}, +#ifdef CONFIG_PLUGINS + {"plugin-path", 1, NULL, 'P'}, + {"plugin", 1, NULL, 'p'}, +#endif + {"file", 1, NULL, 'f'} + }; + + c = getopt_long(argc, argv, optstring, long_options, + &option_index); +#else + c = getopt(argc, argv, optstring); +#endif + if (c == -1) + break; + + switch (c) { + case 'V': + printk(BANNER "Version " OPENBIOS_VERSION_STR "\n"); + return 0; + case 'h': + case '?': + printk(BANNER "Version " OPENBIOS_VERSION_STR "\n" + USAGE, argv[0]); + return 0; + case 'v': + verbose = 1; + break; + case 's': + segfault = 1; + break; +#if 0 + case 'D': + printk("Dumping final dictionary to '%s'\n", optarg); + dictname = optarg; + break; +#endif +#ifdef CONFIG_PLUGINS + case 'P': + printk("Plugin search path is now '%s'\n", optarg); + plugindir = optarg; + break; + case 'p': + printk("Loading plugin %s\n", optarg); + load_plugin(optarg); + break; +#endif + case 'f': + diskemu=open(optarg, O_RDONLY|__LFS); + if(diskemu!=-1) + printk("Using %s as harddisk.\n", optarg); + else + printk("%s not found. no harddisk node.\n", + optarg); + break; + default: + return 1; + } + } + + if (argc < optind + 1) { + printk(USAGE, argv[0]); + return 1; + } + + /* Initialise console */ + init_console(unix_console_ops); + + if ((dict = (unsigned char *) malloc(DICTIONARY_SIZE)) == NULL) { + printk("panic: not enough memory.\n"); + return 1; + } + + dictlimit = DICTIONARY_SIZE; + memset(dict, 0, DICTIONARY_SIZE); + + if (!segfault) { + if (verbose) + printk("Installing SIGSEGV handler..."); + + sa.sa_sigaction = segv_handler; + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_SIGINFO | SA_NODEFER; + sigaction(SIGSEGV, &sa, NULL); + + if (verbose) + printk("done.\n"); + } + + /* set terminal to do non blocking reads */ + init_terminal(); + + if (verbose) + printk("Installing SIGINT handler..."); + + sa.sa_sigaction = int_handler; + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_SIGINFO | SA_NODEFER; + sigaction(SIGINT, &sa, NULL); + + if (verbose) + printk("done.\n"); + + read_dictionary(argv[optind]); + forth_init(); + + PUSH_xt( bind_noname_func(arch_init) ); + fword("PREPOST-initializer"); + + PC = (cell)findword("initialize-of"); + if (PC) { + if (verbose) { + if (optind + 1 != argc) + printk("Warning: only first dictionary used.\n"); + + printk("dictionary loaded (%d bytes).\n", dicthead); + printk("Initializing memory..."); + } + init_memory(); + + if (verbose) { + printk("done\n"); + + printk("Jumping to dictionary..."); + } + + enterforth((xt_t)PC); +#if 0 + if (dictname != NULL) + write_dictionary(dictname); +#endif + + free(memory); + + } else { /* input file is not a dictionary */ + printk("not supported.\n"); + } + + exit_terminal(); + if (diskemu!=-1) + close(diskemu); + + free(dict); + return 0; +} + +#undef printk +int +printk( const char *fmt, ... ) +{ + int i; + + va_list args; + va_start( args, fmt ); + i = vprintf(fmt, args ); + va_end( args ); + return i; +} diff --git a/qemu/roms/openbios/arch/x86/Kconfig b/qemu/roms/openbios/arch/x86/Kconfig new file mode 100644 index 000000000..eac958287 --- /dev/null +++ b/qemu/roms/openbios/arch/x86/Kconfig @@ -0,0 +1,47 @@ +mainmenu "OpenBIOS Configuration" + +config X86 + bool + default y + help + Building for X86 hardware. + +config LITTLE_ENDIAN + bool + default y + help + X86 is little endian + +menu "Kernel binaries (x86)" + +config IMAGE_ELF + bool "ELF image (for LinuxBIOS)" + default y + help + Build a simple elf image that can be used with LinuxBIOS + This image will be called openbios.elf + +config IMAGE_ELF_EMBEDDED + bool "ELF image with embedded dictionary" + default y + help + Build an elf image with embedded dictionary. This image + can easily be used with etherboot. + The image filename is openbios.full + +config IMAGE_ELF_MULTIBOOT + bool "Multiboot image" + default y + help + Build a multiboot image for booting with grub + +endmenu + +menu "Build hosted UNIX Binary" +source "arch/unix/Kconfig" +endmenu + +source "kernel/Kconfig" +source "forth/Kconfig" +source "libopenbios/Kconfig" +source "drivers/Kconfig" diff --git a/qemu/roms/openbios/arch/x86/boot.c b/qemu/roms/openbios/arch/x86/boot.c new file mode 100644 index 000000000..d40ab8c5b --- /dev/null +++ b/qemu/roms/openbios/arch/x86/boot.c @@ -0,0 +1,74 @@ +/* tag: openbios boot command for x86 + * + * Copyright (C) 2003-2004 Stefan Reinauer + * + * See the file "COPYING" for further information about + * the copyright and warranty status of this work. + */ + +#undef BOOTSTRAP +#include "config.h" +#include "libopenbios/bindings.h" +#include "arch/common/nvram.h" +#include "libc/diskio.h" +#include "libopenbios/sys_info.h" +#include "boot.h" + +void go(void) +{ + ucell address, type, size; + int image_retval = 0; + + /* Get the entry point and the type (see forth/debugging/client.fs) */ + feval("saved-program-state >sps.entry @"); + address = POP(); + feval("saved-program-state >sps.file-type @"); + type = POP(); + feval("saved-program-state >sps.file-size @"); + size = POP(); + + printk("\nJumping to entry point " FMT_ucellx " for type " FMT_ucellx "...\n", address, type); + + switch (type) { + case 0x0: + /* Start ELF boot image */ + image_retval = start_elf(address, (uint32_t)&elf_boot_notes); + break; + + case 0x1: + /* Start ELF image */ + image_retval = start_elf(address, (uint32_t)NULL); + break; + + case 0x5: + /* Start a.out image */ + image_retval = start_elf(address, (uint32_t)NULL); + break; + + case 0x10: + /* Start Fcode image */ + printk("Evaluating FCode...\n"); + PUSH(address); + PUSH(1); + fword("byte-load"); + image_retval = 0; + break; + + case 0x11: + /* Start Forth image */ + PUSH(address); + PUSH(size); + fword("eval2"); + image_retval = 0; + break; + } + + printk("Image returned with return value %#x\n", image_retval); +} + + +void boot(void) +{ + /* No platform-specific boot code */ + return; +} diff --git a/qemu/roms/openbios/arch/x86/boot.h b/qemu/roms/openbios/arch/x86/boot.h new file mode 100644 index 000000000..749c608b3 --- /dev/null +++ b/qemu/roms/openbios/arch/x86/boot.h @@ -0,0 +1,18 @@ +/* tag: openbios loader prototypes for x86 + * + * Copyright (C) 2004 Stefan Reinauer + * + * See the file "COPYING" for further information about + * the copyright and warranty status of this work. + */ + +/* linux_load.c */ +int linux_load(struct sys_info *info, const char *file, const char *cmdline); + +/* context.c */ +extern struct context *__context; +unsigned int start_elf(unsigned long entry_point, unsigned long param); + +/* boot.c */ +extern void boot(void); +extern void go(void); diff --git a/qemu/roms/openbios/arch/x86/build.xml b/qemu/roms/openbios/arch/x86/build.xml new file mode 100644 index 000000000..260a33258 --- /dev/null +++ b/qemu/roms/openbios/arch/x86/build.xml @@ -0,0 +1,86 @@ +<build condition="X86"> + + <dictionary name="openbios-x86" init="openbios"> + <object source="init.fs" target="forth"/> + <object source="QEMU,VGA.bin" target="fcode" condition="DRIVER_VGA"/> + </dictionary> + + <library name="x86" type="static" target="target"> + <object source="openbios.c"/> + <object source="exception.c"/> + <object source="console.c"/> + <object source="lib.c"/> + <object source="boot.c"/> + <object source="context.c"/> + <object source="linux_load.c"/> + <object source="segment.c"/> + <object source="sys_info.c"/> + <object source="entry.S"/> + <object source="xbox/console.c" condition="XBOX"/> + <object source="xbox/methods.c" condition="XBOX"/> + </library> + + <executable name="openbios.multiboot" target="target" condition="IMAGE_ELF_MULTIBOOT"> + <rule> + $(call quiet-command,$(LD) --warn-common -N -T $(SRCDIR)/arch/x86/ldscript -o $@.nostrip --whole-archive $^," LINK $(TARGET_DIR)$@") + $(call quiet-command,$(NM) $@.nostrip | sort > $(ODIR)/openbios-multiboot.syms," GEN $(TARGET_DIR)$@.syms") + $(call quiet-command,$(STRIP) $@.nostrip -o $@," STRIP $(TARGET_DIR)$@")</rule> + <object source="multiboot.c"/> + <external-object source="libx86.a"/> + <external-object source="libbootstrap.a"/> + <external-object source="libopenbios.a"/> + <external-object source="libpackages.a"/> + <external-object source="libdrivers.a"/> + <external-object source="liblibc.a"/> + <external-object source="libfs.a"/> + <external-object source="libgcc.a"/> + </executable> + + <executable name="openbios-plain.elf" target="target" condition="IMAGE_ELF"> + <rule> + $(call quiet-command,$(LD) --warn-common -N -T $(SRCDIR)/arch/x86/ldscript -o $@.nostrip --whole-archive $^," LINK $(TARGET_DIR)$@") + $(call quiet-command,$(NM) $@.nostrip | sort > $(ODIR)/openbios-plain.syms," GEN $(TARGET_DIR)$@.syms") + $(call quiet-command,$(STRIP) $@.nostrip -o $@," STRIP $(TARGET_DIR)$@")</rule> + <object source="plainboot.c"/> + <external-object source="libx86.a"/> + <external-object source="libbootstrap.a"/> + <external-object source="libopenbios.a"/> + <external-object source="libpackages.a"/> + <external-object source="libdrivers.a"/> + <external-object source="liblibc.a"/> + <external-object source="libfs.a"/> + <external-object source="libgcc.a"/> + </executable> + + <!-- HACK ALERT --> + + <executable name="target/include/static-dict.h" target="target" condition="IMAGE_ELF_EMBEDDED"> + <rule><![CDATA[ + $(call quiet-command,$(ODIR)/forthstrap -x -D $@ -d $< </dev/null, " GEN $(TARGET_DIR)$@")]]></rule> + <external-object source="openbios-x86.dict"/> + </executable> + + <executable name="target/arch/x86/builtin.o" target="target" condition="IMAGE_ELF_EMBEDDED"> + <rule><![CDATA[ $(SRCDIR)/arch/x86/builtin.c $(ODIR)/target/include/static-dict.h + $(call quiet-command,$(CC) $$EXTRACFLAGS $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/arch/x86/builtin.c, " CC $(TARGET_DIR)$@")]]></rule> + </executable> + + <!-- END OF HACK ALERT --> + + <executable name="openbios-builtin.elf" target="target" condition="IMAGE_ELF_EMBEDDED"> + <rule> + $(call quiet-command,$(LD) --warn-common -N -T $(SRCDIR)/arch/x86/ldscript -o $@.nostrip --whole-archive $^," LINK $(TARGET_DIR)$@") + $(call quiet-command,$(NM) $@.nostrip | sort > $(ODIR)/openbios-builtin.syms," GEN $(TARGET_DIR)$@.syms") + $(call quiet-command,$(STRIP) $@.nostrip -o $@," STRIP $(TARGET_DIR)$@")</rule> + <external-object source="target/arch/x86/builtin.o"/> + <external-object source="libx86.a"/> + <external-object source="libbootstrap.a"/> + <external-object source="libopenbios.a"/> + <external-object source="libpackages.a"/> + <external-object source="libdrivers.a"/> + <external-object source="liblibc.a"/> + <external-object source="libfs.a"/> + <external-object source="libgcc.a"/> + </executable> + +</build> diff --git a/qemu/roms/openbios/arch/x86/builtin.c b/qemu/roms/openbios/arch/x86/builtin.c new file mode 100644 index 000000000..f7d8aba6d --- /dev/null +++ b/qemu/roms/openbios/arch/x86/builtin.c @@ -0,0 +1,32 @@ +/* tag: openbios forth starter for builtin dictionary + * + * Copyright (C) 2003 Stefan Reinauer + * + * See the file "COPYING" for further information about + * the copyright and warranty status of this work. + */ + +#include "config.h" +#include "libopenbios/sys_info.h" + +/* + * wrap an array around the hex'ed dictionary file + */ + +/* 256K for the dictionary */ +#define DICTIONARY_SIZE (256 * 1024 / sizeof(ucell)) +#define DICTIONARY_BASE ((ucell)((char *)&forth_dictionary)) + +static ucell forth_dictionary[DICTIONARY_SIZE] = { +#include "static-dict.h" +}; + +void collect_multiboot_info(struct sys_info *info); +void collect_multiboot_info(struct sys_info *info) +{ + info->dict_start=(unsigned long *)forth_dictionary; + info->dict_end = (unsigned long *)FORTH_DICTIONARY_END; + info->dict_last = (ucell *)((unsigned char *)forth_dictionary + + FORTH_DICTIONARY_LAST); + info->dict_limit = sizeof(forth_dictionary); +} diff --git a/qemu/roms/openbios/arch/x86/console.c b/qemu/roms/openbios/arch/x86/console.c new file mode 100644 index 000000000..906e69c25 --- /dev/null +++ b/qemu/roms/openbios/arch/x86/console.c @@ -0,0 +1,418 @@ +/* + * Copyright (C) 2003, 2004 Stefan Reinauer + * + * See the file "COPYING" for further information about + * the copyright and warranty status of this work. + */ + +#include "config.h" +#include "kernel/kernel.h" +#include "openbios.h" +#include "libopenbios/console.h" + +#ifdef CONFIG_DEBUG_CONSOLE + +/* ****************************************************************** + * serial console functions + * ****************************************************************** */ + +#ifdef CONFIG_DEBUG_CONSOLE_SERIAL + +#define RBR(x) x==2?0x2f8:0x3f8 +#define THR(x) x==2?0x2f8:0x3f8 +#define IER(x) x==2?0x2f9:0x3f9 +#define IIR(x) x==2?0x2fa:0x3fa +#define LCR(x) x==2?0x2fb:0x3fb +#define MCR(x) x==2?0x2fc:0x3fc +#define LSR(x) x==2?0x2fd:0x3fd +#define MSR(x) x==2?0x2fe:0x3fe +#define SCR(x) x==2?0x2ff:0x3ff +#define DLL(x) x==2?0x2f8:0x3f8 +#define DLM(x) x==2?0x2f9:0x3f9 + +static int uart_charav(int port) +{ + if (!port) + return -1; + return ((inb(LSR(port)) & 1) != 0); +} + +static char uart_getchar(int port) +{ + if (!port) + return -1; + while (!uart_charav(port)); + return ((char) inb(RBR(port)) & 0177); +} + +static void uart_putchar(int port, unsigned char c) +{ + if (!port) + return; + if (c == '\n') + uart_putchar(port, '\r'); + while (!(inb(LSR(port)) & 0x20)); + outb(c, THR(port)); +} + +static void uart_init_line(int port, unsigned long baud) +{ + int i, baudconst; + + if (!port) + return; + + switch (baud) { + case 115200: + baudconst = 1; + break; + case 57600: + baudconst = 2; + break; + case 38400: + baudconst = 3; + break; + case 19200: + baudconst = 6; + break; + case 9600: + default: + baudconst = 12; + break; + } + + outb(0x87, LCR(port)); + outb(0x00, DLM(port)); + outb(baudconst, DLL(port)); + outb(0x07, LCR(port)); + outb(0x0f, MCR(port)); + + for (i = 10; i > 0; i--) { + if (inb(LSR(port)) == (unsigned int) 0) + break; + inb(RBR(port)); + } +} + +int uart_init(int port, unsigned long speed) +{ + if (port) + uart_init_line(port, speed); + return -1; +} + +static void serial_putchar(int c) +{ + uart_putchar(CONFIG_SERIAL_PORT, (unsigned char) (c & 0xff)); +} + +static void serial_cls(void) +{ + serial_putchar(27); + serial_putchar('['); + serial_putchar('H'); + serial_putchar(27); + serial_putchar('['); + serial_putchar('J'); +} + +#endif + +/* ****************************************************************** + * simple polling video/keyboard console functions + * ****************************************************************** */ + +#ifdef CONFIG_DEBUG_CONSOLE_VGA + +/* raw vga text mode */ +#define COLUMNS 80 /* The number of columns. */ +#define LINES 25 /* The number of lines. */ +#define ATTRIBUTE 7 /* The attribute of an character. */ + +#define VGA_BASE 0xB8000 /* The video memory address. */ + +/* VGA Index and Data Registers */ +#define VGA_REG_INDEX 0x03D4 /* VGA index register */ +#define VGA_REG_DATA 0x03D5 /* VGA data register */ + +#define VGA_IDX_CURMSL 0x09 /* cursor maximum scan line */ +#define VGA_IDX_CURSTART 0x0A /* cursor start */ +#define VGA_IDX_CUREND 0x0B /* cursor end */ +#define VGA_IDX_CURLO 0x0F /* cursor position (low 8 bits) */ +#define VGA_IDX_CURHI 0x0E /* cursor position (high 8 bits) */ + +/* Save the X and Y position. */ +static int xpos, ypos; +/* Point to the video memory. */ +static volatile unsigned char *video = (unsigned char *) VGA_BASE; + +static void video_initcursor(void) +{ + u8 val; + outb(VGA_IDX_CURMSL, VGA_REG_INDEX); + val = inb(VGA_REG_DATA) & 0x1f; /* maximum scan line -1 */ + + outb(VGA_IDX_CURSTART, VGA_REG_INDEX); + outb(0, VGA_REG_DATA); + + outb(VGA_IDX_CUREND, VGA_REG_INDEX); + outb(val, VGA_REG_DATA); +} + + + +static void video_poscursor(unsigned int x, unsigned int y) +{ + unsigned short pos; + + /* Calculate new cursor position as a function of x and y */ + pos = (y * COLUMNS) + x; + + /* Output the new position to VGA card */ + outb(VGA_IDX_CURLO, VGA_REG_INDEX); /* output low 8 bits */ + outb((u8) (pos), VGA_REG_DATA); + outb(VGA_IDX_CURHI, VGA_REG_INDEX); /* output high 8 bits */ + outb((u8) (pos >> 8), VGA_REG_DATA); + +}; + + +static void video_newline(void) +{ + xpos = 0; + + if (ypos < LINES - 1) { + ypos++; + } else { + int i; + memmove((void *) video, (void *) (video + 2 * COLUMNS), + (LINES - 1) * COLUMNS * 2); + + for (i = ((LINES - 1) * 2 * COLUMNS); + i < 2 * COLUMNS * LINES;) { + video[i++] = 0; + video[i++] = ATTRIBUTE; + } + } + +} + +/* Put the character C on the screen. */ +static void video_putchar(int c) +{ + int p=1; + + if (c == '\n' || c == '\r') { + video_newline(); + return; + } + + if (c == '\b') { + if (xpos) xpos--; + c=' '; + p=0; + } + + + if (xpos >= COLUMNS) + video_newline(); + + *(video + (xpos + ypos * COLUMNS) * 2) = c & 0xFF; + *(video + (xpos + ypos * COLUMNS) * 2 + 1) = ATTRIBUTE; + + if (p) + xpos++; + + video_poscursor(xpos, ypos); +} + +static void video_cls(void) +{ + int i; + + for (i = 0; i < 2 * COLUMNS * LINES;) { + video[i++] = 0; + video[i++] = ATTRIBUTE; + } + + + xpos = 0; + ypos = 0; + + video_initcursor(); + video_poscursor(xpos, ypos); +} + +void video_init(void) +{ + video=phys_to_virt((unsigned char*)VGA_BASE); +} + +/* + * keyboard driver + */ + +static const char normal[] = { + 0x0, 0x1b, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', + '=', '\b', '\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', + 'p', '[', ']', 0xa, 0x0, 'a', 's', 'd', 'f', 'g', 'h', 'j', + 'k', 'l', ';', 0x27, 0x60, 0x0, 0x5c, 'z', 'x', 'c', 'v', 'b', + 'n', 'm', ',', '.', '/', 0x0, '*', 0x0, ' ', 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, '0', 0x7f +}; + +static const char shifted[] = { + 0x0, 0x1b, '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', + '+', '\b', '\t', 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', + 'P', '{', '}', 0xa, 0x0, 'A', 'S', 'D', 'F', 'G', 'H', 'J', + 'K', 'L', ':', 0x22, '~', 0x0, '|', 'Z', 'X', 'C', 'V', 'B', + 'N', 'M', '<', '>', '?', 0x0, '*', 0x0, ' ', 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, '7', '8', + '9', 0x0, '4', '5', '6', 0x0, '1', '2', '3', '0', 0x7f +}; + +static int key_ext; +static int key_lshift = 0, key_rshift = 0, key_caps = 0; + +static char last_key; + +static void keyboard_cmd(unsigned char cmd, unsigned char val) +{ + outb(cmd, 0x60); + /* wait until keyboard controller accepts cmds: */ + while (inb(0x64) & 2); + outb(val, 0x60); + while (inb(0x64) & 2); +} + +static char keyboard_poll(void) +{ + unsigned int c; + if (inb(0x64) & 1) { + c = inb(0x60); + switch (c) { + case 0xe0: + key_ext = 1; + return 0; + case 0x2a: + key_lshift = 1; + return 0; + case 0x36: + key_rshift = 1; + return 0; + case 0xaa: + key_lshift = 0; + return 0; + case 0xb6: + key_rshift = 0; + return 0; + case 0x3a: + if (key_caps) { + key_caps = 0; + keyboard_cmd(0xed, 0); + } else { + key_caps = 1; + keyboard_cmd(0xed, 4); /* set caps led */ + } + return 0; + } + + if (key_ext) { + // void printk(const char *format, ...); + printk("extended keycode: %x\n", c); + + key_ext = 0; + return 0; + } + + if (c & 0x80) /* unhandled key release */ + return 0; + + if (key_lshift || key_rshift) + return key_caps ? normal[c] : shifted[c]; + else + return key_caps ? shifted[c] : normal[c]; + } + return 0; +} + +static int keyboard_dataready(void) +{ + if (last_key) + return 1; + + last_key = keyboard_poll(); + + return (last_key != 0); +} + +static unsigned char keyboard_readdata(void) +{ + char tmp; + while (!keyboard_dataready()); + tmp = last_key; + last_key = 0; + return tmp; +} +#endif + + +/* ****************************************************************** + * common functions, implementing simple concurrent console + * ****************************************************************** */ + +static int arch_putchar(int c) +{ +#ifdef CONFIG_DEBUG_CONSOLE_SERIAL + serial_putchar(c); +#endif +#ifdef CONFIG_DEBUG_CONSOLE_VGA + video_putchar(c); +#endif + return c; +} + +static int arch_availchar(void) +{ +#ifdef CONFIG_DEBUG_CONSOLE_SERIAL + if (uart_charav(CONFIG_SERIAL_PORT)) + return 1; +#endif +#ifdef CONFIG_DEBUG_CONSOLE_VGA + if (keyboard_dataready()) + return 1; +#endif + return 0; +} + +static int arch_getchar(void) +{ +#ifdef CONFIG_DEBUG_CONSOLE_SERIAL + if (uart_charav(CONFIG_SERIAL_PORT)) + return (uart_getchar(CONFIG_SERIAL_PORT)); +#endif +#ifdef CONFIG_DEBUG_CONSOLE_VGA + if (keyboard_dataready()) + return (keyboard_readdata()); +#endif + return 0; +} + +void cls(void) +{ +#ifdef CONFIG_DEBUG_CONSOLE_SERIAL + serial_cls(); +#endif +#ifdef CONFIG_DEBUG_CONSOLE_VGA + video_cls(); +#endif +} + +struct _console_ops arch_console_ops = { + .putchar = arch_putchar, + .availchar = arch_availchar, + .getchar = arch_getchar +}; + +#endif // CONFIG_DEBUG_CONSOLE diff --git a/qemu/roms/openbios/arch/x86/context.c b/qemu/roms/openbios/arch/x86/context.c new file mode 100644 index 000000000..d543f748a --- /dev/null +++ b/qemu/roms/openbios/arch/x86/context.c @@ -0,0 +1,130 @@ +/* tag: x86 context switching + * + * 2003-10 by SONE Takeshi + * + * See the file "COPYING" for further information about + * the copyright and warranty status of this work. + */ + +#include "config.h" +#include "kernel/kernel.h" +#include "segment.h" +#include "context.h" +#include "libopenbios/sys_info.h" +#include "boot.h" +#include "openbios.h" + +#define MAIN_STACK_SIZE 16384 +#define IMAGE_STACK_SIZE 4096 + +#define debug printk + +static void start_main(void); /* forward decl. */ +void __exit_context(void); /* assembly routine */ + +/* + * Main context structure + * It is placed at the bottom of our stack, and loaded by assembly routine + * to start us up. + */ +static struct context main_ctx __attribute__((section (".initctx"))) = { + .gdt_base = (uint32_t) gdt, + .gdt_limit = GDT_LIMIT, + .cs = FLAT_CS, + .ds = FLAT_DS, + .es = FLAT_DS, + .fs = FLAT_DS, + .gs = FLAT_DS, + .ss = FLAT_DS, + .esp = (uint32_t) ESP_LOC(&main_ctx), + .eip = (uint32_t) start_main, + .return_addr = (uint32_t) __exit_context, +}; + +/* This is used by assembly routine to load/store the context which + * it is to switch/switched. */ +struct context *__context = &main_ctx; + +/* Stack for loaded ELF image */ +static uint8_t image_stack[IMAGE_STACK_SIZE]; + +/* Pointer to startup context (physical address) */ +unsigned long __boot_ctx; + +/* + * Main starter + * This is the C function that runs first. + */ +static void start_main(void) +{ + int retval; + + /* Save startup context, so we can refer to it later. + * We have to keep it in physical address since we will relocate. */ + __boot_ctx = virt_to_phys(__context); + + init_exceptions(); + /* Start the real fun */ + retval = openbios(); + + /* Pass return value to startup context. Bootloader may see it. */ + boot_ctx->eax = retval; + + /* Returning from here should jump to __exit_context */ + __context = boot_ctx; +} + +/* Setup a new context using the given stack. + */ +struct context * +init_context(uint8_t *stack, uint32_t stack_size, int num_params) +{ + struct context *ctx; + + ctx = (struct context *) + (stack + stack_size - (sizeof(*ctx) + num_params*sizeof(uint32_t))); + memset(ctx, 0, sizeof(*ctx)); + + /* Fill in reasonable default for flat memory model */ + ctx->gdt_base = virt_to_phys(gdt); + ctx->gdt_limit = GDT_LIMIT; + ctx->cs = FLAT_CS; + ctx->ds = FLAT_DS; + ctx->es = FLAT_DS; + ctx->fs = FLAT_DS; + ctx->gs = FLAT_DS; + ctx->ss = FLAT_DS; + ctx->esp = virt_to_phys(ESP_LOC(ctx)); + ctx->return_addr = virt_to_phys(__exit_context); + + return ctx; +} + +/* Switch to another context. */ +struct context *switch_to(struct context *ctx) +{ + struct context *save, *ret; + + debug("switching to new context:\n"); + save = __context; + __context = ctx; + asm ("pushl %cs; call __switch_context"); + ret = __context; + __context = save; + return ret; +} + +/* Start ELF Boot image */ +unsigned int start_elf(unsigned long entry_point, unsigned long param) +{ + struct context *ctx; + + ctx = init_context(image_stack, sizeof image_stack, 1); + ctx->eip = entry_point; + ctx->param[0] = param; + ctx->eax = 0xe1fb007; + ctx->ebx = param; + + ctx = switch_to(ctx); + return ctx->eax; +} diff --git a/qemu/roms/openbios/arch/x86/context.h b/qemu/roms/openbios/arch/x86/context.h new file mode 100644 index 000000000..6a1c5adbc --- /dev/null +++ b/qemu/roms/openbios/arch/x86/context.h @@ -0,0 +1,48 @@ +#ifndef i386_CONTEXT_H +#define i386_CONTEXT_H + +struct context { + /* Stack Segment, placed here because of the alignment issue... */ + uint16_t ss; + /* Used with sgdt/lgdt */ + uint16_t gdt_limit; + uint32_t gdt_base; + /* General registers, accessed with pushal/popal */ + uint32_t edi; + uint32_t esi; + uint32_t ebp; + uint32_t esp; /* points just below eax */ + uint32_t ebx; + uint32_t edx; + uint32_t ecx; + uint32_t eax; +#define ESP_LOC(ctx) (&(ctx)->gs) + /* Segment registers */ + uint32_t gs; + uint32_t fs; + uint32_t es; + uint32_t ds; + /* Flags */ + uint32_t eflags; + /* Code segment:offset */ + uint32_t eip; + uint32_t cs; + /* Optional stack contents */ + uint32_t return_addr; + uint32_t param[0]; +}; + +/* Create a new context in the given stack */ +struct context * +init_context(uint8_t *stack, uint32_t stack_size, int num_param); + +/* Switch context */ +struct context *switch_to(struct context *); + +/* Holds physical address of boot context */ +extern unsigned long __boot_ctx; + +/* This can always be safely used to refer to the boot context */ +#define boot_ctx ((struct context *) phys_to_virt(__boot_ctx)) + +#endif /* i386_CONTEXT_H */ diff --git a/qemu/roms/openbios/arch/x86/defconfig b/qemu/roms/openbios/arch/x86/defconfig new file mode 100644 index 000000000..b0a02ab3c --- /dev/null +++ b/qemu/roms/openbios/arch/x86/defconfig @@ -0,0 +1,65 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_X86=y +CONFIG_LITTLE_ENDIAN=y + +# +# Kernel binaries (x86) +# +CONFIG_IMAGE_ELF=y +CONFIG_IMAGE_ELF_EMBEDDED=y +CONFIG_IMAGE_ELF_MULTIBOOT=y + +# +# Build hosted UNIX Binary +# +CONFIG_HOST_UNIX=y +# CONFIG_PLUGIN_PCI is not set + +# +# Kernel Debugging +# +# CONFIG_DEBUG is not set +CONFIG_DEBUG_CONSOLE=y +CONFIG_DEBUG_CONSOLE_SERIAL=y +CONFIG_SERIAL_PORT=1 +CONFIG_SERIAL_SPEED=115200 +CONFIG_DEBUG_CONSOLE_VGA=y + +# +# Module Configuration +# +CONFIG_CMDLINE=y +CONFIG_DEBLOCKER=y + +# +# Filesystem Configuration +# +CONFIG_DISK_LABEL=y +CONFIG_PART_SUPPORT=y +CONFIG_PC_PARTS=y +CONFIG_FS=y +CONFIG_GRUBFS=y +CONFIG_FSYS_EXT2FS=y +CONFIG_FSYS_FAT=y +CONFIG_FSYS_JFS=y +# CONFIG_FSYS_MINIX is not set +CONFIG_FSYS_REISERFS=y +CONFIG_FSYS_XFS=y +CONFIG_FSYS_ISO9660=y +# CONFIG_FSYS_FFS is not set +# CONFIG_FSYS_VSTAFS is not set +# CONFIG_DEBUG_FS is not set + +# +# Miscellaneous +# +CONFIG_LINUXBIOS=y + +# +# Drivers +# +CONFIG_DRIVER_PCI=y +CONFIG_DRIVER_IDE=y +# CONFIG_DEBUG_IDE is not set diff --git a/qemu/roms/openbios/arch/x86/entry.S b/qemu/roms/openbios/arch/x86/entry.S new file mode 100644 index 000000000..8f1e42eed --- /dev/null +++ b/qemu/roms/openbios/arch/x86/entry.S @@ -0,0 +1,315 @@ + .globl entry, __switch_context, __exit_context, halt, init_exceptions + + .text + .align 4 + +/* + * Entry point + * We start execution from here. + * It is assumed that CPU is in 32-bit protected mode and + * all segments are 4GB and base zero (flat model). + */ +entry: + /* Save boot context and switch to our main context. + * Main context is statically defined in C. + */ + pushl %cs + call __switch_context + + /* We get here when the main context switches back to + * the boot context. + * Return to previous bootloader. + */ + ret + +/* + * Switch execution context + * This saves registers, segments, and GDT in the stack, then + * switches the stack, and restores everything from the new stack. + * This function takes no argument. New stack pointer is + * taken from global variable __context, and old stack pointer + * is also saved to __context. This way we can just jump to + * this routine to get back to the original context. + * + * Call this routine with lcall or pushl %cs; call. + */ +__switch_context: + /* Save everything in current stack */ + pushfl /* 56 */ + pushl %ds /* 52 */ + pushl %es /* 48 */ + pushl %fs /* 44 */ + pushl %gs /* 40 */ + pushal /* 8 */ + subl $8, %esp + movw %ss, (%esp) /* 0 */ + sgdt 2(%esp) /* 2 */ + +#if 0 + /* Swap %cs and %eip on the stack, so lret will work */ + movl 60(%esp), %eax + xchgl %eax, 64(%esp) + movl %eax, 60(%esp) +#endif + + /* At this point we don't know if we are on flat segment + * or relocated. So compute the address offset from %eip. + * Assuming CS.base==DS.base==SS.base. + */ + call 1f +1: popl %ebx + subl $1b, %ebx + + /* Interrupts are not allowed... */ + cli + + /* Current context pointer is our stack pointer */ + movl %esp, %esi + + /* Normalize the ctx pointer */ + subl %ebx, %esi + + /* Swap it with new value */ + xchgl %esi, __context(%ebx) + + /* Adjust new ctx pointer for current address offset */ + addl %ebx, %esi + + /* Load new %ss and %esp to temporary */ + movzwl (%esi), %edx + movl 20(%esi), %eax + + /* Load new GDT */ + lgdt 2(%esi) + + /* Load new stack segment with new GDT */ + movl %edx, %ss + + /* Set new stack pointer, but we have to adjust it because + * pushal saves %esp value before pushal, and we want the value + * after pushal. + */ + leal -32(%eax), %esp + + /* Load the rest from new stack */ + popal + popl %gs + popl %fs + popl %es + popl %ds + popfl + + /* Finally, load new %cs and %eip */ + lret + +__exit_context: + /* Get back to the original context */ + pushl %cs + call __switch_context + + /* We get here if the other context attempt to switch to this + * dead context. This should not happen. */ + +halt: + cli + hlt + jmp halt + +/* + * initialize exception handler. All exceptions end up in the same + * C function. + */ + +init_exceptions: + pushl %ebx + pushl %edi + + /* Initialize the Interrupt Descriptor table */ + leal _idt, %edi + leal vec0, %ebx + movl $(0x08 << 16), %eax /* cs selector */ + +1: movw %bx, %ax + movl %ebx, %edx + movw $0x8E00, %dx /* Interrupt gate - dpl=0, present */ + movl %eax, 0(%edi) + movl %edx, 4(%edi) + addl $6, %ebx + addl $8, %edi + cmpl $_idt_end, %edi + jne 1b + + /* Load the Interrupt descriptor table */ + lidt idtarg + + movl $0, %eax + popl %edi + popl %ebx + ret + +vec0: + pushl $0 /* error code */ + pushl $0 /* vector */ + jmp int_hand +vec1: + pushl $0 /* error code */ + pushl $1 /* vector */ + jmp int_hand + +vec2: + pushl $0 /* error code */ + pushl $2 /* vector */ + jmp int_hand + +vec3: + pushl $0 /* error code */ + pushl $3 /* vector */ + jmp int_hand + +vec4: + pushl $0 /* error code */ + pushl $4 /* vector */ + jmp int_hand + +vec5: + pushl $0 /* error code */ + pushl $5 /* vector */ + jmp int_hand + +vec6: + pushl $0 /* error code */ + pushl $6 /* vector */ + jmp int_hand +vec7: + pushl $0 /* error code */ + pushl $7 /* vector */ + jmp int_hand + +vec8: + /* error code */ + pushl $8 /* vector */ + jmp int_hand + .word 0x9090 + +vec9: + pushl $0 /* error code */ + pushl $9 /* vector */ + jmp int_hand + +vec10: + /* error code */ + pushl $10 /* vector */ + jmp int_hand + .word 0x9090 + +vec11: + /* error code */ + pushl $11 /* vector */ + jmp int_hand + .word 0x9090 + +vec12: + /* error code */ + pushl $12 /* vector */ + jmp int_hand + .word 0x9090 + +vec13: + /* error code */ + pushl $13 /* vector */ + jmp int_hand + .word 0x9090 + +vec14: + /* error code */ + pushl $14 /* vector */ + jmp int_hand + .word 0x9090 + +vec15: + pushl $0 /* error code */ + pushl $15 /* vector */ + jmp int_hand + +vec16: + pushl $0 /* error code */ + pushl $16 /* vector */ + jmp int_hand + +vec17: + /* error code */ + pushl $17 /* vector */ + jmp int_hand + .word 0x9090 + +vec18: + pushl $0 /* error code */ + pushl $18 /* vector */ + jmp int_hand + +vec19: + pushl $0 /* error code */ + pushl $19 /* vector */ + jmp int_hand + +__divide_error: + pushl $0 /* error code */ + pushl $20 /* vector */ + jmp int_hand + .global __divide_error + +int_hand: + /* At this point on the stack there is: + * 0(%esp) vector + * 4(%esp) error code + * 8(%esp) eip + * 12(%esp) cs + * 16(%esp) eflags + */ + pushl %edi + pushl %esi + pushl %ebp + /* Original stack pointer */ + leal 32(%esp), %ebp + pushl %ebp + pushl %ebx + pushl %edx + pushl %ecx + pushl %eax + + pushl %esp /* Pointer to structure on the stack */ + + call x86_exception + pop %eax /* Drop the pointer */ + + popl %eax + popl %ecx + popl %edx + popl %ebx + popl %ebp /* Ignore saved %esp value */ + popl %ebp + popl %esi + popl %edi + + addl $8, %esp /* pop of the vector and error code */ + + iret + +idtarg: + .word _idt_end - _idt - 1 /* limit */ + .long _idt + .word 0 +_idt: + .fill 20, 8, 0 # idt is unitiailzed +_idt_end: + + .globl arch_nvram_size, arch_nvram_get, arch_nvram_put +arch_nvram_size: + xor %eax, %eax + ret + +arch_nvram_get: + ret + +arch_nvram_put: + ret diff --git a/qemu/roms/openbios/arch/x86/exception.c b/qemu/roms/openbios/arch/x86/exception.c new file mode 100644 index 000000000..fa07242c5 --- /dev/null +++ b/qemu/roms/openbios/arch/x86/exception.c @@ -0,0 +1,92 @@ +#include "config.h" +#include "libopenbios/bindings.h" +#include "asm/types.h" + + + +/* program counter */ +extern ucell PC; + +extern unsigned char *dict; +extern cell dicthead; +extern ucell *last; + + + +struct eregs { + uint32_t eax, ecx, edx, ebx, esp, ebp, esi, edi; + uint32_t vector; + uint32_t error_code; + uint32_t eip; + uint32_t cs; + uint32_t eflags; +}; + +static const char * const exception_names[]= { + "division by zero", + "single step", + "NMI", + "breakpoint", + "interrupt overflow", + "bound range exceeded", + "invalid opcode", + "device unavailable", + "double fault", + "FPU segment overrun", + "invalid TSS", + "segment not present", + "stack exception", + "general protection fault", + "page fault", + "reserved", + "floating point exception", + "alignment check", + "machine check exception", +}; + +void do_nothing(void); +void do_nothing(void) +{ + printk("Doing nothing\n"); +} + +void x86_exception(struct eregs *info); +void x86_exception(struct eregs *info) +{ + if(info->vector <= 18) { + printk("\nUnexpected Exception: %s", + exception_names[info->vector]); + } else { + printk("\nUnexpected Exception: %d", info->vector); + } + + printk( + " @ %02x:%08lx - Halting\n" + "Code: %d eflags: %08lx\n" + "eax: %08lx ebx: %08lx ecx: %08lx edx: %08lx\n" + "edi: %08lx esi: %08lx ebp: %08lx esp: %08lx\n", + info->cs, (unsigned long)info->eip, + info->error_code, (unsigned long)info->eflags, + (unsigned long)info->eax, (unsigned long)info->ebx, + (unsigned long)info->ecx, (unsigned long)info->edx, + (unsigned long)info->edi, (unsigned long)info->esi, + (unsigned long)info->ebp, (unsigned long)info->esp); + + printk("\ndict=0x%x here=0x%x(dict+0x%x) pc=0x%x(dict+0x%x)\n", + (ucell)dict, (ucell)dict + dicthead, dicthead, PC, PC - (ucell) dict); + printk("dstackcnt=%d rstackcnt=%d\n", + dstackcnt, rstackcnt); + + rstackcnt=0; + dstackcnt=0; + + PC=findword("outer-interpreter"); + + info->eip=(uint32_t)&do_nothing; + +/* + for (;;) + asm("hlt;"); + ; +*/ +} diff --git a/qemu/roms/openbios/arch/x86/init.fs b/qemu/roms/openbios/arch/x86/init.fs new file mode 100644 index 000000000..eef72e9b2 --- /dev/null +++ b/qemu/roms/openbios/arch/x86/init.fs @@ -0,0 +1,84 @@ +include config.fs + +:noname + ." Type 'help' for detailed information" cr + \ ." boot secondary slave cdrom: " cr + \ ." 0 > boot hd:2,\boot\vmlinuz root=/dev/hda2" cr + ; DIAG-initializer + +" /" find-device + +new-device + " memory" device-name + \ 12230 encode-int " reg" property + external + : open true ; + : close ; + \ claim ( phys size align -- base ) + \ release ( phys size -- ) +finish-device + +new-device + " cpus" device-name + 1 " #address-cells" int-property + 0 " #size-cells" int-property + + external + : open true ; + : close ; + : decode-unit parse-hex ; + +finish-device + +: make-openable ( path ) + find-dev if + begin ?dup while + \ install trivial open and close methods + dup active-package! is-open + parent + repeat + then +; + +: preopen ( chosen-str node-path ) + 2dup make-openable + + " /chosen" find-device + open-dev ?dup if + encode-int 2swap property + else + 2drop + then + device-end +; + +:noname + set-defaults +; SYSTEM-initializer + +\ preopen device nodes (and store the ihandles under /chosen) +:noname + " memory" " /memory" preopen + " mmu" " /cpus/@0" preopen + " stdout" " /builtin/console" preopen + " stdin" " /builtin/console" preopen + +; SYSTEM-initializer + +\ use the tty interface if available +:noname + " /builtin/console" find-dev if drop + " /builtin/console" " input-device" $setenv + " /builtin/console" " output-device" $setenv + then +; SYSTEM-initializer + +:noname + " keyboard" input +; CONSOLE-IN-initializer + +\ Load VGA FCode driver blob +[IFDEF] CONFIG_DRIVER_VGA + -1 value vga-driver-fcode + " QEMU,VGA.bin" $encode-file to vga-driver-fcode +[THEN] diff --git a/qemu/roms/openbios/arch/x86/ldscript b/qemu/roms/openbios/arch/x86/ldscript new file mode 100644 index 000000000..8976c7af0 --- /dev/null +++ b/qemu/roms/openbios/arch/x86/ldscript @@ -0,0 +1,73 @@ +OUTPUT_FORMAT(elf32-i386) +OUTPUT_ARCH(i386) + +ENTRY(entry) + +/* Initial load address + * To be loaded by GRUB, this must be >= 1MB + */ +BASE_ADDR = 0x100000; + +/* 16KB heap and stack */ +HEAP_SIZE = 16384; +STACK_SIZE = 16384; + +SECTIONS +{ + . = BASE_ADDR; + + /* Put Multiboot header near beginning of file, if any. */ + .hdr : { *(.hdr) *(.hdr.*) } + + /* Start of the program. + * Now the version string is in the note, we must include it + * in the program. Otherwise we lose the string after relocation. */ + . = ALIGN(16); + _start = .; + + /* Putting ELF notes near beginning of file might help bootloaders. + * We discard .note sections other than .note.ELFBoot, + * because some versions of GCC generates useless ones. */ + .note : { *(.note.ELFBoot) } + + /* Normal sections */ + .text : { *(.text) *(.text.*) } + .rodata : { + . = ALIGN(4); + sound_drivers_start = .; + *(.rodata.sound_drivers) + sound_drivers_end = .; + *(.rodata) + *(.rodata.*) + } + .data : { *(.data) *(.data.*) } + + .bss : { + *(.bss) + *(.bss.*) + *(COMMON) + + /* Put heap and stack here, so they are included in PT_LOAD segment + * and the bootloader is aware of it. */ + + . = ALIGN(16); + _heap = .; + . += HEAP_SIZE; + . = ALIGN(16); + _eheap = .; + + _stack = .; + . += STACK_SIZE; + . = ALIGN(16); + _estack = .; + } + + .initctx : { + /* Initial contents of stack. This MUST BE just after the stack. */ + *(.initctx) + } + + _end = .; + + /DISCARD/ : { *(.comment) *(.note) } +} diff --git a/qemu/roms/openbios/arch/x86/lib.c b/qemu/roms/openbios/arch/x86/lib.c new file mode 100644 index 000000000..eeb901b4a --- /dev/null +++ b/qemu/roms/openbios/arch/x86/lib.c @@ -0,0 +1,56 @@ +/* lib.c + * tag: simple function library + * + * Copyright (C) 2003 Stefan Reinauer + * + * See the file "COPYING" for further information about + * the copyright and warranty status of this work. + */ + +#include "config.h" +#include "asm/types.h" +#include <stdarg.h> +#include "libc/stdlib.h" +#include "libc/vsprintf.h" +#include "kernel/kernel.h" + +/* Format a string and print it on the screen, just like the libc + * function printf. + */ +int printk( const char *fmt, ... ) +{ + char *p, buf[512]; + va_list args; + int i; + + va_start(args, fmt); + i = vsnprintf(buf, sizeof(buf), fmt, args); + va_end(args); + + for( p=buf; *p; p++ ) + putchar(*p); + return i; +} + +// dumb quick memory allocator until we get a decent thing here. + +#define MEMSIZE 128*1024 +static char memory[MEMSIZE]; +static void *memptr=memory; +static int memsize=MEMSIZE; + +void *malloc(int size) +{ + void *ret=(void *)0; + if(memsize>=size) { + memsize-=size; + ret=memptr; + memptr = (void *)((unsigned long)memptr + size); + } + return ret; +} + +void free(void *ptr) +{ + /* Nothing yet */ +} diff --git a/qemu/roms/openbios/arch/x86/linux_load.c b/qemu/roms/openbios/arch/x86/linux_load.c new file mode 100644 index 000000000..e06326b09 --- /dev/null +++ b/qemu/roms/openbios/arch/x86/linux_load.c @@ -0,0 +1,671 @@ +/* + * Linux/i386 loader + * Supports bzImage, zImage and Image format. + * + * Based on work by Steve Gehlbach. + * Portions are taken from mkelfImage. + * + * 2003-09 by SONE Takeshi + */ + +#include "config.h" +#include "kernel/kernel.h" +#include "libopenbios/bindings.h" +#include "libopenbios/sys_info.h" +#include "context.h" +#include "segment.h" +#include "libc/diskio.h" +#include "boot.h" + +#define printf printk +#define debug printk +#define strtoull_with_suffix strtol + +#define LINUX_PARAM_LOC 0x90000 +#define COMMAND_LINE_LOC 0x91000 +#define GDT_LOC 0x92000 +#define STACK_LOC 0x93000 + +#define E820MAX 32 /* number of entries in E820MAP */ +struct e820entry { + unsigned long long addr; /* start of memory segment */ + unsigned long long size; /* size of memory segment */ + unsigned long type; /* type of memory segment */ +#define E820_RAM 1 +#define E820_RESERVED 2 +#define E820_ACPI 3 /* usable as RAM once ACPI tables have been read */ +#define E820_NVS 4 +}; + +/* The header of Linux/i386 kernel */ +struct linux_header { + uint8_t reserved1[0x1f1]; /* 0x000 */ + uint8_t setup_sects; /* 0x1f1 */ + uint16_t root_flags; /* 0x1f2 */ + uint8_t reserved2[6]; /* 0x1f4 */ + uint16_t vid_mode; /* 0x1fa */ + uint16_t root_dev; /* 0x1fc */ + uint16_t boot_sector_magic; /* 0x1fe */ + /* 2.00+ */ + uint8_t reserved3[2]; /* 0x200 */ + uint8_t header_magic[4]; /* 0x202 */ + uint16_t protocol_version; /* 0x206 */ + uint32_t realmode_swtch; /* 0x208 */ + uint16_t start_sys; /* 0x20c */ + uint16_t kver_addr; /* 0x20e */ + uint8_t type_of_loader; /* 0x210 */ + uint8_t loadflags; /* 0x211 */ + uint16_t setup_move_size; /* 0x212 */ + uint32_t code32_start; /* 0x214 */ + uint32_t ramdisk_image; /* 0x218 */ + uint32_t ramdisk_size; /* 0x21c */ + uint8_t reserved4[4]; /* 0x220 */ + /* 2.01+ */ + uint16_t heap_end_ptr; /* 0x224 */ + uint8_t reserved5[2]; /* 0x226 */ + /* 2.02+ */ + uint32_t cmd_line_ptr; /* 0x228 */ + /* 2.03+ */ + uint32_t initrd_addr_max; /* 0x22c */ +} __attribute__ ((packed)); + + +/* Paramters passed to 32-bit part of Linux + * This is another view of the structure above.. */ +struct linux_params { + uint8_t orig_x; /* 0x00 */ + uint8_t orig_y; /* 0x01 */ + uint16_t ext_mem_k; /* 0x02 -- EXT_MEM_K sits here */ + uint16_t orig_video_page; /* 0x04 */ + uint8_t orig_video_mode; /* 0x06 */ + uint8_t orig_video_cols; /* 0x07 */ + uint16_t unused2; /* 0x08 */ + uint16_t orig_video_ega_bx; /* 0x0a */ + uint16_t unused3; /* 0x0c */ + uint8_t orig_video_lines; /* 0x0e */ + uint8_t orig_video_isVGA; /* 0x0f */ + uint16_t orig_video_points; /* 0x10 */ + + /* VESA graphic mode -- linear frame buffer */ + uint16_t lfb_width; /* 0x12 */ + uint16_t lfb_height; /* 0x14 */ + uint16_t lfb_depth; /* 0x16 */ + uint32_t lfb_base; /* 0x18 */ + uint32_t lfb_size; /* 0x1c */ + uint16_t cl_magic; /* 0x20 */ +#define CL_MAGIC_VALUE 0xA33F + uint16_t cl_offset; /* 0x22 */ + uint16_t lfb_linelength; /* 0x24 */ + uint8_t red_size; /* 0x26 */ + uint8_t red_pos; /* 0x27 */ + uint8_t green_size; /* 0x28 */ + uint8_t green_pos; /* 0x29 */ + uint8_t blue_size; /* 0x2a */ + uint8_t blue_pos; /* 0x2b */ + uint8_t rsvd_size; /* 0x2c */ + uint8_t rsvd_pos; /* 0x2d */ + uint16_t vesapm_seg; /* 0x2e */ + uint16_t vesapm_off; /* 0x30 */ + uint16_t pages; /* 0x32 */ + uint8_t reserved4[12]; /* 0x34 -- 0x3f reserved for future expansion */ + + //struct apm_bios_info apm_bios_info; /* 0x40 */ + uint8_t apm_bios_info[0x40]; + //struct drive_info_struct drive_info; /* 0x80 */ + uint8_t drive_info[0x20]; + //struct sys_desc_table sys_desc_table; /* 0xa0 */ + uint8_t sys_desc_table[0x140]; + uint32_t alt_mem_k; /* 0x1e0 */ + uint8_t reserved5[4]; /* 0x1e4 */ + uint8_t e820_map_nr; /* 0x1e8 */ + uint8_t reserved6[9]; /* 0x1e9 */ + uint16_t mount_root_rdonly; /* 0x1f2 */ + uint8_t reserved7[4]; /* 0x1f4 */ + uint16_t ramdisk_flags; /* 0x1f8 */ +#define RAMDISK_IMAGE_START_MASK 0x07FF +#define RAMDISK_PROMPT_FLAG 0x8000 +#define RAMDISK_LOAD_FLAG 0x4000 + uint8_t reserved8[2]; /* 0x1fa */ + uint16_t orig_root_dev; /* 0x1fc */ + uint8_t reserved9[1]; /* 0x1fe */ + uint8_t aux_device_info; /* 0x1ff */ + uint8_t reserved10[2]; /* 0x200 */ + uint8_t param_block_signature[4]; /* 0x202 */ + uint16_t param_block_version; /* 0x206 */ + uint8_t reserved11[8]; /* 0x208 */ + uint8_t loader_type; /* 0x210 */ +#define LOADER_TYPE_LOADLIN 1 +#define LOADER_TYPE_BOOTSECT_LOADER 2 +#define LOADER_TYPE_SYSLINUX 3 +#define LOADER_TYPE_ETHERBOOT 4 +#define LOADER_TYPE_KERNEL 5 + uint8_t loader_flags; /* 0x211 */ + uint8_t reserved12[2]; /* 0x212 */ + uint32_t kernel_start; /* 0x214 */ + uint32_t initrd_start; /* 0x218 */ + uint32_t initrd_size; /* 0x21c */ + uint8_t reserved12_5[8]; /* 0x220 */ + uint32_t cmd_line_ptr; /* 0x228 */ + uint8_t reserved13[164]; /* 0x22c */ + struct e820entry e820_map[E820MAX]; /* 0x2d0 */ + uint8_t reserved16[688]; /* 0x550 */ +#define COMMAND_LINE_SIZE 256 + /* Command line is copied here by 32-bit i386/kernel/head.S. + * So I will follow the boot protocol, rather than putting it + * directly here. --ts1 */ + uint8_t command_line[COMMAND_LINE_SIZE]; /* 0x800 */ + uint8_t reserved17[1792]; /* 0x900 - 0x1000 */ +}; + +static uint64_t forced_memsize; +static int fd; + +static unsigned long file_size(void) +{ + long long fpos, fsize; + + /* Save current position */ + fpos = tell(fd); + + /* Go to end of file and get position */ + seek_io(fd, -1); + fsize = tell(fd); + + /* Go back to old position */ + seek_io(fd, 0); + seek_io(fd, fpos); + + return fsize; +} + +/* Load the first part the file and check if it's Linux */ +static uint32_t load_linux_header(struct linux_header *hdr) +{ + int load_high; + uint32_t kern_addr; + + if (read_io(fd, hdr, sizeof *hdr) != sizeof *hdr) { + debug("Can't read Linux header\n"); + return 0; + } + if (hdr->boot_sector_magic != 0xaa55) { + debug("Not a Linux kernel image\n"); + return 0; + } + + /* Linux is found. Print some information */ + if (memcmp(hdr->header_magic, "HdrS", 4) != 0) { + /* This may be floppy disk image or something. + * Perform a simple (incomplete) sanity check. */ + if (hdr->setup_sects >= 16 + || file_size() - (hdr->setup_sects<<9) >= 512<<10) { + debug("This looks like a bootdisk image but not like Linux...\n"); + return 0; + } + + printf("Possible very old Linux"); + /* This kernel does not even have a protocol version. + * Force the value. */ + hdr->protocol_version = 0; /* pre-2.00 */ + } else + printf("Found Linux"); + if (hdr->protocol_version >= 0x200 && hdr->kver_addr) { + char kver[256]; + seek_io(fd, hdr->kver_addr + 0x200); + if (read_io(fd, kver, sizeof kver) != 0) { + kver[255] = 0; + printf(" version %s", kver); + } + } + debug(" (protocol %#x)", hdr->protocol_version); + load_high = 0; + if (hdr->protocol_version >= 0x200) { + debug(" (loadflags %#x)", hdr->loadflags); + load_high = hdr->loadflags & 1; + } + if (load_high) { + printf(" bzImage"); + kern_addr = 0x100000; + } else { + printf(" zImage or Image"); + kern_addr = 0x1000; + } + printf(".\n"); + + return kern_addr; +} + +/* Set up parameters for 32-bit kernel */ +static void +init_linux_params(struct linux_params *params, struct linux_header *hdr) +{ + debug("Setting up paramters at %#lx\n", virt_to_phys(params)); + memset(params, 0, sizeof *params); + + /* Copy some useful values from header */ + params->mount_root_rdonly = hdr->root_flags; + params->orig_root_dev = hdr->root_dev; + + /* Video parameters. + * This assumes we have VGA in standard 80x25 text mode, + * just like our vga.c does. + * Cursor position is filled later to allow some more printf's. */ + params->orig_video_mode = 3; + params->orig_video_cols = 80; + params->orig_video_lines = 25; + params->orig_video_isVGA = 1; + params->orig_video_points = 16; + + params->loader_type = 0xff; /* Unregistered Linux loader */ +} + +/* Memory map */ +static void +set_memory_size(struct linux_params *params, struct sys_info *info) +{ + int i; + uint64_t end; + uint32_t ramtop = 0; + struct e820entry *linux_map; + struct memrange *filo_map; + + linux_map = params->e820_map; + filo_map = info->memrange; + for (i = 0; i < info->n_memranges; i++, linux_map++, filo_map++) { + if (i < E820MAX) { + /* Convert to BIOS e820 style */ + linux_map->addr = filo_map->base; + linux_map->size = filo_map->size; + linux_map->type = E820_RAM; + debug("%016Lx - %016Lx\n", linux_map->addr, + linux_map->addr + linux_map->size); + params->e820_map_nr = i+1; + } + + /* Find out top of RAM. XXX This ignores hole above 1MB */ + end = filo_map->base + filo_map->size; + if (end < (1ULL << 32)) { /* don't count memory above 4GB */ + if (end > ramtop) + ramtop = (uint32_t) end; + } + } + debug("ramtop=%#x\n", ramtop); + /* Size of memory above 1MB in KB */ + params->alt_mem_k = (ramtop - (1<<20)) >> 10; + /* old style, 64MB max */ + if (ramtop >= (64<<20)) + params->ext_mem_k = (63<<10); + else + params->ext_mem_k = params->alt_mem_k; + debug("ext_mem_k=%d, alt_mem_k=%d\n", params->ext_mem_k, params->alt_mem_k); +} + +/* + * Parse command line + * Some parameters, like initrd=<file>, are not passed to kernel, + * we are responsible to process them. + * Parameters for kernel are copied to kern_cmdline. Returns name of initrd. + */ +static char *parse_command_line(const char *orig_cmdline, char *kern_cmdline) +{ + const char *start, *sep, *end, *val; + char name[64]; + int len; + int k_len; + int to_kern; + char *initrd = NULL; + int toolong = 0; + + forced_memsize = 0; + + if (!orig_cmdline) { + *kern_cmdline = 0; + return NULL; + } + + k_len = 0; + debug("original command line: \"%s\"\n", orig_cmdline); + debug("kernel command line at %#lx\n", virt_to_phys(kern_cmdline)); + + start = orig_cmdline; + while (*start == ' ') + start++; + while (*start) { + end = strchr(start, ' '); + if (!end) + end = start + strlen(start); + sep = strchr(start, '='); + if (!sep || sep > end) + sep = end; + len = sep - start; + if (len >= sizeof(name)) + len = sizeof(name) - 1; + memcpy(name, start, len); + name[len] = 0; + + if (*sep == '=') { + val = sep + 1; + len = end - val; + } else { + val = NULL; + len = 0; + } + + /* Only initrd= and mem= are handled here. vga= is not, + * which I believe is a paramter to the realmode part of Linux, + * which we don't execute. */ + if (strcmp(name, "initrd") == 0) { + if (!val) + printf("Missing filename to initrd parameter\n"); + else { + initrd = malloc(len + 1); + memcpy(initrd, val, len); + initrd[len] = 0; + debug("initrd=%s\n", initrd); + } + /* Don't pass this to kernel */ + to_kern = 0; + } else if (strcmp(name, "mem") == 0) { + if (!val) + printf("Missing value for mem parameter\n"); + else { + forced_memsize = strtoull_with_suffix(val, (char**)&val, 0); + if (forced_memsize == 0) + printf("Invalid mem option, ignored\n"); + if (val != end) { + printf("Garbage after mem=<size>, ignored\n"); + forced_memsize = 0; + } + debug("mem=%Lu\n", forced_memsize); + } + /* mem= is for both loader and kernel */ + to_kern = 1; + } else + to_kern = 1; + + if (to_kern) { + /* Copy to kernel command line buffer */ + if (k_len != 0) + kern_cmdline[k_len++] = ' '; /* put separator */ + len = end - start; + if (k_len + len >= COMMAND_LINE_SIZE) { + len = COMMAND_LINE_SIZE - k_len - 1; + if (!toolong) { + printf("Kernel command line is too long; truncated to " + "%d bytes\n", COMMAND_LINE_SIZE-1); + toolong = 1; + } + } + memcpy(kern_cmdline + k_len, start, len); + k_len += len; + } + + start = end; + while (*start == ' ') + start++; + } + kern_cmdline[k_len] = 0; + debug("kernel command line (%d bytes): \"%s\"\n", k_len, kern_cmdline); + + return initrd; +} + +/* Set command line location */ +static void set_command_line_loc(struct linux_params *params, + struct linux_header *hdr) +{ + if (hdr->protocol_version >= 0x202) { + /* new style */ + params->cmd_line_ptr = COMMAND_LINE_LOC; + } else { + /* old style */ + params->cl_magic = CL_MAGIC_VALUE; + params->cl_offset = COMMAND_LINE_LOC - LINUX_PARAM_LOC; + } +} + +/* Load 32-bit part of kernel */ +static int load_linux_kernel(struct linux_header *hdr, uint32_t kern_addr) +{ + uint32_t kern_offset, kern_size; + + if (hdr->setup_sects == 0) + hdr->setup_sects = 4; + kern_offset = (hdr->setup_sects + 1) * 512; + seek_io(fd, kern_offset); + kern_size = file_size() - kern_offset; + debug("offset=%#x addr=%#x size=%#x\n", kern_offset, kern_addr, kern_size); + +#if 0 + if (using_devsize) { + printf("Attempt to load up to end of device as kernel; " + "specify the image size\n"); + return 0; + } +#endif + + printf("Loading kernel... "); + if (read_io(fd, phys_to_virt(kern_addr), kern_size) != kern_size) { + printf("Can't read kernel\n"); + return 0; + } + printf("ok\n"); + + return kern_size; +} + +static int load_initrd(struct linux_header *hdr, struct sys_info *info, + uint32_t kern_end, struct linux_params *params, const char *initrd_file) +{ + uint32_t max; + uint32_t start, end, size; + uint64_t forced; + + fd = open_io(initrd_file); + if (fd == -1) { + printf("Can't open initrd: %s\n", initrd_file); + return -1; + } + +#if 0 + if (using_devsize) { + printf("Attempt to load up to end of device as initrd; " + "specify the image size\n"); + return -1; + } +#endif + + size = file_size(); + + + /* Find out the kernel's restriction on how high the initrd can be + * placed */ + if (hdr->protocol_version >= 0x203) + max = hdr->initrd_addr_max; + else + max = 0x38000000; /* Hardcoded value for older kernels */ + + /* FILO itself is at the top of RAM. (relocated) + * So, try putting initrd just below us. */ + end = virt_to_phys(_start); + if (end > max) + end = max; + + /* If "mem=" option is given, we have to put the initrd within + * the specified range. */ + if (forced_memsize) { + forced = forced_memsize; + if (forced > max) + forced = max; + /* If the "mem=" is lower, it's easy */ + if (forced <= end) + end = forced; + else { + /* Otherwise, see if we can put it above us */ + if (virt_to_phys(_end) + size <= forced) + end = forced; /* Ok */ + } + } + + start = end - size; + start &= ~0xfff; /* page align */ + end = start + size; + + debug("start=%#x end=%#x\n", start, end); + + if (start < kern_end) { + printf("Initrd is too big to fit in memory\n"); + return -1; + } + + printf("Loading initrd... "); + if (read_io(fd, phys_to_virt(start), size) != size) { + printf("Can't read initrd\n"); + return -1; + } + printf("ok\n"); + + params->initrd_start = start; + params->initrd_size = size; + + close_io(fd); + + return 0; +} + +static void hardware_setup(void) +{ + /* Disable nmi */ + outb(0x80, 0x70); + + /* Make sure any coprocessor is properly reset.. */ + outb(0, 0xf0); + outb(0, 0xf1); + + /* we're getting screwed again and again by this problem of the 8259. + * so we're going to leave this lying around for inclusion into + * crt0.S on an as-needed basis. + * + * well, that went ok, I hope. Now we have to reprogram the interrupts :-( + * we put them right after the intel-reserved hardware interrupts, at + * int 0x20-0x2F. There they won't mess up anything. Sadly IBM really + * messed this up with the original PC, and they haven't been able to + * rectify it afterwards. Thus the bios puts interrupts at 0x08-0x0f, + * which is used for the internal hardware interrupts as well. We just + * have to reprogram the 8259's, and it isn't fun. + */ + + outb(0x11, 0x20); /* initialization sequence to 8259A-1 */ + outb(0x11, 0xA0); /* and to 8259A-2 */ + + outb(0x20, 0x21); /* start of hardware int's (0x20) */ + outb(0x28, 0xA1); /* start of hardware int's 2 (0x28) */ + + outb(0x04, 0x21); /* 8259-1 is master */ + outb(0x02, 0xA1); /* 8259-2 is slave */ + + outb(0x01, 0x21); /* 8086 mode for both */ + outb(0x01, 0xA1); + + outb(0xFF, 0xA1); /* mask off all interrupts for now */ + outb(0xFB, 0x21); /* mask all irq's but irq2 which is cascaded */ +} + +/* Start Linux */ +static int start_linux(uint32_t kern_addr, struct linux_params *params) +{ + struct segment_desc *linux_gdt; + struct context *ctx; + //extern int cursor_x, cursor_y; + + ctx = init_context(phys_to_virt(STACK_LOC), 4096, 0); + + /* Linux expects GDT being in low memory */ + linux_gdt = phys_to_virt(GDT_LOC); + memset(linux_gdt, 0, 13*sizeof(struct segment_desc)); + /* Normal kernel code/data segments */ + linux_gdt[2] = gdt[FLAT_CODE]; + linux_gdt[3] = gdt[FLAT_DATA]; + /* 2.6 kernel uses 12 and 13, but head.S uses backward-compatible + * segments (2 and 3), so it SHOULD not be a problem. + * However, some distro kernels (eg. RH9) with backported threading + * patch use 12 and 13 also when booting... */ + linux_gdt[12] = gdt[FLAT_CODE]; + linux_gdt[13] = gdt[FLAT_DATA]; + ctx->gdt_base = GDT_LOC; + ctx->gdt_limit = 14*8-1; + ctx->cs = 0x10; + ctx->ds = 0x18; + ctx->es = 0x18; + ctx->fs = 0x18; + ctx->gs = 0x18; + ctx->ss = 0x18; + + /* Parameter location */ + ctx->esi = virt_to_phys(params); + + /* Entry point */ + ctx->eip = kern_addr; + + debug("eip=%#x\n", kern_addr); + printf("Jumping to entry point...\n"); + +#ifdef VGA_CONSOLE + /* Update VGA cursor position. + * This must be here because the printf changes the value! */ + params->orig_x = cursor_x; + params->orig_y = cursor_y; +#endif + + /* Go... */ + ctx = switch_to(ctx); + + /* It's impossible but... */ + printf("Returned with eax=%#x\n", ctx->eax); + + return ctx->eax; +} + +int linux_load(struct sys_info *info, const char *file, const char *cmdline) +{ + struct linux_header hdr; + struct linux_params *params; + uint32_t kern_addr, kern_size; + char *initrd_file = NULL; + + fd = open_io(file); + if (fd == -1) { + return -1; + } + + kern_addr = load_linux_header(&hdr); + if (kern_addr == 0) + return LOADER_NOT_SUPPORT; + + params = phys_to_virt(LINUX_PARAM_LOC); + init_linux_params(params, &hdr); + set_memory_size(params, info); + initrd_file = parse_command_line(cmdline, phys_to_virt(COMMAND_LINE_LOC)); + set_command_line_loc(params, &hdr); + + kern_size = load_linux_kernel(&hdr, kern_addr); + if (kern_size == 0) { + if (initrd_file) + free(initrd_file); + return -1; + } + + if (initrd_file) { + if (load_initrd(&hdr, info, kern_addr+kern_size, params, initrd_file) + != 0) { + free(initrd_file); + return -1; + } + free(initrd_file); + } + + hardware_setup(); + + start_linux(kern_addr, params); + return 0; +} diff --git a/qemu/roms/openbios/arch/x86/multiboot.c b/qemu/roms/openbios/arch/x86/multiboot.c new file mode 100644 index 000000000..6f6b23dce --- /dev/null +++ b/qemu/roms/openbios/arch/x86/multiboot.c @@ -0,0 +1,127 @@ +/* Support for Multiboot */ + +#include "config.h" +#include "asm/io.h" +#include "libopenbios/sys_info.h" +#include "multiboot.h" + +#ifdef CONFIG_DEBUG_BOOT +#define debug printk +#else +#define debug(x...) +#endif + +struct mbheader { + unsigned int magic, flags, checksum; +}; + +static const struct mbheader multiboot_header + __attribute__((section (".hdr"))) = +{ + MULTIBOOT_HEADER_MAGIC, + MULTIBOOT_HEADER_FLAGS, + -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS) +}; + +/* Multiboot information structure, provided by loader to us */ + +struct multiboot_mmap { + unsigned entry_size; + unsigned base_lo, base_hi; + unsigned size_lo, size_hi; + unsigned type; +}; + +#define MULTIBOOT_MEM_VALID 0x01 +#define MULTIBOOT_BOOT_DEV_VALID 0x02 +#define MULTIBOOT_CMDLINE_VALID 0x04 +#define MULTIBOOT_MODS_VALID 0x08 +#define MULTIBOOT_AOUT_SYMS_VALID 0x10 +#define MULTIBOOT_ELF_SYMS_VALID 0x20 +#define MULTIBOOT_MMAP_VALID 0x40 + +void collect_multiboot_info(struct sys_info *info); +void collect_multiboot_info(struct sys_info *info) +{ + struct multiboot_info *mbinfo; + struct multiboot_mmap *mbmem; + unsigned mbcount, mbaddr; + int i; + struct memrange *mmap; + int mmap_count; + module_t *mod; + + if (info->boot_type != 0x2BADB002) + return; + + debug("Using Multiboot information at %#lx\n", info->boot_data); + + mbinfo = phys_to_virt(info->boot_data); + + if (mbinfo->mods_count != 1) { + printk("multiboot: no dictionary\n"); + return; + } + + mod = (module_t *) mbinfo->mods_addr; + info->dict_start=(unsigned long *)mod->mod_start; + info->dict_end=(unsigned long *)mod->mod_end; + debug("multiboot: dictionary at %p-%p\n", + info->dict_start, info->dict_end); + + if (mbinfo->flags & MULTIBOOT_MMAP_VALID) { + /* convert mmap records */ + mbmem = phys_to_virt(mbinfo->mmap_addr); + mbcount = mbinfo->mmap_length / (mbmem->entry_size + 4); + mmap = malloc(mbcount * sizeof(struct memrange)); + mmap_count = 0; + mbaddr = mbinfo->mmap_addr; + for (i = 0; i < mbcount; i++) { + mbmem = phys_to_virt(mbaddr); + debug("%08x%08x %08x%08x (%d)\n", + mbmem->base_hi, + mbmem->base_lo, + mbmem->size_hi, + mbmem->size_lo, + mbmem->type); + if (mbmem->type == 1) { /* Only normal RAM */ + mmap[mmap_count].base = mbmem->base_lo + + (((unsigned long long) mbmem->base_hi) << 32); + mmap[mmap_count].size = mbmem->size_lo + + (((unsigned long long) mbmem->size_hi) << 32); + mmap_count++; + } + mbaddr += mbmem->entry_size + 4; + if (mbaddr >= mbinfo->mmap_addr + mbinfo->mmap_length) + break; + } + /* simple sanity check - there should be at least 2 RAM segments + * (base 640k and extended) */ + if (mmap_count >= 2) + goto got_it; + + printk("Multiboot mmap is broken\n"); + free(mmap); + /* fall back to mem_lower/mem_upper */ + } + + if (mbinfo->flags & MULTIBOOT_MEM_VALID) { + /* use mem_lower and mem_upper */ + mmap_count = 2; + mmap = malloc(2 * sizeof(*mmap)); + mmap[0].base = 0; + mmap[0].size = mbinfo->mem_lower << 10; + mmap[1].base = 1 << 20; /* 1MB */ + mmap[1].size = mbinfo->mem_upper << 10; + goto got_it; + } + + printk("Can't get memory information from Multiboot\n"); + return; + +got_it: + info->memrange = mmap; + info->n_memranges = mmap_count; + + return; +} diff --git a/qemu/roms/openbios/arch/x86/multiboot.h b/qemu/roms/openbios/arch/x86/multiboot.h new file mode 100644 index 000000000..fd0fe9739 --- /dev/null +++ b/qemu/roms/openbios/arch/x86/multiboot.h @@ -0,0 +1,96 @@ +/* multiboot.h + * tag: header for multiboot + * + * Copyright (C) 2003 Stefan Reinauer + * + * See the file "COPYING" for further information about + * the copyright and warranty status of this work. + */ + +/* magic number for multiboot header */ +#define MULTIBOOT_HEADER_MAGIC 0x1BADB002 + +/* flags for multiboot header */ +#define MULTIBOOT_HEADER_FLAGS 0x00010003 + +/* magic number passed by multiboot-compliant boot loader. */ +#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002 + +/* The size of our stack (8KB). */ +#define STACK_SIZE 0x2000 + +/* C symbol format. HAVE_ASM_USCORE is defined by configure. */ +#ifdef HAVE_ASM_USCORE +# define EXT_C(sym) _ ## sym +#else +# define EXT_C(sym) sym +#endif + +#ifndef ASM +/* We don't want these declarations in boot.S */ + +/* multiboot header */ +typedef struct multiboot_header { + unsigned long magic; + unsigned long flags; + unsigned long checksum; + unsigned long header_addr; + unsigned long load_addr; + unsigned long load_end_addr; + unsigned long bss_end_addr; + unsigned long entry_addr; +} multiboot_header_t; + +/* symbol table for a.out */ +typedef struct aout_symbol_table { + unsigned long tabsize; + unsigned long strsize; + unsigned long addr; + unsigned long reserved; +} aout_symbol_table_t; + +/* section header table for ELF */ +typedef struct elf_section_header_table { + unsigned long num; + unsigned long size; + unsigned long addr; + unsigned long shndx; +} elf_section_header_table_t; + +/* multiboot information */ +typedef struct multiboot_info { + unsigned long flags; + unsigned long mem_lower; + unsigned long mem_upper; + unsigned long boot_device; + unsigned long cmdline; + unsigned long mods_count; + unsigned long mods_addr; + union { + aout_symbol_table_t aout_sym; + elf_section_header_table_t elf_sec; + } u; + unsigned long mmap_length; + unsigned long mmap_addr; +} multiboot_info_t; + +/* module structure */ +typedef struct module { + unsigned long mod_start; + unsigned long mod_end; + unsigned long string; + unsigned long reserved; +} module_t; + +/* memory map. Be careful that the offset 0 is base_addr_low + but no size. */ +typedef struct memory_map { + unsigned long size; + unsigned long base_addr_low; + unsigned long base_addr_high; + unsigned long length_low; + unsigned long length_high; + unsigned long type; +} memory_map_t; + +#endif /* ! ASM */ diff --git a/qemu/roms/openbios/arch/x86/openbios.c b/qemu/roms/openbios/arch/x86/openbios.c new file mode 100644 index 000000000..6145436f4 --- /dev/null +++ b/qemu/roms/openbios/arch/x86/openbios.c @@ -0,0 +1,134 @@ +/* tag: openbios forth environment, executable code + * + * Copyright (C) 2003 Patrick Mauritz, Stefan Reinauer + * + * See the file "COPYING" for further information about + * the copyright and warranty status of this work. + */ + +#include "config.h" +#include "libopenbios/openbios.h" +#include "libopenbios/bindings.h" +#include "libopenbios/console.h" +#include "asm/types.h" +#include "dict.h" +#include "kernel/kernel.h" +#include "kernel/stack.h" +#include "drivers/drivers.h" +#include "drivers/pci.h" +#include "libopenbios/sys_info.h" +#include "libopenbios/video.h" +#include "openbios.h" +#include "relocate.h" +#include "boot.h" + +void collect_sys_info(struct sys_info *info); + +#ifdef CONFIG_DRIVER_PCI +static const pci_arch_t default_pci_host = { + .name = "Intel,i440FX", + .vendor_id = PCI_VENDOR_ID_INTEL, + .device_id = PCI_DEVICE_ID_INTEL_82441, + .io_base = 0x1000, +}; +#endif + +static void init_memory(void) +{ + /* push start and end of available memory to the stack + * so that the forth word QUIT can initialize memory + * management. For now we use hardcoded memory between + * 0x10000 and 0x9ffff (576k). If we need more memory + * than that we have serious bloat. + */ + + PUSH(0x10000); + PUSH(0x9FFFF); +} + +static void +arch_init( void ) +{ + openbios_init(); + modules_init(); +#ifdef CONFIG_DRIVER_PCI + arch = &default_pci_host; + ob_pci_init(); +#endif +#ifdef CONFIG_DRIVER_IDE + setup_timers(); + ob_ide_init("/pci/isa", 0x1f0, 0x3f6, 0x170, 0x376); +#endif +#ifdef CONFIG_DRIVER_FLOPPY + ob_floppy_init("/isa", "floppy0", 0x3f0, 0); +#endif +#ifdef CONFIG_XBOX + setup_video(); + + /* Force video to 32-bit depth */ + VIDEO_DICT_VALUE(video.depth) = 32; + + init_video(); + node_methods_init(); +#endif + device_end(); + bind_func("platform-boot", boot ); + bind_func("(go)", go ); +} + +extern struct _console_ops arch_console_ops; + +int openbios(void) +{ +#ifdef CONFIG_DEBUG_CONSOLE + init_console(arch_console_ops); +#ifdef CONFIG_DEBUG_CONSOLE_SERIAL + uart_init(CONFIG_SERIAL_PORT, CONFIG_SERIAL_SPEED); +#endif + /* Clear the screen. */ + cls(); +#endif + + collect_sys_info(&sys_info); + + dict = (unsigned char *)sys_info.dict_start; + dicthead = (cell)sys_info.dict_end; + last = sys_info.dict_last; + dictlimit = sys_info.dict_limit; + + forth_init(); + + relocate(&sys_info); + +#ifdef CONFIG_DEBUG_CONSOLE_VGA + video_init(); +#endif +#ifdef CONFIG_DEBUG_BOOT + printk("forth started.\n"); + printk("initializing memory..."); +#endif + + init_memory(); + +#ifdef CONFIG_DEBUG_BOOT + printk("done\n"); +#endif + + PUSH_xt( bind_noname_func(arch_init) ); + fword("PREPOST-initializer"); + + PC = (ucell)findword("initialize-of"); + + if (!PC) { + printk("panic: no dictionary entry point.\n"); + return -1; + } +#ifdef CONFIG_DEBUG_DICTIONARY + printk("done (%d bytes).\n", dicthead); + printk("Jumping to dictionary...\n"); +#endif + + enterforth((xt_t)PC); + + return 0; +} diff --git a/qemu/roms/openbios/arch/x86/openbios.h b/qemu/roms/openbios/arch/x86/openbios.h new file mode 100644 index 000000000..a13082276 --- /dev/null +++ b/qemu/roms/openbios/arch/x86/openbios.h @@ -0,0 +1,32 @@ +/* + * Creation Date: <2004/01/15 16:14:05 samuel> + * Time-stamp: <2004/01/15 16:14:05 samuel> + * + * <openbios.h> + * + * + * + * Copyright (C) 2004 Samuel Rydh (samuel@ibrium.se) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#ifndef _H_OPENBIOS +#define _H_OPENBIOS + +int openbios(void); + +/* entry.S */ +void init_exceptions(void); + +/* console.c */ +extern void cls(void); +#ifdef CONFIG_DEBUG_CONSOLE +extern int uart_init(int port, unsigned long speed); +extern void video_init(void); +#endif + +#endif /* _H_OPENBIOS */ diff --git a/qemu/roms/openbios/arch/x86/plainboot.c b/qemu/roms/openbios/arch/x86/plainboot.c new file mode 100644 index 000000000..08dab2d12 --- /dev/null +++ b/qemu/roms/openbios/arch/x86/plainboot.c @@ -0,0 +1,21 @@ +/* tag: openbios fixed address forth starter + * + * Copyright (C) 2003 Stefan Reinauer + * + * See the file "COPYING" for further information about + * the copyright and warranty status of this work. + */ + +#include "config.h" +#include "libopenbios/sys_info.h" +#include "multiboot.h" + +#define FIXED_DICTSTART 0xfffe0000 +#define FIXED_DICTEND 0xfffeffff + +void collect_multiboot_info(struct sys_info *info); +void collect_multiboot_info(struct sys_info *info) +{ + info->dict_start=(unsigned long *)FIXED_DICTSTART; + info->dict_end=(unsigned long *)FIXED_DICTEND; +} diff --git a/qemu/roms/openbios/arch/x86/relocate.h b/qemu/roms/openbios/arch/x86/relocate.h new file mode 100644 index 000000000..d91160a03 --- /dev/null +++ b/qemu/roms/openbios/arch/x86/relocate.h @@ -0,0 +1 @@ +void relocate(struct sys_info *); diff --git a/qemu/roms/openbios/arch/x86/segment.c b/qemu/roms/openbios/arch/x86/segment.c new file mode 100644 index 000000000..5146cd302 --- /dev/null +++ b/qemu/roms/openbios/arch/x86/segment.c @@ -0,0 +1,133 @@ +/* Segmentation of the i386 architecture. + * + * 2003-07 by SONE Takeshi + */ + +#include "config.h" +#include "kernel/kernel.h" +#include "libopenbios/sys_info.h" +#include "relocate.h" +#include "segment.h" + +#define printf printk +#ifdef CONFIG_DEBUG_BOOT +#define debug printk +#else +#define debug(x...) +#endif + +/* i386 lgdt argument */ +struct gdtarg { + unsigned short limit; + unsigned int base; +} __attribute__((packed)); + +/* How far the virtual address (used in C) is different from physical + * address. Since we start in flat mode, the initial value is zero. */ +unsigned long virt_offset = 0; + +/* GDT, the global descriptor table */ +struct segment_desc gdt[NUM_SEG] = { + /* 0x00: null segment */ + {0, 0, 0, 0, 0, 0}, + /* 0x08: flat code segment */ + {0xffff, 0, 0, 0x9f, 0xcf, 0}, + /* 0x10: flat data segment */ + {0xffff, 0, 0, 0x93, 0xcf, 0}, + /* 0x18: code segment for relocated execution */ + {0xffff, 0, 0, 0x9f, 0xcf, 0}, + /* 0x20: data segment for relocated execution */ + {0xffff, 0, 0, 0x93, 0xcf, 0}, +}; + + +void relocate(struct sys_info *info) +{ + int i; + unsigned long prog_addr; + unsigned long prog_size; + unsigned long addr, new_base; + unsigned long long segsize; + unsigned long new_offset; + unsigned d0, d1, d2; + struct gdtarg gdtarg; +#define ALIGNMENT 16 + + prog_addr = virt_to_phys(&_start); + prog_size = virt_to_phys(&_end) - virt_to_phys(&_start); + debug("Current location: %#lx-%#lx\n", prog_addr, prog_addr+prog_size-1); + + new_base = 0; + for (i = 0; i < info->n_memranges; i++) { + if (info->memrange[i].base >= 1ULL<<32) + continue; + segsize = info->memrange[i].size; + if (info->memrange[i].base + segsize > 1ULL<<32) + segsize = (1ULL<<32) - info->memrange[i].base; + if (segsize < prog_size+ALIGNMENT) + continue; + addr = info->memrange[i].base + segsize - prog_size; + addr &= ~(ALIGNMENT-1); + if (addr >= prog_addr && addr < prog_addr + prog_size) + continue; + if (prog_addr >= addr && prog_addr < addr + prog_size) + continue; + if (addr > new_base) + new_base = addr; + } + if (new_base == 0) { + printf("Can't find address to relocate\n"); + return; + } + + debug("Relocating to %#lx-%#lx... ", + new_base, new_base + prog_size - 1); + + /* New virtual address offset */ + new_offset = new_base - (unsigned long) &_start; + + /* Tweak the GDT */ + gdt[RELOC_CODE].base_0 = (unsigned short) new_offset; + gdt[RELOC_CODE].base_16 = (unsigned char) (new_offset>>16); + gdt[RELOC_CODE].base_24 = (unsigned char) (new_offset>>24); + gdt[RELOC_DATA].base_0 = (unsigned short) new_offset; + gdt[RELOC_DATA].base_16 = (unsigned char) (new_offset>>16); + gdt[RELOC_DATA].base_24 = (unsigned char) (new_offset>>24); + + /* Load new GDT and reload segments */ + gdtarg.base = new_offset + (unsigned long) gdt; + gdtarg.limit = GDT_LIMIT; + __asm__ __volatile__ ( + "rep; movsb\n\t" /* copy everything */ + "lgdt %3\n\t" + "ljmp %4, $1f\n1:\t" + "movw %5, %%ds\n\t" + "movw %5, %%es\n\t" + "movw %5, %%fs\n\t" + "movw %5, %%gs\n\t" + "movw %5, %%ss\n" + : "=&S" (d0), "=&D" (d1), "=&c" (d2) + : "m" (gdtarg), "n" (RELOC_CS), "q" ((unsigned short) RELOC_DS), + "0" (&_start), "1" (new_base), "2" (prog_size)); + + virt_offset = new_offset; + debug("ok\n"); +} + +#if 0 +/* Copy GDT to new location and reload it */ +void move_gdt(unsigned long newgdt) +{ + struct gdtarg gdtarg; + + debug("Moving GDT to %#lx...", newgdt); + memcpy(phys_to_virt(newgdt), gdt, sizeof gdt); + gdtarg.base = newgdt; + gdtarg.limit = GDT_LIMIT; + debug("reloading GDT..."); + __asm__ __volatile__ ("lgdt %0\n\t" : : "m" (gdtarg)); + debug("reloading CS for fun..."); + __asm__ __volatile__ ("ljmp %0, $1f\n1:" : : "n" (RELOC_CS)); + debug("ok\n"); +} +#endif diff --git a/qemu/roms/openbios/arch/x86/segment.h b/qemu/roms/openbios/arch/x86/segment.h new file mode 100644 index 000000000..0371a80ae --- /dev/null +++ b/qemu/roms/openbios/arch/x86/segment.h @@ -0,0 +1,30 @@ + +/* Segment indexes. Must match the gdt definition in segment.c. */ +enum { + NULL_SEG, + FLAT_CODE, + FLAT_DATA, + RELOC_CODE, + RELOC_DATA, + NUM_SEG, +}; + +/* Values for segment selector register */ +#define FLAT_CS (FLAT_CODE << 3) +#define FLAT_DS (FLAT_DATA << 3) +#define RELOC_CS (RELOC_CODE << 3) +#define RELOC_DS (RELOC_DATA << 3) + +/* i386 segment descriptor */ +struct segment_desc { + unsigned short limit_0; + unsigned short base_0; + unsigned char base_16; + unsigned char types; + unsigned char flags; + unsigned char base_24; +}; + +extern struct segment_desc gdt[NUM_SEG]; + +#define GDT_LIMIT ((NUM_SEG << 3) - 1) diff --git a/qemu/roms/openbios/arch/x86/sys_info.c b/qemu/roms/openbios/arch/x86/sys_info.c new file mode 100644 index 000000000..9361c9d63 --- /dev/null +++ b/qemu/roms/openbios/arch/x86/sys_info.c @@ -0,0 +1,57 @@ +#include "config.h" +#include "kernel/kernel.h" +#include "libopenbios/sys_info.h" +#include "context.h" + +#ifdef CONFIG_DEBUG_BOOT +#define debug printk +#else +#define debug(x...) +#endif + +void collect_multiboot_info(struct sys_info *); +void collect_sys_info(struct sys_info *info); + +void collect_sys_info(struct sys_info *info) +{ + int i; + unsigned long long total = 0; + struct memrange *mmap; + + /* Pick up paramters given by bootloader to us */ + info->boot_type = boot_ctx->eax; + info->boot_data = boot_ctx->ebx; + info->boot_arg = boot_ctx->param[0]; + debug("boot eax = %#lx\n", info->boot_type); + debug("boot ebx = %#lx\n", info->boot_data); + debug("boot arg = %#lx\n", info->boot_arg); + + collect_elfboot_info(info); +#ifdef CONFIG_LINUXBIOS + collect_linuxbios_info(info); +#endif +#ifdef CONFIG_IMAGE_ELF_MULTIBOOT + collect_multiboot_info(info); +#endif + + if (!info->memrange) { + printk("Can't get memory map from firmware. " + "Using hardcoded default.\n"); + info->n_memranges = 2; + info->memrange = malloc(2 * sizeof(struct memrange)); + info->memrange[0].base = 0; + info->memrange[0].size = 640*1024; + info->memrange[1].base = 1024*1024; + info->memrange[1].size = 32*1024*1024 + - info->memrange[1].base; + } + + debug("\n"); + mmap=info->memrange; + for (i = 0; i < info->n_memranges; i++) { + debug("%016Lx-", mmap[i].base); + debug("%016Lx\n", mmap[i].base+mmap[i].size); + total += mmap[i].size; + } + debug("RAM %Ld MB\n", (total + 512*1024) >> 20); +} diff --git a/qemu/roms/openbios/arch/x86/xbox/console.c b/qemu/roms/openbios/arch/x86/xbox/console.c new file mode 100644 index 000000000..e96e04f07 --- /dev/null +++ b/qemu/roms/openbios/arch/x86/xbox/console.c @@ -0,0 +1,23 @@ +/* + * Xbox framebuffer - Video + Console + * + * Copyright (C) 2005 Ed Schouten <ed@fxq.nl>, + * Stefan Reinauer <stepan@openbios.org> + * + * 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 + */ + + +#include "config.h" +#include "libopenbios/bindings.h" +#include "libc/diskio.h" + +typedef struct osi_fb_info { + unsigned long mphys; + int rb, w, h, depth; +} osi_fb_info_t; + +#include "../../../packages/video.c" +#include "../../../libopenbios/console_common.c" diff --git a/qemu/roms/openbios/arch/x86/xbox/methods.c b/qemu/roms/openbios/arch/x86/xbox/methods.c new file mode 100644 index 000000000..741d15c08 --- /dev/null +++ b/qemu/roms/openbios/arch/x86/xbox/methods.c @@ -0,0 +1,102 @@ +/* + * Creation Date: <2004/08/28 18:38:22 greg> + * Time-stamp: <2004/08/28 18:38:22 greg> + * + * <methods.c> + * + * Misc device node methods + * + * Copyright (C) 2004 Greg Watson + * + * Based on MOL specific code which is + * + * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#include "config.h" +#include "libopenbios/bindings.h" +#include "libc/string.h" +// #include "libopenbios/ofmem.h" + +/************************************************************************/ +/* stdout */ +/************************************************************************/ + +DECLARE_NODE( video_stdout, INSTALL_OPEN, 0, "Tdisplay" ); + +/* ( addr len -- actual ) */ +static void +stdout_write( void ) +{ + int len = POP(); + char *addr = (char*)POP(); + + printk( "%s", s ); + //vfd_draw_str( s ); + console_draw_fstr(addr, len); + + PUSH( len ); +} + +NODE_METHODS( video_stdout ) = { + { "write", stdout_write }, +}; + + +/************************************************************************/ +/* tty */ +/************************************************************************/ + +DECLARE_NODE( tty, INSTALL_OPEN, 0, "/packages/terminal-emulator" ); + +/* ( addr len -- actual ) */ +static void +tty_read( void ) +{ + int ch, len = POP(); + char *p = (char*)POP(); + int ret=0; + + if( len > 0 ) { + ret = 1; + ch = getchar(); + if( ch >= 0 ) { + *p = ch; + } else { + ret = 0; + } + } + PUSH( ret ); +} + +/* ( addr len -- actual ) */ +static void +tty_write( void ) +{ + int i, len = POP(); + char *p = (char*)POP(); + for( i=0; i<len; i++ ) + putchar( *p++ ); + RET( len ); +} + +NODE_METHODS( tty ) = { + { "read", tty_read }, + { "write", tty_write }, +}; + +/************************************************************************/ +/* init */ +/************************************************************************/ + +void +node_methods_init( void ) +{ + REGISTER_NODE( video_stdout ); + REGISTER_NODE( tty ); +} diff --git a/qemu/roms/openbios/build.xml b/qemu/roms/openbios/build.xml new file mode 100644 index 000000000..f776b9a41 --- /dev/null +++ b/qemu/roms/openbios/build.xml @@ -0,0 +1,14 @@ +<?xml version="1.0"?> +<xmlmake> + <project name="openbios"> + <include href="kernel/build.xml"/> + <include href="forth/build.xml"/> + <include href="libc/build.xml"/> + <include href="libgcc/build.xml"/> + <include href="libopenbios/build.xml"/> + <include href="packages/build.xml"/> + <include href="drivers/build.xml"/> + <include href="fs/build.xml"/> + <include href="arch/build.xml"/> + </project> +</xmlmake> diff --git a/qemu/roms/openbios/config/examples/amd64_config.xml b/qemu/roms/openbios/config/examples/amd64_config.xml new file mode 100644 index 000000000..e8904b78d --- /dev/null +++ b/qemu/roms/openbios/config/examples/amd64_config.xml @@ -0,0 +1,61 @@ + <!-- kernel binaries (AMD64) --> + <option name="CONFIG_IMAGE_ELF_MULTIBOOT" type="boolean" value="true"/> + + <!-- Kernel Debugging --> + <option name="CONFIG_DEBUG" type="boolean" value="true"/> + <option name="CONFIG_DEBUG_BOOT" type="boolean" value="true"/> + <option name="CONFIG_DEBUG_DSTACK" type="boolean" value="false"/> + <option name="CONFIG_DEBUG_RSTACK" type="boolean" value="false"/> + <option name="CONFIG_DEBUG_DICTIONARY" type="boolean" value="false"/> + <option name="CONFIG_DEBUG_INTERNAL" type="boolean" value="false"/> + <option name="CONFIG_DEBUG_INTERPRETER" type="boolean" value="false"/> + <option name="CONFIG_DEBUG_CONSOLE" type="boolean" value="true"/> + <option name="CONFIG_DEBUG_CONSOLE_SERIAL" type="boolean" value="true"/> + <option name="CONFIG_SERIAL_PORT" type="boolean" value="true"/> + <option name="CONFIG_SERIAL_SPEED" type="integer" value="115200"/> + <option name="CONFIG_DEBUG_CONSOLE_VGA" type="boolean" value="true"/> + + + <!-- Module Configuration --> + <option name="CONFIG_CMDLINE" type="boolean" value="true"/> + <option name="CONFIG_DEBLOCKER" type="boolean" value="true"/> + <option name="CONFIG_FONT_8X8" type="boolean" value="true"/> + <option name="CONFIG_FONT_8X16" type="boolean" value="false"/> + <option name="CONFIG_LOADER_AOUT" type="boolean" value="false"/> + <option name="CONFIG_LOADER_BOOTINFO" type="boolean" value="false"/> + <option name="CONFIG_LOADER_ELF" type="boolean" value="true"/> + <option name="CONFIG_LOADER_FCODE" type="boolean" value="false"/> + <option name="CONFIG_LOADER_FORTH" type="boolean" value="false"/> + <option name="CONFIG_LOADER_XCOFF" type="boolean" value="false"/> + + <!-- Filesystem Configuration --> + <option name="CONFIG_DISK_LABEL" type="boolean" value="true"/> + <option name="CONFIG_PART_SUPPORT" type="boolean" value="true"/> + <option name="CONFIG_PC_PARTS" type="boolean" value="true"/> + <option name="CONFIG_HFS" type="boolean" value="false"/> + <option name="CONFIG_HFSP" type="boolean" value="true"/> + <option name="CONFIG_GRUBFS" type="boolean" value="true"/> + <option name="CONFIG_FSYS_EXT2FS" type="boolean" value="true"/> + <option name="CONFIG_FSYS_FAT" type="boolean" value="false"/> + <option name="CONFIG_FSYS_JFS" type="boolean" value="false"/> + <option name="CONFIG_FSYS_MINIX" type="boolean" value="false"/> + <option name="CONFIG_FSYS_REISERFS" type="boolean" value="true"/> + <option name="CONFIG_FSYS_XFS" type="boolean" value="false"/> + <option name="CONFIG_FSYS_UFS" type="boolean" value="false"/> + <option name="CONFIG_FSYS_ISO9660" type="boolean" value="false"/> + <option name="CONFIG_FSYS_FFS" type="boolean" value="false"/> + <option name="CONFIG_FSYS_VSTAFS" type="boolean" value="false"/> + <option name="CONFIG_FSYS_NTFS" type="boolean" value="false"/> + <option name="CONFIG_FSYS_AFFS" type="boolean" value="false"/> + <option name="CONFIG_DEBUG_FS" type="boolean" value="true"/> + + <!-- Miscellaneous --> + <option name="CONFIG_LINUXBIOS" type="boolean" value="true"/> + + <!-- Drivers --> + <option name="CONFIG_DRIVER_PCI" type="boolean" value="true"/> + <option name="CONFIG_DEBUG_PCI" type="boolean" value="false"/> + <option name="CONFIG_DRIVER_IDE" type="boolean" value="true"/> + <option name="CONFIG_IDE_NUM_CHANNELS" type="integer" value="4"/> + <option name="CONFIG_DEBUG_IDE" type="boolean" value="false"/> + <option name="CONFIG_DRIVER_VGA" type="boolean" value="false"/> diff --git a/qemu/roms/openbios/config/examples/ppc64_config.xml b/qemu/roms/openbios/config/examples/ppc64_config.xml new file mode 100644 index 000000000..5f79c21cc --- /dev/null +++ b/qemu/roms/openbios/config/examples/ppc64_config.xml @@ -0,0 +1,77 @@ + <!-- Kernel Debugging --> + <option name="CONFIG_DEBUG" type="boolean" value="true"/> + <option name="CONFIG_DEBUG_BOOT" type="boolean" value="false"/> + <option name="CONFIG_DEBUG_DSTACK" type="boolean" value="false"/> + <option name="CONFIG_DEBUG_RSTACK" type="boolean" value="false"/> + <option name="CONFIG_DEBUG_DICTIONARY" type="boolean" value="false"/> + <option name="CONFIG_DEBUG_INTERNAL" type="boolean" value="false"/> + <option name="CONFIG_DEBUG_INTERPRETER" type="boolean" value="false"/> + <option name="CONFIG_DEBUG_CONSOLE" type="boolean" value="true"/> + <option name="CONFIG_DEBUG_CONSOLE_SERIAL" type="boolean" value="true"/> + <option name="CONFIG_SERIAL_PORT" type="integer" value="0"/> + <option name="CONFIG_SERIAL_SPEED" type="integer" value="115200"/> + <option name="CONFIG_DEBUG_CONSOLE_VGA" type="boolean" value="true"/> + <option name="CONFIG_DEBUG_OFMEM" type="boolean" value="false"/> + + + <!-- Module Configuration --> + <option name="CONFIG_CMDLINE" type="boolean" value="true"/> + <option name="CONFIG_DEBLOCKER" type="boolean" value="true"/> + <option name="CONFIG_FONT_8X8" type="boolean" value="true"/> + <option name="CONFIG_FONT_8X16" type="boolean" value="false"/> + <option name="CONFIG_OFMEM" type="boolean" value="true"/> + <option name="CONFIG_OFMEM_MALLOC_ALIGN" type="integer" value="4"/> + <option name="CONFIG_VGA_WIDTH" type="integer" value="800"/> + <option name="CONFIG_VGA_HEIGHT" type="integer" value="600"/> + <option name="CONFIG_VGA_DEPTH" type="integer" value="8"/> + <option name="CONFIG_LOADER_AOUT" type="boolean" value="false"/> + <option name="CONFIG_LOADER_BOOTINFO" type="boolean" value="true"/> + <option name="CONFIG_LOADER_ELF" type="boolean" value="true"/> + <option name="CONFIG_LOADER_FCODE" type="boolean" value="false"/> + <option name="CONFIG_LOADER_FORTH" type="boolean" value="false"/> + <option name="CONFIG_LOADER_XCOFF" type="boolean" value="true"/> + + <!-- Filesystem Configuration --> + <option name="CONFIG_DISK_LABEL" type="boolean" value="true"/> + <option name="CONFIG_PART_SUPPORT" type="boolean" value="true"/> + <option name="CONFIG_MAC_PARTS" type="boolean" value="true"/> + <option name="CONFIG_DEBUG_MAC_PARTS" type="boolean" value="false"/> + <option name="CONFIG_PC_PARTS" type="boolean" value="true"/> + <option name="CONFIG_HFS" type="boolean" value="true"/> + <option name="CONFIG_HFSP" type="boolean" value="true"/> + <option name="CONFIG_ISO9660" type="boolean" value="true"/> + <option name="CONFIG_EXT2" type="boolean" value="true"/> + <option name="CONFIG_GRUBFS" type="boolean" value="true"/> + <option name="CONFIG_FSYS_EXT2FS" type="boolean" value="false"/> + <option name="CONFIG_FSYS_FAT" type="boolean" value="false"/> + <option name="CONFIG_FSYS_JFS" type="boolean" value="false"/> + <option name="CONFIG_FSYS_MINIX" type="boolean" value="false"/> + <option name="CONFIG_FSYS_REISERFS" type="boolean" value="false"/> + <option name="CONFIG_FSYS_XFS" type="boolean" value="false"/> + <option name="CONFIG_FSYS_UFS" type="boolean" value="false"/> + <option name="CONFIG_FSYS_ISO9660" type="boolean" value="false"/> + <option name="CONFIG_FSYS_FFS" type="boolean" value="false"/> + <option name="CONFIG_FSYS_VSTAFS" type="boolean" value="false"/> + <option name="CONFIG_FSYS_NTFS" type="boolean" value="false"/> + <option name="CONFIG_FSYS_AFFS" type="boolean" value="false"/> + <option name="CONFIG_DEBUG_FS" type="boolean" value="false"/> + + <!-- Miscellaneous --> + <option name="CONFIG_LINUXBIOS" type="boolean" value="false"/> + <option name="CONFIG_RTAS" type="boolean" value="false"/> + + <!-- Drivers --> + <option name="CONFIG_DRIVER_PCI" type="boolean" value="true"/> + <option name="CONFIG_DEBUG_PCI" type="boolean" value="false"/> + <option name="CONFIG_DRIVER_IDE" type="boolean" value="true"/> + <option name="CONFIG_IDE_NUM_CHANNELS" type="integer" value="2"/> + <option name="CONFIG_IDE_FIRST_UNIT" type="integer" value="1"/> + <option name="CONFIG_IDE_DEV_NAME" type="string" value="ata-%d"/> + <option name="CONFIG_IDE_DEV_TYPE" type="string" value="ata"/> + <option name="CONFIG_DEBUG_IDE" type="boolean" value="false"/> + <option name="CONFIG_DRIVER_ADB" type="boolean" value="true"/> + <option name="CONFIG_DRIVER_VGA" type="boolean" value="true"/> + <option name="CONFIG_DRIVER_MACIO" type="boolean" value="true"/> + <option name="CONFIG_DRIVER_ESCC" type="boolean" value="true"/> + <option name="CONFIG_DRIVER_FW_CFG" type="boolean" value="true"/> + <option name="CONFIG_FW_CFG_ADDR" type="integer" value="0xf0000510"/> diff --git a/qemu/roms/openbios/config/examples/ppc_config.xml b/qemu/roms/openbios/config/examples/ppc_config.xml new file mode 100644 index 000000000..4c14eb6c8 --- /dev/null +++ b/qemu/roms/openbios/config/examples/ppc_config.xml @@ -0,0 +1,85 @@ + <!-- Kernel Debugging --> + <option name="CONFIG_DEBUG" type="boolean" value="true"/> + <option name="CONFIG_DEBUG_BOOT" type="boolean" value="false"/> + <option name="CONFIG_DEBUG_DSTACK" type="boolean" value="false"/> + <option name="CONFIG_DEBUG_RSTACK" type="boolean" value="false"/> + <option name="CONFIG_DEBUG_DICTIONARY" type="boolean" value="false"/> + <option name="CONFIG_DEBUG_INTERNAL" type="boolean" value="false"/> + <option name="CONFIG_DEBUG_INTERPRETER" type="boolean" value="false"/> + <option name="CONFIG_DEBUG_CONSOLE" type="boolean" value="true"/> + <option name="CONFIG_DEBUG_CONSOLE_SERIAL" type="boolean" value="true"/> + <option name="CONFIG_DRIVER_PC_SERIAL" type="boolean" value="true"/> + <option name="CONFIG_DRIVER_PC_KBD" type="boolean" value="true"/> + <option name="CONFIG_SERIAL_PORT" type="integer" value="0"/> + <option name="CONFIG_SERIAL_SPEED" type="integer" value="115200"/> + <option name="CONFIG_DEBUG_CONSOLE_VGA" type="boolean" value="true"/> + <option name="CONFIG_DEBUG_OFMEM" type="boolean" value="false"/> + + + <!-- Module Configuration --> + <option name="CONFIG_CMDLINE" type="boolean" value="true"/> + <option name="CONFIG_DEBLOCKER" type="boolean" value="true"/> + <option name="CONFIG_FONT_8X8" type="boolean" value="true"/> + <option name="CONFIG_FONT_8X16" type="boolean" value="false"/> + <option name="CONFIG_OFMEM" type="boolean" value="true"/> + <option name="CONFIG_OFMEM_MALLOC_ALIGN" type="integer" value="4"/> + <option name="CONFIG_VGA_WIDTH" type="integer" value="800"/> + <option name="CONFIG_VGA_HEIGHT" type="integer" value="600"/> + <option name="CONFIG_VGA_DEPTH" type="integer" value="8"/> + <option name="CONFIG_LOADER_AOUT" type="boolean" value="false"/> + <option name="CONFIG_LOADER_BOOTINFO" type="boolean" value="true"/> + <option name="CONFIG_LOADER_BOOTCODE" type="boolean" value="true"/> + <option name="CONFIG_LOADER_ELF" type="boolean" value="true"/> + <option name="CONFIG_LOADER_FCODE" type="boolean" value="false"/> + <option name="CONFIG_LOADER_FORTH" type="boolean" value="false"/> + <option name="CONFIG_LOADER_XCOFF" type="boolean" value="true"/> + + <!-- Filesystem Configuration --> + <option name="CONFIG_DISK_LABEL" type="boolean" value="true"/> + <option name="CONFIG_PART_SUPPORT" type="boolean" value="true"/> + <option name="CONFIG_MAC_PARTS" type="boolean" value="true"/> + <option name="CONFIG_DEBUG_MAC_PARTS" type="boolean" value="false"/> + <option name="CONFIG_PC_PARTS" type="boolean" value="true"/> + <option name="CONFIG_HFS" type="boolean" value="true"/> + <option name="CONFIG_HFSP" type="boolean" value="true"/> + <option name="CONFIG_ISO9660" type="boolean" value="true"/> + <option name="CONFIG_EXT2" type="boolean" value="true"/> + <option name="CONFIG_GRUBFS" type="boolean" value="true"/> + <option name="CONFIG_FSYS_EXT2FS" type="boolean" value="false"/> + <option name="CONFIG_FSYS_FAT" type="boolean" value="false"/> + <option name="CONFIG_FSYS_JFS" type="boolean" value="false"/> + <option name="CONFIG_FSYS_MINIX" type="boolean" value="false"/> + <option name="CONFIG_FSYS_REISERFS" type="boolean" value="false"/> + <option name="CONFIG_FSYS_XFS" type="boolean" value="false"/> + <option name="CONFIG_FSYS_UFS" type="boolean" value="false"/> + <option name="CONFIG_FSYS_ISO9660" type="boolean" value="false"/> + <option name="CONFIG_FSYS_FFS" type="boolean" value="false"/> + <option name="CONFIG_FSYS_VSTAFS" type="boolean" value="false"/> + <option name="CONFIG_FSYS_NTFS" type="boolean" value="false"/> + <option name="CONFIG_FSYS_AFFS" type="boolean" value="false"/> + <option name="CONFIG_DEBUG_FS" type="boolean" value="false"/> + + <!-- Miscellaneous --> + <option name="CONFIG_PPC_64BITSUPPORT" type="boolean" value="true"/> + <option name="CONFIG_LINUXBIOS" type="boolean" value="false"/> + <option name="CONFIG_RTAS" type="boolean" value="false"/> + <option name="CONFIG_LOCALS" type="boolean" value="true"/> + + <!-- Drivers --> + <option name="CONFIG_DRIVER_PCI" type="boolean" value="true"/> + <option name="CONFIG_DEBUG_PCI" type="boolean" value="false"/> + <option name="CONFIG_DRIVER_IDE" type="boolean" value="true"/> + <option name="CONFIG_IDE_NUM_CHANNELS" type="integer" value="2"/> + <option name="CONFIG_IDE_FIRST_UNIT" type="integer" value="1"/> + <option name="CONFIG_IDE_DEV_NAME" type="string" value="ata-%d"/> + <option name="CONFIG_IDE_DEV_TYPE" type="string" value="ata"/> + <option name="CONFIG_DEBUG_IDE" type="boolean" value="false"/> + <option name="CONFIG_DRIVER_ADB" type="boolean" value="true"/> + <option name="CONFIG_DRIVER_VGA" type="boolean" value="true"/> + <option name="CONFIG_DRIVER_MACIO" type="boolean" value="true"/> + <option name="CONFIG_DRIVER_ESCC" type="boolean" value="true"/> + <option name="CONFIG_DRIVER_FW_CFG" type="boolean" value="true"/> + <option name="CONFIG_FW_CFG_ADDR" type="integer" value="0xf0000510"/> + <option name="CONFIG_DRIVER_USB" type="boolean" value="true"/> + <option name="CONFIG_DEBUG_USB" type="boolean" value="false"/> + <option name="CONFIG_USB_HID" type="boolean" value="true"/> diff --git a/qemu/roms/openbios/config/examples/sparc32_config.xml b/qemu/roms/openbios/config/examples/sparc32_config.xml new file mode 100644 index 000000000..f2d6afc72 --- /dev/null +++ b/qemu/roms/openbios/config/examples/sparc32_config.xml @@ -0,0 +1,74 @@ + <!-- kernel binaries (SPARC32) --> + <option name="CONFIG_IMAGE_ELF_MULTIBOOT" type="boolean" value="true"/> + + <!-- Kernel Debugging --> + <option name="CONFIG_DEBUG" type="boolean" value="true"/> + <option name="CONFIG_DEBUG_BOOT" type="boolean" value="false"/> + <option name="CONFIG_DEBUG_DSTACK" type="boolean" value="false"/> + <option name="CONFIG_DEBUG_RSTACK" type="boolean" value="false"/> + <option name="CONFIG_DEBUG_DICTIONARY" type="boolean" value="false"/> + <option name="CONFIG_DEBUG_INTERNAL" type="boolean" value="false"/> + <option name="CONFIG_DEBUG_INTERPRETER" type="boolean" value="false"/> + <option name="CONFIG_DEBUG_CONSOLE" type="boolean" value="true"/> + <option name="CONFIG_DEBUG_CONSOLE_SERIAL" type="boolean" value="true"/> + <option name="CONFIG_DEBUG_CONSOLE_VIDEO" type="boolean" value="true"/> + <option name="CONFIG_DEBUG_ESP" type="boolean" value="false"/> + <option name="CONFIG_DEBUG_SUN_PARTS" type="boolean" value="false"/> + <option name="CONFIG_DEBUG_OBP" type="boolean" value="false"/> + <option name="CONFIG_DEBUG_IOMMU" type="boolean" value="false"/> + <option name="CONFIG_SERIAL_PORT" type="integer" value="0"/> + <option name="CONFIG_SERIAL_SPEED" type="integer" value="9600"/> + <option name="CONFIG_DEBUG_OFMEM" type="boolean" value="false"/> + + + <!-- Module Configuration --> + <option name="CONFIG_CMDLINE" type="boolean" value="true"/> + <option name="CONFIG_DEBLOCKER" type="boolean" value="true"/> + <option name="CONFIG_FONT_8X8" type="boolean" value="true"/> + <option name="CONFIG_FONT_8X16" type="boolean" value="false"/> + <option name="CONFIG_OFMEM" type="boolean" value="true"/> + <option name="CONFIG_OFMEM_MALLOC_ALIGN" type="integer" value="8"/> + <option name="CONFIG_LOADER_AOUT" type="boolean" value="true"/> + <option name="CONFIG_LOADER_BOOTINFO" type="boolean" value="false"/> + <option name="CONFIG_LOADER_ELF" type="boolean" value="true"/> + <option name="CONFIG_LOADER_FCODE" type="boolean" value="false"/> + <option name="CONFIG_LOADER_FORTH" type="boolean" value="false"/> + <option name="CONFIG_LOADER_XCOFF" type="boolean" value="false"/> + + <!-- Filesystem Configuration --> + <option name="CONFIG_DISK_LABEL" type="boolean" value="true"/> + <option name="CONFIG_PART_SUPPORT" type="boolean" value="true"/> + <option name="CONFIG_PC_PARTS" type="boolean" value="false"/> + <option name="CONFIG_SUN_PARTS" type="boolean" value="true"/> + <option name="CONFIG_HFS" type="boolean" value="false"/> + <option name="CONFIG_HFSP" type="boolean" value="false"/> + <option name="CONFIG_GRUBFS" type="boolean" value="true"/> + <option name="CONFIG_FSYS_EXT2FS" type="boolean" value="true"/> + <option name="CONFIG_FSYS_FAT" type="boolean" value="false"/> + <option name="CONFIG_FSYS_JFS" type="boolean" value="false"/> + <option name="CONFIG_FSYS_MINIX" type="boolean" value="false"/> + <option name="CONFIG_FSYS_REISERFS" type="boolean" value="false"/> + <option name="CONFIG_FSYS_XFS" type="boolean" value="false"/> + <option name="CONFIG_FSYS_UFS" type="boolean" value="true"/> + <option name="CONFIG_FSYS_ISO9660" type="boolean" value="true"/> + <option name="CONFIG_FSYS_FFS" type="boolean" value="true"/> + <option name="CONFIG_FSYS_VSTAFS" type="boolean" value="false"/> + <option name="CONFIG_FSYS_NTFS" type="boolean" value="false"/> + <option name="CONFIG_FSYS_AFFS" type="boolean" value="false"/> + <option name="CONFIG_DEBUG_FS" type="boolean" value="false"/> + <option name="CONFIG_DEBUG_EXT2FS" type="boolean" value="false"/> + + <!-- Miscellaneous --> + <option name="CONFIG_LINUXBIOS" type="boolean" value="false"/> + + <!-- Drivers --> + <option name="CONFIG_DRIVER_SBUS" type="boolean" value="true"/> + <option name="CONFIG_DEBUG_SBUS" type="boolean" value="false"/> + <option name="CONFIG_DRIVER_OBIO" type="boolean" value="true"/> + <option name="CONFIG_DRIVER_ESP" type="boolean" value="true"/> + <option name="CONFIG_DRIVER_FLOPPY" type="boolean" value="true"/> + <option name="CONFIG_DEBUG_FLOPPY" type="boolean" value="false"/> + <option name="CONFIG_DRIVER_ESCC" type="boolean" value="true"/> + <option name="CONFIG_DRIVER_ESCC_SUN" type="boolean" value="true"/> + <option name="CONFIG_DRIVER_FW_CFG" type="boolean" value="true"/> + <option name="CONFIG_FW_CFG_ADDR" type="integer" value="0xd00000510ULL"/> diff --git a/qemu/roms/openbios/config/examples/sparc64_config.xml b/qemu/roms/openbios/config/examples/sparc64_config.xml new file mode 100644 index 000000000..a4e1336b4 --- /dev/null +++ b/qemu/roms/openbios/config/examples/sparc64_config.xml @@ -0,0 +1,74 @@ + <!-- kernel binaries (SPARC64) --> + <option name="CONFIG_IMAGE_ELF_MULTIBOOT" type="boolean" value="true"/> + + <!-- Kernel Debugging --> + <option name="CONFIG_DEBUG" type="boolean" value="true"/> + <option name="CONFIG_DEBUG_BOOT" type="boolean" value="false"/> + <option name="CONFIG_DEBUG_DSTACK" type="boolean" value="false"/> + <option name="CONFIG_DEBUG_RSTACK" type="boolean" value="false"/> + <option name="CONFIG_DEBUG_DICTIONARY" type="boolean" value="false"/> + <option name="CONFIG_DEBUG_INTERNAL" type="boolean" value="false"/> + <option name="CONFIG_DEBUG_INTERPRETER" type="boolean" value="false"/> + <option name="CONFIG_DEBUG_CONSOLE" type="boolean" value="true"/> + <option name="CONFIG_DEBUG_CONSOLE_SERIAL" type="boolean" value="true"/> + <option name="CONFIG_DEBUG_SUN_PARTS" type="boolean" value="false"/> + <option name="CONFIG_SERIAL_PORT" type="integer" value="0"/> + <option name="CONFIG_SERIAL_SPEED" type="integer" value="115200"/> + <option name="CONFIG_DEBUG_CONSOLE_VGA" type="boolean" value="true"/> + <option name="CONFIG_DEBUG_OFMEM" type="boolean" value="false"/> + + + <!-- Module Configuration --> + <option name="CONFIG_CMDLINE" type="boolean" value="true"/> + <option name="CONFIG_DEBLOCKER" type="boolean" value="true"/> + <option name="CONFIG_FONT_8X8" type="boolean" value="true"/> + <option name="CONFIG_FONT_8X16" type="boolean" value="false"/> + <option name="CONFIG_OFMEM" type="boolean" value="true"/> + <option name="CONFIG_OFMEM_MALLOC_ALIGN" type="integer" value="8"/> + <option name="CONFIG_LOADER_AOUT" type="boolean" value="true"/> + <option name="CONFIG_LOADER_BOOTINFO" type="boolean" value="false"/> + <option name="CONFIG_LOADER_ELF" type="boolean" value="true"/> + <option name="CONFIG_LOADER_FCODE" type="boolean" value="true"/> + <option name="CONFIG_LOADER_FORTH" type="boolean" value="false"/> + <option name="CONFIG_LOADER_XCOFF" type="boolean" value="false"/> + + <!-- Filesystem Configuration --> + <option name="CONFIG_DISK_LABEL" type="boolean" value="true"/> + <option name="CONFIG_PART_SUPPORT" type="boolean" value="true"/> + <option name="CONFIG_PC_PARTS" type="boolean" value="false"/> + <option name="CONFIG_SUN_PARTS" type="boolean" value="true"/> + <option name="CONFIG_HFS" type="boolean" value="false"/> + <option name="CONFIG_HFSP" type="boolean" value="false"/> + <option name="CONFIG_GRUBFS" type="boolean" value="true"/> + <option name="CONFIG_FSYS_EXT2FS" type="boolean" value="true"/> + <option name="CONFIG_FSYS_FAT" type="boolean" value="false"/> + <option name="CONFIG_FSYS_JFS" type="boolean" value="false"/> + <option name="CONFIG_FSYS_MINIX" type="boolean" value="false"/> + <option name="CONFIG_FSYS_REISERFS" type="boolean" value="false"/> + <option name="CONFIG_FSYS_XFS" type="boolean" value="false"/> + <option name="CONFIG_FSYS_UFS" type="boolean" value="true"/> + <option name="CONFIG_FSYS_ISO9660" type="boolean" value="true"/> + <option name="CONFIG_FSYS_FFS" type="boolean" value="true"/> + <option name="CONFIG_FSYS_VSTAFS" type="boolean" value="false"/> + <option name="CONFIG_FSYS_NTFS" type="boolean" value="false"/> + <option name="CONFIG_FSYS_AFFS" type="boolean" value="false"/> + <option name="CONFIG_DEBUG_FS" type="boolean" value="false"/> + <option name="CONFIG_DEBUG_EXT2FS" type="boolean" value="false"/> + + <!-- Miscellaneous --> + <option name="CONFIG_LINUXBIOS" type="boolean" value="false"/> + + <!-- Drivers --> + <option name="CONFIG_DRIVER_PCI" type="boolean" value="true"/> + <option name="CONFIG_DEBUG_PCI" type="boolean" value="false"/> + <option name="CONFIG_DRIVER_IDE" type="boolean" value="true"/> + <option name="CONFIG_IDE_NUM_CHANNELS" type="integer" value="2"/> + <option name="CONFIG_DEBUG_IDE" type="boolean" value="false"/> + <option name="CONFIG_DRIVER_FLOPPY" type="boolean" value="true"/> + <option name="CONFIG_DEBUG_FLOPPY" type="boolean" value="false"/> + <option name="CONFIG_DRIVER_VGA" type="boolean" value="true"/> + <option name="CONFIG_DRIVER_EBUS" type="boolean" value="true"/> + <option name="CONFIG_DRIVER_PC_KBD" type="boolean" value="true"/> + <option name="CONFIG_DRIVER_PC_SERIAL" type="boolean" value="true"/> + <option name="CONFIG_DRIVER_FW_CFG" type="boolean" value="true"/> + <option name="CONFIG_FW_CFG_ADDR" type="integer" value="0x510"/> diff --git a/qemu/roms/openbios/config/examples/x86_config.xml b/qemu/roms/openbios/config/examples/x86_config.xml new file mode 100644 index 000000000..390eaba52 --- /dev/null +++ b/qemu/roms/openbios/config/examples/x86_config.xml @@ -0,0 +1,63 @@ + <!-- kernel binaries (AMD64) --> + <option name="CONFIG_IMAGE_ELF_MULTIBOOT" type="boolean" value="true"/> + + <!-- Kernel Debugging --> + <option name="CONFIG_DEBUG" type="boolean" value="true"/> + <option name="CONFIG_DEBUG_BOOT" type="boolean" value="true"/> + <option name="CONFIG_DEBUG_DSTACK" type="boolean" value="false"/> + <option name="CONFIG_DEBUG_RSTACK" type="boolean" value="false"/> + <option name="CONFIG_DEBUG_DICTIONARY" type="boolean" value="false"/> + <option name="CONFIG_DEBUG_INTERNAL" type="boolean" value="false"/> + <option name="CONFIG_DEBUG_INTERPRETER" type="boolean" value="false"/> + <option name="CONFIG_DEBUG_CONSOLE" type="boolean" value="true"/> + <option name="CONFIG_DEBUG_CONSOLE_SERIAL" type="boolean" value="true"/> + <option name="CONFIG_SERIAL_PORT" type="boolean" value="true"/> + <option name="CONFIG_SERIAL_SPEED" type="integer" value="115200"/> + <option name="CONFIG_DEBUG_CONSOLE_VGA" type="boolean" value="true"/> + + + <!-- Module Configuration --> + <option name="CONFIG_CMDLINE" type="boolean" value="true"/> + <option name="CONFIG_DEBLOCKER" type="boolean" value="true"/> + <option name="CONFIG_FONT_8X8" type="boolean" value="true"/> + <option name="CONFIG_FONT_8X16" type="boolean" value="false"/> + <option name="CONFIG_LOADER_AOUT" type="boolean" value="false"/> + <option name="CONFIG_LOADER_BOOTINFO" type="boolean" value="false"/> + <option name="CONFIG_LOADER_ELF" type="boolean" value="true"/> + <option name="CONFIG_LOADER_FCODE" type="boolean" value="false"/> + <option name="CONFIG_LOADER_FORTH" type="boolean" value="true"/> + <option name="CONFIG_LOADER_XCOFF" type="boolean" value="false"/> + + <!-- Filesystem Configuration --> + <option name="CONFIG_DISK_LABEL" type="boolean" value="true"/> + <option name="CONFIG_PART_SUPPORT" type="boolean" value="true"/> + <option name="CONFIG_PC_PARTS" type="boolean" value="true"/> + <option name="CONFIG_HFS" type="boolean" value="false"/> + <option name="CONFIG_HFSP" type="boolean" value="false"/> + <option name="CONFIG_GRUBFS" type="boolean" value="true"/> + <option name="CONFIG_FSYS_EXT2FS" type="boolean" value="true"/> + <option name="CONFIG_FSYS_FAT" type="boolean" value="false"/> + <option name="CONFIG_FSYS_JFS" type="boolean" value="false"/> + <option name="CONFIG_FSYS_MINIX" type="boolean" value="false"/> + <option name="CONFIG_FSYS_REISERFS" type="boolean" value="true"/> + <option name="CONFIG_FSYS_XFS" type="boolean" value="false"/> + <option name="CONFIG_FSYS_UFS" type="boolean" value="true"/> + <option name="CONFIG_FSYS_ISO9660" type="boolean" value="true"/> + <option name="CONFIG_FSYS_FFS" type="boolean" value="false"/> + <option name="CONFIG_FSYS_VSTAFS" type="boolean" value="false"/> + <option name="CONFIG_FSYS_NTFS" type="boolean" value="false"/> + <option name="CONFIG_FSYS_AFFS" type="boolean" value="false"/> + <option name="CONFIG_DEBUG_FS" type="boolean" value="false"/> + + <!-- Miscellaneous --> + <option name="CONFIG_LINUXBIOS" type="boolean" value="true"/> + + <!-- Drivers --> + <option name="CONFIG_DRIVER_PCI" type="boolean" value="true"/> + <option name="CONFIG_DEBUG_PCI" type="boolean" value="false"/> + <option name="CONFIG_DRIVER_IDE" type="boolean" value="true"/> + <option name="CONFIG_IDE_NUM_CHANNELS" type="integer" value="4"/> + <option name="CONFIG_DEBUG_IDE" type="boolean" value="false"/> + <option name="CONFIG_DRIVER_VGA" type="boolean" value="true"/> + <option name="CONFIG_DRIVER_FLOPPY" type="boolean" value="false"/> + <option name="CONFIG_DEBUG_FLOPPY" type="boolean" value="false"/> diff --git a/qemu/roms/openbios/config/scripts/reldir b/qemu/roms/openbios/config/scripts/reldir new file mode 100755 index 000000000..50f384ec8 --- /dev/null +++ b/qemu/roms/openbios/config/scripts/reldir @@ -0,0 +1,10 @@ +#!/bin/sh + +PREF="." +for x in 0 1 2 3 4 5 6 7 ; do + test -f $PREF/config/configure.in && break + PREF="../$PREF" +done +ROOT=$( echo $(pwd) | sed "s,\(//*[^/][^/]*\)\{$x\}/*\$,," ) +RELNAME=$( echo $(pwd) | sed "s,^$ROOT/*,,g" ) +echo $RELNAME diff --git a/qemu/roms/openbios/config/scripts/switch-arch b/qemu/roms/openbios/config/scripts/switch-arch new file mode 100755 index 000000000..d5e2f7710 --- /dev/null +++ b/qemu/roms/openbios/config/scripts/switch-arch @@ -0,0 +1,427 @@ +#!/bin/sh + +# +# MOLPATH is needed if you want to build openbios-mol.elf +# +MOLPATH=$HOME/mol-0.9.71 + +if [ x"$1" = x -o "$1" = "-help" ]; then + printf "Usage:\n $0 [arch-config]...\n" + printf "arch-config values supported for native or cross compiled builds:\n" + printf " amd64, ppc, sparc32, sparc64, x86\n\n" + printf "Add \"unix-\" prefix to compile openbios-unix executable (native only)\n" + printf "Add \"builtin-\" prefix to compile openbios-builtin executables\n\n" + printf "Without prefixes, builtin and unix targets are selected\n\n" + printf "Special targets: mol-ppc briq-ppc pearpc-ppc qemu-ppc qemu-ppc64 xbox-x86\n\n" + printf "Example: $0 builtin-sparc32 unix-amd64 builtin-amd64\n" + exit 0 +fi + +crosscflags() +{ + host=$1 + target=$2 + + if test "$host" = "powerpc" -o "$host" = "ppc" \ + -o "$host" = "mips" -o "$host" = "s390" \ + -o "$host" = "sparc32" -o "$host" = "sparc64" \ + -o "$host" = "m68k" -o "$host" = "armv4b"; then + hostbigendian="yes" + else + hostbigendian="no" + fi + +# host long bits test + if test "$host" = "sparc64" -o "$host" = "ia64" \ + -o "$host" = "amd64" -o "$host" = "x86_64" \ + -o "$host" = "alpha"; then + hostlongbits="64" + else + hostlongbits="32" + fi + + if test "$target" = "powerpc" -o "$target" = "ppc" \ + -o "$target" = "powerpc64" -o "$target" = "ppc64" \ + -o "$target" = "mips" -o "$target" = "s390" \ + -o "$target" = "sparc32" -o "$target" = "sparc64" \ + -o "$target" = "m68k" -o "$target" = "armv4b"; then + targetbigendian="yes" + else + targetbigendian="no" + fi + +# target long bits test + if test "$target" = "sparc64" -o "$target" = "ia64" \ + -o "$target" = "amd64" -o "$target" = "x86_64" \ + -o "$target" = "powerpc64" -o "$target" = "ppc64" \ + -o "$target" = "alpha"; then + targetlongbits="64" + else + targetlongbits="32" + fi + + if test "$targetbigendian" = "$hostbigendian"; then + cflags="-USWAP_ENDIANNESS" + else + cflags="-DSWAP_ENDIANNESS" + fi + + if test "$targetlongbits" = "$hostlongbits"; then + cflags="$cflags -DNATIVE_BITWIDTH_EQUALS_HOST_BITWIDTH" + elif test "$targetlongbits" -lt "$hostlongbits"; then + cflags="$cflags -DNATIVE_BITWIDTH_SMALLER_THAN_HOST_BITWIDTH" + else + cflags="$cflags -DNATIVE_BITWIDTH_LARGER_THAN_HOST_BITWIDTH" + fi + + if test "$target" = "sparc64" -o "$target" = "ia64" \ + -o "$target" = "amd64" -o "$target" = "x86_64" \ + -o "$target" = "alpha"; then + if test "$host" = "x86"; then + cflags="$cflags -DNEED_FAKE_INT128_T" + elif test "$host" = "arm"; then + cflags="$cflags -DNEED_FAKE_INT128_T" + elif test "$host" = "ppc" -a `uname -s` = "Darwin"; then + cflags="$cflags -DNEED_FAKE_INT128_T" + fi + fi + + CROSSCFLAGS=$cflags +} + +archname() +{ + HOSTARCH=`uname -m | sed -e s/i.86/x86/ -e s/i86pc/x86/ \ + -e s/sun4u/sparc64/ -e s/sparc$/sparc32/ \ + -e s/arm.*/arm/ -e s/sa110/arm/ -e s/x86_64/amd64/ \ + -e "s/Power Macintosh/ppc/"` +} + +select_prefix() +{ + TARGETS="${1}-unknown-linux-gnu- ${1}-linux-gnu- ${1}-linux- ${1}-elf- ${1}-eabi-" + + if [ x"$CROSS_COMPILE" != "x" ]; then + TARGETS=$CROSS_COMPILE + fi + + for TARGET in $TARGETS + do + if type ${TARGET}gcc > /dev/null 2>&1 + then + return + fi + done + if [ "$ARCH" = "$HOSTARCH" ]; then + return + fi + echo "ERROR: no ${1} cross-compiler found !" 1>&2 + exit 1 +} + +config_set_boolean() +{ + option=`echo $1 | tr a-z A-Z` + echo "<option name=\"$option\" type=\"boolean\" value=\"true\" />" +} + +exists() +{ + type "$1" >/dev/null 2>&1 +} + + +SRCDIR=`dirname "$0"`/../.. +BUILDDIR=`pwd` + +# make source path absolute +SRCDIR=`cd "$SRCDIR"; pwd` + +if test "x$HOSTARCH" = "x"; then + archname +fi + +VERSION=`head $SRCDIR/VERSION` + +echo "Configuring OpenBIOS on $HOSTARCH for $*" + +if exists toke; then + : +else + echo "Unable to locate toke executable from the fcode-utils package - aborting" + exit 1 +fi + +target_list="" +for target in $*; do + case $target in + unix-*|builtin-*|plain-*|mol-ppc|briq-ppc|pearpc-ppc|qemu-ppc|qemu-ppc64|xbox-x86) + target_list="$target_list $target" + ;; + cross-*) + echo "\"cross-\" prefix is no longer needed" + target=`echo $target | sed s/cross-//g` + target_list="$target_list builtin-$target" + ;; + *) + #default: build builtin and if possible, unix target + target_list="$target_list builtin-$target unix-$target" + ;; + esac +done + +arch_list="" +for target in $target_list; do + arch=`echo $target | sed s/.*-//g` + if ! test -f $SRCDIR/config/examples/${arch}_config.xml; then + echo "Cannot find $SRCDIR/config/examples/${arch}_config.xml" >&2 + exit 1 + fi + if ! echo $arch_list | grep -q "$arch"; then + arch_list="$arch_list $arch" + fi +done + +for ARCH in $arch_list; do + unix="no" + builtin="no" + plain="no" + mol="no" + briq="no" + pearpc="no" + qemu="no" + xbox="no" + cross="no" + + for target in $target_list; do + case $target in + *-$ARCH) + : + ;; + *) + continue + ;; + esac + case $target in + mol-ppc) + mol="yes" + ;; + briq-ppc) + briq="yes" + ;; + pearpc-ppc) + pearpc="yes" + ;; + builtin-ppc|qemu-ppc|builtin-ppc64|qemu-ppc64) + qemu="yes" + ;; + xbox-x86) + xbox="yes" + ;; + builtin-sparc32) + builtin="yes" + qemu="yes" + ;; + builtin-sparc64) + builtin="yes" + qemu="yes" + ;; + unix-*) + if [ "$ARCH" != "$HOSTARCH" ]; then + # Can't cross compile Unix target + continue + fi + unix="yes" + ;; + builtin-*) + builtin="yes" + ;; + plain-*) + plain="yes" + ;; + esac + done + + BASEARCH=$ARCH + case $ARCH in + amd64) + select_prefix x86_64 + CFLAGS="-fno-builtin" + AS_FLAGS= + ;; + + ppc) + select_prefix powerpc + if [ "$unix" = "no" ]; then + CFLAGS="-m32 -msoft-float -fno-builtin-bcopy -fno-builtin-log2" + AS_FLAGS="-m32" + else + CFLAGS="-fno-builtin" + AS_FLAGS= + fi + ;; + + ppc64) + select_prefix powerpc64 + CFLAGS="-Wa,-a64 -m64 -msoft-float -fno-builtin" + AS_FLAGS="-Wa,-a64" + BASEARCH=ppc + ;; + + sparc32) + select_prefix sparc + CFLAGS="-Wa,-xarch=v8 -Wa,-32 -m32 -mcpu=supersparc -fno-builtin" + AS_FLAGS="-Wa,-xarch=v8 -Wa,-32" + ;; + + sparc64) + select_prefix sparc64 + CFLAGS="-Wa,-xarch=v9b -Wa,-64 -m64 -mcpu=ultrasparc -mcmodel=medany -fno-builtin" + AS_FLAGS="-Wa,-xarch=v9b -Wa,-64" + ;; + + x86) + select_prefix i486 + CFLAGS="-fno-builtin -m32" + AS_FLAGS="-Wa,-32" + ;; + esac + if [ "$ARCH" != "$HOSTARCH" -o `uname -s` = "Darwin" ]; then + cross="yes" + fi + crosscflags $HOSTARCH $ARCH + OBJDIR=$BUILDDIR/obj-$ARCH + ODIRS="$ODIRS $OBJDIR" + + printf "Initializing build tree $OBJDIR..." + rm -rf "$OBJDIR" + mkdir "$OBJDIR" + mkdir -p $OBJDIR/target + mkdir -p $OBJDIR/target/include + mkdir -p $OBJDIR/target/arch + mkdir -p $OBJDIR/target/arch/unix + mkdir -p $OBJDIR/target/arch/$ARCH + mkdir -p $OBJDIR/target/libgcc + mkdir -p $OBJDIR/target/kernel + mkdir -p $OBJDIR/target/libopenbios + mkdir -p $OBJDIR/target/packages + mkdir -p $OBJDIR/target/fs + mkdir -p $OBJDIR/target/fs/grubfs + mkdir -p $OBJDIR/target/fs/hfs + mkdir -p $OBJDIR/target/fs/hfsplus + mkdir -p $OBJDIR/target/fs/iso9660 + mkdir -p $OBJDIR/target/fs/ext2 + mkdir -p $OBJDIR/target/drivers + mkdir -p $OBJDIR/target/libc + mkdir -p $OBJDIR/host/include + mkdir -p $OBJDIR/host/kernel + mkdir -p $OBJDIR/forth + ln -s $SRCDIR/include/arch/$BASEARCH $OBJDIR/target/include/asm + #compile the host binary with target settings instead + #ln -s $SRCDIR/include/arch/$HOSTARCH $OBJDIR/host/include/asm + if [ "$mol" = "yes" ]; then + printf "\nUsing MOL path $MOLPATH...\n" + mkdir -p $OBJDIR/target/arch/ppc/mol + ln -s $MOLPATH/src/shared/osi_calls.h $OBJDIR/target/include/ + ln -s $MOLPATH/src/shared/osi.h $OBJDIR/target/include/ + ln -s $MOLPATH/src/shared/prom.h $OBJDIR/target/include/ + ln -s $MOLPATH/src/include/boothelper_sh.h $OBJDIR/target/include/ + ln -s $MOLPATH/src/include/video_sh.h $OBJDIR/target/include/ + ln -s $MOLPATH/src/include/pseudofs_sh.h $OBJDIR/target/include/ + ln -s $MOLPATH/src/include/kbd_sh.h $OBJDIR/target/include/ + ln -s $MOLPATH/src/drivers/disk/include/scsi_sh.h $OBJDIR/target/include/ + ln -s $MOLPATH/src/drivers/disk/include/ablk_sh.h $OBJDIR/target/include/ + fi + if [ "$briq" = "yes" ]; then + mkdir -p $OBJDIR/target/arch/ppc/briq + fi + if [ "$pearpc" = "yes" ]; then + mkdir -p $OBJDIR/target/arch/ppc/pearpc + fi + if [ "$qemu" = "yes" ]; then + mkdir -p $OBJDIR/target/arch/ppc/qemu + fi + if [ "$xbox" = "yes" ]; then + mkdir -p $OBJDIR/target/arch/x86/xbox + fi + echo "ok." + + ODIR=$OBJDIR + + printf "Creating target config.mak..." + echo "ARCH=$ARCH" > $ODIR/config.mak + if [ "$cross" = "yes" ]; then + echo "TARGET=$TARGET" >> $ODIR/config.mak + fi + echo "CFLAGS=$CFLAGS" >> $ODIR/config.mak + echo "AS_FLAGS=$AS_FLAGS" >> $ODIR/config.mak + echo "HOSTARCH?=$HOSTARCH" >> $ODIR/config.mak + echo "CROSSCFLAGS=$CROSSCFLAGS" >> $ODIR/config.mak + echo "VERSION=\"$VERSION\"" >> $ODIR/config.mak + echo "SRCDIR=$SRCDIR" >> $ODIR/config.mak + echo "ok." + + printf "Creating target rules.mak..." + ln -s $SRCDIR/config/xml/rules.xml $ODIR/rules.xml + echo "<?xml version=\"1.0\"?><config>" > $ODIR/config.xml + # Generic + config_set_boolean CONFIG_$ARCH >> $ODIR/config.xml + if [ "$BASEARCH" != "$ARCH" ]; then + config_set_boolean CONFIG_$BASEARCH >> $ODIR/config.xml + fi + if [ "$mol" = "yes" ]; then + config_set_boolean CONFIG_MOL >> $ODIR/config.xml + fi + if [ "$briq" = "yes" ]; then + config_set_boolean CONFIG_BRIQ >> $ODIR/config.xml + fi + if [ "$pearpc" = "yes" ]; then + config_set_boolean CONFIG_PEARPC >> $ODIR/config.xml + fi + if [ "$qemu" = "yes" ]; then + config_set_boolean CONFIG_QEMU >> $ODIR/config.xml + fi + if [ "$xbox" = "yes" ]; then + config_set_boolean CONFIG_XBOX >> $ODIR/config.xml + fi + if [ "$targetbigendian" = "yes" ]; then + config_set_boolean CONFIG_BIG_ENDIAN >> $ODIR/config.xml + else + config_set_boolean CONFIG_LITTLE_ENDIAN >> $ODIR/config.xml + fi + # Kernel binaries + if [ "$plain" = "yes" ]; then + config_set_boolean CONFIG_IMAGE_ELF >> $ODIR/config.xml + fi + if [ "$builtin" = "yes" ]; then + config_set_boolean CONFIG_IMAGE_ELF_EMBEDDED >> $ODIR/config.xml + fi + # Build hosted Unix binary? + if [ "$unix" = "yes" ]; then + config_set_boolean CONFIG_HOST_UNIX >> $ODIR/config.xml + #config_set_boolean CONFIG_UNIX_QT >> $ODIR/config.xml + #config_set_boolean CONFIG_PLUGINS >> $ODIR/config.xml + fi + cat $SRCDIR/config/examples/${ARCH}_config.xml >> $ODIR/config.xml + + cd $ODIR + echo "</config>" >> $ODIR/config.xml + ln -s $SRCDIR/Makefile.target $ODIR/Makefile + xsltproc $SRCDIR/config/xml/xinclude.xsl $SRCDIR/build.xml > $ODIR/build-full.xml + xsltproc $SRCDIR/config/xml/makefile.xsl $ODIR/build-full.xml > $ODIR/rules.mak + echo "ok." + printf "Creating config files..." + xsltproc $SRCDIR/config/xml/config-c.xsl $ODIR/config.xml > $ODIR/host/include/autoconf.h + xsltproc $SRCDIR/config/xml/config-c.xsl $ODIR/config.xml > $ODIR/target/include/autoconf.h + xsltproc $SRCDIR/config/xml/config-forth.xsl $ODIR/config.xml > $ODIR/forth/config.fs + echo "ok." + + cd $BUILDDIR +done + +if [ "$SRCDIR" != "$BUILDDIR" ]; then + ln -s $SRCDIR/Makefile $BUILDDIR +fi + +echo "ODIRS=$ODIRS" >> $BUILDDIR/config-host.mak +echo "TARGETS=$arch_list" >> $BUILDDIR/config-host.mak diff --git a/qemu/roms/openbios/config/xml/config-c.xsl b/qemu/roms/openbios/config/xml/config-c.xsl new file mode 100644 index 000000000..62ed85446 --- /dev/null +++ b/qemu/roms/openbios/config/xml/config-c.xsl @@ -0,0 +1,57 @@ +<?xml version="1.0" encoding="ISO-8859-15" ?> + +<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> + + <xsl:template match="/"> + <!-- add comment --> + <xsl:text>/* * Automatically generated C config: don't edit */ </xsl:text> + + <!-- scan all config options --> + <xsl:for-each select="config/option"> + <xsl:choose> + + <!-- config option "boolean" --> + <xsl:when test="@type='boolean'"> + <xsl:choose> + <xsl:when test="@value='true'"> + <xsl:text>#define </xsl:text> + <xsl:value-of select="@name"/> + <xsl:text> 1</xsl:text> + </xsl:when> + <xsl:when test="@value='false'"> + <xsl:text>#undef </xsl:text> + <xsl:value-of select="@name"/> + </xsl:when> + <xsl:otherwise> + <xsl:message terminate="yes"> ERROR: boolean configuration option '<xsl:value-of select="@name"/>' has unsupported value '<xsl:value-of select="@type"/>' instead of [true|false].</xsl:message> + </xsl:otherwise> + </xsl:choose> + </xsl:when> + + <!-- config option "integer" --> + <xsl:when test="@type='integer'"> + <xsl:text>#define </xsl:text> + <xsl:value-of select="@name"/><xsl:text> </xsl:text> + <xsl:value-of select="@value"/> + </xsl:when> + + <!-- config option "string" --> + <xsl:when test="@type='string'"> + <xsl:text>#define </xsl:text> + <xsl:value-of select="@name"/><xsl:text> </xsl:text> "<xsl:value-of select="@value"/>" </xsl:when> + + <!-- unsupported config option: bail out --> + <xsl:otherwise> + <xsl:message terminate="yes"> ERROR: configuration option '<xsl:value-of select="@name"/> has unsupported type '<xsl:value-of select="@type"/>'.</xsl:message> + </xsl:otherwise> + + </xsl:choose> + + <xsl:text> </xsl:text> + </xsl:for-each> + + </xsl:template> + + <xsl:output method="text" indent="no" encoding="iso-8859-15"/> + +</xsl:stylesheet> diff --git a/qemu/roms/openbios/config/xml/config-forth.xsl b/qemu/roms/openbios/config/xml/config-forth.xsl new file mode 100644 index 000000000..cace0deb9 --- /dev/null +++ b/qemu/roms/openbios/config/xml/config-forth.xsl @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="ISO-8859-15" ?> + +<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> + + <xsl:template match="/"> + <xsl:for-each select="config/option"> + <xsl:choose> + <xsl:when test="@type='boolean'"> + <xsl:choose> + <xsl:when test="@value='true'"> + <xsl:text>[DEFINE] </xsl:text> + <xsl:value-of select="@name"/> + <xsl:text> </xsl:text> + </xsl:when> + <xsl:when test="@value='false'"> + <!-- nothing to do --> + </xsl:when> + <xsl:otherwise> + <xsl:message terminate="yes"> ERROR: boolean configuration option '<xsl:value-of select="@name"/>' has unsupported value '<xsl:value-of select="@type"/>' instead of [true|false].</xsl:message> + </xsl:otherwise> + </xsl:choose> + </xsl:when> + <xsl:when test="@type='integer'"> + <!-- this makes absolutely no sense but the old code did it as well --> + <xsl:text>[DEFINE] </xsl:text> + <xsl:value-of select="@name"/> + <xsl:text> </xsl:text> + </xsl:when> + <!-- config option "string" --> + <xsl:when test="@type='string'"> + </xsl:when> + <xsl:otherwise> + <xsl:message terminate="yes"> ERROR: configuration option '<xsl:value-of select="@name"/>' has unsupported type '<xsl:value-of select="@type"/>'.</xsl:message> + </xsl:otherwise> + </xsl:choose> + </xsl:for-each> + </xsl:template> + + <xsl:output method="text" indent="no" encoding="iso-8859-15"/> + +</xsl:stylesheet> diff --git a/qemu/roms/openbios/config/xml/dictionary.xsl b/qemu/roms/openbios/config/xml/dictionary.xsl new file mode 100644 index 000000000..61f62d84c --- /dev/null +++ b/qemu/roms/openbios/config/xml/dictionary.xsl @@ -0,0 +1,195 @@ +<?xml version="1.0" encoding="ISO-8859-15" ?> + +<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> + + <xsl:template match="/" mode="dictionaries"> + + <xsl:text> # # dictionary rules # </xsl:text> + + <!-- Set all dictionary source lists empty --> + <xsl:for-each select="//dictionary"> + <xsl:sort select="@name"/> + + <xsl:variable name="conditions"> + <xsl:text>0</xsl:text> + <xsl:for-each select="(ancestor-or-self::*)[@condition!='']"> + <xsl:call-template name="resolve-condition"> + <xsl:with-param select="@condition" name="expression"/> + </xsl:call-template> + </xsl:for-each> + </xsl:variable> + + <xsl:if test="$conditions = 0"> + + <xsl:if test="not(preceding::dictionary/@name = @name)"> + <xsl:value-of select="@name"/> + <xsl:text>-DICTIONARY := </xsl:text> + </xsl:if> + </xsl:if> + </xsl:for-each> + + <!-- Add all forth source files to their dictionaries --> + <xsl:for-each select="//dictionary/object"> + + <xsl:variable name="path"> + <xsl:for-each select="ancestor::build"> + <xsl:call-template name="get-dirname"> + <xsl:with-param select="@base" name="path"/> + </xsl:call-template> + </xsl:for-each> + </xsl:variable> + + <xsl:variable name="conditions"> + <xsl:text>0</xsl:text> + <xsl:for-each select="(ancestor-or-self::*)[@condition!='']"> + <xsl:call-template name="resolve-condition"> + <xsl:with-param select="@condition" name="expression"/> + </xsl:call-template> + </xsl:for-each> + </xsl:variable> + + <xsl:variable name="dictname"> + <xsl:value-of select="parent::*/@name"/> + </xsl:variable> + + <xsl:if test="$conditions=0"> + + <xsl:variable name="source"><xsl:value-of select="@source" /></xsl:variable> + + <!-- Handle just Forth source, not FCode --> + <xsl:if test="not(@target = 'fcode')"> + <xsl:value-of select="$dictname"/><xsl:text>-DICTIONARY:=$(</xsl:text> + <xsl:value-of select="$dictname"/><xsl:text>-DICTIONARY) </xsl:text> + + <xsl:value-of select="$path"/> + <xsl:value-of select="$source"/> + <xsl:text> </xsl:text> + </xsl:if> + + </xsl:if> + </xsl:for-each> + + <xsl:text> </xsl:text> + + <!-- Create targets for all dictionaries --> + <xsl:for-each select="//dictionary"> + <xsl:sort select="@name"/> + + <xsl:variable name="outer-conditions"> + <xsl:text>0</xsl:text> + <xsl:for-each select="(ancestor-or-self::*)[@condition!='']"> + <xsl:call-template name="resolve-condition"> + <xsl:with-param select="@condition" name="expression"/> + </xsl:call-template> + </xsl:for-each> + </xsl:variable> + + <xsl:if test="$outer-conditions = 0"> + + <xsl:if test="not(preceding::dictionary/@name = @name)"> + <xsl:variable name="name"><xsl:value-of select="@name"/></xsl:variable> + <xsl:variable name="init"> + <xsl:value-of select="(//dictionary[@name=$name]/attribute::init)[last()]"/> + </xsl:variable> + <!-- dictionary name and dependencies --> + <xsl:text>$(ODIR)/</xsl:text> + <xsl:value-of select="@name"/><xsl:text>.dict: $(</xsl:text> + <xsl:value-of select="@name"/> + <xsl:text>-DICTIONARY) $(ODIR)/forthstrap</xsl:text> + <xsl:if test="$init!=''"> + <xsl:text> $(ODIR)/</xsl:text><xsl:value-of select="$init"/><xsl:text>.dict</xsl:text> + </xsl:if> + + <!-- Check for Fcode dependency --> + <xsl:for-each select="object[@target = 'fcode']"> + + <xsl:variable name="conditions"> + <xsl:text>0</xsl:text> + <xsl:for-each select="(ancestor-or-self::*)[@condition!='']"> + <xsl:call-template name="resolve-condition"> + <xsl:with-param select="@condition" name="expression"/> + </xsl:call-template> + </xsl:for-each> + </xsl:variable> + + <xsl:if test="$conditions = 0"> + + <xsl:text> $(ODIR)/</xsl:text> + <xsl:value-of select="@source"/> + + </xsl:if> + </xsl:for-each> + + <xsl:text> </xsl:text> + <!-- rule --> + <xsl:text>	$(call quiet-command,$(ODIR)/forthstrap</xsl:text> + <xsl:for-each select="//dictionary[@name = @name]"> + + <xsl:variable name="conditions"> + <xsl:text>0</xsl:text> + <xsl:for-each select="(ancestor-or-self::*)[@condition!='']"> + <xsl:call-template name="resolve-condition"> + <xsl:with-param select="@condition" name="expression"/> + </xsl:call-template> + </xsl:for-each> + </xsl:variable> + + <xsl:variable name="path"> + <xsl:for-each select="ancestor::build"> + <xsl:call-template name="get-dirname"> + <xsl:with-param select="@base" name="path"/> + </xsl:call-template> + </xsl:for-each> + </xsl:variable> + + <xsl:if test="$conditions = 0"> + <xsl:text> -I</xsl:text> + <xsl:text>$(SRCDIR)/</xsl:text> + <xsl:value-of select="$path"/> + </xsl:if> + </xsl:for-each> + + <!-- needed to locate files with full path --> + <xsl:text> -I$(SRCDIR)</xsl:text> + <!-- needed to include config and build date --> + <xsl:text> -I$(ODIR)/forth</xsl:text> + + <xsl:text> -D $@</xsl:text> + <xsl:text> -M $@.d</xsl:text> + <xsl:if test="$init!=''"> + <xsl:text> -d $(ODIR)/</xsl:text><xsl:value-of select="$init"/><xsl:text>.dict</xsl:text> + </xsl:if> + <xsl:text> -c $@-console.log</xsl:text> + <xsl:text> $(</xsl:text> + <xsl:value-of select="@name"/> + <xsl:text>-DICTIONARY)," GEN $(TARGET_DIR)$@") </xsl:text> + </xsl:if> + </xsl:if> + </xsl:for-each> + + <!-- Create dictionaries target containing all dictionaries --> + <xsl:text>dictionaries: </xsl:text> + <xsl:for-each select="//dictionary"> + <xsl:sort select="@name"/> + + <xsl:variable name="conditions"> + <xsl:text>0</xsl:text> + <xsl:for-each select="(ancestor-or-self::*)[@condition!='']"> + <xsl:call-template name="resolve-condition"> + <xsl:with-param select="@condition" name="expression"/> + </xsl:call-template> + </xsl:for-each> + </xsl:variable> + + <xsl:if test="$conditions = 0"> + + <xsl:if test="not(preceding::dictionary/@name = @name)"> + <xsl:text>$(ODIR)/</xsl:text> + <xsl:value-of select="@name"/><xsl:text>.dict </xsl:text> + </xsl:if> + </xsl:if> + </xsl:for-each> + <xsl:text> </xsl:text> + </xsl:template> + +</xsl:stylesheet> diff --git a/qemu/roms/openbios/config/xml/fcode.xsl b/qemu/roms/openbios/config/xml/fcode.xsl new file mode 100644 index 000000000..ccc7e6e84 --- /dev/null +++ b/qemu/roms/openbios/config/xml/fcode.xsl @@ -0,0 +1,48 @@ +<?xml version="1.0" encoding="ISO-8859-15" ?> + +<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> + + <xsl:template match="/" mode="fcode"> + + <xsl:text> # # fcode rules # </xsl:text> + + <!-- Create linker targets for FCode roms --> + <xsl:for-each select="//fcode"> + <xsl:variable name="outer-conditions"> + <xsl:text>0</xsl:text> + <xsl:for-each select="(ancestor-or-self::*)[@condition!='']"> + <xsl:call-template name="resolve-condition"> + <xsl:with-param select="@condition" name="expression"/> + </xsl:call-template> + </xsl:for-each> + </xsl:variable> + + <xsl:if test="$outer-conditions = 0"> + <xsl:if test="(ancestor-or-self::*)"> + + <xsl:variable name="path"> + <xsl:for-each select="ancestor::build"> + <xsl:call-template name="get-dirname"> + <xsl:with-param select="@base" name="path"/> + </xsl:call-template> + </xsl:for-each> + </xsl:variable> + + <!-- Fcode name --> + <xsl:text>$(ODIR)/</xsl:text> + <xsl:value-of select="@name"/> + <xsl:text>:</xsl:text> + + <xsl:text> $(SRCDIR)/</xsl:text> + <xsl:value-of select="$path"/> + <xsl:value-of select="@source"/> + + <!-- FIXME this requires strict spaces in rules.xml --> + <xsl:value-of select="document('rules.xml',.)//rule[@target='host'][@entity='fcode']"/> + <xsl:text> </xsl:text> + </xsl:if> + </xsl:if> + </xsl:for-each> + + </xsl:template> +</xsl:stylesheet> diff --git a/qemu/roms/openbios/config/xml/makefile.xsl b/qemu/roms/openbios/config/xml/makefile.xsl new file mode 100644 index 000000000..56c494cc6 --- /dev/null +++ b/qemu/roms/openbios/config/xml/makefile.xsl @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="ISO-8859-15" ?> + +<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> + + <xsl:include href="util.xsl"/> + <xsl:include href="dictionary.xsl"/> + <xsl:include href="object.xsl"/> + <xsl:include href="fcode.xsl"/> + + <xsl:template match="/"> + <xsl:value-of select="document('rules.xml',.)/rules/pre"/> + <xsl:apply-templates select="." mode="dictionaries"/> + <xsl:apply-templates select="." mode="fcode"/> + <xsl:apply-templates select="." mode="objects"/> + </xsl:template> + + <xsl:output method="text" indent="no" encoding="iso-8859-15"/> + +</xsl:stylesheet> + diff --git a/qemu/roms/openbios/config/xml/object.xsl b/qemu/roms/openbios/config/xml/object.xsl new file mode 100644 index 000000000..cf521f59f --- /dev/null +++ b/qemu/roms/openbios/config/xml/object.xsl @@ -0,0 +1,327 @@ +<?xml version="1.0" encoding="ISO-8859-15" ?> + +<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> + + <!-- wrapper that calls "objects" with parameters --> + <xsl:template match="/" mode="objects"> + <xsl:call-template name="objects"> + <xsl:with-param name="target" select="'host'"/> + </xsl:call-template> + <xsl:call-template name="objects"> + <xsl:with-param name="target" select="'target'"/> + </xsl:call-template> + </xsl:template> + + <!-- main work happens here --> + <xsl:template name="objects"> + + <xsl:param name="target"/> + + <xsl:text> # # </xsl:text> + <xsl:value-of select="$target"/> + <xsl:text> compiler rules # </xsl:text> + + <!-- create rules for all compile objects --> + <xsl:for-each select="//object[(ancestor-or-self::*)[@target = $target]]"> + + <xsl:variable name="path"> + <xsl:for-each select="ancestor::build"> + <xsl:call-template name="get-dirname"> + <xsl:with-param select="@base" name="path"/> + </xsl:call-template> + </xsl:for-each> + </xsl:variable> + + <xsl:variable name="conditions"> + <xsl:text>0</xsl:text> + <xsl:for-each select="(ancestor-or-self::*)[@condition!='']"> + <xsl:call-template name="resolve-condition"> + <xsl:with-param select="@condition" name="expression"/> + </xsl:call-template> + </xsl:for-each> + </xsl:variable> + + <xsl:if test="$conditions=0"> + + <!-- full path of object file --> + <xsl:text>$(ODIR)/</xsl:text> + <xsl:value-of select="$target"/> + <xsl:text>/</xsl:text> + <xsl:value-of select="$path"/> + <xsl:value-of select="substring-before(@source,'.')"/> + <xsl:text>.o: </xsl:text> + + <!-- path of source file --> + <xsl:value-of select="$path"/> + <xsl:value-of select="@source"/> + + + <xsl:choose> + <xsl:when test="child::rule"> + <xsl:value-of select="child::rule"/> + <xsl:text> </xsl:text> + </xsl:when> + <xsl:otherwise> + <xsl:choose> + <xsl:when test="@flags!=''"> + <xsl:value-of select="document('rules.xml',.)//rule[@target=$target][@entity='object'][@extracflags='1']"/> + <xsl:text> </xsl:text> + <xsl:value-of select="@flags"/> + <xsl:text> </xsl:text> + <xsl:value-of select="document('rules.xml',.)//rule[@target=$target][@entity='object'][@extracflags='2']"/> + </xsl:when> + <xsl:otherwise> + <!-- FIXME this requires strict spaces in rules.xml --> + <xsl:value-of select="document('rules.xml',.)//rule[@target=$target][@entity='object']"/> + </xsl:otherwise> + </xsl:choose> + </xsl:otherwise> + </xsl:choose> + + </xsl:if> + </xsl:for-each> + + <!-- Create linker targets for all executables --> + <xsl:for-each select="//executable"> + + <xsl:variable name="outer-conditions"> + <xsl:text>0</xsl:text> + <xsl:for-each select="(ancestor-or-self::*)[@condition!='']"> + <xsl:call-template name="resolve-condition"> + <xsl:with-param select="@condition" name="expression"/> + </xsl:call-template> + </xsl:for-each> + </xsl:variable> + + <xsl:if test="$outer-conditions = 0"> + <xsl:if test="(ancestor-or-self::*)[@target = $target]"> + + <!-- executable name --> + <xsl:text>$(ODIR)/</xsl:text> + <xsl:value-of select="@name"/> + <xsl:text>:</xsl:text> + + <!-- add all objects --> + <xsl:for-each select="object"> + + <xsl:variable name="conditions"> + <xsl:text>0</xsl:text> + <xsl:for-each select="(ancestor-or-self::*)[@condition!='']"> + <xsl:call-template name="resolve-condition"> + <xsl:with-param select="@condition" name="expression"/> + </xsl:call-template> + </xsl:for-each> + </xsl:variable> + + <xsl:if test="$conditions=0"> + + <xsl:variable name="path"> + <xsl:for-each select="ancestor::build"> + <xsl:call-template name="get-dirname"> + <xsl:with-param select="@base" name="path"/> + </xsl:call-template> + </xsl:for-each> + </xsl:variable> + + <xsl:text> $(ODIR)/</xsl:text> + <xsl:value-of select="$target"/> + <xsl:text>/</xsl:text> + <xsl:value-of select="$path"/> + <xsl:value-of select="substring-before(@source,'.')"/> + <xsl:text>.o</xsl:text> + + </xsl:if> + </xsl:for-each> + + <!-- external objects last --> + <xsl:for-each select="external-object"> + + <xsl:variable name="conditions"> + <xsl:text>0</xsl:text> + <xsl:for-each select="(ancestor-or-self::*)[@condition!='']"> + <xsl:call-template name="resolve-condition"> + <xsl:with-param select="@condition" name="expression"/> + </xsl:call-template> + </xsl:for-each> + </xsl:variable> + + <xsl:if test="$conditions=0"> + <xsl:text> $(ODIR)/</xsl:text> + <xsl:value-of select="@source"/> + </xsl:if> + + </xsl:for-each> + + <!-- print executable rule --> + <xsl:choose> + <xsl:when test="child::rule"> + <xsl:value-of select="child::rule"/> + <xsl:text> </xsl:text> + </xsl:when> + <xsl:otherwise> + <!-- FIXME this requires strict spaces in rules.xml --> + <xsl:value-of select="document('rules.xml',.)//rule[@target=$target][@entity='executable']"/> + </xsl:otherwise> + </xsl:choose> + + </xsl:if> + </xsl:if> + </xsl:for-each> + + <!-- create linker targets for all libs --> + <xsl:for-each select="//library"> + <xsl:sort select="@name"/> + + <xsl:variable name="outer-conditions"> + <xsl:text>0</xsl:text> + <xsl:for-each select="(ancestor-or-self::*)[@condition!='']"> + <xsl:call-template name="resolve-condition"> + <xsl:with-param select="@condition" name="expression"/> + </xsl:call-template> + </xsl:for-each> + </xsl:variable> + + <xsl:if test="$outer-conditions = 0"> + + + <xsl:if test="(ancestor-or-self::*)[@target = $target]"> + + <xsl:if test="not(preceding::library/@name = @name)"> + + <!-- output library name --> + <xsl:text>$(ODIR)/lib</xsl:text> + <xsl:value-of select="@name"/> + + <xsl:choose> + <xsl:when test="@type='static'"> + <xsl:text>.a</xsl:text> + </xsl:when> + <xsl:when test="@type='dynamic'"> + <xsl:text>.so</xsl:text> + </xsl:when> + </xsl:choose> + <xsl:text>: </xsl:text> + + <xsl:variable name="name"><xsl:value-of select="@name"/></xsl:variable> + + <!-- enumerate all objects for library target --> + <xsl:for-each select="//library[@name=$name]/object"> + + <xsl:variable name="conditions"> + <xsl:text>0</xsl:text> + <xsl:for-each select="(ancestor-or-self::*)[@condition!='']"> + <xsl:call-template name="resolve-condition"> + <xsl:with-param select="@condition" name="expression"/> + </xsl:call-template> + </xsl:for-each> + </xsl:variable> + + <xsl:if test="$conditions=0"> + + <xsl:variable name="path"> + <xsl:for-each select="ancestor::build"> + <xsl:call-template name="get-dirname"> + <xsl:with-param select="@base" name="path"/> + </xsl:call-template> + </xsl:for-each> + </xsl:variable> + + <xsl:text>$(ODIR)/</xsl:text> + <xsl:value-of select="$target"/> + <xsl:text>/</xsl:text> + <xsl:value-of select="$path"/> + <xsl:value-of select="substring-before(@source,'.')"/> + <xsl:text>.o </xsl:text> + + </xsl:if> + + </xsl:for-each> + + <!-- external objects last --> + <xsl:for-each select="external-object"> + + <xsl:variable name="conditions"> + <xsl:text>0</xsl:text> + <xsl:for-each select="(ancestor-or-self::*)[@condition!='']"> + <xsl:call-template name="resolve-condition"> + <xsl:with-param select="@condition" name="expression"/> + </xsl:call-template> + </xsl:for-each> + </xsl:variable> + + <xsl:if test="$conditions=0"> + <xsl:text> $(ODIR)/</xsl:text> + <xsl:value-of select="@source"/> + </xsl:if> + + </xsl:for-each> + + + <!-- FIXME this requires strict spaces in rules.xml --> + <xsl:value-of select="document('rules.xml',.)//rule[@target=$target][@entity='library']"/> + + </xsl:if> + </xsl:if> + </xsl:if> + </xsl:for-each> + + <!-- create libs rule for all libraries --> + <xsl:value-of select="$target"/> + <xsl:text>-libraries: </xsl:text> + + <!-- don't build unused libraries + <xsl:for-each select="//library"> + <xsl:if test="object[(ancestor-or-self::*)[@target = $target]]"> + + <xsl:variable name="conditions"> + <xsl:text>0</xsl:text> + <xsl:for-each select="(ancestor-or-self::*)[@condition!='']"> + <xsl:call-template name="resolve-condition"> + <xsl:with-param select="@condition" name="expression"/> + </xsl:call-template> + </xsl:for-each> + </xsl:variable> + <xsl:if test="$conditions=0"> + <xsl:text> $(ODIR)/</xsl:text> + <xsl:text>lib</xsl:text> + <xsl:value-of select="@name"/> + <xsl:choose> + <xsl:when test="@type='static'"> + <xsl:text>.a</xsl:text> + </xsl:when> + <xsl:when test="@type='dynamic'"> + <xsl:text>.so</xsl:text> + </xsl:when> + </xsl:choose> + </xsl:if> + </xsl:if> + </xsl:for-each> + --> + <xsl:text> </xsl:text> + + <!-- create exe rule for all executables --> + <xsl:value-of select="$target"/> + <xsl:text>-executables: </xsl:text> + + <xsl:for-each select="//executable"> + <xsl:if test="(ancestor-or-self::*)[@target = $target]"> + + <xsl:variable name="conditions"> + <xsl:text>0</xsl:text> + <xsl:for-each select="(ancestor-or-self::*)[@condition!='']"> + <xsl:call-template name="resolve-condition"> + <xsl:with-param select="@condition" name="expression"/> + </xsl:call-template> + </xsl:for-each> + </xsl:variable> + <xsl:if test="$conditions=0"> + <xsl:text> $(ODIR)/</xsl:text> + <xsl:value-of select="@name"/> + </xsl:if> + </xsl:if> + </xsl:for-each> + <xsl:text> </xsl:text> + + </xsl:template> + +</xsl:stylesheet> diff --git a/qemu/roms/openbios/config/xml/rules.xml b/qemu/roms/openbios/config/xml/rules.xml new file mode 100644 index 000000000..29a720a06 --- /dev/null +++ b/qemu/roms/openbios/config/xml/rules.xml @@ -0,0 +1,34 @@ +<rules> + <!-- host compiler build rules --> +<rule target="host" entity="executable"> + $(call quiet-command,$(HOSTCC) $(HOSTCFLAGS) -o $@ $^," HOSTCC $(TARGET_DIR)$@") +</rule> +<rule target="host" entity="object"> + $(call quiet-command,$(HOSTCC) $(HOSTCFLAGS) $(HOSTINCLUDES) -c -o $@ $<," HOSTCC $(TARGET_DIR)$@") +</rule> +<rule target="host" entity="object" extracflags="1"> + $(call quiet-command,$(HOSTCC) $(HOSTCFLAGS) $(HOSTINCLUDES)</rule> +<rule target="host" entity="object" extracflags="2"> -c -o $@ $<," HOSTCC $(TARGET_DIR)$@") +</rule> +<rule target="host" entity="library"> + $(call quiet--command,$(AR) cru $@ $^; $(RANLIB) $@," HOSTAR $(TARGET_DIR)$@") +</rule> +<rule target="host" entity="fcode"> + $(call quiet-command,$(TOKE) -o $@ $^," TOKE $(TARGET_DIR)$@") +</rule> + + <!-- target/cross compiler build rules --> +<rule target="target" entity="executable"> + $(call quiet-command,$(CC) $(CFLAGS) -o $@ $^," CC $(TARGET_DIR)$@") +</rule> +<rule target="target" entity="object"> + $(call quiet-command,$(CC) $$EXTRACFLAGS $(CFLAGS) $(INCLUDES) -c -o $@ $<," CC $(TARGET_DIR)$@") +</rule> +<rule target="target" entity="object" extracflags="1"> + $(call quiet-command,$(CC) $$EXTRACFLAGS $(CFLAGS) $(INCLUDES)</rule> +<rule target="target" entity="object" extracflags="2"> -c -o $@ $<," CC $(TARGET_DIR)$@") +</rule> +<rule target="target" entity="library"> + $(call quiet-command,$(AR) cru $@ $^; $(RANLIB) $@," AR $(TARGET_DIR)$@") +</rule> +</rules> diff --git a/qemu/roms/openbios/config/xml/util.xsl b/qemu/roms/openbios/config/xml/util.xsl new file mode 100644 index 000000000..3b583b9ac --- /dev/null +++ b/qemu/roms/openbios/config/xml/util.xsl @@ -0,0 +1,80 @@ +<?xml version="1.0" encoding="ISO-8859-15" ?> + +<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> + +<!-- get-dirname: get directory part of file $path--> + +<!-- call me with: + <xsl:param name="path"> + <xsl:for-each select="ancestor::build"> + <xsl:call-template name="get-dirname"> + <xsl:with-param select="@base" name="path"/> + </xsl:call-template> + </xsl:for-each> + </xsl:param> + --> + +<xsl:template name="get-dirname"> + <xsl:param name="path"/> + <xsl:choose> + <xsl:when test="contains($path, '/')"> + <xsl:choose> + <xsl:when test="substring($path, string-length($path)) != '/'"> + <xsl:call-template name="get-dirname"> + <xsl:with-param select="substring($path, 1, string-length($path)-1)" name="path"/> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="$path"/> + </xsl:otherwise> + </xsl:choose> + </xsl:when> + <xsl:otherwise> + <xsl:message terminate="yes"> + No valid relative path + </xsl:message> + </xsl:otherwise> + </xsl:choose> +</xsl:template> + +<!-- return value: 0=found, 1=not found --> +<xsl:template name="resolve-condition"> + <xsl:param name="expression"/> + <xsl:param name="confexpr">CONFIG_<xsl:value-of select="$expression"/></xsl:param> + + <xsl:choose> + <xsl:when test="$expression!=''"> + <xsl:variable name="value"><xsl:value-of select="document('config.xml',.)//option[@name=$confexpr]/attribute::value"/></xsl:variable> + <xsl:variable name="type"><xsl:value-of select="document('config.xml',.)//option[@name=$confexpr]/attribute::type"/></xsl:variable> + <xsl:choose> + <xsl:when test="$type='boolean'"> + <xsl:choose> + <xsl:when test="$value='true'"><xsl:text>0</xsl:text></xsl:when> + <xsl:when test="$value='false'"><xsl:text>1</xsl:text></xsl:when> + <!-- boolean but no value is false --> + <xsl:when test="$value=''"><xsl:text>1</xsl:text></xsl:when> + <xsl:otherwise> + <xsl:message terminate="yes">Error:<xsl:value-of select="$confexpr"/> has no valid value '<xsl:value-of select="$value"/>'.</xsl:message> + </xsl:otherwise> + + </xsl:choose> + </xsl:when> + <!-- if it doesn't exist, it is false --> + <xsl:when test="$type=''"><xsl:text>1</xsl:text></xsl:when> + <xsl:otherwise> + <xsl:message terminate="yes">Error:<xsl:value-of select="$confexpr"/> is not a boolean value ('<xsl:value-of select="$type"/>').</xsl:message> + </xsl:otherwise> + </xsl:choose> + <!-- debug - -> + <xsl:message> + <xsl:value-of select="$confexpr"/> = <xsl:value-of select="$value"/> + </xsl:message> + <!- - --> + </xsl:when> + <!-- if no expression is there we return true --> + <xsl:otherwise>0</xsl:otherwise> + </xsl:choose> +</xsl:template> + + +</xsl:stylesheet> diff --git a/qemu/roms/openbios/config/xml/xinclude.xsl b/qemu/roms/openbios/config/xml/xinclude.xsl new file mode 100644 index 000000000..5bcbf535e --- /dev/null +++ b/qemu/roms/openbios/config/xml/xinclude.xsl @@ -0,0 +1,43 @@ +<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> + + <!-- + Stefans own xinclude implementation. + We really don't want to bother the users with namespaces + --> + + <xsl:output method="xml" indent="yes"/> + <xsl:strip-space elements="*"/> + + <xsl:template match="node() | @*"> + <xsl:copy> + <xsl:apply-templates select="@* | node()"/> + </xsl:copy> + </xsl:template> + + +<!-- <xsl:template match="xi:include" xmlns:xi="http://www.w3.org/2001/XInclude"> --> + <xsl:template match="include"> + <xsl:variable name="href"><xsl:value-of select="@href"/> + </xsl:variable> + <xsl:for-each select="document(@href)"> + <!-- + <xsl:copy><xsl:copy-of select="@*"/> + <xsl:attribute name="base"> + <xsl:value-of select="$href"/> + </xsl:attribute> + <xsl:apply-templates select="node()" /> + </xsl:copy> + --> + <xsl:element name="{local-name(*)}" namespace="{namespace-uri(..)}"> + <xsl:copy-of select="*/@*"/> + <xsl:attribute name="base"> + <xsl:value-of select="$href"/> + </xsl:attribute> + <xsl:for-each select="*"> + <xsl:apply-templates/> + </xsl:for-each> + </xsl:element> + </xsl:for-each> + </xsl:template> + +</xsl:stylesheet> diff --git a/qemu/roms/openbios/drivers/Kconfig b/qemu/roms/openbios/drivers/Kconfig new file mode 100644 index 000000000..3bebc0293 --- /dev/null +++ b/qemu/roms/openbios/drivers/Kconfig @@ -0,0 +1,59 @@ + + +menu "Drivers" + +config DRIVER_PCI + bool "PCI driver" + default y + help + Builtin PCI driver + +config DEBUG_PCI + bool "Debug PCI driver" + default n + help + Debug PCI driver + +config DRIVER_IDE + depends X86 || AMD64 || PPC + bool "Legacy IDE" + default y + help + If you want to be able to boot from IDE, enable this option. + +config IDE_NUM_CHANNELS + depends DRIVER_IDE + int "Number of IDE channels to be probed" + default 4 + help + Number of IDE channels to be probed. This should be set to + one or two if you build OpenBIOS for the Total Impact BRIQ. + +config DEBUG_IDE + depends DRIVER_IDE + bool "Debug IDE driver" + default n + help + Debug IDE driver + +config DRIVER_USB + bool "USB Support" + default n + help + If you want to be able to use USB devices, enable this option. + +config DEBUG_USB + depends DRIVER_USB + bool "Debug USB driver" + default n + help + Debug USB driver + +config USB_HID + depends DRIVER_USB + bool "USB driver for HID devices" + default n + help + If you want to be able to use USB keyboard, enable this option. + +endmenu diff --git a/qemu/roms/openbios/drivers/adb_bus.c b/qemu/roms/openbios/drivers/adb_bus.c new file mode 100644 index 000000000..d67d1f1a4 --- /dev/null +++ b/qemu/roms/openbios/drivers/adb_bus.c @@ -0,0 +1,257 @@ +/* + * + * Open Hack'Ware BIOS ADB bus support, ported to OpenBIOS + * + * Copyright (c) 2005 Jocelyn Mayer + * Copyright (c) 2005 Stefan Reinauer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License V2 + * as published by the Free Software Foundation + * + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + */ + +#include "config.h" +#include "libopenbios/bindings.h" +#include "libc/vsprintf.h" + +#include "adb_bus.h" +#include "adb_kbd.h" +#include "adb_mouse.h" + +DECLARE_UNNAMED_NODE( adb, INSTALL_OPEN, sizeof(int)); + +static void +adb_initialize (int *idx) +{ + phandle_t ph=get_cur_dev(); + + push_str("adb"); + fword("device-type"); + + set_property(ph, "compatible", "adb", 4); + set_int_property(ph, "#address-cells", 1); + set_int_property(ph, "#size-cells", 0); +} + +static void +adb_open(int *idx) +{ + RET(-1); +} + +static void +adb_close(int *idx) +{ +} + +NODE_METHODS( adb ) = { + { NULL, adb_initialize }, + { "open", adb_open }, + { "close", adb_close }, +}; + +adb_bus_t *adb_bus_new (void *host, + int (*req)(void *host, const uint8_t *snd_buf, + int len, uint8_t *rcv_buf)) +{ + adb_bus_t *new; + + new = malloc(sizeof(adb_bus_t)); + if (new == NULL) + return NULL; + new->host = host; + new->req = req; + + return new; +} + +/* Check and relocate all ADB devices as suggested in + * ADB_manager Apple documentation + */ + +int adb_bus_init (char *path, adb_bus_t *bus) +{ + char buf[64]; + uint8_t buffer[ADB_BUF_SIZE]; + uint8_t adb_addresses[16] = + { 8, 9, 10, 11, 12, 13, 14, -1, -1, -1, -1, -1, -1, -1, 0, }; + adb_dev_t tmp_device, **cur; + int address; + int reloc = 0, next_free = 7; + int keep; + + snprintf(buf, sizeof(buf), "%s/adb", path); + REGISTER_NAMED_NODE( adb, buf); + /* Reset the bus */ + // ADB_DPRINTF("\n"); + adb_reset(bus); + cur = &bus->devices; + memset(&tmp_device, 0, sizeof(adb_dev_t)); + tmp_device.bus = bus; + for (address = 1; address < 8 && adb_addresses[reloc] > 0;) { + if (address == ADB_RES) { + /* Reserved */ + address++; + continue; + } + //ADB_DPRINTF("Check device on ADB address %d\n", address); + tmp_device.addr = address; + switch (adb_reg_get(&tmp_device, 3, buffer)) { + case 0: + //ADB_DPRINTF("No device on ADB address %d\n", address); + /* Register this address as free */ + if (adb_addresses[next_free] != 0) + adb_addresses[next_free++] = address; + /* Check next ADB address */ + address++; + break; + case 2: + /* One device answered : + * make it available and relocate it to a free address + */ + if (buffer[0] == ADB_CHADDR) { + /* device self test failed */ + ADB_DPRINTF("device on ADB address %d self-test failed " + "%02x %02x %02x\n", address, + buffer[0], buffer[1], buffer[2]); + keep = 0; + } else { + //ADB_DPRINTF("device on ADB address %d self-test OK\n", + // address); + keep = 1; + } + ADB_DPRINTF("Relocate device on ADB address %d to %d (%d)\n", + address, adb_addresses[reloc], reloc); + buffer[0] = ((buffer[0] & 0x40) & ~0x90) | adb_addresses[reloc]; + if (keep == 1) + buffer[0] |= 0x20; + buffer[1] = ADB_CHADDR_NOCOLL; + if (adb_reg_set(&tmp_device, 3, buffer, 2) < 0) { + ADB_DPRINTF("ADB device relocation failed\n"); + return -1; + } + if (keep == 1) { + *cur = malloc(sizeof(adb_dev_t)); + if (*cur == NULL) { + return -1; + } + (*cur)->type = address; + (*cur)->bus = bus; + (*cur)->addr = adb_addresses[reloc++]; + /* Flush buffers */ + adb_flush(*cur); + switch ((*cur)->type) { + case ADB_PROTECT: + ADB_DPRINTF("Found one protected device\n"); + break; + case ADB_KEYBD: + ADB_DPRINTF("Found one keyboard on address %d\n", address); + adb_kbd_new(buf, *cur); + break; + case ADB_MOUSE: + ADB_DPRINTF("Found one mouse on address %d\n", address); + adb_mouse_new(buf, *cur); + break; + case ADB_ABS: + ADB_DPRINTF("Found one absolute positioning device\n"); + break; + case ADB_MODEM: + ADB_DPRINTF("Found one modem\n"); + break; + case ADB_RES: + ADB_DPRINTF("Found one ADB res device\n"); + break; + case ADB_MISC: + ADB_DPRINTF("Found one ADB misc device\n"); + break; + } + cur = &((*cur)->next); + } + break; + case 1: + case 3 ... 7: + /* SHOULD NOT HAPPEN : register 3 is always two bytes long */ + ADB_DPRINTF("Invalid returned len for ADB register 3\n"); + return -1; + case -1: + /* ADB ERROR */ + ADB_DPRINTF("error gettting ADB register 3\n"); + return -1; + } + } + + return 0; +} + +int adb_cmd (adb_dev_t *dev, uint8_t cmd, uint8_t reg, + uint8_t *buf, int len) +{ + uint8_t adb_send[ADB_BUF_SIZE], adb_rcv[ADB_BUF_SIZE]; + + //ADB_DPRINTF("cmd: %d reg: %d len: %d\n", cmd, reg, len); + if (dev->bus == NULL || dev->bus->req == NULL) { + ADB_DPRINTF("ERROR: invalid bus !\n"); + for (;;); + } + /* Sanity checks */ + if (cmd != ADB_LISTEN && len != 0) { + /* No buffer transmitted but for LISTEN command */ + ADB_DPRINTF("in buffer for cmd %d\n", cmd); + return -1; + } + if (cmd == ADB_LISTEN && ((len < 2 || len > 8) || buf == NULL)) { + /* Need a buffer with a regular register size for LISTEN command */ + ADB_DPRINTF("no/invalid buffer for ADB_LISTEN (%d)\n", len); + return -1; + } + if ((cmd == ADB_TALK || cmd == ADB_LISTEN) && reg > 3) { + /* Need a valid register number for LISTEN and TALK commands */ + ADB_DPRINTF("invalid reg for TALK/LISTEN command (%d %d)\n", cmd, reg); + return -1; + } + switch (cmd) { + case ADB_SEND_RESET: + adb_send[0] = ADB_SEND_RESET; + break; + case ADB_FLUSH: + adb_send[0] = (dev->addr << 4) | ADB_FLUSH; + break; + case ADB_LISTEN: + memcpy(adb_send + 1, buf, len); + /* No break here */ + case ADB_TALK: + adb_send[0] = (dev->addr << 4) | cmd | reg; + break; + } + memset(adb_rcv, 0, ADB_BUF_SIZE); + len = (*dev->bus->req)(dev->bus->host, adb_send, len + 1, adb_rcv); +#ifdef DEBUG_ADB + //printk("%x %x %x %x\n", adb_rcv[0], adb_rcv[1], adb_rcv[2], adb_rcv[3]); +#endif + switch (len) { + case 0: + /* No data */ + break; + case 2 ... 8: + /* Register transmitted */ + if (buf != NULL) + memcpy(buf, adb_rcv, len); + break; + default: + /* Should never happen */ + //ADB_DPRINTF("Cmd %d returned %d bytes !\n", cmd, len); + return -1; + } + //ADB_DPRINTF("retlen: %d\n", len); + + return len; +} diff --git a/qemu/roms/openbios/drivers/adb_bus.h b/qemu/roms/openbios/drivers/adb_bus.h new file mode 100644 index 000000000..205b37536 --- /dev/null +++ b/qemu/roms/openbios/drivers/adb_bus.h @@ -0,0 +1,104 @@ +/* + * ADB bus definitions for Open Hack'Ware + * + * Copyright (c) 2004-2005 Jocelyn Mayer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License V2 + * as published by the Free Software Foundation + * + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + */ + +typedef struct adb_bus_t adb_bus_t; +typedef struct adb_dev_t adb_dev_t; + +#define ADB_BUF_SIZE 8 +struct adb_bus_t { + void *host; + int (*req)(void *host, const uint8_t *snd_buf, int len, uint8_t *rcv_buf); + adb_dev_t *devices; +}; + +struct adb_dev_t { + adb_dev_t *next; + adb_bus_t *bus; + uint8_t addr; + uint8_t type; + void *state; +}; + +#define ADB_BUF_SIZE 8 + +/* ADB commands */ +enum { + ADB_SEND_RESET = 0x00, + ADB_FLUSH = 0x01, + ADB_LISTEN = 0x08, + ADB_TALK = 0x0C, +}; +/* ADB default IDs before relocation */ +enum { + ADB_PROTECT = 0x01, + ADB_KEYBD = 0x02, + ADB_MOUSE = 0x03, + ADB_ABS = 0x04, + ADB_MODEM = 0x05, + ADB_RES = 0x06, + ADB_MISC = 0x07, +}; +/* ADB special device handlers IDs */ +enum { + ADB_CHADDR = 0x00, + ADB_CHADDR_ACTIV = 0xFD, + ADB_CHADDR_NOCOLL = 0xFE, + ADB_SELF_TEST = 0xFF, +}; + +int adb_cmd (adb_dev_t *dev, uint8_t cmd, uint8_t reg, + uint8_t *buf, int len); +void adb_bus_reset (adb_bus_t *bus); +adb_bus_t *adb_bus_new (void *host, + int (*req)(void *host, const uint8_t *snd_buf, + int len, uint8_t *rcv_buf)); +int adb_bus_init (char *path, adb_bus_t *bus); + +static inline int adb_reset (adb_bus_t *bus) +{ + adb_dev_t fake_device; + + memset(&fake_device, 0, sizeof(adb_dev_t)); + fake_device.bus = bus; + + return adb_cmd(&fake_device, ADB_SEND_RESET, 0, NULL, 0); +} + +static inline int adb_flush (adb_dev_t *dev) +{ + return adb_cmd(dev, ADB_FLUSH, 0, NULL, 0); +} + +static inline int adb_reg_get (adb_dev_t *dev, uint8_t reg, uint8_t *buf) +{ + return adb_cmd(dev, ADB_TALK, reg, buf, 0); +} + +static inline int adb_reg_set (adb_dev_t *dev, uint8_t reg, + uint8_t *buf, int len) +{ + return adb_cmd(dev, ADB_LISTEN, reg, buf, len); +} + +#ifdef DEBUG_ADB +#define ADB_DPRINTF(fmt, args...) \ +do { printk("ADB - %s: " fmt, __func__ , ##args); } while (0) +#else +#define ADB_DPRINTF(fmt, args...) do { } while (0) +#endif diff --git a/qemu/roms/openbios/drivers/adb_kbd.c b/qemu/roms/openbios/drivers/adb_kbd.c new file mode 100644 index 000000000..be6099a03 --- /dev/null +++ b/qemu/roms/openbios/drivers/adb_kbd.c @@ -0,0 +1,595 @@ +/* + * + * Open Hack'Ware BIOS ADB keyboard support, ported to OpenBIOS + * + * Copyright (c) 2005 Jocelyn Mayer + * Copyright (c) 2005 Stefan Reinauer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License V2 + * as published by the Free Software Foundation + * + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + */ + +#include "config.h" +#include "libopenbios/bindings.h" +#include "libc/byteorder.h" +#include "libc/vsprintf.h" +#include "kbd.h" + +#include "adb_bus.h" +#include "adb_kbd.h" + +DECLARE_UNNAMED_NODE( keyboard, INSTALL_OPEN, sizeof(int)); + +static void +keyboard_open(int *idx) +{ + RET(-1); +} + +static void +keyboard_close(int *idx) +{ +} + +static void keyboard_read(void); +static void keyboard_getkeymap(void); + +NODE_METHODS( keyboard ) = { + { "open", keyboard_open }, + { "close", keyboard_close }, + { "read", keyboard_read }, + { "get-key-map", keyboard_getkeymap }, +}; + +/* VT100 escape sequences */ + +enum { + KEY_UP = 0, KEY_DOWN, KEY_RIGHT, KEY_LEFT, KEY_PAGE_UP, KEY_PAGE_DOWN, + KEY_DELETE, KEY_HOME, KEY_END, KEY_HELP, + KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6, KEY_F7, KEY_F8, + KEY_F9, KEY_F10, KEY_F11, KEY_F12, KEY_F13, KEY_F14, KEY_F15, KEY_F16 +}; + +#define ADB_MAX_SEQUENCE_LEN 16 + +static const char *ADB_sequences[] = { + [KEY_UP] = "A[", + [KEY_DOWN] = "B[", + [KEY_RIGHT] = "C[", + [KEY_LEFT] = "D[", + [KEY_PAGE_UP] = "~5[", + [KEY_PAGE_DOWN] = "~6[", + [KEY_DELETE] = "~3[", + [KEY_HOME] = "HO", + [KEY_END] = "FO", + [KEY_HELP] = "~2[", + [KEY_F1] = "PO", + [KEY_F2] = "QO", + [KEY_F3] = "RO", + [KEY_F4] = "SO", + [KEY_F5] = "~15[", + [KEY_F6] = "~17[", + [KEY_F7] = "~18[", + [KEY_F8] = "~19[", + [KEY_F9] = "~20[", + [KEY_F10] = "~21[", + [KEY_F11] = "~23[", + [KEY_F12] = "~24[", + [KEY_F13] = "~25[", + [KEY_F14] = "~26[", + [KEY_F15] = "~28[", + [KEY_F15] = "~29[", +}; + +/* ADB US keyboard translation map */ + +static const keymap_t ADB_kbd_us[] = { + /* 0x00 */ + { KBD_SH_CAPS, { 0x61, 0x41, 0x01, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, }, }, + { KBD_SH_CAPS, { 0x73, 0x53, 0x13, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, }, }, + { KBD_SH_CAPS, { 0x64, 0x44, 0x04, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, }, }, + { KBD_SH_CAPS, { 0x66, 0x46, 0x06, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, }, }, + { KBD_SH_CAPS, { 0x68, 0x48, 0x08, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, }, }, + { KBD_SH_CAPS, { 0x67, 0x47, 0x07, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, }, }, + { KBD_SH_CAPS, { 0x7A, 0x5A, 0x1A, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, }, }, + { KBD_SH_CAPS, { 0x78, 0x58, 0x18, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, }, }, + /* 0x08 */ + { KBD_SH_CAPS, { 0x63, 0x43, 0x03, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, }, }, + { KBD_SH_CAPS, { 0x76, 0x56, 0x16, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, }, }, + { KBD_SH_CAPS, { 0x60, 0x40, 0x00, -1, -1, -1, -1, -1, /* ? */ + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, }, }, + { KBD_SH_CAPS, { 0x62, 0x42, 0x02, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, }, }, + { KBD_SH_CAPS, { 0x71, 0x51, 0x11, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, }, }, + { KBD_SH_CAPS, { 0x77, 0x57, 0x17, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, }, }, + { KBD_SH_CAPS, { 0x65, 0x45, 0x05, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, }, }, + { KBD_SH_CAPS, { 0x72, 0x52, 0x12, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, }, }, + /* 0x10 */ + { KBD_SH_CAPS, { 0x79, 0x59, 0x19, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, }, }, + { KBD_SH_CAPS, { 0x74, 0x54, 0x14, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, }, }, + { KBD_SH_CAPS, { 0x31, 0x21, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, }, }, + { KBD_SH_CAPS, { 0x32, 0x40, 0x00, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, }, }, + { KBD_SH_CAPS, { 0x33, 0x23, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, }, }, + { KBD_SH_CAPS, { 0x34, 0x24, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, }, }, + { KBD_SH_CAPS, { 0x36, 0x5E, 0x1E, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, }, }, + { KBD_SH_CAPS, { 0x35, 0x25, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, }, }, + /* 0x18 */ + { KBD_SH_CAPS, { 0x3D, 0x2B, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, }, }, + { KBD_SH_CAPS, { 0x39, 0x28, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, }, }, + { KBD_SH_CAPS, { 0x37, 0x26, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, }, }, + { KBD_SH_CAPS, { 0x2D, 0x5F, 0x1F, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, }, }, + { KBD_SH_CAPS, { 0x38, 0x2A, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, }, }, + { KBD_SH_CAPS, { 0x30, 0x29, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, }, }, + { KBD_SH_CAPS, { 0x5D, 0x7D, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, }, }, + { KBD_SH_CAPS, { 0x6F, 0x4F, 0x0F, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, }, }, + /* 0x20 */ + { KBD_SH_CAPS, { 0x75, 0x55, 0x15, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, }, }, + { KBD_SH_CAPS, { 0x5B, 0x7B, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, }, }, + { KBD_SH_CAPS, { 0x69, 0x49, 0x09, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, }, }, + { KBD_SH_CAPS, { 0x70, 0x50, 0x10, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, }, }, + { KBD_MOD_MAP(0x0D), }, + { KBD_SH_CAPS, { 0x6C, 0x4C, 0x0C, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, }, }, + { KBD_SH_CAPS, { 0x6A, 0x4A, 0x0A, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, }, }, + { KBD_SH_CAPS, { 0x27, 0x22, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, }, }, + /* 0x28 */ + { KBD_SH_CAPS, { 0x6B, 0x4B, 0x0B, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, }, }, + { KBD_SH_CAPS, { 0x3B, 0x3A, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, }, }, + { KBD_SH_CAPS, { 0x5C, 0x7C, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, }, }, + { KBD_SH_CAPS, { 0x2C, 0x3C, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, }, }, + { KBD_SH_CAPS, { 0x2F, 0x3F, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, }, }, + { KBD_SH_CAPS, { 0x6E, 0x4E, 0x0E, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, }, }, + { KBD_SH_CAPS, { 0x6D, 0x4D, 0x0D, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, }, }, + { KBD_SH_CAPS, { 0x2E, 0x3E, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, }, }, + /* 0x30 : tab */ + { KBD_MOD_MAP(0x09), }, + /* 0x31 : space */ + { KBD_MOD_MAP(0x20), }, + /* 0x32 : '<' '>' */ + { KBD_SH_CAPS, { 0x3C, 0x3E, -1, -1, -1, -1, -1, -1, /* ? */ + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, }, }, + /* 0x33 : backspace */ + { KBD_MOD_MAP(0x08), }, + { KBD_MAP_NONE, }, + /* 0x35 : ESC */ + { KBD_MOD_MAP(0x1B), }, + /* 0x36 : control */ + { KBD_MOD_MAP_LCTRL, }, + /* 0x37 : command */ + { KBD_MOD_MAP_LCMD, }, + /* 0x38 : left shift */ + { KBD_MOD_MAP_LSHIFT, }, + /* 0x39 : caps-lock */ + { KBD_MOD_MAP_CAPS, }, + /* 0x3A : option */ + { KBD_MOD_MAP_LOPT, }, + /* 0x3B : left */ + { KBD_MOD_MAP(KBD_SEQUENCE(KEY_LEFT)), }, + /* 0x3C : right */ + { KBD_MOD_MAP(KBD_SEQUENCE(KEY_RIGHT)), }, + /* 0x3D : down */ + { KBD_MOD_MAP(KBD_SEQUENCE(KEY_DOWN)), }, + /* 0x3E : up */ + { KBD_MOD_MAP(KBD_SEQUENCE(KEY_UP)), }, + { KBD_MAP_NONE, }, + /* 0x40 */ + { KBD_MAP_NONE, }, + { KBD_SH_NUML, { 0x7F, 0x2E, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, }, }, + { KBD_MAP_NONE, }, + { KBD_SH_NONE, { 0x2A, 0x2A, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, }, }, + { KBD_MAP_NONE, }, + { KBD_SH_NONE, { 0x2B, 0x2B, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, }, }, + { KBD_MAP_NONE, }, + { KBD_MOD_MAP(0x7F), }, + /* 0x48 */ + { KBD_MAP_NONE, }, + { KBD_MAP_NONE, }, + { KBD_MAP_NONE, }, + { KBD_SH_NONE, { 0x2F, 0x2F, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, }, }, + { KBD_MOD_MAP(0x0D), }, + { KBD_MAP_NONE, }, + { KBD_SH_NONE, { 0x2D, 0x2D, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, }, }, + { KBD_MAP_NONE, }, + /* 0x50 */ + { KBD_MAP_NONE, }, + { KBD_SH_NONE, { 0x3D, 0x3D, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, }, }, + { KBD_SH_NUML, { -1, 0x30, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, }, }, + { KBD_SH_NUML, { -1, 0x31, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, }, }, + { KBD_SH_NUML, { -1, 0x32, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, }, }, + { KBD_SH_NUML, { -1, 0x33, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, }, }, + { KBD_SH_NUML, { -1, 0x34, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, }, }, + { KBD_SH_NUML, { -1, 0x35, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, }, }, + /* 0x58 */ + { KBD_SH_NUML, { -1, 0x36, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, }, }, + { KBD_SH_NUML, { -1, 0x37, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, }, }, + { KBD_MAP_NONE, }, + { KBD_SH_NUML, { -1, 0x38, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, }, }, + { KBD_SH_NUML, { -1, 0x39, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, }, }, + { KBD_MAP_NONE, }, + { KBD_MOD_MAP(0x2F), }, + { KBD_MAP_NONE, }, + /* 0x60 : F5 */ + { KBD_MOD_MAP(KBD_SEQUENCE(KEY_F5)), }, + /* 0x61 : F6 */ + { KBD_MOD_MAP(KBD_SEQUENCE(KEY_F6)), }, + /* 0x62 : F7 */ + { KBD_MOD_MAP(KBD_SEQUENCE(KEY_F7)), }, + /* 0x63 : F3 */ + { KBD_MOD_MAP(KBD_SEQUENCE(KEY_F3)), }, + /* 0x64 : F8 */ + { KBD_MOD_MAP(KBD_SEQUENCE(KEY_F8)), }, + /* 0x65 : F9 */ + { KBD_MOD_MAP(KBD_SEQUENCE(KEY_F9)), }, + { KBD_MAP_NONE, }, + /* 0x67 : F11 */ + { KBD_MOD_MAP(KBD_SEQUENCE(KEY_F11)), }, + /* 0x68 */ + { KBD_MAP_NONE, }, + /* 0x69 : F13 */ + { KBD_MOD_MAP(KBD_SEQUENCE(KEY_F13)), }, + { KBD_MAP_NONE, }, + /* 0x6B : F14 */ + { KBD_MOD_MAP(KBD_SEQUENCE(KEY_F14)), }, + { KBD_MAP_NONE, }, + /* 0x6D : F10 */ + { KBD_MOD_MAP(KBD_SEQUENCE(KEY_F10)), }, + { KBD_MAP_NONE, }, + /* 0x6F : F12 */ + { KBD_MOD_MAP(KBD_SEQUENCE(KEY_F12)), }, + /* 0x70 */ + { KBD_MAP_NONE, }, + /* 0x71 : F15 */ + { KBD_MOD_MAP(KBD_SEQUENCE(KEY_F15)), }, + /* 0x72 : help */ + { KBD_MOD_MAP(KBD_SEQUENCE(KEY_HELP)), }, + /* 0x73 : home */ + { KBD_MOD_MAP(KBD_SEQUENCE(KEY_HOME)), }, + /* 0x74 : page up */ + { KBD_MOD_MAP(KBD_SEQUENCE(KEY_PAGE_UP)), }, + /* 0x75 : del */ + { KBD_MOD_MAP(KBD_SEQUENCE(KEY_DELETE)), }, + /* 0x76 : F4 */ + { KBD_MOD_MAP(KBD_SEQUENCE(KEY_F4)), }, + /* 0x77 : end */ + { KBD_MOD_MAP(KBD_SEQUENCE(KEY_END)), }, + /* 0x78 : F2 */ + { KBD_MOD_MAP(KBD_SEQUENCE(KEY_F2)), }, + /* 0x79 : page down */ + { KBD_MOD_MAP(KBD_SEQUENCE(KEY_PAGE_UP)), }, + /* 0x7A : F1 */ + { KBD_MOD_MAP(KBD_SEQUENCE(KEY_F1)), }, + /* 0x7B : right shift */ + { KBD_MOD_MAP_RSHIFT, }, + /* 0x7C : right option */ + { KBD_MOD_MAP_ROPT, }, + /* 0x7D : right control */ + { KBD_MOD_MAP_RCTRL, }, + { KBD_MAP_NONE, }, + /* 0x7F : power */ + { KBD_MAP_NONE, }, +}; + +typedef struct adb_kbd_t adb_kbd_t; +struct adb_kbd_t { + kbd_t kbd; + int next_key; + char sequence[ADB_MAX_SEQUENCE_LEN]; + int len; + char keytable[32]; +}; + +static adb_dev_t *my_adb_dev = NULL; + +static int adb_kbd_read (void *private) +{ + uint8_t buffer[ADB_BUF_SIZE]; + adb_dev_t *dev = private; + adb_kbd_t *kbd; + int key; + int ret; + + kbd = dev->state; + + if (kbd->len > 0) { + ret = kbd->sequence[kbd->len-- - 1]; + ADB_DPRINTF("Buffered %d (%02x)\n", ret, ret); + return ret; + } + + /* Get saved state */ + ret = -1; + for (key = -1; key == -1; ) { + if (kbd->next_key != -1) { + key = kbd->next_key; + kbd->next_key = -1; + } else { + if (adb_reg_get(dev, 0, buffer) != 2) + break; + kbd->next_key = buffer[1] == 0xFF ? -1 : buffer[1]; + key = buffer[0]; + } + ret = kbd_translate_key(&kbd->kbd, key & 0x7F, key >> 7, kbd->sequence); + if (ret > 0) { + kbd->len = ret; + ret = kbd->sequence[kbd->len-- - 1]; + } + + ADB_DPRINTF("Translated %d (%02x) into %d (%02x)\n", + key, key, ret, ret); + } + + return ret; +} + + +void *adb_kbd_new (char *path, void *private) +{ + char buf[64]; + int props[1]; + phandle_t ph, aliases; + adb_kbd_t *kbd; + adb_dev_t *dev = private; + kbd = (adb_kbd_t*)malloc(sizeof(adb_kbd_t)); + if (kbd != NULL) { + memset(kbd, 0, sizeof(adb_kbd_t)); + kbd_set_keymap(&kbd->kbd, sizeof(ADB_kbd_us) / sizeof(keymap_t), + ADB_kbd_us, ADB_sequences); + kbd->next_key = -1; + kbd->len = 0; + + /* Debugging BootX: the lines below force get-key-map to report that + * cmd-V is being held down, which forces BootX to run in verbose mode + * for debugging. + * + * TODO: if we can find a mapping between the get-key-map bitmap and + * ADB scancodes, the keyboard driver should be altered to update this + * accordingly. + */ + + /* + kbd->keytable[3] = 0x40; + kbd->keytable[28] = 0x10; + */ + + dev->state = kbd; + my_adb_dev = dev; + } + + snprintf(buf, sizeof(buf), "%s/keyboard", path); + REGISTER_NAMED_NODE( keyboard, buf); + + ph = find_dev(buf); + + set_property(ph, "device_type", "keyboard", 9); + props[0] = __cpu_to_be32(dev->addr); + set_property(ph, "reg", (char *)&props, sizeof(props)); + + aliases = find_dev("/aliases"); + set_property(aliases, "adb-keyboard", buf, strlen(buf) + 1); + + return kbd; +} + +/* ( addr len -- actual ) */ +static void keyboard_read(void) +{ + char *addr; + int len, key, i; + len=POP(); + addr=(char *)cell2pointer(POP()); + + for (i = 0; i < len; i++) { + key = adb_kbd_read(my_adb_dev); + if (key == -1 || key == -2) + break; + *addr++ = (char)key; + } + PUSH(i); +} + +/* ( -- keymap ) (?) */ +/* should return a pointer to an array with 32 bytes (256 bits) */ +static void keyboard_getkeymap(void) +{ + adb_kbd_t *kbd = my_adb_dev->state; + + PUSH( pointer2cell(kbd->keytable) ); +} diff --git a/qemu/roms/openbios/drivers/adb_kbd.h b/qemu/roms/openbios/drivers/adb_kbd.h new file mode 100644 index 000000000..b219c12e7 --- /dev/null +++ b/qemu/roms/openbios/drivers/adb_kbd.h @@ -0,0 +1,22 @@ +/* + * + * Open Hack'Ware BIOS ADB keyboard support, ported to OpenBIOS + * + * Copyright (c) 2005 Jocelyn Mayer + * Copyright (c) 2005 Stefan Reinauer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License V2 + * as published by the Free Software Foundation + * + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + */ + +void *adb_kbd_new (char *path, void *private); diff --git a/qemu/roms/openbios/drivers/adb_mouse.c b/qemu/roms/openbios/drivers/adb_mouse.c new file mode 100644 index 000000000..b94a34420 --- /dev/null +++ b/qemu/roms/openbios/drivers/adb_mouse.c @@ -0,0 +1,67 @@ +/* + * + * Open Hack'Ware BIOS ADB mouse support, ported to OpenBIOS + * + * Copyright (c) 2005 Jocelyn Mayer + * Copyright (c) 2005 Stefan Reinauer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License V2 + * as published by the Free Software Foundation + * + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + */ + +#include "config.h" +#include "libopenbios/bindings.h" +#include "libc/byteorder.h" +#include "libc/vsprintf.h" + +#include "adb_bus.h" +#include "adb_mouse.h" + +DECLARE_UNNAMED_NODE( mouse, INSTALL_OPEN, sizeof(int)); + +static void +mouse_open(int *idx) +{ + RET(-1); +} + +static void +mouse_close(int *idx) +{ +} + +NODE_METHODS( mouse ) = { + { "open", mouse_open }, + { "close", mouse_close }, +}; + +void adb_mouse_new (char *path, void *private) +{ + char buf[64]; + int props[1]; + phandle_t ph, aliases; + adb_dev_t *dev = private; + + snprintf(buf, sizeof(buf), "%s/mouse", path); + REGISTER_NAMED_NODE( mouse, buf); + + ph = find_dev(buf); + + set_property(ph, "device_type", "mouse", 6); + props[0] = __cpu_to_be32(dev->addr); + set_property(ph, "reg", (char *)&props, sizeof(props)); + set_int_property(ph, "#buttons", 3); + + aliases = find_dev("/aliases"); + set_property(aliases, "adb-mouse", buf, strlen(buf) + 1); +} diff --git a/qemu/roms/openbios/drivers/adb_mouse.h b/qemu/roms/openbios/drivers/adb_mouse.h new file mode 100644 index 000000000..1f37dac7c --- /dev/null +++ b/qemu/roms/openbios/drivers/adb_mouse.h @@ -0,0 +1,22 @@ +/* + * + * Open Hack'Ware BIOS ADB mouse support, ported to OpenBIOS + * + * Copyright (c) 2005 Jocelyn Mayer + * Copyright (c) 2005 Stefan Reinauer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License V2 + * as published by the Free Software Foundation + * + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + */ + +void adb_mouse_new (char *path, void *private); diff --git a/qemu/roms/openbios/drivers/build.xml b/qemu/roms/openbios/drivers/build.xml new file mode 100644 index 000000000..bd1abd358 --- /dev/null +++ b/qemu/roms/openbios/drivers/build.xml @@ -0,0 +1,41 @@ +<build> + + <library name="drivers" type="static" target="target"> + <object source="pci.c" condition="DRIVER_PCI"/> + <object source="pci_database.c" condition="DRIVER_PCI"/> + <object source="ide.c" condition="DRIVER_IDE"/> + <object source="timer.c" condition="DRIVER_IDE"/> + <object source="kbd.c" condition="DRIVER_ADB"/> + <object source="adb_bus.c" condition="DRIVER_ADB"/> + <object source="adb_kbd.c" condition="DRIVER_ADB"/> + <object source="adb_mouse.c" condition="DRIVER_ADB"/> + <object source="cuda.c" condition="DRIVER_ADB"/> + <object source="floppy.c" condition="DRIVER_FLOPPY"/> + <object source="iommu.c" condition="DRIVER_SBUS"/> + <object source="sbus.c" condition="DRIVER_SBUS"/> + <object source="esp.c" condition="DRIVER_ESP"/> + <object source="obio.c" condition="DRIVER_OBIO"/> + <object source="vga_load_regs.c" condition="DRIVER_VGA"/> + <object source="vga_set_mode.c" condition="DRIVER_VGA"/> + <object source="macio.c" condition="DRIVER_MACIO"/> + <object source="pc_kbd.c" condition="DRIVER_PC_KBD"/> + <object source="pc_serial.c" condition="DRIVER_PC_SERIAL"/> + <object source="escc.c" condition="DRIVER_ESCC"/> + <object source="fw_cfg.c" condition="DRIVER_FW_CFG"/> + <object source="usb.c" condition="DRIVER_USB"/> + <object source="usbhid.c" condition="USB_HID"/> + <object source="usbohci.c" condition="DRIVER_USB"/> + <object source="usbohci_rh.c" condition="DRIVER_USB"/> + </library> + + <dictionary name="openbios" target="forth"> + <object source="pci.fs" condition="DRIVER_PCI"/> + <object source="sbus.fs" condition="DRIVER_SBUS"/> + <object source="esp.fs" condition="DRIVER_ESP"/> + </dictionary> + + <fcode source="tcx.fs" name="QEMU,tcx.bin" condition="DRIVER_SBUS" /> + <fcode source="cgthree.fs" name="QEMU,cgthree.bin" condition="DRIVER_SBUS" /> + <fcode source="vga.fs" name="QEMU,VGA.bin" condition="DRIVER_VGA" /> + +</build> diff --git a/qemu/roms/openbios/drivers/cgthree.fs b/qemu/roms/openbios/drivers/cgthree.fs new file mode 100644 index 000000000..aa0c90cdd --- /dev/null +++ b/qemu/roms/openbios/drivers/cgthree.fs @@ -0,0 +1,197 @@ +\ +\ Fcode payload for QEMU CG3 graphics card +\ +\ This is the Forth source for an Fcode payload to initialise +\ the QEMU CG3 graphics card. +\ +\ (C) Copyright 2013 Mark Cave-Ayland +\ + +fcode-version3 + +\ +\ Instead of using fixed values for the framebuffer address and the width +\ and height, grab the ones passed in by QEMU/generated by OpenBIOS +\ + +: (find-xt) \ ( str len -- xt | -1 ) + $find if + exit + else + 2drop + -1 + then +; + +: (is-openbios) \ ( -- true | false ) + " openbios-video-width" (find-xt) -1 <> if + -1 + else + 0 + then +; + +" openbios-video-width" (find-xt) cell+ value openbios-video-width-xt +" openbios-video-height" (find-xt) cell+ value openbios-video-height-xt +" depth-bits" (find-xt) cell+ value depth-bits-xt +" line-bytes" (find-xt) cell+ value line-bytes-xt +" debug-type" (find-xt) value debug-type-xt + +: openbios-video-width + (is-openbios) if + openbios-video-width-xt @ + else + h# 400 + then +; + +: openbios-video-height + (is-openbios) if + openbios-video-height-xt @ + else + h# 300 + then +; + +: depth-bits + (is-openbios) if + depth-bits-xt @ + else + h# 8 + then +; + +: line-bytes + (is-openbios) if + line-bytes-xt @ + else + h# 400 + then +; + +: debug-type debug-type-xt execute ; + +\ +\ Registers +\ + +h# 400000 constant cg3-off-dac +h# 20 constant /cg3-off-dac + +h# 800000 constant cg3-off-fb +h# c0000 constant /cg3-off-fb + +: >cg3-reg-spec ( offset size -- encoded-reg ) + >r 0 my-address d+ my-space encode-phys r> encode-int encode+ +; + +: cg3-reg + \ A real cg3 rom appears to just map the entire region with a + \ single entry + h# 0 h# 1000000 >cg3-reg-spec + " reg" property +; + +: do-map-in ( offset size -- virt ) + >r my-space r> " map-in" $call-parent +; + +: do-map-out ( virt size ) + " map-out" $call-parent +; + +\ +\ DAC +\ + +-1 value cg3-dac +-1 value fb-addr + +: dac! ( data reg# -- ) + cg3-dac + c! +; + +external + +: color! ( r g b c# -- ) + 0 dac! ( r g b ) + swap rot ( b g r ) + 4 dac! ( b g ) + 4 dac! ( b ) + 4 dac! ( ) +; + +headerless + +\ +\ Mapping +\ + +: dac-map + cg3-off-dac /cg3-off-dac do-map-in to cg3-dac +; + +: fb-map + cg3-off-fb h# c0000 do-map-in to fb-addr +; + +: map-regs + dac-map fb-map +; + +\ +\ Installation +\ + +" cgthree" device-name +" display" device-type +" SUNW,501-1415" model + +: qemu-cg3-driver-install ( -- ) + cg3-dac -1 = if + map-regs + + \ Initial pallette taken from Sun's "Writing FCode Programs" + h# ff h# ff h# ff h# 0 color! \ Background white + h# 0 h# 0 h# 0 h# ff color! \ Foreground black + h# 64 h# 41 h# b4 h# 1 color! \ SUN-blue logo + + fb-addr to frame-buffer-adr + default-font set-font + + frame-buffer-adr encode-int " address" property + + openbios-video-width openbios-video-height over char-width / over char-height / + fb8-install + then +; + +: qemu-cg3-driver-init + + cg3-reg + + openbios-video-height encode-int " height" property + openbios-video-width encode-int " width" property + line-bytes encode-int " linebytes" property + + h# 39 encode-int 0 encode-int encode+ " intr" property + + \ Monitor sense. Some searching suggests that this is + \ 5 for 1024x768 and 7 for 1152x900 + openbios-video-width h# 480 = if + h# 7 + else + h# 5 + then + encode-int " monitor-sense" property + + " SUNW" encode-string " manufacturer" property + " ISO8859-1" encode-string " character-set" property + h# c encode-int " cursorshift" property + + ['] qemu-cg3-driver-install is-install +; + +qemu-cg3-driver-init + +end0 diff --git a/qemu/roms/openbios/drivers/cuda.c b/qemu/roms/openbios/drivers/cuda.c new file mode 100644 index 000000000..9555dea49 --- /dev/null +++ b/qemu/roms/openbios/drivers/cuda.c @@ -0,0 +1,424 @@ +#include "config.h" +#include "libopenbios/bindings.h" +#include "drivers/drivers.h" +#include "libc/byteorder.h" +#include "libc/vsprintf.h" + +#include "macio.h" +#include "cuda.h" + +//#define DEBUG_CUDA +#ifdef DEBUG_CUDA +#define CUDA_DPRINTF(fmt, args...) \ + do { printk("CUDA - %s: " fmt, __func__ , ##args); } while (0) +#else +#define CUDA_DPRINTF(fmt, args...) do { } while (0) +#endif + +#define IO_CUDA_OFFSET 0x00016000 +#define IO_CUDA_SIZE 0x00002000 + +/* VIA registers - spaced 0x200 bytes apart */ +#define RS 0x200 /* skip between registers */ +#define B 0 /* B-side data */ +#define A RS /* A-side data */ +#define DIRB (2*RS) /* B-side direction (1=output) */ +#define DIRA (3*RS) /* A-side direction (1=output) */ +#define T1CL (4*RS) /* Timer 1 ctr/latch (low 8 bits) */ +#define T1CH (5*RS) /* Timer 1 counter (high 8 bits) */ +#define T1LL (6*RS) /* Timer 1 latch (low 8 bits) */ +#define T1LH (7*RS) /* Timer 1 latch (high 8 bits) */ +#define T2CL (8*RS) /* Timer 2 ctr/latch (low 8 bits) */ +#define T2CH (9*RS) /* Timer 2 counter (high 8 bits) */ +#define SR (10*RS) /* Shift register */ +#define ACR (11*RS) /* Auxiliary control register */ +#define PCR (12*RS) /* Peripheral control register */ +#define IFR (13*RS) /* Interrupt flag register */ +#define IER (14*RS) /* Interrupt enable register */ +#define ANH (15*RS) /* A-side data, no handshake */ + +/* Bits in B data register: all active low */ +#define TREQ 0x08 /* Transfer request (input) */ +#define TACK 0x10 /* Transfer acknowledge (output) */ +#define TIP 0x20 /* Transfer in progress (output) */ + +/* Bits in ACR */ +#define SR_CTRL 0x1c /* Shift register control bits */ +#define SR_EXT 0x0c /* Shift on external clock */ +#define SR_OUT 0x10 /* Shift out if 1 */ + +/* Bits in IFR and IER */ +#define IER_SET 0x80 /* set bits in IER */ +#define IER_CLR 0 /* clear bits in IER */ +#define SR_INT 0x04 /* Shift register full/empty */ + +#define CUDA_BUF_SIZE 16 + +#define ADB_PACKET 0 +#define CUDA_PACKET 1 + +/* CUDA commands (2nd byte) */ +#define CUDA_GET_TIME 0x03 +#define CUDA_SET_TIME 0x09 +#define CUDA_POWERDOWN 0x0a +#define CUDA_RESET_SYSTEM 0x11 + +static uint8_t cuda_readb (cuda_t *dev, int reg) +{ + return *(volatile uint8_t *)(dev->base + reg); +} + +static void cuda_writeb (cuda_t *dev, int reg, uint8_t val) +{ + *(volatile uint8_t *)(dev->base + reg) = val; +} + +static void cuda_wait_irq (cuda_t *dev) +{ + int val; + +// CUDA_DPRINTF("\n"); + for(;;) { + val = cuda_readb(dev, IFR); + cuda_writeb(dev, IFR, val & 0x7f); + if (val & SR_INT) + break; + } +} + + + +static int cuda_request (cuda_t *dev, uint8_t pkt_type, const uint8_t *buf, + int buf_len, uint8_t *obuf) +{ + int i, obuf_len, val; + + cuda_writeb(dev, ACR, cuda_readb(dev, ACR) | SR_OUT); + cuda_writeb(dev, SR, pkt_type); + cuda_writeb(dev, B, cuda_readb(dev, B) & ~TIP); + if (buf) { + //CUDA_DPRINTF("Send buf len: %d\n", buf_len); + /* send 'buf' */ + for(i = 0; i < buf_len; i++) { + cuda_wait_irq(dev); + cuda_writeb(dev, SR, buf[i]); + cuda_writeb(dev, B, cuda_readb(dev, B) ^ TACK); + } + } + cuda_wait_irq(dev); + cuda_writeb(dev, ACR, cuda_readb(dev, ACR) & ~SR_OUT); + cuda_readb(dev, SR); + cuda_writeb(dev, B, cuda_readb(dev, B) | TIP | TACK); + + obuf_len = 0; + if (obuf) { + cuda_wait_irq(dev); + cuda_readb(dev, SR); + cuda_writeb(dev, B, cuda_readb(dev, B) & ~TIP); + for(;;) { + cuda_wait_irq(dev); + val = cuda_readb(dev, SR); + if (obuf_len < CUDA_BUF_SIZE) + obuf[obuf_len++] = val; + if (cuda_readb(dev, B) & TREQ) + break; + cuda_writeb(dev, B, cuda_readb(dev, B) ^ TACK); + } + cuda_writeb(dev, B, cuda_readb(dev, B) | TIP | TACK); + + cuda_wait_irq(dev); + cuda_readb(dev, SR); + } +// CUDA_DPRINTF("Got len: %d\n", obuf_len); + + return obuf_len; +} + + + +static int cuda_adb_req (void *host, const uint8_t *snd_buf, int len, + uint8_t *rcv_buf) +{ + uint8_t buffer[CUDA_BUF_SIZE], *pos; + + // CUDA_DPRINTF("len: %d %02x\n", len, snd_buf[0]); + len = cuda_request(host, ADB_PACKET, snd_buf, len, buffer); + if (len > 1 && buffer[0] == ADB_PACKET) { + pos = buffer + 2; + len -= 2; + } else { + pos = buffer + 1; + len = -1; + } + memcpy(rcv_buf, pos, len); + + return len; +} + + +DECLARE_UNNAMED_NODE(ob_cuda, INSTALL_OPEN, sizeof(int)); + +static cuda_t *main_cuda; + +static void +ppc32_reset_all(void) +{ + uint8_t cmdbuf[2], obuf[64]; + + cmdbuf[0] = CUDA_RESET_SYSTEM; + cuda_request(main_cuda, CUDA_PACKET, cmdbuf, sizeof(cmdbuf), obuf); +} + +static void +ppc32_poweroff(void) +{ + uint8_t cmdbuf[2], obuf[64]; + + cmdbuf[0] = CUDA_POWERDOWN; + cuda_request(main_cuda, CUDA_PACKET, cmdbuf, sizeof(cmdbuf), obuf); +} + +static void +ob_cuda_initialize (int *idx) +{ + phandle_t ph=get_cur_dev(); + int props[2]; + + push_str("via-cuda"); + fword("device-type"); + + set_int_property(ph, "#address-cells", 1); + set_int_property(ph, "#size-cells", 0); + + set_property(ph, "compatible", "cuda", 5); + + props[0] = __cpu_to_be32(IO_CUDA_OFFSET); + props[1] = __cpu_to_be32(IO_CUDA_SIZE); + + set_property(ph, "reg", (char *)&props, sizeof(props)); + + /* on newworld machines the cuda is on interrupt 0x19 */ + + props[0] = 0x19; + props[1] = 0; + NEWWORLD(set_property(ph, "interrupts", (char *)props, sizeof(props))); + NEWWORLD(set_int_property(ph, "#interrupt-cells", 2)); + + /* we emulate an oldworld hardware, so we must use + * non-standard oldworld property (needed by linux 2.6.18) + */ + + OLDWORLD(set_int_property(ph, "AAPL,interrupts", 0x12)); + + bind_func("ppc32-reset-all", ppc32_reset_all); + push_str("' ppc32-reset-all to reset-all"); + fword("eval"); +} + +static void +ob_cuda_open(int *idx) +{ + RET(-1); +} + +static void +ob_cuda_close(int *idx) +{ +} + +NODE_METHODS(ob_cuda) = { + { NULL, ob_cuda_initialize }, + { "open", ob_cuda_open }, + { "close", ob_cuda_close }, +}; + +DECLARE_UNNAMED_NODE(rtc, INSTALL_OPEN, sizeof(int)); + +static void +rtc_open(int *idx) +{ + RET(-1); +} + +/* + * get-time ( -- second minute hour day month year ) + * + */ + +static const int days_month[12] = + { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; +static const int days_month_leap[12] = + { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + +static inline int is_leap(int year) +{ + return ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0); +} + +static void +rtc_get_time(int *idx) +{ + uint8_t cmdbuf[2], obuf[64]; + ucell second, minute, hour, day, month, year; + uint32_t now; + int current; + const int *days; + + cmdbuf[0] = CUDA_GET_TIME; + cuda_request(main_cuda, CUDA_PACKET, cmdbuf, sizeof(cmdbuf), obuf); + + /* seconds since 01/01/1904 */ + + now = (obuf[3] << 24) + (obuf[4] << 16) + (obuf[5] << 8) + obuf[6]; + + second = now % 60; + now /= 60; + + minute = now % 60; + now /= 60; + + hour = now % 24; + now /= 24; + + year = now * 100 / 36525; + now -= year * 36525 / 100; + year += 1904; + + days = is_leap(year) ? days_month_leap : days_month; + + current = 0; + month = 0; + while (month < 12) { + if (now <= current + days[month]) { + break; + } + current += days[month]; + month++; + } + month++; + + day = now - current; + + PUSH(second); + PUSH(minute); + PUSH(hour); + PUSH(day); + PUSH(month); + PUSH(year); +} + +/* + * set-time ( second minute hour day month year -- ) + * + */ + +static void +rtc_set_time(int *idx) +{ + uint8_t cmdbuf[5], obuf[3]; + ucell second, minute, hour, day, month, year; + const int *days; + uint32_t now; + unsigned int nb_days; + int i; + + year = POP(); + month = POP(); + day = POP(); + hour = POP(); + minute = POP(); + second = POP(); + + days = is_leap(year) ? days_month_leap : days_month; + nb_days = (year - 1904) * 36525 / 100 + day; + for (i = 0; i < month - 1; i++) + nb_days += days[i]; + + now = (((nb_days * 24) + hour) * 60 + minute) * 60 + second; + + cmdbuf[0] = CUDA_SET_TIME; + cmdbuf[1] = now >> 24; + cmdbuf[2] = now >> 16; + cmdbuf[3] = now >> 8; + cmdbuf[4] = now; + + cuda_request(main_cuda, CUDA_PACKET, cmdbuf, sizeof(cmdbuf), obuf); +} + +NODE_METHODS(rtc) = { + { "open", rtc_open }, + { "get-time", rtc_get_time }, + { "set-time", rtc_set_time }, +}; + +static void +rtc_init(char *path) +{ + phandle_t ph, aliases; + char buf[64]; + + snprintf(buf, sizeof(buf), "%s/rtc", path); + REGISTER_NAMED_NODE(rtc, buf); + + ph = find_dev(buf); + set_property(ph, "device_type", "rtc", 4); + set_property(ph, "compatible", "rtc", 4); + + aliases = find_dev("/aliases"); + set_property(aliases, "rtc", buf, strlen(buf) + 1); + +} + +static void +powermgt_init(char *path) +{ + phandle_t ph; + char buf[64]; + + snprintf(buf, sizeof(buf), "%s/power-mgt", path); + REGISTER_NAMED_NODE(rtc, buf); + + ph = find_dev(buf); + set_property(ph, "device_type", "power-mgt", 10); + set_property(ph, "compatible", "power-mgt", 10); +} + +cuda_t *cuda_init (const char *path, phys_addr_t base) +{ + cuda_t *cuda; + char buf[64]; + phandle_t aliases; + + base += IO_CUDA_OFFSET; + CUDA_DPRINTF(" base=" FMT_plx "\n", base); + cuda = malloc(sizeof(cuda_t)); + if (cuda == NULL) + return NULL; + + snprintf(buf, sizeof(buf), "%s/via-cuda", path); + REGISTER_NAMED_NODE(ob_cuda, buf); + + aliases = find_dev("/aliases"); + set_property(aliases, "via-cuda", buf, strlen(buf) + 1); + + cuda->base = base; + cuda_writeb(cuda, B, cuda_readb(cuda, B) | TREQ | TIP); +#ifdef CONFIG_DRIVER_ADB + cuda->adb_bus = adb_bus_new(cuda, &cuda_adb_req); + if (cuda->adb_bus == NULL) { + free(cuda); + return NULL; + } + adb_bus_init(buf, cuda->adb_bus); +#endif + + rtc_init(buf); + powermgt_init(buf); + + main_cuda = cuda; + + device_end(); + bind_func("poweroff", ppc32_poweroff); + + return cuda; +} diff --git a/qemu/roms/openbios/drivers/cuda.h b/qemu/roms/openbios/drivers/cuda.h new file mode 100644 index 000000000..d3818c03c --- /dev/null +++ b/qemu/roms/openbios/drivers/cuda.h @@ -0,0 +1,17 @@ +#include "adb_bus.h" + +struct cuda_t { + phys_addr_t base; + adb_bus_t *adb_bus; +}; +typedef struct cuda_t cuda_t; + +enum { + CHARDEV_KBD = 0, + CHARDEV_MOUSE, + CHARDEV_SERIAL, + CHARDEV_DISPLAY, + CHARDEV_LAST, +}; + +cuda_t *cuda_init (const char *path, phys_addr_t base); diff --git a/qemu/roms/openbios/drivers/escc.c b/qemu/roms/openbios/drivers/escc.c new file mode 100644 index 000000000..240043be3 --- /dev/null +++ b/qemu/roms/openbios/drivers/escc.c @@ -0,0 +1,476 @@ +#include "config.h" +#include "libopenbios/bindings.h" +#include "libc/byteorder.h" +#include "libc/vsprintf.h" +#include "drivers/drivers.h" +#include "libopenbios/ofmem.h" + +#include "escc.h" + +/* ****************************************************************** + * serial console functions + * ****************************************************************** */ + +static volatile unsigned char *escc_serial_dev; + +#define CTRL(addr) (*(volatile unsigned char *)(uintptr_t)(addr)) +#ifdef CONFIG_DRIVER_ESCC_SUN +#define DATA(addr) (*(volatile unsigned char *)(uintptr_t)(addr + 2)) +#else +#define DATA(addr) (*(volatile unsigned char *)(uintptr_t)(addr + 16)) +#endif + +/* Conversion routines to/from brg time constants from/to bits + * per second. + */ +#define BPS_TO_BRG(bps, freq) ((((freq) + (bps)) / (2 * (bps))) - 2) + +#ifdef CONFIG_DRIVER_ESCC_SUN +#define ESCC_CLOCK 4915200 /* Zilog input clock rate. */ +#else +#define ESCC_CLOCK 3686400 +#endif +#define ESCC_CLOCK_DIVISOR 16 /* Divisor this driver uses. */ + +/* Write Register 3 */ +#define RxENAB 0x1 /* Rx Enable */ +#define Rx8 0xc0 /* Rx 8 Bits/Character */ + +/* Write Register 4 */ +#define SB1 0x4 /* 1 stop bit/char */ +#define X16CLK 0x40 /* x16 clock mode */ + +/* Write Register 5 */ +#define RTS 0x2 /* RTS */ +#define TxENAB 0x8 /* Tx Enable */ +#define Tx8 0x60 /* Tx 8 bits/character */ +#define DTR 0x80 /* DTR */ + +/* Write Register 14 (Misc control bits) */ +#define BRENAB 1 /* Baud rate generator enable */ +#define BRSRC 2 /* Baud rate generator source */ + +/* Read Register 0 */ +#define Rx_CH_AV 0x1 /* Rx Character Available */ +#define Tx_BUF_EMP 0x4 /* Tx Buffer empty */ + +int escc_uart_charav(uintptr_t port) +{ + return (CTRL(port) & Rx_CH_AV) != 0; +} + +char escc_uart_getchar(uintptr_t port) +{ + while (!escc_uart_charav(port)) + ; + return DATA(port) & 0177; +} + +static void escc_uart_port_putchar(uintptr_t port, unsigned char c) +{ + if (!escc_serial_dev) + return; + + if (c == '\n') + escc_uart_port_putchar(port, '\r'); + while (!(CTRL(port) & Tx_BUF_EMP)) + ; + DATA(port) = c; +} + +static void uart_init_line(volatile unsigned char *port, unsigned long baud) +{ + CTRL(port) = 4; // reg 4 + CTRL(port) = SB1 | X16CLK; // no parity, async, 1 stop bit, 16x + // clock + + baud = BPS_TO_BRG(baud, ESCC_CLOCK / ESCC_CLOCK_DIVISOR); + + CTRL(port) = 12; // reg 12 + CTRL(port) = baud & 0xff; + CTRL(port) = 13; // reg 13 + CTRL(port) = (baud >> 8) & 0xff; + CTRL(port) = 14; // reg 14 + CTRL(port) = BRSRC | BRENAB; + + CTRL(port) = 3; // reg 3 + CTRL(port) = RxENAB | Rx8; // enable rx, 8 bits/char + + CTRL(port) = 5; // reg 5 + CTRL(port) = RTS | TxENAB | Tx8 | DTR; // enable tx, 8 bits/char, + // set RTS & DTR + +} + +int escc_uart_init(phys_addr_t port, unsigned long speed) +{ +#ifdef CONFIG_DRIVER_ESCC_SUN + escc_serial_dev = (unsigned char *)ofmem_map_io(port & ~7ULL, ZS_REGS); + escc_serial_dev += port & 7ULL; +#else + escc_serial_dev = (unsigned char *)(uintptr_t)port; +#endif + uart_init_line(escc_serial_dev, speed); + return -1; +} + +void escc_uart_putchar(int c) +{ + escc_uart_port_putchar((uintptr_t)escc_serial_dev, (unsigned char) (c & 0xff)); +} + +void serial_cls(void) +{ + escc_uart_putchar(27); + escc_uart_putchar('['); + escc_uart_putchar('H'); + escc_uart_putchar(27); + escc_uart_putchar('['); + escc_uart_putchar('J'); +} + +/* ( addr len -- actual ) */ +static void +escc_read(ucell *address) +{ + char *addr; + int len; + + len = POP(); + addr = (char *)cell2pointer(POP()); + + if (len < 1) + printk("escc_read: bad len, addr %p len %x\n", addr, len); + + if (escc_uart_charav(*address)) { + *addr = (char)escc_uart_getchar(*address); + PUSH(1); + } else { + PUSH(0); + } +} + +/* ( addr len -- actual ) */ +static void +escc_write(ucell *address) +{ + unsigned char *addr; + int i, len; + + len = POP(); + addr = (unsigned char *)cell2pointer(POP()); + + for (i = 0; i < len; i++) { + escc_uart_port_putchar(*address, addr[i]); + } + PUSH(len); +} + +static void +escc_close(void) +{ +} + +static void +escc_open(ucell *address) +{ +#ifdef CONFIG_DRIVER_ESCC_SUN + int len; + phandle_t ph; + unsigned long *prop; + char *args; + + fword("my-self"); + fword("ihandle>phandle"); + ph = (phandle_t)POP(); + prop = (unsigned long *)get_property(ph, "address", &len); + *address = *prop; + fword("my-args"); + args = pop_fstr_copy(); + if (args) { + if (args[0] == 'a') + *address += 4; + //printk("escc_open: address %lx, args %s\n", *address, args); + free(args); + } +#else + *address = (unsigned long)escc_serial_dev; // XXX +#endif + RET ( -1 ); +} + +DECLARE_UNNAMED_NODE(escc, INSTALL_OPEN, sizeof(ucell)); + +NODE_METHODS(escc) = { + { "open", escc_open }, + { "close", escc_close }, + { "read", escc_read }, + { "write", escc_write }, +}; + +#ifdef CONFIG_DRIVER_ESCC_SUN +static volatile unsigned char *kbd_dev; + +void kbd_init(phys_addr_t base) +{ + kbd_dev = (unsigned char *)ofmem_map_io(base, 2 * 4); + kbd_dev += 4; +} + +static const unsigned char sunkbd_keycode[128] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', 0, 8, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, + 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '\\', 13, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ' ', +}; + +static const unsigned char sunkbd_keycode_shifted[128] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', 0, 8, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, + 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"', '|', 13, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '<', '>', '?', + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ' ', +}; + +static int shiftstate; + +int +keyboard_dataready(void) +{ + return ((kbd_dev[0] & 1) == 1); +} + +unsigned char +keyboard_readdata(void) +{ + unsigned char ch; + + while (!keyboard_dataready()) { } + + do { + ch = kbd_dev[2] & 0xff; + if (ch == 99) + shiftstate |= 1; + else if (ch == 110) + shiftstate |= 2; + else if (ch == 227) + shiftstate &= ~1; + else if (ch == 238) + shiftstate &= ~2; + //printk("getch: %d\n", ch); + } // If release, wait for key press + while ((ch & 0x80) == 0x80 || ch == 238 || ch == 227); + //printk("getch rel: %d\n", ch); + ch &= 0x7f; + if (shiftstate) + ch = sunkbd_keycode_shifted[ch]; + else + ch = sunkbd_keycode[ch]; + //printk("getch xlate: %d\n", ch); + + return ch; +} + +/* ( addr len -- actual ) */ +static void +escc_read_keyboard(void) +{ + unsigned char *addr; + int len; + + len = POP(); + addr = (unsigned char *)POP(); + + if (len < 1) + printk("escc_read: bad len, addr %p len %x\n", addr, len); + + if (keyboard_dataready()) { + *addr = keyboard_readdata(); + PUSH(1); + } else { + PUSH(0); + } +} + +DECLARE_UNNAMED_NODE(escc_keyboard, INSTALL_OPEN, sizeof(ucell)); + +NODE_METHODS(escc_keyboard) = { + { "open", escc_open }, + { "close", escc_close }, + { "read", escc_read_keyboard }, +}; + +void +ob_zs_init(phys_addr_t base, uint64_t offset, int intr, int slave, int keyboard) +{ + char nodebuff[256]; + phandle_t aliases; + + ob_new_obio_device("zs", "serial"); + + ob_reg(base, offset, ZS_REGS, 1); + + PUSH(slave); + fword("encode-int"); + push_str("slave"); + fword("property"); + + if (keyboard) { + PUSH(0); + PUSH(0); + push_str("keyboard"); + fword("property"); + + PUSH(0); + PUSH(0); + push_str("mouse"); + fword("property"); + } + + ob_intr(intr); + + PUSH(0); + PUSH(0); + push_str("port-a-ignore-cd"); + fword("property"); + + PUSH(0); + PUSH(0); + push_str("port-b-ignore-cd"); + fword("property"); + + fword("finish-device"); + + snprintf(nodebuff, sizeof(nodebuff), "/obio/zs@0,%x", + (int)offset & 0xffffffff); + if (keyboard) { + REGISTER_NODE_METHODS(escc_keyboard, nodebuff); + + aliases = find_dev("/aliases"); + set_property(aliases, "keyboard", nodebuff, strlen(nodebuff) + 1); + } else { + REGISTER_NODE_METHODS(escc, nodebuff); + + aliases = find_dev("/aliases"); + snprintf(nodebuff, sizeof(nodebuff), "/obio/zs@0,%x:a", + (int)offset & 0xffffffff); + set_property(aliases, "ttya", nodebuff, strlen(nodebuff) + 1); + + snprintf(nodebuff, sizeof(nodebuff), "/obio/zs@0,%x:b", + (int)offset & 0xffffffff); + set_property(aliases, "ttyb", nodebuff, strlen(nodebuff) + 1); + + } +} + +#else + +static void +escc_add_channel(const char *path, const char *node, phys_addr_t addr, + uint32_t offset) +{ + char buf[64], tty[32]; + phandle_t dnode, aliases; + int len; + cell props[2]; + + /* add device */ + + snprintf(buf, sizeof(buf), "%s/ch-%s", path, node); + + REGISTER_NAMED_NODE(escc, buf); + + activate_device(buf); + + /* add aliases */ + + aliases = find_dev("/aliases"); + + snprintf(buf, sizeof(buf), "%s/ch-%s", path, node); + OLDWORLD(snprintf(tty, sizeof(tty), "tty%s", node)); + OLDWORLD(set_property(aliases, tty, buf, strlen(buf) + 1)); + snprintf(tty, sizeof(tty), "scc%s", node); + set_property(aliases, tty, buf, strlen(buf) + 1); + + /* add properties */ + + dnode = find_dev(buf); + set_property(dnode, "device_type", "serial", + strlen("serial") + 1); + + snprintf(buf, sizeof(buf), "ch-%s", node); + len = strlen(buf) + 1; + snprintf(buf + len, sizeof(buf) - len, "CHRP,es2"); + set_property(dnode, "compatible", buf, len + 9); + + props[0] = IO_ESCC_OFFSET + offset * 0x20; + props[1] = 0x00000020; + set_property(dnode, "reg", (char *)&props, 2 * sizeof(cell)); + + props[0] = addr + IO_ESCC_OFFSET + offset * 0x20; + OLDWORLD(set_property(dnode, "AAPL,address", + (char *)&props, 1 * sizeof(cell))); + + props[0] = 0x00000010 - offset; + OLDWORLD(set_property(dnode, "AAPL,interrupts", + (char *)&props, 1 * sizeof(cell))); + + props[0] = (0x24) + offset; + props[1] = 0; + NEWWORLD(set_property(dnode, "interrupts", + (char *)&props, 2 * sizeof(cell))); + + device_end(); + + uart_init_line((unsigned char*)addr + IO_ESCC_OFFSET + offset * 0x20, + CONFIG_SERIAL_SPEED); +} + +void +escc_init(const char *path, phys_addr_t addr) +{ + char buf[64]; + int props[2]; + phandle_t dnode; + + push_str(path); + fword("find-device"); + fword("new-device"); + + push_str("escc"); + fword("device-name"); + + snprintf(buf, sizeof(buf), "%s/escc", path); + + dnode = find_dev(buf); + + set_int_property(dnode, "#address-cells", 1); + props[0] = __cpu_to_be32(IO_ESCC_OFFSET); + props[1] = __cpu_to_be32(IO_ESCC_SIZE); + set_property(dnode, "reg", (char *)&props, sizeof(props)); + set_property(dnode, "device_type", "escc", + strlen("escc") + 1); + set_property(dnode, "compatible", "escc\0CHRP,es0", 14); + + fword("finish-device"); + + escc_add_channel(buf, "a", addr, 1); + escc_add_channel(buf, "b", addr, 0); + + escc_serial_dev = (unsigned char *)addr + IO_ESCC_OFFSET + + (CONFIG_SERIAL_PORT ? 0 : 0x20); +} +#endif diff --git a/qemu/roms/openbios/drivers/escc.h b/qemu/roms/openbios/drivers/escc.h new file mode 100644 index 000000000..caaf00d40 --- /dev/null +++ b/qemu/roms/openbios/drivers/escc.h @@ -0,0 +1,9 @@ + +#define IO_ESCC_SIZE 0x00001000 +#define IO_ESCC_OFFSET 0x00013000 + +#define ZS_REGS 8 + +void escc_init(const char *path, phys_addr_t addr); +void ob_zs_init(phys_addr_t base, uint64_t offset, int intr, int slave, + int keyboard); diff --git a/qemu/roms/openbios/drivers/esp.c b/qemu/roms/openbios/drivers/esp.c new file mode 100644 index 000000000..ad3db280d --- /dev/null +++ b/qemu/roms/openbios/drivers/esp.c @@ -0,0 +1,598 @@ +/* + * OpenBIOS ESP driver + * + * Copyright (C) 2004 Jens Axboe <axboe@suse.de> + * Copyright (C) 2005 Stefan Reinauer <stepan@openbios.org> + * + * Credit goes to Hale Landis for his excellent ata demo software + * OF node handling and some fixes by Stefan Reinauer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#include "config.h" +#include "libopenbios/bindings.h" +#include "kernel/kernel.h" +#include "libc/byteorder.h" +#include "libc/vsprintf.h" + +#include "drivers/drivers.h" +#include "asm/io.h" +#include "scsi.h" +#include "asm/dma.h" +#include "esp.h" +#include "libopenbios/ofmem.h" + +#define BUFSIZE 4096 + +#ifdef CONFIG_DEBUG_ESP +#define DPRINTF(fmt, args...) \ + do { printk(fmt , ##args); } while (0) +#else +#define DPRINTF(fmt, args...) +#endif + +struct esp_dma { + volatile struct sparc_dma_registers *regs; + enum dvma_rev revision; +}; + +typedef struct sd_private { + unsigned int bs; + const char *media_str[2]; + uint32_t sectors; + uint8_t media; + uint8_t id; + uint8_t present; + char model[40]; +} sd_private_t; + +struct esp_regs { + unsigned char regs[ESP_REG_SIZE]; +}; + +typedef struct esp_private { + volatile struct esp_regs *ll; + uint32_t buffer_dvma; + unsigned int irq; /* device IRQ number */ + struct esp_dma espdma; + unsigned char *buffer; + sd_private_t sd[8]; +} esp_private_t; + +static esp_private_t *global_esp; + +/* DECLARE data structures for the nodes. */ +DECLARE_UNNAMED_NODE(ob_sd, INSTALL_OPEN, sizeof(sd_private_t *)); +DECLARE_UNNAMED_NODE(ob_esp, INSTALL_OPEN, sizeof(esp_private_t *)); + +#ifdef CONFIG_DEBUG_ESP +static void dump_drive(sd_private_t *drive) +{ + printk("SCSI DRIVE @%lx:\n", (unsigned long)drive); + printk("id: %d\n", drive->id); + printk("media: %s\n", drive->media_str[0]); + printk("media: %s\n", drive->media_str[1]); + printk("model: %s\n", drive->model); + printk("sectors: %d\n", drive->sectors); + printk("present: %d\n", drive->present); + printk("bs: %d\n", drive->bs); +} +#endif + +static int +do_command(esp_private_t *esp, sd_private_t *sd, int cmdlen, int replylen) +{ + int status; + + // Set SCSI target + esp->ll->regs[ESP_BUSID] = sd->id & 7; + // Set DMA address + esp->espdma.regs->st_addr = esp->buffer_dvma; + // Set DMA length + esp->ll->regs[ESP_TCLOW] = cmdlen & 0xff; + esp->ll->regs[ESP_TCMED] = (cmdlen >> 8) & 0xff; + // Set DMA direction and enable DMA + esp->espdma.regs->cond_reg = DMA_ENABLE; + // Set ATN, issue command + esp->ll->regs[ESP_CMD] = ESP_CMD_SELA | ESP_CMD_DMA; + // Wait for DMA to complete. Can this fail? + while ((esp->espdma.regs->cond_reg & DMA_HNDL_INTR) == 0) /* no-op */; + // Check status + status = esp->ll->regs[ESP_STATUS]; + // Clear interrupts to avoid guests seeing spurious interrupts + (void)esp->ll->regs[ESP_INTRPT]; + + DPRINTF("do_command: id %d, cmd[0] 0x%x, status 0x%x\n", sd->id, esp->buffer[1], status); + + /* Target didn't want all command data? */ + if ((status & ESP_STAT_TCNT) != ESP_STAT_TCNT) { + return status; + } + if (replylen == 0) { + return 0; + } + /* Target went to status phase instead of data phase? */ + if ((status & ESP_STAT_PMASK) == ESP_STATP) { + return status; + } + + // Get reply + // Set DMA address + esp->espdma.regs->st_addr = esp->buffer_dvma; + // Set DMA length + esp->ll->regs[ESP_TCLOW] = replylen & 0xff; + esp->ll->regs[ESP_TCMED] = (replylen >> 8) & 0xff; + // Set DMA direction + esp->espdma.regs->cond_reg = DMA_ST_WRITE | DMA_ENABLE; + // Transfer + esp->ll->regs[ESP_CMD] = ESP_CMD_TI | ESP_CMD_DMA; + // Wait for DMA to complete + while ((esp->espdma.regs->cond_reg & DMA_HNDL_INTR) == 0) /* no-op */; + // Check status + status = esp->ll->regs[ESP_STATUS]; + // Clear interrupts to avoid guests seeing spurious interrupts + (void)esp->ll->regs[ESP_INTRPT]; + + DPRINTF("do_command_reply: status 0x%x\n", status); + + if ((status & ESP_STAT_TCNT) != ESP_STAT_TCNT) + return status; + else + return 0; // OK +} + +// offset is in sectors +static int +ob_sd_read_sector(esp_private_t *esp, sd_private_t *sd, int offset) +{ + DPRINTF("ob_sd_read_sector id %d sector=%d\n", + sd->id, offset); + + // Setup command = Read(10) + memset(esp->buffer, 0, 11); + esp->buffer[0] = 0x80; + esp->buffer[1] = READ_10; + + esp->buffer[3] = (offset >> 24) & 0xff; + esp->buffer[4] = (offset >> 16) & 0xff; + esp->buffer[5] = (offset >> 8) & 0xff; + esp->buffer[6] = offset & 0xff; + + esp->buffer[8] = 0; + esp->buffer[9] = 1; + + if (do_command(esp, sd, 11, sd->bs)) + return 0; + + return 0; +} + +static unsigned int +read_capacity(esp_private_t *esp, sd_private_t *sd) +{ + // Setup command = Read Capacity + memset(esp->buffer, 0, 11); + esp->buffer[0] = 0x80; + esp->buffer[1] = READ_CAPACITY; + + if (do_command(esp, sd, 11, 8)) { + sd->sectors = 0; + sd->bs = 0; + DPRINTF("read_capacity id %d failed\n", sd->id); + return 0; + } + sd->bs = (esp->buffer[4] << 24) | (esp->buffer[5] << 16) | (esp->buffer[6] << 8) | esp->buffer[7]; + sd->sectors = ((esp->buffer[0] << 24) | (esp->buffer[1] << 16) | (esp->buffer[2] << 8) | esp->buffer[3]) * (sd->bs / 512); + + DPRINTF("read_capacity id %d bs %d sectors %d\n", sd->id, sd->bs, + sd->sectors); + return 1; +} + +static unsigned int +test_unit_ready(esp_private_t *esp, sd_private_t *sd) +{ + /* Setup command = Test Unit Ready */ + memset(esp->buffer, 0, 7); + esp->buffer[0] = 0x80; + esp->buffer[1] = TEST_UNIT_READY; + + if (do_command(esp, sd, 7, 0)) { + DPRINTF("test_unit_ready id %d failed\n", sd->id); + return 0; + } + + DPRINTF("test_unit_ready id %d success\n", sd->id); + return 1; +} + +static unsigned int +inquiry(esp_private_t *esp, sd_private_t *sd) +{ + const char *media[2] = { "UNKNOWN", "UNKNOWN"}; + + // Setup command = Inquiry + memset(esp->buffer, 0, 7); + esp->buffer[0] = 0x80; + esp->buffer[1] = INQUIRY; + + esp->buffer[5] = 36; + + if (do_command(esp, sd, 7, 36)) { + sd->present = 0; + sd->media = -1; + return 0; + } + sd->present = 1; + sd->media = esp->buffer[0]; + + switch (sd->media) { + case TYPE_DISK: + media[0] = "disk"; + media[1] = "hd"; + break; + case TYPE_ROM: + media[0] = "cdrom"; + media[1] = "cd"; + break; + } + sd->media_str[0] = media[0]; + sd->media_str[1] = media[1]; + memcpy(sd->model, &esp->buffer[16], 16); + sd->model[17] = '\0'; + + return 1; +} + + +static void +ob_sd_read_blocks(sd_private_t **sd) +{ + cell n = POP(), cnt = n; + ucell blk = POP(); + char *dest = (char*)POP(); + int pos, spb, sect_offset; + + DPRINTF("ob_sd_read_blocks id %d %lx block=%d n=%d\n", (*sd)->id, (unsigned long)dest, blk, n ); + + if ((*sd)->bs == 0) { + PUSH(0); + return; + } + spb = (*sd)->bs / 512; + while (n) { + sect_offset = blk / spb; + pos = (blk - sect_offset * spb) * 512; + + if (ob_sd_read_sector(global_esp, *sd, sect_offset)) { + DPRINTF("ob_sd_read_blocks: error\n"); + RET(0); + } + while (n && pos < spb * 512) { + memcpy(dest, global_esp->buffer + pos, 512); + pos += 512; + dest += 512; + n--; + blk++; + } + } + PUSH(cnt); +} + +static void +ob_sd_block_size(__attribute__((unused))sd_private_t **sd) +{ + PUSH(512); +} + +static void +ob_sd_open(__attribute__((unused))sd_private_t **sd) +{ + int ret = 1, id; + phandle_t ph; + + fword("my-unit"); + id = POP(); + POP(); // unit id is 2 ints but we only need one. + *sd = &global_esp->sd[id]; + +#ifdef CONFIG_DEBUG_ESP + { + char *args; + + fword("my-args"); + args = pop_fstr_copy(); + DPRINTF("opening drive %d args %s\n", id, args); + free(args); + } +#endif + + selfword("open-deblocker"); + + /* interpose disk-label */ + ph = find_dev("/packages/disk-label"); + fword("my-args"); + PUSH_ph( ph ); + fword("interpose"); + + RET ( -ret ); +} + +static void +ob_sd_close(__attribute__((unused)) sd_private_t **sd) +{ + selfword("close-deblocker"); +} + +NODE_METHODS(ob_sd) = { + { "open", ob_sd_open }, + { "close", ob_sd_close }, + { "read-blocks", ob_sd_read_blocks }, + { "block-size", ob_sd_block_size }, +}; + + +static int +espdma_init(unsigned int slot, uint64_t base, unsigned long offset, + struct esp_dma *espdma) +{ + espdma->regs = (void *)ofmem_map_io(base + (uint64_t)offset, 0x10); + + if (espdma->regs == NULL) { + DPRINTF("espdma_init: cannot map registers\n"); + return -1; + } + + DPRINTF("dma1: "); + + switch ((espdma->regs->cond_reg) & DMA_DEVICE_ID) { + case DMA_VERS0: + espdma->revision = dvmarev0; + DPRINTF("Revision 0 "); + break; + case DMA_ESCV1: + espdma->revision = dvmaesc1; + DPRINTF("ESC Revision 1 "); + break; + case DMA_VERS1: + espdma->revision = dvmarev1; + DPRINTF("Revision 1 "); + break; + case DMA_VERS2: + espdma->revision = dvmarev2; + DPRINTF("Revision 2 "); + break; + case DMA_VERHME: + espdma->revision = dvmahme; + DPRINTF("HME DVMA gate array "); + break; + case DMA_VERSPLUS: + espdma->revision = dvmarevplus; + DPRINTF("Revision 1 PLUS "); + break; + default: + DPRINTF("unknown dma version %x", + (espdma->regs->cond_reg) & DMA_DEVICE_ID); + /* espdma->allocated = 1; */ + break; + } + DPRINTF("\n"); + + push_str("/iommu/sbus/espdma"); + fword("find-device"); + + /* set reg */ + PUSH(slot); + fword("encode-int"); + PUSH(offset); + fword("encode-int"); + fword("encode+"); + PUSH(0x00000010); + fword("encode-int"); + fword("encode+"); + push_str("reg"); + fword("property"); + + return 0; +} + +static void +ob_esp_initialize(__attribute__((unused)) esp_private_t **esp) +{ + phandle_t ph = get_cur_dev(); + + set_int_property(ph, "#address-cells", 2); + set_int_property(ph, "#size-cells", 0); + + /* set device type */ + push_str("scsi"); + fword("device-type"); + + /* QEMU's ESP emulation does not support mixing DMA and FIFO messages. By + setting this attribute, we prevent the Solaris ESP kernel driver from + trying to use this feature when booting a disk image (and failing) */ + PUSH(0x58); + fword("encode-int"); + push_str("scsi-options"); + fword("property"); + + PUSH(0x24); + fword("encode-int"); + PUSH(0); + fword("encode-int"); + fword("encode+"); + push_str("intr"); + fword("property"); +} + +static void +ob_esp_decodeunit(__attribute__((unused)) esp_private_t **esp) +{ + fword("decode-unit-scsi"); +} + + +static void +ob_esp_encodeunit(__attribute__((unused)) esp_private_t **esp) +{ + fword("encode-unit-scsi"); +} + +NODE_METHODS(ob_esp) = { + { NULL, ob_esp_initialize }, + { "decode-unit", ob_esp_decodeunit }, + { "encode-unit", ob_esp_encodeunit }, +}; + +static void +add_alias(const char *device, const char *alias) +{ + DPRINTF("add_alias dev \"%s\" = alias \"%s\"\n", device, alias); + push_str("/aliases"); + fword("find-device"); + push_str(device); + fword("encode-string"); + push_str(alias); + fword("property"); +} + +int +ob_esp_init(unsigned int slot, uint64_t base, unsigned long espoffset, + unsigned long dmaoffset) +{ + int id, diskcount = 0, cdcount = 0, *counter_ptr; + char nodebuff[256], aliasbuff[256]; + esp_private_t *esp; + unsigned int i; + + DPRINTF("Initializing SCSI..."); + + esp = malloc(sizeof(esp_private_t)); + if (!esp) { + DPRINTF("Can't allocate ESP private structure\n"); + return -1; + } + + global_esp = esp; + + if (espdma_init(slot, base, dmaoffset, &esp->espdma) != 0) { + return -1; + } + /* Get the IO region */ + esp->ll = (void *)ofmem_map_io(base + (uint64_t)espoffset, + sizeof(struct esp_regs)); + if (esp->ll == NULL) { + DPRINTF("Can't map ESP registers\n"); + return -1; + } + + esp->buffer = (void *)dvma_alloc(BUFSIZE, &esp->buffer_dvma); + if (!esp->buffer || !esp->buffer_dvma) { + DPRINTF("Can't get a DVMA buffer\n"); + return -1; + } + + // Chip reset + esp->ll->regs[ESP_CMD] = ESP_CMD_RC; + + DPRINTF("ESP at 0x%lx, buffer va 0x%lx dva 0x%lx\n", (unsigned long)esp, + (unsigned long)esp->buffer, (unsigned long)esp->buffer_dvma); + DPRINTF("done\n"); + DPRINTF("Initializing SCSI devices..."); + + for (id = 0; id < 8; id++) { + esp->sd[id].id = id; + if (!inquiry(esp, &esp->sd[id])) { + DPRINTF("Unit %d not present\n", id); + continue; + } + /* Clear Unit Attention condition from reset */ + for (i = 0; i < 5; i++) { + if (test_unit_ready(esp, &esp->sd[id])) { + break; + } + } + if (i == 5) { + DPRINTF("Unit %d present but won't become ready\n", id); + continue; + } + DPRINTF("Unit %d present\n", id); + read_capacity(esp, &esp->sd[id]); + +#ifdef CONFIG_DEBUG_ESP + dump_drive(&esp->sd[id]); +#endif + } + + REGISTER_NAMED_NODE(ob_esp, "/iommu/sbus/espdma/esp"); + device_end(); + /* set reg */ + push_str("/iommu/sbus/espdma/esp"); + fword("find-device"); + PUSH(slot); + fword("encode-int"); + PUSH(espoffset); + fword("encode-int"); + fword("encode+"); + PUSH(0x00000010); + fword("encode-int"); + fword("encode+"); + push_str("reg"); + fword("property"); + + PUSH(0x02625a00); + fword("encode-int"); + push_str("clock-frequency"); + fword("property"); + + for (id = 0; id < 8; id++) { + if (!esp->sd[id].present) + continue; + push_str("/iommu/sbus/espdma/esp"); + fword("find-device"); + fword("new-device"); + push_str("sd"); + fword("device-name"); + push_str("block"); + fword("device-type"); + fword("is-deblocker"); + PUSH(id); + fword("encode-int"); + PUSH(0); + fword("encode-int"); + fword("encode+"); + push_str("reg"); + fword("property"); + fword("finish-device"); + snprintf(nodebuff, sizeof(nodebuff), "/iommu/sbus/espdma/esp/sd@%d,0", + id); + REGISTER_NODE_METHODS(ob_sd, nodebuff); + if (esp->sd[id].media == TYPE_ROM) { + counter_ptr = &cdcount; + } else { + counter_ptr = &diskcount; + } + if (*counter_ptr == 0) { + add_alias(nodebuff, esp->sd[id].media_str[0]); + add_alias(nodebuff, esp->sd[id].media_str[1]); + } + snprintf(aliasbuff, sizeof(aliasbuff), "%s%d", + esp->sd[id].media_str[0], *counter_ptr); + add_alias(nodebuff, aliasbuff); + snprintf(aliasbuff, sizeof(aliasbuff), "%s%d", + esp->sd[id].media_str[1], *counter_ptr); + add_alias(nodebuff, aliasbuff); + snprintf(aliasbuff, sizeof(aliasbuff), "sd(0,%d,0)", id); + add_alias(nodebuff, aliasbuff); + snprintf(aliasbuff, sizeof(aliasbuff), "sd(0,%d,0)@0,0", id); + add_alias(nodebuff, aliasbuff); + (*counter_ptr)++; + } + DPRINTF("done\n"); + + return 0; +} diff --git a/qemu/roms/openbios/drivers/esp.fs b/qemu/roms/openbios/drivers/esp.fs new file mode 100644 index 000000000..9e37c0a0e --- /dev/null +++ b/qemu/roms/openbios/drivers/esp.fs @@ -0,0 +1,18 @@ +\ ------------------------------------------------------------------------- +\ SCSI encode/decode unit +\ ------------------------------------------------------------------------- + +: decode-unit-scsi ( str len -- id lun ) + ascii , left-split + ( addr-R len-R addr-L len-L ) + parse-hex + -rot parse-hex + swap +; + +: encode-unit-scsi ( id lun -- str len) + swap + pocket tohexstr + " ," pocket tmpstrcat >r + rot pocket tohexstr r> tmpstrcat drop +; diff --git a/qemu/roms/openbios/drivers/esp.h b/qemu/roms/openbios/drivers/esp.h new file mode 100644 index 000000000..2b9bd5e01 --- /dev/null +++ b/qemu/roms/openbios/drivers/esp.h @@ -0,0 +1,269 @@ +/* $Id: esp.h,v 1.28 2000/03/30 01:33:17 davem Exp $ + * esp.h: Defines and structures for the Sparc ESP (Enhanced SCSI + * Processor) driver under Linux. + * + * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + */ + +#ifndef _SPARC_ESP_H +#define _SPARC_ESP_H + +/* For dvma controller register definitions. */ +#include "asm/dma.h" + +/* The ESP SCSI controllers have their register sets in three + * "classes": + * + * 1) Registers which are both read and write. + * 2) Registers which are read only. + * 3) Registers which are write only. + * + * Yet, they all live within the same IO space. + */ + +/* All the ESP registers are one byte each and are accessed longwords + * apart with a big-endian ordering to the bytes. + */ + /* Access Description Offset */ +#define ESP_TCLOW 0x00UL /* rw Low bits of the transfer count 0x00 */ +#define ESP_TCMED 0x04UL /* rw Mid bits of the transfer count 0x04 */ +#define ESP_FDATA 0x08UL /* rw FIFO data bits 0x08 */ +#define ESP_CMD 0x0cUL /* rw SCSI command bits 0x0c */ +#define ESP_STATUS 0x10UL /* ro ESP status register 0x10 */ +#define ESP_BUSID ESP_STATUS /* wo Bus ID for select/reselect 0x10 */ +#define ESP_INTRPT 0x14UL /* ro Kind of interrupt 0x14 */ +#define ESP_TIMEO ESP_INTRPT /* wo Timeout value for select/resel 0x14 */ +#define ESP_SSTEP 0x18UL /* ro Sequence step register 0x18 */ +#define ESP_STP ESP_SSTEP /* wo Transfer period per sync 0x18 */ +#define ESP_FFLAGS 0x1cUL /* ro Bits of current FIFO info 0x1c */ +#define ESP_SOFF ESP_FFLAGS /* wo Sync offset 0x1c */ +#define ESP_CFG1 0x20UL /* rw First configuration register 0x20 */ +#define ESP_CFACT 0x24UL /* wo Clock conversion factor 0x24 */ +#define ESP_STATUS2 ESP_CFACT /* ro HME status2 register 0x24 */ +#define ESP_CTEST 0x28UL /* wo Chip test register 0x28 */ +#define ESP_CFG2 0x2cUL /* rw Second configuration register 0x2c */ +#define ESP_CFG3 0x30UL /* rw Third configuration register 0x30 */ +#define ESP_TCHI 0x38UL /* rw High bits of transfer count 0x38 */ +#define ESP_UID ESP_TCHI /* ro Unique ID code 0x38 */ +#define FAS_RLO ESP_TCHI /* rw HME extended counter 0x38 */ +#define ESP_FGRND 0x3cUL /* rw Data base for fifo 0x3c */ +#define FAS_RHI ESP_FGRND /* rw HME extended counter 0x3c */ +#define ESP_REG_SIZE 0x40UL + +/* Various revisions of the ESP board. */ +enum esp_rev { + esp100 = 0x00, /* NCR53C90 - very broken */ + esp100a = 0x01, /* NCR53C90A */ + esp236 = 0x02, + fas236 = 0x03, + fas100a = 0x04, + fast = 0x05, + fashme = 0x06, + espunknown = 0x07 +}; + +/* Bitfield meanings for the above registers. */ + +/* ESP config reg 1, read-write, found on all ESP chips */ +#define ESP_CONFIG1_ID 0x07 /* My BUS ID bits */ +#define ESP_CONFIG1_CHTEST 0x08 /* Enable ESP chip tests */ +#define ESP_CONFIG1_PENABLE 0x10 /* Enable parity checks */ +#define ESP_CONFIG1_PARTEST 0x20 /* Parity test mode enabled? */ +#define ESP_CONFIG1_SRRDISAB 0x40 /* Disable SCSI reset reports */ +#define ESP_CONFIG1_SLCABLE 0x80 /* Enable slow cable mode */ + +/* ESP config reg 2, read-write, found only on esp100a+esp200+esp236 chips */ +#define ESP_CONFIG2_DMAPARITY 0x01 /* enable DMA Parity (200,236) */ +#define ESP_CONFIG2_REGPARITY 0x02 /* enable reg Parity (200,236) */ +#define ESP_CONFIG2_BADPARITY 0x04 /* Bad parity target abort */ +#define ESP_CONFIG2_SCSI2ENAB 0x08 /* Enable SCSI-2 features (tmode only) */ +#define ESP_CONFIG2_HI 0x10 /* High Impedance DREQ ??? */ +#define ESP_CONFIG2_HMEFENAB 0x10 /* HME features enable */ +#define ESP_CONFIG2_BCM 0x20 /* Enable byte-ctrl (236) */ +#define ESP_CONFIG2_DISPINT 0x20 /* Disable pause irq (hme) */ +#define ESP_CONFIG2_FENAB 0x40 /* Enable features (fas100,esp216) */ +#define ESP_CONFIG2_SPL 0x40 /* Enable status-phase latch (esp236) */ +#define ESP_CONFIG2_MKDONE 0x40 /* HME magic feature */ +#define ESP_CONFIG2_HME32 0x80 /* HME 32 extended */ +#define ESP_CONFIG2_MAGIC 0xe0 /* Invalid bits... */ + +/* ESP config register 3 read-write, found only esp236+fas236+fas100a+hme chips */ +#define ESP_CONFIG3_FCLOCK 0x01 /* FAST SCSI clock rate (esp100a/hme) */ +#define ESP_CONFIG3_TEM 0x01 /* Enable thresh-8 mode (esp/fas236) */ +#define ESP_CONFIG3_FAST 0x02 /* Enable FAST SCSI (esp100a/hme) */ +#define ESP_CONFIG3_ADMA 0x02 /* Enable alternate-dma (esp/fas236) */ +#define ESP_CONFIG3_TENB 0x04 /* group2 SCSI2 support (esp100a/hme) */ +#define ESP_CONFIG3_SRB 0x04 /* Save residual byte (esp/fas236) */ +#define ESP_CONFIG3_TMS 0x08 /* Three-byte msg's ok (esp100a/hme) */ +#define ESP_CONFIG3_FCLK 0x08 /* Fast SCSI clock rate (esp/fas236) */ +#define ESP_CONFIG3_IDMSG 0x10 /* ID message checking (esp100a/hme) */ +#define ESP_CONFIG3_FSCSI 0x10 /* Enable FAST SCSI (esp/fas236) */ +#define ESP_CONFIG3_GTM 0x20 /* group2 SCSI2 support (esp/fas236) */ +#define ESP_CONFIG3_IDBIT3 0x20 /* Bit 3 of HME SCSI-ID (hme) */ +#define ESP_CONFIG3_TBMS 0x40 /* Three-byte msg's ok (esp/fas236) */ +#define ESP_CONFIG3_EWIDE 0x40 /* Enable Wide-SCSI (hme) */ +#define ESP_CONFIG3_IMS 0x80 /* ID msg chk'ng (esp/fas236) */ +#define ESP_CONFIG3_OBPUSH 0x80 /* Push odd-byte to dma (hme) */ + +/* ESP command register read-write */ +/* Group 1 commands: These may be sent at any point in time to the ESP + * chip. None of them can generate interrupts 'cept + * the "SCSI bus reset" command if you have not disabled + * SCSI reset interrupts in the config1 ESP register. + */ +#define ESP_CMD_NULL 0x00 /* Null command, ie. a nop */ +#define ESP_CMD_FLUSH 0x01 /* FIFO Flush */ +#define ESP_CMD_RC 0x02 /* Chip reset */ +#define ESP_CMD_RS 0x03 /* SCSI bus reset */ + +/* Group 2 commands: ESP must be an initiator and connected to a target + * for these commands to work. + */ +#define ESP_CMD_TI 0x10 /* Transfer Information */ +#define ESP_CMD_ICCSEQ 0x11 /* Initiator cmd complete sequence */ +#define ESP_CMD_MOK 0x12 /* Message okie-dokie */ +#define ESP_CMD_TPAD 0x18 /* Transfer Pad */ +#define ESP_CMD_SATN 0x1a /* Set ATN */ +#define ESP_CMD_RATN 0x1b /* De-assert ATN */ + +/* Group 3 commands: ESP must be in the MSGOUT or MSGIN state and be connected + * to a target as the initiator for these commands to work. + */ +#define ESP_CMD_SMSG 0x20 /* Send message */ +#define ESP_CMD_SSTAT 0x21 /* Send status */ +#define ESP_CMD_SDATA 0x22 /* Send data */ +#define ESP_CMD_DSEQ 0x23 /* Discontinue Sequence */ +#define ESP_CMD_TSEQ 0x24 /* Terminate Sequence */ +#define ESP_CMD_TCCSEQ 0x25 /* Target cmd cmplt sequence */ +#define ESP_CMD_DCNCT 0x27 /* Disconnect */ +#define ESP_CMD_RMSG 0x28 /* Receive Message */ +#define ESP_CMD_RCMD 0x29 /* Receive Command */ +#define ESP_CMD_RDATA 0x2a /* Receive Data */ +#define ESP_CMD_RCSEQ 0x2b /* Receive cmd sequence */ + +/* Group 4 commands: The ESP must be in the disconnected state and must + * not be connected to any targets as initiator for + * these commands to work. + */ +#define ESP_CMD_RSEL 0x40 /* Reselect */ +#define ESP_CMD_SEL 0x41 /* Select w/o ATN */ +#define ESP_CMD_SELA 0x42 /* Select w/ATN */ +#define ESP_CMD_SELAS 0x43 /* Select w/ATN & STOP */ +#define ESP_CMD_ESEL 0x44 /* Enable selection */ +#define ESP_CMD_DSEL 0x45 /* Disable selections */ +#define ESP_CMD_SA3 0x46 /* Select w/ATN3 */ +#define ESP_CMD_RSEL3 0x47 /* Reselect3 */ + +/* This bit enables the ESP's DMA on the SBus */ +#define ESP_CMD_DMA 0x80 /* Do DMA? */ + + +/* ESP status register read-only */ +#define ESP_STAT_PIO 0x01 /* IO phase bit */ +#define ESP_STAT_PCD 0x02 /* CD phase bit */ +#define ESP_STAT_PMSG 0x04 /* MSG phase bit */ +#define ESP_STAT_PMASK 0x07 /* Mask of phase bits */ +#define ESP_STAT_TDONE 0x08 /* Transfer Completed */ +#define ESP_STAT_TCNT 0x10 /* Transfer Counter Is Zero */ +#define ESP_STAT_PERR 0x20 /* Parity error */ +#define ESP_STAT_SPAM 0x40 /* Real bad error */ +/* This indicates the 'interrupt pending' condition on esp236, it is a reserved + * bit on other revs of the ESP. + */ +#define ESP_STAT_INTR 0x80 /* Interrupt */ + +/* HME only: status 2 register */ +#define ESP_STAT2_SCHBIT 0x01 /* Upper bits 3-7 of sstep enabled */ +#define ESP_STAT2_FFLAGS 0x02 /* The fifo flags are now latched */ +#define ESP_STAT2_XCNT 0x04 /* The transfer counter is latched */ +#define ESP_STAT2_CREGA 0x08 /* The command reg is active now */ +#define ESP_STAT2_WIDE 0x10 /* Interface on this adapter is wide */ +#define ESP_STAT2_F1BYTE 0x20 /* There is one byte at top of fifo */ +#define ESP_STAT2_FMSB 0x40 /* Next byte in fifo is most significant */ +#define ESP_STAT2_FEMPTY 0x80 /* FIFO is empty */ + +/* The status register can be masked with ESP_STAT_PMASK and compared + * with the following values to determine the current phase the ESP + * (at least thinks it) is in. For our purposes we also add our own + * software 'done' bit for our phase management engine. + */ +#define ESP_DOP (0) /* Data Out */ +#define ESP_DIP (ESP_STAT_PIO) /* Data In */ +#define ESP_CMDP (ESP_STAT_PCD) /* Command */ +#define ESP_STATP (ESP_STAT_PCD|ESP_STAT_PIO) /* Status */ +#define ESP_MOP (ESP_STAT_PMSG|ESP_STAT_PCD) /* Message Out */ +#define ESP_MIP (ESP_STAT_PMSG|ESP_STAT_PCD|ESP_STAT_PIO) /* Message In */ + +/* ESP interrupt register read-only */ +#define ESP_INTR_S 0x01 /* Select w/o ATN */ +#define ESP_INTR_SATN 0x02 /* Select w/ATN */ +#define ESP_INTR_RSEL 0x04 /* Reselected */ +#define ESP_INTR_FDONE 0x08 /* Function done */ +#define ESP_INTR_BSERV 0x10 /* Bus service */ +#define ESP_INTR_DC 0x20 /* Disconnect */ +#define ESP_INTR_IC 0x40 /* Illegal command given */ +#define ESP_INTR_SR 0x80 /* SCSI bus reset detected */ + +/* Interrupt status macros */ +#define ESP_SRESET_IRQ(esp) ((esp)->intreg & (ESP_INTR_SR)) +#define ESP_ILLCMD_IRQ(esp) ((esp)->intreg & (ESP_INTR_IC)) +#define ESP_SELECT_WITH_ATN_IRQ(esp) ((esp)->intreg & (ESP_INTR_SATN)) +#define ESP_SELECT_WITHOUT_ATN_IRQ(esp) ((esp)->intreg & (ESP_INTR_S)) +#define ESP_SELECTION_IRQ(esp) ((ESP_SELECT_WITH_ATN_IRQ(esp)) || \ + (ESP_SELECT_WITHOUT_ATN_IRQ(esp))) +#define ESP_RESELECTION_IRQ(esp) ((esp)->intreg & (ESP_INTR_RSEL)) + +/* ESP sequence step register read-only */ +#define ESP_STEP_VBITS 0x07 /* Valid bits */ +#define ESP_STEP_ASEL 0x00 /* Selection&Arbitrate cmplt */ +#define ESP_STEP_SID 0x01 /* One msg byte sent */ +#define ESP_STEP_NCMD 0x02 /* Was not in command phase */ +#define ESP_STEP_PPC 0x03 /* Early phase chg caused cmnd + * bytes to be lost + */ +#define ESP_STEP_FINI4 0x04 /* Command was sent ok */ + +/* Ho hum, some ESP's set the step register to this as well... */ +#define ESP_STEP_FINI5 0x05 +#define ESP_STEP_FINI6 0x06 +#define ESP_STEP_FINI7 0x07 + +/* ESP chip-test register read-write */ +#define ESP_TEST_TARG 0x01 /* Target test mode */ +#define ESP_TEST_INI 0x02 /* Initiator test mode */ +#define ESP_TEST_TS 0x04 /* Tristate test mode */ + +/* ESP unique ID register read-only, found on fas236+fas100a only */ +#define ESP_UID_F100A 0x00 /* ESP FAS100A */ +#define ESP_UID_F236 0x02 /* ESP FAS236 */ +#define ESP_UID_REV 0x07 /* ESP revision */ +#define ESP_UID_FAM 0xf8 /* ESP family */ + +/* ESP fifo flags register read-only */ +/* Note that the following implies a 16 byte FIFO on the ESP. */ +#define ESP_FF_FBYTES 0x1f /* Num bytes in FIFO */ +#define ESP_FF_ONOTZERO 0x20 /* offset ctr not zero (esp100) */ +#define ESP_FF_SSTEP 0xe0 /* Sequence step */ + +/* ESP clock conversion factor register write-only */ +#define ESP_CCF_F0 0x00 /* 35.01MHz - 40MHz */ +#define ESP_CCF_NEVER 0x01 /* Set it to this and die */ +#define ESP_CCF_F2 0x02 /* 10MHz */ +#define ESP_CCF_F3 0x03 /* 10.01MHz - 15MHz */ +#define ESP_CCF_F4 0x04 /* 15.01MHz - 20MHz */ +#define ESP_CCF_F5 0x05 /* 20.01MHz - 25MHz */ +#define ESP_CCF_F6 0x06 /* 25.01MHz - 30MHz */ +#define ESP_CCF_F7 0x07 /* 30.01MHz - 35MHz */ + +/* HME only... */ +#define ESP_BUSID_RESELID 0x10 +#define ESP_BUSID_CTR32BIT 0x40 + +#define ESP_BUS_TIMEOUT 275 /* In milli-seconds */ +#define ESP_TIMEO_CONST 8192 +#define ESP_NEG_DEFP(mhz, cfact) \ + ((ESP_BUS_TIMEOUT * ((mhz) / 1000)) / (8192 * (cfact))) +#define ESP_MHZ_TO_CYCLE(mhertz) ((1000000000) / ((mhertz) / 1000)) +#define ESP_TICK(ccf, cycle) ((7682 * (ccf) * (cycle) / 1000)) + +#endif /* !(_SPARC_ESP_H) */ diff --git a/qemu/roms/openbios/drivers/floppy.c b/qemu/roms/openbios/drivers/floppy.c new file mode 100644 index 000000000..329987b17 --- /dev/null +++ b/qemu/roms/openbios/drivers/floppy.c @@ -0,0 +1,1179 @@ +#include "config.h" +#include "libopenbios/bindings.h" +#include "kernel/kernel.h" +#include "libc/byteorder.h" +#include "libc/vsprintf.h" + +#include "drivers/drivers.h" + +#include "timer.h" + +/* DECLARE data structures for the nodes. */ +DECLARE_UNNAMED_NODE( ob_floppy, INSTALL_OPEN, 2*sizeof(int) ); + +#ifdef CONFIG_DEBUG_FLOPPY +#define printk_info printk +#define printk_debug printk +#else +#define printk_info(x ...) +#define printk_debug(x ...) +#endif +#define printk_err printk + +#define FD_DRIVE 0 + + +#define FD_STATUS_A (0) /* Status register A */ +#define FD_STATUS_B (1) /* Status register B */ +#define FD_DOR (2) /* Digital Output Register */ +#define FD_TDR (3) /* Tape Drive Register */ +#define FD_STATUS (4) /* Main Status Register */ +#define FD_DSR (4) /* Data Rate Select Register (old) */ +#define FD_DATA (5) /* Data Transfer (FIFO) register */ +#define FD_DIR (7) /* Digital Input Register (read) */ +#define FD_DCR (7) /* Diskette Control Register (write)*/ + +/* Bit of FD_STATUS_A */ +#define STA_INT_PENDING 0x80 /* Interrupt Pending */ + +/* DOR */ +#define DOR_DRIVE0 0x00 +#define DOR_DRIVE1 0x01 +#define DOR_DRIVE2 0x02 +#define DOR_DRIVE3 0x03 +#define DOR_DRIVE_MASK 0x03 +#define DOR_NO_RESET 0x04 +#define DOR_DMA_EN 0x08 +#define DOR_MOT_EN0 0x10 +#define DOR_MOT_EN1 0x20 +#define DOR_MOT_EN2 0x40 +#define DOR_MOT_EN3 0x80 + +/* Bits of main status register */ +#define STATUS_BUSYMASK 0x0F /* drive busy mask */ +#define STATUS_BUSY 0x10 /* FDC busy */ +#define STATUS_NON_DMA 0x20 /* 0- DMA mode */ +#define STATUS_DIR 0x40 /* 0- cpu->fdc */ +#define STATUS_READY 0x80 /* Data reg ready */ + +/* Bits of FD_ST0 */ +#define ST0_DS 0x03 /* drive select mask */ +#define ST0_HA 0x04 /* Head (Address) */ +#define ST0_NR 0x08 /* Not Ready */ +#define ST0_ECE 0x10 /* Equipment check error */ +#define ST0_SE 0x20 /* Seek end */ +#define ST0_INTR 0xC0 /* Interrupt code mask */ +#define ST0_INTR_OK (0 << 6) +#define ST0_INTR_ERROR (1 << 6) +#define ST0_INTR_INVALID (2 << 6) +#define ST0_INTR_POLL_ERROR (3 << 6) + +/* Bits of FD_ST1 */ +#define ST1_MAM 0x01 /* Missing Address Mark */ +#define ST1_WP 0x02 /* Write Protect */ +#define ST1_ND 0x04 /* No Data - unreadable */ +#define ST1_OR 0x10 /* OverRun */ +#define ST1_CRC 0x20 /* CRC error in data or addr */ +#define ST1_EOC 0x80 /* End Of Cylinder */ + +/* Bits of FD_ST2 */ +#define ST2_MAM 0x01 /* Missing Address Mark (again) */ +#define ST2_BC 0x02 /* Bad Cylinder */ +#define ST2_SNS 0x04 /* Scan Not Satisfied */ +#define ST2_SEH 0x08 /* Scan Equal Hit */ +#define ST2_WC 0x10 /* Wrong Cylinder */ +#define ST2_CRC 0x20 /* CRC error in data field */ +#define ST2_CM 0x40 /* Control Mark = deleted */ + +/* Bits of FD_ST3 */ +#define ST3_HA 0x04 /* Head (Address) */ +#define ST3_DS 0x08 /* drive is double-sided */ +#define ST3_TZ 0x10 /* Track Zero signal (1=track 0) */ +#define ST3_RY 0x20 /* drive is ready */ +#define ST3_WP 0x40 /* Write Protect */ +#define ST3_FT 0x80 /* Drive Fault */ + +/* Values for FD_COMMAND */ +#define FD_RECALIBRATE 0x07 /* move to track 0 */ +#define FD_SEEK 0x0F /* seek track */ +#define FD_READ 0xA6 /* read with MT, SKip deleted */ +#define FD_WRITE 0xC5 /* write with MT, MFM */ +#define FD_SENSEI 0x08 /* Sense Interrupt Status */ +#define FD_SPECIFY 0x03 /* specify HUT etc */ +#define FD_FORMAT 0x4D /* format one track */ +#define FD_VERSION 0x10 /* get version code */ +#define FD_CONFIGURE 0x13 /* configure FIFO operation */ +#define FD_PERPENDICULAR 0x12 /* perpendicular r/w mode */ +#define FD_GETSTATUS 0x04 /* read ST3 */ +#define FD_DUMPREGS 0x0E /* dump the contents of the fdc regs */ +#define FD_READID 0xEA /* prints the header of a sector */ +#define FD_UNLOCK 0x14 /* Fifo config unlock */ +#define FD_LOCK 0x94 /* Fifo config lock */ +#define FD_RSEEK_OUT 0x8f /* seek out (i.e. to lower tracks) */ +#define FD_RSEEK_IN 0xcf /* seek in (i.e. to higher tracks) */ + + +/* the following commands are new in the 82078. They are not used in the + * floppy driver, except the first three. These commands may be useful for apps + * which use the FDRAWCMD interface. For doc, get the 82078 spec sheets at + * http://www-techdoc.intel.com/docs/periph/fd_contr/datasheets/ */ + +#define FD_PARTID 0x18 /* part id ("extended" version cmd) */ +#define FD_SAVE 0x2e /* save fdc regs for later restore */ +#define FD_DRIVESPEC 0x8e /* drive specification: Access to the + * 2 Mbps data transfer rate for tape + * drives */ + +#define FD_RESTORE 0x4e /* later restore */ +#define FD_POWERDOWN 0x27 /* configure FDC's powersave features */ +#define FD_FORMAT_N_WRITE 0xef /* format and write in one go. */ +#define FD_OPTION 0x33 /* ISO format (which is a clean way to + * pack more sectors on a track) */ + +/* FDC version return types */ +#define FDC_NONE 0x00 +#define FDC_UNKNOWN 0x10 /* DO NOT USE THIS TYPE EXCEPT IF IDENTIFICATION + FAILS EARLY */ +#define FDC_8272A 0x20 /* Intel 8272a, NEC 765 */ +#define FDC_765ED 0x30 /* Non-Intel 1MB-compatible FDC, can't detect */ +#define FDC_82072 0x40 /* Intel 82072; 8272a + FIFO + DUMPREGS */ +#define FDC_82072A 0x45 /* 82072A (on Sparcs) */ +#define FDC_82077_ORIG 0x51 /* Original version of 82077AA, sans LOCK */ +#define FDC_82077 0x52 /* 82077AA-1 */ +#define FDC_82078_UNKN 0x5f /* Unknown 82078 variant */ +#define FDC_82078 0x60 /* 44pin 82078 or 64pin 82078SL */ +#define FDC_82078_1 0x61 /* 82078-1 (2Mbps fdc) */ +#define FDC_S82078B 0x62 /* S82078B (first seen on Adaptec AVA-2825 VLB + * SCSI/EIDE/Floppy controller) */ +#define FDC_87306 0x63 /* National Semiconductor PC 87306 */ + +/* + * Beware: the fdc type list is roughly sorted by increasing features. + * Presence of features is tested by comparing the FDC version id with the + * "oldest" version that has the needed feature. + * If during FDC detection, an obscure test fails late in the sequence, don't + * assign FDC_UNKNOWN. Else the FDC will be treated as a dumb 8272a, or worse. + * This is especially true if the tests are unneeded. + */ + +/* Parameters for a 1.44 3.5" disk */ +#define DISK_H1440_SIZE 2880 +#define DISK_H1440_SECT 18 +#define DISK_H1440_HEAD 2 +#define DISK_H1440_TRACK 80 +#define DISK_H1440_STRETCH 0 +#define DISK_H1440_GAP 0x1B +#define DISK_H1440_RATE 0x00 +#define DISK_H1440_SPEC1 0xCF +#define DISK_H1440_FMT_GAP 0x6C + +/* Parameters for a 1.44 3.5" drive */ +#define DRIVE_H1440_MAX_DTR 500 +#define DRIVE_H1440_HLT 16 /* ms */ +#define DRIVE_H1440_HUT 16 /* ms */ +#define DRIVE_H1440_SRT 4000 /* us */ +#define DRIVE_H1440_SPINUP 400 /* ms */ +#define DRIVE_H1440_SPINDOWN 3000 /* ms */ +#define DRIVE_H1440_SPINDOWN_OFFSET 10 +#define DRIVE_H1440_SELECT_DELAY 20 /* ms */ +#define DRIVE_H1440_RPS 5 +#define DRIVE_H1440_TRACKS 83 +#define DRIVE_H1440_TIMEOUT 3000 /* ms */ +#define DRIVE_H1440_INTERLEAVE_SECT 20 + +/* Floppy drive configuration */ +#define FIFO_DEPTH 10 +#define USE_IMPLIED_SEEK 0 +#define USE_FIFO 1 +#define FIFO_THRESHOLD 10 +#define TRACK_PRECOMPENSATION 0 + +#define SLOW_FLOPPY 0 + +#define FD_RESET_DELAY 20 /* microseconds */ + +/* + * FDC state + */ +static struct drive_state { + unsigned track; +} drive_state[1]; + +static struct floppy_fdc_state { + int in_sync; + int spec1; /* spec1 value last used */ + int spec2; /* spec2 value last used */ + int dtr; + unsigned char dor; + unsigned char version; /* FDC version code */ + void (*fdc_outb)(unsigned char data, unsigned long port); + unsigned char (*fdc_inb)(unsigned long port); + unsigned long io_base; + unsigned long mmio_base; +} fdc_state; + +/* Synchronization of FDC access. */ +#define FD_COMMAND_NONE -1 +#define FD_COMMAND_ERROR 2 +#define FD_COMMAND_OKAY 3 + +/* + * globals used by 'result()' + */ +#define MAX_REPLIES 16 + +static void show_floppy(void); +static void floppy_reset(void); + +/* + * IO port operations + */ +static unsigned char +ob_fdc_inb(unsigned long port) +{ + return inb(fdc_state.io_base + port); +} + +static void +ob_fdc_outb(unsigned char data, unsigned long port) +{ + outb(data, fdc_state.io_base + port); +} + +/* + * MMIO operations + */ +static unsigned char +ob_fdc_mmio_readb(unsigned long port) +{ + return *(unsigned char *)(fdc_state.mmio_base + port); +} + +static void +ob_fdc_mmio_writeb(unsigned char data, unsigned long port) +{ + *(unsigned char *)(fdc_state.mmio_base + port) = data; +} + +static int set_dor(char mask, char data) +{ + unsigned char newdor,olddor; + + olddor = fdc_state.dor; + newdor = (olddor & mask) | data; + if (newdor != olddor){ + fdc_state.dor = newdor; + fdc_state.fdc_outb(newdor, FD_DOR); + } + return olddor; +} + +/* waits until the fdc becomes ready */ +static int wait_til_ready(void) +{ + int counter, status; + for (counter = 0; counter < 10000; counter++) { + status = fdc_state.fdc_inb(FD_STATUS); + if (status & STATUS_READY) { + return status; + } + } + printk_debug("Getstatus times out (%x)\n", status); + show_floppy(); + return -3; +} + + +/* sends a command byte to the fdc */ +static int output_byte(unsigned char byte) +{ + int status; + + if ((status = wait_til_ready()) < 0) + return status; + if ((status & (STATUS_READY|STATUS_DIR|STATUS_NON_DMA)) == STATUS_READY){ + fdc_state.fdc_outb(byte,FD_DATA); + return 0; + } + printk_debug("Unable to send byte %x to FDC_STATE. Status=%x\n", + byte, status); + + show_floppy(); + return -2; +} + +/* gets the response from the fdc */ +static int result(unsigned char *reply_buffer, int max_replies) +{ + int i, status=0; + + for(i=0; i < max_replies; i++) { + if ((status = wait_til_ready()) < 0) + break; + status &= STATUS_DIR|STATUS_READY|STATUS_BUSY|STATUS_NON_DMA; + if ((status & ~STATUS_BUSY) == STATUS_READY){ + return i; + } + if (status == (STATUS_DIR|STATUS_READY|STATUS_BUSY)) + reply_buffer[i] = fdc_state.fdc_inb(FD_DATA); + else + break; + } + if (i == max_replies) + return i; + printk_debug("get result error. Last status=%x Read bytes=%d\n", + status, i); + show_floppy(); + return -1; +} +#define MORE_OUTPUT -2 +/* does the fdc need more output? */ +static int need_more_output(void) +{ + unsigned char reply_buffer[MAX_REPLIES]; + int status; + if ((status = wait_til_ready()) < 0) + return -1; + if ((status & (STATUS_READY|STATUS_DIR|STATUS_NON_DMA)) == STATUS_READY) + return MORE_OUTPUT; + return result(reply_buffer, MAX_REPLIES); +} + +static int output_command(unsigned char *cmd, int count) +{ + int i, status; + for(i = 0; i < count; i++) { + if ((status = output_byte(cmd[i])) < 0) { + printk_err("full command not acceppted, status =%x\n", + status); + return -1; + } + } + return 0; +} + +static int output_new_command(unsigned char *cmd, int count) +{ + int i, status; + if ((status = output_byte(cmd[0])) < 0) + return -1; + if (need_more_output() != MORE_OUTPUT) + return -1; + for(i = 1; i < count; i++) { + if ((status = output_byte(cmd[i])) < 0) { + printk_err("full new command not acceppted, status =%d\n", + status); + return -1; + } + } + return 0; +} + + +/* Collect pending interrupt status */ +static unsigned char collect_interrupt(void) +{ + unsigned char pcn = 0xff; + unsigned char reply_buffer[MAX_REPLIES]; + int nr; +#ifdef CONFIG_DEBUG_FLOPPY + int i, status; +#endif + nr = result(reply_buffer, MAX_REPLIES); + if (nr != 0) { + printk_debug("SENSEI\n"); + } + else { + int max_sensei = 4; + do { + if (output_byte(FD_SENSEI) < 0) + break; + nr = result(reply_buffer, MAX_REPLIES); + if (nr == 2) { + pcn = reply_buffer[1]; + printk_debug("SENSEI %02x %02x\n", + reply_buffer[0], reply_buffer[1]); + } + max_sensei--; + }while(((reply_buffer[0] & 0x83) != FD_DRIVE) && (nr == 2) && max_sensei); +#ifdef CONFIG_DEBUG_FLOPPY + status = fdc_state.fdc_inb(FD_STATUS); + printk_debug("status = %x, reply_buffer=", status); + for(i = 0; i < nr; i++) { + printk_debug(" %x", + reply_buffer[i]); + } + printk_debug("\n"); +#else + fdc_state.fdc_inb(FD_STATUS); +#endif + } + + return pcn; +} + + +/* selects the fdc and drive, and enables the fdc's input/dma, and it's motor. */ +static void set_drive(int drive) +{ + int fdc = (drive >> 2) & 1; + int status; + unsigned new_dor; + if (drive > 3) { + printk_err("bad drive value\n"); + return; + } + if (fdc != 0) { + printk_err("bad fdc value\n"); + return; + } + drive &= 3; +#if 0 + new_dor = 8; /* Enable the controller */ +#else + new_dor = 0; /* Don't enable DMA on the controller */ +#endif + new_dor |= (1 << (drive + 4)); /* Spinup the selected drive */ + new_dor |= drive; /* Select the drive for commands as well */ + set_dor(0xc, new_dor); + + mdelay(DRIVE_H1440_SPINUP); + + status = fdc_state.fdc_inb(FD_STATUS); + printk_debug("set_drive status = %02x, new_dor = %02x\n", + status, new_dor); + if (status != STATUS_READY) { + printk_err("set_drive bad status\n"); + } +} + + +/* Disable the motor for a given floppy drive */ +static void floppy_motor_off(int drive) +{ + unsigned mask; + printk_debug("floppy_motor_off\n"); + /* fix the number of drives */ + drive &= 3; + /* Clear the bit for the drive we care about */ + mask = 0xff; + mask &= ~(1 << (drive +4)); + /* Now clear the bit in the Digital Output Register */ + set_dor(mask, 0); +} + +/* Set the FDC's data transfer rate on behalf of the specified drive. + * NOTE: with 82072/82077 FDCs, changing the data rate requires a reissue + * of the specify command (i.e. using the fdc_specify function). + */ +static void fdc_dtr(unsigned rate) +{ + rate &= 3; + /* If data rate not already set to desired value, set it. */ + if (fdc_state.in_sync && (rate == fdc_state.dtr)) + return; + + /* Set dtr */ + fdc_state.fdc_outb(rate, FD_DCR); + + /* TODO: some FDC/drive combinations (C&T 82C711 with TEAC 1.2MB) + * need a stabilization period of several milliseconds to be + * enforced after data rate changes before R/W operations. + * Pause 5 msec to avoid trouble. (Needs to be 2 jiffies) + */ + fdc_state.dtr = rate & 3; + mdelay(5); +} /* fdc_dtr */ + +static int fdc_configure(int use_implied_seek, int use_fifo, + unsigned fifo_threshold, unsigned precompensation) +{ + unsigned config_bits; + unsigned char cmd[4]; + /* 0 EIS EFIFO POLL FIFOOTHR[4] */ + + /* santize parameters */ + config_bits = fifo_threshold & 0xf; + config_bits |= (1 << 4); /* Always disable background floppy poll */ + config_bits |= (!use_fifo) << 5; + config_bits |= (!!use_implied_seek) << 6; + + precompensation &= 0xff; /* pre-compensation from track 0 upwards */ + + cmd[0] = FD_CONFIGURE; + cmd[1] = 0; + cmd[2] = config_bits; + cmd[3] = precompensation; + + /* Turn on FIFO */ + if (output_new_command(cmd, 4) < 0) + return 0; + return 1; +} + +#define NOMINAL_DTR 500 +/* Issue a "SPECIFY" command to set the step rate time, head unload time, + * head load time, and DMA disable flag to values needed by floppy. + * + * The value "dtr" is the data transfer rate in Kbps. It is needed + * to account for the data rate-based scaling done by the 82072 and 82077 + * FDC types. This parameter is ignored for other types of FDCs (i.e. + * 8272a). + * + * Note that changing the data transfer rate has a (probably deleterious) + * effect on the parameters subject to scaling for 82072/82077 FDCs, so + * fdc_specify is called again after each data transfer rate + * change. + * + * srt: 1000 to 16000 in microseconds + * hut: 16 to 240 milliseconds + * hlt: 2 to 254 milliseconds + * + * These values are rounded up to the next highest available delay time. + */ +static void fdc_specify( + unsigned head_load_time, unsigned head_unload_time, unsigned step_rate) +{ + unsigned char cmd[3]; + unsigned long srt, hlt, hut; + unsigned long dtr = NOMINAL_DTR; + unsigned long scale_dtr = NOMINAL_DTR; + int hlt_max_code = 0x7f; + int hut_max_code = 0xf; + + printk_debug("fdc_specify\n"); + + switch (DISK_H1440_RATE & 0x03) { + case 3: + dtr = 1000; + break; + case 1: + dtr = 300; + if (fdc_state.version >= FDC_82078) { + /* chose the default rate table, not the one + * where 1 = 2 Mbps */ + cmd[0] = FD_DRIVESPEC; + cmd[1] = FD_DRIVE & 3; + cmd[2] = 0xc0; + output_new_command(cmd,3); + /* FIXME how do I handle errors here? */ + } + break; + case 2: + dtr = 250; + break; + } + + + if (fdc_state.version >= FDC_82072) { + scale_dtr = dtr; + hlt_max_code = 0x00; /* 0==256msec*dtr0/dtr (not linear!) */ + hut_max_code = 0x0; /* 0==256msec*dtr0/dtr (not linear!) */ + } + + /* Convert step rate from microseconds to milliseconds and 4 bits */ + srt = 16 - (step_rate*scale_dtr/1000 + NOMINAL_DTR - 1)/NOMINAL_DTR; + if (SLOW_FLOPPY) { + srt = srt / 4; + } + if (srt > 0xf) { + srt = 0xf; + } + + hlt = (head_load_time*scale_dtr/2 + NOMINAL_DTR - 1)/NOMINAL_DTR; + if (hlt < 0x01) + hlt = 0x01; + else if (hlt > 0x7f) + hlt = hlt_max_code; + + hut = (head_unload_time*scale_dtr/16 + NOMINAL_DTR - 1)/NOMINAL_DTR; + if (hut < 0x1) + hut = 0x1; + else if (hut > 0xf) + hut = hut_max_code; + + cmd[0] = FD_SPECIFY; + cmd[1] = (srt << 4) | hut; + cmd[2] = (hlt << 1) | 1; /* Always disable DMA */ + + /* If these parameters did not change, just return with success */ + if (!fdc_state.in_sync || fdc_state.spec1 != cmd[1] || fdc_state.spec2 != cmd[2]) { + /* Go ahead and set spec1 and spec2 */ + output_command(cmd, 3); + /* FIXME how do I handle errors here... */ + printk_info("FD_SPECIFY(%02x, %02x)\n", cmd[1], cmd[2]); + } +} /* fdc_specify */ + + +/* + * reset is done by pulling bit 2 of DOR low for a while (old FDCs), + * or by setting the self clearing bit 7 of STATUS (newer FDCs) + */ +static void reset_fdc(void) +{ + unsigned char reply[MAX_REPLIES]; + + fdc_state.in_sync = 0; + + /* Pseudo-DMA may intercept 'reset finished' interrupt. */ + /* Irrelevant for systems with true DMA (i386). */ + + if (fdc_state.version >= FDC_82072A) + fdc_state.fdc_outb(0x80 | (fdc_state.dtr &3), FD_DSR); + else { + fdc_state.fdc_outb(fdc_state.dor & ~DOR_NO_RESET, FD_DOR); + udelay(FD_RESET_DELAY); + fdc_state.fdc_outb(fdc_state.dor, FD_DOR); + } + result(reply, MAX_REPLIES); +} + + + +static void show_floppy(void) +{ + + printk_debug("\n"); + printk_debug("floppy driver state\n"); + printk_debug("-------------------\n"); + + printk_debug("fdc_bytes: %02x %02x xx %02x %02x %02x xx %02x\n", + fdc_state.fdc_inb(FD_STATUS_A), + fdc_state.fdc_inb(FD_STATUS_B), + fdc_state.fdc_inb(FD_TDR), + fdc_state.fdc_inb(FD_STATUS), + fdc_state.fdc_inb(FD_DATA), + fdc_state.fdc_inb(FD_DIR)); + + printk_debug("status=%x\n", fdc_state.fdc_inb(FD_STATUS)); + printk_debug("\n"); +} + +static void floppy_recalibrate(void) +{ + unsigned char cmd[2]; + unsigned char reply[MAX_REPLIES]; + int nr, success; + success = 0; + do { + printk_debug("floppy_recalibrate\n"); + /* Send the recalibrate command to the controller. + * We don't have interrupts or anything we can poll + * so we have to guess when it is done. + */ + cmd[0] = FD_RECALIBRATE; + cmd[1] = 0; + if (output_command(cmd, 2) < 0) + continue; + + /* Sleep for the maximum time the recalibrate command + * can run. + */ + mdelay(80*DRIVE_H1440_SRT/1000); + + /* Now call FD_SENSEI to end the command + * and collect up the reply. + */ + if (output_byte(FD_SENSEI) < 0) + continue; + nr = result(reply, MAX_REPLIES); + + /* Now see if we have succeeded in our seek */ + success = + /* We have the right size result */ + (nr == 2) && + /* The command didn't terminate in error */ + ((reply[0] & ST0_INTR) == ST0_INTR_OK) && + /* We finished a seek */ + (reply[0] & ST0_SE) && + /* We are at cylinder 0 */ + (reply[1] == 0); + } while(!success); + /* Remember we are at track 0 */ + drive_state[FD_DRIVE].track = 0; +} + + +static int floppy_seek(unsigned track) +{ + unsigned char cmd[3]; + unsigned char reply[MAX_REPLIES]; + int nr, success; + unsigned distance, old_track; + + /* Look up the old track and see if we need to + * do anything. + */ + old_track = drive_state[FD_DRIVE].track; + if (old_track == track) { + return 1; + } + + /* Compute the distance we are about to move, + * We need to know this so we know how long to sleep... + */ + distance = (old_track > track)?(old_track - track):(track - old_track); + distance += 1; + + + /* Send the seek command to the controller. + * We don't have interrupts or anything we can poll + * so we have to guess when it is done. + */ + cmd[0] = FD_SEEK; + cmd[1] = FD_DRIVE; + cmd[2] = track; + if (output_command(cmd, 3) < 0) + return 0; + + /* Sleep for the time it takes to step throuhg distance tracks. + */ + mdelay(distance*DRIVE_H1440_SRT/1000); + + /* Now call FD_SENSEI to end the command + * and collect up the reply. + */ + cmd[0] = FD_SENSEI; + if (output_command(cmd, 1) < 0) + return 0; + nr = result(reply, MAX_REPLIES); + + /* Now see if we have succeeded in our seek */ + success = + /* We have the right size result */ + (nr == 2) && + /* The command didn't terminate in error */ + ((reply[0] & ST0_INTR) == ST0_INTR_OK) && + /* We finished a seek */ + (reply[0] & ST0_SE) && + /* We are at cylinder 0 */ + (reply[1] == track); + if (success) + drive_state[FD_DRIVE].track = track; + else { + printk_debug("seek failed\n"); + printk_debug("nr = %d\n", nr); + printk_debug("ST0 = %02x\n", reply[0]); + printk_debug("PCN = %02x\n", reply[1]); + printk_debug("status = %d\n", fdc_state.fdc_inb(FD_STATUS)); + } + return success; +} + +static int read_ok(unsigned head) +{ + unsigned char results[7]; + int result_ok; + int nr; + + /* read back the read results */ + nr = result(results, 7); + + /* Now see if they say we are o.k. */ + result_ok = 0; + /* Are my result bytes o.k.? */ + if (nr == 7) { + /* Are we o.k. */ + if ((results[0] & ST0_INTR) == ST0_INTR_OK) { + result_ok = 1; + } + /* Or did we get just an overflow error */ + else if (((results[0] & ST0_INTR) == ST0_INTR_ERROR) && + (results[1]== ST1_OR) && + (results[2] == 0)) { + result_ok = 1; + } + /* Verify the reply had the correct head */ + if (((results[0] & ST0_HA) >> 2) != head) { + result_ok = 0; + } + /* Verify the reply had the correct drive */ + if (((results[0] & ST0_DS) != FD_DRIVE)) { + result_ok = 0; + } + } + if (!result_ok) { + printk_debug("result_bytes = %d\n", nr); + printk_debug("ST0 = %02x\n", results[0]); + printk_debug("ST1 = %02x\n", results[1]); + printk_debug("ST2 = %02x\n", results[2]); + printk_debug(" C = %02x\n", results[3]); + printk_debug(" H = %02x\n", results[4]); + printk_debug(" R = %02x\n", results[5]); + printk_debug(" N = %02x\n", results[6]); + } + return result_ok; +} + +static int floppy_read_sectors( + char *dest, unsigned byte_offset, unsigned length, + unsigned sector, unsigned head, unsigned track) +{ + /* MT == Multitrack */ + /* MFM == MFM or FM Mode */ + /* SK == Skip deleted data addres Mark */ + /* HDS == Head number select */ + /* DS0 == Disk Drive Select 0 */ + /* DS1 == Disk Drive Select 1 */ + /* C == Cylinder number 0 - 255 */ + /* H == Head number */ + /* R == Record */ + /* N == The number of data bytes written in a sector */ + /* EOT == End of Track */ + /* GPL == Gap Length */ + /* DTL == Data Length */ + /* MT MFM SK 0 1 1 0 0 */ + /* 0 0 0 0 0 HDS DS1 DS0 */ + /* C, H, R, N, EOT, GPL, DTL */ + + int i, status, result_ok; + int max_bytes, bytes_read; + int ret; + unsigned char cmd[9]; + unsigned end_offset; + + end_offset = byte_offset + length; + max_bytes = 512*(DISK_H1440_SECT - sector + 1); + + if (byte_offset >= max_bytes) { + return 0; + } + cmd[0] = FD_READ | (((DISK_H1440_HEAD ==2)?1:0) << 6); + cmd[1] = (head << 2) | FD_DRIVE; + cmd[2] = track; + cmd[3] = head; + cmd[4] = sector; + cmd[5] = 2; /* 2^N *128 == Sector size. Hard coded to 512 bytes */ + cmd[6] = DISK_H1440_SECT; + cmd[7] = DISK_H1440_GAP; + cmd[8] = 0xff; + + /* Output the command bytes */ + if (output_command(cmd, 9) < 0) + return -1; + + /* The execution stage begins when STATUS_READY&STATUS_NON_DMA is set */ + do { + status = fdc_state.fdc_inb(FD_STATUS); + status &= STATUS_READY | STATUS_NON_DMA; + } while(status != (STATUS_READY|STATUS_NON_DMA)); + + for(i = 0; i < max_bytes; i++) { + unsigned char byte; + if ((status = wait_til_ready()) < 0) { + break; + } + status &= STATUS_READY|STATUS_DIR|STATUS_NON_DMA; + if (status != (STATUS_READY|STATUS_DIR|STATUS_NON_DMA)) { + break; + } + byte = fdc_state.fdc_inb(FD_DATA); + if ((i >= byte_offset) && (i < end_offset)) { + dest[i - byte_offset] = byte; + } + } + bytes_read = i; + + /* The result stage begins when STATUS_NON_DMA is cleared */ + while((status = fdc_state.fdc_inb(FD_STATUS)) & STATUS_NON_DMA) { + /* We get extra bytes in the fifo past + * the end of the sector and drop them on the floor. + * Otherwise the fifo is polluted. + */ + fdc_state.fdc_inb(FD_DATA); + } + /* Did I get an error? */ + result_ok = read_ok(head); + /* Did I read enough bytes? */ + ret = -1; + if (result_ok && (bytes_read == max_bytes)) { + ret = bytes_read - byte_offset; + if (ret > length) { + ret = length; + } + } + + if (ret < 0) { + printk_debug("ret = %d\n", ret); + printk_debug("bytes_read = %d\n", bytes_read); + printk_debug("status = %x\n", status); + } + return ret; +} + + +static int __floppy_read(char *dest, unsigned long offset, unsigned long length) +{ + unsigned head, track, sector, byte_offset, sector_offset; + int ret; + + /* break the offset up into sectors and bytes */ + byte_offset = offset % 512; + sector_offset = offset / 512; + + /* Find the disk block we are starting with... */ + sector = (sector_offset % DISK_H1440_SECT) + 1; + head = (sector_offset / DISK_H1440_SECT) % DISK_H1440_HEAD; + track = (sector_offset / (DISK_H1440_SECT *DISK_H1440_HEAD))% DISK_H1440_TRACK; + + /* First seek to our start track */ + if (!floppy_seek(track)) { + return -1; + } + /* Then read the data */ + ret = floppy_read_sectors(dest, byte_offset, length, sector, head, track); + if (ret >= 0) { + return ret; + } + /* If we failed reset the fdc... */ + floppy_reset(); + return -1; +} + +static int floppy_read(char *dest, unsigned long offset, unsigned long length) +{ + int fr_result, bytes_read;; + + printk_debug("floppy_read\n"); + bytes_read = 0; + do { + int max_errors = 3; + do { + fr_result = __floppy_read(dest + bytes_read, offset, + length - bytes_read); + if (max_errors-- == 0) { + return (bytes_read)?bytes_read: -1; + } + } while (fr_result <= 0); + offset += fr_result; + bytes_read += fr_result; + } while(bytes_read < length); + return bytes_read; +} + +/* Determine the floppy disk controller type */ +/* This routine was written by David C. Niemi */ +static char get_fdc_version(void) +{ + int bytes, ret; + unsigned char reply_buffer[MAX_REPLIES]; + + ret = output_byte(FD_DUMPREGS); /* 82072 and better know DUMPREGS */ + if (ret < 0) + return FDC_NONE; + if ((bytes = result(reply_buffer, MAX_REPLIES)) <= 0x00) + return FDC_NONE; /* No FDC present ??? */ + if ((bytes==1) && (reply_buffer[0] == 0x80)){ + printk_info("FDC is an 8272A\n"); + return FDC_8272A; /* 8272a/765 don't know DUMPREGS */ + } + if (bytes != 10) { + printk_debug("init: DUMPREGS: unexpected return of %d bytes.\n", + bytes); + return FDC_UNKNOWN; + } + if (!fdc_configure(USE_IMPLIED_SEEK, USE_FIFO, FIFO_THRESHOLD, + TRACK_PRECOMPENSATION)) { + printk_info("FDC is an 82072\n"); + return FDC_82072; /* 82072 doesn't know CONFIGURE */ + } + + output_byte(FD_PERPENDICULAR); + if (need_more_output() == MORE_OUTPUT) { + output_byte(0); + } else { + printk_info("FDC is an 82072A\n"); + return FDC_82072A; /* 82072A as found on Sparcs. */ + } + + output_byte(FD_UNLOCK); + bytes = result(reply_buffer, MAX_REPLIES); + if ((bytes == 1) && (reply_buffer[0] == 0x80)){ + printk_info("FDC is a pre-1991 82077\n"); + return FDC_82077_ORIG; /* Pre-1991 82077, doesn't know + * LOCK/UNLOCK */ + } + if ((bytes != 1) || (reply_buffer[0] != 0x00)) { + printk_debug("FDC init: UNLOCK: unexpected return of %d bytes.\n", + bytes); + return FDC_UNKNOWN; + } + output_byte(FD_PARTID); + bytes = result(reply_buffer, MAX_REPLIES); + if (bytes != 1) { + printk_debug("FDC init: PARTID: unexpected return of %d bytes.\n", + bytes); + return FDC_UNKNOWN; + } + if (reply_buffer[0] == 0x80) { + printk_info("FDC is a post-1991 82077\n"); + return FDC_82077; /* Revised 82077AA passes all the tests */ + } + switch (reply_buffer[0] >> 5) { + case 0x0: + /* Either a 82078-1 or a 82078SL running at 5Volt */ + printk_info("FDC is an 82078.\n"); + return FDC_82078; + case 0x1: + printk_info("FDC is a 44pin 82078\n"); + return FDC_82078; + case 0x2: + printk_info("FDC is a S82078B\n"); + return FDC_S82078B; + case 0x3: + printk_info("FDC is a National Semiconductor PC87306\n"); + return FDC_87306; + default: + printk_info("FDC init: 82078 variant with unknown PARTID=%d.\n", + reply_buffer[0] >> 5); + return FDC_82078_UNKN; + } +} /* get_fdc_version */ + + +static int floppy_init(unsigned long io_base, unsigned long mmio_base) +{ + printk_debug("floppy_init\n"); + fdc_state.in_sync = 0; + fdc_state.spec1 = -1; + fdc_state.spec2 = -1; + fdc_state.dtr = -1; + fdc_state.dor = DOR_NO_RESET; + fdc_state.version = FDC_UNKNOWN; + if (mmio_base) { + fdc_state.fdc_inb = ob_fdc_mmio_readb; + fdc_state.fdc_outb = ob_fdc_mmio_writeb; + } else { + fdc_state.fdc_inb = ob_fdc_inb; + fdc_state.fdc_outb = ob_fdc_outb; + } + fdc_state.io_base = io_base; + fdc_state.mmio_base = mmio_base; + reset_fdc(); + /* Try to determine the floppy controller type */ + fdc_state.version = get_fdc_version(); + if (fdc_state.version == FDC_NONE) { + return -1; + } + floppy_reset(); + printk_info("fdc_state.version = %04x\n", fdc_state.version); + return 0; +} + +static void floppy_reset(void) +{ + printk_debug("floppy_reset\n"); + floppy_motor_off(FD_DRIVE); + reset_fdc(); + fdc_dtr(DISK_H1440_RATE); + /* program data rate via ccr */ + collect_interrupt(); + fdc_configure(USE_IMPLIED_SEEK, USE_FIFO, FIFO_THRESHOLD, + TRACK_PRECOMPENSATION); + fdc_specify(DRIVE_H1440_HLT, DRIVE_H1440_HUT, DRIVE_H1440_SRT); + set_drive(FD_DRIVE); + floppy_recalibrate(); + fdc_state.in_sync = 1; +} + +static void +ob_floppy_initialize(const char *path) +{ + int props[3]; + phandle_t ph = find_dev(path); + + set_property(ph, "device_type", "block", sizeof("block")); + + // Set dummy reg properties + props[0] = __cpu_to_be32(0); props[1] = __cpu_to_be32(0); props[2] = __cpu_to_be32(0); + set_property(ph, "reg", (char *)&props, 3*sizeof(int)); + + fword("is-deblocker"); +} + + +static void +ob_floppy_open(int *idx) +{ + int ret = 1; + phandle_t ph; + + fword("my-unit"); + idx[0]=POP(); + + fword("my-parent"); + fword("ihandle>phandle"); + ph=(phandle_t)POP(); + + selfword("open-deblocker"); + + /* interpose disk-label */ + ph = find_dev("/packages/disk-label"); + fword("my-args"); + PUSH_ph( ph ); + fword("interpose"); + + RET ( -ret ); +} + +static void +ob_floppy_close(int *idx) +{ + selfword("close-deblocker"); +} + +static void +ob_floppy_read_blocks(int *idx) +{ + cell cnt = POP(); + ucell blk = POP(); + char *dest = (char*)POP(); + floppy_read(dest, blk*512, cnt*512); + PUSH(cnt); +} + + +static void +ob_floppy_block_size(int *idx) +{ + PUSH(512); +} + +static void +ob_floppy_max_transfer(int *idx) +{ + // Fixme + PUSH(18 * 512); +} + +NODE_METHODS(ob_floppy) = { + { "open", ob_floppy_open }, + { "close", ob_floppy_close }, + { "read-blocks", ob_floppy_read_blocks }, + { "block-size", ob_floppy_block_size }, + { "max-transfer", ob_floppy_max_transfer }, +}; + + +int ob_floppy_init(const char *path, const char *dev_name, + unsigned long io_base, unsigned long mmio_base) +{ + char nodebuff[128]; + phandle_t aliases; + + snprintf(nodebuff, sizeof(nodebuff), "%s/%s", path, dev_name); + if (!mmio_base) { + REGISTER_NAMED_NODE(ob_floppy, nodebuff); + ob_floppy_initialize(nodebuff); + } else { + // Already in tree and mapped + REGISTER_NODE_METHODS(ob_floppy, nodebuff); + } + floppy_init(io_base, mmio_base); + + aliases = find_dev("/aliases"); + set_property(aliases, "floppy", nodebuff, strlen(nodebuff) + 1); + + return 0; +} diff --git a/qemu/roms/openbios/drivers/floppy.h b/qemu/roms/openbios/drivers/floppy.h new file mode 100644 index 000000000..b0f30d555 --- /dev/null +++ b/qemu/roms/openbios/drivers/floppy.h @@ -0,0 +1,9 @@ +#ifndef FLOPPY_SUBR_H +#define FLOPPY_SUBR_H + +int floppy_init(void); +int floppy_read(char *dest, unsigned long offset, unsigned long length); +void floppy_fini(void); + + +#endif /* FLOPPY_SUBR_H */ diff --git a/qemu/roms/openbios/drivers/fw_cfg.c b/qemu/roms/openbios/drivers/fw_cfg.c new file mode 100644 index 000000000..402757070 --- /dev/null +++ b/qemu/roms/openbios/drivers/fw_cfg.c @@ -0,0 +1,76 @@ +#include "config.h" +#include "libopenbios/bindings.h" +#include "libc/byteorder.h" +#include "libopenbios/ofmem.h" +#define NO_QEMU_PROTOS +#include "arch/common/fw_cfg.h" + +#if !defined(CONFIG_SPARC64) +static volatile uint16_t *fw_cfg_cmd; +static volatile uint8_t *fw_cfg_data; + +void +fw_cfg_read(uint16_t cmd, char *buf, unsigned int nbytes) +{ + unsigned int i; + + *fw_cfg_cmd = cmd; + for (i = 0; i < nbytes; i++) + buf[i] = *fw_cfg_data; +} +#else +// XXX depends on PCI bus location, should be removed +void +fw_cfg_read(uint16_t cmd, char *buf, unsigned int nbytes) +{ + unsigned int i; + + outw(cmd, CONFIG_FW_CFG_ADDR); + for (i = 0; i < nbytes; i++) + buf[i] = inb(CONFIG_FW_CFG_ADDR + 1); +} +#endif + +uint64_t +fw_cfg_read_i64(uint16_t cmd) +{ + uint64_t buf; + + fw_cfg_read(cmd, (char *)&buf, sizeof(uint64_t)); + + return __le64_to_cpu(buf); +} + +uint32_t +fw_cfg_read_i32(uint16_t cmd) +{ + uint32_t buf; + + fw_cfg_read(cmd, (char *)&buf, sizeof(uint32_t)); + + return __le32_to_cpu(buf); +} + +uint16_t +fw_cfg_read_i16(uint16_t cmd) +{ + uint16_t buf; + + fw_cfg_read(cmd, (char *)&buf, sizeof(uint16_t)); + + return __le16_to_cpu(buf); +} + +void +fw_cfg_init(void) +{ +#if defined(CONFIG_SPARC32) + fw_cfg_cmd = (void *)ofmem_map_io(CONFIG_FW_CFG_ADDR, 2); + fw_cfg_data = (uint8_t *)fw_cfg_cmd + 2; +#elif defined(CONFIG_SPARC64) + // Nothing for the port version +#elif defined(CONFIG_PPC) + fw_cfg_cmd = (void *)CONFIG_FW_CFG_ADDR; + fw_cfg_data = (void *)(CONFIG_FW_CFG_ADDR + 2); +#endif +} diff --git a/qemu/roms/openbios/drivers/hdreg.h b/qemu/roms/openbios/drivers/hdreg.h new file mode 100644 index 000000000..91e4d1ff6 --- /dev/null +++ b/qemu/roms/openbios/drivers/hdreg.h @@ -0,0 +1,289 @@ +/* + * this header holds data structures as dictated by spec + */ +#ifndef HDREG_H +#define HDREG_H + +struct hd_driveid { + unsigned short config; /* lots of obsolete bit flags */ + unsigned short cyls; /* Obsolete, "physical" cyls */ + unsigned short reserved2; /* reserved (word 2) */ + unsigned short heads; /* Obsolete, "physical" heads */ + unsigned short track_bytes; /* unformatted bytes per track */ + unsigned short sector_bytes; /* unformatted bytes per sector */ + unsigned short sectors; /* Obsolete, "physical" sectors per track */ + unsigned short vendor0; /* vendor unique */ + unsigned short vendor1; /* vendor unique */ + unsigned short vendor2; /* Retired vendor unique */ + unsigned char serial_no[20]; /* 0 = not_specified */ + unsigned short buf_type; /* Retired */ + unsigned short buf_size; /* Retired, 512 byte increments + * 0 = not_specified + */ + unsigned short ecc_bytes; /* for r/w long cmds; 0 = not_specified */ + unsigned char fw_rev[8]; /* 0 = not_specified */ + unsigned char model[40]; /* 0 = not_specified */ + unsigned char max_multsect; /* 0=not_implemented */ + unsigned char vendor3; /* vendor unique */ + unsigned short dword_io; /* 0=not_implemented; 1=implemented */ + unsigned char vendor4; /* vendor unique */ + unsigned char capability; /* (upper byte of word 49) + * 3: IORDYsup + * 2: IORDYsw + * 1: LBA + * 0: DMA + */ + unsigned short reserved50; /* reserved (word 50) */ + unsigned char vendor5; /* Obsolete, vendor unique */ + unsigned char tPIO; /* Obsolete, 0=slow, 1=medium, 2=fast */ + unsigned char vendor6; /* Obsolete, vendor unique */ + unsigned char tDMA; /* Obsolete, 0=slow, 1=medium, 2=fast */ + unsigned short field_valid; /* (word 53) + * 2: ultra_ok word 88 + * 1: eide_ok words 64-70 + * 0: cur_ok words 54-58 + */ + unsigned short cur_cyls; /* Obsolete, logical cylinders */ + unsigned short cur_heads; /* Obsolete, l heads */ + unsigned short cur_sectors; /* Obsolete, l sectors per track */ + unsigned short cur_capacity0; /* Obsolete, l total sectors on drive */ + unsigned short cur_capacity1; /* Obsolete, (2 words, misaligned int) */ + unsigned char multsect; /* current multiple sector count */ + unsigned char multsect_valid; /* when (bit0==1) multsect is ok */ + unsigned int lba_capacity; /* Obsolete, total number of sectors */ + unsigned short dma_1word; /* Obsolete, single-word dma info */ + unsigned short dma_mword; /* multiple-word dma info */ + unsigned short eide_pio_modes; /* bits 0:mode3 1:mode4 */ + unsigned short eide_dma_min; /* min mword dma cycle time (ns) */ + unsigned short eide_dma_time; /* recommended mword dma cycle time (ns) */ + unsigned short eide_pio; /* min cycle time (ns), no IORDY */ + unsigned short eide_pio_iordy; /* min cycle time (ns), with IORDY */ + unsigned short words69_70[2]; /* reserved words 69-70 + * future command overlap and queuing + */ + /* HDIO_GET_IDENTITY currently returns only words 0 through 70 */ + unsigned short words71_74[4]; /* reserved words 71-74 + * for IDENTIFY PACKET DEVICE command + */ + unsigned short queue_depth; /* (word 75) + * 15:5 reserved + * 4:0 Maximum queue depth -1 + */ + unsigned short words76_79[4]; /* reserved words 76-79 */ + unsigned short major_rev_num; /* (word 80) */ + unsigned short minor_rev_num; /* (word 81) */ + unsigned short command_set_1; /* (word 82) supported + * 15: Obsolete + * 14: NOP command + * 13: READ_BUFFER + * 12: WRITE_BUFFER + * 11: Obsolete + * 10: Host Protected Area + * 9: DEVICE Reset + * 8: SERVICE Interrupt + * 7: Release Interrupt + * 6: look-ahead + * 5: write cache + * 4: PACKET Command + * 3: Power Management Feature Set + * 2: Removable Feature Set + * 1: Security Feature Set + * 0: SMART Feature Set + */ + unsigned short command_set_2; /* (word 83) + * 15: Shall be ZERO + * 14: Shall be ONE + * 13: FLUSH CACHE EXT + * 12: FLUSH CACHE + * 11: Device Configuration Overlay + * 10: 48-bit Address Feature Set + * 9: Automatic Acoustic Management + * 8: SET MAX security + * 7: reserved 1407DT PARTIES + * 6: SetF sub-command Power-Up + * 5: Power-Up in Standby Feature Set + * 4: Removable Media Notification + * 3: APM Feature Set + * 2: CFA Feature Set + * 1: READ/WRITE DMA QUEUED + * 0: Download MicroCode + */ + unsigned short cfsse; /* (word 84) + * cmd set-feature supported extensions + * 15: Shall be ZERO + * 14: Shall be ONE + * 13:6 reserved + * 5: General Purpose Logging + * 4: Streaming Feature Set + * 3: Media Card Pass Through + * 2: Media Serial Number Valid + * 1: SMART selt-test supported + * 0: SMART error logging + */ + unsigned short cfs_enable_1; /* (word 85) + * command set-feature enabled + * 15: Obsolete + * 14: NOP command + * 13: READ_BUFFER + * 12: WRITE_BUFFER + * 11: Obsolete + * 10: Host Protected Area + * 9: DEVICE Reset + * 8: SERVICE Interrupt + * 7: Release Interrupt + * 6: look-ahead + * 5: write cache + * 4: PACKET Command + * 3: Power Management Feature Set + * 2: Removable Feature Set + * 1: Security Feature Set + * 0: SMART Feature Set + */ + unsigned short cfs_enable_2; /* (word 86) + * command set-feature enabled + * 15: Shall be ZERO + * 14: Shall be ONE + * 13: FLUSH CACHE EXT + * 12: FLUSH CACHE + * 11: Device Configuration Overlay + * 10: 48-bit Address Feature Set + * 9: Automatic Acoustic Management + * 8: SET MAX security + * 7: reserved 1407DT PARTIES + * 6: SetF sub-command Power-Up + * 5: Power-Up in Standby Feature Set + * 4: Removable Media Notification + * 3: APM Feature Set + * 2: CFA Feature Set + * 1: READ/WRITE DMA QUEUED + * 0: Download MicroCode + */ + unsigned short csf_default; /* (word 87) + * command set-feature default + * 15: Shall be ZERO + * 14: Shall be ONE + * 13:6 reserved + * 5: General Purpose Logging enabled + * 4: Valid CONFIGURE STREAM executed + * 3: Media Card Pass Through enabled + * 2: Media Serial Number Valid + * 1: SMART selt-test supported + * 0: SMART error logging + */ + unsigned short dma_ultra; /* (word 88) */ + unsigned short trseuc; /* time required for security erase */ + unsigned short trsEuc; /* time required for enhanced erase */ + unsigned short CurAPMvalues; /* current APM values */ + unsigned short mprc; /* master password revision code */ + unsigned short hw_config; /* hardware config (word 93) + * 15: Shall be ZERO + * 14: Shall be ONE + * 13: + * 12: + * 11: + * 10: + * 9: + * 8: + * 7: + * 6: + * 5: + * 4: + * 3: + * 2: + * 1: + * 0: Shall be ONE + */ + unsigned short acoustic; /* (word 94) + * 15:8 Vendor's recommended value + * 7:0 current value + */ + unsigned short msrqs; /* min stream request size */ + unsigned short sxfert; /* stream transfer time */ + unsigned short sal; /* stream access latency */ + unsigned int spg; /* stream performance granularity */ + unsigned long long lba_capacity_2;/* 48-bit total number of sectors */ + unsigned short words104_125[22];/* reserved words 104-125 */ + unsigned short last_lun; /* (word 126) */ + unsigned short word127; /* (word 127) Feature Set + * Removable Media Notification + * 15:2 reserved + * 1:0 00 = not supported + * 01 = supported + * 10 = reserved + * 11 = reserved + */ + unsigned short dlf; /* (word 128) + * device lock function + * 15:9 reserved + * 8 security level 1:max 0:high + * 7:6 reserved + * 5 enhanced erase + * 4 expire + * 3 frozen + * 2 locked + * 1 en/disabled + * 0 capability + */ + unsigned short csfo; /* (word 129) + * current set features options + * 15:4 reserved + * 3: auto reassign + * 2: reverting + * 1: read-look-ahead + * 0: write cache + */ + unsigned short words130_155[26];/* reserved vendor words 130-155 */ + unsigned short word156; /* reserved vendor word 156 */ + unsigned short words157_159[3];/* reserved vendor words 157-159 */ + unsigned short cfa_power; /* (word 160) CFA Power Mode + * 15 word 160 supported + * 14 reserved + * 13 + * 12 + * 11:0 + */ + unsigned short words161_175[15];/* Reserved for CFA */ + unsigned short words176_205[30];/* Current Media Serial Number */ + unsigned short words206_254[49];/* reserved words 206-254 */ + unsigned short integrity_word; /* (word 255) + * 15:8 Checksum + * 7:0 Signature + */ +}; + +struct request_sense { +#if defined(CONFIG_BIG_ENDIAN) + u8 valid : 1; + u8 error_code : 7; +#elif defined(CONFIG_LITTLE_ENDIAN) + u8 error_code : 7; + u8 valid : 1; +#endif + u8 segment_number; +#if defined(CONFIG_BIG_ENDIAN) + u8 reserved1 : 2; + u8 ili : 1; + u8 reserved2 : 1; + u8 sense_key : 4; +#elif defined(CONFIG_LITTLE_ENDIAN) + u8 sense_key : 4; + u8 reserved2 : 1; + u8 ili : 1; + u8 reserved1 : 2; +#endif + u8 information[4]; + u8 add_sense_len; + u8 command_info[4]; + u8 asc; + u8 ascq; + u8 fruc; + u8 sks[3]; + u8 asb[46]; +}; + +struct atapi_capacity { + u32 lba; + u32 block_size; +}; + +#endif diff --git a/qemu/roms/openbios/drivers/ide.c b/qemu/roms/openbios/drivers/ide.c new file mode 100644 index 000000000..327c64a40 --- /dev/null +++ b/qemu/roms/openbios/drivers/ide.c @@ -0,0 +1,1685 @@ +/* + * OpenBIOS polled ide driver + * + * Copyright (C) 2004 Jens Axboe <axboe@suse.de> + * Copyright (C) 2005 Stefan Reinauer <stepan@openbios.org> + * + * Credit goes to Hale Landis for his excellent ata demo software + * OF node handling and some fixes by Stefan Reinauer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#include "config.h" +#include "libopenbios/bindings.h" +#include "kernel/kernel.h" +#include "libc/byteorder.h" +#include "libc/vsprintf.h" + +#include "drivers/drivers.h" +#include "ide.h" +#include "hdreg.h" +#include "timer.h" + +#ifdef CONFIG_DEBUG_IDE +#define IDE_DPRINTF(fmt, args...) \ +do { printk("IDE - %s: " fmt, __func__ , ##args); } while (0) +#else +#define IDE_DPRINTF(fmt, args...) do { } while (0) +#endif + +/* DECLARE data structures for the nodes. */ +DECLARE_UNNAMED_NODE( ob_ide, INSTALL_OPEN, sizeof(struct ide_drive*) ); +DECLARE_UNNAMED_NODE( ob_ide_ctrl, INSTALL_OPEN, sizeof(int)); + +/* + * define to 2 for the standard 2 channels only + */ +#ifndef CONFIG_IDE_NUM_CHANNELS +#define IDE_NUM_CHANNELS 4 +#else +#define IDE_NUM_CHANNELS CONFIG_IDE_NUM_CHANNELS +#endif +#define IDE_MAX_CHANNELS 4 + +#ifndef CONFIG_IDE_FIRST_UNIT +#define FIRST_UNIT 0 +#else +#define FIRST_UNIT CONFIG_IDE_FIRST_UNIT +#endif + +#ifndef CONFIG_IDE_DEV_TYPE +#define DEV_TYPE "ide" +#else +#define DEV_TYPE CONFIG_IDE_DEV_TYPE +#endif + +#ifndef CONFIG_IDE_DEV_NAME +#define DEV_NAME "ide%d" +#else +#define DEV_NAME CONFIG_IDE_DEV_NAME +#endif + +static int current_channel = FIRST_UNIT; + +static struct ide_channel *channels = NULL; + +static inline void ide_add_channel(struct ide_channel *chan) +{ + chan->next = channels; + channels = chan; +} + +static struct ide_channel *ide_seek_channel(const char *name) +{ + struct ide_channel *current; + + current = channels; + while (current) { + if (!strcmp(current->name, name)) + return current; + current = current->next; + } + return NULL; +} + +/* + * don't be pedantic + */ +#undef ATA_PEDANTIC + +static void dump_drive(struct ide_drive *drive) +{ +#ifdef CONFIG_DEBUG_IDE + printk("IDE DRIVE @%lx:\n", (unsigned long)drive); + printk("unit: %d\n",drive->unit); + printk("present: %d\n",drive->present); + printk("type: %d\n",drive->type); + printk("media: %d\n",drive->media); + printk("model: %s\n",drive->model); + printk("nr: %d\n",drive->nr); + printk("cyl: %d\n",drive->cyl); + printk("head: %d\n",drive->head); + printk("sect: %d\n",drive->sect); + printk("bs: %d\n",drive->bs); +#endif +} + +/* + * old style io port operations + */ +static unsigned char +ob_ide_inb(struct ide_channel *chan, unsigned int port) +{ + return inb(chan->io_regs[port]); +} + +static void +ob_ide_outb(struct ide_channel *chan, unsigned char data, unsigned int port) +{ + outb(data, chan->io_regs[port]); +} + +static void +ob_ide_insw(struct ide_channel *chan, + unsigned int port, unsigned char *addr, unsigned int count) +{ + insw(chan->io_regs[port], addr, count); +} + +static void +ob_ide_outsw(struct ide_channel *chan, + unsigned int port, unsigned char *addr, unsigned int count) +{ + outsw(chan->io_regs[port], addr, count); +} + +static inline unsigned char +ob_ide_pio_readb(struct ide_drive *drive, unsigned int offset) +{ + struct ide_channel *chan = drive->channel; + + return chan->obide_inb(chan, offset); +} + +static inline void +ob_ide_pio_writeb(struct ide_drive *drive, unsigned int offset, + unsigned char data) +{ + struct ide_channel *chan = drive->channel; + + chan->obide_outb(chan, data, offset); +} + +static inline void +ob_ide_pio_insw(struct ide_drive *drive, unsigned int offset, + unsigned char *addr, unsigned int len) +{ + struct ide_channel *chan = drive->channel; + + if (len & 1) { + IDE_DPRINTF("%d: command not word aligned\n", drive->nr); + return; + } + + chan->obide_insw(chan, offset, addr, len / 2); +} + +static inline void +ob_ide_pio_outsw(struct ide_drive *drive, unsigned int offset, + unsigned char *addr, unsigned int len) +{ + struct ide_channel *chan = drive->channel; + + if (len & 1) { + IDE_DPRINTF("%d: command not word aligned\n", drive->nr); + return; + } + + chan->obide_outsw(chan, offset, addr, len / 2); +} + +static void +ob_ide_400ns_delay(struct ide_drive *drive) +{ + (void) ob_ide_pio_readb(drive, IDEREG_ASTATUS); + (void) ob_ide_pio_readb(drive, IDEREG_ASTATUS); + (void) ob_ide_pio_readb(drive, IDEREG_ASTATUS); + (void) ob_ide_pio_readb(drive, IDEREG_ASTATUS); + + udelay(1); +} + +static void +ob_ide_error(struct ide_drive *drive, unsigned char stat, const char *msg) +{ +#ifdef CONFIG_DEBUG_IDE + struct ide_channel *chan = drive->channel; + unsigned char err; +#endif + + if (!stat) + stat = ob_ide_pio_readb(drive, IDEREG_STATUS); + + IDE_DPRINTF("ob_ide_error drive<%d>: %s:\n", drive->nr, msg); + IDE_DPRINTF(" cmd=%x, stat=%x", chan->ata_cmd.command, stat); + + if ((stat & (BUSY_STAT | ERR_STAT)) == ERR_STAT) { +#ifdef CONFIG_DEBUG_IDE + err = +#endif + ob_ide_pio_readb(drive, IDEREG_ERROR); + IDE_DPRINTF(", err=%x", err); + } + IDE_DPRINTF("\n"); + +#ifdef CONFIG_DEBUG_IDE + /* + * see if sense is valid and dump that + */ + if (chan->ata_cmd.command == WIN_PACKET) { + struct atapi_command *cmd = &chan->atapi_cmd; + unsigned char old_cdb = cmd->cdb[0]; + + if (cmd->cdb[0] == ATAPI_REQ_SENSE) { + old_cdb = cmd->old_cdb; + + IDE_DPRINTF(" atapi opcode=%02x", old_cdb); + } else { + int i; + + IDE_DPRINTF(" cdb: "); + for (i = 0; i < sizeof(cmd->cdb); i++) + IDE_DPRINTF("%02x ", cmd->cdb[i]); + } + if (cmd->sense_valid) + IDE_DPRINTF(", sense: %02x/%02x/%02x", + cmd->sense.sense_key, cmd->sense.asc, + cmd->sense.ascq); + else + IDE_DPRINTF(", no sense"); + IDE_DPRINTF("\n"); + } +#endif +} + +/* + * wait for 'stat' to be set. returns 1 if failed, 0 if succesful + */ +static int +ob_ide_wait_stat(struct ide_drive *drive, unsigned char ok_stat, + unsigned char bad_stat, unsigned char *ret_stat) +{ + unsigned char stat; + int i; + + ob_ide_400ns_delay(drive); + + for (i = 0; i < 5000; i++) { + stat = ob_ide_pio_readb(drive, IDEREG_STATUS); + if (!(stat & BUSY_STAT)) + break; + + udelay(1000); + } + + if (ret_stat) + *ret_stat = stat; + + if (stat & bad_stat) + return 1; + + if ((stat & ok_stat) || !ok_stat) + return 0; + + return 1; +} + +static int +ob_ide_select_drive(struct ide_drive *drive) +{ + struct ide_channel *chan = drive->channel; + unsigned char control = IDEHEAD_DEV0; + + if (ob_ide_wait_stat(drive, 0, BUSY_STAT, NULL)) { + IDE_DPRINTF("select_drive: timed out\n"); + return 1; + } + + /* + * don't select drive if already active. Note: we always + * wait for BUSY clear + */ + if (drive->unit == chan->selected) + return 0; + + if (drive->unit) + control = IDEHEAD_DEV1; + + ob_ide_pio_writeb(drive, IDEREG_CURRENT, control); + ob_ide_400ns_delay(drive); + + if (ob_ide_wait_stat(drive, 0, BUSY_STAT, NULL)) { + IDE_DPRINTF("select_drive: timed out\n"); + return 1; + } + + chan->selected = drive->unit; + return 0; +} + +static void +ob_ide_write_tasklet(struct ide_drive *drive, struct ata_command *cmd) +{ + ob_ide_pio_writeb(drive, IDEREG_FEATURE, cmd->task[1]); + ob_ide_pio_writeb(drive, IDEREG_NSECTOR, cmd->task[3]); + ob_ide_pio_writeb(drive, IDEREG_SECTOR, cmd->task[7]); + ob_ide_pio_writeb(drive, IDEREG_LCYL, cmd->task[8]); + ob_ide_pio_writeb(drive, IDEREG_HCYL, cmd->task[9]); + + ob_ide_pio_writeb(drive, IDEREG_FEATURE, cmd->task[0]); + ob_ide_pio_writeb(drive, IDEREG_NSECTOR, cmd->task[2]); + ob_ide_pio_writeb(drive, IDEREG_SECTOR, cmd->task[4]); + ob_ide_pio_writeb(drive, IDEREG_LCYL, cmd->task[5]); + ob_ide_pio_writeb(drive, IDEREG_HCYL, cmd->task[6]); + + if (drive->unit) + cmd->device_head |= IDEHEAD_DEV1; + + ob_ide_pio_writeb(drive, IDEREG_CURRENT, cmd->device_head); + + ob_ide_pio_writeb(drive, IDEREG_COMMAND, cmd->command); + ob_ide_400ns_delay(drive); +} + +static void +ob_ide_write_registers(struct ide_drive *drive, struct ata_command *cmd) +{ + /* + * we are _always_ polled + */ + ob_ide_pio_writeb(drive, IDEREG_CONTROL, cmd->control | IDECON_NIEN); + + ob_ide_pio_writeb(drive, IDEREG_FEATURE, cmd->feature); + ob_ide_pio_writeb(drive, IDEREG_NSECTOR, cmd->nsector); + ob_ide_pio_writeb(drive, IDEREG_SECTOR, cmd->sector); + ob_ide_pio_writeb(drive, IDEREG_LCYL, cmd->lcyl); + ob_ide_pio_writeb(drive, IDEREG_HCYL, cmd->hcyl); + + if (drive->unit) + cmd->device_head |= IDEHEAD_DEV1; + + ob_ide_pio_writeb(drive, IDEREG_CURRENT, cmd->device_head); + + ob_ide_pio_writeb(drive, IDEREG_COMMAND, cmd->command); + ob_ide_400ns_delay(drive); +} + +/* + * execute command with "pio non data" protocol + */ +#if 0 +static int +ob_ide_pio_non_data(struct ide_drive *drive, struct ata_command *cmd) +{ + if (ob_ide_select_drive(drive)) + return 1; + + ob_ide_write_registers(drive, cmd); + + if (ob_ide_wait_stat(drive, 0, BUSY_STAT, NULL)) + return 1; + + return 0; +} +#endif + +/* + * execute given command with a pio data-in phase. + */ +static int +ob_ide_pio_data_in(struct ide_drive *drive, struct ata_command *cmd) +{ + unsigned char stat; + unsigned int bytes, timeout; + + if (ob_ide_select_drive(drive)) + return 1; + + /* + * ATA must set ready and seek stat, ATAPI need only clear busy + */ + timeout = 0; + do { + stat = ob_ide_pio_readb(drive, IDEREG_STATUS); + + if (drive->type == ide_type_ata) { + /* + * this is BIOS code, don't be too pedantic + */ +#ifdef ATA_PEDANTIC + if ((stat & (BUSY_STAT | READY_STAT | SEEK_STAT)) == + (READY_STAT | SEEK_STAT)) + break; +#else + if ((stat & (BUSY_STAT | READY_STAT)) == READY_STAT) + break; +#endif + } else { + if (!(stat & BUSY_STAT)) + break; + } + ob_ide_400ns_delay(drive); + } while (timeout++ < 1000); + + if (timeout >= 1000) { + ob_ide_error(drive, stat, "drive timed out"); + cmd->stat = stat; + return 1; + } + + ob_ide_write_registers(drive, cmd); + + /* + * now read the data + */ + bytes = cmd->buflen; + do { + unsigned count = cmd->buflen; + + if (count > drive->bs) + count = drive->bs; + + /* delay 100ms for ATAPI? */ + + /* + * wait for BUSY clear + */ + if (ob_ide_wait_stat(drive, 0, BUSY_STAT | ERR_STAT, &stat)) { + ob_ide_error(drive, stat, "timed out waiting for BUSY clear"); + cmd->stat = stat; + break; + } + + /* + * transfer the data + */ + if ((stat & (BUSY_STAT | DRQ_STAT)) == DRQ_STAT) { + ob_ide_pio_insw(drive, IDEREG_DATA, cmd->buffer, count); + cmd->bytes -= count; + cmd->buffer += count; + bytes -= count; + + ob_ide_400ns_delay(drive); + } + + if (stat & (BUSY_STAT | WRERR_STAT | ERR_STAT)) { + cmd->stat = stat; + break; + } + + if (!(stat & DRQ_STAT)) { + cmd->stat = stat; + break; + } + } while (bytes); + + if (bytes) + IDE_DPRINTF("bytes=%d, stat=%x\n", bytes, stat); + + return bytes ? 1 : 0; +} + +/* + * execute ata command with pio packet protocol + */ +static int +ob_ide_pio_packet(struct ide_drive *drive, struct atapi_command *cmd) +{ + unsigned char stat, reason, lcyl, hcyl; + struct ata_command *acmd = &drive->channel->ata_cmd; + unsigned char *buffer; + unsigned int bytes; + + if (ob_ide_select_drive(drive)) + return 1; + + if (cmd->buflen && cmd->data_direction == atapi_ddir_none) + IDE_DPRINTF("non-zero buflen but no data direction\n"); + + memset(acmd, 0, sizeof(*acmd)); + acmd->lcyl = cmd->buflen & 0xff; + acmd->hcyl = (cmd->buflen >> 8) & 0xff; + acmd->command = WIN_PACKET; + ob_ide_write_registers(drive, acmd); + + /* + * BUSY must be set, _or_ DRQ | ERR + */ + stat = ob_ide_pio_readb(drive, IDEREG_ASTATUS); + if ((stat & BUSY_STAT) == 0) { + if (!(stat & (DRQ_STAT | ERR_STAT))) { + ob_ide_error(drive, stat, "bad stat in atapi cmd"); + cmd->stat = stat; + return 1; + } + } + + if (ob_ide_wait_stat(drive, 0, BUSY_STAT | ERR_STAT, &stat)) { + ob_ide_error(drive, stat, "timeout, ATAPI BUSY clear"); + cmd->stat = stat; + return 1; + } + + if ((stat & (BUSY_STAT | DRQ_STAT | ERR_STAT)) != DRQ_STAT) { + /* + * if command isn't request sense, then we have a problem. if + * we are doing a sense, ERR_STAT == CHECK_CONDITION + */ + if (cmd->cdb[0] != ATAPI_REQ_SENSE) { + IDE_DPRINTF("odd, drive didn't want to transfer %x\n", + stat); + return 1; + } + } + + /* + * transfer cdb + */ + ob_ide_pio_outsw(drive, IDEREG_DATA, cmd->cdb,sizeof(cmd->cdb)); + ob_ide_400ns_delay(drive); + + /* + * ok, cdb was sent to drive, now do data transfer (if any) + */ + bytes = cmd->buflen; + buffer = cmd->buffer; + do { + unsigned int bc; + + if (ob_ide_wait_stat(drive, 0, BUSY_STAT | ERR_STAT, &stat)) { + ob_ide_error(drive, stat, "busy not clear after cdb"); + cmd->stat = stat; + break; + } + + /* + * transfer complete! + */ + if ((stat & (BUSY_STAT | DRQ_STAT)) == 0) + break; + + if ((stat & (BUSY_STAT | DRQ_STAT)) != DRQ_STAT) + break; + + reason = ob_ide_pio_readb(drive, IDEREG_NSECTOR); + lcyl = ob_ide_pio_readb(drive, IDEREG_LCYL); + hcyl = ob_ide_pio_readb(drive, IDEREG_HCYL); + + /* + * check if the drive wants to transfer data in the same + * direction as we do... + */ + if ((reason & IREASON_CD) && cmd->data_direction != atapi_ddir_read) { + ob_ide_error(drive, stat, "atapi, bad transfer ddir"); + break; + } + + bc = (hcyl << 8) | lcyl; + if (!bc) + break; + + if (bc > bytes) + bc = bytes; + + if (cmd->data_direction == atapi_ddir_read) + ob_ide_pio_insw(drive, IDEREG_DATA, buffer, bc); + else + ob_ide_pio_outsw(drive, IDEREG_DATA, buffer, bc); + + bytes -= bc; + buffer += bc; + + ob_ide_400ns_delay(drive); + } while (bytes); + + if (cmd->data_direction != atapi_ddir_none) + (void) ob_ide_wait_stat(drive, 0, BUSY_STAT, &stat); + + if (bytes) + IDE_DPRINTF("cdb failed, bytes=%d, stat=%x\n", bytes, stat); + + return (stat & ERR_STAT) || bytes; +} + +/* + * execute a packet command, with retries if appropriate + */ +static int +ob_ide_atapi_packet(struct ide_drive *drive, struct atapi_command *cmd) +{ + int retries = 5, ret; + + if (drive->type != ide_type_atapi) + return 1; + if (cmd->buflen > 0xffff) + return 1; + + /* + * retry loop + */ + do { + ret = ob_ide_pio_packet(drive, cmd); + if (!ret) + break; + + /* + * request sense failed, bummer + */ + if (cmd->cdb[0] == ATAPI_REQ_SENSE) + break; + + if (ob_ide_atapi_request_sense(drive)) + break; + + /* + * we know sense is valid. retry if the drive isn't ready, + * otherwise don't bother. + */ + if (cmd->sense.sense_key != ATAPI_SENSE_NOT_READY) + break; + /* + * ... except 'medium not present' + */ + if (cmd->sense.asc == 0x3a) + break; + + udelay(1000000); + } while (retries--); + + if (ret) + ob_ide_error(drive, 0, "atapi command"); + + return ret; +} + +static int +ob_ide_atapi_request_sense(struct ide_drive *drive) +{ + struct atapi_command *cmd = &drive->channel->atapi_cmd; + unsigned char old_cdb; + + /* + * save old cdb for debug error + */ + old_cdb = cmd->cdb[0]; + + memset(cmd, 0, sizeof(*cmd)); + cmd->cdb[0] = ATAPI_REQ_SENSE; + cmd->cdb[4] = 18; + cmd->buffer = (unsigned char *) &cmd->sense; + cmd->buflen = 18; + cmd->data_direction = atapi_ddir_read; + cmd->old_cdb = old_cdb; + + if (ob_ide_atapi_packet(drive, cmd)) + return 1; + + cmd->sense_valid = 1; + return 0; +} + +/* + * make sure drive is ready and media loaded + */ +static int +ob_ide_atapi_drive_ready(struct ide_drive *drive) +{ + struct atapi_command *cmd = &drive->channel->atapi_cmd; + struct atapi_capacity cap; + + IDE_DPRINTF("ob_ide_atapi_drive_ready\n"); + + /* + * Test Unit Ready is like a ping + */ + memset(cmd, 0, sizeof(*cmd)); + cmd->cdb[0] = ATAPI_TUR; + + if (ob_ide_atapi_packet(drive, cmd)) { + IDE_DPRINTF("%d: TUR failed\n", drive->nr); + return 1; + } + + /* + * don't force load of tray (bit 2 in byte 4 of cdb), it's + * annoying and we don't want to deal with errors from drives + * that cannot do it + */ + memset(cmd, 0, sizeof(*cmd)); + cmd->cdb[0] = ATAPI_START_STOP_UNIT; + cmd->cdb[4] = 0x01; + + if (ob_ide_atapi_packet(drive, cmd)) { + IDE_DPRINTF("%d: START_STOP unit failed\n", drive->nr); + return 1; + } + + /* + * finally, get capacity and block size + */ + memset(cmd, 0, sizeof(*cmd)); + memset(&cap, 0, sizeof(cap)); + + cmd->cdb[0] = ATAPI_READ_CAPACITY; + cmd->buffer = (unsigned char *) ∩ + cmd->buflen = sizeof(cap); + cmd->data_direction = atapi_ddir_read; + + if (ob_ide_atapi_packet(drive, cmd)) { + drive->sectors = 0x1fffff; + drive->bs = 2048; + return 1; + } + + drive->sectors = __be32_to_cpu(cap.lba) + 1; + drive->bs = __be32_to_cpu(cap.block_size); + return 0; +} + +/* + * read from an atapi device, using READ_10 + */ +static int +ob_ide_read_atapi(struct ide_drive *drive, unsigned long long block, + unsigned char *buf, unsigned int sectors) +{ + struct atapi_command *cmd = &drive->channel->atapi_cmd; + + if (ob_ide_atapi_drive_ready(drive)) + return 1; + + memset(cmd, 0, sizeof(*cmd)); + + /* + * READ_10 should work on generally any atapi device + */ + cmd->cdb[0] = ATAPI_READ_10; + cmd->cdb[2] = (block >> 24) & 0xff; + cmd->cdb[3] = (block >> 16) & 0xff; + cmd->cdb[4] = (block >> 8) & 0xff; + cmd->cdb[5] = block & 0xff; + cmd->cdb[7] = (sectors >> 8) & 0xff; + cmd->cdb[8] = sectors & 0xff; + + cmd->buffer = buf; + cmd->buflen = sectors * 2048; + cmd->data_direction = atapi_ddir_read; + + return ob_ide_atapi_packet(drive, cmd); +} + +static int +ob_ide_read_ata_chs(struct ide_drive *drive, unsigned long long block, + unsigned char *buf, unsigned int sectors) +{ + struct ata_command *cmd = &drive->channel->ata_cmd; + unsigned int track = (block / drive->sect); + unsigned int sect = (block % drive->sect) + 1; + unsigned int head = (track % drive->head); + unsigned int cyl = (track / drive->head); + + /* + * fill in chs command to read from disk at given location + */ + cmd->buffer = buf; + cmd->buflen = sectors * 512; + + cmd->nsector = sectors & 0xff; + cmd->sector = sect; + cmd->lcyl = cyl; + cmd->hcyl = cyl >> 8; + cmd->device_head = head; + + cmd->command = WIN_READ; + + return ob_ide_pio_data_in(drive, cmd); +} + +static int +ob_ide_read_ata_lba28(struct ide_drive *drive, unsigned long long block, + unsigned char *buf, unsigned int sectors) +{ + struct ata_command *cmd = &drive->channel->ata_cmd; + + memset(cmd, 0, sizeof(*cmd)); + + /* + * fill in 28-bit lba command to read from disk at given location + */ + cmd->buffer = buf; + cmd->buflen = sectors * 512; + + cmd->nsector = sectors; + cmd->sector = block; + cmd->lcyl = block >>= 8; + cmd->hcyl = block >>= 8; + cmd->device_head = ((block >> 8) & 0x0f); + cmd->device_head |= (1 << 6); + + cmd->command = WIN_READ; + + return ob_ide_pio_data_in(drive, cmd); +} + +static int +ob_ide_read_ata_lba48(struct ide_drive *drive, unsigned long long block, + unsigned char *buf, unsigned int sectors) +{ + struct ata_command *cmd = &drive->channel->ata_cmd; + + memset(cmd, 0, sizeof(*cmd)); + + cmd->buffer = buf; + cmd->buflen = sectors * 512; + + /* + * we are using tasklet addressing here + */ + cmd->task[2] = sectors; + cmd->task[3] = sectors >> 8; + cmd->task[4] = block; + cmd->task[5] = block >> 8; + cmd->task[6] = block >> 16; + cmd->task[7] = block >> 24; + cmd->task[8] = (u64) block >> 32; + cmd->task[9] = (u64) block >> 40; + + cmd->command = WIN_READ_EXT; + + ob_ide_write_tasklet(drive, cmd); + + return ob_ide_pio_data_in(drive, cmd); +} +/* + * read 'sectors' sectors from ata device + */ +static int +ob_ide_read_ata(struct ide_drive *drive, unsigned long long block, + unsigned char *buf, unsigned int sectors) +{ + unsigned long long end_block = block + sectors; + const int need_lba48 = (end_block > (1ULL << 28)) || (sectors > 255); + + if (end_block > drive->sectors) + return 1; + if (need_lba48 && drive->addressing != ide_lba48) + return 1; + + /* + * use lba48 if we have to, otherwise use the faster lba28 + */ + if (need_lba48) + return ob_ide_read_ata_lba48(drive, block, buf, sectors); + else if (drive->addressing != ide_chs) + return ob_ide_read_ata_lba28(drive, block, buf, sectors); + + return ob_ide_read_ata_chs(drive, block, buf, sectors); +} + +static int +ob_ide_read_sectors(struct ide_drive *drive, unsigned long long block, + unsigned char *buf, unsigned int sectors) +{ + if (!sectors) + return 1; + if (block + sectors > drive->sectors) + return 1; + + IDE_DPRINTF("ob_ide_read_sectors: block=%lu sectors=%u\n", + (unsigned long) block, sectors); + + if (drive->type == ide_type_ata) + return ob_ide_read_ata(drive, block, buf, sectors); + else + return ob_ide_read_atapi(drive, block, buf, sectors); +} + +/* + * byte swap the string if necessay, and strip leading/trailing blanks + */ +static void +ob_ide_fixup_string(unsigned char *s, unsigned int len) +{ + unsigned char *p = s, *end = &s[len & ~1]; + + /* + * if big endian arch, byte swap the string + */ +#ifdef CONFIG_BIG_ENDIAN + for (p = end ; p != s;) { + unsigned short *pp = (unsigned short *) (p -= 2); + *pp = __le16_to_cpu(*pp); + } +#endif + + while (s != end && *s == ' ') + ++s; + while (s != end && *s) + if (*s++ != ' ' || (s != end && *s && *s != ' ')) + *p++ = *(s-1); + while (p != end) + *p++ = '\0'; +} + +/* + * it's big endian, we need to swap (if on little endian) the items we use + */ +static int +ob_ide_fixup_id(struct hd_driveid *id) +{ + ob_ide_fixup_string(id->model, 40); + id->config = __le16_to_cpu(id->config); + id->lba_capacity = __le32_to_cpu(id->lba_capacity); + id->cyls = __le16_to_cpu(id->cyls); + id->heads = __le16_to_cpu(id->heads); + id->sectors = __le16_to_cpu(id->sectors); + id->command_set_2 = __le16_to_cpu(id->command_set_2); + id->cfs_enable_2 = __le16_to_cpu(id->cfs_enable_2); + + return 0; +} + +static int +ob_ide_identify_drive(struct ide_drive *drive) +{ + struct ata_command *cmd = &drive->channel->ata_cmd; + struct hd_driveid id; + + memset(cmd, 0, sizeof(*cmd)); + cmd->buffer = (unsigned char *) &id; + cmd->buflen = 512; + + if (drive->type == ide_type_ata) + cmd->command = WIN_IDENTIFY; + else if (drive->type == ide_type_atapi) + cmd->command = WIN_IDENTIFY_PACKET; + else { + IDE_DPRINTF("%s: called with bad device type %d\n", + __FUNCTION__, drive->type); + return 1; + } + + if (ob_ide_pio_data_in(drive, cmd)) + return 1; + + ob_ide_fixup_id(&id); + + if (drive->type == ide_type_atapi) { + drive->media = (id.config >> 8) & 0x1f; + drive->sectors = 0x7fffffff; + drive->bs = 2048; + drive->max_sectors = 31; + } else { + drive->media = ide_media_disk; + drive->sectors = id.lba_capacity; + drive->bs = 512; + drive->max_sectors = 255; + +#ifdef CONFIG_IDE_LBA48 + if ((id.command_set_2 & 0x0400) && (id.cfs_enable_2 & 0x0400)) { + drive->addressing = ide_lba48; + drive->max_sectors = 65535; + } else +#endif + if (id.capability & 2) + drive->addressing = ide_lba28; + else { + drive->addressing = ide_chs; + } + + /* only set these in chs mode? */ + drive->cyl = id.cyls; + drive->head = id.heads; + drive->sect = id.sectors; + } + + strncpy(drive->model, (char*)id.model, sizeof(id.model)); + drive->model[40] = '\0'; + return 0; +} + +/* + * identify type of devices on channel. must have already been probed. + */ +static void +ob_ide_identify_drives(struct ide_channel *chan) +{ + struct ide_drive *drive; + int i; + + for (i = 0; i < 2; i++) { + drive = &chan->drives[i]; + + if (!drive->present) + continue; + + ob_ide_identify_drive(drive); + } +} + +/* + * software reset (ATA-4, section 8.3) + */ +static void +ob_ide_software_reset(struct ide_drive *drive) +{ + struct ide_channel *chan = drive->channel; + + ob_ide_pio_writeb(drive, IDEREG_CONTROL, IDECON_NIEN | IDECON_SRST); + ob_ide_400ns_delay(drive); + ob_ide_pio_writeb(drive, IDEREG_CONTROL, IDECON_NIEN); + ob_ide_400ns_delay(drive); + + /* + * if master is present, wait for BUSY clear + */ + if (chan->drives[0].present) + ob_ide_wait_stat(drive, 0, BUSY_STAT, NULL); + + /* + * if slave is present, wait until it allows register access + */ + if (chan->drives[1].present) { + unsigned char sectorn, sectorc; + int timeout = 1000; + + do { + /* + * select it + */ + ob_ide_pio_writeb(drive, IDEREG_CURRENT, IDEHEAD_DEV1); + ob_ide_400ns_delay(drive); + + sectorn = ob_ide_pio_readb(drive, IDEREG_SECTOR); + sectorc = ob_ide_pio_readb(drive, IDEREG_NSECTOR); + + if (sectorc == 0x01 && sectorn == 0x01) + break; + + } while (--timeout); + } + + /* + * reset done, reselect original device + */ + drive->channel->selected = -1; + ob_ide_select_drive(drive); +} + +/* + * this serves as both a device check, and also to verify that the drives + * we initially "found" are really there + */ +static void +ob_ide_device_type_check(struct ide_drive *drive) +{ + unsigned char sc, sn, cl, ch, st; + + if (ob_ide_select_drive(drive)) + return; + + sc = ob_ide_pio_readb(drive, IDEREG_NSECTOR); + sn = ob_ide_pio_readb(drive, IDEREG_SECTOR); + + if (sc == 0x01 && sn == 0x01) { + /* + * read device signature + */ + cl = ob_ide_pio_readb(drive, IDEREG_LCYL); + ch = ob_ide_pio_readb(drive, IDEREG_HCYL); + st = ob_ide_pio_readb(drive, IDEREG_STATUS); + if (cl == 0x14 && ch == 0xeb) + drive->type = ide_type_atapi; + else if (cl == 0x00 && ch == 0x00 && st != 0x00) + drive->type = ide_type_ata; + else + drive->present = 0; + } else + drive->present = 0; +} + +/* + * pure magic + */ +static void +ob_ide_device_check(struct ide_drive *drive) +{ + unsigned char sc, sn; + + /* + * non-existing io port should return 0xff, don't probe this + * channel at all then + */ + if (ob_ide_pio_readb(drive, IDEREG_STATUS) == 0xff) { + drive->channel->present = 0; + return; + } + + if (ob_ide_select_drive(drive)) + return; + + ob_ide_pio_writeb(drive, IDEREG_NSECTOR, 0x55); + ob_ide_pio_writeb(drive, IDEREG_SECTOR, 0xaa); + ob_ide_pio_writeb(drive, IDEREG_NSECTOR, 0xaa); + ob_ide_pio_writeb(drive, IDEREG_SECTOR, 0x55); + ob_ide_pio_writeb(drive, IDEREG_NSECTOR, 0x55); + ob_ide_pio_writeb(drive, IDEREG_SECTOR, 0xaa); + + sc = ob_ide_pio_readb(drive, IDEREG_NSECTOR); + sn = ob_ide_pio_readb(drive, IDEREG_SECTOR); + + /* + * we _think_ the device is there, we will make sure later + */ + if (sc == 0x55 && sn == 0xaa) { + drive->present = 1; + drive->type = ide_type_unknown; + } +} + +/* + * probe the legacy ide ports and find attached devices. + */ +static void +ob_ide_probe(struct ide_channel *chan) +{ + struct ide_drive *drive; + int i; + + for (i = 0; i < 2; i++) { + drive = &chan->drives[i]; + + ob_ide_device_check(drive); + + /* + * no point in continuing + */ + if (!chan->present) + break; + + if (!drive->present) + continue; + + /* + * select and reset device + */ + if (ob_ide_select_drive(drive)) + continue; + + ob_ide_software_reset(drive); + + ob_ide_device_type_check(drive); + } +} + +/* + * The following functions are interfacing with OpenBIOS. They + * are device node methods. Thus they have to do proper stack handling. + * + */ + +/* + * 255 sectors for ata lba28, 65535 for lba48, and 31 sectors for atapi + */ +static void +ob_ide_max_transfer(int *idx) +{ + struct ide_drive *drive = *(struct ide_drive **)idx; + + IDE_DPRINTF("max_transfer %x\n", drive->max_sectors * drive->bs); + + PUSH(drive->max_sectors * drive->bs); +} + +static void +ob_ide_read_blocks(int *idx) +{ + cell n = POP(), cnt=n; + ucell blk = POP(); + unsigned char *dest = (unsigned char *)cell2pointer(POP()); + struct ide_drive *drive = *(struct ide_drive **)idx; + + IDE_DPRINTF("ob_ide_read_blocks %lx block=%ld n=%ld\n", + (unsigned long)dest, (unsigned long)blk, (long)n); + + while (n) { + int len = n; + if (len > drive->max_sectors) + len = drive->max_sectors; + + if (ob_ide_read_sectors(drive, blk, dest, len)) { + IDE_DPRINTF("ob_ide_read_blocks: error\n"); + RET(0); + } + + dest += len * drive->bs; + n -= len; + blk += len; + } + + PUSH(cnt); +} + +static void +ob_ide_block_size(int *idx) +{ + struct ide_drive *drive = *(struct ide_drive **)idx; + + IDE_DPRINTF("ob_ide_block_size: block size %x\n", drive->bs); + + PUSH(drive->bs); +} + +static void +ob_ide_initialize(int *idx) +{ + int props[3]; + phandle_t ph=get_cur_dev(); + + push_str("block"); + fword("device-type"); + + // Set dummy reg properties + + set_int_property(ph, "#address-cells", 1); + set_int_property(ph, "#size-cells", 0); + + props[0] = __cpu_to_be32(0); props[1] = __cpu_to_be32(0); props[2] = __cpu_to_be32(0); + set_property(ph, "reg", (char *)&props, 3*sizeof(int)); + + fword("is-deblocker"); +} + +static void +ob_ide_open(int *idx) +{ + int ret=1, len; + phandle_t ph; + struct ide_drive *drive; + struct ide_channel *chan; + char *idename; + int unit; + + fword("my-unit"); + unit = POP(); + + fword("my-parent"); + fword("ihandle>phandle"); + ph=(phandle_t)POP(); + idename=get_property(ph, "name", &len); + + chan = ide_seek_channel(idename); + drive = &chan->drives[unit]; + *(struct ide_drive **)idx = drive; + + IDE_DPRINTF("opening channel %d unit %d\n", idx[1], idx[0]); + dump_drive(drive); + + if (drive->type != ide_type_ata) + ret= !ob_ide_atapi_drive_ready(drive); + + selfword("open-deblocker"); + + /* interpose disk-label */ + ph = find_dev("/packages/disk-label"); + fword("my-args"); + PUSH_ph( ph ); + fword("interpose"); + + RET ( -ret ); +} + +static void +ob_ide_close(struct ide_drive *drive) +{ + selfword("close-deblocker"); +} + +NODE_METHODS(ob_ide) = { + { NULL, ob_ide_initialize }, + { "open", ob_ide_open }, + { "close", ob_ide_close }, + { "read-blocks", ob_ide_read_blocks }, + { "block-size", ob_ide_block_size }, + { "max-transfer", ob_ide_max_transfer }, +}; + +static void +ob_ide_ctrl_initialize(int *idx) +{ + phandle_t ph=get_cur_dev(); + + /* set device type */ + push_str(DEV_TYPE); + fword("device-type"); + + set_int_property(ph, "#address-cells", 1); + set_int_property(ph, "#size-cells", 0); +} + +static void +ob_ide_ctrl_decodeunit(int *idx) +{ + fword("parse-hex"); +} + +NODE_METHODS(ob_ide_ctrl) = { + { NULL, ob_ide_ctrl_initialize }, + { "decode-unit", ob_ide_ctrl_decodeunit }, +}; + +static void set_cd_alias(const char *path) +{ + phandle_t aliases; + + aliases = find_dev("/aliases"); + + if (get_property(aliases, "cd", NULL)) + return; + + set_property(aliases, "cd", path, strlen(path) + 1); + set_property(aliases, "cdrom", path, strlen(path) + 1); +} + +static void set_hd_alias(const char *path) +{ + phandle_t aliases; + + aliases = find_dev("/aliases"); + + if (get_property(aliases, "hd", NULL)) + return; + + set_property(aliases, "hd", path, strlen(path) + 1); + set_property(aliases, "disk", path, strlen(path) + 1); +} + +static void set_ide_alias(const char *path) +{ + phandle_t aliases; + static int ide_counter = 0; + char idestr[8]; + + aliases = find_dev("/aliases"); + + snprintf(idestr, sizeof(idestr), "ide%d", ide_counter++); + set_property(aliases, idestr, path, strlen(path) + 1); +} + +int ob_ide_init(const char *path, uint32_t io_port0, uint32_t ctl_port0, + uint32_t io_port1, uint32_t ctl_port1) +{ + int i, j; + char nodebuff[128]; + phandle_t dnode; + struct ide_channel *chan; + int io_ports[IDE_MAX_CHANNELS]; + int ctl_ports[IDE_MAX_CHANNELS]; + u32 props[6]; + + io_ports[0] = io_port0; + ctl_ports[0] = ctl_port0; + io_ports[1] = io_port1; + ctl_ports[1] = ctl_port1; + + for (i = 0; i < IDE_NUM_CHANNELS; i++, current_channel++) { + + chan = malloc(sizeof(struct ide_channel)); + + snprintf(chan->name, sizeof(chan->name), + DEV_NAME, current_channel); + + chan->mmio = 0; + + for (j = 0; j < 8; j++) + chan->io_regs[j] = io_ports[i] + j; + + chan->io_regs[8] = ctl_ports[i]; + chan->io_regs[9] = ctl_ports[i] + 1; + + chan->obide_inb = ob_ide_inb; + chan->obide_insw = ob_ide_insw; + chan->obide_outb = ob_ide_outb; + chan->obide_outsw = ob_ide_outsw; + + chan->selected = -1; + + /* + * assume it's there, if not io port dead check will clear + */ + chan->present = 1; + + for (j = 0; j < 2; j++) { + chan->drives[j].present = 0; + chan->drives[j].unit = j; + chan->drives[j].channel = chan; + /* init with a decent value */ + chan->drives[j].bs = 512; + + chan->drives[j].nr = i * 2 + j; + } + + ide_add_channel(chan); + + ob_ide_probe(chan); + + if (!chan->present) + continue; + + ob_ide_identify_drives(chan); + + snprintf(nodebuff, sizeof(nodebuff), "%s/" DEV_NAME, path, + current_channel); + REGISTER_NAMED_NODE(ob_ide_ctrl, nodebuff); + + dnode = find_dev(nodebuff); + +#if !defined(CONFIG_PPC) && !defined(CONFIG_SPARC64) + props[0]=14; props[1]=0; + set_property(dnode, "interrupts", + (char *)&props, 2*sizeof(props[0])); +#endif + + props[0] = __cpu_to_be32(chan->io_regs[0]); + props[1] = __cpu_to_be32(1); props[2] = __cpu_to_be32(8); + props[3] = __cpu_to_be32(chan->io_regs[8]); + props[4] = __cpu_to_be32(1); props[5] = __cpu_to_be32(2); + set_property(dnode, "reg", (char *)&props, 6*sizeof(props[0])); + + IDE_DPRINTF(DEV_NAME": [io ports 0x%x-0x%x,0x%x]\n", + current_channel, chan->io_regs[0], + chan->io_regs[0] + 7, chan->io_regs[8]); + + for (j = 0; j < 2; j++) { + struct ide_drive *drive = &chan->drives[j]; + const char *media = "UNKNOWN"; + + if (!drive->present) + continue; + + IDE_DPRINTF(" drive%d [ATA%s ", j, + drive->type == ide_type_atapi ? "PI" : ""); + switch (drive->media) { + case ide_media_floppy: + media = "floppy"; + break; + case ide_media_cdrom: + media = "cdrom"; + break; + case ide_media_optical: + media = "mo"; + break; + case ide_media_disk: + media = "disk"; + break; + } + IDE_DPRINTF("%s]: %s\n", media, drive->model); + snprintf(nodebuff, sizeof(nodebuff), + "%s/" DEV_NAME "/%s", path, current_channel, + media); + REGISTER_NAMED_NODE(ob_ide, nodebuff); + dnode=find_dev(nodebuff); + set_int_property(dnode, "reg", j); + + /* create aliases */ + + set_ide_alias(nodebuff); + if (drive->media == ide_media_cdrom) + set_cd_alias(nodebuff); + if (drive->media == ide_media_disk) + set_hd_alias(nodebuff); + } + } + + return 0; +} + +#if defined(CONFIG_DRIVER_MACIO) +static unsigned char +macio_ide_inb(struct ide_channel *chan, unsigned int port) +{ + return in_8((unsigned char*)(chan->mmio + (port << 4))); +} + +static void +macio_ide_outb(struct ide_channel *chan, unsigned char data, unsigned int port) +{ + out_8((unsigned char*)(chan->mmio + (port << 4)), data); +} + +static void +macio_ide_insw(struct ide_channel *chan, + unsigned int port, unsigned char *addr, unsigned int count) +{ + _insw((uint16_t*)(chan->mmio + (port << 4)), addr, count); +} + +static void +macio_ide_outsw(struct ide_channel *chan, + unsigned int port, unsigned char *addr, unsigned int count) +{ + _outsw((uint16_t*)(chan->mmio + (port << 4)), addr, count); +} + +#define MACIO_IDE_OFFSET 0x00020000 +#define MACIO_IDE_SIZE 0x00001000 + +int macio_ide_init(const char *path, uint32_t addr, int nb_channels) +{ + int i, j; + char nodebuff[128]; + phandle_t dnode; + u32 props[8]; + struct ide_channel *chan; + + /* IDE ports on Macs are numbered from 3. + * Also see comments in macio.c:openpic_init() */ + current_channel = 3; + + for (i = 0; i < nb_channels; i++, current_channel++) { + + chan = malloc(sizeof(struct ide_channel)); + + snprintf(chan->name, sizeof(chan->name), + DEV_NAME, current_channel); + + chan->mmio = addr + MACIO_IDE_OFFSET + i * MACIO_IDE_SIZE; + + chan->obide_inb = macio_ide_inb; + chan->obide_insw = macio_ide_insw; + chan->obide_outb = macio_ide_outb; + chan->obide_outsw = macio_ide_outsw; + + chan->selected = -1; + + /* + * assume it's there, if not io port dead check will clear + */ + chan->present = 1; + + for (j = 0; j < 2; j++) { + chan->drives[j].present = 0; + chan->drives[j].unit = j; + chan->drives[j].channel = chan; + /* init with a decent value */ + chan->drives[j].bs = 512; + + chan->drives[j].nr = i * 2 + j; + } + + ob_ide_probe(chan); + + if (!chan->present) { + free(chan); + continue; + } + + ide_add_channel(chan); + + ob_ide_identify_drives(chan); + + snprintf(nodebuff, sizeof(nodebuff), "%s/" DEV_NAME, path, + current_channel); + REGISTER_NAMED_NODE(ob_ide_ctrl, nodebuff); + + dnode = find_dev(nodebuff); + + set_property(dnode, "compatible", (is_oldworld() ? + "heathrow-ata" : "keylargo-ata"), 13); + + props[0] = 0x00000526; + props[1] = 0x00000085; + props[2] = 0x00000025; + props[3] = 0x00000025; + props[4] = 0x00000025; + props[5] = 0x00000000; + props[6] = 0x00000000; + props[7] = 0x00000000; + OLDWORLD(set_property(dnode, "AAPL,pio-timing", + (char *)&props, 8*sizeof(props[0]))); + + /* The first interrupt entry is the ide interrupt, the second + the dbdma interrupt */ + switch (i) { + case 0: + props[0] = 0x0000000d; + props[2] = 0x00000002; + break; + case 1: + props[0] = 0x0000000e; + props[2] = 0x00000003; + break; + case 2: + props[0] = 0x0000000f; + props[2] = 0x00000004; + break; + default: + props[0] = 0x00000000; + props[2] = 0x00000000; + break; + } + props[1] = 0x00000000; /* XXX level triggered on real hw */ + props[3] = 0x00000000; + NEWWORLD(set_property(dnode, "interrupts", + (char *)&props, 4*sizeof(props[0]))); + NEWWORLD(set_int_property(dnode, "#interrupt-cells", 2)); + + props[1] = props[2]; + OLDWORLD(set_property(dnode, "AAPL,interrupts", + (char *)&props, 2*sizeof(props[0]))); + + props[0] = MACIO_IDE_OFFSET + i * MACIO_IDE_SIZE; + props[1] = MACIO_IDE_SIZE; + props[2] = 0x00008b00 + i * 0x0200; + props[3] = 0x0200; + set_property(dnode, "reg", (char *)&props, 4*sizeof(props[0])); + + props[0] = addr + MACIO_IDE_OFFSET + i * MACIO_IDE_SIZE; + props[1] = addr + 0x00008b00 + i * 0x0200; + OLDWORLD(set_property(dnode, "AAPL,address", + (char *)&props, 2*sizeof(props[0]))); + + props[0] = 0; + OLDWORLD(set_property(dnode, "AAPL,bus-id", (char*)props, + 1 * sizeof(props[0]))); + IDE_DPRINTF(DEV_NAME": [io ports 0x%lx]\n", + current_channel, chan->mmio); + + for (j = 0; j < 2; j++) { + struct ide_drive *drive = &chan->drives[j]; + const char *media = "UNKNOWN"; + + if (!drive->present) + continue; + + IDE_DPRINTF(" drive%d [ATA%s ", j, + drive->type == ide_type_atapi ? "PI" : ""); + switch (drive->media) { + case ide_media_floppy: + media = "floppy"; + break; + case ide_media_cdrom: + media = "cdrom"; + break; + case ide_media_optical: + media = "mo"; + break; + case ide_media_disk: + media = "disk"; + break; + } + IDE_DPRINTF("%s]: %s\n", media, drive->model); + snprintf(nodebuff, sizeof(nodebuff), + "%s/" DEV_NAME "/%s", path, current_channel, + media); + REGISTER_NAMED_NODE(ob_ide, nodebuff); + dnode = find_dev(nodebuff); + set_int_property(dnode, "reg", j); + + /* create aliases */ + + set_ide_alias(nodebuff); + if (drive->media == ide_media_cdrom) + set_cd_alias(nodebuff); + if (drive->media == ide_media_disk) + set_hd_alias(nodebuff); + } + } + + return 0; +} +#endif /* CONFIG_DRIVER_MACIO */ diff --git a/qemu/roms/openbios/drivers/ide.h b/qemu/roms/openbios/drivers/ide.h new file mode 100644 index 000000000..d6c4b9f5d --- /dev/null +++ b/qemu/roms/openbios/drivers/ide.h @@ -0,0 +1,213 @@ +#ifndef IDE_H +#define IDE_H + +#include "hdreg.h" + +/* + * legacy ide ports + */ +#define IDEREG_DATA 0x00 +#define IDEREG_ERROR 0x01 +#define IDEREG_FEATURE IDEREG_ERROR +#define IDEREG_NSECTOR 0x02 +#define IDEREG_SECTOR 0x03 +#define IDEREG_LCYL 0x04 +#define IDEREG_HCYL 0x05 +#define IDEREG_CURRENT 0x06 +#define IDEREG_STATUS 0x07 +#define IDEREG_COMMAND IDEREG_STATUS +#define IDEREG_CONTROL 0x08 +#define IDEREG_ASTATUS IDEREG_CONTROL + +/* + * device control bits + */ +#define IDECON_NIEN 0x02 +#define IDECON_SRST 0x04 + +/* + * device head bits + */ +#define IDEHEAD_LBA 0x40 +#define IDEHEAD_DEV0 0x00 +#define IDEHEAD_DEV1 0x10 + +/* + * status bytes + */ +#define ERR_STAT 0x01 +#define DRQ_STAT 0x08 +#define SEEK_STAT 0x10 +#define WRERR_STAT 0x20 +#define READY_STAT 0x40 +#define BUSY_STAT 0x80 + +#define IREASON_CD 0x01 +#define IREASON_IO 0x02 + +/* + * ATA opcodes + */ +#define WIN_READ 0x20 +#define WIN_READ_EXT 0x24 +#define WIN_IDENTIFY 0xEC +#define WIN_PACKET 0xA0 +#define WIN_IDENTIFY_PACKET 0xA1 + +/* + * ATAPI opcodes + */ +#define ATAPI_TUR 0x00 +#define ATAPI_READ_10 0x28 +#define ATAPI_REQ_SENSE 0x03 +#define ATAPI_START_STOP_UNIT 0x1b +#define ATAPI_READ_CAPACITY 0x25 + +/* + * atapi sense keys + */ +#define ATAPI_SENSE_NOT_READY 0x02 + +/* + * supported device types + */ +enum { + ide_type_unknown, + ide_type_ata, + ide_type_atapi, +}; + +enum { + ide_media_floppy = 0x00, + ide_media_cdrom = 0x05, + ide_media_optical = 0x07, + ide_media_disk = 0x20, +}; + +/* + * drive addressing + */ +enum { + ide_chs = 1, + ide_lba28, + ide_lba48, +}; + +/* + * simple ata command that works for everything (except 48-bit lba commands) + */ +struct ata_command { + unsigned char *buffer; + unsigned int buflen; + + /* + * data register + */ + unsigned char data; + unsigned char feature; + unsigned char nsector; + unsigned char sector; + unsigned char lcyl; + unsigned char hcyl; + unsigned char device_head; + unsigned char command; + unsigned char control; + + /* + * or tasklet, just for lba48 for now (above could be scrapped) + */ + unsigned char task[10]; + + /* + * output + */ + unsigned char stat; + unsigned int bytes; +}; + +struct atapi_command { + unsigned char cdb[12]; + unsigned char *buffer; + unsigned int buflen; + unsigned char data_direction; + + unsigned char stat; + unsigned char sense_valid; + struct request_sense sense; + unsigned char old_cdb; +}; + +struct ide_channel; + +struct ide_drive { + char unit; /* 0: master, 1: slave */ + char present; /* there or not */ + char type; /* ata or atapi */ + char media; /* disk, cdrom, etc */ + char addressing; /* chs/lba28/lba48 */ + + char model[41]; /* name */ + int nr; + + unsigned long sectors; + + unsigned int max_sectors; + + /* + * for legacy chs crap + */ + unsigned int cyl; + unsigned int head; + unsigned int sect; + + unsigned int bs; /* block size */ + + struct ide_channel *channel; +}; + +struct ide_channel { + + char name[32]; + struct ide_channel *next; + + /* + * either mmio or io_regs is set to indicate mmio or not + */ + unsigned long mmio; + int io_regs[10]; + + /* + * can be set to a mmio hook, default it legacy outb/inb + */ + void (*obide_outb)(struct ide_channel *chan, + unsigned char addr, unsigned int port); + unsigned char (*obide_inb)(struct ide_channel *chan, + unsigned int port); + void (*obide_insw)(struct ide_channel *chan, + unsigned int port, unsigned char *addr, + unsigned int count); + void (*obide_outsw)(struct ide_channel *chan, + unsigned int port, unsigned char *addr, + unsigned int count); + + struct ide_drive drives[2]; + char selected; + char present; + + /* + * only one can be busy per channel + */ + struct ata_command ata_cmd; + struct atapi_command atapi_cmd; + +}; + +enum { + atapi_ddir_none, + atapi_ddir_read, + atapi_ddir_write, +}; + +static int ob_ide_atapi_request_sense(struct ide_drive *drive); + +#endif diff --git a/qemu/roms/openbios/drivers/iommu.c b/qemu/roms/openbios/drivers/iommu.c new file mode 100644 index 000000000..cd9a64bb6 --- /dev/null +++ b/qemu/roms/openbios/drivers/iommu.c @@ -0,0 +1,207 @@ +/** + ** Proll (PROM replacement) + ** iommu.c: Functions for DVMA management. + ** Copyright 1999 Pete Zaitcev + ** This code is licensed under GNU General Public License. + **/ +#include "config.h" +#include "libopenbios/bindings.h" +#include "libopenbios/ofmem.h" +#include "drivers/drivers.h" +#include "iommu.h" +#include "arch/sparc32/ofmem_sparc32.h" + +#ifdef CONFIG_DEBUG_IOMMU +#define DPRINTF(fmt, args...) \ + do { printk(fmt , ##args); } while (0) +#else +#define DPRINTF(fmt, args...) +#endif + +/* + * IOMMU parameters + */ +struct iommu { + struct iommu_regs *regs; + unsigned int *page_table; + unsigned long plow; /* Base bus address */ +}; + +static struct iommu ciommu; + +static void +iommu_invalidate(struct iommu_regs *iregs) +{ + iregs->tlbflush = 0; +} + +/* + * XXX This is a problematic interface. We alloc _memory_ which is uncached. + * So if we ever reuse allocations somebody is going to get uncached pages. + * Returned address is always aligned by page. + * BTW, we were not going to give away anonymous storage, were we not? + */ +void * +dvma_alloc(int size, unsigned int *pphys) +{ + void *va; + unsigned int pa, ba; + unsigned int npages; + unsigned int mva, mpa; + unsigned int i; + unsigned int *iopte; + struct iommu *t = &ciommu; + int ret; + + npages = (size + (PAGE_SIZE-1)) / PAGE_SIZE; + ret = ofmem_posix_memalign(&va, npages * PAGE_SIZE, PAGE_SIZE); + if (ret != 0) + return NULL; + + ba = (unsigned int)mem_alloc(&cdvmem, npages * PAGE_SIZE, PAGE_SIZE); + if (ba == 0) + return NULL; + + pa = (unsigned int)va2pa((unsigned long)va); + + /* + * Change page attributes in MMU to uncached. + */ + mva = (unsigned int) va; + mpa = (unsigned int) pa; + ofmem_arch_map_pages(mpa, mva, npages * PAGE_SIZE, ofmem_arch_io_translation_mode(mpa)); + + /* + * Map into IOMMU page table. + */ + mpa = (unsigned int) pa; + iopte = &t->page_table[(ba - t->plow) / PAGE_SIZE]; + for (i = 0; i < npages; i++) { + *iopte++ = MKIOPTE(mpa); + mpa += PAGE_SIZE; + } + + *pphys = ba; + + return va; +} + +/* + * Initialize IOMMU + * This looks like initialization of CPU MMU but + * the routine is higher in food chain. + */ +static struct iommu_regs * +iommu_init(struct iommu *t, uint64_t base) +{ + unsigned int *ptab; + int ptsize; +#ifdef CONFIG_DEBUG_IOMMU + unsigned int impl, vers; +#endif + unsigned int tmp; + struct iommu_regs *regs; + int ret; + unsigned long vasize; + + regs = (struct iommu_regs *)ofmem_map_io(base, IOMMU_REGS); + if (regs == NULL) { + DPRINTF("Cannot map IOMMU\n"); + for (;;) { } + } + t->regs = regs; +#ifdef CONFIG_DEBUG_IOMMU + impl = (regs->control & IOMMU_CTRL_IMPL) >> 28; + vers = (regs->control & IOMMU_CTRL_VERS) >> 24; +#endif + + tmp = regs->control; + tmp &= ~(IOMMU_CTRL_RNGE); + + tmp |= (IOMMU_RNGE_32MB | IOMMU_CTRL_ENAB); + t->plow = 0xfe000000; /* End - 32 MB */ + /* Size of VA region that we manage */ + vasize = 0x2000000; /* 32 MB */ + + regs->control = tmp; + iommu_invalidate(regs); + + /* Allocate IOMMU page table */ + /* Tremendous alignment causes great waste... */ + ptsize = (vasize / PAGE_SIZE) * sizeof(int); + ret = ofmem_posix_memalign((void *)&ptab, ptsize, ptsize); + if (ret != 0) { + DPRINTF("Cannot allocate IOMMU table [0x%x]\n", ptsize); + for (;;) { } + } + t->page_table = ptab; + + /* flush_cache_all(); */ + /** flush_tlb_all(); **/ + tmp = (unsigned int)va2pa((unsigned long)ptab); + regs->base = tmp >> 4; + iommu_invalidate(regs); + + DPRINTF("IOMMU: impl %d vers %d page table at 0x%p (pa 0x%x) of size %d bytes\n", + impl, vers, t->page_table, tmp, ptsize); + + mem_init(&cdvmem, (char*)t->plow, (char *)0xfffff000); + return regs; +} + +/* ( addr.lo addr.hi size -- virt ) */ + +static void +ob_iommu_map_in(void) +{ + phys_addr_t phys; + ucell size, virt; + + size = POP(); + phys = POP(); + phys = (phys << 32) + POP(); + + virt = ofmem_map_io(phys, size); + + PUSH(virt); +} + +/* ( virt size ) */ + +static void +ob_iommu_map_out(void) +{ + ucell size = POP(); + ucell virt = POP(); + + ofmem_release_io(virt, size); +} + +void +ob_init_iommu(uint64_t base) +{ + struct iommu_regs *regs; + + regs = iommu_init(&ciommu, base); + + push_str("/iommu"); + fword("find-device"); + PUSH((unsigned long)regs); + fword("encode-int"); + push_str("address"); + fword("property"); + + PUSH(base >> 32); + fword("encode-int"); + PUSH(base & 0xffffffff); + fword("encode-int"); + fword("encode+"); + PUSH(IOMMU_REGS); + fword("encode-int"); + fword("encode+"); + push_str("reg"); + fword("property"); + + bind_func("map-in", ob_iommu_map_in); + bind_func("map-out", ob_iommu_map_out); +} diff --git a/qemu/roms/openbios/drivers/iommu.h b/qemu/roms/openbios/drivers/iommu.h new file mode 100644 index 000000000..59e3387ca --- /dev/null +++ b/qemu/roms/openbios/drivers/iommu.h @@ -0,0 +1,102 @@ +/* iommu.h: Definitions for the sun4m IOMMU. + * + * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) + * Adapted for Proll by Pete Zaitcev in 1999 (== made worse than original). + */ + +/* #include <asm/page.h> */ + +/* The iommu handles all virtual to physical address translations + * that occur between the SBUS and physical memory. Access by + * the cpu to IO registers and similar go over the mbus so are + * translated by the on chip SRMMU. The iommu and the srmmu do + * not need to have the same translations at all, in fact most + * of the time the translations they handle are a disjunct set. + * Basically the iommu handles all dvma sbus activity. + */ + +/* The IOMMU registers occupy three pages in IO space. */ +struct iommu_regs { + /* First page */ + volatile unsigned long control; /* IOMMU control */ + volatile unsigned long base; /* Physical base of iopte page table */ + volatile unsigned long _unused1[3]; + volatile unsigned long tlbflush; /* write only */ + volatile unsigned long pageflush; /* write only */ + volatile unsigned long _unused2[1017]; + /* Second page */ + volatile unsigned long afsr; /* Async-fault status register */ + volatile unsigned long afar; /* Async-fault physical address */ + volatile unsigned long _unused3[2]; + volatile unsigned long sbuscfg0; /* SBUS configuration registers, per-slot */ + volatile unsigned long sbuscfg1; + volatile unsigned long sbuscfg2; + volatile unsigned long sbuscfg3; + volatile unsigned long mfsr; /* Memory-fault status register */ + volatile unsigned long mfar; /* Memory-fault physical address */ + volatile unsigned long _unused4[1014]; + /* Third page */ + volatile unsigned long mid; /* IOMMU module-id */ +}; + +#define IOMMU_CTRL_IMPL 0xf0000000 /* Implementation */ +#define IOMMU_CTRL_VERS 0x0f000000 /* Version */ +#define IOMMU_CTRL_RNGE 0x0000001c /* Mapping RANGE */ +#define IOMMU_RNGE_16MB 0x00000000 /* 0xff000000 -> 0xffffffff */ +#define IOMMU_RNGE_32MB 0x00000004 /* 0xfe000000 -> 0xffffffff */ +#define IOMMU_RNGE_64MB 0x00000008 /* 0xfc000000 -> 0xffffffff */ +#define IOMMU_RNGE_128MB 0x0000000c /* 0xf8000000 -> 0xffffffff */ +#define IOMMU_RNGE_256MB 0x00000010 /* 0xf0000000 -> 0xffffffff */ +#define IOMMU_RNGE_512MB 0x00000014 /* 0xe0000000 -> 0xffffffff */ +#define IOMMU_RNGE_1GB 0x00000018 /* 0xc0000000 -> 0xffffffff */ +#define IOMMU_RNGE_2GB 0x0000001c /* 0x80000000 -> 0xffffffff */ +#define IOMMU_CTRL_ENAB 0x00000001 /* IOMMU Enable */ + +#define IOMMU_AFSR_ERR 0x80000000 /* LE, TO, or BE asserted */ +#define IOMMU_AFSR_LE 0x40000000 /* SBUS reports error after transaction */ +#define IOMMU_AFSR_TO 0x20000000 /* Write access took more than 12.8 us. */ +#define IOMMU_AFSR_BE 0x10000000 /* Write access received error acknowledge */ +#define IOMMU_AFSR_SIZE 0x0e000000 /* Size of transaction causing error */ +#define IOMMU_AFSR_S 0x01000000 /* Sparc was in supervisor mode */ +#define IOMMU_AFSR_RESV 0x00f00000 /* Reserver, forced to 0x8 by hardware */ +#define IOMMU_AFSR_ME 0x00080000 /* Multiple errors occurred */ +#define IOMMU_AFSR_RD 0x00040000 /* A read operation was in progress */ +#define IOMMU_AFSR_FAV 0x00020000 /* IOMMU afar has valid contents */ + +#define IOMMU_SBCFG_SAB30 0x00010000 /* Phys-address bit 30 when bypass enabled */ +#define IOMMU_SBCFG_BA16 0x00000004 /* Slave supports 16 byte bursts */ +#define IOMMU_SBCFG_BA8 0x00000002 /* Slave supports 8 byte bursts */ +#define IOMMU_SBCFG_BYPASS 0x00000001 /* Bypass IOMMU, treat all addresses + produced by this device as pure + physical. */ + +#define IOMMU_MFSR_ERR 0x80000000 /* One or more of PERR1 or PERR0 */ +#define IOMMU_MFSR_S 0x01000000 /* Sparc was in supervisor mode */ +#define IOMMU_MFSR_CPU 0x00800000 /* CPU transaction caused parity error */ +#define IOMMU_MFSR_ME 0x00080000 /* Multiple parity errors occurred */ +#define IOMMU_MFSR_PERR 0x00006000 /* high bit indicates parity error occurred + on the even word of the access, low bit + indicated odd word caused the parity error */ +#define IOMMU_MFSR_BM 0x00001000 /* Error occurred while in boot mode */ +#define IOMMU_MFSR_C 0x00000800 /* Address causing error was marked cacheable */ +#define IOMMU_MFSR_RTYP 0x000000f0 /* Memory request transaction type */ + +#define IOMMU_MID_SBAE 0x001f0000 /* SBus arbitration enable */ +#define IOMMU_MID_SE 0x00100000 /* Enables SCSI/ETHERNET arbitration */ +#define IOMMU_MID_SB3 0x00080000 /* Enable SBUS device 3 arbitration */ +#define IOMMU_MID_SB2 0x00040000 /* Enable SBUS device 2 arbitration */ +#define IOMMU_MID_SB1 0x00020000 /* Enable SBUS device 1 arbitration */ +#define IOMMU_MID_SB0 0x00010000 /* Enable SBUS device 0 arbitration */ +#define IOMMU_MID_MID 0x0000000f /* Module-id, hardcoded to 0x8 */ + +/* The format of an iopte in the page tables */ +#define IOPTE_PAGE 0x07ffff00 /* Physical page number (PA[30:12]) */ +#define IOPTE_CACHE 0x00000080 /* Cached (in vme IOCACHE or Viking/MXCC) */ +#define IOPTE_WRITE 0x00000004 /* Writeable */ +#define IOPTE_VALID 0x00000002 /* IOPTE is valid */ +#define IOPTE_WAZ 0x00000001 /* Write as zeros */ + +#define IOPERM (IOPTE_CACHE | IOPTE_WRITE | IOPTE_VALID) +#define MKIOPTE(phys) (((((phys)>>4) & IOPTE_PAGE) | IOPERM) & ~IOPTE_WAZ) + +#define IOMMU_REGS 0x300 diff --git a/qemu/roms/openbios/drivers/kbd.c b/qemu/roms/openbios/drivers/kbd.c new file mode 100644 index 000000000..43070d877 --- /dev/null +++ b/qemu/roms/openbios/drivers/kbd.c @@ -0,0 +1,116 @@ +/* + * <kbd.c> + * + * Open Hack'Ware BIOS generic keyboard input translation. + * + * Copyright (c) 2005 Jocelyn Mayer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License V2 + * as published by the Free Software Foundation + * + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + */ + +#include "config.h" +#include "libc/string.h" +#include "asm/types.h" +#include "kbd.h" + +//#define DEBUG_KBD +#ifdef DEBUG_KBD +#define KBD_DPRINTF(fmt, args...) \ +do { printk("KBD - %s: " fmt, __func__ , ##args); } while (0) +#else +#define KBD_DPRINTF(fmt, args...) do { } while (0) +#endif + +int kbd_set_keymap (kbd_t *kbd, int nb_keys, const keymap_t *keymap, const char **sequences) +{ + kbd->nb_keys = nb_keys; + kbd->keymap = keymap; + kbd->sequences = sequences; + + return 0; +} + +int kbd_translate_key (kbd_t *kbd, int keycode, int up_down, char *sequence) +{ + const keymap_t *keyt; + int mod_state, key, type; + int ret; + + ret = -1; + /* Get key table */ + if (keycode < kbd->nb_keys) { + keyt = &kbd->keymap[keycode]; + /* Get modifier state */ + mod_state = (kbd->mod_state | (kbd->mod_state >> 8)) & 0xFF; + /* Adjust with lock */ + if (keyt->lck_shift >= 0) { + if ((kbd->mod_state >> (16 + keyt->lck_shift)) & 0x01) { + KBD_DPRINTF("adjust with lock %02x => %02x (%d %08x)\n", + mod_state, + mod_state ^ ((kbd->mod_state >> + (16 + keyt->lck_shift)) & + 0x01), + keyt->lck_shift, kbd->mod_state); + } + mod_state ^= (kbd->mod_state >> (16 + keyt->lck_shift)) & 0x01; + } + key = keyt->trans[mod_state]; + type = key & 0xFF000000; + key &= ~0xFF000000; + switch (type) { + case KBD_TYPE_REGULAR: + if (!up_down) { + /* We don't care about up events on "normal" keys */ + *sequence = key; + ret = 1; + } + break; + case KBD_TYPE_SEQUENCE: + if (!up_down) { + /* We don't care about up events on "normal" keys */ + ret = strlen(kbd->sequences[key]); + memcpy(sequence, kbd->sequences[key], ret); + } + break; + case KBD_TYPE_LOCK: + if (!up_down) { + kbd->mod_state ^= key; + ret = -2; + KBD_DPRINTF("Change modifier type %d key %04x %s => %08x\n", + type, key, up_down ? "up" : "down", + kbd->mod_state); + } + break; + case KBD_TYPE_LMOD: + case KBD_TYPE_RMOD: + if (up_down) + kbd->mod_state &= ~key; + else + kbd->mod_state |= key; + KBD_DPRINTF("Change modifier type %d key %04x %s => %08x\n", + type, key, up_down ? "up" : "down", kbd->mod_state); + ret = -2; /* The caller may know the key was a modifier */ + break; + default: + KBD_DPRINTF("Unknown key: keycode=%02x mod_state=%02x (%08x)\n", + keycode, mod_state, kbd->mod_state); + break; + } + } else { + KBD_DPRINTF("Unmanaged key: keycode=%02x mod_state %08x\n", + keycode, kbd->mod_state); + } + + return ret; +} diff --git a/qemu/roms/openbios/drivers/kbd.h b/qemu/roms/openbios/drivers/kbd.h new file mode 100644 index 000000000..8a7d0d476 --- /dev/null +++ b/qemu/roms/openbios/drivers/kbd.h @@ -0,0 +1,108 @@ +/* + * <kbd.h> + * + * Open Hack'Ware BIOS generic keyboard management definitions. + * + * Copyright (c) 2005 Jocelyn Mayer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License V2 + * as published by the Free Software Foundation + * + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + */ + +#if !defined (__OHW_KBD_H__) +#define __OHW_KBD_H__ +typedef struct kbd_t kbd_t; +typedef struct keymap_t keymap_t; +struct kbd_t { + uint32_t mod_state; + /* Modifier state + * 0x00 kk ll rr + * | | | | + * Not used for now -+ | | | + * Locks ---------------+ | | + * Left modifiers ---------+ | + * Right modifiers -----------+ + */ + int nb_keys; + const keymap_t *keymap; + const char **sequences; +}; + +/* Modifiers */ +typedef enum { + KBD_MOD_SHIFT = 0x01, + KBD_MOD_CTRL = 0x02, + KBD_MOD_ALT = 0x04, + KBD_MOD_CMD = 0x08, + KBD_MOD_OPT = 0x10, +} kbd_modifiers; + +/* Locks */ +typedef enum { + KBD_LCK_CAPS = 0x01, + KBD_LCK_NUM = 0x02, + KBD_LCK_SCROLL = 0x04, +} kbd_locks; + +/* Lock shifts */ +typedef enum { + KBD_SH_NONE = -1, + KBD_SH_CAPS = 0, + KBD_SH_NUML = 1, + KBD_SH_SCRL = 2, +} kbd_lck_shifts; + +enum { + KBD_TYPE_REGULAR = 0 << 24, + KBD_TYPE_LMOD = 1 << 24, + KBD_TYPE_RMOD = 2 << 24, + KBD_TYPE_LOCK = 3 << 24, + KBD_TYPE_SEQUENCE = 4 << 24, +}; + +#define KBD_SEQUENCE(sequence) (KBD_TYPE_SEQUENCE | (sequence)) + +#define KBD_MOD_MAP(mod) \ +KBD_SH_NONE, { (mod), (mod), (mod), (mod), (mod), (mod), (mod), (mod), \ + (mod), (mod), (mod), (mod), (mod), (mod), (mod), (mod), \ + (mod), (mod), (mod), (mod), (mod), (mod), (mod), (mod), \ + (mod), (mod), (mod), (mod), (mod), (mod), (mod), (mod), } +#define KBD_MOD_MAP_LSHIFT KBD_MOD_MAP(KBD_TYPE_LMOD | KBD_MOD_SHIFT) +#define KBD_MOD_MAP_RSHIFT KBD_MOD_MAP(KBD_TYPE_RMOD | (KBD_MOD_SHIFT << 8)) +#define KBD_MOD_MAP_LCTRL KBD_MOD_MAP(KBD_TYPE_LMOD | KBD_MOD_CTRL) +#define KBD_MOD_MAP_RCTRL KBD_MOD_MAP(KBD_TYPE_RMOD | (KBD_MOD_CTRL << 8)) +#define KBD_MOD_MAP_LALT KBD_MOD_MAP(KBD_TYPE_LMOD | KBD_MOD_ALT) +#define KBD_MOD_MAP_RALT KBD_MOD_MAP(KBD_TYPE_RMOD | (KBD_MOD_ALT << 8)) +#define KBD_MOD_MAP_LCMD KBD_MOD_MAP(KBD_TYPE_LMOD | KBD_MOD_CMD) +#define KBD_MOD_MAP_RCMD KBD_MOD_MAP(KBD_TYPE_RMOD | (KBD_MOD_CMD << 8)) +#define KBD_MOD_MAP_LOPT KBD_MOD_MAP(KBD_TYPE_LMOD | KBD_MOD_OPT) +#define KBD_MOD_MAP_ROPT KBD_MOD_MAP(KBD_TYPE_RMOD | (KBD_MOD_OPT << 8)) +#define KBD_MOD_MAP_CAPS KBD_MOD_MAP(KBD_TYPE_LOCK | (KBD_LCK_CAPS << 16)) +#define KBD_MOD_MAP_NUML KBD_MOD_MAP(KBD_TYPE_LOCK | (KBD_LCK_NUML << 16)) +#define KBD_MOD_MAP_SCROLL KBD_MOD_MAP(KBD_TYPE_LOCK | (KBD_LCK_SCRL << 16)) +#define KBD_MAP_NONE KBD_MOD_MAP(-1) + +/* Keymap definition */ +struct keymap_t { + /* Set the lock which applies to this key (if any) */ + int lck_shift; + /* Key translations */ + uint32_t trans[32]; +}; + +void *kbd_new (int len); +int kbd_set_keymap (kbd_t *kbd, int nb_keys, const keymap_t *keymap, + const char **sequences); +int kbd_translate_key (kbd_t *kbd, int keycode, int up_down, char *sequence); + +#endif /* !defined (__OHW_KBD_H__) */ diff --git a/qemu/roms/openbios/drivers/macio.c b/qemu/roms/openbios/drivers/macio.c new file mode 100644 index 000000000..f54bc86dc --- /dev/null +++ b/qemu/roms/openbios/drivers/macio.c @@ -0,0 +1,281 @@ +/* + * derived from mol/mol.c, + * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#include "config.h" +#include "arch/common/nvram.h" +#include "packages/nvram.h" +#include "libopenbios/bindings.h" +#include "libc/byteorder.h" +#include "libc/vsprintf.h" + +#include "drivers/drivers.h" +#include "macio.h" +#include "cuda.h" +#include "escc.h" +#include "drivers/pci.h" + +#define OW_IO_NVRAM_SIZE 0x00020000 +#define OW_IO_NVRAM_OFFSET 0x00060000 +#define OW_IO_NVRAM_SHIFT 4 + +#define NW_IO_NVRAM_SIZE 0x00004000 +#define NW_IO_NVRAM_OFFSET 0xfff04000 + +#define IO_OPENPIC_SIZE 0x00040000 +#define IO_OPENPIC_OFFSET 0x00040000 + +static char *nvram; + +static int macio_nvram_shift(void) +{ + int nvram_flat; + + if (is_oldworld()) + return OW_IO_NVRAM_SHIFT; + + nvram_flat = fw_cfg_read_i32(FW_CFG_PPC_NVRAM_FLAT); + return nvram_flat ? 0 : 1; +} + +int +macio_get_nvram_size(void) +{ + int shift = macio_nvram_shift(); + if (is_oldworld()) + return OW_IO_NVRAM_SIZE >> shift; + else + return NW_IO_NVRAM_SIZE >> shift; +} + +static unsigned long macio_nvram_offset(void) +{ + unsigned long r; + + /* Hypervisor tells us where NVRAM lies */ + r = fw_cfg_read_i32(FW_CFG_PPC_NVRAM_ADDR); + if (r) + return r; + + /* Fall back to hardcoded addresses */ + if (is_oldworld()) + return OW_IO_NVRAM_OFFSET; + + return NW_IO_NVRAM_OFFSET; +} + +static unsigned long macio_nvram_size(void) +{ + if (is_oldworld()) + return OW_IO_NVRAM_SIZE; + else + return NW_IO_NVRAM_SIZE; +} + +void macio_nvram_init(const char *path, phys_addr_t addr) +{ + phandle_t chosen, aliases; + phandle_t dnode; + int props[2]; + char buf[64]; + unsigned long nvram_size, nvram_offset; + + nvram_offset = macio_nvram_offset(); + nvram_size = macio_nvram_size(); + + nvram = (char*)addr + nvram_offset; + snprintf(buf, sizeof(buf), "%s/nvram", path); + nvram_init(buf); + dnode = find_dev(buf); + set_int_property(dnode, "#bytes", arch_nvram_size() ); + props[0] = __cpu_to_be32(nvram_offset); + props[1] = __cpu_to_be32(nvram_size); + set_property(dnode, "reg", (char *)&props, sizeof(props)); + set_property(dnode, "device_type", "nvram", 6); + NEWWORLD(set_property(dnode, "compatible", "nvram,flash", 12)); + + chosen = find_dev("/chosen"); + push_str(buf); + fword("open-dev"); + set_int_property(chosen, "nvram", POP()); + + aliases = find_dev("/aliases"); + set_property(aliases, "nvram", buf, strlen(buf) + 1); +} + +#ifdef DUMP_NVRAM +static void +dump_nvram(void) +{ + int i, j; + for (i = 0; i < 10; i++) + { + for (j = 0; j < 16; j++) + printk ("%02x ", nvram[(i*16+j)<<4]); + printk (" "); + for (j = 0; j < 16; j++) + if (isprint(nvram[(i*16+j)<<4])) + printk("%c", nvram[(i*16+j)<<4]); + else + printk("."); + printk ("\n"); + } +} +#endif + + +void +macio_nvram_put(char *buf) +{ + int i; + unsigned int it_shift = macio_nvram_shift(); + + for (i=0; i < arch_nvram_size(); i++) + nvram[i << it_shift] = buf[i]; +#ifdef DUMP_NVRAM + printk("new nvram:\n"); + dump_nvram(); +#endif +} + +void +macio_nvram_get(char *buf) +{ + int i; + unsigned int it_shift = macio_nvram_shift(); + + for (i=0; i< arch_nvram_size(); i++) + buf[i] = nvram[i << it_shift]; + +#ifdef DUMP_NVRAM + printk("current nvram:\n"); + dump_nvram(); +#endif +} + +static void +openpic_init(const char *path, phys_addr_t addr) +{ + phandle_t dnode; + int props[2]; + char buf[128]; + + push_str(path); + fword("find-device"); + fword("new-device"); + push_str("interrupt-controller"); + fword("device-name"); + + snprintf(buf, sizeof(buf), "%s/interrupt-controller", path); + dnode = find_dev(buf); + set_property(dnode, "device_type", "open-pic", 9); + set_property(dnode, "compatible", "chrp,open-pic", 14); + set_property(dnode, "built-in", "", 0); + props[0] = __cpu_to_be32(IO_OPENPIC_OFFSET); + props[1] = __cpu_to_be32(IO_OPENPIC_SIZE); + set_property(dnode, "reg", (char *)&props, sizeof(props)); + set_int_property(dnode, "#interrupt-cells", 2); + set_int_property(dnode, "#address-cells", 0); + set_property(dnode, "interrupt-controller", "", 0); + set_int_property(dnode, "clock-frequency", 4166666); + + fword("finish-device"); +} + +DECLARE_NODE(ob_macio, INSTALL_OPEN, sizeof(int), "Tmac-io"); + +/* ( str len -- addr ) */ + +static void +ob_macio_decode_unit(void *private) +{ + ucell addr; + + const char *arg = pop_fstr_copy(); + + addr = strtol(arg, NULL, 16); + + free((char*)arg); + + PUSH(addr); +} + +/* ( addr -- str len ) */ + +static void +ob_macio_encode_unit(void *private) +{ + char buf[8]; + + ucell addr = POP(); + + snprintf(buf, sizeof(buf), "%x", addr); + + push_str(buf); +} + +NODE_METHODS(ob_macio) = { + { "decode-unit", ob_macio_decode_unit }, + { "encode-unit", ob_macio_encode_unit }, +}; + +static void +ob_unin_init(void) +{ + phandle_t dnode; + int props[2]; + + push_str("/"); + fword("find-device"); + fword("new-device"); + push_str("uni-n"); + fword("device-name"); + + dnode = find_dev("/uni-n"); + set_property(dnode, "device_type", "memory-controller", 18); + set_property(dnode, "compatible", "uni-north", 10); + set_int_property(dnode, "device-rev", 0); + props[0] = __cpu_to_be32(0xf8000000); + props[1] = __cpu_to_be32(0x1000000); + set_property(dnode, "reg", (char *)&props, sizeof(props)); + + fword("finish-device"); +} + +void +ob_macio_heathrow_init(const char *path, phys_addr_t addr) +{ + phandle_t aliases; + + REGISTER_NODE(ob_macio); + aliases = find_dev("/aliases"); + set_property(aliases, "mac-io", path, strlen(path) + 1); + + cuda_init(path, addr); + macio_nvram_init(path, addr); + escc_init(path, addr); + macio_ide_init(path, addr, 2); +} + +void +ob_macio_keylargo_init(const char *path, phys_addr_t addr) +{ + phandle_t aliases; + + aliases = find_dev("/aliases"); + set_property(aliases, "mac-io", path, strlen(path) + 1); + + cuda_init(path, addr); + /* The NewWorld NVRAM is not located in the MacIO device */ + macio_nvram_init("", 0); + escc_init(path, addr); + macio_ide_init(path, addr, 2); + openpic_init(path, addr); + ob_unin_init(); +} diff --git a/qemu/roms/openbios/drivers/macio.h b/qemu/roms/openbios/drivers/macio.h new file mode 100644 index 000000000..925b8812b --- /dev/null +++ b/qemu/roms/openbios/drivers/macio.h @@ -0,0 +1,5 @@ +extern phandle_t pic_handle; + +void ob_macio_heathrow_init(const char *path, phys_addr_t addr); +void ob_macio_keylargo_init(const char *path, phys_addr_t addr); +void macio_nvram_init(const char *path, phys_addr_t addr); diff --git a/qemu/roms/openbios/drivers/obio.c b/qemu/roms/openbios/drivers/obio.c new file mode 100644 index 000000000..7c135a362 --- /dev/null +++ b/qemu/roms/openbios/drivers/obio.c @@ -0,0 +1,525 @@ +/* + * OpenBIOS Sparc OBIO driver + * + * (C) 2004 Stefan Reinauer <stepan@openbios.org> + * (C) 2005 Ed Schouten <ed@fxq.nl> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#include "config.h" +#include "libopenbios/bindings.h" +#include "kernel/kernel.h" +#include "libc/byteorder.h" +#include "libc/vsprintf.h" + +#include "drivers/drivers.h" +#include "arch/common/nvram.h" +#include "libopenbios/ofmem.h" +#include "obio.h" +#include "escc.h" + +#define PROMDEV_KBD 0 /* input from keyboard */ +#define PROMDEV_SCREEN 0 /* output to screen */ +#define PROMDEV_TTYA 1 /* in/out to ttya */ + +/* DECLARE data structures for the nodes. */ +DECLARE_UNNAMED_NODE( ob_obio, INSTALL_OPEN, sizeof(int) ); + +void +ob_new_obio_device(const char *name, const char *type) +{ + push_str("/obio"); + fword("find-device"); + fword("new-device"); + + push_str(name); + fword("device-name"); + + if (type) { + push_str(type); + fword("device-type"); + } +} + +static unsigned long +map_reg(uint64_t base, uint64_t offset, unsigned long size, int map, + int phys_hi) +{ + PUSH(phys_hi); + fword("encode-int"); + PUSH(offset); + fword("encode-int"); + fword("encode+"); + PUSH(size); + fword("encode-int"); + fword("encode+"); + push_str("reg"); + fword("property"); + + if (map) { + unsigned long addr; + + addr = (unsigned long)ofmem_map_io(base + offset, size); + + PUSH(addr); + fword("encode-int"); + push_str("address"); + fword("property"); + return addr; + } + return 0; +} + +unsigned long +ob_reg(uint64_t base, uint64_t offset, unsigned long size, int map) +{ + return map_reg(base, offset, size, map, 0); +} + +void +ob_intr(int intr) +{ + PUSH(intr); + fword("encode-int"); + PUSH(0); + fword("encode-int"); + fword("encode+"); + push_str("intr"); + fword("property"); +} + +void +ob_eccmemctl_init(uint64_t base) +{ + uint32_t version, *regs; + const char *mc_type; + + push_str("/"); + fword("find-device"); + fword("new-device"); + + push_str("eccmemctl"); + fword("device-name"); + + PUSH(0x20); + fword("encode-int"); + push_str("width"); + fword("property"); + + regs = (uint32_t *)map_reg(ECC_BASE, 0, ECC_SIZE, 1, ECC_BASE >> 32); + + version = regs[0]; + switch (version) { + case 0x00000000: + mc_type = "MCC"; + break; + case 0x10000000: + mc_type = "EMC"; + break; + default: + case 0x20000000: + mc_type = "SMC"; + break; + } + push_str(mc_type); + fword("encode-string"); + push_str("mc-type"); + fword("property"); + + fword("finish-device"); +} + +static unsigned char *nvram; + +#define NVRAM_OB_START (0) +#define NVRAM_OB_SIZE ((NVRAM_IDPROM - NVRAM_OB_START) & ~15) + +void +arch_nvram_get(char *data) +{ + memcpy(data, &nvram[NVRAM_OB_START], NVRAM_OB_SIZE); +} + +void +arch_nvram_put(char *data) +{ + memcpy(&nvram[NVRAM_OB_START], data, NVRAM_OB_SIZE); +} + +int +arch_nvram_size(void) +{ + return NVRAM_OB_SIZE; +} + +void +ss5_init(uint64_t base) +{ + ob_new_obio_device("slavioconfig", NULL); + + ob_reg(base, SLAVIO_SCONFIG, SCONFIG_REGS, 0); + + fword("finish-device"); +} + +static void +ob_nvram_init(uint64_t base, uint64_t offset) +{ + ob_new_obio_device("eeprom", NULL); + + nvram = (unsigned char *)ob_reg(base, offset, NVRAM_SIZE, 1); + + PUSH((unsigned long)nvram); + fword("encode-int"); + push_str("address"); + fword("property"); + + push_str("mk48t08"); + fword("model"); + + fword("finish-device"); + + // Add /idprom + push_str("/"); + fword("find-device"); + + PUSH((long)&nvram[NVRAM_IDPROM]); + PUSH(32); + fword("encode-bytes"); + push_str("idprom"); + fword("property"); +} + +static void +ob_fd_init(uint64_t base, uint64_t offset, int intr) +{ + unsigned long addr; + + ob_new_obio_device("SUNW,fdtwo", "block"); + + addr = ob_reg(base, offset, FD_REGS, 1); + + ob_intr(intr); + + fword("is-deblocker"); + + ob_floppy_init("/obio", "SUNW,fdtwo", 0, addr); + + fword("finish-device"); +} + +static void +ob_auxio_init(uint64_t base, uint64_t offset) +{ + ob_new_obio_device("auxio", NULL); + + ob_reg(base, offset, AUXIO_REGS, 1); + + fword("finish-device"); +} + +volatile unsigned char *power_reg; +volatile unsigned int *reset_reg; + +static void +sparc32_reset_all(void) +{ + *reset_reg = 1; +} + +// AUX 2 (Software Powerdown Control) and reset +static void +ob_aux2_reset_init(uint64_t base, uint64_t offset, int intr) +{ + ob_new_obio_device("power", NULL); + + power_reg = (void *)ob_reg(base, offset, AUXIO2_REGS, 1); + + // Not in device tree + reset_reg = (unsigned int *)ofmem_map_io(base + (uint64_t)SLAVIO_RESET, RESET_REGS); + + bind_func("sparc32-reset-all", sparc32_reset_all); + push_str("' sparc32-reset-all to reset-all"); + fword("eval"); + + ob_intr(intr); + + fword("finish-device"); +} + +volatile struct sun4m_timer_regs *counter_regs; + +static void +ob_counter_init(uint64_t base, unsigned long offset, int ncpu) +{ + int i; + + ob_new_obio_device("counter", NULL); + + for (i = 0; i < ncpu; i++) { + PUSH(0); + fword("encode-int"); + if (i != 0) fword("encode+"); + PUSH(offset + (i * PAGE_SIZE)); + fword("encode-int"); + fword("encode+"); + PUSH(COUNTER_REGS); + fword("encode-int"); + fword("encode+"); + } + + PUSH(0); + fword("encode-int"); + fword("encode+"); + PUSH(offset + 0x10000); + fword("encode-int"); + fword("encode+"); + PUSH(COUNTER_REGS); + fword("encode-int"); + fword("encode+"); + + push_str("reg"); + fword("property"); + + + counter_regs = (struct sun4m_timer_regs *)ofmem_map_io(base + (uint64_t)offset, sizeof(*counter_regs)); + counter_regs->cfg = 0xfffffffe; + counter_regs->l10_timer_limit = 0; + counter_regs->cpu_timers[0].l14_timer_limit = 0x9c4000; /* see comment in obio.h */ + counter_regs->cpu_timers[0].cntrl = 1; + + for (i = 0; i < ncpu; i++) { + PUSH((unsigned long)&counter_regs->cpu_timers[i]); + fword("encode-int"); + if (i != 0) + fword("encode+"); + } + PUSH((unsigned long)&counter_regs->l10_timer_limit); + fword("encode-int"); + fword("encode+"); + push_str("address"); + fword("property"); + + fword("finish-device"); +} + +static volatile struct sun4m_intregs *intregs; + +static void +ob_interrupt_init(uint64_t base, unsigned long offset, int ncpu) +{ + int i; + + ob_new_obio_device("interrupt", NULL); + + for (i = 0; i < ncpu; i++) { + PUSH(0); + fword("encode-int"); + if (i != 0) fword("encode+"); + PUSH(offset + (i * PAGE_SIZE)); + fword("encode-int"); + fword("encode+"); + PUSH(INTERRUPT_REGS); + fword("encode-int"); + fword("encode+"); + } + + PUSH(0); + fword("encode-int"); + fword("encode+"); + PUSH(offset + 0x10000); + fword("encode-int"); + fword("encode+"); + PUSH(INTERRUPT_REGS); + fword("encode-int"); + fword("encode+"); + + push_str("reg"); + fword("property"); + + intregs = (struct sun4m_intregs *)ofmem_map_io(base | (uint64_t)offset, sizeof(*intregs)); + intregs->clear = ~SUN4M_INT_MASKALL; + intregs->cpu_intregs[0].clear = ~0x17fff; + + for (i = 0; i < ncpu; i++) { + PUSH((unsigned long)&intregs->cpu_intregs[i]); + fword("encode-int"); + if (i != 0) + fword("encode+"); + } + PUSH((unsigned long)&intregs->tbt); + fword("encode-int"); + fword("encode+"); + push_str("address"); + fword("property"); + + fword("finish-device"); +} + +/* SMP CPU boot structure */ +struct smp_cfg { + uint32_t smp_ctx; + uint32_t smp_ctxtbl; + uint32_t smp_entry; + uint32_t valid; +}; + +static struct smp_cfg *smp_header; + +int +start_cpu(unsigned int pc, unsigned int context_ptr, unsigned int context, int cpu) +{ + if (!cpu) + return -1; + + cpu &= 7; + + smp_header->smp_entry = pc; + smp_header->smp_ctxtbl = context_ptr; + smp_header->smp_ctx = context; + smp_header->valid = cpu; + + intregs->cpu_intregs[cpu].set = SUN4M_SOFT_INT(14); + + return 0; +} + +static void +ob_smp_init(unsigned long mem_size) +{ + // See arch/sparc32/entry.S for memory layout + smp_header = (struct smp_cfg *)ofmem_map_io((uint64_t)(mem_size - 0x100), + sizeof(struct smp_cfg)); +} + +static void +ob_obio_open(__attribute__((unused))int *idx) +{ + int ret=1; + RET ( -ret ); +} + +static void +ob_obio_close(__attribute__((unused))int *idx) +{ + selfword("close-deblocker"); +} + +static void +ob_obio_initialize(__attribute__((unused))int *idx) +{ + push_str("/"); + fword("find-device"); + fword("new-device"); + + push_str("obio"); + fword("device-name"); + + push_str("hierarchical"); + fword("device-type"); + + PUSH(2); + fword("encode-int"); + push_str("#address-cells"); + fword("property"); + + PUSH(1); + fword("encode-int"); + push_str("#size-cells"); + fword("property"); + + fword("finish-device"); +} + +static void +ob_set_obio_ranges(uint64_t base) +{ + push_str("/obio"); + fword("find-device"); + PUSH(0); + fword("encode-int"); + PUSH(0); + fword("encode-int"); + fword("encode+"); + PUSH(base >> 32); + fword("encode-int"); + fword("encode+"); + PUSH(base & 0xffffffff); + fword("encode-int"); + fword("encode+"); + PUSH(SLAVIO_SIZE); + fword("encode-int"); + fword("encode+"); + push_str("ranges"); + fword("property"); +} + +static void +ob_obio_decodeunit(__attribute__((unused)) int *idx) +{ + fword("decode-unit-sbus"); +} + + +static void +ob_obio_encodeunit(__attribute__((unused)) int *idx) +{ + fword("encode-unit-sbus"); +} + +NODE_METHODS(ob_obio) = { + { NULL, ob_obio_initialize }, + { "open", ob_obio_open }, + { "close", ob_obio_close }, + { "encode-unit", ob_obio_encodeunit }, + { "decode-unit", ob_obio_decodeunit }, +}; + + +int +ob_obio_init(uint64_t slavio_base, unsigned long fd_offset, + unsigned long counter_offset, unsigned long intr_offset, + int intr_ncpu, unsigned long aux1_offset, unsigned long aux2_offset, + unsigned long mem_size) +{ + + // All devices were integrated to NCR89C105, see + // http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C105.txt + + //printk("Initializing OBIO devices...\n"); +#if 0 // XXX + REGISTER_NAMED_NODE(ob_obio, "/obio"); + device_end(); +#endif + ob_set_obio_ranges(slavio_base); + + // Zilog Z8530 serial ports, see http://www.zilog.com + // Must be before zs@0,0 or Linux won't boot + ob_zs_init(slavio_base, SLAVIO_ZS1, ZS_INTR, 0, 0); + + ob_zs_init(slavio_base, SLAVIO_ZS, ZS_INTR, 1, 1); + + // M48T08 NVRAM, see http://www.st.com + ob_nvram_init(slavio_base, SLAVIO_NVRAM); + + // 82078 FDC + if (fd_offset != (unsigned long) -1) + ob_fd_init(slavio_base, fd_offset, FD_INTR); + + ob_auxio_init(slavio_base, aux1_offset); + + if (aux2_offset != (unsigned long) -1) + ob_aux2_reset_init(slavio_base, aux2_offset, AUXIO2_INTR); + + ob_counter_init(slavio_base, counter_offset, intr_ncpu); + + ob_interrupt_init(slavio_base, intr_offset, intr_ncpu); + + ob_smp_init(mem_size); + + return 0; +} diff --git a/qemu/roms/openbios/drivers/obio.h b/qemu/roms/openbios/drivers/obio.h new file mode 100644 index 000000000..49c3040c4 --- /dev/null +++ b/qemu/roms/openbios/drivers/obio.h @@ -0,0 +1,165 @@ +/* Addresses, interrupt numbers, register sizes */ + +#define SLAVIO_ZS 0x00000000ULL +#define SLAVIO_ZS1 0x00100000ULL +#define ZS_INTR 0x2c + +#define SLAVIO_NVRAM 0x00200000ULL +#define NVRAM_SIZE 0x2000 +#define NVRAM_IDPROM 0x1fd8 + +#define SLAVIO_FD 0x00400000ULL +#define FD_REGS 15 +#define FD_INTR 0x2b + +#define SLAVIO_SCONFIG 0x00800000ULL +#define SCONFIG_REGS 1 + +#define AUXIO_REGS 1 + +#define AUXIO2_REGS 1 +#define AUXIO2_INTR 0x22 + +#define SLAVIO_COUNTER 0x00d00000ULL +#define COUNTER_REGS 0x10 + +#define SLAVIO_INTERRUPT 0x00e00000ULL +#define INTERRUPT_REGS 0x10 + +#define SLAVIO_RESET 0x00f00000ULL +#define RESET_REGS 1 + +#define ECC_BASE 0xf00000000ULL +#define ECC_SIZE 0x20 + +#define SLAVIO_SIZE 0x01000000 + +#define SUN4M_NCPUS 16 + +#define CFG_ADDR 0xd00000510ULL +#define CFG_SIZE 3 + +/* linux/include/asm-sparc/timer.h */ + +/* A sun4m has two blocks of registers which are probably of the same + * structure. LSI Logic's L64851 is told to _decrement_ from the limit + * value. Aurora behaves similarly but its limit value is compacted in + * other fashion (it's wider). Documented fields are defined here. + */ + +/* As with the interrupt register, we have two classes of timer registers + * which are per-cpu and master. Per-cpu timers only hit that cpu and are + * only level 14 ticks, master timer hits all cpus and is level 10. + */ + +#define SUN4M_PRM_CNT_L 0x80000000 +#define SUN4M_PRM_CNT_LVALUE 0x7FFFFC00 + +struct sun4m_timer_percpu_info { + __volatile__ unsigned int l14_timer_limit; /* Initial value is 0x009c4000 */ + __volatile__ unsigned int l14_cur_count; + + /* This register appears to be write only and/or inaccessible + * on Uni-Processor sun4m machines. + */ + __volatile__ unsigned int l14_limit_noclear; /* Data access error is here */ + + __volatile__ unsigned int cntrl; /* =1 after POST on Aurora */ + __volatile__ unsigned char space[PAGE_SIZE - 16]; +}; + +struct sun4m_timer_regs { + struct sun4m_timer_percpu_info cpu_timers[SUN4M_NCPUS]; + volatile unsigned int l10_timer_limit; + volatile unsigned int l10_cur_count; + + /* Again, this appears to be write only and/or inaccessible + * on uni-processor sun4m machines. + */ + volatile unsigned int l10_limit_noclear; + + /* This register too, it must be magic. */ + volatile unsigned int foobar; + + volatile unsigned int cfg; /* equals zero at boot time... */ +}; + +/* + * Registers of hardware timer in sun4m. + */ +struct sun4m_timer_percpu { + volatile unsigned int l14_timer_limit; /* Initial value is 0x009c4000 = 10ms period*/ + volatile unsigned int l14_cur_count; +}; + +struct sun4m_timer_global { + volatile unsigned int l10_timer_limit; + volatile unsigned int l10_cur_count; +}; + +/* linux/include/asm-sparc/irq.h */ + +/* These registers are used for sending/receiving irqs from/to + * different cpu's. + */ +struct sun4m_intreg_percpu { + unsigned int tbt; /* Interrupts still pending for this cpu. */ + + /* These next two registers are WRITE-ONLY and are only + * "on bit" sensitive, "off bits" written have NO affect. + */ + unsigned int clear; /* Clear this cpus irqs here. */ + unsigned int set; /* Set this cpus irqs here. */ + unsigned char space[PAGE_SIZE - 12]; +}; + +/* + * djhr + * Actually the clear and set fields in this struct are misleading.. + * according to the SLAVIO manual (and the same applies for the SEC) + * the clear field clears bits in the mask which will ENABLE that IRQ + * the set field sets bits in the mask to DISABLE the IRQ. + * + * Also the undirected_xx address in the SLAVIO is defined as + * RESERVED and write only.. + * + * DAVEM_NOTE: The SLAVIO only specifies behavior on uniprocessor + * sun4m machines, for MP the layout makes more sense. + */ +struct sun4m_intregs { + struct sun4m_intreg_percpu cpu_intregs[SUN4M_NCPUS]; + unsigned int tbt; /* IRQ's that are still pending. */ + unsigned int irqs; /* Master IRQ bits. */ + + /* Again, like the above, two these registers are WRITE-ONLY. */ + unsigned int clear; /* Clear master IRQ's by setting bits here. */ + unsigned int set; /* Set master IRQ's by setting bits here. */ + + /* This register is both READ and WRITE. */ + unsigned int undirected_target; /* Which cpu gets undirected irqs. */ +}; + +/* Dave Redman (djhr@tadpole.co.uk) + * The sun4m interrupt registers. + */ +#define SUN4M_INT_ENABLE 0x80000000 +#define SUN4M_INT_E14 0x00000080 +#define SUN4M_INT_E10 0x00080000 + +#define SUN4M_HARD_INT(x) (0x000000001 << (x)) +#define SUN4M_SOFT_INT(x) (0x000010000 << (x)) + +#define SUN4M_INT_MASKALL 0x80000000 /* mask all interrupts */ +#define SUN4M_INT_MODULE_ERR 0x40000000 /* module error */ +#define SUN4M_INT_M2S_WRITE 0x20000000 /* write buffer error */ +#define SUN4M_INT_ECC 0x10000000 /* ecc memory error */ +#define SUN4M_INT_FLOPPY 0x00400000 /* floppy disk */ +#define SUN4M_INT_MODULE 0x00200000 /* module interrupt */ +#define SUN4M_INT_VIDEO 0x00100000 /* onboard video */ +#define SUN4M_INT_REALTIME 0x00080000 /* system timer */ +#define SUN4M_INT_SCSI 0x00040000 /* onboard scsi */ +#define SUN4M_INT_AUDIO 0x00020000 /* audio/isdn */ +#define SUN4M_INT_ETHERNET 0x00010000 /* onboard ethernet */ +#define SUN4M_INT_SERIAL 0x00008000 /* serial ports */ +#define SUN4M_INT_KBDMS 0x00004000 /* keyboard/mouse */ +#define SUN4M_INT_SBUSBITS 0x00003F80 /* sbus int bits */ diff --git a/qemu/roms/openbios/drivers/pc_kbd.c b/qemu/roms/openbios/drivers/pc_kbd.c new file mode 100644 index 000000000..49218f82e --- /dev/null +++ b/qemu/roms/openbios/drivers/pc_kbd.c @@ -0,0 +1,236 @@ +/* + * Copyright (C) 2003, 2004 Stefan Reinauer + * + * See the file "COPYING" for further information about + * the copyright and warranty status of this work. + */ + +#include "config.h" +#include "libopenbios/bindings.h" +#include "kernel/kernel.h" +#include "drivers/drivers.h" +#include "libc/vsprintf.h" + +/* ****************************************************************** + * simple polling video/keyboard console functions + * ****************************************************************** */ + +#define SER_SIZE 8 + +/* + * keyboard driver + */ + +static const char normal[] = { + 0x0, 0x1b, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', + '=', '\b', '\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', + 'p', '[', ']', 0xa, 0x0, 'a', 's', 'd', 'f', 'g', 'h', 'j', + 'k', 'l', ';', 0x27, 0x60, 0x0, 0x5c, 'z', 'x', 'c', 'v', 'b', + 'n', 'm', ',', '.', '/', 0x0, '*', 0x0, ' ', 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, '0', 0x7f +}; + +static const char shifted[] = { + 0x0, 0x1b, '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', + '+', '\b', '\t', 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', + 'P', '{', '}', 0xa, 0x0, 'A', 'S', 'D', 'F', 'G', 'H', 'J', + 'K', 'L', ':', 0x22, '~', 0x0, '|', 'Z', 'X', 'C', 'V', 'B', + 'N', 'M', '<', '>', '?', 0x0, '*', 0x0, ' ', 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, '7', '8', + '9', 0x0, '4', '5', '6', 0x0, '1', '2', '3', '0', 0x7f +}; + +static int key_ext; +static int key_lshift = 0, key_rshift = 0, key_caps = 0; + +static char last_key; + +static void pc_kbd_cmd(unsigned char cmd, unsigned char val) +{ + outb(cmd, 0x60); + /* wait until keyboard controller accepts cmds: */ + while (inb(0x64) & 2); + outb(val, 0x60); + while (inb(0x64) & 2); +} + +static void pc_kbd_controller_cmd(unsigned char cmd, unsigned char val) +{ + outb(cmd, 0x64); + /* wait until keyboard controller accepts cmds: */ + while (inb(0x64) & 2); + outb(val, 0x60); + while (inb(0x64) & 2); +} + +static char pc_kbd_poll(void) +{ + unsigned int c; + if (inb(0x64) & 1) { + c = inb(0x60); + switch (c) { + case 0xe0: + key_ext = 1; + return 0; + case 0x2a: + key_lshift = 1; + return 0; + case 0x36: + key_rshift = 1; + return 0; + case 0xaa: + key_lshift = 0; + return 0; + case 0xb6: + key_rshift = 0; + return 0; + case 0x3a: + if (key_caps) { + key_caps = 0; + pc_kbd_cmd(0xed, 0); + } else { + key_caps = 1; + pc_kbd_cmd(0xed, 4); /* set caps led */ + } + return 0; + } + + if (key_ext) { + // void printk(const char *format, ...); + printk("extended keycode: %x\n", c); + + key_ext = 0; + return 0; + } + + if (c & 0x80) /* unhandled key release */ + return 0; + + if (key_lshift || key_rshift) + return key_caps ? normal[c] : shifted[c]; + else + return key_caps ? shifted[c] : normal[c]; + } + return 0; +} + +int pc_kbd_dataready(void) +{ + if (last_key) + return 1; + + last_key = pc_kbd_poll(); + + return (last_key != 0); +} + +unsigned char pc_kbd_readdata(void) +{ + char tmp; + while (!pc_kbd_dataready()); + tmp = last_key; + last_key = 0; + return tmp; +} + +/* ( addr len -- actual ) */ +static void +pc_kbd_read(void) +{ + unsigned char *addr; + int len; + + len = POP(); + addr = (unsigned char *)POP(); + + if (len != 1) + printk("pc_kbd_read: bad len, addr %lx len %x\n", (unsigned long)addr, len); + + if (pc_kbd_dataready()) { + *addr = pc_kbd_readdata(); + PUSH(1); + } else { + PUSH(0); + } +} + +static void +pc_kbd_close(void) +{ +} + +static void +pc_kbd_open(unsigned long *address) +{ + int len; + phandle_t ph; + unsigned long *prop; + + fword("my-self"); + fword("ihandle>phandle"); + ph = (phandle_t)POP(); + prop = (unsigned long *)get_property(ph, "address", &len); + *address = *prop; + + RET ( -1 ); +} + +DECLARE_UNNAMED_NODE(pc_kbd, INSTALL_OPEN, sizeof(unsigned long)); + +NODE_METHODS(pc_kbd) = { + { "open", pc_kbd_open }, + { "close", pc_kbd_close }, + { "read", pc_kbd_read }, +}; + +void +ob_pc_kbd_init(const char *path, const char *dev_name, uint64_t base, + uint64_t offset, int intr) +{ + phandle_t chosen, aliases; + char nodebuff[128]; + + snprintf(nodebuff, sizeof(nodebuff), "%s/%s", path, dev_name); + REGISTER_NAMED_NODE(pc_kbd, nodebuff); + + push_str(nodebuff); + fword("find-device"); + + push_str(dev_name); + fword("device-name"); + + push_str("serial"); + fword("device-type"); + + PUSH(-1); + fword("encode-int"); + push_str("keyboard"); + fword("property"); + + PUSH((base + offset) >> 32); + fword("encode-int"); + PUSH((base + offset) & 0xffffffff); + fword("encode-int"); + fword("encode+"); + PUSH(SER_SIZE); + fword("encode-int"); + fword("encode+"); + push_str("reg"); + fword("property"); + + PUSH(offset); + fword("encode-int"); + push_str("address"); + fword("property"); + + chosen = find_dev("/chosen"); + push_str(nodebuff); + fword("open-dev"); + set_int_property(chosen, "keyboard", POP()); + + aliases = find_dev("/aliases"); + set_property(aliases, "keyboard", nodebuff, strlen(nodebuff) + 1); + + pc_kbd_controller_cmd(0x60, 0x40); // Write mode command, translated mode +} diff --git a/qemu/roms/openbios/drivers/pc_serial.c b/qemu/roms/openbios/drivers/pc_serial.c new file mode 100644 index 000000000..a638e1f99 --- /dev/null +++ b/qemu/roms/openbios/drivers/pc_serial.c @@ -0,0 +1,208 @@ +/* + * Copyright (C) 2003, 2004 Stefan Reinauer + * + * See the file "COPYING" for further information about + * the copyright and warranty status of this work. + */ + +#include "config.h" +#include "libopenbios/bindings.h" +#include "kernel/kernel.h" +#include "drivers/drivers.h" +#include "libc/vsprintf.h" + +/* ****************************************************************** + * serial console functions + * ****************************************************************** */ + +#define SER_SIZE 8 + +#define RBR(x) x==2?0x2f8:0x3f8 +#define THR(x) x==2?0x2f8:0x3f8 +#define IER(x) x==2?0x2f9:0x3f9 +#define IIR(x) x==2?0x2fa:0x3fa +#define LCR(x) x==2?0x2fb:0x3fb +#define MCR(x) x==2?0x2fc:0x3fc +#define LSR(x) x==2?0x2fd:0x3fd +#define MSR(x) x==2?0x2fe:0x3fe +#define SCR(x) x==2?0x2ff:0x3ff +#define DLL(x) x==2?0x2f8:0x3f8 +#define DLM(x) x==2?0x2f9:0x3f9 + +int uart_charav(int port) +{ + return ((inb(LSR(port)) & 1) != 0); +} + +char uart_getchar(int port) +{ + while (!uart_charav(port)); + return ((char) inb(RBR(port)) & 0177); +} + +static void uart_port_putchar(int port, unsigned char c) +{ + if (c == '\n') + uart_port_putchar(port, '\r'); + while (!(inb(LSR(port)) & 0x20)); + outb(c, THR(port)); +} + +static void uart_init_line(int port, unsigned long baud) +{ + int i, baudconst; + + switch (baud) { + case 115200: + baudconst = 1; + break; + case 57600: + baudconst = 2; + break; + case 38400: + baudconst = 3; + break; + case 19200: + baudconst = 6; + break; + case 9600: + default: + baudconst = 12; + break; + } + + outb(0x87, LCR(port)); + outb(0x00, DLM(port)); + outb(baudconst, DLL(port)); + outb(0x07, LCR(port)); + outb(0x0f, MCR(port)); + + for (i = 10; i > 0; i--) { + if (inb(LSR(port)) == (unsigned int) 0) + break; + inb(RBR(port)); + } +} + +#ifdef CONFIG_DEBUG_CONSOLE_SERIAL +int uart_init(int port, unsigned long speed) +{ + uart_init_line(port, speed); + return -1; +} + +void uart_putchar(int c) +{ + uart_port_putchar(CONFIG_SERIAL_PORT, (unsigned char) (c & 0xff)); +} +#endif + +/* ( addr len -- actual ) */ +static void +pc_serial_read(unsigned long *address) +{ + char *addr; + int len; + + len = POP(); + addr = (char *)POP(); + + if (len != 1) + printk("pc_serial_read: bad len, addr %lx len %x\n", (unsigned long)addr, len); + + if (uart_charav(*address)) { + *addr = (char)uart_getchar(*address); + PUSH(1); + } else { + PUSH(0); + } +} + +/* ( addr len -- actual ) */ +static void +pc_serial_write(unsigned long *address) +{ + unsigned char *addr; + int i, len; + + len = POP(); + addr = (unsigned char *)POP(); + + for (i = 0; i < len; i++) { + uart_port_putchar(*address, addr[i]); + } + PUSH(len); +} + +static void +pc_serial_close(void) +{ +} + +static void +pc_serial_open(unsigned long *address) +{ + RET ( -1 ); +} + +static void +pc_serial_init(unsigned long *address) +{ + *address = POP(); +} + +DECLARE_UNNAMED_NODE(pc_serial, INSTALL_OPEN, sizeof(unsigned long)); + +NODE_METHODS(pc_serial) = { + { "init", pc_serial_init }, + { "open", pc_serial_open }, + { "close", pc_serial_close }, + { "read", pc_serial_read }, + { "write", pc_serial_write }, +}; + +void +ob_pc_serial_init(const char *path, const char *dev_name, uint64_t base, + uint64_t offset, int intr) +{ + phandle_t aliases; + char nodebuff[128]; + + snprintf(nodebuff, sizeof(nodebuff), "%s/%s", path, dev_name); + REGISTER_NAMED_NODE(pc_serial, nodebuff); + + push_str(nodebuff); + fword("find-device"); + + PUSH(offset); + PUSH(find_package_method("init", get_cur_dev())); + fword("execute"); + + push_str("serial"); + fword("device-type"); + + PUSH((base + offset) >> 32); + fword("encode-int"); + PUSH((base + offset) & 0xffffffff); + fword("encode-int"); + fword("encode+"); + PUSH(SER_SIZE); + fword("encode-int"); + fword("encode+"); + push_str("reg"); + fword("property"); + +#if !defined(CONFIG_SPARC64) + PUSH(offset); + fword("encode-int"); + push_str("address"); + fword("property"); +#endif + +#if defined(CONFIG_SPARC64) + set_int_property(get_cur_dev(), "interrupts", 1); +#endif + + aliases = find_dev("/aliases"); + set_property(aliases, "ttya", nodebuff, strlen(nodebuff) + 1); +} diff --git a/qemu/roms/openbios/drivers/pci.c b/qemu/roms/openbios/drivers/pci.c new file mode 100644 index 000000000..366f4a17f --- /dev/null +++ b/qemu/roms/openbios/drivers/pci.c @@ -0,0 +1,1569 @@ +/* + * OpenBIOS pci driver + * + * This driver is compliant to the + * PCI bus binding to IEEE 1275-1994 Rev 2.1 + * + * (C) 2004 Stefan Reinauer <stepan@openbios.org> + * (C) 2005 Ed Schouten <ed@fxq.nl> + * + * Some parts from OpenHackWare-0.4, Copyright (c) 2004-2005 Jocelyn Mayer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#include "config.h" +#include "libopenbios/bindings.h" +#include "libopenbios/ofmem.h" +#include "kernel/kernel.h" +#include "drivers/pci.h" +#include "libc/byteorder.h" +#include "libc/vsprintf.h" + +#include "drivers/drivers.h" +#include "drivers/vga.h" +#include "packages/video.h" +#include "libopenbios/video.h" +#include "timer.h" +#include "pci.h" +#include "pci_database.h" +#ifdef CONFIG_DRIVER_MACIO +#include "cuda.h" +#include "macio.h" +#endif +#ifdef CONFIG_DRIVER_USB +#include "drivers/usb.h" +#endif + +#if defined (CONFIG_DEBUG_PCI) +# define PCI_DPRINTF(format, ...) printk(format, ## __VA_ARGS__) +#else +# define PCI_DPRINTF(format, ...) do { } while (0) +#endif + +#define set_bool_property(ph, name) set_property(ph, name, NULL, 0); + +/* DECLARE data structures for the nodes. */ + +DECLARE_UNNAMED_NODE( ob_pci_bus_node, INSTALL_OPEN, 2*sizeof(int) ); +DECLARE_UNNAMED_NODE( ob_pci_simple_node, INSTALL_OPEN, 2*sizeof(int) ); +DECLARE_UNNAMED_NODE( ob_pci_empty_node, 0, 2*sizeof(int) ); + +const pci_arch_t *arch; + +#define IS_NOT_RELOCATABLE 0x80000000 +#define IS_PREFETCHABLE 0x40000000 +#define IS_ALIASED 0x20000000 + +enum { + CONFIGURATION_SPACE = 0, + IO_SPACE = 1, + MEMORY_SPACE_32 = 2, + MEMORY_SPACE_64 = 3, +}; + +static int encode_int32_cells(int num_cells, u32 *prop, ucell val) +{ + int i = 0; + + /* hi ... lo */ + for (i=0; i < num_cells; ++i) { + prop[num_cells - i - 1] = val; + val >>= 16; + val >>= 16; + } + + return num_cells; +} + +static inline int pci_encode_phys_addr(u32 *phys, int flags, int space_code, + pci_addr dev, uint8_t reg, uint64_t addr) +{ + + /* phys.hi */ + + phys[0] = flags | (space_code << 24) | dev | reg; + + /* phys.mid */ + + phys[1] = addr >> 32; + + /* phys.lo */ + + phys[2] = addr; + + return 3; +} + +static inline int pci_encode_size(u32 *prop, uint64_t size) +{ + return encode_int32_cells(2, prop, size); +} + +static int host_address_cells(void) +{ + return get_int_property(find_dev("/"), "#address-cells", NULL); +} + +static int host_encode_phys_addr(u32 *prop, ucell addr) +{ + return encode_int32_cells(host_address_cells(), prop, addr); +} + +static int host_size_cells(void) +{ + return get_int_property(find_dev("/"), "#size-cells", NULL); +} + +/* +static int parent_address_cells(void) +{ + phandle_t parent_ph = ih_to_phandle(my_parent()); + return get_int_property(parent_ph, "#address-cells", NULL); +} + +static int parent_size_cells(void) +{ + phandle_t parent_ph = ih_to_phandle(my_parent()); + return get_int_property(parent_ph, "#size-cells", NULL); +} +*/ + +#if defined(CONFIG_DEBUG_PCI) +static void dump_reg_property(const char* description, int nreg, u32 *reg) +{ + int i; + printk("%s reg", description); + for (i=0; i < nreg; ++i) { + printk(" %08X", reg[i]); + } + printk("\n"); +} +#endif + +static unsigned long pci_bus_addr_to_host_addr(uint32_t ba) +{ + return arch->host_pci_base + (unsigned long)ba; +} + +static void +ob_pci_open(int *idx) +{ + int ret=1; + RET ( -ret ); +} + +static void +ob_pci_close(int *idx) +{ +} + +static void +ob_pci_initialize(int *idx) +{ +} + +/* ( str len -- phys.lo phys.mid phys.hi ) */ + +static void +ob_pci_decode_unit(int *idx) +{ + ucell hi, mid, lo; + const char *arg = pop_fstr_copy(); + int dev, fn, reg, ss, n, p, t; + int bus = 0; /* no information */ + char *ptr; + + PCI_DPRINTF("ob_pci_decode_unit idx=%p\n", idx); + + fn = 0; + reg = 0; + n = 0; + p = 0; + t = 0; + + ptr = (char*)arg; + if (*ptr == 'n') { + n = IS_NOT_RELOCATABLE; + ptr++; + } + if (*ptr == 'i') { + ss = IO_SPACE; + ptr++; + if (*ptr == 't') { + t = IS_ALIASED; + ptr++; + } + + /* DD,F,RR,NNNNNNNN */ + + dev = strtol(ptr, &ptr, 16); + ptr++; + fn = strtol(ptr, &ptr, 16); + ptr++; + reg = strtol(ptr, &ptr, 16); + ptr++; + lo = strtol(ptr, &ptr, 16); + mid = 0; + + } else if (*ptr == 'm') { + ss = MEMORY_SPACE_32; + ptr++; + if (*ptr == 't') { + t = IS_ALIASED; + ptr++; + } + if (*ptr == 'p') { + p = IS_PREFETCHABLE; + ptr++; + } + + /* DD,F,RR,NNNNNNNN */ + + dev = strtol(ptr, &ptr, 16); + ptr++; + fn = strtol(ptr, &ptr, 16); + ptr++; + reg = strtol(ptr, &ptr, 16); + ptr++; + lo = strtol(ptr, &ptr, 16); + mid = 0; + + } else if (*ptr == 'x') { + unsigned long long addr64; + ss = MEMORY_SPACE_64; + ptr++; + if (*ptr == 'p') { + p = IS_PREFETCHABLE; + ptr++; + } + + /* DD,F,RR,NNNNNNNNNNNNNNNN */ + + dev = strtol(ptr, &ptr, 16); + ptr++; + fn = strtol(ptr, &ptr, 16); + ptr++; + reg = strtol(ptr, &ptr, 16); + ptr++; + addr64 = strtoll(ptr, &ptr, 16); + lo = (ucell)addr64; + mid = addr64 >> 32; + + } else { + ss = CONFIGURATION_SPACE; + /* "DD" or "DD,FF" */ + dev = strtol(ptr, &ptr, 16); + if (*ptr == ',') { + ptr++; + fn = strtol(ptr, NULL, 16); + } + lo = 0; + mid = 0; + } + free((char*)arg); + + hi = n | p | t | (ss << 24) | (bus << 16) | (dev << 11) | (fn << 8) | reg; + + PUSH(lo); + PUSH(mid); + PUSH(hi); + + PCI_DPRINTF("ob_pci_decode_unit idx=%p addr=" + FMT_ucellx " " FMT_ucellx " " FMT_ucellx "\n", + idx, lo, mid, hi); +} + +/* ( phys.lo phy.mid phys.hi -- str len ) */ + +static void +ob_pci_encode_unit(int *idx) +{ + char buf[28]; + cell hi = POP(); + cell mid = POP(); + cell lo = POP(); + int n, p, t, ss, dev, fn, reg; + + n = hi & IS_NOT_RELOCATABLE; + p = hi & IS_PREFETCHABLE; + t = hi & IS_ALIASED; + ss = (hi >> 24) & 0x03; + + dev = (hi >> 11) & 0x1F; + fn = (hi >> 8) & 0x07; + reg = hi & 0xFF; + + switch(ss) { + case CONFIGURATION_SPACE: + + if (fn == 0) /* DD */ + snprintf(buf, sizeof(buf), "%x", dev); + else /* DD,F */ + snprintf(buf, sizeof(buf), "%x,%x", dev, fn); + break; + + case IO_SPACE: + + /* [n]i[t]DD,F,RR,NNNNNNNN */ + snprintf(buf, sizeof(buf), "%si%s%x,%x,%x," FMT_ucellx, + n ? "n" : "", /* relocatable */ + t ? "t" : "", /* aliased */ + dev, fn, reg, t ? lo & 0x03FF : lo); + break; + + case MEMORY_SPACE_32: + + /* [n]m[t][p]DD,F,RR,NNNNNNNN */ + snprintf(buf, sizeof(buf), "%sm%s%s%x,%x,%x," FMT_ucellx, + n ? "n" : "", /* relocatable */ + t ? "t" : "", /* aliased */ + p ? "p" : "", /* prefetchable */ + dev, fn, reg, lo ); + break; + + case MEMORY_SPACE_64: + + /* [n]x[p]DD,F,RR,NNNNNNNNNNNNNNNN */ + snprintf(buf, sizeof(buf), "%sx%s%x,%x,%x,%llx", + n ? "n" : "", /* relocatable */ + p ? "p" : "", /* prefetchable */ + dev, fn, reg, ((long long)mid << 32) | (long long)lo); + break; + } + push_str(buf); + + PCI_DPRINTF("ob_pci_encode_unit space=%d dev=%d fn=%d buf=%s\n", + ss, dev, fn, buf); +} + +/* ( pci-addr.lo pci-addr.hi size -- virt ) */ + +static void +ob_pci_map_in(int *idx) +{ + phys_addr_t phys; + uint32_t ba; + ucell size, virt; + + PCI_DPRINTF("ob_pci_bar_map_in idx=%p\n", idx); + + size = POP(); + POP(); + ba = POP(); + + phys = pci_bus_addr_to_host_addr(ba); + +#if defined(CONFIG_OFMEM) + ofmem_claim_phys(phys, size, 0); + +#if defined(CONFIG_PPC) + /* For some reason PPC gets upset when virt != phys for map-in... */ + virt = ofmem_claim_virt(phys, size, 0); +#else + virt = ofmem_claim_virt(-1, size, size); +#endif + + ofmem_map(phys, virt, size, ofmem_arch_io_translation_mode(phys)); + +#else + virt = size; /* Keep compiler quiet */ + virt = phys; +#endif + + PUSH(virt); +} + +NODE_METHODS(ob_pci_bus_node) = { + { NULL, ob_pci_initialize }, + { "open", ob_pci_open }, + { "close", ob_pci_close }, + { "decode-unit", ob_pci_decode_unit }, + { "encode-unit", ob_pci_encode_unit }, + { "pci-map-in", ob_pci_map_in }, +}; + +NODE_METHODS(ob_pci_simple_node) = { + { NULL, ob_pci_initialize }, + { "open", ob_pci_open }, + { "close", ob_pci_close }, +}; + +NODE_METHODS(ob_pci_empty_node) = { + { NULL, ob_pci_initialize } +}; + +static void pci_set_bus_range(const pci_config_t *config) +{ + phandle_t dev = find_dev(config->path); + u32 props[2]; + + props[0] = config->secondary_bus; + props[1] = config->subordinate_bus; + + PCI_DPRINTF("setting bus range for %s PCI device, " + "package handle " FMT_ucellx " " + "bus primary=%d secondary=%d subordinate=%d\n", + config->path, + dev, + config->primary_bus, + config->secondary_bus, + config->subordinate_bus); + + + set_property(dev, "bus-range", (char *)props, 2 * sizeof(props[0])); +} + +static void pci_host_set_reg(phandle_t phandle) +{ + phandle_t dev = phandle; + + /* at most 2 integers for address and size */ + u32 props[4]; + int ncells = 0; + + ncells += encode_int32_cells(host_address_cells(), props + ncells, + arch->cfg_base); + + ncells += encode_int32_cells(host_size_cells(), props + ncells, + arch->cfg_len); + + set_property(dev, "reg", (char *)props, ncells * sizeof(props[0])); + +#if defined(CONFIG_DEBUG_PCI) + dump_reg_property("pci_host_set_reg", 4, props); +#endif +} + +/* child-phys : parent-phys : size */ +/* 3 cells for PCI : 2 cells for 64bit parent : 2 cells for PCI */ + +static void pci_host_set_ranges(const pci_config_t *config) +{ + phandle_t dev = get_cur_dev(); + u32 props[32]; + int ncells; + + ncells = 0; + /* first encode PCI configuration space */ + { + ncells += pci_encode_phys_addr(props + ncells, 0, CONFIGURATION_SPACE, + config->dev, 0, 0); + ncells += host_encode_phys_addr(props + ncells, arch->cfg_addr); + ncells += pci_encode_size(props + ncells, arch->cfg_len); + } + + if (arch->io_base) { + ncells += pci_encode_phys_addr(props + ncells, 0, IO_SPACE, + config->dev, 0, 0); + ncells += host_encode_phys_addr(props + ncells, arch->io_base); + ncells += pci_encode_size(props + ncells, arch->io_len); + } + if (arch->rbase) { + ncells += pci_encode_phys_addr(props + ncells, 0, MEMORY_SPACE_32, + config->dev, 0, 0); + ncells += host_encode_phys_addr(props + ncells, arch->rbase); + ncells += pci_encode_size(props + ncells, arch->rlen); + } + if (arch->pci_mem_base) { + ncells += pci_encode_phys_addr(props + ncells, 0, MEMORY_SPACE_32, + config->dev, 0, arch->pci_mem_base); + ncells += host_encode_phys_addr(props + ncells, arch->host_pci_base + + arch->pci_mem_base); + ncells += pci_encode_size(props + ncells, arch->mem_len); + } + set_property(dev, "ranges", (char *)props, ncells * sizeof(props[0])); +} + +int host_config_cb(const pci_config_t *config) +{ + //XXX this overrides "reg" property + pci_host_set_reg(get_cur_dev()); + pci_host_set_ranges(config); + + return 0; +} + +static int sabre_configure(phandle_t dev) +{ + uint32_t props[28]; + + props[0] = 0xc0000000; + props[1] = 0x20000000; + set_property(dev, "virtual-dma", (char *)props, 2 * sizeof(props[0])); + props[0] = 1; + set_property(dev, "#virtual-dma-size-cells", (char *)props, + sizeof(props[0])); + set_property(dev, "#virtual-dma-addr-cells", (char *)props, + sizeof(props[0])); + + set_property(dev, "no-streaming-cache", (char *)props, 0); + + props[0] = 0x000007f0; + props[1] = 0x000007ee; + props[2] = 0x000007ef; + props[3] = 0x000007e5; + set_property(dev, "interrupts", (char *)props, 4 * sizeof(props[0])); + props[0] = 0x0000001f; + set_property(dev, "upa-portid", (char *)props, 1 * sizeof(props[0])); + return 0; +} + +int sabre_config_cb(const pci_config_t *config) +{ + host_config_cb(config); + + return sabre_configure(get_cur_dev()); +} + +int bridge_config_cb(const pci_config_t *config) +{ + phandle_t aliases; + + aliases = find_dev("/aliases"); + set_property(aliases, "bridge", config->path, strlen(config->path) + 1); + + return 0; +} + +int ide_config_cb2 (const pci_config_t *config) +{ + ob_ide_init(config->path, + config->assigned[0] & ~0x0000000F, + (config->assigned[1] & ~0x0000000F) + 2, + config->assigned[2] & ~0x0000000F, + (config->assigned[3] & ~0x0000000F) + 2); + return 0; +} + +int eth_config_cb (const pci_config_t *config) +{ + phandle_t ph = get_cur_dev(); + + set_property(ph, "network-type", "ethernet", 9); + set_property(ph, "removable", "network", 8); + set_property(ph, "category", "net", 4); + + return 0; +} + +static inline void pci_decode_pci_addr(pci_addr addr, int *flags, + int *space_code, uint32_t *mask) +{ + *flags = 0; + + if (addr & 0x01) { + *space_code = IO_SPACE; + *mask = 0x00000001; + } else { + if (addr & 0x04) { + *space_code = MEMORY_SPACE_64; + *flags |= IS_NOT_RELOCATABLE; /* XXX: why not relocatable? */ + } else { + *space_code = MEMORY_SPACE_32; + } + + if (addr & 0x08) { + *flags |= IS_PREFETCHABLE; + } + + *mask = 0x0000000F; + } +} + +/* + * "Designing PCI Cards and Drivers for Power Macintosh Computers", p. 454 + * + * "AAPL,address" provides an array of 32-bit logical addresses + * Nth entry corresponding to Nth "assigned-address" base address entry. + */ + +static void pci_set_AAPL_address(const pci_config_t *config) +{ + phandle_t dev = get_cur_dev(); + cell props[7]; + int ncells, i; + + ncells = 0; + for (i = 0; i < 6; i++) { + if (!config->assigned[i] || !config->sizes[i]) + continue; + props[ncells++] = config->assigned[i] & ~0x0000000F; + } + if (ncells) + set_property(dev, "AAPL,address", (char *)props, + ncells * sizeof(cell)); +} + +static void pci_set_assigned_addresses(phandle_t phandle, + const pci_config_t *config, int num_bars) +{ + phandle_t dev = phandle; + u32 props[32]; + int ncells; + int i; + uint32_t mask; + int flags, space_code; + + ncells = 0; + for (i = 0; i < num_bars; i++) { + /* consider only bars with non-zero region size */ + if (!config->sizes[i]) + continue; + pci_decode_pci_addr(config->assigned[i], + &flags, &space_code, &mask); + + ncells += pci_encode_phys_addr(props + ncells, + flags, space_code, config->dev, + PCI_BASE_ADDR_0 + (i * sizeof(uint32_t)), + config->assigned[i] & ~mask); + + props[ncells++] = 0x00000000; + props[ncells++] = config->sizes[i]; + } + if (ncells) + set_property(dev, "assigned-addresses", (char *)props, + ncells * sizeof(props[0])); +} + +/* call after writing "reg" property to update config->path */ +static void ob_pci_reload_device_path(phandle_t phandle, pci_config_t *config) +{ + /* since "name" and "reg" are now assigned + we need to reload current node name */ + + PUSH(phandle); + fword("get-package-path"); + char *new_path = pop_fstr_copy(); + if (new_path) { + if (0 != strcmp(config->path, new_path)) { + PCI_DPRINTF("\n=== CHANGED === package path old=%s new=%s\n", + config->path, new_path); + strncpy(config->path, new_path, sizeof(config->path)); + config->path[sizeof(config->path)-1] = '\0'; + } + free(new_path); + } else { + PCI_DPRINTF("\n=== package path old=%s new=NULL\n", config->path); + } +} + +static void pci_set_reg(phandle_t phandle, + pci_config_t *config, int num_bars) +{ + phandle_t dev = phandle; + u32 props[38]; + int ncells; + int i; + uint32_t mask; + int space_code, flags; + + ncells = 0; + + /* first (addr, size) pair is the beginning of configuration address space */ + ncells += pci_encode_phys_addr(props + ncells, 0, CONFIGURATION_SPACE, + config->dev, 0, 0); + + ncells += pci_encode_size(props + ncells, 0); + + for (i = 0; i < num_bars; i++) { + /* consider only bars with non-zero region size */ + if (!config->sizes[i]) + continue; + + pci_decode_pci_addr(config->regions[i], + &flags, &space_code, &mask); + + ncells += pci_encode_phys_addr(props + ncells, + flags, space_code, config->dev, + PCI_BASE_ADDR_0 + (i * sizeof(uint32_t)), + config->regions[i] & ~mask); + + /* set size */ + ncells += pci_encode_size(props + ncells, config->sizes[i]); + } + + set_property(dev, "reg", (char *)props, ncells * sizeof(props[0])); + ob_pci_reload_device_path(dev, config); + +#if defined(CONFIG_DEBUG_PCI) + dump_reg_property("pci_set_reg", ncells, props); +#endif +} + + +static void pci_set_ranges(const pci_config_t *config) +{ + phandle_t dev = get_cur_dev(); + u32 props[32]; + int ncells; + int i; + uint32_t mask; + int flags; + int space_code; + + ncells = 0; + for (i = 0; i < 6; i++) { + if (!config->assigned[i] || !config->sizes[i]) + continue; + + /* child address */ + + props[ncells++] = 0x00000000; + + /* parent address */ + + pci_decode_pci_addr(config->assigned[i], + &flags, &space_code, &mask); + ncells += pci_encode_phys_addr(props + ncells, flags, space_code, + config->dev, 0x10 + i * 4, + config->assigned[i] & ~mask); + + /* size */ + + props[ncells++] = config->sizes[i]; + } + set_property(dev, "ranges", (char *)props, ncells * sizeof(props[0])); +} + +int macio_heathrow_config_cb (const pci_config_t *config) +{ + pci_set_ranges(config); + +#ifdef CONFIG_DRIVER_MACIO + ob_macio_heathrow_init(config->path, config->assigned[0] & ~0x0000000F); +#endif + return 0; +} + +int macio_keylargo_config_cb (const pci_config_t *config) +{ + pci_set_ranges(config); + +#ifdef CONFIG_DRIVER_MACIO + ob_macio_keylargo_init(config->path, config->assigned[0] & ~0x0000000F); +#endif + return 0; +} + +int vga_config_cb (const pci_config_t *config) +{ + unsigned long rom; + uint32_t rom_size, size; + phandle_t ph; + + if (config->assigned[0] != 0x00000000) { + setup_video(); + + rom = pci_bus_addr_to_host_addr(config->assigned[1] & ~0x0000000F); + rom_size = config->sizes[1]; + + ph = get_cur_dev(); + + if (rom_size >= 8) { + const char *p; + + p = (const char *)rom; + if (p[0] == 'N' && p[1] == 'D' && p[2] == 'R' && p[3] == 'V') { + size = *(uint32_t*)(p + 4); + set_property(ph, "driver,AAPL,MacOS,PowerPC", p + 8, size); + } + } + + /* Currently we don't read FCode from the hardware but execute it directly */ + feval("['] vga-driver-fcode 2 cells + 1 byte-load"); + +#ifdef CONFIG_MOL + /* Install special words for Mac On Linux */ + molvideo_init(); +#endif + + } + + return 0; +} + +int ebus_config_cb(const pci_config_t *config) +{ +#ifdef CONFIG_DRIVER_EBUS + phandle_t dev = get_cur_dev(); + uint32_t props[12]; + int ncells; + int i; + uint32_t mask; + int flags, space_code; + + props[0] = 0x14; + props[1] = 0x3f8; + props[2] = 1; + props[3] = find_dev("/"); + props[4] = 0x2b; + set_property(dev, "interrupt-map", (char *)props, 5 * sizeof(props[0])); + + props[0] = 0x000001ff; + props[1] = 0xffffffff; + props[2] = 3; + set_property(dev, "interrupt-map-mask", (char *)props, 3 * sizeof(props[0])); + + /* Build ranges property from the BARs */ + ncells = 0; + for (i = 0; i < 6; i++) { + /* consider only bars with non-zero region size */ + if (!config->sizes[i]) + continue; + + pci_decode_pci_addr(config->assigned[i], + &flags, &space_code, &mask); + + props[ncells++] = PCI_BASE_ADDR_0 + (i * sizeof(uint32_t)); + props[ncells++] = 0x0; + + ncells += pci_encode_phys_addr(props + ncells, + flags, space_code, config->dev, + PCI_BASE_ADDR_0 + (i * sizeof(uint32_t)), + 0); + + props[ncells++] = config->sizes[i]; + } + + set_property(dev, "ranges", (char *)props, ncells * sizeof(props[0])); + + /* Build eeprom node */ + fword("new-device"); + PUSH(0x14); + fword("encode-int"); + PUSH(0x2000); + fword("encode-int"); + fword("encode+"); + PUSH(0x2000); + fword("encode-int"); + fword("encode+"); + push_str("reg"); + fword("property"); + + push_str("mk48t59"); + fword("model"); + + push_str("eeprom"); + fword("device-name"); + fword("finish-device"); + +#ifdef CONFIG_DRIVER_FLOPPY + ob_floppy_init(config->path, "fdthree", 0x3f0ULL, 0); +#endif +#ifdef CONFIG_DRIVER_PC_SERIAL + ob_pc_serial_init(config->path, "su", (PCI_BASE_ADDR_1 | 0ULL) << 32, 0x3f8ULL, 0); +#endif +#ifdef CONFIG_DRIVER_PC_KBD + ob_pc_kbd_init(config->path, "kb_ps2", (PCI_BASE_ADDR_1 | 0ULL) << 32, 0x60ULL, 0); +#endif +#endif + return 0; +} + +int i82378_config_cb(const pci_config_t *config) +{ +#ifdef CONFIG_DRIVER_PC_SERIAL + ob_pc_serial_init(config->path, "serial", arch->io_base, 0x3f8ULL, 0); +#endif +#ifdef CONFIG_DRIVER_PC_KBD + ob_pc_kbd_init(config->path, "8042", arch->io_base, 0x60ULL, 0); +#endif +#ifdef CONFIG_DRIVER_IDE + ob_ide_init(config->path, 0x1f0, 0x3f6, 0x170, 0x376); +#endif + + return 0; +} + +int usb_ohci_config_cb(const pci_config_t *config) +{ +#ifdef CONFIG_DRIVER_USB + ob_usb_ohci_init(config->path, 0x80000000 | config->dev); +#endif + return 0; +} + +static void ob_pci_add_properties(phandle_t phandle, + pci_addr addr, const pci_dev_t *pci_dev, + const pci_config_t *config, int num_bars) +{ + /* cannot use get_cur_dev() path resolution since "name" and "reg" + properties are being changed */ + phandle_t dev=phandle; + int status,id; + uint16_t vendor_id, device_id; + uint8_t rev; + uint8_t class_prog; + uint32_t class_code; + + vendor_id = pci_config_read16(addr, PCI_VENDOR_ID); + device_id = pci_config_read16(addr, PCI_DEVICE_ID); + rev = pci_config_read8(addr, PCI_REVISION_ID); + class_prog = pci_config_read8(addr, PCI_CLASS_PROG); + class_code = pci_config_read16(addr, PCI_CLASS_DEVICE); + + if (pci_dev) { + /**/ + if (pci_dev->name) { + push_str(pci_dev->name); + fword("encode-string"); + push_str("name"); + fword("property"); + } else { + char path[256]; + snprintf(path, sizeof(path), + "pci%x,%x", vendor_id, device_id); + push_str(path); + fword("encode-string"); + push_str("name"); + fword("property"); + } + } else { + PCI_DPRINTF("*** missing pci_dev\n"); + } + + /* create properties as described in 2.5 */ + + set_int_property(dev, "vendor-id", vendor_id); + set_int_property(dev, "device-id", device_id); + set_int_property(dev, "revision-id", rev); + set_int_property(dev, "class-code", class_code << 8 | class_prog); + + if (config->irq_pin) { + OLDWORLD(set_int_property(dev, "AAPL,interrupts", + config->irq_line)); +#if defined(CONFIG_SPARC64) + set_int_property(dev, "interrupts", config->irq_pin); +#else + NEWWORLD(set_int_property(dev, "interrupts", config->irq_pin)); +#endif + } + + set_int_property(dev, "min-grant", pci_config_read8(addr, PCI_MIN_GNT)); + set_int_property(dev, "max-latency", pci_config_read8(addr, PCI_MAX_LAT)); + + status=pci_config_read16(addr, PCI_STATUS); + + set_int_property(dev, "devsel-speed", + (status&PCI_STATUS_DEVSEL_MASK)>>10); + + if(status&PCI_STATUS_FAST_BACK) + set_bool_property(dev, "fast-back-to-back"); + if(status&PCI_STATUS_66MHZ) + set_bool_property(dev, "66mhz-capable"); + if(status&PCI_STATUS_UDF) + set_bool_property(dev, "udf-supported"); + + id=pci_config_read16(addr, PCI_SUBSYSTEM_VENDOR_ID); + if(id) + set_int_property(dev, "subsystem-vendor-id", id); + id=pci_config_read16(addr, PCI_SUBSYSTEM_ID); + if(id) + set_int_property(dev, "subsystem-id", id); + + set_int_property(dev, "cache-line-size", + pci_config_read16(addr, PCI_CACHE_LINE_SIZE)); + + if (pci_dev) { + if (pci_dev->type) { + push_str(pci_dev->type); + fword("encode-string"); + push_str("device_type"); + fword("property"); + } + if (pci_dev->model) { + push_str(pci_dev->model); + fword("encode-string"); + push_str("model"); + fword("property"); + } + if (pci_dev->compat) + set_property(dev, "compatible", + pci_dev->compat, pci_compat_len(pci_dev)); + + if (pci_dev->acells) + set_int_property(dev, "#address-cells", + pci_dev->acells); + if (pci_dev->scells) + set_int_property(dev, "#size-cells", + pci_dev->scells); + if (pci_dev->icells) + set_int_property(dev, "#interrupt-cells", + pci_dev->icells); + } + + pci_set_assigned_addresses(phandle, config, num_bars); + OLDWORLD(pci_set_AAPL_address(config)); + + PCI_DPRINTF("\n"); +} + +#ifdef CONFIG_XBOX +static char pci_xbox_blacklisted (int bus, int devnum, int fn) +{ + /* + * The Xbox MCPX chipset is a derivative of the nForce 1 + * chipset. It almost has the same bus layout; some devices + * cannot be used, because they have been removed. + */ + + /* + * Devices 00:00.1 and 00:00.2 used to be memory controllers on + * the nForce chipset, but on the Xbox, using them will lockup + * the chipset. + */ + if ((bus == 0) && (devnum == 0) && ((fn == 1) || (fn == 2))) + return 1; + + /* + * Bus 1 only contains a VGA controller at 01:00.0. When you try + * to probe beyond that device, you only get garbage, which + * could cause lockups. + */ + if ((bus == 1) && ((devnum != 0) || (fn != 0))) + return 1; + + /* + * Bus 2 used to contain the AGP controller, but the Xbox MCPX + * doesn't have one. Probing it can cause lockups. + */ + if (bus >= 2) + return 1; + + /* + * The device is not blacklisted. + */ + return 0; +} +#endif + +static void ob_pci_configure_bar(pci_addr addr, pci_config_t *config, + int reg, int config_addr, + uint32_t *p_omask, + unsigned long *mem_base, + unsigned long *io_base) +{ + uint32_t smask, amask, size, reloc, min_align; + unsigned long base; + + config->assigned[reg] = 0x00000000; + config->sizes[reg] = 0x00000000; + + if ((*p_omask & 0x0000000f) == 0x4) { + /* 64 bits memory mapping */ + PCI_DPRINTF("Skipping 64 bit BARs for %s\n", config->path); + return; + } + + config->regions[reg] = pci_config_read32(addr, config_addr); + + /* get region size */ + + pci_config_write32(addr, config_addr, 0xffffffff); + smask = pci_config_read32(addr, config_addr); + if (smask == 0x00000000 || smask == 0xffffffff) + return; + + if (smask & 0x00000001 && reg != 6) { + /* I/O space */ + base = *io_base; + min_align = 1 << 7; + amask = 0x00000001; + } else { + /* Memory Space */ + base = *mem_base; + min_align = 1 << 16; + amask = 0x0000000F; + if (reg == 6) { + smask |= 1; /* ROM */ + } + } + *p_omask = smask & amask; + smask &= ~amask; + size = (~smask) + 1; + config->sizes[reg] = size; + reloc = base; + if (size < min_align) + size = min_align; + reloc = (reloc + size -1) & ~(size - 1); + if (*io_base == base) { + PCI_DPRINTF("changing io_base from 0x%lx to 0x%x\n", + *io_base, reloc + size); + *io_base = reloc + size; + } else { + PCI_DPRINTF("changing mem_base from 0x%lx to 0x%x\n", + *mem_base, reloc + size); + *mem_base = reloc + size; + } + PCI_DPRINTF("Configuring BARs for %s: reloc 0x%x omask 0x%x " + "io_base 0x%lx mem_base 0x%lx size 0x%x\n", + config->path, reloc, *p_omask, *io_base, *mem_base, size); + pci_config_write32(addr, config_addr, reloc | *p_omask); + config->assigned[reg] = reloc | *p_omask; +} + +static void ob_pci_configure_irq(pci_addr addr, pci_config_t *config) +{ + uint8_t irq_pin, irq_line; + + irq_pin = pci_config_read8(addr, PCI_INTERRUPT_PIN); + if (irq_pin) { + config->irq_pin = irq_pin; + irq_pin = (((config->dev >> 11) & 0x1F) + irq_pin - 1) & 3; + irq_line = arch->irqs[irq_pin]; + pci_config_write8(addr, PCI_INTERRUPT_LINE, irq_line); + config->irq_line = irq_line; + } else + config->irq_line = -1; +} + +static void +ob_pci_configure(pci_addr addr, pci_config_t *config, int num_regs, int rom_bar, + unsigned long *mem_base, unsigned long *io_base) + +{ + uint32_t omask; + uint16_t cmd; + int reg; + pci_addr config_addr; + + ob_pci_configure_irq(addr, config); + + omask = 0x00000000; + for (reg = 0; reg < num_regs; ++reg) { + config_addr = PCI_BASE_ADDR_0 + reg * 4; + + ob_pci_configure_bar(addr, config, reg, config_addr, + &omask, mem_base, + io_base); + } + + if (rom_bar) { + config_addr = rom_bar; + ob_pci_configure_bar(addr, config, reg, config_addr, + &omask, mem_base, io_base); + } + cmd = pci_config_read16(addr, PCI_COMMAND); + cmd |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY; + pci_config_write16(addr, PCI_COMMAND, cmd); +} + +static void ob_configure_pci_device(const char* parent_path, + int *bus_num, unsigned long *mem_base, unsigned long *io_base, + int bus, int devnum, int fn, int *p_is_multi); + +static void ob_scan_pci_bus(int *bus_num, unsigned long *mem_base, + unsigned long *io_base, const char *path, + int bus) +{ + int devnum, fn, is_multi; + + PCI_DPRINTF("\nScanning bus %d at %s...\n", bus, path); + + for (devnum = 0; devnum < 32; devnum++) { + is_multi = 0; + for (fn = 0; fn==0 || (is_multi && fn<8); fn++) { + ob_configure_pci_device(path, bus_num, mem_base, io_base, + bus, devnum, fn, &is_multi); + + } + } +} + +static void ob_configure_pci_bridge(pci_addr addr, + int *bus_num, unsigned long *mem_base, + unsigned long *io_base, + int primary_bus, pci_config_t *config) +{ + config->primary_bus = primary_bus; + pci_config_write8(addr, PCI_PRIMARY_BUS, config->primary_bus); + + config->secondary_bus = *bus_num; + pci_config_write8(addr, PCI_SECONDARY_BUS, config->secondary_bus); + + config->subordinate_bus = 0xff; + pci_config_write8(addr, PCI_SUBORDINATE_BUS, config->subordinate_bus); + + PCI_DPRINTF("scanning new pci bus %u under bridge %s\n", + config->secondary_bus, config->path); + + /* make pci bridge parent device, prepare for recursion */ + + ob_scan_pci_bus(bus_num, mem_base, io_base, + config->path, config->secondary_bus); + + /* bus scan updates *bus_num to last revealed pci bus number */ + config->subordinate_bus = *bus_num; + pci_config_write8(addr, PCI_SUBORDINATE_BUS, config->subordinate_bus); + + PCI_DPRINTF("bridge %s PCI bus primary=%d secondary=%d subordinate=%d\n", + config->path, config->primary_bus, config->secondary_bus, + config->subordinate_bus); + + pci_set_bus_range(config); +} + +static int ob_pci_read_identification(int bus, int devnum, int fn, + int *p_vid, int *p_did, + uint8_t *p_class, uint8_t *p_subclass) +{ + int vid, did; + uint32_t ccode; + pci_addr addr; + +#ifdef CONFIG_XBOX + if (pci_xbox_blacklisted (bus, devnum, fn)) + return; +#endif + addr = PCI_ADDR(bus, devnum, fn); + vid = pci_config_read16(addr, PCI_VENDOR_ID); + did = pci_config_read16(addr, PCI_DEVICE_ID); + + if (vid==0xffff || vid==0) { + return 0; + } + + if (p_vid) { + *p_vid = vid; + } + + if (p_did) { + *p_did = did; + } + + ccode = pci_config_read16(addr, PCI_CLASS_DEVICE); + + if (p_class) { + *p_class = ccode >> 8; + } + + if (p_subclass) { + *p_subclass = ccode; + } + + return 1; +} + +static void ob_configure_pci_device(const char* parent_path, + int *bus_num, unsigned long *mem_base, unsigned long *io_base, + int bus, int devnum, int fn, int *p_is_multi) +{ + int vid, did; + unsigned int htype; + pci_addr addr; + pci_config_t config = {}; + const pci_dev_t *pci_dev; + uint8_t class, subclass, iface; + int num_bars, rom_bar; + + phandle_t phandle = 0; + int is_host_bridge = 0; + + if (!ob_pci_read_identification(bus, devnum, fn, &vid, &did, &class, &subclass)) { + return; + } + + addr = PCI_ADDR(bus, devnum, fn); + iface = pci_config_read8(addr, PCI_CLASS_PROG); + + pci_dev = pci_find_device(class, subclass, iface, + vid, did); + + PCI_DPRINTF("%x:%x.%x - %x:%x - ", bus, devnum, fn, + vid, did); + + htype = pci_config_read8(addr, PCI_HEADER_TYPE); + + if (fn == 0) { + if (p_is_multi) { + *p_is_multi = htype & 0x80; + } + } + + /* stop adding host bridge accessible from it's primary bus + PCI host bridge is to be added by host code + */ + if (class == PCI_BASE_CLASS_BRIDGE && + subclass == PCI_SUBCLASS_BRIDGE_HOST) { + is_host_bridge = 1; + } + + if (is_host_bridge) { + /* reuse device tree node */ + PCI_DPRINTF("host bridge found - "); + snprintf(config.path, sizeof(config.path), + "%s", parent_path); + } else if (pci_dev == NULL || pci_dev->name == NULL) { + snprintf(config.path, sizeof(config.path), + "%s/pci%x,%x", parent_path, vid, did); + } + else { + snprintf(config.path, sizeof(config.path), + "%s/%s", parent_path, pci_dev->name); + } + + PCI_DPRINTF("%s - ", config.path); + + config.dev = addr & 0x00FFFFFF; + + switch (class) { + case PCI_BASE_CLASS_BRIDGE: + if (subclass != PCI_SUBCLASS_BRIDGE_HOST) { + REGISTER_NAMED_NODE_PHANDLE(ob_pci_bus_node, config.path, phandle); + } + break; + case PCI_CLASS_DISPLAY: + REGISTER_NAMED_NODE_PHANDLE(ob_pci_empty_node, config.path, phandle); + break; + default: + REGISTER_NAMED_NODE_PHANDLE(ob_pci_simple_node, config.path, phandle); + break; + } + + if (is_host_bridge) { + phandle = find_dev(config.path); + + if (get_property(phandle, "vendor-id", NULL)) { + PCI_DPRINTF("host bridge already configured\n"); + return; + } + } + + activate_dev(phandle); + + if (htype & PCI_HEADER_TYPE_BRIDGE) { + num_bars = 2; + rom_bar = PCI_ROM_ADDRESS1; + } else { + num_bars = 6; + rom_bar = PCI_ROM_ADDRESS; + } + + ob_pci_configure(addr, &config, num_bars, rom_bar, + mem_base, io_base); + + ob_pci_add_properties(phandle, addr, pci_dev, &config, num_bars); + + if (!is_host_bridge) { + pci_set_reg(phandle, &config, num_bars); + } + + /* call device-specific configuration callback */ + if (pci_dev && pci_dev->config_cb) { + //activate_device(config.path); + pci_dev->config_cb(&config); + } + + /* device is configured so we may move it out of scope */ + device_end(); + + /* scan bus behind bridge device */ + //if (htype & PCI_HEADER_TYPE_BRIDGE && class == PCI_BASE_CLASS_BRIDGE) { + if ( class == PCI_BASE_CLASS_BRIDGE && + ( subclass == PCI_SUBCLASS_BRIDGE_PCI || + subclass == PCI_SUBCLASS_BRIDGE_HOST ) ) { + + if (subclass == PCI_SUBCLASS_BRIDGE_PCI) { + /* reserve next pci bus number for this PCI bridge */ + ++(*bus_num); + } + + ob_configure_pci_bridge(addr, bus_num, mem_base, io_base, bus, &config); + } +} + +static void ob_pci_set_available(phandle_t host, unsigned long mem_base, unsigned long io_base) +{ + /* Create an available property for both memory and IO space */ + uint32_t props[10]; + int ncells; + + ncells = 0; + ncells += pci_encode_phys_addr(props + ncells, 0, MEMORY_SPACE_32, 0, 0, mem_base); + ncells += pci_encode_size(props + ncells, arch->mem_len - mem_base); + ncells += pci_encode_phys_addr(props + ncells, 0, IO_SPACE, 0, 0, io_base); + ncells += pci_encode_size(props + ncells, arch->io_len - io_base); + + set_property(host, "available", (char *)props, ncells * sizeof(props[0])); +} + +/* Convert device/irq pin to interrupt property */ +#define SUN4U_INTERRUPT(dev, irq_pin) \ + ((((dev >> 11) << 2) + irq_pin - 1) & 0x1f) + +static void ob_pci_host_set_interrupt_map(phandle_t host) +{ + phandle_t dnode = 0; + u32 props[128]; + int i; + +#if defined(CONFIG_PPC) + phandle_t target_node; + + /* Oldworld macs do interrupt maps differently */ + if (!is_newworld()) + return; + + dnode = dt_iterate_type(0, "open-pic"); + if (dnode) { + /* patch in openpic interrupt-parent properties */ + target_node = find_dev("/pci/mac-io"); + set_int_property(target_node, "interrupt-parent", dnode); + + target_node = find_dev("/pci/mac-io/escc/ch-a"); + set_int_property(target_node, "interrupt-parent", dnode); + + target_node = find_dev("/pci/mac-io/escc/ch-b"); + set_int_property(target_node, "interrupt-parent", dnode); + + /* QEMU only emulates 2 of the 3 ata buses currently */ + /* On a new world Mac these are not numbered but named by the + * ATA version they support. Thus we have: ata-3, ata-3, ata-4 + * On g3beige they all called just ide. + * We take ata-3 and ata-4 which seems to work for both + * at least for clients we care about */ + target_node = find_dev("/pci/mac-io/ata-3"); + set_int_property(target_node, "interrupt-parent", dnode); + + target_node = find_dev("/pci/mac-io/ata-4"); + set_int_property(target_node, "interrupt-parent", dnode); + + target_node = find_dev("/pci/mac-io/via-cuda"); + set_int_property(target_node, "interrupt-parent", dnode); + + target_node = find_dev("/pci"); + set_int_property(target_node, "interrupt-parent", dnode); + + /* openpic interrupt mapping */ + for (i = 0; i < (7*8); i += 7) { + props[i + PCI_INT_MAP_PCI0] = 0; + props[i + PCI_INT_MAP_PCI1] = 0; + props[i + PCI_INT_MAP_PCI2] = 0; + props[i + PCI_INT_MAP_PCI_INT] = (i / 7) + 1; // starts at PINA=1 + props[i + PCI_INT_MAP_PIC_HANDLE] = dnode; + props[i + PCI_INT_MAP_PIC_INT] = arch->irqs[i / 7]; + props[i + PCI_INT_MAP_PIC_POL] = 3; + } + set_property(host, "interrupt-map", (char *)props, 7 * 8 * sizeof(props[0])); + + props[PCI_INT_MAP_PCI0] = 0; + props[PCI_INT_MAP_PCI1] = 0; + props[PCI_INT_MAP_PCI2] = 0; + props[PCI_INT_MAP_PCI_INT] = 0x7; + + set_property(host, "interrupt-map-mask", (char *)props, 4 * sizeof(props[0])); + } +#elif defined(CONFIG_SPARC64) + int ncells, len; + u32 *val, addr; + char *reg; + + /* Set interrupt-map for PCI devices with an interrupt pin present */ + ncells = 0; + + PUSH(host); + fword("child"); + dnode = POP(); + while (dnode) { + if (get_int_property(dnode, "interrupts", &len)) { + reg = get_property(dnode, "reg", &len); + if (reg) { + val = (u32 *)reg; + + for (i = 0; i < (len / sizeof(u32)); i += 5) { + addr = val[i]; + + /* Device address is in 1st 32-bit word of encoded PCI address for config space */ + if (!(addr & 0x03000000)) { + ncells += pci_encode_phys_addr(props + ncells, 0, 0, addr, 0, 0); + props[ncells++] = 1; /* always interrupt pin 1 for QEMU */ + props[ncells++] = host; + props[ncells++] = SUN4U_INTERRUPT(addr, 1); + } + } + } + } + + PUSH(dnode); + fword("peer"); + dnode = POP(); + } + set_property(host, "interrupt-map", (char *)props, ncells * sizeof(props[0])); + + props[0] = 0x0000f800; + props[1] = 0x0; + props[2] = 0x0; + props[3] = 7; + set_property(host, "interrupt-map-mask", (char *)props, 4 * sizeof(props[0])); +#endif +} + +int ob_pci_init(void) +{ + int bus, devnum, fn; + uint8_t class, subclass; + unsigned long mem_base, io_base; + + pci_config_t config = {}; /* host bridge */ + phandle_t phandle_host = 0; + + PCI_DPRINTF("Initializing PCI host bridge...\n"); + + activate_device("/"); + + /* Find all PCI bridges */ + + mem_base = arch->pci_mem_base; + /* I/O ports under 0x400 are used by devices mapped at fixed + location. */ + io_base = 0x400; + + bus = 0; + + for (devnum = 0; devnum < 32; devnum++) { + /* scan only fn 0 */ + fn = 0; + + if (!ob_pci_read_identification(bus, devnum, fn, + 0, 0, &class, &subclass)) { + continue; + } + + if (class != PCI_BASE_CLASS_BRIDGE || subclass != PCI_SUBCLASS_BRIDGE_HOST) { + continue; + } + + /* create root node for host PCI bridge */ + + /* configure */ + snprintf(config.path, sizeof(config.path), "/pci"); + + REGISTER_NAMED_NODE_PHANDLE(ob_pci_bus_node, config.path, phandle_host); + + pci_host_set_reg(phandle_host); + + /* update device path after changing "reg" property */ + ob_pci_reload_device_path(phandle_host, &config); + + ob_configure_pci_device(config.path, &bus, &mem_base, &io_base, + bus, devnum, fn, 0); + + /* we expect single host PCI bridge + but this may be machine-specific */ + break; + } + + /* create available attributes for the PCI bridge */ + ob_pci_set_available(phandle_host, mem_base, io_base); + + /* configure the host bridge interrupt map */ + ob_pci_host_set_interrupt_map(phandle_host); + + device_end(); + + return 0; +} diff --git a/qemu/roms/openbios/drivers/pci.fs b/qemu/roms/openbios/drivers/pci.fs new file mode 100644 index 000000000..563b652a4 --- /dev/null +++ b/qemu/roms/openbios/drivers/pci.fs @@ -0,0 +1,92 @@ +[IFDEF] CONFIG_DRIVER_PCI + +: pci-addr-encode ( addr.lo addr.mi addr.hi ) + rot >r swap >r + encode-int + r> encode-int encode+ + r> encode-int encode+ + ; + +: pci-len-encode ( len.lo len.hi ) + encode-int + rot encode-int encode+ + ; + +\ Get region offset for BAR reg +: pci-bar-offset@ ( bar-reg -- off.lo off.hi -1 | 0 ) + " reg" active-package get-package-property 0= if + begin + decode-phys \ ( reg prop prop-len phys.lo phys.mid phys.hi ) + ff and 5 pick = if + >r >r 3drop r> r> + -1 exit + else + 2drop + then + \ Drop the size as we don't need it + decode-int drop decode-int drop + dup 0= + until + 3drop + 0 exit + else + 0 + then + ; + +\ Get region size for BAR reg +: pci-bar-size@ ( bar-reg -- size ) + " reg" active-package get-package-property 0= if + begin + decode-phys \ ( reg prop prop-len phys.lo phys.mid phys.hi ) + ff and 5 pick = if + 2drop decode-int drop + decode-int + >r 3drop r> + exit + else + 2drop decode-int drop + decode-int drop + then + dup 0= + until + 3drop + 0 \ default size of 0 if BAR not found + then + ; + +\ Get base address for configured BAR reg +: pci-bar-base@ ( bar-reg -- addr.lo addr.hi -1 | 0 ) + " assigned-addresses" active-package get-package-property 0= if + begin + decode-phys \ ( reg prop prop-len phys.lo phys.mid phys.hi ) + ff and 5 pick = if + >r >r 3drop r> r> + -1 exit + else + 2drop + then + \ Drop the size as we don't need it + decode-int drop decode-int drop + dup 0= + until + 3drop + 0 exit + else + 0 + then + ; + +\ Get PCI bus address and size for configured BAR reg +: pci-bar>pci-region ( bar-reg -- addr.lo addr.hi size ) + dup + >r pci-bar-offset@ if + swap r@ pci-bar-base@ if + swap d+ + then + swap r@ pci-bar-size@ + then + r> drop + ; + +[THEN] diff --git a/qemu/roms/openbios/drivers/pci.h b/qemu/roms/openbios/drivers/pci.h new file mode 100644 index 000000000..84a2b2cf6 --- /dev/null +++ b/qemu/roms/openbios/drivers/pci.h @@ -0,0 +1,87 @@ +#ifndef PCI_H +#define PCI_H + +#define PCI_VENDOR_ID 0x00 +#define PCI_DEVICE_ID 0x02 + +#define PCI_COMMAND 0x04 +#define PCI_COMMAND_IO 0x01 +#define PCI_COMMAND_MEMORY 0x02 +#define PCI_COMMAND_BUS_MASTER 0x04 + +#define PCI_STATUS 0x06 /* 16 bits */ +#define PCI_STATUS_CAP_LIST 0x10 /* Support Capability List */ +#define PCI_STATUS_66MHZ 0x20 /* Support 66 Mhz PCI 2.1 bus */ +#define PCI_STATUS_UDF 0x40 /* Support User Definable Features + [obsolete] */ +#define PCI_STATUS_FAST_BACK 0x80 /* Accept fast-back to back */ +#define PCI_STATUS_PARITY 0x100 /* Detected parity error */ +#define PCI_STATUS_DEVSEL_MASK 0x600 /* DEVSEL timing */ +#define PCI_STATUS_DEVSEL_FAST 0x000 +#define PCI_STATUS_DEVSEL_MEDIUM 0x200 +#define PCI_STATUS_DEVSEL_SLOW 0x400 +#define PCI_STATUS_SIG_TARGET_ABORT 0x800 /* Set on target abort */ +#define PCI_STATUS_REC_TARGET_ABORT 0x1000 /* Master ack of " */ +#define PCI_STATUS_REC_MASTER_ABORT 0x2000 /* Set on master abort */ +#define PCI_STATUS_SIG_SYSTEM_ERROR 0x4000 /* Set when we drive SERR */ +#define PCI_STATUS_DETECTED_PARITY 0x8000 /* Set on parity error */ + + +#define PCI_REVISION_ID 0x08 /* Revision ID */ +#define PCI_CLASS_DISPLAY 0x03 +#define PCI_CLASS_PROG 0x09 +#define PCI_CLASS_DEVICE 0x0a +#define PCI_CACHE_LINE_SIZE 0x0c /* 8 bits */ +#define PCI_HEADER_TYPE 0x0e +#define PCI_HEADER_TYPE_NORMAL 0x00 +#define PCI_HEADER_TYPE_BRIDGE 0x01 +#define PCI_HEADER_TYPE_CARDBUS 0x02 +#define PCI_PRIMARY_BUS 0x18 +#define PCI_SECONDARY_BUS 0x19 +#define PCI_SUBORDINATE_BUS 0x1A +#define PCI_BASE_ADDR_0 0x10 +#define PCI_BASE_ADDR_1 0x14 +#define PCI_BASE_ADDR_2 0x18 +#define PCI_BASE_ADDR_3 0x1c +#define PCI_BASE_ADDR_4 0x20 +#define PCI_BASE_ADDR_5 0x24 + +#define PCI_SUBSYSTEM_VENDOR_ID 0x2c +#define PCI_SUBSYSTEM_ID 0x2e + +#define PCI_ROM_ADDRESS 0x30 /* Bits 31..11 are address, 10..1 reserved */ +#define PCI_ROM_ADDRESS_ENABLE 0x01 +#define PCI_ROM_ADDRESS_MASK (~0x7ffUL) +#define PCI_ROM_ADDRESS1 0x38 /* ROM_ADDRESS in bridge header */ + +#define PCI_INTERRUPT_LINE 0x3c /* 8 bits */ +#define PCI_INTERRUPT_PIN 0x3d /* 8 bits */ +#define PCI_MIN_GNT 0x3e /* 8 bits */ +#define PCI_MAX_LAT 0x3f /* 8 bits */ + +typedef struct { + u16 signature; + u8 reserved[0x16]; + u16 dptr; +} rom_header_t; + +typedef struct { + u32 signature; + u16 vendor; + u16 device; + u16 reserved_1; + u16 dlen; + u8 drevision; + u8 class_hi; + u16 class_lo; + u16 ilen; + u16 irevision; + u8 type; + u8 indicator; + u16 reserved_2; +} pci_data_t; + + +#include "asm/pci.h" + +#endif /* PCI_H */ diff --git a/qemu/roms/openbios/drivers/pci_database.c b/qemu/roms/openbios/drivers/pci_database.c new file mode 100644 index 000000000..0070a78ba --- /dev/null +++ b/qemu/roms/openbios/drivers/pci_database.c @@ -0,0 +1,1275 @@ +#include "config.h" +#include "libopenbios/bindings.h" +#include "drivers/pci.h" +#include "libc/vsprintf.h" + +#include "pci_database.h" + +/* PCI devices database */ + +typedef struct pci_class_t pci_class_t; +typedef struct pci_subclass_t pci_subclass_t; +typedef struct pci_iface_t pci_iface_t; + +struct pci_iface_t { + uint8_t iface; + const char *name; + const char *type; + const pci_dev_t *devices; + int (*config_cb)(const pci_config_t *config); + const void *private; +}; + +struct pci_subclass_t { + uint8_t subclass; + const char *name; + const char *type; + const pci_dev_t *devices; + const pci_iface_t *iface; + int (*config_cb)(const pci_config_t *config); + const void *private; +}; + +struct pci_class_t { + const char *name; + const char *type; + const pci_subclass_t *subc; +}; + +/* Current machine description */ + +static const pci_subclass_t undef_subclass[] = { + { + 0xFF, NULL, NULL, NULL, NULL, + NULL, NULL, + }, +}; + +static const pci_dev_t scsi_devices[] = { + { + /* Virtio-block controller */ + PCI_VENDOR_ID_REDHAT_QUMRANET, PCI_DEVICE_ID_VIRTIO_BLOCK, + NULL, "virtio-blk", NULL, + "pci1af4,1001\0pci1af4,1001\0pciclass,01018f\0", + 0, 0, 0, + NULL, NULL, + }, + { + 0xFFFF, 0xFFFF, + NULL, NULL, NULL, NULL, + -1, -1, -1, + NULL, NULL, + }, +}; + +static const pci_dev_t ide_devices[] = { + { + PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_646, /* CMD646 IDE controller */ + "pci-ide", "pci-ata", NULL, + "pci1095,646\0pci1095,646\0pciclass,01018f\0", + 0, 0, 0, + ide_config_cb2, NULL, + }, + { + 0xFFFF, 0xFFFF, + NULL, NULL, NULL, NULL, + -1, -1, -1, + NULL, NULL, + }, +}; + +static const pci_subclass_t mass_subclass[] = { + { + PCI_SUBCLASS_STORAGE_SCSI, "SCSI bus controller", + "scsi", scsi_devices, NULL, + NULL, NULL, + }, + { + PCI_SUBCLASS_STORAGE_IDE, "IDE controller", + "ide", ide_devices, NULL, + NULL, NULL, + }, + { + PCI_SUBCLASS_STORAGE_FLOPPY, "Floppy disk controller", + NULL, NULL, NULL, + NULL, NULL, + }, + { + PCI_SUBCLASS_STORAGE_IPI, "IPI bus controller", + NULL, NULL, NULL, + NULL, NULL, + }, + { + PCI_SUBCLASS_STORAGE_RAID, "RAID controller", + NULL, NULL, NULL, + NULL, NULL, + }, + { + PCI_SUBCLASS_STORAGE_ATA, "ATA controller", + "ata", NULL, NULL, + NULL, NULL, + }, + { + PCI_SUBCLASS_STORAGE_OTHER, "misc mass-storage controller", + NULL, NULL, NULL, + NULL, NULL, + }, + { + 0xFF, NULL, + NULL, NULL, NULL, + NULL, NULL, + }, +}; + +static const pci_dev_t eth_devices[] = { + { + PCI_VENDOR_ID_REALTEK, PCI_DEVICE_ID_REALTEK_RTL8029, + NULL, "NE2000", "NE2000 PCI", NULL, + 0, 0, 0, + NULL, "ethernet", + }, + { + /* Virtio-network controller */ + PCI_VENDOR_ID_REDHAT_QUMRANET, PCI_DEVICE_ID_VIRTIO_NET, + NULL, "virtio-net", NULL, + "pci1af4,1000\0pci1af4,1000\0pciclass,020000\0", + 0, 0, 0, + NULL, NULL, + }, + { + 0xFFFF, 0xFFFF, + NULL, NULL, NULL, NULL, + -1, -1, -1, + NULL, NULL, + }, +}; + +static const pci_subclass_t net_subclass[] = { + { + PCI_SUBCLASS_NETWORK_ETHERNET, "ethernet controller", + NULL, eth_devices, NULL, + eth_config_cb, "ethernet", + }, + { + PCI_SUBCLASS_NETWORK_TOKEN_RING, "token ring controller", + NULL, NULL, NULL, + NULL, NULL, + }, + { + PCI_SUBCLASS_NETWORK_FDDI, "FDDI controller", + NULL, NULL, NULL, + NULL, NULL, + }, + { + PCI_SUBCLASS_NETWORK_ATM, "ATM controller", + NULL, NULL, NULL, + NULL, NULL, + }, + { + PCI_SUBCLASS_NETWORK_ISDN, "ISDN controller", + NULL, NULL, NULL, + NULL, NULL, + }, + { + PCI_SUBCLASS_NETWORK_WORDFIP, "WordFip controller", + NULL, NULL, NULL, + NULL, NULL, + }, + { + PCI_SUBCLASS_NETWORK_PICMG214, "PICMG 2.14 controller", + NULL, NULL, NULL, + NULL, NULL, + }, + { + PCI_SUBCLASS_NETWORK_OTHER, "misc network controller", + NULL, NULL, NULL, + NULL, NULL, + }, + { + 0xFF, NULL, + NULL, NULL, NULL, + NULL, NULL, + }, +}; + +static const pci_dev_t vga_devices[] = { + { + PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RAGE128_PF, + NULL, "ATY", "ATY Rage128", "VGA\0", + 0, 0, 0, + NULL, NULL, + }, + { + PCI_VENDOR_ID_QEMU, PCI_DEVICE_ID_QEMU_VGA, + NULL, "QEMU,VGA", "Qemu VGA", "VGA\0", + 0, 0, 0, + NULL, NULL, + }, + { + 0xFFFF, 0xFFFF, + NULL, NULL, NULL, NULL, + -1, -1, -1, + NULL, NULL, + }, +}; + +static const struct pci_iface_t vga_iface[] = { + { + 0x00, "VGA controller", NULL, + vga_devices, &vga_config_cb, NULL, + }, + { + 0x01, "8514 compatible controller", NULL, + NULL, NULL, NULL, + }, + { + 0xFF, NULL, NULL, + NULL, NULL, NULL, + }, +}; + +static const pci_subclass_t displ_subclass[] = { + { + PCI_SUBCLASS_DISPLAY_VGA, "display controller", + NULL, NULL, vga_iface, + NULL, NULL, + }, + { + PCI_SUBCLASS_DISPLAY_XGA, "XGA display controller", + NULL, NULL, NULL, + NULL, NULL, + }, + { + PCI_SUBCLASS_DISPLAY_3D, "3D display controller", + NULL, NULL, NULL, + NULL, NULL, + }, + { + PCI_SUBCLASS_DISPLAY_OTHER, "misc display controller", + NULL, NULL, NULL, + NULL, NULL, + }, + { + 0xFF, NULL, + NULL, NULL, NULL, + NULL, NULL, + }, +}; + +static const pci_subclass_t media_subclass[] = { + { + PCI_SUBCLASS_MULTIMEDIA_VIDEO, "video device", + NULL, NULL, NULL, + NULL, NULL, + }, + { + PCI_SUBCLASS_MULTIMEDIA_AUDIO, "audio device", + NULL, NULL, NULL, + NULL, NULL, + }, + { + PCI_SUBCLASS_MULTIMEDIA_PHONE, "computer telephony device", + NULL, NULL, NULL, + NULL, NULL, + }, + { + PCI_SUBCLASS_MULTIMEDIA_OTHER, "misc multimedia device", + NULL, NULL, NULL, + NULL, NULL, + }, + { + 0xFF, NULL, + NULL, NULL, NULL, + NULL, NULL, + }, +}; + +static const pci_subclass_t mem_subclass[] = { + { + PCI_SUBCLASS_MEMORY_RAM, "RAM controller", + NULL, NULL, NULL, + NULL, NULL, + }, + { + PCI_SUBCLASS_MEMORY_FLASH, "flash controller", + NULL, NULL, NULL, + NULL, NULL, + }, + { + 0xFF, NULL, + NULL, NULL, NULL, + NULL, NULL, + }, +}; + + +static const pci_dev_t hbrg_devices[] = { + { + PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_U3_AGP, NULL, + "pci", "AAPL,UniNorth", "u3-agp\0", + 3, 2, 1, + host_config_cb, NULL, + }, + { + PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_UNI_N_AGP, NULL, + "pci", "AAPL,UniNorth", "uni-north\0", + 3, 2, 1, + host_config_cb, NULL, + }, + { + PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_UNI_N_PCI, NULL, + "pci", "AAPL,UniNorth", "uni-north\0", + 3, 2, 1, + host_config_cb, NULL, + }, + { + PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_UNI_N_I_PCI, NULL, + "pci", "AAPL,UniNorth", "uni-north\0", + 3, 2, 1, + NULL, NULL + }, + { + PCI_VENDOR_ID_MOTOROLA, PCI_DEVICE_ID_MOTOROLA_MPC106, "pci", + "pci", "MOT,MPC106", "grackle\0", + 3, 2, 1, + host_config_cb, NULL + }, + { + PCI_VENDOR_ID_MOTOROLA, PCI_DEVICE_ID_MOTOROLA_RAVEN, NULL, + "pci", "PREP Host PCI Bridge - Motorola Raven", NULL, + 3, 2, 1, + host_config_cb, NULL, + }, + { + PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_SABRE, NULL, + "pci", "SUNW,sabre", "pci108e,a000\0pciclass,0\0", + 3, 2, 1, + sabre_config_cb, NULL, + }, + { + 0xFFFF, 0xFFFF, + NULL, NULL, NULL, NULL, + -1, -1, -1, + NULL, NULL, + }, +}; + +static const pci_dev_t PCIbrg_devices[] = { + { + PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21154, NULL, + "pci-bridge", "DEV,21154", "DEV,21154\0pci-bridge\0", + 3, 2, 1, + bridge_config_cb, NULL, + }, + { + PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_SIMBA, NULL, + "pci", "SUNW,simba", "pci108e,5000\0pciclass,060400\0", + 3, 2, 1, + bridge_config_cb, NULL, + }, + { + 0xFFFF, 0xFFFF, + NULL, NULL, NULL, NULL, + -1, -1, -1, + NULL, NULL, + }, +}; + +static const pci_dev_t miscbrg_devices[] = { + { + PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_EBUS, NULL, + "ebus", "ebus", "pci108e,1000\0pciclass,068000\0", + 2, 1, 1, + ebus_config_cb, NULL, + }, + { + 0xFFFF, 0xFFFF, + NULL, NULL, NULL, NULL, + -1, -1, -1, + NULL, NULL, + }, +}; + +static const pci_dev_t isabrg_devices[] = { + { + PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82378, NULL, + "isa", "isa", "pci8086,484\0", + 1, 1, 1, + i82378_config_cb, NULL, + }, + { + 0xFFFF, 0xFFFF, + NULL, NULL, NULL, NULL, + -1, -1, -1, + NULL, NULL, + }, +}; + +static const pci_subclass_t bridg_subclass[] = { + { + PCI_SUBCLASS_BRIDGE_HOST, "PCI host bridge", + "pci", hbrg_devices, NULL, + NULL, NULL, + }, + { + PCI_SUBCLASS_BRIDGE_ISA, "ISA bridge", + "isa", isabrg_devices, NULL, + NULL, NULL, + }, + { + PCI_SUBCLASS_BRIDGE_EISA, "EISA bridge", + NULL, NULL, NULL, + NULL, NULL, + }, + { + PCI_SUBCLASS_BRIDGE_MC, "MCA bridge", + NULL, NULL, NULL, + NULL, NULL, + }, + { + PCI_SUBCLASS_BRIDGE_PCI, "PCI-to-PCI bridge", + "pci", PCIbrg_devices, NULL, + NULL, NULL, + }, + { + PCI_SUBCLASS_BRIDGE_PCMCIA, "PCMCIA bridge", + NULL, NULL, NULL, + NULL, NULL, + }, + { + PCI_SUBCLASS_BRIDGE_NUBUS, "NUBUS bridge", + NULL, NULL, NULL, + NULL, NULL, + }, + { + PCI_SUBCLASS_BRIDGE_CARDBUS, "cardbus bridge", + NULL, NULL, NULL, + NULL, NULL, + }, + { + PCI_SUBCLASS_BRIDGE_RACEWAY, "raceway bridge", + NULL, NULL, NULL, + NULL, NULL, + }, + { + PCI_SUBCLASS_BRIDGE_PCI_SEMITP, "semi-transparent PCI-to-PCI bridge", + NULL, NULL, NULL, + NULL, NULL, + }, + { + PCI_SUBCLASS_BRIDGE_IB_PCI, "infiniband-to-PCI bridge", + NULL, NULL, NULL, + NULL, NULL, + }, + { + PCI_SUBCLASS_BRIDGE_OTHER, "misc PCI bridge", + NULL, miscbrg_devices, NULL, + NULL, NULL, + }, + { + 0xFF, NULL, + NULL, NULL, NULL, + NULL, NULL, + }, +}; + +static const pci_iface_t serial_iface[] = { + { + 0x00, "XT serial controller", NULL, + NULL, NULL, NULL, + }, + { + 0x01, "16450 serial controller", NULL, + NULL, NULL, NULL, + }, + { + 0x02, "16550 serial controller", NULL, + NULL, NULL, NULL, + }, + { + 0x03, "16650 serial controller", NULL, + NULL, NULL, NULL, + }, + { + 0x04, "16750 serial controller", NULL, + NULL, NULL, NULL, + }, + { + 0x05, "16850 serial controller", NULL, + NULL, NULL, NULL, + }, + { + 0x06, "16950 serial controller", NULL, + NULL, NULL, NULL, + }, + { + 0xFF, NULL, NULL, + NULL, NULL, NULL, + }, +}; + +static const pci_iface_t par_iface[] = { + { + 0x00, "parallel port", NULL, + NULL, NULL, NULL, + }, + { + 0x01, "bi-directional parallel port", NULL, + NULL, NULL, NULL, + }, + { + 0x02, "ECP 1.x parallel port", NULL, + NULL, NULL, NULL, + }, + { + 0x03, "IEEE 1284 controller", NULL, + NULL, NULL, NULL, + }, + { + 0xFE, "IEEE 1284 device", NULL, + NULL, NULL, NULL, + }, + { + 0xFF, NULL, NULL, + NULL, NULL, NULL, + }, +}; + +static const pci_iface_t modem_iface[] = { + { + 0x00, "generic modem", NULL, + NULL, NULL, NULL, + }, + { + 0x01, "Hayes 16450 modem", NULL, + NULL, NULL, NULL, + }, + { + 0x02, "Hayes 16550 modem", NULL, + NULL, NULL, NULL, + }, + { + 0x03, "Hayes 16650 modem", NULL, + NULL, NULL, NULL, + }, + { + 0x04, "Hayes 16750 modem", NULL, + NULL, NULL, NULL, + }, + { + 0xFF, NULL, NULL, + NULL, NULL, NULL, + }, +}; + +static const pci_subclass_t comm_subclass[] = { + { + PCI_SUBCLASS_COMMUNICATION_SERIAL, "serial controller", + NULL, NULL, serial_iface, + NULL, NULL, + }, + { + PCI_SUBCLASS_COMMUNICATION_PARALLEL, "parallel port", + NULL, NULL, par_iface, + NULL, NULL, + }, + { + PCI_SUBCLASS_COMMUNICATION_MULTISERIAL, "multiport serial controller", + NULL, NULL, NULL, + NULL, NULL, + }, + { + PCI_SUBCLASS_COMMUNICATION_MODEM, "modem", + NULL, NULL, modem_iface, + NULL, NULL, + }, + { + PCI_SUBCLASS_COMMUNICATION_GPIB, "GPIB controller", + NULL, NULL, NULL, + NULL, NULL, + }, + { + PCI_SUBCLASS_COMMUNICATION_SC, "smart card", + NULL, NULL, NULL, + NULL, NULL, + }, + { + PCI_SUBCLASS_COMMUNICATION_OTHER, "misc communication device", + NULL, NULL, NULL, + NULL, NULL, + }, + { + 0xFF, NULL, + NULL, NULL, NULL, + NULL, NULL, + }, +}; + +static const pci_iface_t pic_iface[] = { + { + 0x00, "8259 PIC", NULL, + NULL, NULL, NULL, + }, + { + 0x01, "ISA PIC", NULL, + NULL, NULL, NULL, + }, + { + 0x02, "EISA PIC", NULL, + NULL, NULL, NULL, + }, + { + 0x10, "I/O APIC", NULL, + NULL, NULL, NULL, + }, + { + 0x20, "I/O APIC", NULL, + NULL, NULL, NULL, + }, + { + 0xFF, NULL, NULL, + NULL, NULL, NULL, + }, +}; + +static const pci_iface_t dma_iface[] = { + { + 0x00, "8237 DMA controller", NULL, + NULL, NULL, NULL, + }, + { + 0x01, "ISA DMA controller", NULL, + NULL, NULL, NULL, + }, + { + 0x02, "EISA DMA controller", NULL, + NULL, NULL, NULL, + }, + { + 0xFF, NULL, NULL, + NULL, NULL, NULL, + }, +}; + +static const pci_iface_t tmr_iface[] = { + { + 0x00, "8254 system timer", NULL, + NULL, NULL, NULL, + }, + { + 0x01, "ISA system timer", NULL, + NULL, NULL, NULL, + }, + { + 0x02, "EISA system timer", NULL, + NULL, NULL, NULL, + }, + { + 0xFF, NULL, NULL, + NULL, NULL, NULL, + }, +}; + +static const pci_iface_t rtc_iface[] = { + { + 0x00, "generic RTC controller", NULL, + NULL, NULL, NULL, + }, + { + 0x01, "ISA RTC controller", NULL, + NULL, NULL, NULL, + }, + { + 0xFF, NULL, NULL, + NULL, NULL, NULL, + }, +}; + +static const pci_dev_t sys_devices[] = { + /* IBM MPIC controller */ + { + PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OPENPIC, + "open-pic", "MPIC", NULL, "chrp,open-pic\0", + 0, 0, 2, + NULL, NULL, + }, + /* IBM MPIC2 controller */ + { + PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OPENPIC2, + "open-pic", "MPIC2", NULL, "chrp,open-pic\0", + 0, 0, 2, + NULL, NULL, + }, + { + 0xFFFF, 0xFFFF, + NULL, NULL, NULL, NULL, + -1, -1, -1, + NULL, NULL, + }, +}; + +static const pci_subclass_t sys_subclass[] = { + { + PCI_SUBCLASS_SYSTEM_PIC, "PIC", + NULL, NULL, pic_iface, + NULL, NULL, + }, + { + PCI_SUBCLASS_SYSTEM_DMA, "DMA controller", + NULL, NULL, dma_iface, + NULL, NULL, + }, + { + PCI_SUBCLASS_SYSTEM_TIMER, "system timer", + NULL, NULL, tmr_iface, + NULL, NULL, + }, + { + PCI_SUBCLASS_SYSTEM_RTC, "RTC controller", + NULL, NULL, rtc_iface, + NULL, NULL, + }, + { + PCI_SUBCLASS_SYSTEM_PCI_HOTPLUG, "PCI hotplug controller", + NULL, NULL, NULL, + NULL, NULL, + }, + { + PCI_SUBCLASS_SYSTEM_OTHER, "misc system peripheral", + NULL, sys_devices, NULL, + NULL, NULL, + }, + { + 0xFF, NULL, + NULL, NULL, NULL, + NULL, NULL, + }, +}; + +static const pci_subclass_t inp_subclass[] = { + { + PCI_SUBCLASS_INPUT_KEYBOARD, "keyboard controller", + NULL, NULL, NULL, + NULL, NULL, + }, + { + PCI_SUBCLASS_INPUT_PEN, "digitizer", + NULL, NULL, NULL, + NULL, NULL, + }, + { + PCI_SUBCLASS_INPUT_MOUSE, "mouse controller", + NULL, NULL, NULL, + NULL, NULL, + }, + { + PCI_SUBCLASS_INPUT_SCANNER, "scanner controller", + NULL, NULL, NULL, + NULL, NULL, + }, + { + PCI_SUBCLASS_INPUT_GAMEPORT, "gameport controller", + NULL, NULL, NULL, + NULL, NULL, + }, + { + PCI_SUBCLASS_INPUT_OTHER, "misc input device", + NULL, NULL, NULL, + NULL, NULL, + }, + { + 0xFF, NULL, + NULL, NULL, NULL, + NULL, NULL, + }, +}; + +static const pci_subclass_t dock_subclass[] = { + { + PCI_SUBCLASS_DOCKING_GENERIC, "generic docking station", + NULL, NULL, NULL, + NULL, NULL, + }, + { + PCI_SUBCLASS_DOCKING_OTHER, "misc docking station", + NULL, NULL, NULL, + NULL, NULL, + }, + { + 0xFF, NULL, + NULL, NULL, NULL, + NULL, NULL, + }, +}; + +static const pci_subclass_t cpu_subclass[] = { + { + PCI_SUBCLASS_PROCESSOR_386, "i386 processor", + NULL, NULL, NULL, + NULL, NULL, + }, + { + PCI_SUBCLASS_PROCESSOR_486, "i486 processor", + NULL, NULL, NULL, + NULL, NULL, + }, + { + PCI_SUBCLASS_PROCESSOR_PENTIUM, "pentium processor", + NULL, NULL, NULL, + NULL, NULL, + }, + { + PCI_SUBCLASS_PROCESSOR_ALPHA, "alpha processor", + NULL, NULL, NULL, + NULL, NULL, + }, + { + PCI_SUBCLASS_PROCESSOR_POWERPC, "PowerPC processor", + NULL, NULL, NULL, + NULL, NULL, + }, + { + PCI_SUBCLASS_PROCESSOR_MIPS, "MIPS processor", + NULL, NULL, NULL, + NULL, NULL, + }, + { + PCI_SUBCLASS_PROCESSOR_CO, "co-processor", + NULL, NULL, NULL, + NULL, NULL, + }, + { + 0xFF, NULL, + NULL, NULL, NULL, + NULL, NULL, + }, +}; + +static const pci_dev_t usb_devices[] = { +#if defined(CONFIG_QEMU) + { + PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_KEYL_USB, + "usb", "usb", NULL, + "pci106b,3f\0pciclass,0c0310\0", + 1, 0, 0, + NULL, NULL, + }, +#endif + { + 0xFFFF, 0xFFFF, + NULL, NULL, NULL, NULL, + -1, -1, -1, + NULL, NULL, + }, +}; + +static const pci_iface_t usb_iface[] = { + { + 0x00, "UHCI USB controller", NULL, + NULL, NULL, NULL, + }, + { + 0x10, "OHCI USB controller", NULL, + usb_devices, &usb_ohci_config_cb, NULL, + }, + { + 0x20, "EHCI USB controller", NULL, + NULL, NULL, NULL, + }, + { + 0x80, "misc USB controller", NULL, + NULL, NULL, NULL, + }, + { + 0xFE, "USB device", NULL, + NULL, NULL, NULL, + }, + { + 0xFF, NULL, NULL, + NULL, NULL, NULL, + }, +}; + +static const pci_iface_t ipmi_iface[] = { + { + 0x00, "IPMI SMIC interface", NULL, + NULL, NULL, NULL, + }, + { + 0x01, "IPMI keyboard interface", NULL, + NULL, NULL, NULL, + }, + { + 0x02, "IPMI block transfer interface", NULL, + NULL, NULL, NULL, + }, + { + 0xFF, NULL, NULL, + NULL, NULL, NULL, + }, +}; + +static const pci_subclass_t ser_subclass[] = { + { + PCI_SUBCLASS_SERIAL_FIREWIRE, "Firewire bus controller", + "ieee1394", NULL, NULL, + NULL, NULL, + }, + { + PCI_SUBCLASS_SERIAL_ACCESS, "ACCESS bus controller", + NULL, NULL, NULL, + NULL, NULL, + }, + { + PCI_SUBCLASS_SERIAL_SSA, "SSA controller", + NULL, NULL, NULL, + NULL, NULL, + }, + { + PCI_SUBCLASS_SERIAL_USB, "USB controller", + "usb", NULL, usb_iface, + NULL, NULL, + }, + { + PCI_SUBCLASS_SERIAL_FIBER, "fibre channel controller", + NULL, NULL, NULL, + NULL, NULL, + }, + { + PCI_SUBCLASS_SERIAL_SMBUS, "SMBus controller", + NULL, NULL, NULL, + NULL, NULL, + }, + { + PCI_SUBCLASS_SERIAL_IB, "InfiniBand controller", + NULL, NULL, NULL, + NULL, NULL, + }, + { + PCI_SUBCLASS_SERIAL_IPMI, "IPMI interface", + NULL, NULL, ipmi_iface, + NULL, NULL, + }, + { + PCI_SUBCLASS_SERIAL_SERCOS, "SERCOS controller", + NULL, NULL, ipmi_iface, + NULL, NULL, + }, + { + PCI_SUBCLASS_SERIAL_CANBUS, "CANbus controller", + NULL, NULL, ipmi_iface, + NULL, NULL, + }, + { + 0xFF, NULL, + NULL, NULL, NULL, + NULL, NULL, + }, +}; + +static const pci_subclass_t wrl_subclass[] = { + { + PCI_SUBCLASS_WIRELESS_IRDA, "IRDA controller", + NULL, NULL, NULL, + NULL, NULL, + }, + { + PCI_SUBCLASS_WIRELESS_CIR, "consumer IR controller", + NULL, NULL, NULL, + NULL, NULL, + }, + { + PCI_SUBCLASS_WIRELESS_RF_CONTROLLER, "RF controller", + NULL, NULL, NULL, + NULL, NULL, + }, + { + PCI_SUBCLASS_WIRELESS_BLUETOOTH, "bluetooth controller", + NULL, NULL, NULL, + NULL, NULL, + }, + { + PCI_SUBCLASS_WIRELESS_BROADBAND, "broadband controller", + NULL, NULL, NULL, + NULL, NULL, + }, + { + PCI_SUBCLASS_WIRELESS_OTHER, "misc wireless controller", + NULL, NULL, NULL, + NULL, NULL, + }, + { + 0xFF, NULL, + NULL, NULL, NULL, + NULL, NULL, + }, +}; + +static const pci_subclass_t sat_subclass[] = { + { + PCI_SUBCLASS_SATELLITE_TV, "satellite TV controller", + NULL, NULL, NULL, + NULL, NULL, + }, + { + PCI_SUBCLASS_SATELLITE_AUDIO, "satellite audio controller", + NULL, NULL, NULL, + NULL, NULL, + }, + { + PCI_SUBCLASS_SATELLITE_VOICE, "satellite voice controller", + NULL, NULL, NULL, + NULL, NULL, + }, + { + PCI_SUBCLASS_SATELLITE_DATA, "satellite data controller", + NULL, NULL, NULL, + NULL, NULL, + }, + { + 0xFF, NULL, + NULL, NULL, NULL, + NULL, NULL, + }, +}; + +static const pci_subclass_t crypt_subclass[] = { + { + PCI_SUBCLASS_CRYPT_NETWORK, "cryptographic network controller", + NULL, NULL, NULL, + NULL, NULL, + }, + { + PCI_SUBCLASS_CRYPT_ENTERTAINMENT, + "cryptographic entertainment controller", + NULL, NULL, NULL, + NULL, NULL, + }, + { + PCI_SUBCLASS_CRYPT_OTHER, "misc cryptographic controller", + NULL, NULL, NULL, + NULL, NULL, + }, + { + 0xFF, NULL, + NULL, NULL, NULL, + NULL, NULL, + }, +}; + +static const pci_subclass_t spc_subclass[] = { + { + PCI_SUBCLASS_SP_DPIO, "DPIO module", + NULL, NULL, NULL, + NULL, NULL, + }, + { + PCI_SUBCLASS_SP_PERF, "performances counters", + NULL, NULL, NULL, + NULL, NULL, + }, + { + PCI_SUBCLASS_SP_SYNCH, "communication synchronisation", + NULL, NULL, NULL, + NULL, NULL, + }, + { + PCI_SUBCLASS_SP_MANAGEMENT, "management card", + NULL, NULL, NULL, + NULL, NULL, + }, + { + PCI_SUBCLASS_SP_OTHER, "misc signal processing controller", + NULL, NULL, NULL, + NULL, NULL, + }, + { + 0xFF, NULL, + NULL, NULL, NULL, + NULL, NULL, + }, +}; + +static const pci_class_t pci_classes[] = { + /* 0x00 */ + { "undefined", NULL, undef_subclass, }, + /* 0x01 */ + { "mass-storage controller", NULL, mass_subclass, }, + /* 0x02 */ + { "network controller", "network", net_subclass, }, + /* 0x03 */ + { "display controller", "display", displ_subclass, }, + /* 0x04 */ + { "multimedia device", NULL, media_subclass, }, + /* 0x05 */ + { "memory controller", "memory-controller", mem_subclass, }, + /* 0x06 */ + { "PCI bridge", NULL, bridg_subclass, }, + /* 0x07 */ + { "communication device", NULL, comm_subclass,}, + /* 0x08 */ + { "system peripheral", NULL, sys_subclass, }, + /* 0x09 */ + { "input device", NULL, inp_subclass, }, + /* 0x0A */ + { "docking station", NULL, dock_subclass, }, + /* 0x0B */ + { "processor", NULL, cpu_subclass, }, + /* 0x0C */ + { "serial bus controller", NULL, ser_subclass, }, + /* 0x0D */ + { "wireless controller", NULL, wrl_subclass, }, + /* 0x0E */ + { "intelligent I/O controller", NULL, NULL, }, + /* 0x0F */ + { "satellite communication controller", NULL, sat_subclass, }, + /* 0x10 */ + { "cryptographic controller", NULL, crypt_subclass, }, + /* 0x11 */ + { "signal processing controller", NULL, spc_subclass, }, +}; + +static const pci_dev_t misc_pci[] = { + /* Heathrow Mac I/O */ + { + PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_343S1201, + "mac-io", "mac-io", "AAPL,343S1201", "heathrow\0", + 1, 1, 1, + &macio_heathrow_config_cb, NULL, + }, + /* Paddington Mac I/O */ + { + PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_343S1211, + "mac-io", "mac-io", "AAPL,343S1211", "paddington\0heathrow\0", + 1, 1, 1, + &macio_heathrow_config_cb, NULL, + }, + /* KeyLargo Mac I/O */ + { + PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_UNI_N_KEYL, + "mac-io", "mac-io", "AAPL,Keylargo", "Keylargo\0", + 1, 1, 1, + &macio_keylargo_config_cb, NULL, + }, + { + 0xFFFF, 0xFFFF, + NULL, NULL, NULL, NULL, + -1, -1, -1, + NULL, NULL, + }, +}; + +const pci_dev_t *pci_find_device (uint8_t class, uint8_t subclass, + uint8_t iface, uint16_t vendor, + uint16_t product) +{ + int (*config_cb)(const pci_config_t *config); + const pci_class_t *pclass; + const pci_subclass_t *psubclass; + const pci_iface_t *piface; + const pci_dev_t *dev; + const void *private; + pci_dev_t *new; + const char *name, *type; + + name = "unknown"; + type = "unknown"; + config_cb = NULL; + private = NULL; + + if (class == 0x00 && subclass == 0x01) { + /* Special hack for old style VGA devices */ + class = 0x03; + subclass = 0x00; + } else if (class == 0xFF) { + /* Special case for misc devices */ + dev = misc_pci; + goto find_device; + } + if (class > (sizeof(pci_classes) / sizeof(pci_class_t))) { + name = "invalid PCI device"; + type = "invalid"; + goto bad_device; + } + pclass = &pci_classes[class]; + name = pclass->name; + type = pclass->type; + for (psubclass = pclass->subc; ; psubclass++) { + if (psubclass->subclass == 0xFF) + goto bad_device; + if (psubclass->subclass == subclass) { + if (psubclass->name != NULL) + name = psubclass->name; + if (psubclass->type != NULL) + type = psubclass->type; + if (psubclass->config_cb != NULL) { + config_cb = psubclass->config_cb; + } + if (psubclass->private != NULL) + private = psubclass->private; + if (psubclass->iface != NULL) + break; + dev = psubclass->devices; + goto find_device; + } + } + for (piface = psubclass->iface; ; piface++) { + if (piface->iface == 0xFF) { + dev = psubclass->devices; + break; + } + if (piface->iface == iface) { + if (piface->name != NULL) + name = piface->name; + if (piface->type != NULL) + type = piface->type; + if (piface->config_cb != NULL) { + config_cb = piface->config_cb; + } + if (piface->private != NULL) + private = piface->private; + dev = piface->devices; + break; + } + } +find_device: + if (dev == NULL) + goto bad_device; + for (;; dev++) { + if (dev->vendor == 0xFFFF && dev->product == 0xFFFF) { + goto bad_device; + } + if (dev->vendor == vendor && dev->product == product) { + if (dev->name != NULL) + name = dev->name; + if (dev->type != NULL) + type = dev->type; + if (dev->config_cb != NULL) { + config_cb = dev->config_cb; + } + if (dev->private != NULL) + private = dev->private; + new = malloc(sizeof(pci_dev_t)); + if (new == NULL) + return NULL; + new->vendor = vendor; + new->product = product; + new->type = type; + new->name = name; + new->model = dev->model; + new->compat = dev->compat; + new->acells = dev->acells; + new->scells = dev->scells; + new->icells = dev->icells; + new->config_cb = config_cb; + new->private = private; + + return new; + } + } +bad_device: + printk("Cannot manage '%s' PCI device type '%s':\n %x %x (%x %x %x)\n", + name, type, vendor, product, class, subclass, iface); + + return NULL; +} diff --git a/qemu/roms/openbios/drivers/pci_database.h b/qemu/roms/openbios/drivers/pci_database.h new file mode 100644 index 000000000..7f053d808 --- /dev/null +++ b/qemu/roms/openbios/drivers/pci_database.h @@ -0,0 +1,57 @@ +typedef struct pci_config_t pci_config_t; + +struct pci_config_t { + char path[256]; + uint32_t dev; /* bus, dev, fn */ + uint32_t regions[7]; + uint32_t assigned[7]; + uint32_t sizes[7]; + int irq_pin; + int irq_line; + u32 primary_bus; + u32 secondary_bus; + u32 subordinate_bus; +}; + +typedef struct pci_dev_t pci_dev_t; +struct pci_dev_t { + uint16_t vendor; + uint16_t product; + const char *type; + const char *name; + const char *model; + const char *compat; + int acells; + int scells; + int icells; + int (*config_cb)(const pci_config_t *config); + const void *private; +}; + +extern int ide_config_cb2(const pci_config_t *config); +extern int eth_config_cb(const pci_config_t *config); +extern int macio_heathrow_config_cb(const pci_config_t *config); +extern int macio_keylargo_config_cb(const pci_config_t *config); +extern int vga_config_cb(const pci_config_t *config); +extern int host_config_cb(const pci_config_t *config); +extern int sabre_config_cb(const pci_config_t *config); +extern int bridge_config_cb(const pci_config_t *config); +extern int ebus_config_cb(const pci_config_t *config); +extern int i82378_config_cb(const pci_config_t *config); +extern int usb_ohci_config_cb(const pci_config_t *config); + +static inline int pci_compat_len(const pci_dev_t *dev) +{ + int len, ret; + const char *path = dev->compat; + ret = 0; + while ((len = strlen(path)) != 0) { + ret += len + 1; + path += len + 1; + } + return ret; +} + +extern const pci_dev_t *pci_find_device(uint8_t class, uint8_t subclass, + uint8_t iface, uint16_t vendor, + uint16_t product); diff --git a/qemu/roms/openbios/drivers/sbus.c b/qemu/roms/openbios/drivers/sbus.c new file mode 100644 index 000000000..a9b26c0a0 --- /dev/null +++ b/qemu/roms/openbios/drivers/sbus.c @@ -0,0 +1,523 @@ +/* + * OpenBIOS SBus driver + * + * (C) 2004 Stefan Reinauer <stepan@openbios.org> + * (C) 2005 Ed Schouten <ed@fxq.nl> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#include "config.h" +#include "libopenbios/bindings.h" +#include "kernel/kernel.h" +#include "libc/byteorder.h" +#include "libc/vsprintf.h" +#include "drivers/drivers.h" +#include "libopenbios/ofmem.h" +#include "libopenbios/video.h" + +#define SBUS_REGS 0x28 +#define SBUS_SLOTS 16 +#define APC_REGS 0x10 +#define APC_OFFSET 0x0a000000ULL +#define CS4231_REGS 0x40 +#define CS4231_OFFSET 0x0c000000ULL +#define MACIO_ESPDMA 0x00400000ULL /* ESP DMA controller */ +#define MACIO_ESP 0x00800000ULL /* ESP SCSI */ +#define SS600MP_ESPDMA 0x00081000ULL +#define SS600MP_ESP 0x00080000ULL +#define SS600MP_LEBUFFER (SS600MP_ESPDMA + 0x10) // XXX should be 0x40000 +#define LEDMA_REGS 0x4 +#define LE_REGS 0x20 + +#ifdef CONFIG_DEBUG_SBUS +#define DPRINTF(fmt, args...) \ + do { printk(fmt , ##args); } while (0) +#else +#define DPRINTF(fmt, args...) +#endif + +typedef struct le_private { + uint32_t *dmaregs; + uint32_t *regs; +} le_private_t; + +static void +ob_sbus_node_init(uint64_t base) +{ + void *regs; + + push_str("/iommu/sbus"); + fword("find-device"); + + PUSH(base >> 32); + fword("encode-int"); + PUSH(base & 0xffffffff); + fword("encode-int"); + fword("encode+"); + PUSH(SBUS_REGS); + fword("encode-int"); + fword("encode+"); + push_str("reg"); + fword("property"); + + regs = (void *)ofmem_map_io(base, SBUS_REGS); + PUSH((unsigned long)regs); + fword("encode-int"); + push_str("address"); + fword("property"); +} + +static void +ob_le_init(unsigned int slot, uint64_t base, unsigned long leoffset, unsigned long dmaoffset) +{ + le_private_t *le; + + le = malloc(sizeof(le_private_t)); + if (!le) { + DPRINTF("Can't allocate LANCE private structure\n"); + return; + } + + /* Get the IO region for DMA registers */ + le->dmaregs = (void *)ofmem_map_io(base + (uint64_t)dmaoffset, LEDMA_REGS); + if (le->dmaregs == NULL) { + DPRINTF("Can't map LANCE DMA registers\n"); + return; + } + + /* Now it appears that the Solaris kernel forgets to set up the LANCE DMA mapping + and so it must inherit the one from OpenBIOS. The symptom of this is that the + LANCE DMA base addr register is still zero, and so we start sending network + packets containing random areas of memory. + + The correct fix for this should be to use dvma_alloc() to grab a section of + memory and point the LANCE DMA buffers to use that instead; this gets + slightly further but still crashes. Time-consuming investigation on various + hacked versions of QEMU seems to indicate that Solaris always assumes the LANCE + DMA base address is fixed 0xff000000 when setting up the IOMMU for the LANCE + card. Hence we imitate this behaviour here. */ + le->dmaregs[3] = 0xff000000; + + push_str("/iommu/sbus/ledma"); + fword("find-device"); + PUSH(slot); + fword("encode-int"); + PUSH(dmaoffset); + fword("encode-int"); + fword("encode+"); + PUSH(0x00000020); + fword("encode-int"); + fword("encode+"); + push_str("reg"); + fword("property"); + + /* Get the IO region for Lance registers */ + le->regs = (void *)ofmem_map_io(base + (uint64_t)leoffset, LE_REGS); + if (le->regs == NULL) { + DPRINTF("Can't map LANCE registers\n"); + return; + } + + push_str("/iommu/sbus/ledma/le"); + fword("find-device"); + PUSH(slot); + fword("encode-int"); + PUSH(leoffset); + fword("encode-int"); + fword("encode+"); + PUSH(0x00000004); + fword("encode-int"); + fword("encode+"); + push_str("reg"); + fword("property"); +} + +uint16_t graphic_depth; + +static void +ob_tcx_init(unsigned int slot, const char *path) +{ + char buf[6]; + + printk("No display device located during SBus probe - falling back to internal TCX driver\n"); + + /* Make the sbus node the current instance and active package for probing */ + feval("active-package my-self"); + push_str("/iommu/sbus"); + feval("2dup find-device open-dev to my-self"); + + fword("new-device"); + PUSH(0); + PUSH(0); + snprintf(buf, 6, "%x,0", slot); + push_str(buf); + fword("set-args"); + feval("['] tcx-driver-fcode 2 cells + 1 byte-load"); + fword("finish-device"); + + /* Restore */ + feval("to my-self active-package!"); +} + +static void +ob_apc_init(unsigned int slot, unsigned long base) +{ + push_str("/iommu/sbus"); + fword("find-device"); + fword("new-device"); + + push_str("power-management"); + fword("device-name"); + + PUSH(slot); + fword("encode-int"); + PUSH(base); + fword("encode-int"); + fword("encode+"); + PUSH(APC_REGS); + fword("encode-int"); + fword("encode+"); + push_str("reg"); + fword("property"); + + fword("finish-device"); +} + +static void +ob_cs4231_init(unsigned int slot) +{ + push_str("/iommu/sbus"); + fword("find-device"); + fword("new-device"); + + push_str("SUNW,CS4231"); + fword("device-name"); + + push_str("serial"); + fword("device-type"); + + PUSH(slot); + fword("encode-int"); + PUSH(CS4231_OFFSET); + fword("encode-int"); + fword("encode+"); + PUSH(CS4231_REGS); + fword("encode-int"); + fword("encode+"); + push_str("reg"); + fword("property"); + + PUSH(5); + fword("encode-int"); + PUSH(0); + fword("encode-int"); + fword("encode+"); + push_str("intr"); + fword("property"); + + PUSH(5); + fword("encode-int"); + push_str("interrupts"); + fword("property"); + + push_str("audio"); + fword("encode-string"); + push_str("alias"); + fword("property"); + + fword("finish-device"); +} + +static void +ob_macio_init(unsigned int slot, uint64_t base, unsigned long offset) +{ + // All devices were integrated to NCR89C100, see + // http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C100.txt + + // NCR 53c9x, aka ESP. See + // http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR53C9X.txt +#ifdef CONFIG_DRIVER_ESP + ob_esp_init(slot, base, offset + MACIO_ESP, offset + MACIO_ESPDMA); +#endif + + // NCR 92C990, Am7990, Lance. See http://www.amd.com + ob_le_init(slot, base, offset + 0x00c00000, offset + 0x00400010); + + // Parallel port + //ob_bpp_init(base); +} + +static void +sbus_probe_self(unsigned int slot, unsigned long offset) +{ + /* Wrapper for calling probe-self in Forth. This is mainly because some + drivers don't handle properties correctly when the sbus node is set + as the current instance during probe. */ + char buf[6]; + + printk("Probing SBus slot %d offset %ld\n", slot, offset); + + /* Make the sbus node the current instance and active package for probing */ + feval("active-package my-self"); + push_str("/iommu/sbus"); + feval("open-dev to my-self"); + + PUSH(0); + PUSH(0); + snprintf(buf, 6, "%x,%lx", slot, offset); + push_str(buf); + fword("2dup"); + fword("probe-self-sbus"); + + /* Restore */ + feval("to my-self active-package!"); +} + +static int +sbus_probe_sucess(void) +{ + /* Return true if the last sbus_probe_self() resulted in + the successful detection and execution of FCode */ + fword("probe-fcode?"); + return POP(); +} + +static void +sbus_probe_slot_ss5(unsigned int slot, uint64_t base) +{ + /* Probe the slot */ + sbus_probe_self(slot, 0); + + /* If the device was successfully created by FCode then do nothing */ + if (sbus_probe_sucess()) { + return; + } + + switch(slot) { + case 3: // SUNW,tcx + ob_tcx_init(slot, "/iommu/sbus/SUNW,tcx"); + break; + case 4: + // SUNW,CS4231 + ob_cs4231_init(slot); + // Power management (APC) + ob_apc_init(slot, APC_OFFSET); + break; + case 5: // MACIO: le, esp, bpp + ob_macio_init(slot, base, 0x08000000); + break; + default: + break; + } +} + +static void +sbus_probe_slot_ss10(unsigned int slot, uint64_t base) +{ + /* Probe the slot */ + sbus_probe_self(slot, 0); + + /* If the device was successfully created by FCode then do nothing */ + if (sbus_probe_sucess()) { + return; + } + + switch(slot) { + case 2: // SUNW,tcx + ob_tcx_init(slot, "/iommu/sbus/SUNW,tcx"); + break; + case 0xf: // le, esp, bpp, power-management + ob_macio_init(slot, base, 0); + // Power management (APC) XXX should not exist + ob_apc_init(slot, APC_OFFSET); + break; + default: + break; + } +} + +static void +sbus_probe_slot_ss600mp(unsigned int slot, uint64_t base) +{ + /* Probe the slot */ + sbus_probe_self(slot, 0); + + /* If the device was successfully created by FCode then do nothing */ + if (sbus_probe_sucess()) { + return; + } + + switch(slot) { + case 2: // SUNW,tcx + ob_tcx_init(slot, "/iommu/sbus/SUNW,tcx"); + break; + case 0xf: // le, esp, bpp, power-management +#ifdef CONFIG_DRIVER_ESP + ob_esp_init(slot, base, SS600MP_ESP, SS600MP_ESPDMA); +#endif + // NCR 92C990, Am7990, Lance. See http://www.amd.com + ob_le_init(slot, base, 0x00060000, SS600MP_LEBUFFER); + // Power management (APC) XXX should not exist + ob_apc_init(slot, APC_OFFSET); + break; + default: + break; + } +} + +static void +ob_sbus_open(void) +{ + int ret=1; + RET ( -ret ); +} + +static void +ob_sbus_close(void) +{ + selfword("close-deblocker"); +} + +static void +ob_sbus_initialize(void) +{ +} + + +NODE_METHODS(ob_sbus_node) = { + { NULL, ob_sbus_initialize }, + { "open", ob_sbus_open }, + { "close", ob_sbus_close }, +}; + +struct sbus_offset { + int slot, type; + uint64_t base; + unsigned long size; +}; + +static const struct sbus_offset sbus_offsets_ss5[SBUS_SLOTS] = { + { 0, 0, 0x20000000, 0x10000000,}, + { 1, 0, 0x30000000, 0x10000000,}, + { 2, 0, 0x40000000, 0x10000000,}, + { 3, 0, 0x50000000, 0x10000000,}, + { 4, 0, 0x60000000, 0x10000000,}, + { 5, 0, 0x70000000, 0x10000000,}, +}; + +/* Shared with ss600mp */ +static const struct sbus_offset sbus_offsets_ss10[SBUS_SLOTS] = { + { 0, 0, 0xe00000000ULL, 0x10000000,}, + { 1, 0, 0xe10000000ULL, 0x10000000,}, + { 2, 0, 0xe20000000ULL, 0x10000000,}, + { 3, 0, 0xe30000000ULL, 0x10000000,}, + [0xf] = { 0xf, 0, 0xef0000000ULL, 0x10000000,}, +}; + +static void +ob_add_sbus_range(const struct sbus_offset *range, int notfirst) +{ + if (!notfirst) { + push_str("/iommu/sbus"); + fword("find-device"); + } + PUSH(range->slot); + fword("encode-int"); + if (notfirst) + fword("encode+"); + PUSH(range->type); + fword("encode-int"); + fword("encode+"); + PUSH(range->base >> 32); + fword("encode-int"); + fword("encode+"); + PUSH(range->base & 0xffffffff); + fword("encode-int"); + fword("encode+"); + PUSH(range->size); + fword("encode-int"); + fword("encode+"); +} + +static int +ob_sbus_init_ss5(void) +{ + unsigned int slot; + int notfirst = 0; + + for (slot = 0; slot < SBUS_SLOTS; slot++) { + if (sbus_offsets_ss5[slot].size > 0) + ob_add_sbus_range(&sbus_offsets_ss5[slot], notfirst++); + } + push_str("ranges"); + fword("property"); + + for (slot = 0; slot < SBUS_SLOTS; slot++) { + if (sbus_offsets_ss5[slot].size > 0) + sbus_probe_slot_ss5(slot, sbus_offsets_ss5[slot].base); + } + + return 0; +} + +static int +ob_sbus_init_ss10(void) +{ + unsigned int slot; + int notfirst = 0; + + for (slot = 0; slot < SBUS_SLOTS; slot++) { + if (sbus_offsets_ss10[slot].size > 0) + ob_add_sbus_range(&sbus_offsets_ss10[slot], notfirst++); + } + push_str("ranges"); + fword("property"); + + for (slot = 0; slot < SBUS_SLOTS; slot++) { + if (sbus_offsets_ss10[slot].size > 0) + sbus_probe_slot_ss10(slot, sbus_offsets_ss10[slot].base); + } + + return 0; +} + +static int +ob_sbus_init_ss600mp(void) +{ + unsigned int slot; + int notfirst = 0; + + for (slot = 0; slot < SBUS_SLOTS; slot++) { + if (sbus_offsets_ss10[slot].size > 0) + ob_add_sbus_range(&sbus_offsets_ss10[slot], notfirst++); + } + push_str("ranges"); + fword("property"); + + for (slot = 0; slot < SBUS_SLOTS; slot++) { + if (sbus_offsets_ss10[slot].size > 0) + sbus_probe_slot_ss600mp(slot, sbus_offsets_ss10[slot].base); + } + + return 0; +} + +int ob_sbus_init(uint64_t base, int machine_id) +{ + ob_sbus_node_init(base); + + switch (machine_id) { + case 66: + return ob_sbus_init_ss600mp(); + case 64 ... 65: + return ob_sbus_init_ss10(); + case 32 ... 63: + return ob_sbus_init_ss5(); + default: + return -1; + } +} diff --git a/qemu/roms/openbios/drivers/sbus.fs b/qemu/roms/openbios/drivers/sbus.fs new file mode 100644 index 000000000..b84a3ac72 --- /dev/null +++ b/qemu/roms/openbios/drivers/sbus.fs @@ -0,0 +1,94 @@ +\ ------------------------------------------------------------------------- +\ SBus encode/decode unit +\ ------------------------------------------------------------------------- + +: decode-unit-sbus ( str len -- id lun ) + ascii , left-split + ( addr-R len-R addr-L len-L ) + parse-hex + -rot parse-hex + swap +; + +: encode-unit-sbus ( id lun -- str len) + swap + pocket tohexstr + " ," pocket tmpstrcat >r + rot pocket tohexstr r> tmpstrcat drop +; + +\ Convert sbus unit (from decode-unit) to physical address using +\ sbus node ranges property + +: sbus-unit>addr ( phys.lo phys.hi -- phys.lo phys.hi -1 | 0 ) + " ranges" my-self ihandle>phandle + get-package-property 0= if ( phys.lo phys.hi prop prop-len ) + begin + 2over swap drop 0 swap \ force phys.lo to zero for matching + 2swap ( unit.phys.lo unit.phys.hi 0 phys.hi res prop prop-len ) + 0 -rot ( unit.phys.lo unit.phys.hi res prop prop-len ) + 2 0 do + decode-int -rot >r >r ( unit.phys.lo unit.phys.hi res phys.x -- R: prop-len prop ) + rot ( unit.phys.lo res phys.x phys.hi ) + = if + 1+ + then ( unit.phys.lo res ) + r> r> ( unit.phys.lo res prop prop-len ) + loop + rot ( prop prop-len res ) + 2 = if \ did we match the unit address? if so, return the physical address + decode-phys 2swap 2drop 2swap ( unit.phys.lo unit.phys.hi phys.lo phys.hi ) + drop 0 d+ \ force unit.phys.hi to zero and add address for final offset + -1 exit + else + decode-phys 2drop decode-int drop \ drop the size and carry on + then + dup 0= until + 2drop 2drop 0 + then +; + +: map-in-sbus ( phys.lo phys.hi size ) + >r sbus-unit>addr if + r@ " map-in" $call-parent + then + r> drop +; + +: map-out-sbus ( virt size ) + " map-out" $call-parent +; + +\ ------------------------------------------------------------------------- +\ SBus probe +\ ------------------------------------------------------------------------- + +: probe-self-sbus ( arg-adr arg-len reg-adr reg-len fcode-adr fcode-len -- ) + + 0 to probe-fcode? + + ['] decode-unit-sbus catch if + 2drop 2drop 2drop 2drop + exit + then + + h# 10000 map-in-sbus + + dup cpeek if + dup h# f1 = swap h# fd = or if + new-device + >r set-args r> + dup 1 byte-load + finish-device + + -1 to probe-fcode? + else + nip nip nip nip + ." Invalid FCode start byte" cr + then + else + nip nip nip nip + then + + h# 10000 map-out-sbus +; diff --git a/qemu/roms/openbios/drivers/scsi.h b/qemu/roms/openbios/drivers/scsi.h new file mode 100644 index 000000000..cb975fc70 --- /dev/null +++ b/qemu/roms/openbios/drivers/scsi.h @@ -0,0 +1,262 @@ +#ifndef _LINUX_SCSI_H +#define _LINUX_SCSI_H + +/* + * This header file contains public constants and structures used by + * the scsi code for linux. + */ + +/* + $Header: /usr/src/linux/include/linux/RCS/scsi.h,v 1.3 1993/09/24 12:20:33 drew Exp $ + + For documentation on the OPCODES, MESSAGES, and SENSE values, + please consult the SCSI standard. + +*/ + +/* + * SCSI opcodes + */ + +#define TEST_UNIT_READY 0x00 +#define REZERO_UNIT 0x01 +#define REQUEST_SENSE 0x03 +#define FORMAT_UNIT 0x04 +#define READ_BLOCK_LIMITS 0x05 +#define REASSIGN_BLOCKS 0x07 +#define READ_6 0x08 +#define WRITE_6 0x0a +#define SEEK_6 0x0b +#define READ_REVERSE 0x0f +#define WRITE_FILEMARKS 0x10 +#define SPACE 0x11 +#define INQUIRY 0x12 +#define RECOVER_BUFFERED_DATA 0x14 +#define MODE_SELECT 0x15 +#define RESERVE 0x16 +#define RELEASE 0x17 +#define COPY 0x18 +#define ERASE 0x19 +#define MODE_SENSE 0x1a +#define START_STOP 0x1b +#define RECEIVE_DIAGNOSTIC 0x1c +#define SEND_DIAGNOSTIC 0x1d +#define ALLOW_MEDIUM_REMOVAL 0x1e + +#define SET_WINDOW 0x24 +#define READ_CAPACITY 0x25 +#define READ_10 0x28 +#define WRITE_10 0x2a +#define SEEK_10 0x2b +#define WRITE_VERIFY 0x2e +#define VERIFY 0x2f +#define SEARCH_HIGH 0x30 +#define SEARCH_EQUAL 0x31 +#define SEARCH_LOW 0x32 +#define SET_LIMITS 0x33 +#define PRE_FETCH 0x34 +#define READ_POSITION 0x34 +#define SYNCHRONIZE_CACHE 0x35 +#define LOCK_UNLOCK_CACHE 0x36 +#define READ_DEFECT_DATA 0x37 +#define MEDIUM_SCAN 0x38 +#define COMPARE 0x39 +#define COPY_VERIFY 0x3a +#define WRITE_BUFFER 0x3b +#define READ_BUFFER 0x3c +#define UPDATE_BLOCK 0x3d +#define READ_LONG 0x3e +#define WRITE_LONG 0x3f +#define CHANGE_DEFINITION 0x40 +#define WRITE_SAME 0x41 +#define READ_TOC 0x43 +#define LOG_SELECT 0x4c +#define LOG_SENSE 0x4d +#define MODE_SELECT_10 0x55 +#define RESERVE_10 0x56 +#define RELEASE_10 0x57 +#define MODE_SENSE_10 0x5a +#define PERSISTENT_RESERVE_IN 0x5e +#define PERSISTENT_RESERVE_OUT 0x5f +#define REPORT_LUNS 0xa0 +#define MOVE_MEDIUM 0xa5 +#define READ_12 0xa8 +#define WRITE_12 0xaa +#define WRITE_VERIFY_12 0xae +#define SEARCH_HIGH_12 0xb0 +#define SEARCH_EQUAL_12 0xb1 +#define SEARCH_LOW_12 0xb2 +#define READ_ELEMENT_STATUS 0xb8 +#define SEND_VOLUME_TAG 0xb6 +#define WRITE_LONG_2 0xea +#define READ_16 0x88 +#define WRITE_16 0x8a +#define VERIFY_16 0x8f +#define SERVICE_ACTION_IN 0x9e +/* values for service action in */ +#define SAI_READ_CAPACITY_16 0x10 + +#define SCSI_RETRY_10(c) ((c) == READ_6 || (c) == WRITE_6 || (c) == SEEK_6) + +/* + * SCSI Architecture Model (SAM) Status codes. Taken from SAM-3 draft + * T10/1561-D Revision 4 Draft dated 7th November 2002. + */ +#define SAM_STAT_GOOD 0x00 +#define SAM_STAT_CHECK_CONDITION 0x02 +#define SAM_STAT_CONDITION_MET 0x04 +#define SAM_STAT_BUSY 0x08 +#define SAM_STAT_INTERMEDIATE 0x10 +#define SAM_STAT_INTERMEDIATE_CONDITION_MET 0x14 +#define SAM_STAT_RESERVATION_CONFLICT 0x18 +#define SAM_STAT_COMMAND_TERMINATED 0x22 /* obsolete in SAM-3 */ +#define SAM_STAT_TASK_SET_FULL 0x28 +#define SAM_STAT_ACA_ACTIVE 0x30 +#define SAM_STAT_TASK_ABORTED 0x40 + +/* + * Status codes + */ + +#define GOOD 0x00 +#define CHECK_CONDITION 0x01 +#define CONDITION_GOOD 0x02 +#define BUSY 0x04 +#define INTERMEDIATE_GOOD 0x08 +#define INTERMEDIATE_C_GOOD 0x0a +#define RESERVATION_CONFLICT 0x0c +#define COMMAND_TERMINATED 0x11 +#define QUEUE_FULL 0x14 + +#define STATUS_MASK 0x3e + +/* + * SENSE KEYS + */ + +#define NO_SENSE 0x00 +#define RECOVERED_ERROR 0x01 +#define NOT_READY 0x02 +#define MEDIUM_ERROR 0x03 +#define HARDWARE_ERROR 0x04 +#define ILLEGAL_REQUEST 0x05 +#define UNIT_ATTENTION 0x06 +#define DATA_PROTECT 0x07 +#define BLANK_CHECK 0x08 +#define COPY_ABORTED 0x0a +#define ABORTED_COMMAND 0x0b +#define VOLUME_OVERFLOW 0x0d +#define MISCOMPARE 0x0e + + +/* + * DEVICE TYPES + */ + +#define TYPE_DISK 0x00 +#define TYPE_TAPE 0x01 +#define TYPE_PRINTER 0x02 +#define TYPE_PROCESSOR 0x03 /* HP scanners use this */ +#define TYPE_WORM 0x04 /* Treated as ROM by our system */ +#define TYPE_ROM 0x05 +#define TYPE_SCANNER 0x06 +#define TYPE_MOD 0x07 /* Magneto-optical disk - + * - treated as TYPE_DISK */ +#define TYPE_MEDIUM_CHANGER 0x08 +#define TYPE_COMM 0x09 /* Communications device */ +#define TYPE_ENCLOSURE 0x0d /* Enclosure Services Device */ +#define TYPE_NO_LUN 0x7f + +/* + * standard mode-select header prepended to all mode-select commands + * + * moved here from cdrom.h -- kraxel + */ + +struct ccs_modesel_head +{ + uint8_t _r1; /* reserved */ + uint8_t medium; /* device-specific medium type */ + uint8_t _r2; /* reserved */ + uint8_t block_desc_length; /* block descriptor length */ + uint8_t density; /* device-specific density code */ + uint8_t number_blocks_hi; /* number of blocks in this block desc */ + uint8_t number_blocks_med; + uint8_t number_blocks_lo; + uint8_t _r3; + uint8_t block_length_hi; /* block length for blocks in this desc */ + uint8_t block_length_med; + uint8_t block_length_lo; +}; + +/* + * MESSAGE CODES + */ + +#define COMMAND_COMPLETE 0x00 +#define EXTENDED_MESSAGE 0x01 +#define EXTENDED_MODIFY_DATA_POINTER 0x00 +#define EXTENDED_SDTR 0x01 +#define EXTENDED_EXTENDED_IDENTIFY 0x02 /* SCSI-I only */ +#define EXTENDED_WDTR 0x03 +#define SAVE_POINTERS 0x02 +#define RESTORE_POINTERS 0x03 +#define DISCONNECT 0x04 +#define INITIATOR_ERROR 0x05 +#define ABORT 0x06 +#define MESSAGE_REJECT 0x07 +#define NOP 0x08 +#define MSG_PARITY_ERROR 0x09 +#define LINKED_CMD_COMPLETE 0x0a +#define LINKED_FLG_CMD_COMPLETE 0x0b +#define BUS_DEVICE_RESET 0x0c + +#define INITIATE_RECOVERY 0x0f /* SCSI-II only */ +#define RELEASE_RECOVERY 0x10 /* SCSI-II only */ + +#define SIMPLE_QUEUE_TAG 0x20 +#define HEAD_OF_QUEUE_TAG 0x21 +#define ORDERED_QUEUE_TAG 0x22 + +/* + * Here are some scsi specific ioctl commands which are sometimes useful. + */ +/* These are a few other constants only used by scsi devices */ +/* Note that include/linux/cdrom.h also defines IOCTL 0x5300 - 0x5395 */ + +#define SCSI_IOCTL_GET_IDLUN 0x5382 /* conflicts with CDROMAUDIOBUFSIZ */ + +/* Used to turn on and off tagged queuing for scsi devices */ + +#define SCSI_IOCTL_TAGGED_ENABLE 0x5383 +#define SCSI_IOCTL_TAGGED_DISABLE 0x5384 + +/* Used to obtain the host number of a device. */ +#define SCSI_IOCTL_PROBE_HOST 0x5385 + +/* Used to get the bus number for a device */ +#define SCSI_IOCTL_GET_BUS_NUMBER 0x5386 + +/* Used to get the PCI location of a device */ +#define SCSI_IOCTL_GET_PCI 0x5387 + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-indent-level: 4 + * c-brace-imaginary-offset: 0 + * c-brace-offset: -4 + * c-argdecl-indent: 4 + * c-label-offset: -4 + * c-continued-statement-offset: 4 + * c-continued-brace-offset: 0 + * indent-tabs-mode: nil + * tab-width: 8 + * End: + */ + +#endif diff --git a/qemu/roms/openbios/drivers/tcx.fs b/qemu/roms/openbios/drivers/tcx.fs new file mode 100644 index 000000000..af8991fd0 --- /dev/null +++ b/qemu/roms/openbios/drivers/tcx.fs @@ -0,0 +1,280 @@ +\ +\ Fcode payload for QEMU TCX graphics card +\ +\ This is the Forth source for an Fcode payload to initialise +\ the QEMU TCX graphics card. +\ +\ (C) Copyright 2013 Mark Cave-Ayland +\ + +fcode-version3 + +\ +\ Instead of using fixed values for the framebuffer address and the width +\ and height, grab the ones passed in by QEMU/generated by OpenBIOS +\ + +: (find-xt) \ ( str len -- xt | -1 ) + $find if + exit + else + 2drop + -1 + then +; + +: (is-openbios) \ ( -- true | false ) + " openbios-video-width" (find-xt) -1 <> if + -1 + else + 0 + then +; + +" openbios-video-width" (find-xt) cell+ value openbios-video-width-xt +" openbios-video-height" (find-xt) cell+ value openbios-video-height-xt +" depth-bits" (find-xt) cell+ value depth-bits-xt +" line-bytes" (find-xt) cell+ value line-bytes-xt + +: openbios-video-width + (is-openbios) if + openbios-video-width-xt @ + else + h# 400 + then +; + +: openbios-video-height + (is-openbios) if + openbios-video-height-xt @ + else + h# 300 + then +; + +: depth-bits + (is-openbios) if + depth-bits-xt @ + else + h# 8 + then +; + +: line-bytes + (is-openbios) if + line-bytes-xt @ + else + h# 400 + then +; + +\ +\ Registers +\ + +h# 0 constant tcx-off-rom +h# 10000 constant /tcx-off-rom + +h# 200000 constant tcx-off-cmap +h# 4000 constant /tcx-off-cmap-24 +h# 4 constant /tcx-off-cmap-8 + +h# 240000 constant tcx-off-dhc +h# 4000 constant /tcx-off-dhc-24 +h# 4 constant /tcx-off-dhc-8 + +h# 280000 constant tcx-off-alt +h# 8000 constant /tcx-off-alt-24 +h# 1 constant /tcx-off-alt-8 + +h# 301000 constant tcx-off-thc-24 +h# 300000 constant tcx-off-thc-8 +h# 1000 constant /tcx-off-thc-24 +h# 81c constant /tcx-off-thc-8 + +h# 701000 constant tcx-off-tec +h# 1000 constant /tcx-off-tec + +h# 800000 constant tcx-off-dfb8 +h# 100000 constant /tcx-off-dfb8 + +h# 2000000 constant tcx-off-dfb24 +h# 400000 constant /tcx-off-dfb24-24 +h# 1 constant /tcx-off-dfb24-8 + +h# 4000000 constant tcx-off-stip +h# 800000 constant /tcx-off-stip + +h# 6000000 constant tcx-off-blit +h# 800000 constant /tcx-off-blit + +h# a000000 constant tcx-off-rdfb32 +h# 400000 constant /tcx-off-rdfb32-24 +h# 1 constant /tcx-off-rdfb32-8 + +h# c000000 constant tcx-off-rstip +h# 800000 constant /tcx-off-rstip-24 +h# 1 constant /tcx-off-rstip-8 + +h# e000000 constant tcx-off-rblit +h# 800000 constant /tcx-off-rblit-24 +h# 1 constant /tcx-off-rblit-8 + +: >tcx-reg-spec ( offset size -- encoded-reg ) + >r 0 my-address d+ my-space encode-phys r> encode-int encode+ +; + +: tcx-8bit-reg + \ WARNING: order is important (at least to Solaris) + tcx-off-dfb8 /tcx-off-dfb8 >tcx-reg-spec + tcx-off-dfb24 /tcx-off-dfb24-8 >tcx-reg-spec encode+ + tcx-off-stip /tcx-off-stip >tcx-reg-spec encode+ + tcx-off-blit /tcx-off-blit >tcx-reg-spec encode+ + tcx-off-rdfb32 /tcx-off-rdfb32-8 >tcx-reg-spec encode+ + tcx-off-rstip /tcx-off-rstip-8 >tcx-reg-spec encode+ + tcx-off-rblit /tcx-off-rblit-8 >tcx-reg-spec encode+ + tcx-off-tec /tcx-off-tec >tcx-reg-spec encode+ + tcx-off-cmap /tcx-off-cmap-8 >tcx-reg-spec encode+ + tcx-off-thc-8 /tcx-off-thc-8 >tcx-reg-spec encode+ + tcx-off-rom /tcx-off-rom >tcx-reg-spec encode+ + tcx-off-dhc /tcx-off-dhc-8 >tcx-reg-spec encode+ + tcx-off-alt /tcx-off-alt-8 >tcx-reg-spec encode+ + " reg" property +; + +: tcx-24bit-reg + \ WARNING: order is important (at least to Solaris) + tcx-off-dfb8 /tcx-off-dfb8 >tcx-reg-spec + tcx-off-dfb24 /tcx-off-dfb24-24 >tcx-reg-spec encode+ + tcx-off-stip /tcx-off-stip >tcx-reg-spec encode+ + tcx-off-blit /tcx-off-blit >tcx-reg-spec encode+ + tcx-off-rdfb32 /tcx-off-rdfb32-24 >tcx-reg-spec encode+ + tcx-off-rstip /tcx-off-rstip-24 >tcx-reg-spec encode+ + tcx-off-rblit /tcx-off-rblit-24 >tcx-reg-spec encode+ + tcx-off-tec /tcx-off-tec >tcx-reg-spec encode+ + tcx-off-cmap /tcx-off-cmap-24 >tcx-reg-spec encode+ + tcx-off-thc-24 /tcx-off-thc-24 >tcx-reg-spec encode+ + tcx-off-rom /tcx-off-rom >tcx-reg-spec encode+ + tcx-off-dhc /tcx-off-dhc-24 >tcx-reg-spec encode+ + tcx-off-alt /tcx-off-alt-24 >tcx-reg-spec encode+ + " reg" property +; + +: do-map-in ( offset size -- virt ) + >r my-space r> " map-in" $call-parent +; + +: do-map-out ( virt size ) + " map-out" $call-parent +; + +\ +\ DAC +\ + +-1 value tcx-dac +-1 value /tcx-dac +-1 value fb-addr + +: dac! ( data reg# -- ) + >r dup 2dup bljoin r> tcx-dac + l! +; + +external + +: color! ( r g b c# -- ) + 0 dac! ( r g b ) + swap rot ( b g r ) + 4 dac! ( b g ) + 4 dac! ( b ) + 4 dac! ( ) +; + +headerless + +\ +\ Mapping +\ + +: dac-map + tcx-off-cmap /tcx-dac do-map-in to tcx-dac +; + +: fb-map + tcx-off-dfb8 h# c0000 do-map-in to fb-addr +; + +: map-regs + dac-map fb-map +; + +\ +\ Installation +\ + +" SUNW,tcx" device-name +" display" device-type + +: qemu-tcx-driver-install ( -- ) + tcx-dac -1 = if + map-regs + + \ Initial pallette taken from Sun's "Writing FCode Programs" + h# ff h# ff h# ff h# 0 color! \ Background white + h# 0 h# 0 h# 0 h# ff color! \ Foreground black + h# 64 h# 41 h# b4 h# 1 color! \ SUN-blue logo + + fb-addr to frame-buffer-adr + default-font set-font + + \ Sun TCX adapters don't have an address property, but it is useful for + \ OpenBIOS developers. Unfortunately NetBSD SPARC32 has a bug that causes + \ it to fail initialising TCX if the address property is present; so work + \ around this by adding an underscore prefix + frame-buffer-adr encode-int " _address" property + + openbios-video-width openbios-video-height over char-width / over char-height / + fb8-install + then +; + +: qemu-tcx-driver-init + + \ Handle differences between 8-bit/24-bit mode + depth-bits 8 = if + tcx-8bit-reg + /tcx-off-cmap-8 to /tcx-dac + " true" encode-string " tcx-8-bit" property + else + tcx-24bit-reg + /tcx-off-cmap-24 to /tcx-dac + + \ Even with a 24-bit enabled TCX card, the control plane is + \ used in 8-bit mode. So force the video subsystem into 8-bit + \ mode before initialisation. + 8 depth-bits-xt ! + openbios-video-width line-bytes-xt ! + then + + h# 1d encode-int " vbporch" property + h# a0 encode-int " hbporch" property + h# 06 encode-int " vsync" property + h# 88 encode-int " hsync" property + h# 03 encode-int " vfporch" property + h# 18 encode-int " hfporch" property + h# 03dfd240 encode-int " pixfreq" property + h# 3c encode-int " vfreq" property + + openbios-video-height encode-int " height" property + openbios-video-width encode-int " width" property + line-bytes encode-int " linebytes" property + + h# 39 encode-int 0 encode-int encode+ " intr" property + 5 encode-int " interrupts" property + + ['] qemu-tcx-driver-install is-install +; + +qemu-tcx-driver-init + +end0 diff --git a/qemu/roms/openbios/drivers/timer.c b/qemu/roms/openbios/drivers/timer.c new file mode 100644 index 000000000..d6794ae9c --- /dev/null +++ b/qemu/roms/openbios/drivers/timer.c @@ -0,0 +1,100 @@ +/* + * OpenBIOS native timer driver + * + * (C) 2004 Stefan Reinauer <stepan@openbios.org> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#include "config.h" +#include "drivers/drivers.h" +#include "timer.h" +#include "asm/io.h" + +#if defined(CONFIG_X86) || defined(CONFIG_AMD64) + +void setup_timers(void) +{ + /* nothing to do */ +} + +static void load_timer2(unsigned int ticks) +{ + /* Set up the timer gate, turn off the speaker */ + outb((inb(PPC_PORTB) & ~PPCB_SPKR) | PPCB_T2GATE, PPC_PORTB); + outb(TIMER2_SEL | WORD_ACCESS | MODE0 | BINARY_COUNT, + TIMER_MODE_PORT); + outb(ticks & 0xFF, TIMER2_PORT); + outb(ticks >> 8, TIMER2_PORT); +} + +void udelay(unsigned int usecs) +{ + load_timer2((usecs * TICKS_PER_MS) / 1000); + while ((inb(PPC_PORTB) & PPCB_T2OUT) == 0); +} + +unsigned long currticks(void) +{ + static unsigned long totticks = 0UL; /* High resolution */ + unsigned long ticks = 0; + unsigned char portb = inb(PPC_PORTB); + + /* + * Read the timer, and hope it hasn't wrapped around + * (call this again within 54ms), then restart it + */ + outb(TIMER2_SEL | LATCH_COUNT, TIMER_MODE_PORT); + ticks = inb(TIMER2_PORT); + ticks |= inb(TIMER2_PORT) << 8; + outb(TIMER2_SEL | WORD_ACCESS | MODE0 | BINARY_COUNT, + TIMER_MODE_PORT); + outb(0, TIMER2_PORT); + outb(0, TIMER2_PORT); + + /* + * Check if the timer was running. If not, + * result is rubbish and need to start it + */ + if (portb & PPCB_T2GATE) { + totticks += (0x10000 - ticks); + } else { + /* Set up the timer gate, turn off the speaker */ + outb((portb & ~PPCB_SPKR) | PPCB_T2GATE, PPC_PORTB); + } + return totticks / TICKS_PER_MS; +} +#endif + +#ifdef CONFIG_PPC + +void setup_timers(void) +{ + /* nothing to do */ +} + +/* + * TODO: pass via lb table + */ +unsigned long timer_freq = 10000000 / 4; + +void udelay(unsigned int usecs) +{ + unsigned long ticksperusec = timer_freq / 1000000; + _wait_ticks(ticksperusec * usecs); +} + +#endif + +void ndelay(unsigned int nsecs) +{ + udelay((nsecs + 999) / 1000); +} + +void mdelay(unsigned int msecs) +{ + udelay(msecs * 1000); +} diff --git a/qemu/roms/openbios/drivers/timer.h b/qemu/roms/openbios/drivers/timer.h new file mode 100644 index 000000000..7e86db3fa --- /dev/null +++ b/qemu/roms/openbios/drivers/timer.h @@ -0,0 +1,62 @@ +/* Taken from Etherboot */ +/* Defines for routines to implement a low-overhead timer for drivers */ + + /* + * 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 2, or (at + * your option) any later version. + */ + +#ifndef TIMER_H +#define TIMER_H + +/* Ports for the 8254 timer chip */ +#define TIMER2_PORT 0x42 +#define TIMER_MODE_PORT 0x43 + +/* Meaning of the mode bits */ +#define TIMER0_SEL 0x00 +#define TIMER1_SEL 0x40 +#define TIMER2_SEL 0x80 +#define READBACK_SEL 0xC0 + +#define LATCH_COUNT 0x00 +#define LOBYTE_ACCESS 0x10 +#define HIBYTE_ACCESS 0x20 +#define WORD_ACCESS 0x30 + +#define MODE0 0x00 +#define MODE1 0x02 +#define MODE2 0x04 +#define MODE3 0x06 +#define MODE4 0x08 +#define MODE5 0x0A + +#define BINARY_COUNT 0x00 +#define BCD_COUNT 0x01 + +/* Timers tick over at this rate */ +#define CLOCK_TICK_RATE 1193180U +#define TICKS_PER_MS (CLOCK_TICK_RATE/1000) + +/* Parallel Peripheral Controller Port B */ +#define PPC_PORTB 0x61 + +/* Meaning of the port bits */ +#define PPCB_T2OUT 0x20 /* Bit 5 */ +#define PPCB_SPKR 0x02 /* Bit 1 */ +#define PPCB_T2GATE 0x01 /* Bit 0 */ + +extern void ndelay(unsigned int nsecs); +extern void udelay(unsigned int usecs); +extern void mdelay(unsigned int msecs); +extern unsigned long currticks(void); +extern unsigned long get_timer_freq(void); + +/* arch/ppc/timebase.S */ +void _wait_ticks(unsigned long nticks); + +#define TICKS_PER_SEC 1000 + +#endif /* TIMER_H */ diff --git a/qemu/roms/openbios/drivers/usb.c b/qemu/roms/openbios/drivers/usb.c new file mode 100644 index 000000000..c6e37174e --- /dev/null +++ b/qemu/roms/openbios/drivers/usb.c @@ -0,0 +1,587 @@ +/* + * Driver for USB ported from CoreBoot + * + * Copyright (C) 2014 BALATON Zoltan + * + * This file was part of the libpayload project. + * + * Copyright (C) 2008-2010 coresystems GmbH + * + * 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. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + */ + +#include "config.h" +#include "drivers/usb.h" +#include "usb.h" +#include "timer.h" +#include "libc/byteorder.h" + +hci_t *usb_hcs = 0; + +static void usb_nop_init (usbdev_t *dev); + +static void +usb_nop_destroy (usbdev_t *dev) +{ + if (dev->descriptor != 0) + free (dev->descriptor); + usb_nop_init (dev); + dev->address = -1; + dev->hub = -1; + dev->port = -1; +} + +static void +usb_nop_poll (usbdev_t *dev) +{ + return; +} + +static void +usb_nop_init (usbdev_t *dev) +{ + dev->descriptor = 0; + dev->destroy = usb_nop_destroy; + dev->poll = usb_nop_poll; +} + +hci_t * +new_controller (void) +{ + hci_t *controller = malloc (sizeof (hci_t)); + + if (controller) { + /* atomic */ + controller->next = usb_hcs; + usb_hcs = controller; + /* atomic end */ + } + + return controller; +} + +void +detach_controller (hci_t *controller) +{ + if (controller == NULL) + return; + if (usb_hcs == controller) { + usb_hcs = controller->next; + } else { + hci_t *it = usb_hcs; + while (it != NULL) { + if (it->next == controller) { + it->next = controller->next; + return; + } + it = it->next; + } + } +} + +/** + * Shut down all controllers + */ +int +usb_exit (void) +{ + while (usb_hcs != NULL) { + usb_hcs->shutdown(usb_hcs); + } + return 0; +} + +/** + * Polls all hubs on all USB controllers, to find out about device changes + */ +void +usb_poll (void) +{ + if (usb_hcs == 0) + return; + hci_t *controller = usb_hcs; + while (controller != NULL) { + int i; + for (i = 0; i < 128; i++) { + if (controller->devices[i] != 0) { + controller->devices[i]->poll (controller->devices[i]); + } + } + controller = controller->next; + } +} + +void +init_device_entry (hci_t *controller, int i) +{ + if (controller->devices[i] != 0) + usb_debug("warning: device %d reassigned?\n", i); + controller->devices[i] = malloc(sizeof(usbdev_t)); + controller->devices[i]->controller = controller; + controller->devices[i]->address = -1; + controller->devices[i]->hub = -1; + controller->devices[i]->port = -1; + controller->devices[i]->init = usb_nop_init; + controller->devices[i]->init (controller->devices[i]); +} + +void +set_feature (usbdev_t *dev, int endp, int feature, int rtype) +{ + dev_req_t dr; + + dr.bmRequestType = rtype; + dr.data_dir = host_to_device; + dr.bRequest = SET_FEATURE; + dr.wValue = __cpu_to_le16(feature); + dr.wIndex = __cpu_to_le16(endp); + dr.wLength = 0; + dev->controller->control (dev, OUT, sizeof (dr), &dr, 0, 0); +} + +void +get_status (usbdev_t *dev, int intf, int rtype, int len, void *data) +{ + dev_req_t dr; + + dr.bmRequestType = rtype; + dr.data_dir = device_to_host; + dr.bRequest = GET_STATUS; + dr.wValue = 0; + dr.wIndex = __cpu_to_le16(intf); + dr.wLength = __cpu_to_le16(len); + dev->controller->control (dev, IN, sizeof (dr), &dr, len, data); +} + +u8 * +get_descriptor (usbdev_t *dev, unsigned char bmRequestType, int descType, + int descIdx, int langID) +{ + u8 buf[8]; + u8 *result; + dev_req_t dr; + int size; + + dr.bmRequestType = bmRequestType; + dr.data_dir = device_to_host; // always like this for descriptors + dr.bRequest = GET_DESCRIPTOR; + dr.wValue = __cpu_to_le16((descType << 8) | descIdx); + dr.wIndex = __cpu_to_le16(langID); + dr.wLength = __cpu_to_le16(8); + if (dev->controller->control (dev, IN, sizeof (dr), &dr, 8, buf)) { + usb_debug ("getting descriptor size (type %x) failed\n", + descType); + } + + if (descType == 1) { + device_descriptor_t *dd = (device_descriptor_t *) buf; + usb_debug ("maxPacketSize0: %x\n", dd->bMaxPacketSize0); + if (dd->bMaxPacketSize0 != 0) + dev->endpoints[0].maxpacketsize = dd->bMaxPacketSize0; + } + + /* special case for configuration descriptors: they carry all their + subsequent descriptors with them, and keep the entire size at a + different location */ + size = buf[0]; + if (buf[1] == 2) { + int realsize = __le16_to_cpu(((unsigned short *) (buf + 2))[0]); + size = realsize; + } + result = malloc (size); + memset (result, 0, size); + dr.wLength = __cpu_to_le16(size); + if (dev->controller-> + control (dev, IN, sizeof (dr), &dr, size, result)) { + usb_debug ("getting descriptor (type %x, size %x) failed\n", + descType, size); + } + + return result; +} + +void +set_configuration (usbdev_t *dev) +{ + dev_req_t dr; + + dr.bmRequestType = 0; + dr.bRequest = SET_CONFIGURATION; + dr.wValue = __cpu_to_le16(dev->configuration[5]); + dr.wIndex = 0; + dr.wLength = 0; + dev->controller->control (dev, OUT, sizeof (dr), &dr, 0, 0); +} + +int +clear_feature (usbdev_t *dev, int endp, int feature, int rtype) +{ + dev_req_t dr; + + dr.bmRequestType = rtype; + dr.data_dir = host_to_device; + dr.bRequest = CLEAR_FEATURE; + dr.wValue = __cpu_to_le16(feature); + dr.wIndex = __cpu_to_le16(endp); + dr.wLength = 0; + return dev->controller->control (dev, OUT, sizeof (dr), &dr, 0, 0); +} + +int +clear_stall (endpoint_t *ep) +{ + usbdev_t *dev = ep->dev; + int endp = ep->endpoint; + int rtype = gen_bmRequestType (host_to_device, standard_type, + endp ? endp_recp : dev_recp); + + int ret = clear_feature (dev, endp, ENDPOINT_HALT, rtype); + ep->toggle = 0; + return ret; +} + +/* returns free address or -1 */ +static int +get_free_address (hci_t *controller) +{ + int i; + for (i = 1; i < 128; i++) { + if (controller->devices[i] == 0) + return i; + } + usb_debug ("no free address found\n"); + return -1; // no free address +} + +int +generic_set_address (hci_t *controller, int speed, int hubport, int hubaddr) +{ + int adr = get_free_address (controller); // address to set + dev_req_t dr; + + memset (&dr, 0, sizeof (dr)); + dr.data_dir = host_to_device; + dr.req_type = standard_type; + dr.req_recp = dev_recp; + dr.bRequest = SET_ADDRESS; + dr.wValue = __cpu_to_le16(adr); + dr.wIndex = 0; + dr.wLength = 0; + + init_device_entry(controller, adr); + usbdev_t *dev = controller->devices[adr]; + // dummy values for registering the address + dev->address = 0; + dev->hub = hubaddr; + dev->port = hubport; + dev->speed = speed; + dev->endpoints[0].dev = dev; + dev->endpoints[0].endpoint = 0; + dev->endpoints[0].maxpacketsize = 8; + dev->endpoints[0].toggle = 0; + dev->endpoints[0].direction = SETUP; + mdelay (50); + if (dev->controller->control (dev, OUT, sizeof (dr), &dr, 0, 0)) { + return -1; + } + mdelay (50); + + return adr; +} + +/* Normalize bInterval to log2 of microframes */ +static int +usb_decode_interval(const int speed, const endpoint_type type, const unsigned char bInterval) +{ +#define LOG2(a) ((sizeof(unsigned) << 3) - __builtin_clz(a) - 1) + switch (speed) { + case LOW_SPEED: + switch (type) { + case ISOCHRONOUS: case INTERRUPT: + return LOG2(bInterval) + 3; + default: + return 0; + } + case FULL_SPEED: + switch (type) { + case ISOCHRONOUS: + return (bInterval - 1) + 3; + case INTERRUPT: + return LOG2(bInterval) + 3; + default: + return 0; + } + case HIGH_SPEED: + switch (type) { + case ISOCHRONOUS: case INTERRUPT: + return bInterval - 1; + default: + return LOG2(bInterval); + } + case SUPER_SPEED: + switch (type) { + case ISOCHRONOUS: case INTERRUPT: + return bInterval - 1; + default: + return 0; + } + default: + return 0; + } +#undef LOG2 +} + +static int +set_address (hci_t *controller, int speed, int hubport, int hubaddr) +{ + int adr = controller->set_address(controller, speed, hubport, hubaddr); + if (adr < 0 || !controller->devices[adr]) { + usb_debug ("set_address failed\n"); + return -1; + } + configuration_descriptor_t *cd; + device_descriptor_t *dd; + + usbdev_t *dev = controller->devices[adr]; + dev->address = adr; + dev->hub = hubaddr; + dev->port = hubport; + dev->speed = speed; + dev->descriptor = get_descriptor (dev, gen_bmRequestType + (device_to_host, standard_type, dev_recp), 1, 0, 0); + dd = (device_descriptor_t *) dev->descriptor; + + usb_debug ("* found device (0x%04x:0x%04x, USB %x.%x)", + __le16_to_cpu(dd->idVendor), __le16_to_cpu(dd->idProduct), + __le16_to_cpu(dd->bcdUSB) >> 8, __le16_to_cpu(dd->bcdUSB) & 0xff); + dev->quirks = USB_QUIRK_NONE; + + usb_debug ("\ndevice has %x configurations\n", dd->bNumConfigurations); + if (dd->bNumConfigurations == 0) { + /* device isn't usable */ + usb_debug ("... no usable configuration!\n"); + dev->address = 0; + return -1; + } + + dev->configuration = get_descriptor (dev, gen_bmRequestType + (device_to_host, standard_type, dev_recp), 2, 0, 0); + cd = (configuration_descriptor_t *) dev->configuration; + interface_descriptor_t *interface = + (interface_descriptor_t *) (((char *) cd) + cd->bLength); + { + int i; + int num = cd->bNumInterfaces; + interface_descriptor_t *current = interface; + usb_debug ("device has %x interfaces\n", num); + if (num > 1) { + usb_debug ("\nNOTICE: This driver defaults to using the first interface.\n" + "This might be the wrong choice and lead to limited functionality\n" + "of the device.\n"); + /* we limit to the first interface, as there was no need to + * implement something else for the time being. If you need + * it, see the SetInterface and GetInterface functions in + * the USB specification, and adapt appropriately. + */ + num = (num > 1) ? 1 : num; + } + for (i = 0; i < num; i++) { + int j; + usb_debug (" #%x has %x endpoints, interface %x:%x, protocol %x\n", + current->bInterfaceNumber, current->bNumEndpoints, current->bInterfaceClass, current->bInterfaceSubClass, current->bInterfaceProtocol); + endpoint_descriptor_t *endp = + (endpoint_descriptor_t *) (((char *) current) + + current->bLength); + /* Skip any non-endpoint descriptor */ + if (endp->bDescriptorType != 0x05) + endp = (endpoint_descriptor_t *)(((char *)endp) + ((char *)endp)[0]); + + memset (dev->endpoints, 0, sizeof (dev->endpoints)); + dev->num_endp = 1; // 0 always exists + dev->endpoints[0].dev = dev; + dev->endpoints[0].maxpacketsize = dd->bMaxPacketSize0; + dev->endpoints[0].direction = SETUP; + dev->endpoints[0].type = CONTROL; + dev->endpoints[0].interval = usb_decode_interval(dev->speed, CONTROL, endp->bInterval); + for (j = 1; j <= current->bNumEndpoints; j++) { +#ifdef CONFIG_DEBUG_USB + static const char *transfertypes[4] = { + "control", "isochronous", "bulk", "interrupt" + }; + usb_debug (" #%x: Endpoint %x (%s), max packet size %x, type %s\n", j, endp->bEndpointAddress & 0x7f, ((endp->bEndpointAddress & 0x80) != 0) ? "in" : "out", __le16_to_cpu(endp->wMaxPacketSize), transfertypes[endp->bmAttributes]); +#endif + endpoint_t *ep = + &dev->endpoints[dev->num_endp++]; + ep->dev = dev; + ep->endpoint = endp->bEndpointAddress; + ep->toggle = 0; + ep->maxpacketsize = __le16_to_cpu(endp->wMaxPacketSize); + ep->direction = + ((endp->bEndpointAddress & 0x80) == + 0) ? OUT : IN; + ep->type = endp->bmAttributes; + ep->interval = usb_decode_interval(dev->speed, ep->type, endp->bInterval); + endp = (endpoint_descriptor_t + *) (((char *) endp) + endp->bLength); + } + current = (interface_descriptor_t *) endp; + } + } + + if (controller->finish_device_config && + controller->finish_device_config(dev)) + return adr; /* Device isn't configured correctly, + only control transfers may work. */ + + set_configuration(dev); + + int class = dd->bDeviceClass; + if (class == 0) + class = interface->bInterfaceClass; + + usb_debug(", class: "); + switch (class) { + case audio_device: + usb_debug("audio\n"); + break; + case comm_device: + usb_debug("communication\n"); + break; + case hid_device: + usb_debug ("HID\n"); +#ifdef CONFIG_USB_HID + controller->devices[adr]->init = usb_hid_init; + return adr; +#else + usb_debug ("NOTICE: USB HID support not compiled in\n"); +#endif + break; + case physical_device: + usb_debug("physical\n"); + break; + case imaging_device: + usb_debug("camera\n"); + break; + case printer_device: + usb_debug("printer\n"); + break; + case msc_device: + usb_debug ("MSC\n"); +#ifdef CONFIG_USB_MSC + controller->devices[adr]->init = usb_msc_init; + return adr; +#else + usb_debug ("NOTICE: USB MSC support not compiled in\n"); +#endif + break; + case hub_device: + usb_debug ("hub\n"); +#ifdef CONFIG_USB_HUB + controller->devices[adr]->init = usb_hub_init; + return adr; +#else + usb_debug ("NOTICE: USB hub support not compiled in.\n"); +#endif + break; + case cdc_device: + usb_debug("CDC\n"); + break; + case ccid_device: + usb_debug("smartcard / CCID\n"); + break; + case security_device: + usb_debug("content security\n"); + break; + case video_device: + usb_debug("video\n"); + break; + case healthcare_device: + usb_debug("healthcare\n"); + break; + case diagnostic_device: + usb_debug("diagnostic\n"); + break; + case wireless_device: + usb_debug("wireless\n"); + break; + default: + usb_debug("unsupported class %x\n", class); + break; + } + controller->devices[adr]->init = usb_generic_init; + return adr; +} + +/* + * Should be called by the hub drivers whenever a physical detach occurs + * and can be called by usb class drivers if they are unsatisfied with a + * malfunctioning device. + */ +void +usb_detach_device(hci_t *controller, int devno) +{ + /* check if device exists, as we may have + been called yet by the usb class driver */ + if (controller->devices[devno]) { + controller->devices[devno]->destroy (controller->devices[devno]); + free(controller->devices[devno]); + controller->devices[devno] = NULL; + if (controller->destroy_device) + controller->destroy_device(controller, devno); + } +} + +int +usb_attach_device(hci_t *controller, int hubaddress, int port, int speed) +{ +#ifdef CONFIG_USB_DEBUG + static const char* speeds[] = { "full", "low", "high" }; + usb_debug ("%sspeed device\n", (speed <= 2) ? speeds[speed] : "invalid value - no"); +#endif + int newdev = set_address (controller, speed, port, hubaddress); + if (newdev == -1) + return -1; + usbdev_t *newdev_t = controller->devices[newdev]; + // determine responsible driver - current done in set_address + newdev_t->init (newdev_t); + /* init() may have called usb_detach_device() yet, so check */ + return controller->devices[newdev] ? newdev : -1; +} + +static void +usb_generic_destroy (usbdev_t *dev) +{ + if (usb_generic_remove) + usb_generic_remove(dev); +} + +void +usb_generic_init (usbdev_t *dev) +{ + dev->data = NULL; + dev->destroy = usb_generic_destroy; + + if (usb_generic_create) + usb_generic_create(dev); +} diff --git a/qemu/roms/openbios/drivers/usb.h b/qemu/roms/openbios/drivers/usb.h new file mode 100644 index 000000000..2e23a1370 --- /dev/null +++ b/qemu/roms/openbios/drivers/usb.h @@ -0,0 +1,357 @@ +/* + * Driver for USB ported from CoreBoot + * + * Copyright (C) 2014 BALATON Zoltan + * + * This file was part of the libpayload project. + * + * Copyright (C) 2008 coresystems GmbH + * + * 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. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + */ + +#ifndef __USB_H +#define __USB_H +#include <drivers/pci.h> + +typedef enum { host_to_device = 0, device_to_host = 1 } dev_req_dir; +typedef enum { standard_type = 0, class_type = 1, vendor_type = + 2, reserved_type = 3 +} dev_req_type; +typedef enum { dev_recp = 0, iface_recp = 1, endp_recp = 2, other_recp = 3 +} dev_req_recp; + +typedef enum { + GET_STATUS = 0, + CLEAR_FEATURE = 1, + SET_FEATURE = 3, + SET_ADDRESS = 5, + GET_DESCRIPTOR = 6, + SET_DESCRIPTOR = 7, + GET_CONFIGURATION = 8, + SET_CONFIGURATION = 9, + GET_INTERFACE = 10, + SET_INTERFACE = 11, + SYNCH_FRAME = 12 +} bRequest_Codes; + +typedef enum { + ENDPOINT_HALT = 0, + DEVICE_REMOTE_WAKEUP = 1, + TEST_MODE = 2 +} feature_selectors; + +enum { + audio_device = 0x01, + comm_device = 0x02, + hid_device = 0x03, + physical_device = 0x05, + imaging_device = 0x06, + printer_device = 0x07, + msc_device = 0x08, + hub_device = 0x09, + cdc_device = 0x0a, + ccid_device = 0x0b, + security_device = 0x0d, + video_device = 0x0e, + healthcare_device = 0x0f, + diagnostic_device = 0xdc, + wireless_device = 0xe0, + misc_device = 0xef, +}; + +enum { hid_subclass_none = 0, hid_subclass_boot = 1 }; + +enum { + hid_boot_proto_none = 0, + hid_boot_proto_keyboard = 1, + hid_boot_proto_mouse = 2 +}; + +typedef struct { + union { + struct { +#ifdef CONFIG_BIG_ENDIAN + dev_req_dir data_dir:1; + dev_req_type req_type:2; + dev_req_recp req_recp:5; +#else + dev_req_recp req_recp:5; + dev_req_type req_type:2; + dev_req_dir data_dir:1; +#endif + } __attribute__ ((packed)); + unsigned char bmRequestType; + } __attribute__ ((packed)); + unsigned char bRequest; + unsigned short wValue; + unsigned short wIndex; + unsigned short wLength; +} __attribute__ ((packed)) dev_req_t; + +struct usbdev_hc; +typedef struct usbdev_hc hci_t; + +struct usbdev; +typedef struct usbdev usbdev_t; + +typedef enum { SETUP, IN, OUT } direction_t; +typedef enum { CONTROL = 0, ISOCHRONOUS = 1, BULK = 2, INTERRUPT = 3 +} endpoint_type; + +typedef struct { + usbdev_t *dev; + int endpoint; + direction_t direction; + int toggle; + int maxpacketsize; + endpoint_type type; + int interval; /* expressed as binary logarithm of the number + of microframes (i.e. t = 125us * 2^interval) */ +} endpoint_t; + +enum { FULL_SPEED = 0, LOW_SPEED = 1, HIGH_SPEED = 2, SUPER_SPEED = 3 }; + +struct usbdev { + hci_t *controller; + endpoint_t endpoints[32]; + int num_endp; + int address; // usb address + int hub; // hub, device is attached to + int port; // port where device is attached + int speed; // 1: lowspeed, 0: fullspeed, 2: highspeed + u32 quirks; // quirks field. got to love usb + void *data; + u8 *descriptor; + u8 *configuration; + void (*init) (usbdev_t *dev); + void (*destroy) (usbdev_t *dev); + void (*poll) (usbdev_t *dev); +}; + +typedef enum { OHCI = 0, UHCI = 1, EHCI = 2, XHCI = 3} hc_type; + +struct usbdev_hc { + hci_t *next; + u32 reg_base; + hc_type type; + usbdev_t *devices[128]; // dev 0 is root hub, 127 is last addressable + + /* start(): Resume operation. */ + void (*start) (hci_t *controller); + /* stop(): Stop operation but keep controller initialized. */ + void (*stop) (hci_t *controller); + /* reset(): Perform a controller reset. The controller needs to + be (re)initialized afterwards to work (again). */ + void (*reset) (hci_t *controller); + /* init(): Initialize a (previously reset) controller + to a working state. */ + void (*init) (hci_t *controller); + /* shutdown(): Stop operation, detach host controller and shutdown + this driver instance. After calling shutdown() any + other usage of this hci_t* is invalid. */ + void (*shutdown) (hci_t *controller); + + int (*bulk) (endpoint_t *ep, int size, u8 *data, int finalize); + int (*control) (usbdev_t *dev, direction_t pid, int dr_length, + void *devreq, int data_length, u8 *data); + void* (*create_intr_queue) (endpoint_t *ep, int reqsize, int reqcount, int reqtiming); + void (*destroy_intr_queue) (endpoint_t *ep, void *queue); + u8* (*poll_intr_queue) (void *queue); + void *instance; + + /* set_address(): Tell the usb device its address and + return it. xHCI controllers want to + do this by themself. Also, the usbdev + structure has to be allocated and + initialized. */ + int (*set_address) (hci_t *controller, int speed, int hubport, int hubaddr); + /* finish_device_config(): Another hook for xHCI, + returns 0 on success. */ + int (*finish_device_config) (usbdev_t *dev); + /* destroy_device(): Finally, destroy all structures that + were allocated during set_address() + and finish_device_config(). */ + void (*destroy_device) (hci_t *controller, int devaddr); +}; + +typedef struct { + unsigned char bDescLength; + unsigned char bDescriptorType; + unsigned char bNbrPorts; + union { + struct { +#ifdef CONFIG_BIG_ENDIAN + unsigned long:8; + unsigned long arePortIndicatorsSupported:1; + unsigned long ttThinkTime:2; + unsigned long overcurrentProtectionMode:2; + unsigned long isCompoundDevice:1; + unsigned long logicalPowerSwitchingMode:2; +#else + unsigned long logicalPowerSwitchingMode:2; + unsigned long isCompoundDevice:1; + unsigned long overcurrentProtectionMode:2; + unsigned long ttThinkTime:2; + unsigned long arePortIndicatorsSupported:1; + unsigned long:8; +#endif + } __attribute__ ((packed)); + unsigned short wHubCharacteristics; + } __attribute__ ((packed)); + unsigned char bPowerOn2PwrGood; + unsigned char bHubContrCurrent; + char DeviceRemovable[]; +} __attribute__ ((packed)) hub_descriptor_t; + +typedef struct { + unsigned char bLength; + unsigned char bDescriptorType; + unsigned short bcdUSB; + unsigned char bDeviceClass; + unsigned char bDeviceSubClass; + unsigned char bDeviceProtocol; + unsigned char bMaxPacketSize0; + unsigned short idVendor; + unsigned short idProduct; + unsigned short bcdDevice; + unsigned char iManufacturer; + unsigned char iProduct; + unsigned char iSerialNumber; + unsigned char bNumConfigurations; +} __attribute__ ((packed)) device_descriptor_t; + +typedef struct { + unsigned char bLength; + unsigned char bDescriptorType; + unsigned short wTotalLength; + unsigned char bNumInterfaces; + unsigned char bConfigurationValue; + unsigned char iConfiguration; + unsigned char bmAttributes; + unsigned char bMaxPower; +} __attribute__ ((packed)) configuration_descriptor_t; + +typedef struct { + unsigned char bLength; + unsigned char bDescriptorType; + unsigned char bInterfaceNumber; + unsigned char bAlternateSetting; + unsigned char bNumEndpoints; + unsigned char bInterfaceClass; + unsigned char bInterfaceSubClass; + unsigned char bInterfaceProtocol; + unsigned char iInterface; +} __attribute__ ((packed)) interface_descriptor_t; + +typedef struct { + unsigned char bLength; + unsigned char bDescriptorType; + unsigned char bEndpointAddress; + unsigned char bmAttributes; + unsigned short wMaxPacketSize; + unsigned char bInterval; +} __attribute__ ((packed)) endpoint_descriptor_t; + +typedef struct { + unsigned char bLength; + unsigned char bDescriptorType; + unsigned short bcdHID; + unsigned char bCountryCode; + unsigned char bNumDescriptors; + unsigned char bReportDescriptorType; + unsigned short wReportDescriptorLength; +} __attribute__ ((packed)) hid_descriptor_t; + +hci_t *new_controller (void); +void detach_controller (hci_t *controller); +void usb_poll (void); +void init_device_entry (hci_t *controller, int num); + +void set_feature (usbdev_t *dev, int endp, int feature, int rtype); +void get_status (usbdev_t *dev, int endp, int rtype, int len, void *data); +void set_configuration (usbdev_t *dev); +int clear_feature (usbdev_t *dev, int endp, int feature, int rtype); +int clear_stall (endpoint_t *ep); + +void usb_hub_init (usbdev_t *dev); +void usb_hid_init (usbdev_t *dev); +void usb_msc_init (usbdev_t *dev); +void usb_generic_init (usbdev_t *dev); + +u8 *get_descriptor (usbdev_t *dev, unsigned char bmRequestType, + int descType, int descIdx, int langID); + +static inline unsigned char +gen_bmRequestType (dev_req_dir dir, dev_req_type type, dev_req_recp recp) +{ + return (dir << 7) | (type << 5) | recp; +} + +/* default "set address" handler */ +int generic_set_address (hci_t *controller, int speed, int hubport, int hubaddr); + +void usb_detach_device(hci_t *controller, int devno); +int usb_attach_device(hci_t *controller, int hubaddress, int port, int speed); + +u32 usb_quirk_check(u16 vendor, u16 device); +int usb_interface_check(u16 vendor, u16 device); + +#define USB_QUIRK_MSC_FORCE_PROTO_SCSI (1 << 0) +#define USB_QUIRK_MSC_FORCE_PROTO_ATAPI (1 << 1) +#define USB_QUIRK_MSC_FORCE_PROTO_UFI (1 << 2) +#define USB_QUIRK_MSC_FORCE_PROTO_RBC (1 << 3) +#define USB_QUIRK_MSC_FORCE_TRANS_BBB (1 << 4) +#define USB_QUIRK_MSC_FORCE_TRANS_CBI (1 << 5) +#define USB_QUIRK_MSC_FORCE_TRANS_CBI_I (1 << 6) +#define USB_QUIRK_MSC_NO_TEST_UNIT_READY (1 << 7) +#define USB_QUIRK_MSC_SHORT_INQUIRY (1 << 8) +#define USB_QUIRK_TEST (1 << 31) +#define USB_QUIRK_NONE 0 + +#ifdef CONFIG_DEBUG_USB +#define usb_debug(fmt, args...) do { printk(fmt , ##args); } while (0) +#else +#define usb_debug(fmt, args...) +#endif + +/** + * To be implemented by libpayload-client. It's called by the USB stack + * when a new USB device is found which isn't claimed by a built in driver, + * so the client has the chance to know about it. + * + * @param dev descriptor for the USB device + */ +void __attribute__((weak)) usb_generic_create (usbdev_t *dev); + +/** + * To be implemented by libpayload-client. It's called by the USB stack + * when it finds out that a USB device is removed which wasn't claimed by a + * built in driver. + * + * @param dev descriptor for the USB device + */ +void __attribute__((weak)) usb_generic_remove (usbdev_t *dev); + +#endif diff --git a/qemu/roms/openbios/drivers/usbhid.c b/qemu/roms/openbios/drivers/usbhid.c new file mode 100644 index 000000000..a423278a8 --- /dev/null +++ b/qemu/roms/openbios/drivers/usbhid.c @@ -0,0 +1,579 @@ +/* + * Driver for HID devices ported from CoreBoot + * + * Copyright (C) 2014 BALATON Zoltan + * + * This file was part of the libpayload project. + * + * Copyright (C) 2008-2010 coresystems GmbH + * + * 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. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + */ + +#include "config.h" +#include "libopenbios/bindings.h" +#include <libc/string.h> +#include "libc/byteorder.h" +#include "libc/vsprintf.h" +#include "drivers/usb.h" +#include "usb.h" + +DECLARE_UNNAMED_NODE(usb_kbd, INSTALL_OPEN, sizeof(int)); + +static void +keyboard_open(int *idx) +{ + RET(-1); +} + +static void +keyboard_close(int *idx) +{ +} + +static void keyboard_read(void); + +NODE_METHODS( usb_kbd ) = { + { "open", keyboard_open }, + { "close", keyboard_close }, + { "read", keyboard_read }, +}; + +#ifdef CONFIG_USB_DEBUG +static const char *boot_protos[3] = { "(none)", "keyboard", "mouse" }; +#endif +typedef enum { hid_proto_boot = 0, hid_proto_report = 1 } hid_proto; +enum { GET_REPORT = 0x1, GET_IDLE = 0x2, GET_PROTOCOL = 0x3, SET_REPORT = + 0x9, SET_IDLE = 0xa, SET_PROTOCOL = 0xb +}; + +typedef union { + struct { + u8 modifiers; + u8 repeats; + u8 keys[6]; + }; + u8 buffer[8]; +} usb_hid_keyboard_event_t; + +typedef struct { + void* queue; + hid_descriptor_t *descriptor; + + usb_hid_keyboard_event_t previous; + int lastkeypress; + int repeat_delay; +} usbhid_inst_t; + +#define HID_INST(dev) ((usbhid_inst_t*)(dev)->data) + +static void +usb_hid_destroy (usbdev_t *dev) +{ + if (HID_INST(dev)->queue) { + int i; + for (i = 0; i <= dev->num_endp; i++) { + if (dev->endpoints[i].endpoint == 0) + continue; + if (dev->endpoints[i].type != INTERRUPT) + continue; + if (dev->endpoints[i].direction != IN) + continue; + break; + } + dev->controller->destroy_intr_queue( + &dev->endpoints[i], HID_INST(dev)->queue); + HID_INST(dev)->queue = NULL; + } + free (dev->data); +} + +/* keybuffer is global to all USB keyboards */ +static int keycount; +#define KEYBOARD_BUFFER_SIZE 16 +static short keybuffer[KEYBOARD_BUFFER_SIZE]; + +const char *countries[36][2] = { + { "unknown", "us" }, + { "Arabic", "ae" }, + { "Belgian", "be" }, + { "Canadian-Bilingual", "ca" }, + { "Canadian-French", "ca" }, + { "Czech Republic", "cz" }, + { "Danish", "dk" }, + { "Finnish", "fi" }, + { "French", "fr" }, + { "German", "de" }, + { "Greek", "gr" }, + { "Hebrew", "il" }, + { "Hungary", "hu" }, + { "International (ISO)", "iso" }, + { "Italian", "it" }, + { "Japan (Katakana)", "jp" }, + { "Korean", "us" }, + { "Latin American", "us" }, + { "Netherlands/Dutch", "nl" }, + { "Norwegian", "no" }, + { "Persian (Farsi)", "ir" }, + { "Poland", "pl" }, + { "Portuguese", "pt" }, + { "Russia", "ru" }, + { "Slovakia", "sl" }, + { "Spanish", "es" }, + { "Swedish", "se" }, + { "Swiss/French", "ch" }, + { "Swiss/German", "ch" }, + { "Switzerland", "ch" }, + { "Taiwan", "tw" }, + { "Turkish-Q", "tr" }, + { "UK", "uk" }, + { "US", "us" }, + { "Yugoslavia", "yu" }, + { "Turkish-F", "tr" }, + /* 36 - 255: Reserved */ +}; + + + +struct layout_maps { + const char *country; + const short map[4][0x80]; +}; + +static const struct layout_maps *map; + +#define KEY_BREAK 0x101 /* Not on PC KBD */ +#define KEY_DOWN 0x102 /* Down arrow key */ +#define KEY_UP 0x103 /* Up arrow key */ +#define KEY_LEFT 0x104 /* Left arrow key */ +#define KEY_RIGHT 0x105 /* Right arrow key */ +#define KEY_HOME 0x106 /* home key */ +#define KEY_BACKSPACE 0x107 /* not on pc */ +#define KEY_F0 0x108 /* function keys; 64 reserved */ +#define KEY_F(n) (KEY_F0 + (n)) + +#define KEY_DC 0x14a /* delete character */ +#define KEY_IC 0x14b /* insert char or enter ins mode */ + +#define KEY_NPAGE 0x152 /* next page */ +#define KEY_PPAGE 0x153 /* previous page */ + +#define KEY_ENTER 0x157 /* enter or send (unreliable) */ + +#define KEY_PRINT 0x15a /* print/copy */ + +#define KEY_END 0x166 /* end key */ + +static const struct layout_maps keyboard_layouts[] = { +// #ifdef CONFIG_PC_KEYBOARD_LAYOUT_US +{ .country = "us", .map = { + { /* No modifier */ + -1, -1, -1, -1, 'a', 'b', 'c', 'd', + 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', + /* 0x10 */ + 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', + 'u', 'v', 'w', 'x', 'y', 'z', '1', '2', + /* 0x20 */ + '3', '4', '5', '6', '7', '8', '9', '0', + '\n', '\e', '\b', '\t', ' ', '-', '=', '[', + /* 0x30 */ + ']', '\\', -1, ';', '\'', '`', ',', '.', + '/', -1 /* CapsLk */, KEY_F(1), KEY_F(2), KEY_F(3), KEY_F(4), KEY_F(5), KEY_F(6), + /* 0x40 */ + KEY_F(7), KEY_F(8), KEY_F(9), KEY_F(10), KEY_F(11), KEY_F(12), KEY_PRINT, -1 /* ScrLk */, + KEY_BREAK, KEY_IC, KEY_HOME, KEY_PPAGE, KEY_DC, KEY_END, KEY_NPAGE, KEY_RIGHT, + /* 50 */ + KEY_LEFT, KEY_DOWN, KEY_UP, -1 /*NumLck*/, '/', '*', '-' /* = ? */, '+', + KEY_ENTER, KEY_END, KEY_DOWN, KEY_NPAGE, KEY_LEFT, -1, KEY_RIGHT, KEY_HOME, + /* 60 */ + KEY_UP, KEY_PPAGE, -1, KEY_DC, -1 /* < > | */, -1 /* Win Key Right */, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + /* 70 */ + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + }, + { /* Shift modifier */ + -1, -1, -1, -1, 'A', 'B', 'C', 'D', + 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', + /* 0x10 */ + 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', + 'U', 'V', 'W', 'X', 'Y', 'Z', '!', '@', + /* 0x20 */ + '#', '$', '%', '^', '&', '*', '(', ')', + '\n', '\e', '\b', '\t', ' ', '_', '+', '{', + /* 0x30 */ + '}', '|', -1, ':', '"', '~', '<', '>', + '?', -1 /* CapsLk */, KEY_F(1), KEY_F(2), KEY_F(3), KEY_F(4), KEY_F(5), KEY_F(6), + /* 0x40 */ + KEY_F(7), KEY_F(8), KEY_F(9), KEY_F(10), KEY_F(11), KEY_F(12), KEY_PRINT, -1 /* ScrLk */, + KEY_BREAK, KEY_IC, KEY_HOME, KEY_PPAGE, KEY_DC, KEY_END, KEY_NPAGE, KEY_RIGHT, + /* 50 */ + KEY_LEFT, KEY_DOWN, KEY_UP, -1 /*NumLck*/, '/', '*', '-' /* = ? */, '+', + KEY_ENTER, KEY_END, KEY_DOWN, KEY_NPAGE, KEY_LEFT, -1, KEY_RIGHT, KEY_HOME, + /* 60 */ + KEY_UP, KEY_PPAGE, -1, KEY_DC, -1 /* < > | */, -1 /* Win Key Right */, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + /* 70 */ + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + }, + { /* Alt */ + -1, -1, -1, -1, 'a', 'b', 'c', 'd', + 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', + /* 0x10 */ + 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', + 'u', 'v', 'w', 'x', 'y', 'z', '1', '2', + /* 0x20 */ + '3', '4', '5', '6', '7', '8', '9', '0', + '\n', '\e', '\b', '\t', ' ', '-', '=', '[', + /* 0x30 */ + ']', '\\', -1, ';', '\'', '`', ',', '.', + '/', -1 /* CapsLk */, KEY_F(1), KEY_F(2), KEY_F(3), KEY_F(4), KEY_F(5), KEY_F(6), + /* 0x40 */ + KEY_F(7), KEY_F(8), KEY_F(9), KEY_F(10), KEY_F(11), KEY_F(12), KEY_PRINT, -1 /* ScrLk */, + KEY_BREAK, KEY_IC, KEY_HOME, KEY_PPAGE, KEY_DC, KEY_END, KEY_NPAGE, KEY_RIGHT, + /* 50 */ + KEY_LEFT, KEY_DOWN, KEY_UP, -1 /*NumLck*/, '/', '*', '-' /* = ? */, '+', + KEY_ENTER, KEY_END, KEY_DOWN, KEY_NPAGE, KEY_LEFT, -1, KEY_RIGHT, KEY_HOME, + /* 60 */ + KEY_UP, KEY_PPAGE, -1, KEY_DC, -1 /* < > | */, -1 /* Win Key Right */, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + /* 70 */ + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + }, + { /* Shift+Alt modifier */ + -1, -1, -1, -1, 'A', 'B', 'C', 'D', + 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', + /* 0x10 */ + 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', + 'U', 'V', 'W', 'X', 'Y', 'Z', '!', '@', + /* 0x20 */ + '#', '$', '%', '^', '&', '*', '(', ')', + '\n', '\e', '\b', '\t', ' ', '-', '=', '[', + /* 0x30 */ + ']', '\\', -1, ':', '\'', '`', ',', '.', + '/', -1 /* CapsLk */, KEY_F(1), KEY_F(2), KEY_F(3), KEY_F(4), KEY_F(5), KEY_F(6), + /* 0x40 */ + KEY_F(7), KEY_F(8), KEY_F(9), KEY_F(10), KEY_F(11), KEY_F(12), KEY_PRINT, -1 /* ScrLk */, + KEY_BREAK, KEY_IC, KEY_HOME, KEY_PPAGE, KEY_DC, KEY_END, KEY_NPAGE, KEY_RIGHT, + /* 50 */ + KEY_LEFT, KEY_DOWN, KEY_UP, -1 /*NumLck*/, '/', '*', '-' /* = ? */, '+', + KEY_ENTER, KEY_END, KEY_DOWN, KEY_NPAGE, KEY_LEFT, -1, KEY_RIGHT, KEY_HOME, + /* 60 */ + KEY_UP, KEY_PPAGE, -1, KEY_DC, -1 /* < > | */, -1 /* Win Key Right */, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + /* 70 */ + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + } +}}, +//#endif +}; + +#define MOD_SHIFT (1 << 0) +#define MOD_ALT (1 << 1) +#define MOD_CTRL (1 << 2) + +static void usb_hid_keyboard_queue(int ch) { + /* ignore key presses if buffer full */ + if (keycount < KEYBOARD_BUFFER_SIZE) + keybuffer[keycount++] = ch; +} + +#define KEYBOARD_REPEAT_MS 30 +#define INITIAL_REPEAT_DELAY 10 +#define REPEAT_DELAY 2 + +static void +usb_hid_process_keyboard_event(usbhid_inst_t *const inst, + const usb_hid_keyboard_event_t *const current) +{ + const usb_hid_keyboard_event_t *const previous = &inst->previous; + + int i, keypress = 0, modifiers = 0; + + if (current->modifiers & 0x01) /* Left-Ctrl */ modifiers |= MOD_CTRL; + if (current->modifiers & 0x02) /* Left-Shift */ modifiers |= MOD_SHIFT; + if (current->modifiers & 0x04) /* Left-Alt */ modifiers |= MOD_ALT; + if (current->modifiers & 0x08) /* Left-GUI */ ; + if (current->modifiers & 0x10) /* Right-Ctrl */ modifiers |= MOD_CTRL; + if (current->modifiers & 0x20) /* Right-Shift */ modifiers |= MOD_SHIFT; + if (current->modifiers & 0x40) /* Right-AltGr */ modifiers |= MOD_ALT; + if (current->modifiers & 0x80) /* Right-GUI */ ; + + /* Did the event change at all? */ + if (inst->lastkeypress && + !memcmp(current, previous, sizeof(*current))) { + /* No. Then it's a key repeat event. */ + if (inst->repeat_delay) { + inst->repeat_delay--; + } else { + usb_hid_keyboard_queue(inst->lastkeypress); + inst->repeat_delay = REPEAT_DELAY; + } + + return; + } + + inst->lastkeypress = 0; + + for (i=0; i<6; i++) { + int j; + int skip = 0; + // No more keys? skip + if (current->keys[i] == 0) + return; + + for (j=0; j<6; j++) { + if (current->keys[i] == previous->keys[j]) { + skip = 1; + break; + } + } + if (skip) + continue; + + + /* Mask off MOD_CTRL */ + keypress = map->map[modifiers & 0x03][current->keys[i]]; + + if (modifiers & MOD_CTRL) { + switch (keypress) { + case 'a' ... 'z': + keypress &= 0x1f; + break; + default: + continue; + } + } + + if (keypress == -1) { + /* Debug: Print unknown keys */ + usb_debug ("usbhid: <%x> %x [ %x %x %x %x %x %x ] %d\n", + current->modifiers, current->repeats, + current->keys[0], current->keys[1], + current->keys[2], current->keys[3], + current->keys[4], current->keys[5], i); + + /* Unknown key? Try next one in the queue */ + continue; + } + + usb_hid_keyboard_queue(keypress); + + /* Remember for authentic key repeat */ + inst->lastkeypress = keypress; + inst->repeat_delay = INITIAL_REPEAT_DELAY; + } +} + +static void +usb_hid_poll (usbdev_t *dev) +{ + usb_hid_keyboard_event_t current; + const u8 *buf; + + while ((buf=dev->controller->poll_intr_queue (HID_INST(dev)->queue))) { + memcpy(¤t.buffer, buf, 8); + usb_hid_process_keyboard_event(HID_INST(dev), ¤t); + HID_INST(dev)->previous = current; + } +} + +static void +usb_hid_set_idle (usbdev_t *dev, interface_descriptor_t *interface, u16 duration) +{ + dev_req_t dr; + dr.data_dir = host_to_device; + dr.req_type = class_type; + dr.req_recp = iface_recp; + dr.bRequest = SET_IDLE; + dr.wValue = __cpu_to_le16((duration >> 2) << 8); + dr.wIndex = __cpu_to_le16(interface->bInterfaceNumber); + dr.wLength = 0; + dev->controller->control (dev, OUT, sizeof (dev_req_t), &dr, 0, 0); +} + +static void +usb_hid_set_protocol (usbdev_t *dev, interface_descriptor_t *interface, hid_proto proto) +{ + dev_req_t dr; + dr.data_dir = host_to_device; + dr.req_type = class_type; + dr.req_recp = iface_recp; + dr.bRequest = SET_PROTOCOL; + dr.wValue = __cpu_to_le16(proto); + dr.wIndex = __cpu_to_le16(interface->bInterfaceNumber); + dr.wLength = 0; + dev->controller->control (dev, OUT, sizeof (dev_req_t), &dr, 0, 0); +} + +static int usb_hid_set_layout (const char *country) +{ + /* FIXME should be per keyboard */ + int i; + + for (i=0; i<sizeof(keyboard_layouts)/sizeof(keyboard_layouts[0]); i++) { + if (strncmp(keyboard_layouts[i].country, country, + strlen(keyboard_layouts[i].country))) + continue; + + /* Found, changing keyboard layout */ + map = &keyboard_layouts[i]; + usb_debug(" Keyboard layout '%s'\n", map->country); + return 0; + } + + usb_debug(" Keyboard layout '%s' not found, using '%s'\n", + country, map->country); + + /* Nothing found, not changed */ + return -1; +} + +void +usb_hid_init (usbdev_t *dev) +{ + configuration_descriptor_t *cd = (configuration_descriptor_t*)dev->configuration; + interface_descriptor_t *interface = (interface_descriptor_t*)(((char *) cd) + cd->bLength); + + if (interface->bInterfaceSubClass == hid_subclass_boot) { + u8 countrycode = 0; + usb_debug (" supports boot interface..\n"); + usb_debug (" it's a %s\n", + boot_protos[interface->bInterfaceProtocol]); + switch (interface->bInterfaceProtocol) { + case hid_boot_proto_keyboard: + dev->data = malloc (sizeof (usbhid_inst_t)); + if (!dev->data) { + printk("Not enough memory for USB HID device.\n"); + return; + } + memset(&HID_INST(dev)->previous, 0x00, + sizeof(HID_INST(dev)->previous)); + usb_debug (" configuring...\n"); + usb_hid_set_protocol(dev, interface, hid_proto_boot); + usb_hid_set_idle(dev, interface, KEYBOARD_REPEAT_MS); + usb_debug (" activating...\n"); +#if 0 + HID_INST (dev)->descriptor = + (hid_descriptor_t *) + get_descriptor(dev, gen_bmRequestType + (device_to_host, standard_type, iface_recp), + 0x21, 0, 0); + countrycode = HID_INST(dev)->descriptor->bCountryCode; +#endif + /* 35 countries defined: */ + if (countrycode > 35) + countrycode = 0; + usb_debug (" Keyboard has %s layout (country code %02x)\n", + countries[countrycode][0], countrycode); + + /* Set keyboard layout accordingly */ + usb_hid_set_layout(countries[countrycode][1]); + + // only add here, because we only support boot-keyboard HID devices + dev->destroy = usb_hid_destroy; + dev->poll = usb_hid_poll; + int i; + for (i = 0; i <= dev->num_endp; i++) { + if (dev->endpoints[i].endpoint == 0) + continue; + if (dev->endpoints[i].type != INTERRUPT) + continue; + if (dev->endpoints[i].direction != IN) + continue; + break; + } + usb_debug (" found endpoint %x for interrupt-in\n", i); + /* 20 buffers of 8 bytes, for every 10 msecs */ + HID_INST(dev)->queue = dev->controller->create_intr_queue (&dev->endpoints[i], 8, 20, 10); + keycount = 0; + usb_debug (" configuration done.\n"); + break; + default: + usb_debug("NOTICE: HID interface protocol %d%s not supported.\n", + interface->bInterfaceProtocol, + (interface->bInterfaceProtocol == hid_boot_proto_mouse ? + " (USB mouse)" : "")); + break; + } + } +} + +static int usbhid_havechar (void) +{ + return (keycount != 0); +} + +static int usbhid_getchar (void) +{ + short ret; + + if (keycount == 0) + return 0; + ret = keybuffer[0]; + memmove(keybuffer, keybuffer + 1, --keycount); + + return (int)ret; +} + +/* ( addr len -- actual ) */ +static void keyboard_read(void) +{ + char *addr; + int len, key, i; + + usb_poll(); + len=POP(); + addr=(char *)cell2pointer(POP()); + + for (i = 0; i < len; i++) { + if (!usbhid_havechar()) + break; + key = usbhid_getchar(); + *addr++ = (char)key; + } + PUSH(i); +} + +void ob_usb_hid_add_keyboard(const char *path) +{ + char name[128]; + phandle_t aliases; + + snprintf(name, sizeof(name), "%s/keyboard", path); + usb_debug("Found keyboard at %s\n", name); + REGISTER_NAMED_NODE(usb_kbd, name); + + push_str(name); + fword("find-device"); + + push_str("keyboard"); + fword("device-type"); + + aliases = find_dev("/aliases"); + set_property(aliases, "adb-keyboard", name, strlen(name) + 1); +} diff --git a/qemu/roms/openbios/drivers/usbohci.c b/qemu/roms/openbios/drivers/usbohci.c new file mode 100644 index 000000000..774164b0b --- /dev/null +++ b/qemu/roms/openbios/drivers/usbohci.c @@ -0,0 +1,926 @@ +/* + * Driver for USB OHCI ported from CoreBoot + * + * Copyright (C) 2014 BALATON Zoltan + * + * This file was part of the libpayload project. + * + * Copyright (C) 2010 Patrick Georgi + * + * 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. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + */ + +//#define USB_DEBUG_ED + +#include "config.h" +#include <asm/io.h> +#include <libopenbios/ofmem.h> +#include "timer.h" +#include "drivers/pci.h" +#include "pci.h" +#include <drivers/usb.h> +#include "usbohci_private.h" +#include "usbohci.h" + +static void ohci_start (hci_t *controller); +static void ohci_stop (hci_t *controller); +static void ohci_reset (hci_t *controller); +static void ohci_shutdown (hci_t *controller); +static int ohci_bulk (endpoint_t *ep, int size, u8 *data, int finalize); +static int ohci_control (usbdev_t *dev, direction_t dir, int drlen, void *devreq, + int dalen, u8 *data); +static void* ohci_create_intr_queue (endpoint_t *ep, int reqsize, int reqcount, int reqtiming); +static void ohci_destroy_intr_queue (endpoint_t *ep, void *queue); +static u8* ohci_poll_intr_queue (void *queue); +static void ohci_process_done_queue(ohci_t *ohci, int spew_debug); + +#ifdef USB_DEBUG_ED +static void +dump_td (td_t *cur) +{ + usb_debug("+---------------------------------------------------+\n"); + if (((__le32_to_cpu(cur->config) & (3UL << 19)) >> 19) == 0) + usb_debug("|..[SETUP]..........................................|\n"); + else if (((__le32_to_cpu(cur->config) & (3UL << 8)) >> 8) == 2) + usb_debug("|..[IN].............................................|\n"); + else if (((__le32_to_cpu(cur->config) & (3UL << 8)) >> 8) == 1) + usb_debug("|..[OUT]............................................|\n"); + else + usb_debug("|..[]...............................................|\n"); + usb_debug("|:|============ OHCI TD at [0x%08lx] ==========|:|\n", virt_to_phys(cur)); + usb_debug("|:| ERRORS = [%ld] | CONFIG = [0x%08x] | |:|\n", + 3 - ((__le32_to_cpu(cur->config) & (3UL << 26)) >> 26), __le32_to_cpu(cur->config)); + usb_debug("|:+-----------------------------------------------+:|\n"); + usb_debug("|:| C | Condition Code | [%02ld] |:|\n", + (__le32_to_cpu(cur->config) & (0xFUL << 28)) >> 28); + usb_debug("|:| O | Direction/PID | [%ld] |:|\n", + (__le32_to_cpu(cur->config) & (3UL << 19)) >> 19); + usb_debug("|:| N | Buffer Rounding | [%ld] |:|\n", + (__le32_to_cpu(cur->config) & (1UL << 18)) >> 18); + usb_debug("|:| F | Delay Intterrupt | [%ld] |:|\n", + (__le32_to_cpu(cur->config) & (7UL << 21)) >> 21); + usb_debug("|:| I | Data Toggle | [%ld] |:|\n", + (__le32_to_cpu(cur->config) & (3UL << 24)) >> 24); + usb_debug("|:| G | Error Count | [%ld] |:|\n", + (__le32_to_cpu(cur->config) & (3UL << 26)) >> 26); + usb_debug("|:+-----------------------------------------------+:|\n"); + usb_debug("|:| Current Buffer Pointer [0x%08x] |:|\n", __le32_to_cpu(cur->current_buffer_pointer)); + usb_debug("|:+-----------------------------------------------+:|\n"); + usb_debug("|:| Next TD [0x%08x] |:|\n", __le32_to_cpu(cur->next_td)); + usb_debug("|:+-----------------------------------------------+:|\n"); + usb_debug("|:| Current Buffer End [0x%08x] |:|\n", __le32_to_cpu(cur->buffer_end)); + usb_debug("|:|-----------------------------------------------|:|\n"); + usb_debug("|...................................................|\n"); + usb_debug("+---------------------------------------------------+\n"); +} + +static void +dump_ed (ed_t *cur) +{ + td_t *tmp_td = NULL; + usb_debug("+===================================================+\n"); + usb_debug("| ############# OHCI ED at [0x%08lx] ########### |\n", virt_to_phys(cur)); + usb_debug("+---------------------------------------------------+\n"); + usb_debug("| Next Endpoint Descriptor [0x%08lx] |\n", __le32_to_cpu(cur->next_ed) & ~0xFUL); + usb_debug("+---------------------------------------------------+\n"); + usb_debug("| | @ 0x%08x : |\n", __le32_to_cpu(cur->config)); + usb_debug("| C | Maximum Packet Length | [%04ld] |\n", + ((__le32_to_cpu(cur->config) & (0x3fffUL << 16)) >> 16)); + usb_debug("| O | Function Address | [%04d] |\n", + __le32_to_cpu(cur->config) & 0x7F); + usb_debug("| N | Endpoint Number | [%02ld] |\n", + (__le32_to_cpu(cur->config) & (0xFUL << 7)) >> 7); + usb_debug("| F | Endpoint Direction | [%ld] |\n", + ((__le32_to_cpu(cur->config) & (3UL << 11)) >> 11)); + usb_debug("| I | Endpoint Speed | [%ld] |\n", + ((__le32_to_cpu(cur->config) & (1UL << 13)) >> 13)); + usb_debug("| G | Skip | [%ld] |\n", + ((__le32_to_cpu(cur->config) & (1UL << 14)) >> 14)); + usb_debug("| | Format | [%ld] |\n", + ((__le32_to_cpu(cur->config) & (1UL << 15)) >> 15)); + usb_debug("+---------------------------------------------------+\n"); + usb_debug("| TD Queue Tail Pointer [0x%08lx] |\n", + __le32_to_cpu(cur->tail_pointer) & ~0xFUL); + usb_debug("+---------------------------------------------------+\n"); + usb_debug("| TD Queue Head Pointer [0x%08lx] |\n", + __le32_to_cpu(cur->head_pointer) & ~0xFUL); + usb_debug("| CarryToggleBit [%d] Halted [%d] |\n", + (u16)(__le32_to_cpu(cur->head_pointer) & 0x2UL)>>1, (u16)(__le32_to_cpu(cur->head_pointer) & 0x1UL)); + + tmp_td = (td_t *)phys_to_virt((__le32_to_cpu(cur->head_pointer) & ~0xFUL)); + if ((__le32_to_cpu(cur->head_pointer) & ~0xFUL) != (__le32_to_cpu(cur->tail_pointer) & ~0xFUL)) { + usb_debug("|:::::::::::::::::: OHCI TD CHAIN ::::::::::::::::::|\n"); + while (virt_to_phys(tmp_td) != (__le32_to_cpu(cur->tail_pointer) & ~0xFUL)) + { + dump_td(tmp_td); + tmp_td = (td_t *)phys_to_virt((__le32_to_cpu(tmp_td->next_td) & ~0xFUL)); + } + usb_debug("|:::::::::::::::: EOF OHCI TD CHAIN ::::::::::::::::|\n"); + usb_debug("+---------------------------------------------------+\n"); + } else { + usb_debug("+---------------------------------------------------+\n"); + } +} +#endif + +static void +ohci_reset (hci_t *controller) +{ + if (controller == NULL) + return; + + OHCI_INST(controller)->opreg->HcCommandStatus = __cpu_to_le32(HostControllerReset); + mdelay(2); /* wait 2ms */ + OHCI_INST(controller)->opreg->HcControl = 0; + mdelay(10); /* wait 10ms */ +} + +static void +ohci_reinit (hci_t *controller) +{ +} + +hci_t * +ohci_init (void *bar) +{ + int i; + + hci_t *controller = new_controller (); + + if (!controller) { + printk("Could not create USB controller instance.\n"); + return NULL; + } + + controller->instance = malloc (sizeof (ohci_t)); + if(!controller->instance) { + printk("Not enough memory creating USB controller instance.\n"); + return NULL; + } + + controller->type = OHCI; + + controller->start = ohci_start; + controller->stop = ohci_stop; + controller->reset = ohci_reset; + controller->init = ohci_reinit; + controller->shutdown = ohci_shutdown; + controller->bulk = ohci_bulk; + controller->control = ohci_control; + controller->set_address = generic_set_address; + controller->finish_device_config = NULL; + controller->destroy_device = NULL; + controller->create_intr_queue = ohci_create_intr_queue; + controller->destroy_intr_queue = ohci_destroy_intr_queue; + controller->poll_intr_queue = ohci_poll_intr_queue; + for (i = 0; i < 128; i++) { + controller->devices[i] = 0; + } + init_device_entry (controller, 0); + OHCI_INST (controller)->roothub = controller->devices[0]; + + controller->reg_base = (u32)(unsigned long)bar; + OHCI_INST (controller)->opreg = (opreg_t*)phys_to_virt(controller->reg_base); + usb_debug("OHCI Version %x.%x\n", + (READ_OPREG(OHCI_INST(controller), HcRevision) >> 4) & 0xf, + READ_OPREG(OHCI_INST(controller), HcRevision) & 0xf); + + if ((READ_OPREG(OHCI_INST(controller), HcControl) & HostControllerFunctionalStateMask) == USBReset) { + /* cold boot */ + OHCI_INST (controller)->opreg->HcControl &= __cpu_to_le32(~RemoteWakeupConnected); + OHCI_INST (controller)->opreg->HcFmInterval = + __cpu_to_le32((11999 * FrameInterval) | ((((11999 - 210)*6)/7) * FSLargestDataPacket)); + /* TODO: right value for PowerOnToPowerGoodTime ? */ + OHCI_INST (controller)->opreg->HcRhDescriptorA = + __cpu_to_le32(NoPowerSwitching | NoOverCurrentProtection | (10 * PowerOnToPowerGoodTime)); + OHCI_INST (controller)->opreg->HcRhDescriptorB = __cpu_to_le32(0 * DeviceRemovable); + udelay(100); /* TODO: reset asserting according to USB spec */ + } else if ((READ_OPREG(OHCI_INST(controller), HcControl) & HostControllerFunctionalStateMask) != USBOperational) { + OHCI_INST (controller)->opreg->HcControl = + __cpu_to_le32((READ_OPREG(OHCI_INST(controller), HcControl) & ~HostControllerFunctionalStateMask) + | USBResume); + udelay(100); /* TODO: resume time according to USB spec */ + } + int interval = OHCI_INST (controller)->opreg->HcFmInterval; + + OHCI_INST (controller)->opreg->HcCommandStatus = __cpu_to_le32(HostControllerReset); + udelay (10); /* at most 10us for reset to complete. State must be set to Operational within 2ms (5.1.1.4) */ + OHCI_INST (controller)->opreg->HcFmInterval = interval; + ofmem_posix_memalign((void **)&(OHCI_INST (controller)->hcca), 256, 256); + memset((void*)OHCI_INST (controller)->hcca, 0, 256); + + usb_debug("HCCA addr %p\n", OHCI_INST(controller)->hcca); + /* Initialize interrupt table. */ + u32 *const intr_table = OHCI_INST(controller)->hcca->HccaInterruptTable; + ed_t *const periodic_ed; + ofmem_posix_memalign((void **)&periodic_ed, sizeof(ed_t), sizeof(ed_t)); + memset((void *)periodic_ed, 0, sizeof(*periodic_ed)); + for (i = 0; i < 32; ++i) + intr_table[i] = __cpu_to_le32(virt_to_phys(periodic_ed)); + OHCI_INST (controller)->periodic_ed = periodic_ed; + + OHCI_INST (controller)->opreg->HcHCCA = __cpu_to_le32(virt_to_phys(OHCI_INST(controller)->hcca)); + /* Make sure periodic schedule is enabled. */ + OHCI_INST (controller)->opreg->HcControl |= __cpu_to_le32(PeriodicListEnable); + OHCI_INST (controller)->opreg->HcControl &= __cpu_to_le32(~IsochronousEnable); // unused by this driver + // disable everything, contrary to what OHCI spec says in 5.1.1.4, as we don't need IRQs + OHCI_INST (controller)->opreg->HcInterruptEnable = __cpu_to_le32(1<<31); + OHCI_INST (controller)->opreg->HcInterruptDisable = __cpu_to_le32(~(1<<31)); + OHCI_INST (controller)->opreg->HcInterruptStatus = __cpu_to_le32(~0); + OHCI_INST (controller)->opreg->HcPeriodicStart = + __cpu_to_le32((READ_OPREG(OHCI_INST(controller), HcFmInterval) & FrameIntervalMask) / 10 * 9); + OHCI_INST (controller)->opreg->HcControl = __cpu_to_le32((READ_OPREG(OHCI_INST(controller), HcControl) + & ~HostControllerFunctionalStateMask) | USBOperational); + + mdelay(100); + + controller->devices[0]->controller = controller; + controller->devices[0]->init = ohci_rh_init; + controller->devices[0]->init (controller->devices[0]); + return controller; +} + +hci_t * +ohci_pci_init (pci_addr addr) +{ + u32 reg_base; + uint16_t cmd; + + cmd = pci_config_read16(addr, PCI_COMMAND); + cmd |= PCI_COMMAND_BUS_MASTER; + pci_config_write16(addr, PCI_COMMAND, cmd); + + /* regarding OHCI spec, Appendix A, BAR_OHCI register description, Table A-4 + * BASE ADDRESS only [31-12] bits. All other usually 0, but not all. + * OHCI mandates MMIO, so bit 0 is clear */ + reg_base = pci_config_read32 (addr, PCI_BASE_ADDR_0) & 0xfffff000; + + return ohci_init((void *)(unsigned long)reg_base); +} + +static void +ohci_shutdown (hci_t *controller) +{ + if (controller == 0) + return; + detach_controller (controller); + ohci_stop(controller); + OHCI_INST (controller)->roothub->destroy (OHCI_INST (controller)-> + roothub); + controller->reset (controller); + free ((void *)OHCI_INST (controller)->periodic_ed); + free (OHCI_INST (controller)); + free (controller); +} + +static void +ohci_start (hci_t *controller) +{ +// TODO: turn on all operation of OHCI, but assume that it's initialized. +} + +static void +ohci_stop (hci_t *controller) +{ +// TODO: turn off all operation of OHCI +} + +static int +wait_for_ed(usbdev_t *dev, ed_t *head, int pages) +{ + usb_debug("Waiting for %d pages on dev %p with head %p\n", pages, dev, head); + /* wait for results */ + /* TOTEST: how long to wait? + * give 2s per TD (2 pages) plus another 2s for now + */ + int timeout = pages*1000 + 2000; + while (((__le32_to_cpu(head->head_pointer) & ~3) != __le32_to_cpu(head->tail_pointer)) && + !(__le32_to_cpu(head->head_pointer) & 1) && + ((__le32_to_cpu((((td_t*)phys_to_virt(__le32_to_cpu(head->head_pointer) & ~3)))->config) + & TD_CC_MASK) >= TD_CC_NOACCESS) && timeout--) { + /* don't log every ms */ + if (!(timeout % 100)) + usb_debug("intst: %x; ctrl: %x; cmdst: %x; head: %x -> %x, tail: %x, condition: %x\n", + READ_OPREG(OHCI_INST(dev->controller), HcInterruptStatus), + READ_OPREG(OHCI_INST(dev->controller), HcControl), + READ_OPREG(OHCI_INST(dev->controller), HcCommandStatus), + __le32_to_cpu(head->head_pointer), + __le32_to_cpu(((td_t*)phys_to_virt(__le32_to_cpu(head->head_pointer) & ~3))->next_td), + __le32_to_cpu(head->tail_pointer), + (__le32_to_cpu(((td_t*)phys_to_virt(__le32_to_cpu(head->head_pointer) & ~3))->config) & TD_CC_MASK) >> TD_CC_SHIFT); + mdelay(1); + } + if (timeout < 0) + usb_debug("Error: ohci: endpoint " + "descriptor processing timed out.\n"); + /* Clear the done queue. */ + ohci_process_done_queue(OHCI_INST(dev->controller), 1); + + if (__le32_to_cpu(head->head_pointer) & 1) { + usb_debug("HALTED!\n"); + return 1; + } + return 0; +} + +static void +ohci_free_ed (ed_t *const head) +{ + /* In case the transfer canceled, we have to free unprocessed TDs. */ + while ((__le32_to_cpu(head->head_pointer) & ~0x3) != __le32_to_cpu(head->tail_pointer)) { + /* Save current TD pointer. */ + td_t *const cur_td = + (td_t*)phys_to_virt(__le32_to_cpu(head->head_pointer) & ~0x3); + /* Advance head pointer. */ + head->head_pointer = cur_td->next_td; + /* Free current TD. */ + free((void *)cur_td); + } + + /* Always free the dummy TD */ + if ((__le32_to_cpu(head->head_pointer) & ~0x3) == __le32_to_cpu(head->tail_pointer)) + free(phys_to_virt(__le32_to_cpu(head->head_pointer) & ~0x3)); + /* and the ED. */ + free((void *)head); +} + +static int +ohci_control (usbdev_t *dev, direction_t dir, int drlen, void *devreq, int dalen, + unsigned char *data) +{ + td_t *cur; + + // pages are specified as 4K in OHCI, so don't use getpagesize() + int first_page = (unsigned long)data / 4096; + int last_page = (unsigned long)(data+dalen-1)/4096; + if (last_page < first_page) last_page = first_page; + int pages = (dalen==0)?0:(last_page - first_page + 1); + + /* First TD. */ + td_t *const first_td; + ofmem_posix_memalign((void **)&first_td, sizeof(td_t), sizeof(td_t)); + memset((void *)first_td, 0, sizeof(*first_td)); + cur = first_td; + + cur->config = __cpu_to_le32(TD_DIRECTION_SETUP | + TD_DELAY_INTERRUPT_NOINTR | + TD_TOGGLE_FROM_TD | + TD_TOGGLE_DATA0 | + TD_CC_NOACCESS); + cur->current_buffer_pointer = __cpu_to_le32(virt_to_phys(devreq)); + cur->buffer_end = __cpu_to_le32(virt_to_phys((char *)devreq + drlen - 1)); + + while (pages > 0) { + /* One more TD. */ + td_t *const next; + ofmem_posix_memalign((void **)&next, sizeof(td_t), sizeof(td_t)); + memset((void *)next, 0, sizeof(*next)); + /* Linked to the previous. */ + cur->next_td = __cpu_to_le32(virt_to_phys(next)); + /* Advance to the new TD. */ + cur = next; + + cur->config = __cpu_to_le32((dir == IN ? TD_DIRECTION_IN : TD_DIRECTION_OUT) | + TD_DELAY_INTERRUPT_NOINTR | + TD_TOGGLE_FROM_ED | + TD_CC_NOACCESS); + cur->current_buffer_pointer = __cpu_to_le32(virt_to_phys(data)); + pages--; + int consumed = (4096 - ((unsigned long)data % 4096)); + if (consumed >= dalen) { + // end of data is within same page + cur->buffer_end = __cpu_to_le32(virt_to_phys(data + dalen - 1)); + dalen = 0; + /* assert(pages == 0); */ + } else { + dalen -= consumed; + data += consumed; + pages--; + int second_page_size = dalen; + if (dalen > 4096) { + second_page_size = 4096; + } + cur->buffer_end = __cpu_to_le32(virt_to_phys(data + second_page_size - 1)); + dalen -= second_page_size; + data += second_page_size; + } + } + + /* One more TD. */ + td_t *const next_td; + ofmem_posix_memalign((void **)&next_td, sizeof(td_t), sizeof(td_t)); + memset((void *)next_td, 0, sizeof(*next_td)); + /* Linked to the previous. */ + cur->next_td = __cpu_to_le32(virt_to_phys(next_td)); + /* Advance to the new TD. */ + cur = next_td; + cur->config = __cpu_to_le32((dir == IN ? TD_DIRECTION_OUT : TD_DIRECTION_IN) | + TD_DELAY_INTERRUPT_ZERO | /* Write done head after this TD. */ + TD_TOGGLE_FROM_TD | + TD_TOGGLE_DATA1 | + TD_CC_NOACCESS); + cur->current_buffer_pointer = 0; + cur->buffer_end = 0; + + /* Final dummy TD. */ + td_t *const final_td; + ofmem_posix_memalign((void **)&final_td, sizeof(td_t), sizeof(td_t)); + memset((void *)final_td, 0, sizeof(*final_td)); + /* Linked to the previous. */ + cur->next_td = __cpu_to_le32(virt_to_phys(final_td)); + + /* Data structures */ + ed_t *head; + ofmem_posix_memalign((void **)&head, sizeof(ed_t), sizeof(ed_t)); + memset((void*)head, 0, sizeof(*head)); + head->config = __cpu_to_le32((dev->address << ED_FUNC_SHIFT) | + (0 << ED_EP_SHIFT) | + (OHCI_FROM_TD << ED_DIR_SHIFT) | + (dev->speed?ED_LOWSPEED:0) | + (dev->endpoints[0].maxpacketsize << ED_MPS_SHIFT)); + head->tail_pointer = __cpu_to_le32(virt_to_phys(final_td)); + head->head_pointer = __cpu_to_le32(virt_to_phys(first_td)); + + usb_debug("ohci_control(): doing transfer with %x. first_td at %x\n", + __le32_to_cpu(head->config) & ED_FUNC_MASK, __le32_to_cpu(head->head_pointer)); +#ifdef USB_DEBUG_ED + dump_ed(head); +#endif + + /* activate schedule */ + OHCI_INST(dev->controller)->opreg->HcControlHeadED = __cpu_to_le32(virt_to_phys(head)); + OHCI_INST(dev->controller)->opreg->HcControl |= __cpu_to_le32(ControlListEnable); + OHCI_INST(dev->controller)->opreg->HcCommandStatus = __cpu_to_le32(ControlListFilled); + + int failure = wait_for_ed(dev, head, + (dalen==0)?0:(last_page - first_page + 1)); + /* Wait some frames before and one after disabling list access. */ + mdelay(4); + OHCI_INST(dev->controller)->opreg->HcControl &= __cpu_to_le32(~ControlListEnable); + mdelay(1); + + /* free memory */ + ohci_free_ed(head); + + return failure; +} + +/* finalize == 1: if data is of packet aligned size, add a zero length packet */ +static int +ohci_bulk (endpoint_t *ep, int dalen, u8 *data, int finalize) +{ + int i; + usb_debug("bulk: %x bytes from %p, finalize: %x, maxpacketsize: %x\n", dalen, data, finalize, ep->maxpacketsize); + + td_t *cur, *next; + + // pages are specified as 4K in OHCI, so don't use getpagesize() + int first_page = (unsigned long)data / 4096; + int last_page = (unsigned long)(data+dalen-1)/4096; + if (last_page < first_page) last_page = first_page; + int pages = (dalen==0)?0:(last_page - first_page + 1); + int td_count = (pages+1)/2; + + if (finalize && ((dalen % ep->maxpacketsize) == 0)) { + td_count++; + } + + /* First TD. */ + td_t *const first_td; + ofmem_posix_memalign((void **)&first_td, sizeof(td_t), sizeof(td_t)); + memset((void *)first_td, 0, sizeof(*first_td)); + cur = next = first_td; + + for (i = 0; i < td_count; ++i) { + /* Advance to next TD. */ + cur = next; + cur->config = __cpu_to_le32((ep->direction == IN ? TD_DIRECTION_IN : TD_DIRECTION_OUT) | + TD_DELAY_INTERRUPT_NOINTR | + TD_TOGGLE_FROM_ED | + TD_CC_NOACCESS); + cur->current_buffer_pointer = __cpu_to_le32(virt_to_phys(data)); + pages--; + if (dalen == 0) { + /* magic TD for empty packet transfer */ + cur->current_buffer_pointer = 0; + cur->buffer_end = 0; + /* assert((pages == 0) && finalize); */ + } + int consumed = (4096 - ((unsigned long)data % 4096)); + if (consumed >= dalen) { + // end of data is within same page + cur->buffer_end = __cpu_to_le32(virt_to_phys(data + dalen - 1)); + dalen = 0; + /* assert(pages == finalize); */ + } else { + dalen -= consumed; + data += consumed; + pages--; + int second_page_size = dalen; + if (dalen > 4096) { + second_page_size = 4096; + } + cur->buffer_end = __cpu_to_le32(virt_to_phys(data + second_page_size - 1)); + dalen -= second_page_size; + data += second_page_size; + } + /* One more TD. */ + ofmem_posix_memalign((void **)&next, sizeof(td_t), sizeof(td_t)); + memset((void *)next, 0, sizeof(*next)); + /* Linked to the previous. */ + cur->next_td = __cpu_to_le32(virt_to_phys(next)); + } + + /* Write done head after last TD. */ + cur->config &= __cpu_to_le32(~TD_DELAY_INTERRUPT_MASK); + /* Advance to final, dummy TD. */ + cur = next; + + /* Data structures */ + ed_t *head; + ofmem_posix_memalign((void **)&head, sizeof(ed_t), sizeof(ed_t)); + memset((void*)head, 0, sizeof(*head)); + head->config = __cpu_to_le32((ep->dev->address << ED_FUNC_SHIFT) | + ((ep->endpoint & 0xf) << ED_EP_SHIFT) | + (((ep->direction==IN)?OHCI_IN:OHCI_OUT) << ED_DIR_SHIFT) | + (ep->dev->speed?ED_LOWSPEED:0) | + (ep->maxpacketsize << ED_MPS_SHIFT)); + head->tail_pointer = __cpu_to_le32(virt_to_phys(cur)); + head->head_pointer = __cpu_to_le32(virt_to_phys(first_td) | (ep->toggle?ED_TOGGLE:0)); + + usb_debug("doing bulk transfer with %x(%x). first_td at %lx, last %lx\n", + __le32_to_cpu(head->config) & ED_FUNC_MASK, + (__le32_to_cpu(head->config) & ED_EP_MASK) >> ED_EP_SHIFT, + virt_to_phys(first_td), virt_to_phys(cur)); + + /* activate schedule */ + OHCI_INST(ep->dev->controller)->opreg->HcBulkHeadED = __cpu_to_le32(virt_to_phys(head)); + OHCI_INST(ep->dev->controller)->opreg->HcControl |= __cpu_to_le32(BulkListEnable); + OHCI_INST(ep->dev->controller)->opreg->HcCommandStatus = __cpu_to_le32(BulkListFilled); + + int failure = wait_for_ed(ep->dev, head, + (dalen==0)?0:(last_page - first_page + 1)); + /* Wait some frames before and one after disabling list access. */ + mdelay(4); + OHCI_INST(ep->dev->controller)->opreg->HcControl &= __cpu_to_le32(~BulkListEnable); + mdelay(1); + + ep->toggle = __le32_to_cpu(head->head_pointer) & ED_TOGGLE; + + /* free memory */ + ohci_free_ed(head); + + if (failure) { + /* try cleanup */ + clear_stall(ep); + } + + return failure; +} + + +struct _intr_queue; + +struct _intrq_td { + volatile td_t td; + u8 *data; + struct _intrq_td *next; + struct _intr_queue *intrq; +}; + +struct _intr_queue { + volatile ed_t ed; + struct _intrq_td *head; + struct _intrq_td *tail; + u8 *data; + int reqsize; + endpoint_t *endp; + unsigned int remaining_tds; + int destroy; +}; + +typedef struct _intrq_td intrq_td_t; +typedef struct _intr_queue intr_queue_t; + +#define INTRQ_TD_FROM_TD(x) ((intrq_td_t *)x) + +static void +ohci_fill_intrq_td(intrq_td_t *const td, intr_queue_t *const intrq, + u8 *const data) +{ + memset(td, 0, sizeof(*td)); + td->td.config = __cpu_to_le32(TD_QUEUETYPE_INTR | + (intrq->endp->direction == IN ? TD_DIRECTION_IN : TD_DIRECTION_OUT) | + TD_DELAY_INTERRUPT_ZERO | + TD_TOGGLE_FROM_ED | + TD_CC_NOACCESS); + td->td.current_buffer_pointer = __cpu_to_le32(virt_to_phys(data)); + td->td.buffer_end = __cpu_to_le32(virt_to_phys(data) + intrq->reqsize - 1); + td->intrq = intrq; + td->data = data; +} + +/* create and hook-up an intr queue into device schedule */ +static void * +ohci_create_intr_queue(endpoint_t *const ep, const int reqsize, + const int reqcount, const int reqtiming) +{ + int i; + intrq_td_t *first_td = NULL, *last_td = NULL; + + if (reqsize > 4096) + return NULL; + + intr_queue_t *const intrq; + ofmem_posix_memalign((void **)&intrq, sizeof(intrq->ed), sizeof(*intrq)); + memset(intrq, 0, sizeof(*intrq)); + intrq->data = (u8 *)malloc(reqcount * reqsize); + intrq->reqsize = reqsize; + intrq->endp = ep; + + /* Create #reqcount TDs. */ + u8 *cur_data = intrq->data; + for (i = 0; i < reqcount; ++i) { + intrq_td_t *const td; + ofmem_posix_memalign((void **)&td, sizeof(td->td), sizeof(*td)); + ++intrq->remaining_tds; + ohci_fill_intrq_td(td, intrq, cur_data); + cur_data += reqsize; + if (!first_td) + first_td = td; + else + last_td->td.next_td = __cpu_to_le32(virt_to_phys(&td->td)); + last_td = td; + } + + /* Create last, dummy TD. */ + intrq_td_t *dummy_td; + ofmem_posix_memalign((void **)&dummy_td, sizeof(dummy_td->td), sizeof(*dummy_td)); + memset(dummy_td, 0, sizeof(*dummy_td)); + dummy_td->intrq = intrq; + if (last_td) + last_td->td.next_td = __cpu_to_le32(virt_to_phys(&dummy_td->td)); + last_td = dummy_td; + + /* Initialize ED. */ + intrq->ed.config = __cpu_to_le32((ep->dev->address << ED_FUNC_SHIFT) | + ((ep->endpoint & 0xf) << ED_EP_SHIFT) | + (((ep->direction == IN) ? OHCI_IN : OHCI_OUT) << ED_DIR_SHIFT) | + (ep->dev->speed ? ED_LOWSPEED : 0) | + (ep->maxpacketsize << ED_MPS_SHIFT)); + intrq->ed.tail_pointer = __cpu_to_le32(virt_to_phys(last_td)); + intrq->ed.head_pointer = __cpu_to_le32(virt_to_phys(first_td) | (ep->toggle ? ED_TOGGLE : 0)); + +#ifdef USB_DEBUG_ED + dump_ed(&intrq->ed); +#endif + /* Insert ED into periodic table. */ + int nothing_placed = 1; + ohci_t *const ohci = OHCI_INST(ep->dev->controller); + u32 *const intr_table = ohci->hcca->HccaInterruptTable; + const u32 dummy_ptr = __cpu_to_le32(virt_to_phys(ohci->periodic_ed)); + for (i = 0; i < 32; i += reqtiming) { + /* Advance to the next free position. */ + while ((i < 32) && (intr_table[i] != dummy_ptr)) ++i; + if (i < 32) { + usb_debug("Placed endpoint %lx to %d\n", virt_to_phys(&intrq->ed), i); + intr_table[i] = __cpu_to_le32(virt_to_phys(&intrq->ed)); + nothing_placed = 0; + } + } + if (nothing_placed) { + usb_debug("Error: Failed to place ohci interrupt endpoint " + "descriptor into periodic table: no space left\n"); + ohci_destroy_intr_queue(ep, intrq); + return NULL; + } + + return intrq; +} + +/* remove queue from device schedule, dropping all data that came in */ +static void +ohci_destroy_intr_queue(endpoint_t *const ep, void *const q_) +{ + intr_queue_t *const intrq = (intr_queue_t *)q_; + + int i; + + /* Remove interrupt queue from periodic table. */ + ohci_t *const ohci = OHCI_INST(ep->dev->controller); + u32 *const intr_table = ohci->hcca->HccaInterruptTable; + for (i=0; i < 32; ++i) { + if (intr_table[i] == __cpu_to_le32(virt_to_phys(intrq))) + intr_table[i] = __cpu_to_le32(virt_to_phys(ohci->periodic_ed)); + } + /* Wait for frame to finish. */ + mdelay(1); + + /* Free unprocessed TDs. */ + while ((__le32_to_cpu(intrq->ed.head_pointer) & ~0x3) != __le32_to_cpu(intrq->ed.tail_pointer)) { + td_t *const cur_td = (td_t *)phys_to_virt(__le32_to_cpu(intrq->ed.head_pointer) & ~0x3); + intrq->ed.head_pointer = cur_td->next_td; + free(INTRQ_TD_FROM_TD(cur_td)); + --intrq->remaining_tds; + } + /* Free final, dummy TD. */ + free(phys_to_virt(__le32_to_cpu(intrq->ed.head_pointer) & ~0x3)); + /* Free data buffer. */ + free(intrq->data); + + /* Free TDs already fetched from the done queue. */ + ohci_process_done_queue(ohci, 1); + while (intrq->head) { + intrq_td_t *const cur_td = (intrq_td_t *const )__le32_to_cpu(intrq->head); + intrq->head = intrq->head->next; + free(cur_td); + --intrq->remaining_tds; + } + + /* Mark interrupt queue to be destroyed. + ohci_process_done_queue() will free the remaining TDs + and finish the interrupt queue off once all TDs are gone. */ + intrq->destroy = 1; + + /* Save data toggle. */ + ep->toggle = __le32_to_cpu(intrq->ed.head_pointer) & ED_TOGGLE; +} + +/* read one intr-packet from queue, if available. extend the queue for new input. + return NULL if nothing new available. + Recommended use: while (data=poll_intr_queue(q)) process(data); + */ +static u8 * +ohci_poll_intr_queue(void *const q_) +{ + intr_queue_t *const intrq = (intr_queue_t *)q_; + + u8 *data = NULL; + + /* Process done queue first, then check if we have work to do. */ + ohci_process_done_queue(OHCI_INST(intrq->endp->dev->controller), 0); + + if (intrq->head) { + /* Save pointer to processed TD and advance. */ + intrq_td_t *const cur_td = intrq->head; + intrq->head = cur_td->next; + + /* Return data buffer of this TD. */ + data = cur_td->data; + + /* Requeue this TD (i.e. copy to dummy and requeue as dummy). */ + intrq_td_t *const dummy_td = + INTRQ_TD_FROM_TD(phys_to_virt(__le32_to_cpu(intrq->ed.tail_pointer))); + ohci_fill_intrq_td(dummy_td, intrq, data); + /* Reset all but intrq pointer (i.e. init as dummy). */ + memset(cur_td, 0, sizeof(*cur_td)); + cur_td->intrq = intrq; + /* Insert into interrupt queue as dummy. */ + dummy_td->td.next_td = __le32_to_cpu(virt_to_phys(&cur_td->td)); + intrq->ed.tail_pointer = __le32_to_cpu(virt_to_phys(&cur_td->td)); + } + + return data; +} + +static void +ohci_process_done_queue(ohci_t *const ohci, const int spew_debug) +{ + int i, j; + + /* Temporary queue of interrupt queue TDs (to reverse order). */ + intrq_td_t *temp_tdq = NULL; + + /* Check if done head has been written. */ + if (!(READ_OPREG(ohci, HcInterruptStatus) & WritebackDoneHead)) + return; + /* Fetch current done head. + Lsb is only interesting for hw interrupts. */ + u32 phys_done_queue = __le32_to_cpu(ohci->hcca->HccaDoneHead) & ~1; + /* Tell host controller, he may overwrite the done head pointer. */ + ohci->opreg->HcInterruptStatus = __cpu_to_le32(WritebackDoneHead); + + i = 0; + /* Process done queue (it's in reversed order). */ + while (phys_done_queue) { + td_t *const done_td = (td_t *)phys_to_virt(phys_done_queue); + + /* Advance pointer to next TD. */ + phys_done_queue = __le32_to_cpu(done_td->next_td); + + switch (__le32_to_cpu(done_td->config) & TD_QUEUETYPE_MASK) { + case TD_QUEUETYPE_ASYNC: + /* Free processed async TDs. */ + free((void *)done_td); + break; + case TD_QUEUETYPE_INTR: { + intrq_td_t *const td = INTRQ_TD_FROM_TD(done_td); + intr_queue_t *const intrq = td->intrq; + /* Check if the corresponding interrupt + queue is still beeing processed. */ + if (intrq->destroy) { + /* Free this TD, and */ + free(td); + --intrq->remaining_tds; + /* the interrupt queue if it has no more TDs. */ + if (!intrq->remaining_tds) + free(intrq); + usb_debug("Freed TD from orphaned interrupt " + "queue, %d TDs remain.\n", + intrq->remaining_tds); + } else { + /* Save done TD to be processed. */ + td->next = temp_tdq; + temp_tdq = td; + } + break; + } + default: + break; + } + ++i; + } + if (spew_debug) + usb_debug("Processed %d done TDs.\n", i); + + j = 0; + /* Process interrupt queue TDs in right order. */ + while (temp_tdq) { + /* Save pointer of current TD and advance. */ + intrq_td_t *const cur_td = temp_tdq; + temp_tdq = temp_tdq->next; + + /* The interrupt queue for the current TD. */ + intr_queue_t *const intrq = cur_td->intrq; + /* Append to interrupt queue. */ + if (!intrq->head) { + /* First element. */ + intrq->head = intrq->tail = cur_td; + } else { + /* Insert at tail. */ + intrq->tail->next = cur_td; + intrq->tail = cur_td; + } + /* It's always the last element. */ + cur_td->next = NULL; + ++j; + } + if (spew_debug) + usb_debug("processed %d done tds, %d intr tds thereof.\n", i, j); +} + +int ob_usb_ohci_init (const char *path, uint32_t addr) +{ + hci_t *ctrl; + int i; + + usb_debug("ohci_init: %s addr = %x\n", path, addr); + ctrl = ohci_pci_init(addr); + if (!ctrl) + return 0; + + /* Init ports */ + usb_poll(); + + /* Look for a keyboard */ + for (i = 0; i < 128; i++) { + if (ctrl->devices[i] && ctrl->devices[i]->configuration) { + configuration_descriptor_t *cd; + interface_descriptor_t *intf; + + cd = (configuration_descriptor_t *)ctrl->devices[i]->configuration; + intf = (interface_descriptor_t *)(ctrl->devices[i]->configuration + cd->bLength); + usb_debug("Device at port %d is class %d\n", i, intf->bInterfaceClass); + if (intf->bInterfaceClass == hid_device && + intf->bInterfaceSubClass == hid_subclass_boot && + intf->bInterfaceProtocol == hid_boot_proto_keyboard ) { + break; + } + } + } + if ( i < 128 ) + ob_usb_hid_add_keyboard(path); + + return 1; +} diff --git a/qemu/roms/openbios/drivers/usbohci.h b/qemu/roms/openbios/drivers/usbohci.h new file mode 100644 index 000000000..690332871 --- /dev/null +++ b/qemu/roms/openbios/drivers/usbohci.h @@ -0,0 +1,45 @@ +/* + * Driver for USB OHCI ported from CoreBoot + * + * Copyright (C) 2014 BALATON Zoltan + * + * This file was part of the libpayload project. + * + * Copyright (C) 2010 Patrick Georgi + * + * 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. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + */ + +#ifndef __OHCI_H +#define __OHCI_H + +#include "config.h" +#include "usbohci_private.h" + +hci_t *ohci_pci_init (u32 addr); +hci_t *ohci_init (void *bar); + +void ohci_rh_init (usbdev_t *dev); + +#endif diff --git a/qemu/roms/openbios/drivers/usbohci_private.h b/qemu/roms/openbios/drivers/usbohci_private.h new file mode 100644 index 000000000..b3a723e21 --- /dev/null +++ b/qemu/roms/openbios/drivers/usbohci_private.h @@ -0,0 +1,270 @@ +/* + * Driver for USB OHCI ported from CoreBoot + * + * Copyright (C) 2014 BALATON Zoltan + * + * This file was part of the libpayload project. + * + * Copyright (C) 2010 Patrick Georgi + * + * 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. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + */ + +#ifndef __OHCI_PRIVATE_H +#define __OHCI_PRIVATE_H + +#include "libc/byteorder.h" +#include "usb.h" + +#define READ_OPREG(ohci, field) (__le32_to_cpu((ohci)->opreg->field)) +#define MASK(startbit, lenbit) (((1<<(lenbit))-1)<<(startbit)) + + // FIXME: fake + typedef enum { CMD} reg; + + enum { + NumberDownstreamPorts = 1<<0, + PowerSwitchingMode = 1<<8, + NoPowerSwitching = 1<<9, + DeviceType = 1<<10, + OverCurrentProtectionMode = 1<<11, + NoOverCurrentProtection = 1<<12, + PowerOnToPowerGoodTime = 1<<24 + } HcRhDescriptorAReg; + + enum { + NumberDownstreamPortsMask = MASK(0, 8), + PowerOnToPowerGoodTimeMask = MASK(24, 8) + } HcRhDescriptorAMask; + + enum { + DeviceRemovable = 1<<0, + PortPowerControlMask = 1<<16 + } HcRhDescriptorBReg; + + enum { + CurrentConnectStatus = 1<<0, + PortEnableStatus = 1<<1, + PortSuspendStatus = 1<<2, + PortOverCurrentIndicator = 1<<3, + PortResetStatus = 1<<4, + PortPowerStatus = 1<<8, + LowSpeedDeviceAttached = 1<<9, + ConnectStatusChange = 1<<16, + PortEnableStatusChange = 1<<17, + PortSuspendStatusChange = 1<<18, + PortOverCurrentIndicatorChange = 1<<19, + PortResetStatusChange = 1<<20 + } HcRhPortStatusRead; + enum { + ClearPortEnable = 1<<0, + SetPortEnable = 1<<1, + SetPortSuspend = 1<<2, + ClearSuspendStatus = 1<<3, + SetPortReset = 1<<4, + SetPortPower = 1<<8, + ClearPortPower = 1<<9, + } HcRhPortStatusSet; + + enum { + LocalPowerStatus = 1<<0, + OverCurrentIndicator = 1<<1, + DeviceRemoteWakeupEnable = 1<<15, + LocalPowerStatusChange = 1<<16, + OverCurrentIndicatorChange = 1<<17, + ClearRemoteWakeupEnable = 1<<31 + } HcRhStatusReg; + + enum { + FrameInterval = 1<<0, + FSLargestDataPacket = 1<<16, + FrameIntervalToggle = 1<<31 + } HcFmIntervalOffset; + enum { + FrameIntervalMask = MASK(0, 14), + FSLargestDataPacketMask = MASK(16, 15), + FrameIntervalToggleMask = MASK(31, 1) + } HcFmIntervalMask; + + enum { + ControlBulkServiceRatio = 1<<0, + PeriodicListEnable = 1<<2, + IsochronousEnable = 1<<3, + ControlListEnable = 1<<4, + BulkListEnable = 1<<5, + HostControllerFunctionalState = 1<<6, + InterruptRouting = 1<<8, + RemoteWakeupConnected = 1<<9, + RemoteWakeupEnable = 1<<10 + } HcControlReg; + + enum { + ControlBulkServiceRatioMask = MASK(0, 2), + HostControllerFunctionalStateMask = MASK(6, 2) + } HcControlMask; + + enum { + USBReset = 0*HostControllerFunctionalState, + USBResume = 1*HostControllerFunctionalState, + USBOperational = 2*HostControllerFunctionalState, + USBSuspend = 3*HostControllerFunctionalState + }; + + enum { + HostControllerReset = 1<<0, + ControlListFilled = 1<<1, + BulkListFilled = 1<<2, + OwnershipChangeRequest = 1<<3, + SchedulingOverrunCount = 1<<16 + } HcCommandStatusReg; + + enum { + SchedulingOverrunCountMask = MASK(16, 2) + } HcCommandStatusMask; + + enum { + FrameRemaining = 1<<0, + FrameRemainingToggle = 1<<31 + } HcFmRemainingReg; + + enum { + SchedulingOverrung = 1<<0, + WritebackDoneHead = 1<<1, + StartofFrame = 1<<2, + ResumeDetected = 1<<3, + UnrecoverableError = 1<<4, + FrameNumberOverflow = 1<<5, + RootHubStatusChange = 1<<6, + OwnershipChange = 1<<30 + } HcInterruptStatusReg; + + typedef struct { + // Control and Status Partition + volatile u32 HcRevision; + volatile u32 HcControl; + volatile u32 HcCommandStatus; + volatile u32 HcInterruptStatus; + volatile u32 HcInterruptEnable; + volatile u32 HcInterruptDisable; + + // Memory Pointer Partition + volatile u32 HcHCCA; + volatile u32 HcPeriodCurrentED; + volatile u32 HcControlHeadED; + volatile u32 HcControlCurrentED; + volatile u32 HcBulkHeadED; + volatile u32 HcBulkCurrentED; + volatile u32 HcDoneHead; + + // Frame Counter Partition + volatile u32 HcFmInterval; + volatile u32 HcFmRemaining; + volatile u32 HcFmNumber; + volatile u32 HcPeriodicStart; + volatile u32 HcLSThreshold; + + // Root Hub Partition + volatile u32 HcRhDescriptorA; + volatile u32 HcRhDescriptorB; + volatile u32 HcRhStatus; + /* all bits in HcRhPortStatus registers are R/WC, so + _DO NOT_ use |= to set the bits, + this clears the entire state */ + volatile u32 HcRhPortStatus[]; + } __attribute__ ((packed)) opreg_t; + + typedef struct { /* should be 256 bytes according to spec */ + u32 HccaInterruptTable[32]; + volatile u16 HccaFrameNumber; + volatile u16 HccaPad1; + volatile u32 HccaDoneHead; + u8 reserved[116]; /* pad according to spec */ + u8 what[4]; /* really pad to 256 as spec only covers 252 */ + } __attribute__ ((packed)) hcca_t; + + typedef volatile struct { + u32 config; + u32 tail_pointer; + u32 head_pointer; + u32 next_ed; + } __attribute__ ((packed)) ed_t; +#define ED_HALTED 1 +#define ED_TOGGLE 2 + +#define ED_FUNC_SHIFT 0 +#define ED_FUNC_MASK MASK(0, 7) +#define ED_EP_SHIFT 7 +#define ED_EP_MASK MASK(7, 4) +#define ED_DIR_SHIFT 11 +#define ED_DIR_MASK MASK(11, 2) +#define ED_LOWSPEED (1 << 13) +#define ED_MPS_SHIFT 16 + + typedef volatile struct { + u32 config; + u32 current_buffer_pointer; + u32 next_td; + u32 buffer_end; + } __attribute__ ((packed)) td_t; +/* + * Bits 0 through 17 of .config won't be interpreted by the host controller + * (HC) and, after processing the TD, the HC has to ensure those bits have + * the same state as before. So we are free to use those bits for our own + * purpose. + */ +#define TD_QUEUETYPE_SHIFT 0 +#define TD_QUEUETYPE_MASK MASK(TD_QUEUETYPE_SHIFT, 2) +#define TD_QUEUETYPE_ASYNC (0 << TD_QUEUETYPE_SHIFT) +#define TD_QUEUETYPE_INTR (1 << TD_QUEUETYPE_SHIFT) + +#define TD_DIRECTION_SHIFT 19 +#define TD_DIRECTION_MASK MASK(TD_DIRECTION_SHIFT, 2) +#define TD_DIRECTION_SETUP OHCI_SETUP << TD_DIRECTION_SHIFT +#define TD_DIRECTION_IN OHCI_IN << TD_DIRECTION_SHIFT +#define TD_DIRECTION_OUT OHCI_OUT << TD_DIRECTION_SHIFT +#define TD_DELAY_INTERRUPT_SHIFT 21 +#define TD_DELAY_INTERRUPT_MASK MASK(TD_DELAY_INTERRUPT_SHIFT, 3) +#define TD_DELAY_INTERRUPT_ZERO 0 +#define TD_DELAY_INTERRUPT_NOINTR (7 << TD_DELAY_INTERRUPT_SHIFT) +#define TD_TOGGLE_DATA0 0 +#define TD_TOGGLE_DATA1 (1 << 24) +#define TD_TOGGLE_FROM_ED 0 +#define TD_TOGGLE_FROM_TD (1 << 25) +#define TD_CC_SHIFT 28 +#define TD_CC_MASK MASK(TD_CC_SHIFT, 4) +#define TD_CC_NOERR 0 +#define TD_CC_NOACCESS (14 << TD_CC_SHIFT) /* the lower of the two values, so "no access" can be tested with >= */ + +#define OHCI_INST(controller) ((ohci_t*)((controller)->instance)) + + typedef struct ohci { + opreg_t *opreg; + hcca_t *hcca; + usbdev_t *roothub; + ed_t *periodic_ed; + } ohci_t; + + typedef enum { OHCI_SETUP=0, OHCI_OUT=1, OHCI_IN=2, OHCI_FROM_TD=3 } ohci_pid_t; + +#endif diff --git a/qemu/roms/openbios/drivers/usbohci_rh.c b/qemu/roms/openbios/drivers/usbohci_rh.c new file mode 100644 index 000000000..55503be61 --- /dev/null +++ b/qemu/roms/openbios/drivers/usbohci_rh.c @@ -0,0 +1,212 @@ +/* + * Driver for USB OHCI Root Hubs ported from CoreBoot + * + * Copyright (C) 2014 BALATON Zoltan + * + * This file was part of the libpayload project. + * + * Copyright (C) 2010 Patrick Georgi + * + * 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. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + */ + +#include "config.h" +#include "timer.h" +#include "usbohci_private.h" +#include "usbohci.h" + +typedef struct { + int numports; + int *port; +} rh_inst_t; + +#define RH_INST(dev) ((rh_inst_t*)(dev)->data) + +static void +ohci_rh_enable_port (usbdev_t *dev, int port) +{ + /* Reset RH port should hold 50ms with pulses of at least 10ms and + * gaps of at most 3ms (usb20 spec 7.1.7.5). + * After reset, the port will be enabled automatically (ohci spec + * 7.4.4). + */ + int total_delay = 100; /* 100 * 500us == 50ms */ + while (total_delay > 0) { + if (!(READ_OPREG(OHCI_INST(dev->controller), HcRhPortStatus[port]) + & CurrentConnectStatus)) + return; + + /* start reset */ + OHCI_INST (dev->controller)->opreg->HcRhPortStatus[port] = + __cpu_to_le32(SetPortReset); + int timeout = 200; /* timeout after 200 * 500us == 100ms */ + while ((READ_OPREG(OHCI_INST(dev->controller), HcRhPortStatus[port]) + & PortResetStatus) + && timeout--) { + udelay(500); total_delay--; + } + if (READ_OPREG(OHCI_INST(dev->controller), HcRhPortStatus[port]) + & PortResetStatus) { + usb_debug("Warning: root-hub port reset timed out.\n"); + break; + } + if ((200-timeout) < 20) { + usb_debug("Warning: port reset too short: %dms; " + "should be at least 10ms.\n", + (200-timeout)/2); + total_delay = 0; /* can happen on QEMU */ + } + /* clear reset status change */ + OHCI_INST(dev->controller)->opreg->HcRhPortStatus[port] = + __cpu_to_le32(PortResetStatusChange); + usb_debug ("rh port reset finished after %dms.\n", (200-timeout)/2); + } +} + +/* disable root hub */ +static void +ohci_rh_disable_port (usbdev_t *dev, int port) +{ + OHCI_INST (dev->controller)->opreg->HcRhPortStatus[port] = + __cpu_to_le32(ClearPortEnable); // disable port + int timeout = 50; /* timeout after 50 * 100us == 5ms */ + while ((READ_OPREG(OHCI_INST (dev->controller), HcRhPortStatus[port]) + & PortEnableStatus) + && timeout--) { + udelay(100); + } +} + +static void +ohci_rh_scanport (usbdev_t *dev, int port) +{ + if (port >= RH_INST(dev)->numports) { + usb_debug("Invalid port %d\n", port); + return; + } + + /* device registered, and device change logged, so something must have happened */ + if (RH_INST (dev)->port[port] != -1) { + usb_detach_device(dev->controller, RH_INST (dev)->port[port]); + RH_INST (dev)->port[port] = -1; + } + + /* no device attached + previously registered devices are detached, nothing left to do */ + if (!(READ_OPREG(OHCI_INST(dev->controller), HcRhPortStatus[port]) & CurrentConnectStatus)) + return; + + // clear port state change + OHCI_INST(dev->controller)->opreg->HcRhPortStatus[port] = __cpu_to_le32(ConnectStatusChange); + ohci_rh_enable_port (dev, port); + + mdelay(100); // wait for signal to stabilize + + if (!(READ_OPREG(OHCI_INST(dev->controller), HcRhPortStatus[port]) & PortEnableStatus)) { + usb_debug ("port enable failed\n"); + return; + } + + int speed = (READ_OPREG(OHCI_INST(dev->controller), HcRhPortStatus[port]) & LowSpeedDeviceAttached) != 0; + RH_INST (dev)->port[port] = usb_attach_device(dev->controller, dev->address, port, speed); +} + +static int +ohci_rh_report_port_changes (usbdev_t *dev) +{ + ohci_t *const ohcic = OHCI_INST (dev->controller); + + int i; + + for (i = 0; i < RH_INST(dev)->numports; i++) { + // maybe detach+attach happened between two scans? + if (READ_OPREG(ohcic, HcRhPortStatus[i]) & ConnectStatusChange) { + ohcic->opreg->HcRhPortStatus[i] = __cpu_to_le32(ConnectStatusChange); + usb_debug("attachment change on port %d\n", i); + return i; + } + } + + // no change + return -1; +} + +static void +ohci_rh_destroy (usbdev_t *dev) +{ + int i; + for (i = 0; i < RH_INST (dev)->numports; i++) + ohci_rh_disable_port (dev, i); + free (RH_INST (dev)); +} + +static void +ohci_rh_poll (usbdev_t *dev) +{ + ohci_t *const ohcic = OHCI_INST (dev->controller); + + int port; + + /* Check if anything changed. */ + if (!(READ_OPREG(ohcic, HcInterruptStatus) & RootHubStatusChange)) + return; + ohcic->opreg->HcInterruptStatus = __cpu_to_le32(RootHubStatusChange); + usb_debug("root hub status change\n"); + + /* Scan ports with changed connection status. */ + while ((port = ohci_rh_report_port_changes (dev)) != -1) + ohci_rh_scanport (dev, port); +} + +void +ohci_rh_init (usbdev_t *dev) +{ + int i; + + dev->destroy = ohci_rh_destroy; + dev->poll = ohci_rh_poll; + + dev->data = malloc (sizeof (rh_inst_t)); + if (!dev->data) { + printk("Not enough memory for OHCI RH.\n"); + return; + } + + RH_INST (dev)->numports = READ_OPREG(OHCI_INST(dev->controller), HcRhDescriptorA) & NumberDownstreamPortsMask; + RH_INST (dev)->port = malloc(sizeof(int) * RH_INST (dev)->numports); + usb_debug("%d ports registered\n", RH_INST (dev)->numports); + + for (i = 0; i < RH_INST (dev)->numports; i++) { + ohci_rh_enable_port (dev, i); + RH_INST (dev)->port[i] = -1; + } + + /* we can set them here because a root hub _really_ shouldn't + appear elsewhere */ + dev->address = 0; + dev->hub = -1; + dev->port = -1; + + usb_debug("rh init done\n"); +} diff --git a/qemu/roms/openbios/drivers/vga.fs b/qemu/roms/openbios/drivers/vga.fs new file mode 100644 index 000000000..ec4c6c5f1 --- /dev/null +++ b/qemu/roms/openbios/drivers/vga.fs @@ -0,0 +1,204 @@ +\ +\ Fcode payload for QEMU VGA graphics card +\ +\ This is the Forth source for an Fcode payload to initialise +\ the QEMU VGA graphics card. +\ +\ (C) Copyright 2013 Mark Cave-Ayland +\ + +fcode-version3 + +\ +\ Dictionary lookups for words that don't have an FCode +\ + +: (find-xt) \ ( str len -- xt | -1 ) + $find if + exit + else + -1 + then +; + +" openbios-video-width" (find-xt) cell+ value openbios-video-width-xt +" openbios-video-height" (find-xt) cell+ value openbios-video-height-xt +" depth-bits" (find-xt) cell+ value depth-bits-xt +" line-bytes" (find-xt) cell+ value line-bytes-xt + +: openbios-video-width openbios-video-width-xt @ ; +: openbios-video-height openbios-video-height-xt @ ; +: depth-bits depth-bits-xt @ ; +: line-bytes line-bytes-xt @ ; + +" fb8-fillrect" (find-xt) value fb8-fillrect-xt +: fb8-fillrect fb8-fillrect-xt execute ; + +\ +\ IO port words +\ + +" ioc!" (find-xt) value ioc!-xt +" iow!" (find-xt) value iow!-xt + +: ioc! ioc!-xt execute ; +: iow! iow!-xt execute ; + +\ +\ VGA registers +\ + +h# 3c0 constant vga-addr +h# 3c8 constant dac-write-addr +h# 3c9 constant dac-data-addr + +: vga-color! ( r g b index -- ) + \ Set the VGA colour registers + dac-write-addr ioc! rot + 2 >> dac-data-addr ioc! swap + 2 >> dac-data-addr ioc! + 2 >> dac-data-addr ioc! +; + +\ +\ VBE registers +\ + +h# 0 constant VBE_DISPI_INDEX_ID +h# 1 constant VBE_DISPI_INDEX_XRES +h# 2 constant VBE_DISPI_INDEX_YRES +h# 3 constant VBE_DISPI_INDEX_BPP +h# 4 constant VBE_DISPI_INDEX_ENABLE +h# 5 constant VBE_DISPI_INDEX_BANK +h# 6 constant VBE_DISPI_INDEX_VIRT_WIDTH +h# 7 constant VBE_DISPI_INDEX_VIRT_HEIGHT +h# 8 constant VBE_DISPI_INDEX_X_OFFSET +h# 9 constant VBE_DISPI_INDEX_Y_OFFSET +h# a constant VBE_DISPI_INDEX_NB + +h# 0 constant VBE_DISPI_DISABLED +h# 1 constant VBE_DISPI_ENABLED + +\ +\ Bochs VBE register writes +\ + +: vbe-iow! ( val addr -- ) + h# 1ce iow! + h# 1d0 iow! +; + +\ +\ Initialise Bochs VBE mode +\ + +: vbe-init ( -- ) + h# 0 vga-addr ioc! \ Enable blanking + VBE_DISPI_DISABLED VBE_DISPI_INDEX_ENABLE vbe-iow! + h# 0 VBE_DISPI_INDEX_X_OFFSET vbe-iow! + h# 0 VBE_DISPI_INDEX_Y_OFFSET vbe-iow! + openbios-video-width VBE_DISPI_INDEX_XRES vbe-iow! + openbios-video-height VBE_DISPI_INDEX_YRES vbe-iow! + depth-bits VBE_DISPI_INDEX_BPP vbe-iow! + VBE_DISPI_ENABLED VBE_DISPI_INDEX_ENABLE vbe-iow! + h# 0 vga-addr ioc! + h# 20 vga-addr ioc! \ Disable blanking +; + +\ +\ PCI +\ + +" pci-bar>pci-region" (find-xt) value pci-bar>pci-region-xt +: pci-bar>pci-region pci-bar>pci-region-xt execute ; + +h# 10 constant cfg-bar0 \ Framebuffer BAR +-1 value fb-addr + +: map-fb ( -- ) + cfg-bar0 pci-bar>pci-region \ ( pci-addr.lo pci-addr.hi size ) + " pci-map-in" $call-parent + to fb-addr +; + +\ +\ Publically visible words +\ + +external + +[IFDEF] CONFIG_MOL +defer mol-color! + +\ Hook for MOL (see packages/molvideo.c) +\ +\ Perhaps for neatness this there should be a separate molvga.fs +\ but let's leave it here for now. + +: color! ( r g b index -- ) + mol-color! +; + +[ELSE] + +\ Standard VGA + +: color! ( r g b index -- ) + vga-color! +; + +[THEN] + +: fill-rectangle ( color_ind x y width height -- ) + fb8-fillrect +; + +: dimensions ( -- width height ) + openbios-video-width + openbios-video-height +; + +: set-colors ( table start count -- ) + 0 do + over dup \ ( table start table table ) + c@ swap 1+ \ ( table start r table-g ) + dup c@ swap 1+ \ ( table start r g table-b ) + c@ 3 pick \ ( table start r g b index ) + color! \ ( table start ) + 1+ + swap 3 + swap \ ( table+3 start+1 ) + loop +; + +headerless + +\ +\ Installation +\ + +: qemu-vga-driver-install ( -- ) + fb-addr -1 = if + map-fb fb-addr to frame-buffer-adr + default-font set-font + + frame-buffer-adr encode-int " address" property + + openbios-video-width openbios-video-height over char-width / over char-height / + fb8-install + then +; + +: qemu-vga-driver-init + + vbe-init + openbios-video-width encode-int " width" property + openbios-video-height encode-int " height" property + depth-bits encode-int " depth" property + line-bytes encode-int " linebytes" property + + ['] qemu-vga-driver-install is-install +; + +qemu-vga-driver-init + +end0 diff --git a/qemu/roms/openbios/drivers/vga.h b/qemu/roms/openbios/drivers/vga.h new file mode 100644 index 000000000..a37e66e62 --- /dev/null +++ b/qemu/roms/openbios/drivers/vga.h @@ -0,0 +1,231 @@ +/* + * + * modified + * by Steve M. Gehlbach <steve@kesa.com> + * + * Originally from linux/drivers/video/vga16.c by + * Ben Pfaff <pfaffben@debian.org> and Petr Vandrovec <VANDROVE@vc.cvut.cz> + * Copyright 1999 Ben Pfaff <pfaffben@debian.org> and Petr Vandrovec <VANDROVE@vc.cvut.cz> + * Based on VGA info at http://www.goodnet.com/~tinara/FreeVGA/home.htm + * Based on VESA framebuffer (c) 1998 Gerd Knorr <kraxel@goldbach.in-berlin.de> + * + */ + +#ifndef VGA_H_INCL +#define VGA_H_INCL 1 + +#include "drivers/vga.h" + +//#include <cpu/p5/io.h> + +#define u8 unsigned char +#define u16 unsigned short +#define u32 unsigned int +#define __u32 u32 + +#define VERROR -1 +#define CHAR_HEIGHT 16 +#define LINES 25 +#define COLS 80 + +// macros for writing to vga regs +#define write_crtc(data,addr) outb(addr,CRT_IC); outb(data,CRT_DC) +#define write_att(data,addr) inb(IS1_RC); inb(0x80); outb(addr,ATT_IW); inb(0x80); outb(data,ATT_IW); inb(0x80) +#define write_seq(data,addr) outb(addr,SEQ_I); outb(data,SEQ_D) +#define write_gra(data,addr) outb(addr,GRA_I); outb(data,GRA_D) +u8 read_seq_b(u16 addr); +u8 read_gra_b(u16 addr); +u8 read_crtc_b(u16 addr); +u8 read_att_b(u16 addr); + + +#ifdef VGA_HARDWARE_FIXUP +void vga_hardware_fixup(void); +#else +#define vga_hardware_fixup() do{} while(0) +#endif + +#define SYNC_HOR_HIGH_ACT 1 /* horizontal sync high active */ +#define SYNC_VERT_HIGH_ACT 2 /* vertical sync high active */ +#define SYNC_EXT 4 /* external sync */ +#define SYNC_COMP_HIGH_ACT 8 /* composite sync high active */ +#define SYNC_BROADCAST 16 /* broadcast video timings */ + /* vtotal = 144d/288n/576i => PAL */ + /* vtotal = 121d/242n/484i => NTSC */ + +#define SYNC_ON_GREEN 32 /* sync on green */ + +#define VMODE_NONINTERLACED 0 /* non interlaced */ +#define VMODE_INTERLACED 1 /* interlaced */ +#define VMODE_DOUBLE 2 /* double scan */ +#define VMODE_MASK 255 + +#define VMODE_YWRAP 256 /* ywrap instead of panning */ +#define VMODE_SMOOTH_XPAN 512 /* smooth xpan possible (internally used) */ +#define VMODE_CONUPDATE 512 /* don't update x/yoffset */ + +/* VGA data register ports */ +#define CRT_DC 0x3D5 /* CRT Controller Data Register - color emulation */ +#define CRT_DM 0x3B5 /* CRT Controller Data Register - mono emulation */ +#define ATT_R 0x3C1 /* Attribute Controller Data Read Register */ +#define GRA_D 0x3CF /* Graphics Controller Data Register */ +#define SEQ_D 0x3C5 /* Sequencer Data Register */ + +#define MIS_R 0x3CC // Misc Output Read Register +#define MIS_W 0x3C2 // Misc Output Write Register + +#define IS1_RC 0x3DA /* Input Status Register 1 - color emulation */ +#define IS1_RM 0x3BA /* Input Status Register 1 - mono emulation */ +#define PEL_D 0x3C9 /* PEL Data Register */ +#define PEL_MSK 0x3C6 /* PEL mask register */ + +/* EGA-specific registers */ +#define GRA_E0 0x3CC /* Graphics enable processor 0 */ +#define GRA_E1 0x3CA /* Graphics enable processor 1 */ + + +/* VGA index register ports */ +#define CRT_IC 0x3D4 /* CRT Controller Index - color emulation */ +#define CRT_IM 0x3B4 /* CRT Controller Index - mono emulation */ +#define ATT_IW 0x3C0 /* Attribute Controller Index & Data Write Register */ +#define GRA_I 0x3CE /* Graphics Controller Index */ +#define SEQ_I 0x3C4 /* Sequencer Index */ +#define PEL_IW 0x3C8 /* PEL Write Index */ +#define PEL_IR 0x3C7 /* PEL Read Index */ +#define DAC_REG 0x3C8 /* DAC register */ +#define DAC_VAL 0x3C9 /* DAC value */ + +/* standard VGA indexes max counts */ +#define CRTC_C 25 /* 25 CRT Controller Registers sequentially set*/ + // the remainder are not in the par array +#define ATT_C 21 /* 21 Attribute Controller Registers */ +#define GRA_C 9 /* 9 Graphics Controller Registers */ +#define SEQ_C 5 /* 5 Sequencer Registers */ +#define MIS_C 1 /* 1 Misc Output Register */ + +#define CRTC_H_TOTAL 0 +#define CRTC_H_DISP 1 +#define CRTC_H_BLANK_START 2 +#define CRTC_H_BLANK_END 3 +#define CRTC_H_SYNC_START 4 +#define CRTC_H_SYNC_END 5 +#define CRTC_V_TOTAL 6 +#define CRTC_OVERFLOW 7 +#define CRTC_PRESET_ROW 8 +#define CRTC_MAX_SCAN 9 +#define CRTC_CURSOR_START 0x0A +#define CRTC_CURSOR_END 0x0B +#define CRTC_START_HI 0x0C +#define CRTC_START_LO 0x0D +#define CRTC_CURSOR_HI 0x0E +#define CRTC_CURSOR_LO 0x0F +#define CRTC_V_SYNC_START 0x10 +#define CRTC_V_SYNC_END 0x11 +#define CRTC_V_DISP_END 0x12 +#define CRTC_OFFSET 0x13 +#define CRTC_UNDERLINE 0x14 +#define CRTC_V_BLANK_START 0x15 +#define CRTC_V_BLANK_END 0x16 +#define CRTC_MODE 0x17 +#define CRTC_LINE_COMPARE 0x18 + +#define ATC_MODE 0x10 +#define ATC_OVERSCAN 0x11 +#define ATC_PLANE_ENABLE 0x12 +#define ATC_PEL 0x13 +#define ATC_COLOR_PAGE 0x14 + +#define SEQ_CLOCK_MODE 0x01 +#define SEQ_PLANE_WRITE 0x02 +#define SEQ_CHARACTER_MAP 0x03 +#define SEQ_MEMORY_MODE 0x04 + +#define GDC_SR_VALUE 0x00 +#define GDC_SR_ENABLE 0x01 +#define GDC_COMPARE_VALUE 0x02 +#define GDC_DATA_ROTATE 0x03 +#define GDC_PLANE_READ 0x04 +#define GDC_MODE 0x05 +#define GDC_MISC 0x06 +#define GDC_COMPARE_MASK 0x07 +#define GDC_BIT_MASK 0x08 + +// text attributes +#define VGA_ATTR_CLR_RED 0x4 +#define VGA_ATTR_CLR_GRN 0x2 +#define VGA_ATTR_CLR_BLU 0x1 +#define VGA_ATTR_CLR_YEL (VGA_ATTR_CLR_RED | VGA_ATTR_CLR_GRN) +#define VGA_ATTR_CLR_CYN (VGA_ATTR_CLR_GRN | VGA_ATTR_CLR_BLU) +#define VGA_ATTR_CLR_MAG (VGA_ATTR_CLR_BLU | VGA_ATTR_CLR_RED) +#define VGA_ATTR_CLR_BLK 0 +#define VGA_ATTR_CLR_WHT (VGA_ATTR_CLR_RED | VGA_ATTR_CLR_GRN | VGA_ATTR_CLR_BLU) +#define VGA_ATTR_BNK 0x80 +#define VGA_ATTR_ITN 0x08 + +/* + * vga register parameters + * these are copied to the + * registers. + * + */ +struct vga_par { + u8 crtc[CRTC_C]; + u8 atc[ATT_C]; + u8 gdc[GRA_C]; + u8 seq[SEQ_C]; + u8 misc; // the misc register, MIS_W + u8 vss; +}; + + +/* Interpretation of offset for color fields: All offsets are from the right, + * inside a "pixel" value, which is exactly 'bits_per_pixel' wide (means: you + * can use the offset as right argument to <<). A pixel afterwards is a bit + * stream and is written to video memory as that unmodified. This implies + * big-endian byte order if bits_per_pixel is greater than 8. + */ +struct fb_bitfield { + __u32 offset; /* beginning of bitfield */ + __u32 length; /* length of bitfield */ + __u32 msb_right; /* != 0 : Most significant bit is */ + /* right */ +}; + +struct screeninfo { + __u32 xres; /* visible resolution */ + __u32 yres; + __u32 xres_virtual; /* virtual resolution */ + __u32 yres_virtual; + __u32 xoffset; /* offset from virtual to visible */ + __u32 yoffset; /* resolution */ + + __u32 bits_per_pixel; /* guess what */ + __u32 grayscale; /* != 0 Graylevels instead of colors */ + + struct fb_bitfield red; /* bitfield in fb mem if true color, */ + struct fb_bitfield green; /* else only length is significant */ + struct fb_bitfield blue; + struct fb_bitfield transp; /* transparency */ + + __u32 nonstd; /* != 0 Non standard pixel format */ + + __u32 activate; /* see FB_ACTIVATE_* */ + + __u32 height; /* height of picture in mm */ + __u32 width; /* width of picture in mm */ + + __u32 accel_flags; /* acceleration flags (hints) */ + + /* Timing: All values in pixclocks, except pixclock (of course) */ + __u32 pixclock; /* pixel clock in ps (pico seconds) */ + __u32 left_margin; /* time from sync to picture */ + __u32 right_margin; /* time from picture to sync */ + __u32 upper_margin; /* time from sync to picture */ + __u32 lower_margin; + __u32 hsync_len; /* length of horizontal sync */ + __u32 vsync_len; /* length of vertical sync */ + __u32 sync; /* sync polarity */ + __u32 vmode; /* interlaced etc */ + __u32 reserved[6]; /* Reserved for future compatibility */ +}; +#endif diff --git a/qemu/roms/openbios/drivers/vga_load_regs.c b/qemu/roms/openbios/drivers/vga_load_regs.c new file mode 100644 index 000000000..dda6b798a --- /dev/null +++ b/qemu/roms/openbios/drivers/vga_load_regs.c @@ -0,0 +1,496 @@ +#include "asm/io.h" +#include "drivers/vga.h" +#include "vga.h" + +/* + * $Id$ + * $Source$ + * + * from the Linux kernel code base. + * orig by Ben Pfaff and Petr Vandrovec. + * + * modified by + * Steve M. Gehlbach <steve@kesa.com> + * + * NOTE: to change the horiz and vertical pixels, + * change the xres,yres,xres_virt,yres_virt setting + * in the screeninfo structure below. You may also need + * to change the border settings as well. + * + * Convert the screeninfo structure to data for + * writing to the vga registers + * + */ + +// prototypes +static int vga_decode_var(const struct screeninfo *var, struct vga_par *par); +static int vga_set_regs(const struct vga_par *par); + +u8 read_seq_b(u16 addr) { + outb(addr,SEQ_I); + return inb(SEQ_D); +} +u8 read_gra_b(u16 addr) { + outb(addr,GRA_I); + return inb(GRA_D); +} +u8 read_crtc_b(u16 addr) { + outb(addr,CRT_IC); + return inb(CRT_DC); +} +u8 read_att_b(u16 addr) { + inb(IS1_RC); + inb(0x80); + outb(addr,ATT_IW); + return inb(ATT_R); +} + + +/* +From: The Frame Buffer Device +by Geert Uytterhoeven <geert@linux-m68k.org> +in the linux kernel docs. + +The following picture summarizes all timings. The horizontal retrace time is +the sum of the left margin, the right margin and the hsync length, while the +vertical retrace time is the sum of the upper margin, the lower margin and the +vsync length. + + +----------+---------------------------------------------+----------+-------+ + | | ^ | | | + | | |upper_margin | | | + | | | | | | + +----------###############################################----------+-------+ + | # ^ # | | + | # | # | | + | # | # | | + | # | # | | + | left # | # right | hsync | + | margin # | xres # margin | len | + |<-------->#<---------------+--------------------------->#<-------->|<----->| + | # | # | | + | # | # | | + | # | # | | + | # |yres # | | + | # | # | | + | # | # | | + | # | # | | + | # | # | | + | # | # | | + | # | # | | + | # | # | | + | # | # | | + | # | # | | + +----------###############################################----------+-------+ + | | ^ | | | + | | |lower_margin | | | + | | | | | | + +----------+---------------------------------------------+----------+-------+ + | | ^ | | | + | | |vsync_len | | | + | | | | | | + +----------+---------------------------------------------+----------+-------+ + +All horizontal timings are in number of dotclocks +(in picoseconds, 1E-12 s), and vertical timings in number of scanlines. + +The vga uses the following fields: + + - pixclock: pixel clock in ps (pico seconds) + - xres,yres,xres_v,yres_v + - left_margin: time from sync to picture + - right_margin: time from picture to sync + - upper_margin: time from sync to picture + - lower_margin: time from picture to sync + - hsync_len: length of horizontal sync + - vsync_len: length of vertical sync + +*/ + +/* our display parameters per the above */ + +static const struct screeninfo vga_settings = { + 640,400,640,400,/* xres,yres,xres_virt,yres_virt */ + 0,0, /* xoffset,yoffset */ + 4, /* bits_per_pixel NOT USED*/ + 0, /* greyscale ? */ + {0,0,0}, /* R */ + {0,0,0}, /* G */ + {0,0,0}, /* B */ + {0,0,0}, /* transparency */ + 0, /* standard pixel format */ + 0, // activate now + -1,-1, // height and width in mm + 0, // accel flags + 39721, // pixclock: 79442 -> 12.587 Mhz (NOT USED) + // 70616 -> 14.161 + // 39721 -> 25.175 + // 35308 -> 28.322 + + 48, 16, 39, 8, // margins left,right,upper,lower + 96, // hsync length + 2, // vsync length + 0, // sync polarity + 0, // non interlaced, single mode + {0,0,0,0,0,0} // compatibility +}; + +// ALPHA-MODE +// Hard coded to BIOS VGA mode 3 (alpha color text) +// screen size settable in screeninfo structure + +static int vga_decode_var(const struct screeninfo *var, + struct vga_par *par) +{ + u8 VgaAttributeTable[16] = + { 0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x014, 0x007, 0x038, 0x039, 0x03A, 0x03B, 0x03C, 0x03D, 0x03E, 0x03F}; + + u32 xres, right, hslen, left, xtotal; + u32 yres, lower, vslen, upper, ytotal; + u32 vxres, xoffset, vyres, yoffset; + u32 pos; + u8 r7, rMode; + int i; + + xres = (var->xres + 7) & ~7; + vxres = (var->xres_virtual + 0xF) & ~0xF; + xoffset = (var->xoffset + 7) & ~7; + left = (var->left_margin + 7) & ~7; + right = (var->right_margin + 7) & ~7; + hslen = (var->hsync_len + 7) & ~7; + + if (vxres < xres) + vxres = xres; + if (xres + xoffset > vxres) + xoffset = vxres - xres; + + xres >>= 3; + right >>= 3; + hslen >>= 3; + left >>= 3; + vxres >>= 3; + xtotal = xres + right + hslen + left; + if (xtotal >= 256) + return VERROR; //xtotal too big + if (hslen > 32) + return VERROR; //hslen too big + if (right + hslen + left > 64) + return VERROR; //hblank too big + par->crtc[CRTC_H_TOTAL] = xtotal - 5; + par->crtc[CRTC_H_BLANK_START] = xres - 1; + par->crtc[CRTC_H_DISP] = xres - 1; + pos = xres + right; + par->crtc[CRTC_H_SYNC_START] = pos; + pos += hslen; + par->crtc[CRTC_H_SYNC_END] = (pos & 0x1F) | 0x20 ; //<--- stpc text mode p178 + pos += left - 2; /* blank_end + 2 <= total + 5 */ + par->crtc[CRTC_H_BLANK_END] = (pos & 0x1F) | 0x80; + if (pos & 0x20) + par->crtc[CRTC_H_SYNC_END] |= 0x80; + + yres = var->yres; + lower = var->lower_margin; + vslen = var->vsync_len; + upper = var->upper_margin; + vyres = var->yres_virtual; + yoffset = var->yoffset; + + if (yres > vyres) + vyres = yres; + if (vxres * vyres > 65536) { + vyres = 65536 / vxres; + if (vyres < yres) + return VERROR; // out of memory + } + if (yoffset + yres > vyres) + yoffset = vyres - yres; + + if (var->vmode & VMODE_DOUBLE) { + yres <<= 1; + lower <<= 1; + vslen <<= 1; + upper <<= 1; + } + ytotal = yres + lower + vslen + upper; + if (ytotal > 1024) { + ytotal >>= 1; + yres >>= 1; + lower >>= 1; + vslen >>= 1; + upper >>= 1; + rMode = 0x04; + } else + rMode = 0x00; + if (ytotal > 1024) + return VERROR; //ytotal too big + if (vslen > 16) + return VERROR; //vslen too big + par->crtc[CRTC_V_TOTAL] = ytotal - 2; + r7 = 0x10; /* disable linecompare */ + if (ytotal & 0x100) r7 |= 0x01; + if (ytotal & 0x200) r7 |= 0x20; + par->crtc[CRTC_PRESET_ROW] = 0; + + +// GMODE <--> ALPHA-MODE +// default using alpha mode so we need to set char rows= CHAR_HEIGHT-1 + par->crtc[CRTC_MAX_SCAN] = 0x40 | (CHAR_HEIGHT-1); /* 16 scanlines, linecmp max*/ + + if (var->vmode & VMODE_DOUBLE) + par->crtc[CRTC_MAX_SCAN] |= 0x80; + par->crtc[CRTC_CURSOR_START] = 0x00; // curs enabled, start line = 0 + par->crtc[CRTC_CURSOR_END] = CHAR_HEIGHT-1; // end line = 12 + pos = yoffset * vxres + (xoffset >> 3); + par->crtc[CRTC_START_HI] = pos >> 8; + par->crtc[CRTC_START_LO] = pos & 0xFF; + par->crtc[CRTC_CURSOR_HI] = 0x00; + par->crtc[CRTC_CURSOR_LO] = 0x00; + pos = yres - 1; + par->crtc[CRTC_V_DISP_END] = pos & 0xFF; + par->crtc[CRTC_V_BLANK_START] = pos & 0xFF; + if (pos & 0x100) + r7 |= 0x0A; /* 0x02 -> DISP_END, 0x08 -> BLANK_START */ + if (pos & 0x200) { + r7 |= 0x40; /* 0x40 -> DISP_END */ + par->crtc[CRTC_MAX_SCAN] |= 0x20; /* BLANK_START */ + } + pos += lower; + par->crtc[CRTC_V_SYNC_START] = pos & 0xFF; + if (pos & 0x100) + r7 |= 0x04; + if (pos & 0x200) + r7 |= 0x80; + pos += vslen; + par->crtc[CRTC_V_SYNC_END] = (pos & 0x0F) & ~0x10; /* disabled reg write prot, IRQ */ + pos += upper - 1; /* blank_end + 1 <= ytotal + 2 */ + par->crtc[CRTC_V_BLANK_END] = pos & 0xFF; /* 0x7F for original VGA, + but some SVGA chips requires all 8 bits to set */ + if (vxres >= 512) + return VERROR; //vxres too long + par->crtc[CRTC_OFFSET] = vxres >> 1; + + // put the underline off of the character, necessary in alpha color mode + par->crtc[CRTC_UNDERLINE] = 0x1f; + + par->crtc[CRTC_MODE] = rMode | 0xA3; // word mode + par->crtc[CRTC_LINE_COMPARE] = 0xFF; + par->crtc[CRTC_OVERFLOW] = r7; + + + // not used ?? + par->vss = 0x00; /* 3DA */ + + for (i = 0x00; i < 0x10; i++) { + par->atc[i] = VgaAttributeTable[i]; + } + // GMODE <--> ALPHA-MODE + par->atc[ATC_MODE] = 0x0c; // text mode + + par->atc[ATC_OVERSCAN] = 0x00; // no border + par->atc[ATC_PLANE_ENABLE] = 0x0F; + par->atc[ATC_PEL] = xoffset & 7; + par->atc[ATC_COLOR_PAGE] = 0x00; + + par->misc = 0x67; /* enable CPU, ports 0x3Dx, positive sync*/ + if (var->sync & SYNC_HOR_HIGH_ACT) + par->misc &= ~0x40; + if (var->sync & SYNC_VERT_HIGH_ACT) + par->misc &= ~0x80; + + par->seq[SEQ_CLOCK_MODE] = 0x01; //8-bit char; 0x01=alpha mode + par->seq[SEQ_PLANE_WRITE] = 0x03; // just char/attr plane + par->seq[SEQ_CHARACTER_MAP] = 0x00; + par->seq[SEQ_MEMORY_MODE] = 0x02; // A/G bit not used in stpc; O/E on, C4 off + + par->gdc[GDC_SR_VALUE] = 0x00; + // bits set in the SR_EN regs will enable set/reset action + // based on the bit settings in the SR_VAL register + par->gdc[GDC_SR_ENABLE] = 0x00; + par->gdc[GDC_COMPARE_VALUE] = 0x00; + par->gdc[GDC_DATA_ROTATE] = 0x00; + par->gdc[GDC_PLANE_READ] = 0; + par->gdc[GDC_MODE] = 0x10; //Okay + + // GMODE <--> ALPHA-MMODE + par->gdc[GDC_MISC] = 0x0e; // b0=0 ->alpha mode; memory at 0xb8000 + + par->gdc[GDC_COMPARE_MASK] = 0x00; + par->gdc[GDC_BIT_MASK] = 0xFF; + + return 0; +} + +// +// originally from the stpc web site +// +static const unsigned char VgaLookupTable[3 * 0x3f + 3] = { + // Red Green Blue + 0x000, 0x000, 0x000, // 00h + 0x000, 0x000, 0x02A, // 01h + 0x000, 0x02A, 0x000, // 02h + 0x000, 0x02A, 0x02A, // 03h + 0x02A, 0x000, 0x000, // 04h + 0x02A, 0x000, 0x02A, // 05h + 0x02A, 0x02A, 0x000, // 06h + 0x02A, 0x02A, 0x02A, // 07h + 0x000, 0x000, 0x015, // 08h + 0x000, 0x000, 0x03F, // 09h + 0x000, 0x02A, 0x015, // 0Ah + 0x000, 0x02A, 0x03F, // 0Bh + 0x02A, 0x000, 0x015, // 0Ch + 0x02A, 0x000, 0x03F, // 0Dh + 0x02A, 0x02A, 0x015, // 0Eh + 0x02A, 0x02A, 0x03F, // 0Fh + 0x000, 0x015, 0x000, // 10h + 0x000, 0x015, 0x02A, // 11h + 0x000, 0x03F, 0x000, // 12h + 0x000, 0x03F, 0x02A, // 13h + 0x02A, 0x015, 0x000, // 14h + 0x02A, 0x015, 0x02A, // 15h + 0x02A, 0x03F, 0x000, // 16h + 0x02A, 0x03F, 0x02A, // 17h + 0x000, 0x015, 0x015, // 18h + 0x000, 0x015, 0x03F, // 19h + 0x000, 0x03F, 0x015, // 1Ah + 0x000, 0x03F, 0x03F, // 1Bh + 0x02A, 0x015, 0x015, // 1Ch + 0x02A, 0x015, 0x03F, // 1Dh + 0x02A, 0x03F, 0x015, // 1Eh + 0x02A, 0x03F, 0x03F, // 1Fh + 0x015, 0x000, 0x000, // 20h + 0x015, 0x000, 0x02A, // 21h + 0x015, 0x02A, 0x000, // 22h + 0x015, 0x02A, 0x02A, // 23h + 0x03F, 0x000, 0x000, // 24h + 0x03F, 0x000, 0x02A, // 25h + 0x03F, 0x02A, 0x000, // 26h + 0x03F, 0x02A, 0x02A, // 27h + 0x015, 0x000, 0x015, // 28h + 0x015, 0x000, 0x03F, // 29h + 0x015, 0x02A, 0x015, // 2Ah + 0x015, 0x02A, 0x03F, // 2Bh + 0x03F, 0x000, 0x015, // 2Ch + 0x03F, 0x000, 0x03F, // 2Dh + 0x03F, 0x02A, 0x015, // 2Eh + 0x03F, 0x02A, 0x03F, // 2Fh + 0x015, 0x015, 0x000, // 30h + 0x015, 0x015, 0x02A, // 31h + 0x015, 0x03F, 0x000, // 32h + 0x015, 0x03F, 0x02A, // 33h + 0x03F, 0x015, 0x000, // 34h + 0x03F, 0x015, 0x02A, // 35h + 0x03F, 0x03F, 0x000, // 36h + 0x03F, 0x03F, 0x02A, // 37h + 0x015, 0x015, 0x015, // 38h + 0x015, 0x015, 0x03F, // 39h + 0x015, 0x03F, 0x015, // 3Ah + 0x015, 0x03F, 0x03F, // 3Bh + 0x03F, 0x015, 0x015, // 3Ch + 0x03F, 0x015, 0x03F, // 3Dh + 0x03F, 0x03F, 0x015, // 3Eh + 0x03F, 0x03F, 0x03F, // 3Fh +}; + +/* + * From the Linux kernel. + * orig by Ben Pfaff and Petr Vandrovec. + * see the note in the vga.h for attribution. + * + * modified by + * Steve M. Gehlbach <steve@kesa.com> + * for the linuxbios project + * + * Write the data in the vga parameter structure + * to the vga registers, along with other default + * settings. + * + */ +static int vga_set_regs(const struct vga_par *par) +{ + int i; + + /* update misc output register */ + outb(par->misc, MIS_W); + + /* synchronous reset on */ + outb(0x00, SEQ_I); + outb(0x00, SEQ_D); + + /* write sequencer registers */ + outb(1, SEQ_I); + outb(par->seq[1] | 0x20, SEQ_D); // blank display + for (i = 2; i < SEQ_C; i++) { + outb(i, SEQ_I); + outb(par->seq[i], SEQ_D); + } + + /* synchronous reset off */ + outb(0x00, SEQ_I); + outb(0x03, SEQ_D); + + /* deprotect CRT registers 0-7 */ + outb(0x11, CRT_IC); + outb(par->crtc[0x11], CRT_DC); + + /* write CRT registers */ + for (i = 0; i < CRTC_C; i++) { + outb(i, CRT_IC); + outb(par->crtc[i], CRT_DC); + } + /* write graphics controller registers */ + for (i = 0; i < GRA_C; i++) { + outb(i, GRA_I); + outb(par->gdc[i], GRA_D); + } + + /* write attribute controller registers */ + for (i = 0; i < ATT_C; i++) { + inb(IS1_RC); /* reset flip-flop */ + inb(0x80); //delay + outb(i, ATT_IW); + inb(0x80); //delay + + outb(par->atc[i], ATT_IW); + inb(0x80); //delay + } + + // initialize the color table + outb(0, PEL_IW); + i = 0; + // length is a magic number right now + while ( i < (0x3f*3 + 3) ) { + outb(VgaLookupTable[i++], PEL_D); + outb(VgaLookupTable[i++], PEL_D); + outb(VgaLookupTable[i++], PEL_D); + } + + outb(0x0ff, PEL_MSK); // palette mask + + // very important + // turn on video, disable palette access + inb(IS1_RC); /* reset flip-flop */ + inb(0x80); //delay + outb(0x20, ATT_IW); + + /* Wait for screen to stabilize. */ + //for(i=0;i<1000;i++) { inb(0x80); } + + outb(0x01, SEQ_I); // unblank display + outb(par->seq[1], SEQ_D); + +// turn on display, disable access to attr palette + inb(IS1_RC); + outb(0x20, ATT_IW); + +return 0; +} + +void +vga_load_regs(void) +{ + struct vga_par par; + + if (vga_decode_var(&vga_settings, &par) == 0) { + vga_set_regs(&par); + } +} diff --git a/qemu/roms/openbios/drivers/vga_set_mode.c b/qemu/roms/openbios/drivers/vga_set_mode.c new file mode 100644 index 000000000..339ad2966 --- /dev/null +++ b/qemu/roms/openbios/drivers/vga_set_mode.c @@ -0,0 +1,148 @@ +/* + * $Id$ + * $Source$ + * + * by + * Steve M. Gehlbach <steve@kesa.com> + * + * These routines set graphics mode and alpha mode + * for switching back and forth. + * + * Register settings are + * more or less as follows: + * + * Register Graphics Alpha + * 16 color + * ------------------------------------------------ + * GDC_MODE 0x00 0x10 + * GDC_MISC 0x05 0x0e + * SEQ_MEMORY_MODE 0x06 0x02 + * SEQ_PLANE_WRITE 0x0f 0x03 + * CRTC_CURSOR_START 0x20 0x00 + * CRTC_CURSOR_END 0x00 CHAR_HEIGHT-1 + * CRTC_MODE 0xe3 0xa3 + * CRTC_MAX_SCAN 0x40 0x40 | CHAR_HEIGHT-1 + * ATC_MODE 0x01 0x0c + * + */ + +#include "asm/io.h" +#include "vga.h" + +void vga_set_gmode (void) { + u8 byte; + + byte = read_att_b(ATC_MODE) & ~0x0f; + write_att(byte|0x1, ATC_MODE); +// +// display is off at this point + + byte = read_seq_b(SEQ_PLANE_WRITE) & ~0xf; + write_seq(byte|0xf,SEQ_PLANE_WRITE); // all planes + byte = read_seq_b(SEQ_MEMORY_MODE); + write_seq(byte|4,SEQ_MEMORY_MODE); + + byte = read_gra_b(GDC_MODE) & ~0x10; + write_gra(byte,GDC_MODE); + write_gra(0x05, GDC_MISC); + + write_crtc(0x20, CRTC_CURSOR_START); + write_crtc(0x00, CRTC_CURSOR_END); + byte = read_crtc_b(CRTC_MODE) & ~0xe0; + write_crtc(byte|0xe0, CRTC_MODE); + byte = read_crtc_b(CRTC_MAX_SCAN) & ~0x01f; + write_crtc(byte, CRTC_MAX_SCAN); + + byte = inb(MIS_R); // get 3c2 value by reading 3cc + outb(byte & ~0xc,MIS_W); // clear last bits to set 25Mhz clock and low page + + +// turn on display, disable access to attr palette + inb(IS1_RC); + outb(0x20, ATT_IW); +} + +void vga_set_amode (void) { + u8 byte; + write_att(0x0c, ATC_MODE); + + //reset palette to normal in the case it was changed + write_att(0x0, ATC_COLOR_PAGE); +// +// display is off at this point + + write_seq(0x3,SEQ_PLANE_WRITE); // planes 0 & 1 + byte = read_seq_b(SEQ_MEMORY_MODE) & ~0x04; + write_seq(byte,SEQ_MEMORY_MODE); + + byte = read_gra_b(GDC_MODE) & ~0x60; + write_gra(byte|0x10,GDC_MODE); + + write_gra(0x0e, GDC_MISC); + + write_crtc(0x00, CRTC_CURSOR_START); + write_crtc(CHAR_HEIGHT-1, CRTC_CURSOR_END); + + byte = read_crtc_b(CRTC_MODE) & ~0xe0; + write_crtc(byte|0xa0, CRTC_MODE); + byte = read_crtc_b(CRTC_MAX_SCAN) & ~0x01f; + write_crtc(byte | (CHAR_HEIGHT-1), CRTC_MAX_SCAN); + + +// turn on display, disable access to attr palette + inb(IS1_RC); + outb(0x20, ATT_IW); +} + +/* + * by Steve M. Gehlbach, Ph.D. <steve@kesa.com> + * + * vga_font_load loads a font into font memory. It + * assumes alpha mode has been set. + * + * The font load code follows technique used + * in the tiara project, which came from + * the Universal Talkware Boot Loader, + * http://www.talkware.net. + */ + +void vga_font_load(unsigned char *vidmem, const unsigned char *font, int height, int num_chars) { + +/* Note: the font table is 'height' long but the font storage area + * is 32 bytes long. + */ + + int i,j; + u8 byte; + + // set sequencer map 2, odd/even off + byte = read_seq_b(SEQ_PLANE_WRITE) & ~0xf; + write_seq(byte|4,SEQ_PLANE_WRITE); + byte = read_seq_b(SEQ_MEMORY_MODE); + write_seq(byte|4,SEQ_MEMORY_MODE); + + // select graphics map 2, odd/even off, map starts at 0xa0000 + write_gra(2,GDC_PLANE_READ); + byte = read_gra_b(GDC_MODE) & ~0x10; + write_gra(byte,GDC_MODE); + write_gra(0,GDC_MISC); + + for (i = 0 ; i < num_chars ; i++) { + for (j = 0 ; j < height ; j++) { + vidmem[i*32+j] = font[i*16+j]; + } + } + + // set sequencer back to maps 0,1, odd/even on + byte = read_seq_b(SEQ_PLANE_WRITE) & ~0xf; + write_seq(byte|3,SEQ_PLANE_WRITE); + byte = read_seq_b(SEQ_MEMORY_MODE) & ~0x4; + write_seq(byte,SEQ_MEMORY_MODE); + + // select graphics back to map 0,1, odd/even on + write_gra(0,GDC_PLANE_READ); + byte = read_gra_b(GDC_MODE); + write_gra(byte|0x10,GDC_MODE); + write_gra(0xe,GDC_MISC); + +} diff --git a/qemu/roms/openbios/forth/Kconfig b/qemu/roms/openbios/forth/Kconfig new file mode 100644 index 000000000..87ff19172 --- /dev/null +++ b/qemu/roms/openbios/forth/Kconfig @@ -0,0 +1,9 @@ +# +# +# + +#menu "Packages" +# +#source "forth/packages/Kconfig" +# +#endmenu diff --git a/qemu/roms/openbios/forth/admin/README b/qemu/roms/openbios/forth/admin/README new file mode 100644 index 000000000..711f7e0e8 --- /dev/null +++ b/qemu/roms/openbios/forth/admin/README @@ -0,0 +1,3 @@ +\ This directory contains code that implements +\ the Administration command group +\ (Chapter 7.4 in the IEEE 1275-1994) diff --git a/qemu/roms/openbios/forth/admin/banner.fs b/qemu/roms/openbios/forth/admin/banner.fs new file mode 100644 index 000000000..5439fc082 --- /dev/null +++ b/qemu/roms/openbios/forth/admin/banner.fs @@ -0,0 +1,49 @@ +\ 7.4.10 Banner + +defer builtin-logo +defer builtin-banner +0 value suppress-banner? + +:noname + 0 0 +; to builtin-logo + +:noname + builddate s" built on " version s" Welcome to OpenBIOS v" pocket + tmpstrcat tmpstrcat tmpstrcat drop +; to builtin-banner + +: suppress-banner ( -- ) + 1 to suppress-banner? +; + +: banner ( -- ) + suppress-banner + stdout @ ?dup 0= if exit then + + \ draw logo if stdout is a "display" node + dup ihandle>phandle " device_type" rot get-package-property if 0 0 then + " display" strcmp if + drop + else + \ draw logo ( ihandle ) + dup ihandle>phandle " draw-logo" rot find-method if + ( ihandle xt ) + swap >r >r + 0 \ line # + oem-logo? if oem-logo else builtin-logo then + ( 0 addr logo-len ) + 200 = if + d# 64 d# 64 + r> r> call-package + else + r> r> 2drop 2drop + then + else + drop + then + then + + oem-banner? if oem-banner else builtin-banner then + type cr +; diff --git a/qemu/roms/openbios/forth/admin/build.xml b/qemu/roms/openbios/forth/admin/build.xml new file mode 100644 index 000000000..665449672 --- /dev/null +++ b/qemu/roms/openbios/forth/admin/build.xml @@ -0,0 +1,25 @@ +<build> + + <!-- + build description for forth administrative command group + + Copyright (C) 2003-2005 by Stefan Reinauer + See the file "COPYING" for further information about + the copyright and warranty status of this work. + --> + + <dictionary name="openbios" target="forth"> + <object source="devices.fs"/> + <object source="nvram.fs"/> + <object source="callback.fs"/> + <object source="help.fs"/> + <object source="iocontrol.fs"/> + <object source="banner.fs"/> + <object source="reset.fs"/> + <object source="script.fs"/> + <object source="security.fs"/> + <object source="selftest.fs"/> + <object source="userboot.fs"/> + </dictionary> + +</build> diff --git a/qemu/roms/openbios/forth/admin/callback.fs b/qemu/roms/openbios/forth/admin/callback.fs new file mode 100644 index 000000000..e318af23b --- /dev/null +++ b/qemu/roms/openbios/forth/admin/callback.fs @@ -0,0 +1,10 @@ +\ 7.4.9 Client program callback + +: callback ( "service-name< >" "arguments<cr>" -- ) + ; + +: $callback ( argn ... arg1 nargs addr len -- retn ... ret2 Nreturns-1 ) + ; + +: sync ( -- ) + ; diff --git a/qemu/roms/openbios/forth/admin/devices.fs b/qemu/roms/openbios/forth/admin/devices.fs new file mode 100644 index 000000000..6f9e8efbb --- /dev/null +++ b/qemu/roms/openbios/forth/admin/devices.fs @@ -0,0 +1,515 @@ +\ tag: device tree administration +\ +\ this code implements IEEE 1275-1994 +\ +\ Copyright (C) 2003 Samuel Rydh +\ Copyright (C) 2003-2006 Stefan Reinauer +\ +\ See the file "COPYING" for further information about +\ the copyright and warranty status of this work. +\ + + +\ 7.4.11.1 Device alias + +: devalias ( "{alias-name}< >{device-specifier}<cr>" -- ) + ; + +: nvalias ( "alias-name< >device-specifier<cr>" -- ) + ; + +: $nvalias ( name-str name-len dev-str dev-len -- ) + ; + +: nvunalias ( "alias-name< >" -- ) + ; + +: $nvunalias ( name-str name-len -- ) + ; + + +\ 7.4.11.2 Device tree browsing + +: dev ( "<spaces>device-specifier" -- ) + bl parse + find-device +; + +: cd + dev +; + +\ find-device ( dev-str dev-len -- ) +\ implemented in pathres.fs + +: device-end ( -- ) + 0 active-package! + ; + +\ Open selected device node and make it the current instance +\ section H.8 errata: pre OpenFirmware, but Sun OBP compatible +: select-dev ( -- ) + open-dev dup 0= abort" failed opening parent." + dup to my-self + ihandle>phandle active-package! +; + +\ Close current node, deselect active package and current instance, +\ leaving no instance selected +\ section H.8 errata: pre OpenFirmware, but Sun OBP compatible +: unselect-dev ( -- ) + my-self close-dev + device-end + 0 to my-self +; + +: begin-package ( arg-str arg-len reg-str reg-len dev-str dev-len -- ) + select-dev + new-device + set-args +; + +: end-package ( -- ) + finish-device + unselect-dev +; + +: ?active-package ( -- phandle ) + active-package dup 0= abort" no active device" +; + +\ ------------------------------------------------------- +\ path handling +\ ------------------------------------------------------- + +\ used if parent lacks an encode-unit method +: def-encode-unit ( unitaddr ... ) + pocket tohexstr +; + +: get-encode-unit-xt ( phandle.parent -- xt ) + >dn.parent @ + " encode-unit" rot find-method + 0= if ['] def-encode-unit then +; + +: get-nodename ( phandle -- str len ) + " name" rot get-package-property if " <noname>" else 1- then +; + +\ helper, return the node name in the format 'cpus@addr' +: pnodename ( phandle -- str len ) + dup get-nodename rot + dup " reg" rot get-package-property if drop exit then rot + + \ set active-package and clear my-self (decode-phys needs this) + my-self >r 0 to my-self + active-package >r + dup active-package! + + ( name len prop len phandle ) + get-encode-unit-xt + + ( name len prop len xt ) + depth >r >r + decode-phys r> execute + r> -rot >r >r depth! 3drop + + ( name len R: len str ) + r> r> " @" + here 20 + \ abuse dictionary for temporary storage + tmpstrcat >r + 2swap r> tmpstrcat drop + pocket tmpstrcpy drop + + r> active-package! + r> to my-self +; + +: inodename ( ihandle -- str len ) + my-self over to my-self >r + ihandle>phandle get-nodename + + \ nonzero unit number? + false >r + depth >r my-unit r> 1+ + begin depth over > while + swap 0<> if r> drop true >r then + repeat + drop + + \ if not... check for presence of "reg" property + r> ?dup 0= if + " reg" my-self ihandle>phandle get-package-property + if false else 2drop true then + then + + ( name len print-unit-flag ) + if + my-self ihandle>phandle get-encode-unit-xt + + ( name len xt ) + depth >r >r + my-unit r> execute + r> -rot >r >r depth! drop + r> r> + ( name len str len ) + here 20 + tmpstrcpy + " @" rot tmpstrcat drop + 2swap pocket tmpstrcat drop + then + + \ add :arguments + my-args dup if + " :" pocket tmpstrcat drop + 2swap pocket tmpstrcat drop + else + 2drop + then + + r> to my-self +; + +\ helper, also used by client interface (package-to-path) +: get-package-path ( phandle -- str len ) + ?dup 0= if 0 0 then + + dup >dn.parent @ 0= if drop " /" exit then + \ dictionary abused for temporary storage + >r 0 0 here 40 + + begin r> dup >dn.parent @ dup >r while + ( path len tempbuf phandle R: phandle.parent ) + pnodename rot tmpstrcat + " /" rot tmpstrcat + repeat + r> 3drop + pocket tmpstrcpy drop +; + +\ used by client interface (instance-to-path) +: get-instance-path ( ihandle -- str len ) + ?dup 0= if 0 0 then + + dup ihandle>phandle >dn.parent @ 0= if drop " /" exit then + + \ dictionary abused for temporary storage + >r 0 0 here 40 + + begin r> dup >in.my-parent @ dup >r while + ( path len tempbuf ihandle R: ihandle.parent ) + dup >in.interposed @ 0= if + inodename rot tmpstrcat + " /" rot tmpstrcat + else + drop + then + repeat + r> 3drop + pocket tmpstrcpy drop +; + +\ used by client interface (instance-to-interposed-path) +: get-instance-interposed-path ( ihandle -- str len ) + ?dup 0= if 0 0 then + + dup ihandle>phandle >dn.parent @ 0= if drop " /" exit then + + \ dictionary abused for temporary storage + >r 0 0 here 40 + + begin r> dup >in.my-parent @ dup >r while + ( path len tempbuf ihandle R: ihandle.parent ) + dup >r inodename rot tmpstrcat + r> >in.interposed @ if " /%" else " /" then + rot tmpstrcat + repeat + r> 3drop + pocket tmpstrcpy drop +; + +: pwd ( -- ) + ?active-package get-package-path type +; + +: ls ( -- ) + cr + ?active-package >dn.child @ + begin dup while + dup u. dup pnodename type cr + >dn.peer @ + repeat + drop +; + + +\ ------------------------------------------- +\ property printing +\ ------------------------------------------- + +: .p-string? ( data len -- true | data len false ) + \ no trailing zero? + 2dup + 1- c@ if 0 exit then + + swap >r 0 + \ count zeros and detect unprintable characters? + over 1- begin 1- dup 0>= while + dup r@ + c@ + ( len zerocnt n ch ) + + ?dup 0= if + swap 1+ swap + else + dup 1b <= swap 80 >= or + if 2drop r> swap 0 exit then + then + repeat drop r> -rot + ( data len zerocnt ) + + \ simple string + 0= if + ascii " emit 1- type ascii " emit true exit + then + + \ make sure there are no double zeros (except possibly at the end) + 2dup over + swap + ( data len end ptr ) + begin 2dup <> while + dup c@ 0= if + 2dup 1+ <> if 2drop false exit then + then + dup cstrlen 1+ + + repeat + 2drop + + ." {" + 0 -rot over + swap + \ multistring ( cnt end ptr ) + begin 2dup <> while + rot dup if ." , " then 1+ -rot + dup cstrlen 2dup + ascii " emit type ascii " emit + 1+ + + repeat + ." }" + 3drop true +; + +: .p-int? ( data len -- 1 | data len 0 ) + dup 4 <> if false exit then + decode-int -rot 2drop true swap + dup 0>= if . exit then + dup -ff < if u. exit then + . +; + +\ Print a number zero-padded +: 0.r ( u minlen -- ) + 0 swap <# 1 ?do # loop #s #> type +; + +: .p-bytes? ( data len -- 1 | data len 0 ) + ." -- " dup . ." : " + swap >r 0 + begin 2dup > while + dup r@ + c@ + ( len n ch ) + + 2 0.r space + 1+ + repeat + 2drop r> drop 1 +; + +\ this function tries to heuristically determine the data format +: (.property) ( data len -- ) + dup 0= if 2drop ." <empty>" exit then + + .p-string? if exit then + .p-int? if exit then + .p-bytes? if exit then + 2drop ." <unimplemented type>" +; + +\ Print the value of a property in "reg" format +: .p-reg ( #acells #scells data len -- ) + 2dup + -rot ( #acells #scells data+len data len ) + >r >r -rot ( data+len #acells #scells R: len data ) + 4 * swap 4 * dup r> r> ( data+len #sbytes #abytes #abytes data len ) + bounds ( data+len #sbytes #abytes #abytes data+len data ) ?do + dup 0= if 2 spaces then \ start of "size" part + 2dup <> if \ non-first byte in row + dup 3 and 0= if space then \ make numbers more readable + then + i c@ 2 0.r \ print byte + 1- 3dup nip + 0= if \ end of row + 3 pick i 1+ > if \ non-last byte + cr \ start new line + d# 26 spaces \ indentation + then + drop dup \ update counter + then + loop + 3drop drop +; + +\ Return the number of cells per physical address +: .p-translations-#pacells ( -- #cells ) + " /" find-package if + " #address-cells" rot get-package-property if + 1 + else + decode-int nip nip 1 max + then + else + 1 + then +; + +\ Return the number of cells per translation entry +: .p-translations-#cells ( -- #cells ) + [IFDEF] CONFIG_PPC + my-#acells 3 * + .p-translations-#pacells + + [ELSE] + my-#acells 3 * + [THEN] +; + +\ Set up column offsets +: .p-translations-cols ( -- col1 ... coln #cols ) + .p-translations-#cells 4 * + [IFDEF] CONFIG_PPC + 4 - + dup 4 - + dup .p-translations-#pacells 4 * - + 3 + [ELSE] + my-#acells 4 * - + dup my-#scells 4 * - + 2 + [THEN] +; + +\ Print the value of the MMU translations property +: .p-translations ( data len -- ) + >r >r .p-translations-cols r> r> ( col1 ... coln #cols data len ) + 2dup + -rot ( col1 ... coln #cols data+len data len ) + >r >r .p-translations-#cells 4 * dup r> r> + ( col1 ... coln #cols data+len #bytes #bytes len data ) + bounds ( col1 ... coln #cols data+len #bytes #bytes data+len data ) ?do + 3 pick 4 + 4 ?do \ check all defined columns + i pick over = if + 2 spaces \ start new column + then + loop + 2dup <> if \ non-first byte in row + dup 3 and 0= if space then \ make numbers more readable + then + i c@ 2 0.r \ print byte + 1- dup 0= if \ end of row + 2 pick i 1+ > if \ non-last byte + cr \ start new line + d# 26 spaces \ indentation + then + drop dup \ update counter + then + loop + 2drop drop 0 ?do drop loop +; + +\ This function hardwires data formats to particular node properties +: (.property-by-name) ( name-str name-len data len -- ) + 2over " reg" strcmp 0= if + my-#acells my-#scells 2swap .p-reg + 2drop exit + then + + active-package get-nodename " memory" strcmp 0= if + 2over " available" strcmp 0= if + my-#acells my-#scells 2swap .p-reg + 2drop exit + then + then + " /chosen" find-dev if + " mmu" rot get-package-property 0= if + decode-int nip nip ihandle>phandle active-package = if + 2over " available" strcmp 0= if + my-#acells my-#scells 1 max 2swap .p-reg + 2drop exit + then + 2over " translations" strcmp 0= if + .p-translations + 2drop exit + then + then + then + then + + 2swap 2drop ( data len ) + (.property) +; + +: .properties ( -- ) + ?active-package dup >r if + 0 0 + begin + r@ next-property + while + cr 2dup dup -rot type + begin ." " 1+ dup d# 26 >= until drop + 2dup + 2dup active-package get-package-property drop + ( name-str name-len data len ) + (.property-by-name) + repeat + then + r> drop + cr +; + + +\ 7.4.11 Device tree + +: print-dev ( phandle -- phandle ) + dup u. + dup get-package-path type + dup " device_type" rot get-package-property if + cr + else + ." (" decode-string type ." )" cr 2drop + then + ; + +: show-sub-devs ( subtree-phandle -- ) + print-dev + >dn.child @ + begin dup while + dup recurse + >dn.peer @ + repeat + drop + ; + +: show-all-devs ( -- ) + active-package + cr " /" find-device + ?active-package show-sub-devs + active-package! + ; + + +: show-devs ( "{device-specifier}<cr>" -- ) + active-package + cr " /" find-device + linefeed parse find-device + ?active-package show-sub-devs + active-package! + ; + + + +\ 7.4.11.3 Device probing + +\ Set to true if the last probe-self was successful +0 value probe-fcode? + +: probe-all ( -- ) + ; diff --git a/qemu/roms/openbios/forth/admin/help.fs b/qemu/roms/openbios/forth/admin/help.fs new file mode 100644 index 000000000..e6e624b2a --- /dev/null +++ b/qemu/roms/openbios/forth/admin/help.fs @@ -0,0 +1,51 @@ +\ tag: firmware help +\ +\ this code implements IEEE 1275-1994 ch. 7.4.1 +\ +\ Copyright (C) 2003 Stefan Reinauer +\ +\ See the file "COPYING" for further information about +\ the copyright and warranty status of this work. +\ + +hex + +: (help-generic) + ." Enter 'help command-name' or 'help category-name' for more help" cr + ." (Use ONLY the first word of a category description)" cr + ." Examples: help select -or- help line" cr cr + ." Categories:" cr + ." boot (Load and execute a client program)" cr + ." diag (Diagnostic routines)" cr + ; + +: (help-diag) + ." test <device> Run the selftest method for specified device" cr + ." test-all Execute test for all devices using selftest method" cr + ; + +: (help-boot) + ." boot [<device-specifier>:<device-arguments>] [boot-arguments]" cr + ." Examples:" cr + ." boot Default boot (values specified in nvram variables)" cr + ." boot disk1:a Boot from disk1 partition a" cr + ." boot hd:1,\boot\vmlinuz root=/dev/hda1" cr + ; + +: help ( "{name}<cr>" -- ) + \ Provide information for category or specific command. + linefeed parse cr + dup 0= if + (help-generic) + 2drop + else + 2dup " diag" rot min comp not if + (help-diag) 2drop exit + then + 2dup " boot" rot min comp not if + (help-boot) 2drop exit + then + ." No help available for " type cr + then + ; + diff --git a/qemu/roms/openbios/forth/admin/iocontrol.fs b/qemu/roms/openbios/forth/admin/iocontrol.fs new file mode 100644 index 000000000..b0f578f4d --- /dev/null +++ b/qemu/roms/openbios/forth/admin/iocontrol.fs @@ -0,0 +1,168 @@ +\ tag: stdin/stdout handling +\ +\ Copyright (C) 2003 Samuel Rydh +\ +\ See the file "COPYING" for further information about +\ the copyright and warranty status of this work. +\ + +\ 7.4.5 I/O control + +variable stdout +variable stdin + +: input ( dev-str dev-len -- ) + 2dup find-dev 0= if + ." Input device " type ." not found." cr exit + then + + " read" rot find-method 0= if + type ." has no read method." cr exit + then + drop + + \ open stdin device + 2dup open-dev ?dup 0= if + ." Opening " type ." failed." cr exit + then + -rot 2drop + + \ call install-abort if present + dup " install-abort" rot ['] $call-method catch if 3drop then + + \ close old stdin + stdin @ ?dup if + dup " remove-abort" rot ['] $call-method catch if 3drop then + close-dev + then + stdin ! + + \ update /chosen + " /chosen" find-package if + >r stdin @ encode-int " stdin" r> (property) + then + +[IFDEF] CONFIG_SPARC32 + \ update stdin-path properties + \ (this isn't part of the IEEE1275 spec but needed by older Solaris) + " /" find-package if + >r stdin @ get-instance-path encode-string " stdin-path" r> (property) + then +[THEN] +; + +: output ( dev-str dev-len -- ) + 2dup find-dev 0= if + ." Output device " type ." not found." cr exit + then + + " write" rot find-method 0= if + type ." has no write method." cr exit + then + drop + + \ open stdin device + 2dup open-dev ?dup 0= if + ." Opening " type ." failed." cr exit + then + -rot 2drop + + \ close old stdout + stdout @ ?dup if close-dev then + stdout ! + + \ update /chosen + " /chosen" find-package if + >r stdout @ encode-int " stdout" r> (property) + then + +[IFDEF] CONFIG_SPARC32 + \ update stdout-path properties + \ (this isn't part of the IEEE1275 spec but needed by older Solaris) + " /" find-package if + >r stdout @ get-instance-path encode-string " stdout-path" r> (property) + then +[THEN] +; + +: io ( dev-str dev-len -- ) + 2dup input output +; + +\ key?, key and emit implementation +variable io-char +variable io-out-char + +: io-key? ( -- available? ) + io-char @ -1 <> if true exit then + io-char 1 " read" stdin @ $call-method + 1 = +; + +: io-key ( -- key ) + \ poll for key + begin io-key? until + io-char c@ -1 to io-char +; + +: io-emit ( char -- ) + stdout @ if + io-out-char c! + io-out-char 1 " write" stdout @ $call-method + then + drop +; + +variable CONSOLE-IN-list +variable CONSOLE-OUT-list + +: CONSOLE-IN-initializer ( xt -- ) + CONSOLE-IN-list list-add , +; +: CONSOLE-OUT-initializer ( xt -- ) + CONSOLE-OUT-list list-add , +; + +: install-console ( -- ) + + \ create screen alias + " /aliases" find-package if + >r + " screen" find-package if drop else + \ bad (or missing) screen alias + 0 " display" iterate-device-type ?dup if + ( display-ph R: alias-ph ) + get-package-path encode-string " screen" r@ (property) + then + then + r> drop + then + + output-device output + input-device input + + \ let arch determine a useful output device + CONSOLE-OUT-list begin list-get while + stdout @ if drop else @ execute then + repeat + + \ let arch determine a useful input device + CONSOLE-IN-list begin list-get while + stdin @ if drop else @ execute then + repeat + + \ activate console + stdout @ if + ['] io-emit to emit + then + + stdin @ if + -1 to io-char + ['] io-key? to key? + ['] io-key to key + then +; + +:noname + " screen" output +; CONSOLE-OUT-initializer diff --git a/qemu/roms/openbios/forth/admin/nvram.fs b/qemu/roms/openbios/forth/admin/nvram.fs new file mode 100644 index 000000000..20f6462b9 --- /dev/null +++ b/qemu/roms/openbios/forth/admin/nvram.fs @@ -0,0 +1,385 @@ +\ tag: nvram config handling +\ +\ this code implements IEEE 1275-1994 +\ +\ Copyright (C) 2003, 2004 Samuel Rydh +\ +\ See the file "COPYING" for further information about +\ the copyright and warranty status of this work. +\ + +struct ( config ) + 2 cells field >cf.name + 2 cells field >cf.default \ 0 -1 if no default + /n field >cf.check-xt + /n field >cf.exec-xt + /n field >cf.next +constant config-info.size + +0 value config-root + +\ -------------------------------------------------------- +\ config handling +\ -------------------------------------------------------- + +: find-config ( name-str len -- 0|configptr ) + config-root + begin ?dup while + -rot + 2dup 4 pick >cf.name 2@ + strcmp 0= if + 2drop exit + then + rot >cf.next @ + repeat + 2drop 0 +; + +: is-config-word ( configp -- ) + dup >cf.name 2@ $create , + does> @ + dup >cf.name 2@ + s" /options" find-dev if + get-package-property if 0 -1 then + ( configp prop-str prop-len ) + \ drop trailing zero + ?dup if 1- then + else + 2drop 0 -1 + then + \ use default value if property is missing + dup 0< if 2drop dup >cf.default 2@ then + \ no default value, use empty string + dup 0< if 2drop 0 0 then + + rot >cf.exec-xt @ execute +; + +: new-config ( name-str name-len -- configp ) + 2dup find-config ?dup if + nip nip + 0 0 2 pick >cf.default 2! + else + dict-strdup + here config-info.size allot + dup config-info.size 0 fill + config-root over >cf.next ! + dup to config-root + dup >r >cf.name 2! r> + dup is-config-word + then + ( configp ) +; + +: config-default ( str len configp -- ) + -rot + dup 0> if dict-strdup then + rot >cf.default 2! +; + +: no-conf-def ( configp -- ) + 0 -1 +; + +\ -------------------------------------------------------- +\ config types +\ -------------------------------------------------------- + +: exec-str-conf ( str len -- str len ) + \ trivial +; +: check-str-conf ( str len -- str len valid? ) + \ nothing + true +; + +: str-config ( def-str len name len -- configp ) + new-config >r + ['] exec-str-conf r@ >cf.exec-xt ! + ['] check-str-conf r@ >cf.check-xt ! + r> config-default +; + +\ ------------------------------------------------------------ + +: exec-int-conf ( str len -- value ) + \ fixme + parse-hex +; +: check-int-conf ( str len -- str len valid? ) + true +; + +: int-config ( def-str len name len -- configp ) + new-config >r + ['] exec-int-conf r@ >cf.exec-xt ! + ['] check-int-conf r@ >cf.check-xt ! + r> config-default +; + +\ ------------------------------------------------------------ + +: exec-secmode-conf ( str len -- n ) + 2dup s" command" strcmp 0= if 2drop 1 exit then + 2dup s" full" strcmp 0= if 2drop 2 exit then + 2drop 0 +; +: check-secmode-conf ( str len -- str len valid? ) + 2dup s" none" strcmp 0= if true exit then + 2dup s" command" strcmp 0= if true exit then + 2dup s" full" strcmp 0= if true exit then + false +; + +: secmode-config ( def-str len name len -- configp ) + new-config >r + ['] exec-secmode-conf r@ >cf.exec-xt ! + ['] check-secmode-conf r@ >cf.check-xt ! + r> config-default +; + +\ ------------------------------------------------------------ + +: exec-bool-conf ( str len -- value ) + 2dup s" true" strcmp 0= if 2drop true exit then + 2dup s" false" strcmp 0= if 2drop false exit then + 2dup s" TRUE" strcmp 0= if 2drop false exit then + 2dup s" FALSE" strcmp 0= if 2drop false exit then + parse-hex 0<> +; + +: check-bool-conf ( name len -- str len valid? ) + 2dup s" true" strcmp 0= if true exit then + 2dup s" false" strcmp 0= if true exit then + 2dup s" TRUE" strcmp 0= if 2drop s" true" true exit then + 2dup s" FALSE" strcmp 0= if 2drop s" false" true exit then + false +; + +: bool-config ( configp -- configp ) + new-config >r + ['] exec-bool-conf r@ >cf.exec-xt ! + ['] check-bool-conf r@ >cf.check-xt ! + r> config-default +; + + +\ -------------------------------------------------------- +\ 7.4.4 Nonvolatile memory +\ -------------------------------------------------------- + +: $setenv ( data-addr data-len name-str name-len -- ) + 2dup find-config ?dup if + >r 2swap r> + ( name len data len configptr ) + >cf.check-xt @ execute + 0= abort" Invalid value." + 2swap + else + \ create string config type + 2dup no-conf-def 2swap str-config + then + + 2swap encode-string 2swap + s" /options" find-package drop + encode-property +; + +: setenv ( "nv-param< >new-value<eol>" -- ) + parse-word + \ XXX drop blanks + dup if linefeed parse else 0 0 then + + dup 0= abort" Invalid value." + 2swap $setenv +; + +: printenv ( "{param-name}<eol>" -- ) + \ XXX temporary implementation + linefeed parse 2drop + + active-package + s" /options" find-device + .properties + active-package! +; + +: (set-default) ( configptr -- ) + dup >cf.default 2@ dup 0>= if + rot >cf.name 2@ $setenv + else + \ no default value + 3drop + then +; + +: set-default ( "param-name<eol>" -- ) + linefeed parse + find-config ?dup if + (set-default) + else + ." No such parameter." -2 throw + then +; + +: set-defaults ( -- ) + config-root + begin ?dup while + dup (set-default) + >cf.next @ + repeat +; + +( maxlen "new-name< >" -- ) ( E: -- addr len ) +: nodefault-bytes + ; + + +\ -------------------------------------------------------- +\ initialize config from nvram +\ -------------------------------------------------------- + +\ CHRP format (array of null-terminated strings, "variable=value") +: nvram-load-configs ( data len -- ) + \ XXX: no len checking performed... + drop + begin dup c@ while + ( data ) + dup cstrlen 2dup + 1+ -rot + ( next str len ) + ascii = left-split ( next val len name str ) + ['] $setenv catch if + 2drop 2drop + then + repeat drop +; + +: (nvram-store-one) ( buf len str len -- buf len success? ) + swap >r + 2dup < if r> 2drop 2drop false exit then + ( buf len strlen R: str ) + swap over - r> swap >r -rot + ( str buf strlen R: res_len ) + 2dup + >r move r> r> true +; + +: (make-configstr) ( configptr ph -- str len ) + >r + >cf.name 2@ + 2dup r> get-package-property if + 2drop 0 0 exit + else + dup if 1- then + then + ( name len value-str len ) + 2swap s" =" 2swap + pocket tmpstrcat tmpstrcat drop + 2dup + 0 swap c! + 1+ +; + +: nvram-store-configs ( data len -- ) + 2 - \ make room for two trailing zeros + + s" /options" find-dev 0= if 2drop exit then + >r + config-root + ( data len configptr R: phandle ) + begin ?dup while + r@ over >r (make-configstr) + ( buf len val len R: configptr phandle ) + (nvram-store-one) drop + r> >cf.next @ + repeat + \ null terminate + 2 + 0 fill + r> drop +; + + +\ -------------------------------------------------------- +\ NVRAM variables +\ -------------------------------------------------------- +\ fcode-debug? input-device output-device +s" true" s" auto-boot?" bool-config \ 7.4.3.5 +s" boot" s" boot-command" str-config \ 7.4.3.5 +s" " s" boot-file" str-config \ 7.4.3.5 +s" false" s" diag-switch?" bool-config \ 7.4.3.5 +no-conf-def s" diag-device" str-config \ 7.4.3.5 +no-conf-def s" diag-file" str-config \ 7.4.3.5 +s" false" s" fcode-debug?" bool-config \ 7.7 +s" " s" nvramrc" str-config \ 7.4.4.2 +s" false" s" oem-banner?" bool-config +s" " s" oem-banner" str-config +s" false" s" oem-logo?" bool-config +no-conf-def s" oem-logo" str-config +s" false" s" use-nvramrc?" bool-config \ 7.4.4.2 +s" keyboard" s" input-device" str-config \ 7.4.5 +s" screen" s" output-device" str-config \ 7.4.5 +s" 80" s" screen-#columns" int-config \ 7.4.5 +s" 24" s" screen-#rows" int-config \ 7.4.5 +s" 0" s" selftest-#megs" int-config +no-conf-def s" security-mode" secmode-config + +\ --- devices --- +s" -1" s" pci-probe-mask" int-config +s" false" s" default-mac-address" bool-config +s" false" s" skip-netboot?" bool-config +s" true" s" scroll-lock" bool-config + +[IFDEF] CONFIG_PPC +\ ---- PPC ---- +s" false" s" little-endian?" bool-config +s" false" s" real-mode?" bool-config +s" -1" s" real-base" int-config +s" -1" s" real-size" int-config +s" 4000000" s" load-base" int-config +s" -1" s" virt-base" int-config +s" -1" s" virt-size" int-config +[THEN] + +[IFDEF] CONFIG_X86 +\ ---- X86 ---- +s" true" s" little-endian?" bool-config +[THEN] + +[IFDEF] CONFIG_SPARC32 +\ ---- SPARC32 ---- +s" 4000" s" load-base" int-config +s" true" s" tpe-link-test?" bool-config +s" 9600,8,n,1,-" s" ttya-mode" str-config +s" true" s" ttya-ignore-cd" bool-config +s" false" s" ttya-rts-dtr-off" bool-config +s" 9600,8,n,1,-" s" ttyb-mode" str-config +s" true" s" ttyb-ignore-cd" bool-config +s" false" s" ttyb-rts-dtr-off" bool-config +[THEN] + +[IFDEF] CONFIG_SPARC64 +\ ---- SPARC64 ---- +s" 4000" s" load-base" int-config +s" false" s" little-endian?" bool-config +[THEN] + +\ --- ??? --- +s" " s" boot-screen" str-config +s" " s" boot-script" str-config +s" false" s" use-generic?" bool-config +s" disk" s" boot-device" str-config \ 7.4.3.5 +s" " s" boot-args" str-config \ ??? + +\ defers +['] fcode-debug? to _fcode-debug? +['] diag-switch? to _diag-switch? + +\ Hack for load-base: it seems that some Sun bootloaders try +\ and execute "<value> to load-base" which will only work if +\ load-base is value. Hence we redefine load-base here as a +\ value using its normal default. +[IFDEF] CONFIG_SPARC64 +load-base value load-base +[THEN] + +: release-load-area + drop +; diff --git a/qemu/roms/openbios/forth/admin/reset.fs b/qemu/roms/openbios/forth/admin/reset.fs new file mode 100644 index 000000000..565692658 --- /dev/null +++ b/qemu/roms/openbios/forth/admin/reset.fs @@ -0,0 +1,12 @@ +\ 7.4.7 Reset + +defer reset-all ( -- ) + +: no-reset-all + s" reset-all is not available on this platform." type cr + ; + +' no-reset-all to reset-all + +\ OpenBOOT knows reset as well. +: reset reset-all ; diff --git a/qemu/roms/openbios/forth/admin/script.fs b/qemu/roms/openbios/forth/admin/script.fs new file mode 100644 index 000000000..a65adb207 --- /dev/null +++ b/qemu/roms/openbios/forth/admin/script.fs @@ -0,0 +1,16 @@ +\ 7.4.4.2 The script + +: nvedit ( -- ) + ; + +: nvstore ( -- ) + ; + +: nvquit ( -- ) + ; + +: nvrecover ( -- ) + ; + +: nvrun ( -- ) + ; diff --git a/qemu/roms/openbios/forth/admin/security.fs b/qemu/roms/openbios/forth/admin/security.fs new file mode 100644 index 000000000..ef2ec30be --- /dev/null +++ b/qemu/roms/openbios/forth/admin/security.fs @@ -0,0 +1,10 @@ +\ 7.4.6 Security + +: password ( -- ) + ; + +: security-password ( -- password-str password-len ) + ; + +: security-#badlogins ( -- n ) + ; diff --git a/qemu/roms/openbios/forth/admin/selftest.fs b/qemu/roms/openbios/forth/admin/selftest.fs new file mode 100644 index 000000000..20c0c963b --- /dev/null +++ b/qemu/roms/openbios/forth/admin/selftest.fs @@ -0,0 +1,49 @@ +\ tag: self-test +\ +\ this code implements IEEE 1275-1994 ch. 7.4.8 +\ +\ Copyright (C) 2003 Stefan Reinauer +\ +\ See the file "COPYING" for further information about +\ the copyright and warranty status of this work. +\ + +\ +\ 7.4.8 Self-test +\ + +: $test ( devname-addr devname-len -- ) + 2dup ." Testing device " type ." : " + find-dev if + s" self-test" rot find-method if + execute + else + ." no self-test method." + then + else + ." no such device." + then + cr +; + +: test ( "device-specifier<cr>"-- ) + linefeed parse cr $test + ; + +: test-sub-devs + >dn.child @ + begin dup while + dup get-package-path $test + dup recurse + >dn.peer @ + repeat + drop +; + +: test-all ( "{device-specifier}<cr>" -- ) + active-package + cr " /" find-device + linefeed parse find-device + ?active-package test-sub-devs + active-package! + ; diff --git a/qemu/roms/openbios/forth/admin/userboot.fs b/qemu/roms/openbios/forth/admin/userboot.fs new file mode 100644 index 000000000..3ae899c2f --- /dev/null +++ b/qemu/roms/openbios/forth/admin/userboot.fs @@ -0,0 +1,29 @@ +\ 7.4.3.5 User commands for booting + +: boot ( "{param-text}<cr>" -- ) + linefeed parse + + \ Copy NVRAM parameters from boot-file to bootargs in case any parameters have + \ been specified for the platform-specific boot code + s" boot-file" $find drop execute + encode-string + " /chosen" (find-dev) if + " bootargs" rot (property) + then + + \ Execute platform-specific boot code, e.g. kernel + s" platform-boot" $find if + execute + then + + (find-bootdevice) \ Setup bootargs + $load \ load and go + go +; + + +\ : diagnostic-mode? ( -- diag? ) +\ ; + +\ : diag-switch? ( -- diag? ) +\ ; diff --git a/qemu/roms/openbios/forth/bootstrap/bootstrap.fs b/qemu/roms/openbios/forth/bootstrap/bootstrap.fs new file mode 100644 index 000000000..0668cf7d8 --- /dev/null +++ b/qemu/roms/openbios/forth/bootstrap/bootstrap.fs @@ -0,0 +1,1590 @@ +\ tag: bootstrap of basic forth words +\ +\ Copyright (C) 2003-2005 Stefan Reinauer, Patrick Mauritz +\ +\ See the file "COPYING" for further information about +\ the copyright and warranty status of this work. +\ + +\ +\ this file contains almost all forth words described +\ by the open firmware user interface. Some more complex +\ parts are found in seperate files (memory management, +\ vocabulary support) +\ + +\ +\ often used constants (reduces dictionary size) +\ + +1 constant 1 +2 constant 2 +3 constant 3 +-1 constant -1 +0 constant 0 + +0 value my-self + +\ +\ 7.3.5.1 Numeric-base control +\ + +: decimal 10 base ! ; +: hex 16 base ! ; +: octal 8 base ! ; +hex + +\ +\ vocabulary words +\ + +variable current forth-last current ! + +: last + current @ + ; + +variable #order 0 #order ! + +defer context +0 value vocabularies? + +defer locals-end +0 value locals-dict +variable locals-dict-buf + +\ +\ 7.3.7 Flag constants +\ + +1 1 = constant true +0 1 = constant false + +\ +\ 7.3.9.2.2 Immediate words (part 1) +\ + +: (immediate) ( xt -- ) + 1 - dup c@ 1 or swap c! + ; + +: (compile-only) + 1 - dup c@ 2 or swap c! + ; + +: immediate + last @ (immediate) + ; + +: compile-only + last @ (compile-only) + ; + +: flags? ( xt -- flags ) + /n /c + - c@ 7f and + ; + +: immediate? ( xt -- true|false ) + flags? 1 and 1 = + ; + +: compile-only? ( xt -- true|false ) + flags? 2 and 2 = + ; + +: [ 0 state ! ; compile-only +: ] -1 state ! ; + + + +\ +\ 7.3.9.2.1 Data space allocation +\ + +: allot here + here! ; +: , here /n allot ! ; +: c, here /c allot c! ; + +: align + /n here /n 1 - and - \ how many bytes to next alignment + /n 1 - and allot \ mask out everything that is bigger + ; \ than cellsize-1 + +: null-align + here dup align here swap - 0 fill + ; + +: w, + here 1 and allot \ if here is not even, we have to align. + here /w allot w! + ; + +: l, + /l here /l 1 - and - \ same as in align, with /l + /l 1 - and \ if it's /l we are already aligned. + allot + here /l allot l! + ; + + +\ +\ 7.3.6 comparison operators (part 1) +\ + +: <> = invert ; + + +\ +\ 7.3.9.2.4 Miscellaneous dictionary (part 1) +\ + +: (to) ( xt-new xt-defer -- ) + /n + ! + ; + +: >body ( xt -- a-addr ) /n 1 lshift + ; +: body> ( a-addr -- xt ) /n 1 lshift - ; + +: reveal latest @ last ! ; +: recursive reveal ; immediate +: recurse latest @ /n + , ; immediate + +: noop ; + +defer environment? +: no-environment? + 2drop false + ; + +['] no-environment? ['] environment? (to) + + +\ +\ 7.3.8.1 Conditional branches +\ + +\ A control stack entry is implemented using 2 data stack items +\ of the form ( addr type ). type can be one of the +\ following: +\ 0 - orig +\ 1 - dest +\ 2 - do-sys + +: resolve-orig here nip over /n + - swap ! ; +: (if) ['] do?branch , here 0 0 , ; compile-only +: (then) resolve-orig ; compile-only + +variable tmp-comp-depth -1 tmp-comp-depth ! +variable tmp-comp-buf 0 tmp-comp-buf ! + +: setup-tmp-comp ( -- ) + state @ 0 = (if) + here tmp-comp-buf @ here! , \ save here and switch to tmp directory + 1 , \ DOCOL + depth tmp-comp-depth ! \ save control depth + ] + (then) +; + +: execute-tmp-comp ( -- ) + depth tmp-comp-depth @ = + (if) + -1 tmp-comp-depth ! + ['] (semis) , + tmp-comp-buf @ + dup @ here! + 0 state ! + /n + execute + (then) +; + +: if setup-tmp-comp ['] do?branch , here 0 0 , ; immediate +: then resolve-orig execute-tmp-comp ; compile-only +: else ['] dobranch , here 0 0 , 2swap resolve-orig ; compile-only + +\ +\ 7.3.8.3 Conditional loops +\ + +\ some dummy words for see +: (begin) ; +: (again) ; +: (until) ; +: (while) ; +: (repeat) ; + +\ resolve-dest requires a loop... +: (resolve-dest) here /n + nip - , ; +: (resolve-begin) setup-tmp-comp ['] (begin) , here 1 ; immediate +: (resolve-until) ['] (until) , ['] do?branch , (resolve-dest) execute-tmp-comp ; compile-only + +: resolve-dest ( dest origN ... orig ) + 2 >r + (resolve-begin) + \ Find topmost control stack entry with a type of 1 (dest) + r> dup dup pick 1 = if + \ Move it to the top + roll + swap 1 - roll + \ Resolve it + (resolve-dest) + 1 \ force exit + else + drop + 2 + >r + 0 + then + (resolve-until) +; + +: begin + setup-tmp-comp + ['] (begin) , + here + 1 + ; immediate + +: again + ['] (again) , + ['] dobranch , + resolve-dest + execute-tmp-comp + ; compile-only + +: until + ['] (until) , + ['] do?branch , + resolve-dest + execute-tmp-comp + ; compile-only + +: while + setup-tmp-comp + ['] (while) , + ['] do?branch , + here 0 0 , 2swap + ; immediate + +: repeat + ['] (repeat) , + ['] dobranch , + resolve-dest resolve-orig + execute-tmp-comp + ; compile-only + + +\ +\ 7.3.8.4 Counted loops +\ + +variable leaves 0 leaves ! + +: resolve-loop + leaves @ + begin + ?dup + while + dup @ \ leaves -- leaves *leaves ) + swap \ -- *leaves leaves ) + here over - \ -- *leaves leaves here-leaves + swap ! \ -- *leaves + repeat + here nip - , + leaves ! + ; + +: do + setup-tmp-comp + leaves @ + here 2 + ['] (do) , + 0 leaves ! + ; immediate + +: ?do + setup-tmp-comp + leaves @ + ['] (?do) , + here 2 + here leaves ! + 0 , + ; immediate + +: loop + ['] (loop) , + resolve-loop + execute-tmp-comp + ; immediate + +: +loop + ['] (+loop) , + resolve-loop + execute-tmp-comp + ; immediate + + +\ Using primitive versions of i and j +\ speeds up loops by 300% +\ : i r> r@ swap >r ; +\ : j r> r> r> r@ -rot >r >r swap >r ; + +: unloop r> r> r> 2drop >r ; + +: leave + ['] unloop , + ['] dobranch , + leaves @ + here leaves ! + , + ; immediate + +: ?leave if leave then ; + +\ +\ 7.3.8.2 Case statement +\ + +: case + setup-tmp-comp + 0 +; immediate + +: endcase + ['] drop , + 0 ?do + ['] then execute + loop + execute-tmp-comp +; immediate + +: of + 1 + >r + ['] over , + ['] = , + ['] if execute + ['] drop , + r> + ; immediate + +: endof + >r + ['] else execute + r> + ; immediate + +\ +\ 7.3.8.5 Other control flow commands +\ + +: exit r> drop ; + + +\ +\ 7.3.4.3 ASCII constants (part 1) +\ + +20 constant bl +07 constant bell +08 constant bs +0d constant carret +0a constant linefeed + + +\ +\ 7.3.1.1 - stack duplication +\ +: tuck swap over ; +: 3dup 2 pick 2 pick 2 pick ; + +\ +\ 7.3.1.2 - stack removal +\ +: clear 0 depth! ; +: 3drop 2drop drop ; + +\ +\ 7.3.1.3 - stack rearrangement +\ + +: 2rot >r >r 2swap r> r> 2swap ; + +\ +\ 7.3.1.4 - return stack +\ + +\ Note: these words are not part of the official OF specification, however +\ they are part of the ANSI DPANS94 core extensions (see section 6.2) and +\ so this seems an appropriate place for them. +: 2>r r> -rot swap >r >r >r ; +: 2r> r> r> r> rot >r swap ; +: 2r@ r> r> r> 2dup >r >r rot >r swap ; + +\ +\ 7.3.2.1 - single precision integer arithmetic (part 1) +\ + +: u/mod 0 swap mu/mod drop ; +: 1+ 1 + ; +: 1- 1 - ; +: 2+ 2 + ; +: 2- 2 - ; +: even 1+ -2 and ; +: bounds over + swap ; + +\ +\ 7.3.2.2 bitwise logical operators +\ +: << lshift ; +: >> rshift ; +: 2* 1 lshift ; +: u2/ 1 rshift ; +: 2/ 1 >>a ; +: not invert ; + +\ +\ 7.3.2.3 double number arithmetic +\ + +: s>d dup 0 < ; +: dnegate 0 0 2swap d- ; +: dabs dup 0 < if dnegate then ; +: um/mod mu/mod drop ; + +\ symmetric division +: sm/rem ( d n -- rem quot ) + over >r >r dabs r@ abs um/mod r> 0 < + if + negate + then + r> 0 < if + negate swap negate swap + then + ; + +\ floored division +: fm/mod ( d n -- rem quot ) + dup >r 2dup xor 0 < >r sm/rem over 0 <> r> and if + 1 - swap r> + swap exit + then + r> drop + ; + +\ +\ 7.3.2.1 - single precision integer arithmetic (part 2) +\ + +: */mod ( n1 n2 n3 -- quot rem ) >r m* r> fm/mod ; +: */ ( n1 n2 n3 -- n1*n2/n3 ) */mod nip ; +: /mod >r s>d r> fm/mod ; +: mod /mod drop ; +: / /mod nip ; + + +\ +\ 7.3.2.4 Data type conversion +\ + +: lwsplit ( quad -- w.lo w.hi ) + dup ffff and swap 10 rshift ffff and +; + +: wbsplit ( word -- b.lo b.hi ) + dup ff and swap 8 rshift ff and +; + +: lbsplit ( quad -- b.lo b2 b3 b.hi ) + lwsplit swap wbsplit rot wbsplit +; + +: bwjoin ( b.lo b.hi -- word ) + ff and 8 lshift swap ff and or +; + +: wljoin ( w.lo w.hi -- quad ) + ffff and 10 lshift swap ffff and or +; + +: bljoin ( b.lo b2 b3 b.hi -- quad ) + bwjoin -rot bwjoin swap wljoin +; + +: wbflip ( word -- word ) \ flips bytes in a word + dup 8 rshift ff and swap ff and bwjoin +; + +: lwflip ( q1 -- q2 ) + dup 10 rshift ffff and swap ffff and wljoin +; + +: lbflip ( q1 -- q2 ) + dup 10 rshift ffff and wbflip swap ffff and wbflip wljoin +; + +\ +\ 7.3.2.5 address arithmetic +\ + +: /c* /c * ; +: /w* /w * ; +: /l* /l * ; +: /n* /n * ; +: ca+ /c* + ; +: wa+ /w* + ; +: la+ /l* + ; +: na+ /n* + ; +: ca1+ /c + ; +: wa1+ /w + ; +: la1+ /l + ; +: na1+ /n + ; +: aligned /n 1- + /n negate and ; +: char+ ca1+ ; +: cell+ na1+ ; +: chars /c* ; +: cells /n* ; +/n constant cell + +\ +\ 7.3.6 Comparison operators +\ + +: <= > not ; +: >= < not ; +: 0= 0 = ; +: 0<= 0 <= ; +: 0< 0 < ; +: 0<> 0 <> ; +: 0> 0 > ; +: 0>= 0 >= ; +: u<= u> not ; +: u>= u< not ; +: within >r over > swap r> >= or not ; +: between 1 + within ; + +\ +\ 7.3.3.1 Memory access +\ + +: 2@ dup cell+ @ swap @ ; +: 2! dup >r ! r> cell+ ! ; + +: <w@ w@ dup 8000 >= if 10000 - then ; + +: comp ( str1 str2 len -- 0|1|-1 ) + >r 0 -rot r> + bounds ?do + dup c@ i c@ - dup if + < if 1 else -1 then swap leave + then + drop ca1+ + loop + drop +; + +\ compare two string + +: $= ( str1 len1 str2 len2 -- true|false ) + rot ( str1 str2 len2 len1 ) + over ( str1 str2 len2 len1 len2 ) + <> if ( str1 str2 len2 ) + 3drop + false + else ( str1 str2 len2 ) + comp + 0= + then +; + +\ : +! tuck @ + swap ! ; +: off false swap ! ; +: on true swap ! ; +: blank bl fill ; +: erase 0 fill ; +: wbflips ( waddr len -- ) + bounds do i w@ wbflip i w! /w +loop +; + +: lwflips ( qaddr len -- ) + bounds do i l@ lwflip i l! /l +loop +; + +: lbflips ( qaddr len -- ) + bounds do i l@ lbflip i l! /l +loop +; + + +\ +\ 7.3.8.6 Error handling (part 1) +\ + +variable catchframe +0 catchframe ! + +: catch + my-self >r + depth >r + catchframe @ >r + rdepth catchframe ! + execute + r> catchframe ! + r> r> 2drop 0 + ; + +: throw + ?dup if + catchframe @ rdepth! + r> catchframe ! + r> swap >r depth! + drop r> + r> ['] my-self (to) + then + ; + +\ +\ 7.3.3.2 memory allocation +\ + +include memory.fs + + +\ +\ 7.3.4.4 Console output (part 1) +\ + +defer emit + +: type bounds ?do i c@ emit loop ; + +\ this one obviously only works when called +\ with a forth string as count fetches addr-1. +\ openfirmware has no such req. therefore it has to go: + +\ : type 0 do count emit loop drop ; + +: debug-type bounds ?do i c@ (emit) loop ; + +\ +\ 7.3.4.1 Text Input +\ + +0 value source-id +0 value ib +variable #ib 0 #ib ! +variable >in 0 >in ! + +: source ( -- addr len ) + ib #ib @ + ; + +: /string ( c-addr1 u1 n -- c-addr2 u2 ) + tuck - -rot + swap +; + + +\ +\ pockets implementation for 7.3.4.1 + +100 constant pocketsize +4 constant numpockets +variable pockets 0 pockets ! +variable whichpocket 0 whichpocket ! + +\ allocate 4 pockets to begin with +: init-pockets ( -- ) + pocketsize numpockets * alloc-mem pockets ! + ; + +: pocket ( ?? -- ?? ) + pocketsize whichpocket @ * + pockets @ + + whichpocket @ 1 + numpockets mod + whichpocket ! + ; + +\ span variable from 7.3.4.2 +variable span 0 span ! + +\ if char is bl then any control character is matched +: findchar ( str len char -- offs true | false ) + swap 0 do + over i + c@ + over dup bl = if <= else = then if + 2drop i dup dup leave + \ i nip nip true exit \ replaces above + then + loop + = + \ drop drop false + ; + +: parse ( delim text<delim> -- str len ) + >r \ save delimiter + ib >in @ + + span @ >in @ - \ ib+offs len-offset. + dup 0 < if \ if we are already at the end of the string, return an empty string + + 0 \ move to end of input string + r> drop + exit + then + 2dup r> \ ib+offs len-offset ib+offs len-offset delim + findchar if \ look for the delimiter. + nip dup 1+ + else + dup + then + >in +! + \ dup -1 = if drop 0 then \ workaround for negative length + ; + +: skipws ( -- ) + ib span @ ( -- ib recvchars ) + begin + dup >in @ > if ( -- recvchars>offs ) + over >in @ + + c@ bl <= + else + false + then + while + 1 >in +! + repeat + 2drop + ; + +: parse-word ( < >text< > -- str len ) + skipws bl parse + ; + +: word ( delim <delims>text<delim> -- pstr ) + pocket >r parse dup r@ c! bounds r> dup 2swap + do + char+ i c@ over c! + loop + drop + ; + +: ( 29 parse 2drop ; immediate +: \ span @ >in ! ; immediate + + + +\ +\ 7.3.4.7 String literals +\ + +: ", + bounds ?do + i c@ c, + loop + ; + +: (") ( -- addr len ) + r> dup + 2 cells + ( r-addr addr ) + over cell+ @ ( r-addr addr len ) + rot over + aligned cell+ >r ( addr len R: r-addr ) + ; + +: handle-text ( temp-addr len -- addr len ) + state @ if + ['] (") , dup , ", null-align + else + pocket swap + dup >r + 0 ?do + over i + c@ over i + c! + loop + nip r> + then + ; + +: s" + 22 parse handle-text + ; immediate + + + +\ +\ 7.3.4.4 Console output (part 2) +\ + +: ." + 22 parse handle-text + ['] type + state @ if + , + else + execute + then + ; immediate + +: .( + 29 parse handle-text + ['] type + state @ if + , + else + execute + then + ; immediate + + + +\ +\ 7.3.4.8 String manipulation +\ + +: count ( pstr -- str len ) 1+ dup 1- c@ ; + +: pack ( str len addr -- pstr ) + 2dup c! \ store len + 1+ swap 0 ?do + over i + c@ over i + c! + loop nip 1- + ; + +: lcc ( char1 -- char2 ) dup 41 5a between if 20 + then ; +: upc ( char1 -- char2 ) dup 61 7a between if 20 - then ; + +: -trailing ( str len1 -- str len2 ) + begin + dup 0<> if \ len != 0 ? + 2dup 1- + + c@ bl = + else + false + then + while + 1- + repeat + ; + + +\ +\ 7.3.4.5 Output formatting +\ + +: cr linefeed emit ; +: debug-cr linefeed (emit) ; +: (cr carret emit ; +: space bl emit ; +: spaces 0 ?do space loop ; +variable #line 0 #line ! +variable #out 0 #out ! + + +\ +\ 7.3.9.2.3 Dictionary search +\ + +\ helper functions + +: lfa2name ( lfa -- name len ) + 1- \ skip flag byte + begin \ skip 0 padding + 1- dup c@ ?dup + until + 7f and \ clear high bit in length + + tuck - swap ( ptr-to-len len - name len ) + ; + +: comp-nocase ( str1 str2 len -- true|false ) + 0 do + 2dup i + c@ upc ( str1 str2 byteX ) + swap i + c@ upc ( str1 str2 byte1 byte2 ) + <> if + 0 leave + then + loop + if -1 else drop 0 then + swap drop + ; + +: comp-word ( b-str len lfa -- true | false ) + lfa2name ( str len str len -- ) + >r swap r> ( str str len len ) + over = if ( str str len ) + comp-nocase + else + drop drop drop false \ if len does not match, string does not match + then +; + +\ $find is an fcode word, but we place it here since we use it for find. + +: find-wordlist ( name-str name-len last -- xt true | name-str name-len false ) + + @ >r + + begin + 2dup r@ dup if comp-word dup false = then + while + r> @ >r drop + repeat + + r@ if \ successful? + -rot 2drop r> cell+ swap + else + r> drop drop drop false + then + + ; + +: $find ( name-str name-len -- xt true | name-str name-len false ) + locals-dict 0<> if + locals-dict-buf @ find-wordlist ?dup if + exit + then + then + vocabularies? if + #order @ 0 ?do + i cells context + @ + find-wordlist + ?dup if + unloop exit + then + loop + false + else + forth-last find-wordlist + then + ; + +\ look up a word in the current wordlist +: $find1 ( name-str name-len -- xt true | name-str name-len false ) + vocabularies? if + current @ + else + forth-last + then + find-wordlist + ; + + +: ' + parse-word $find 0= if + type 3a emit -13 throw + then + ; + +: ['] + parse-word $find 0= if + type 3a emit -13 throw + then + state @ if + ['] (lit) , , + then + ; immediate + +: find ( pstr -- xt n | pstr false ) + dup count $find \ pstr xt true | pstr name-str name-len false + if + nip true + over immediate? if + negate \ immediate returns 1 + then + else + 2drop false + then + ; + + +\ +\ 7.3.9.2.2 Immediate words (part 2) +\ + +: literal ['] (lit) , , ; immediate +: compile, , ; immediate +: compile r> cell+ dup @ , >r ; +: [compile] ['] ' execute , ; immediate + +: postpone + parse-word $find if + dup immediate? not if + ['] (lit) , , ['] , + then + , + else + s" undefined word " type type cr + then + ; immediate + + +\ +\ 7.3.9.2.4 Miscellaneous dictionary (part 2) +\ + +variable #instance + +: instance ( -- ) + true #instance ! +; + +: #instance-base + my-self dup if @ then +; + +: #instance-offs + my-self dup if na1+ then +; + +\ the following instance words are used internally +\ to implement variable instantiation. + +: instance-cfa? ( cfa -- true | false ) + b e within \ b,c and d are instance defining words +; + +: behavior ( xt-defer -- xt ) + dup @ instance-cfa? if + #instance-base ?dup if + swap na1+ @ + @ + else + 3 /n* + @ + then + else + na1+ @ + then +; + +: (ito) ( xt-new xt-defer -- ) + #instance-base ?dup if + swap na1+ @ + ! + else + 3 /n* + ! + then +; + +: (to-xt) ( xt -- ) + dup @ instance-cfa? + state @ if + swap ['] (lit) , , if ['] (ito) else ['] (to) then , + else + if (ito) else /n + ! then + then +; + +: to + ['] ' execute + (to-xt) + ; immediate + +: is ( xt "wordname<>" -- ) + parse-word $find if + (to) + else + s" could not find " type type + then + ; + +\ +\ 7.3.4.2 Console Input +\ + +defer key? +defer key + +: accept ( addr len -- len2 ) + tuck 0 do + key + dup linefeed = if + space drop drop drop i 0 leave + then + dup emit over c! 1 + + loop + drop ( cr ) + ; + +: expect ( addr len -- ) + accept span ! + ; + + +\ +\ 7.3.4.3 ASCII constants (part 2) +\ + +: handle-lit + state @ if + 2 = if + ['] (lit) , , + then + ['] (lit) , , + else + drop + then + ; + +: char + parse-word 0<> if c@ else s" Unexpected EOL." type cr then ; + ; + +: ascii char 1 handle-lit ; immediate +: [char] char 1 handle-lit ; immediate + +: control + char bl 1- and 1 handle-lit +; immediate + + + +\ +\ 7.3.8.6 Error handling (part 2) +\ + +: abort + -1 throw + ; + +: abort" + ['] if execute + 22 parse handle-text + ['] type , + ['] (lit) , + -2 , + ['] throw , + ['] then execute + ; compile-only + +\ +\ 7.5.3.1 Dictionary search +\ + +\ this does not belong here, but its nice for testing + +: words ( -- ) + last + begin @ + ?dup while + dup lfa2name + + \ Don't print spaces for headerless words + dup if + type space + else + type + then + + repeat + cr + ; + +\ +\ 7.3.5.4 Numeric output primitives +\ + +false value capital-hex? + +: pad ( -- addr ) here 100 + aligned ; + +: todigit ( num -- ascii ) + dup 9 > if + capital-hex? not if + 20 + + then + 7 + + then + 30 + + ; + +: <# pad dup ! ; +: hold pad dup @ 1- tuck swap ! c! ; +: sign + 0< if + 2d hold + then + ; + +: # base @ mu/mod rot todigit hold ; +: #s begin # 2dup or 0= until ; +: #> 2drop pad dup @ tuck - ; +: (.) <# dup >r abs 0 #s r> sign #> ; + +: u# base @ u/mod swap todigit hold ; +: u#s begin u# dup 0= until ; +: u#> 0 #> ; +: (u.) <# u#s u#> ; + +\ +\ 7.3.5.3 Numeric output +\ + +: . (.) type space ; +: s. . ; +: u. (u.) type space ; +: .r swap (.) rot 2dup < if over - spaces else drop then type ; +: u.r swap (u.) rot 2dup < if over - spaces else drop then type ; +: .d base @ swap decimal . base ! ; +: .h base @ swap hex . base ! ; + +: .s + 3c emit depth dup (.) type 3e emit space + 0 + ?do + depth i - 1- pick . + loop + cr + ; + +\ +\ 7.3.5.2 Numeric input +\ + +: digit ( char base -- n true | char false ) + swap dup upc dup + 41 5a ( A - Z ) between if + 7 - + else + dup 39 > if \ protect from : and ; + -rot 2drop false exit + then + then + + 30 ( number 0 ) - rot over swap 0 swap within if + nip true + else + drop false + then + ; + +: >number + begin + dup + while + over c@ base @ digit 0= if + drop exit + then >r 2swap r> swap base @ um* drop rot base @ um* d+ 2swap + 1 /string + repeat + ; + +: numdelim? + dup 2e = swap 2c = or +; + + +: $dnumber? + 0 0 2swap dup 0= if + 2drop 2drop 0 exit + then over c@ 2d = dup >r negate /string begin + >number dup 1 > + while + over c@ numdelim? 0= if + 2drop 2drop r> drop 0 exit + then 1 /string + repeat if + c@ 2e = if + true + else + 2drop r> drop 0 exit + then + else + drop false + then over or if + r> if + dnegate + then 2 + else + drop r> if + negate + then 1 + then +; + + +: $number ( ) + $dnumber? + case + 0 of true endof + 1 of false endof + 2 of drop false endof + endcase +; + +: d# + parse-word + base @ >r + + decimal + + $number if + s" illegal number" type cr 0 + then + r> base ! + 1 handle-lit + ; immediate + +: h# + parse-word + base @ >r + + hex + + $number if + s" illegal number" type cr 0 + then + r> base ! + 1 handle-lit + ; immediate + +: o# + parse-word + base @ >r + + octal + + $number if + s" illegal number" type cr 0 + then + r> base ! + 1 handle-lit + ; immediate + + +\ +\ 7.3.4.7 String Literals (part 2) +\ + +: " + pocket dup + begin + span @ >in @ > if + 22 parse >r ( pocket pocket str R: len ) + over r@ move \ copy string + r> + ( pocket nextdest ) + ib >in @ + c@ ( pocket nextdest nexchar ) + 1 >in +! + 28 = \ is nextchar a parenthesis? + span @ >in @ > \ more input? + and + else + false + then + while + 29 parse \ parse everything up to the next ')' + bounds ?do + i c@ 10 digit if + i 1+ c@ 10 digit if + swap 4 lshift or + else + drop + then + over c! 1+ + 2 + else + drop 1 + then + +loop + repeat + over - + handle-text +; immediate + + +\ +\ 7.3.3.1 Memory Access (part 2) +\ + +: dump ( addr len -- ) + over + swap + cr + do i u. space + 10 0 do + j i + c@ + dup 10 / todigit emit + 10 mod todigit emit + space + i 7 = if space then + loop + 3 spaces + 10 0 do + j i + c@ + dup 20 < if drop 2e then \ non-printables as dots? + emit + loop + cr + 10 +loop +; + + + +\ +\ 7.3.9.1 Defining words +\ + +: header ( name len -- ) + dup if \ might be a noname... + 2dup $find1 if + drop 2dup type s" isn't unique." type cr + else + 2drop + then + then + null-align + dup -rot ", 80 or c, \ write name and len + here /n 1- and 0= if 0 c, then \ pad and space for flags + null-align + 80 here 1- c! \ write flags byte + here last @ , latest ! \ write backlink and set latest + ; + + +: : + parse-word header + 1 , ] + ; + +: :noname + 0 0 header + here + 1 , ] + ; + +: ; + locals-dict 0<> if + 0 ['] locals-dict /n + ! + ['] locals-end , + then + ['] (semis) , reveal ['] [ execute + ; immediate + +: constant + parse-word header + 3 , , \ compile DOCON and value + reveal + ; + +0 value active-package +: instance, ( size -- ) + \ first word of the device node holds the instance size + dup active-package @ dup rot + active-package ! + , , \ offset size +; + +: instance? ( -- flag ) + #instance @ dup if + false #instance ! + then +; + +: value + parse-word header + instance? if + /n b , instance, , \ DOIVAL + else + 3 , , + then + reveal + ; + +: variable + parse-word header + instance? if + /n c , instance, 0 , + else + 4 , 0 , + then + reveal + ; + +: $buffer: ( size str len -- where ) + header + instance? if + /n over /n 1- and - /n 1- and + \ align buffer size + dup c , instance, \ DOIVAR + else + 4 , + then + here swap + 2dup 0 fill \ zerofill + allot + reveal +; + +: buffer: ( size -- ) + parse-word $buffer: drop +; + +: (undefined-defer) ( -- ) + \ XXX: this does not work with behavior ... execute + r@ 2 cells - lfa2name + s" undefined defer word " type type cr ; + +: (undefined-idefer) ( -- ) + s" undefined idefer word " type cr ; + +: defer ( new-name< > -- ) + parse-word header + instance? if + 2 /n* d , instance, \ DOIDEFER + ['] (undefined-idefer) + else + 5 , + ['] (undefined-defer) + then + , + ['] (semis) , + reveal + ; + +: alias ( new-name< >old-name< > -- ) + parse-word + parse-word $find if + -rot \ move xt behind. + header + 1 , \ fixme we want our own cfa here. + , \ compile old name xt + ['] (semis) , + reveal + else + s" undefined word " type type space + 2drop + then + ; + +: $create + header 6 , + ['] noop , + reveal + ; + +: create + parse-word $create + ; + +: (does>) + r> cell+ \ get address of code to execute + latest @ \ backlink of just "create"d word + cell+ cell+ ! \ write code to execute after the + \ new word's CFA + ; + +: does> + ['] (does>) , \ compile does handling + 1 , \ compile docol + ; immediate + +0 constant struct + +: field + create + over , + + + does> + @ + + ; + +: 2constant + create , , + does> 2@ reveal + ; + +\ +\ initializer for the temporary compile buffer +\ + +: init-tmp-comp + here 200 allot tmp-comp-buf ! +; + +\ the end diff --git a/qemu/roms/openbios/forth/bootstrap/build.xml b/qemu/roms/openbios/forth/bootstrap/build.xml new file mode 100644 index 000000000..d950a46df --- /dev/null +++ b/qemu/roms/openbios/forth/bootstrap/build.xml @@ -0,0 +1,16 @@ +<build> + <!-- + build description for openbios forth bootstrap + + Copyright (C) 2004-2005 by Stefan Reinauer + See the file "COPYING" for further information about + the copyright and warranty status of this work. + --> + + <dictionary name="bootstrap"> + <object source="start.fs" target="forth"/> + </dictionary> + + <dictionary name="openbios" init="bootstrap"/> + +</build> diff --git a/qemu/roms/openbios/forth/bootstrap/builtin.fs b/qemu/roms/openbios/forth/bootstrap/builtin.fs new file mode 100644 index 000000000..03f5fde1f --- /dev/null +++ b/qemu/roms/openbios/forth/bootstrap/builtin.fs @@ -0,0 +1,28 @@ +\ tag: initialize builtin functionality +\ +\ Copyright (C) 2003 Stefan Reinauer +\ +\ See the file "COPYING" for further information about +\ the copyright and warranty status of this work. +\ + + + +: init-builtin-terminal ( -- ) + + \ define key, key? and emit + ['] (key) ['] key (to) + ['] (key?) ['] key? (to) + ['] (emit) ['] emit (to) + + \ 2 bytes band guard on each side + 100 #ib ! + #ib @ dup ( -- ibs ibs ) + cell+ alloc-mem ( -- ibs addr ) + dup -rot ( -- addr ibs addr ) + + /w + ['] ib (to) \ assign input buffer + 0 fill \ erase tib + 0 ['] source-id (to) \ builtin terminal has id 0 + + ; diff --git a/qemu/roms/openbios/forth/bootstrap/hayes.fs b/qemu/roms/openbios/forth/bootstrap/hayes.fs new file mode 100644 index 000000000..e5a46f406 --- /dev/null +++ b/qemu/roms/openbios/forth/bootstrap/hayes.fs @@ -0,0 +1,1064 @@ +\ From: John Hayes S1I +\ Subject: tester.fr +\ Date: Mon, 27 Nov 95 13:10:09 PST + +\ (C) 1995 JOHNS HOPKINS UNIVERSITY / APPLIED PHYSICS LABORATORY +\ MAY BE DISTRIBUTED FREELY AS LONG AS THIS COPYRIGHT NOTICE REMAINS. +\ VERSION 1.1 + +HEX + +\ switch output of hex values to capital letters +true to capital-hex? + + +\ SET THE FOLLOWING FLAG TO TRUE FOR MORE VERBOSE OUTPUT; THIS MAY +\ ALLOW YOU TO TELL WHICH TEST CAUSED YOUR SYSTEM TO HANG. + +VARIABLE VERBOSE + FALSE VERBOSE ! + +: EMPTY-STACK \ ( ... -- ) EMPTY STACK: HANDLES UNDERFLOWED STACK TOO. + DEPTH ?DUP IF DUP 0< IF NEGATE 0 DO 0 LOOP ELSE 0 DO DROP LOOP THEN THEN ; + +: ERROR \ ( C-ADDR U -- ) DISPLAY AN ERROR MESSAGE FOLLOWED BY + \ THE LINE THAT HAD THE ERROR. + \ TYPE SOURCE TYPE CR \ DISPLAY LINE CORRESPONDING TO ERROR + + \ FIXME beginagain wants the following for output: + TYPE SOURCE drop span @ TYPE CR \ DISPLAY LINE CORRESPONDING TO ERROR + EMPTY-STACK \ THROW AWAY EVERY THING ELSE + -99 SYS-DEBUG \ MAKE BEGINAGAIN BOOTSTRAP FAIL. +; + +VARIABLE ACTUAL-DEPTH \ STACK RECORD +CREATE ACTUAL-RESULTS 20 CELLS ALLOT + +: { \ ( -- ) SYNTACTIC SUGAR. + ; + +: -> \ ( ... -- ) RECORD DEPTH AND CONTENT OF STACK. + DEPTH DUP ACTUAL-DEPTH ! \ RECORD DEPTH + ?DUP IF \ IF THERE IS SOMETHING ON STACK + 0 DO ACTUAL-RESULTS I CELLS + ! LOOP \ SAVE THEM + THEN ; + +: } \ ( ... -- ) COMPARE STACK (EXPECTED) CONTENTS WITH SAVED + \ (ACTUAL) CONTENTS. + DEPTH ACTUAL-DEPTH @ = IF \ IF DEPTHS MATCH + DEPTH ?DUP IF \ IF THERE IS SOMETHING ON THE STACK + 0 DO \ FOR EACH STACK ITEM + ACTUAL-RESULTS I CELLS + @ \ COMPARE ACTUAL WITH EXPECTED + <> IF S" INCORRECT RESULT: " ERROR LEAVE THEN + LOOP + THEN + ELSE \ DEPTH MISMATCH + S" WRONG NUMBER OF RESULTS: " ERROR + THEN ; + +: TESTING \ ( -- ) TALKING COMMENT. + SOURCE VERBOSE @ + IF DUP >R TYPE CR R> >IN ! + ELSE >IN ! DROP + THEN + ; + +\ From: John Hayes S1I +\ Subject: core.fr +\ Date: Mon, 27 Nov 95 13:10 + +\ (C) 1995 JOHNS HOPKINS UNIVERSITY / APPLIED PHYSICS LABORATORY +\ MAY BE DISTRIBUTED FREELY AS LONG AS THIS COPYRIGHT NOTICE REMAINS. +\ VERSION 1.2 +\ THIS PROGRAM TESTS THE CORE WORDS OF AN ANS FORTH SYSTEM. +\ THE PROGRAM ASSUMES A TWO'S COMPLEMENT IMPLEMENTATION WHERE +\ THE RANGE OF SIGNED NUMBERS IS -2^(N-1) ... 2^(N-1)-1 AND +\ THE RANGE OF UNSIGNED NUMBERS IS 0 ... 2^(N)-1. +\ I HAVEN'T FIGURED OUT HOW TO TEST KEY, QUIT, ABORT, OR ABORT"... +\ I ALSO HAVEN'T THOUGHT OF A WAY TO TEST ENVIRONMENT?... + +TESTING CORE WORDS +HEX + +\ ------------------------------------------------------------------------ +TESTING BASIC ASSUMPTIONS + +{ -> } \ START WITH CLEAN SLATE +( TEST IF ANY BITS ARE SET; ANSWER IN BASE 1 ) +{ : BITSSET? IF 0 0 ELSE 0 THEN ; -> } +{ 0 BITSSET? -> 0 } ( ZERO IS ALL BITS CLEAR ) +{ 1 BITSSET? -> 0 0 } ( OTHER NUMBER HAVE AT LEAST ONE BIT ) +{ -1 BITSSET? -> 0 0 } + +\ ------------------------------------------------------------------------ +TESTING BOOLEANS: INVERT AND OR XOR + +{ 0 0 AND -> 0 } +{ 0 1 AND -> 0 } +{ 1 0 AND -> 0 } +{ 1 1 AND -> 1 } + +{ 0 INVERT 1 AND -> 1 } +{ 1 INVERT 1 AND -> 0 } + +0 CONSTANT 0S +0 INVERT CONSTANT 1S + +{ 0S INVERT -> 1S } +{ 1S INVERT -> 0S } + +{ 0S 0S AND -> 0S } +{ 0S 1S AND -> 0S } +{ 1S 0S AND -> 0S } +{ 1S 1S AND -> 1S } + +{ 0S 0S OR -> 0S } +{ 0S 1S OR -> 1S } +{ 1S 0S OR -> 1S } +{ 1S 1S OR -> 1S } + +{ 0S 0S XOR -> 0S } +{ 0S 1S XOR -> 1S } +{ 1S 0S XOR -> 1S } +{ 1S 1S XOR -> 0S } + +\ ------------------------------------------------------------------------ +TESTING 2* 2/ LSHIFT RSHIFT + +( WE TRUST 1S, INVERT, AND BITSSET?; WE WILL CONFIRM RSHIFT LATER ) +1S 1 RSHIFT INVERT CONSTANT MSB +{ MSB BITSSET? -> 0 0 } + +{ 0S 2* -> 0S } +{ 1 2* -> 2 } +{ 4000 2* -> 8000 } +{ 1S 2* 1 XOR -> 1S } +{ MSB 2* -> 0S } + +{ 0S 2/ -> 0S } +{ 1 2/ -> 0 } +{ 4000 2/ -> 2000 } +{ 1S 2/ -> 1S } \ MSB PROPOGATED +{ 1S 1 XOR 2/ -> 1S } +{ MSB 2/ MSB AND -> MSB } + +{ 1 0 LSHIFT -> 1 } +{ 1 1 LSHIFT -> 2 } +{ 1 2 LSHIFT -> 4 } +{ 1 F LSHIFT -> 8000 } \ BIGGEST GUARANTEED SHIFT +{ 1S 1 LSHIFT 1 XOR -> 1S } +{ MSB 1 LSHIFT -> 0 } + +{ 1 0 RSHIFT -> 1 } +{ 1 1 RSHIFT -> 0 } +{ 2 1 RSHIFT -> 1 } +{ 4 2 RSHIFT -> 1 } +{ 8000 F RSHIFT -> 1 } \ BIGGEST +{ MSB 1 RSHIFT MSB AND -> 0 } \ RSHIFT ZERO FILLS MSBS +{ MSB 1 RSHIFT 2* -> MSB } + +\ ------------------------------------------------------------------------ +TESTING COMPARISONS: 0= = 0< < > U< MIN MAX +0 INVERT CONSTANT MAX-UINT +0 INVERT 1 RSHIFT CONSTANT MAX-INT +0 INVERT 1 RSHIFT INVERT CONSTANT MIN-INT +0 INVERT 1 RSHIFT CONSTANT MID-UINT +0 INVERT 1 RSHIFT INVERT CONSTANT MID-UINT+1 + +0S CONSTANT <FALSE> +1S CONSTANT <TRUE> + +{ 0 0= -> <TRUE> } +{ 1 0= -> <FALSE> } +{ 2 0= -> <FALSE> } +{ -1 0= -> <FALSE> } +{ MAX-UINT 0= -> <FALSE> } +{ MIN-INT 0= -> <FALSE> } +{ MAX-INT 0= -> <FALSE> } + +{ 0 0 = -> <TRUE> } +{ 1 1 = -> <TRUE> } +{ -1 -1 = -> <TRUE> } +{ 1 0 = -> <FALSE> } +{ -1 0 = -> <FALSE> } +{ 0 1 = -> <FALSE> } +{ 0 -1 = -> <FALSE> } + +{ 0 0< -> <FALSE> } +{ -1 0< -> <TRUE> } +{ MIN-INT 0< -> <TRUE> } +{ 1 0< -> <FALSE> } +{ MAX-INT 0< -> <FALSE> } + +{ 0 1 < -> <TRUE> } +{ 1 2 < -> <TRUE> } +{ -1 0 < -> <TRUE> } +{ -1 1 < -> <TRUE> } +{ MIN-INT 0 < -> <TRUE> } +{ MIN-INT MAX-INT < -> <TRUE> } +{ 0 MAX-INT < -> <TRUE> } +{ 0 0 < -> <FALSE> } +{ 1 1 < -> <FALSE> } +{ 1 0 < -> <FALSE> } +{ 2 1 < -> <FALSE> } +{ 0 -1 < -> <FALSE> } +{ 1 -1 < -> <FALSE> } +{ 0 MIN-INT < -> <FALSE> } +{ MAX-INT MIN-INT < -> <FALSE> } +{ MAX-INT 0 < -> <FALSE> } + +{ 0 1 > -> <FALSE> } +{ 1 2 > -> <FALSE> } +{ -1 0 > -> <FALSE> } +{ -1 1 > -> <FALSE> } +{ MIN-INT 0 > -> <FALSE> } +{ MIN-INT MAX-INT > -> <FALSE> } +{ 0 MAX-INT > -> <FALSE> } +{ 0 0 > -> <FALSE> } +{ 1 1 > -> <FALSE> } +{ 1 0 > -> <TRUE> } +{ 2 1 > -> <TRUE> } +{ 0 -1 > -> <TRUE> } +{ 1 -1 > -> <TRUE> } +{ 0 MIN-INT > -> <TRUE> } +{ MAX-INT MIN-INT > -> <TRUE> } +{ MAX-INT 0 > -> <TRUE> } + +{ 0 1 U< -> <TRUE> } +{ 1 2 U< -> <TRUE> } +{ 0 MID-UINT U< -> <TRUE> } +{ 0 MAX-UINT U< -> <TRUE> } +{ MID-UINT MAX-UINT U< -> <TRUE> } +{ 0 0 U< -> <FALSE> } +{ 1 1 U< -> <FALSE> } +{ 1 0 U< -> <FALSE> } +{ 2 1 U< -> <FALSE> } +{ MID-UINT 0 U< -> <FALSE> } +{ MAX-UINT 0 U< -> <FALSE> } +{ MAX-UINT MID-UINT U< -> <FALSE> } + +{ 0 1 MIN -> 0 } +{ 1 2 MIN -> 1 } +{ -1 0 MIN -> -1 } +{ -1 1 MIN -> -1 } +{ MIN-INT 0 MIN -> MIN-INT } +{ MIN-INT MAX-INT MIN -> MIN-INT } +{ 0 MAX-INT MIN -> 0 } +{ 0 0 MIN -> 0 } +{ 1 1 MIN -> 1 } +{ 1 0 MIN -> 0 } +{ 2 1 MIN -> 1 } +{ 0 -1 MIN -> -1 } +{ 1 -1 MIN -> -1 } +{ 0 MIN-INT MIN -> MIN-INT } +{ MAX-INT MIN-INT MIN -> MIN-INT } +{ MAX-INT 0 MIN -> 0 } + +{ 0 1 MAX -> 1 } +{ 1 2 MAX -> 2 } +{ -1 0 MAX -> 0 } +{ -1 1 MAX -> 1 } +{ MIN-INT 0 MAX -> 0 } +{ MIN-INT MAX-INT MAX -> MAX-INT } +{ 0 MAX-INT MAX -> MAX-INT } +{ 0 0 MAX -> 0 } +{ 1 1 MAX -> 1 } +{ 1 0 MAX -> 1 } +{ 2 1 MAX -> 2 } +{ 0 -1 MAX -> 0 } +{ 1 -1 MAX -> 1 } +{ 0 MIN-INT MAX -> 0 } +{ MAX-INT MIN-INT MAX -> MAX-INT } +{ MAX-INT 0 MAX -> MAX-INT } + +\ ------------------------------------------------------------------------ +TESTING STACK OPS: 2DROP 2DUP 2OVER 2SWAP ?DUP DEPTH DROP DUP OVER ROT SWAP + +{ 1 2 2DROP -> } +{ 1 2 2DUP -> 1 2 1 2 } +{ 1 2 3 4 2OVER -> 1 2 3 4 1 2 } +{ 1 2 3 4 2SWAP -> 3 4 1 2 } +{ 0 ?DUP -> 0 } +{ 1 ?DUP -> 1 1 } +{ -1 ?DUP -> -1 -1 } +{ DEPTH -> 0 } +{ 0 DEPTH -> 0 1 } +{ 0 1 DEPTH -> 0 1 2 } +{ 0 DROP -> } +{ 1 2 DROP -> 1 } +{ 1 DUP -> 1 1 } +{ 1 2 OVER -> 1 2 1 } +{ 1 2 3 ROT -> 2 3 1 } +{ 1 2 SWAP -> 2 1 } + +\ ------------------------------------------------------------------------ +TESTING >R R> R@ + +{ : GR1 >R R> ; -> } +{ : GR2 >R R@ R> DROP ; -> } +{ 123 GR1 -> 123 } +{ 123 GR2 -> 123 } +{ 1S GR1 -> 1S } ( RETURN STACK HOLDS CELLS ) + +\ ------------------------------------------------------------------------ +TESTING ADD/SUBTRACT: + - 1+ 1- ABS NEGATE + +{ 0 5 + -> 5 } +{ 5 0 + -> 5 } +{ 0 -5 + -> -5 } +{ -5 0 + -> -5 } +{ 1 2 + -> 3 } +{ 1 -2 + -> -1 } +{ -1 2 + -> 1 } +{ -1 -2 + -> -3 } +{ -1 1 + -> 0 } +{ MID-UINT 1 + -> MID-UINT+1 } + +{ 0 5 - -> -5 } +{ 5 0 - -> 5 } +{ 0 -5 - -> 5 } +{ -5 0 - -> -5 } +{ 1 2 - -> -1 } +{ 1 -2 - -> 3 } +{ -1 2 - -> -3 } +{ -1 -2 - -> 1 } +{ 0 1 - -> -1 } +{ MID-UINT+1 1 - -> MID-UINT } + +{ 0 1+ -> 1 } +{ -1 1+ -> 0 } +{ 1 1+ -> 2 } +{ MID-UINT 1+ -> MID-UINT+1 } + +{ 2 1- -> 1 } +{ 1 1- -> 0 } +{ 0 1- -> -1 } +{ MID-UINT+1 1- -> MID-UINT } + +{ 0 NEGATE -> 0 } +{ 1 NEGATE -> -1 } +{ -1 NEGATE -> 1 } +{ 2 NEGATE -> -2 } +{ -2 NEGATE -> 2 } + +{ 0 ABS -> 0 } +{ 1 ABS -> 1 } +{ -1 ABS -> 1 } +{ MIN-INT ABS -> MID-UINT+1 } + +\ ------------------------------------------------------------------------ +TESTING MULTIPLY: S>D * M* UM* + +{ 0 S>D -> 0 0 } +{ 1 S>D -> 1 0 } +{ 2 S>D -> 2 0 } +{ -1 S>D -> -1 -1 } +{ -2 S>D -> -2 -1 } +{ MIN-INT S>D -> MIN-INT -1 } +{ MAX-INT S>D -> MAX-INT 0 } + +{ 0 0 M* -> 0 S>D } +{ 0 1 M* -> 0 S>D } +{ 1 0 M* -> 0 S>D } +{ 1 2 M* -> 2 S>D } +{ 2 1 M* -> 2 S>D } +{ 3 3 M* -> 9 S>D } +{ -3 3 M* -> -9 S>D } +{ 3 -3 M* -> -9 S>D } +{ -3 -3 M* -> 9 S>D } +{ 0 MIN-INT M* -> 0 S>D } +{ 1 MIN-INT M* -> MIN-INT S>D } +{ 2 MIN-INT M* -> 0 1S } +{ 0 MAX-INT M* -> 0 S>D } +{ 1 MAX-INT M* -> MAX-INT S>D } +{ 2 MAX-INT M* -> MAX-INT 1 LSHIFT 0 } +{ MIN-INT MIN-INT M* -> 0 MSB 1 RSHIFT } +{ MAX-INT MIN-INT M* -> MSB MSB 2/ } +{ MAX-INT MAX-INT M* -> 1 MSB 2/ INVERT } + +{ 0 0 * -> 0 } \ TEST IDENTITIES +{ 0 1 * -> 0 } +{ 1 0 * -> 0 } +{ 1 2 * -> 2 } +{ 2 1 * -> 2 } +{ 3 3 * -> 9 } +{ -3 3 * -> -9 } +{ 3 -3 * -> -9 } +{ -3 -3 * -> 9 } + +{ MID-UINT+1 1 RSHIFT 2 * -> MID-UINT+1 } +{ MID-UINT+1 2 RSHIFT 4 * -> MID-UINT+1 } +{ MID-UINT+1 1 RSHIFT MID-UINT+1 OR 2 * -> MID-UINT+1 } + +{ 0 0 UM* -> 0 0 } +{ 0 1 UM* -> 0 0 } +{ 1 0 UM* -> 0 0 } +{ 1 2 UM* -> 2 0 } +{ 2 1 UM* -> 2 0 } +{ 3 3 UM* -> 9 0 } + +{ MID-UINT+1 1 RSHIFT 2 UM* -> MID-UINT+1 0 } +{ MID-UINT+1 2 UM* -> 0 1 } +{ MID-UINT+1 4 UM* -> 0 2 } +{ 1S 2 UM* -> 1S 1 LSHIFT 1 } +{ MAX-UINT MAX-UINT UM* -> 1 1 INVERT } + +\ ------------------------------------------------------------------------ +TESTING DIVIDE: FM/MOD SM/REM UM/MOD */ */MOD / /MOD MOD + +{ 0 S>D 1 FM/MOD -> 0 0 } +{ 1 S>D 1 FM/MOD -> 0 1 } +{ 2 S>D 1 FM/MOD -> 0 2 } +{ -1 S>D 1 FM/MOD -> 0 -1 } +{ -2 S>D 1 FM/MOD -> 0 -2 } +{ 0 S>D -1 FM/MOD -> 0 0 } +{ 1 S>D -1 FM/MOD -> 0 -1 } +{ 2 S>D -1 FM/MOD -> 0 -2 } +{ -1 S>D -1 FM/MOD -> 0 1 } +{ -2 S>D -1 FM/MOD -> 0 2 } +{ 2 S>D 2 FM/MOD -> 0 1 } +{ -1 S>D -1 FM/MOD -> 0 1 } +{ -2 S>D -2 FM/MOD -> 0 1 } +{ 7 S>D 3 FM/MOD -> 1 2 } +{ 7 S>D -3 FM/MOD -> -2 -3 } +{ -7 S>D 3 FM/MOD -> 2 -3 } +{ -7 S>D -3 FM/MOD -> -1 2 } +{ MAX-INT S>D 1 FM/MOD -> 0 MAX-INT } +{ MIN-INT S>D 1 FM/MOD -> 0 MIN-INT } +{ MAX-INT S>D MAX-INT FM/MOD -> 0 1 } +{ MIN-INT S>D MIN-INT FM/MOD -> 0 1 } +{ 1S 1 4 FM/MOD -> 3 MAX-INT } +{ 1 MIN-INT M* 1 FM/MOD -> 0 MIN-INT } +{ 1 MIN-INT M* MIN-INT FM/MOD -> 0 1 } +{ 2 MIN-INT M* 2 FM/MOD -> 0 MIN-INT } +{ 2 MIN-INT M* MIN-INT FM/MOD -> 0 2 } +{ 1 MAX-INT M* 1 FM/MOD -> 0 MAX-INT } +{ 1 MAX-INT M* MAX-INT FM/MOD -> 0 1 } +{ 2 MAX-INT M* 2 FM/MOD -> 0 MAX-INT } +{ 2 MAX-INT M* MAX-INT FM/MOD -> 0 2 } +{ MIN-INT MIN-INT M* MIN-INT FM/MOD -> 0 MIN-INT } +{ MIN-INT MAX-INT M* MIN-INT FM/MOD -> 0 MAX-INT } +{ MIN-INT MAX-INT M* MAX-INT FM/MOD -> 0 MIN-INT } +{ MAX-INT MAX-INT M* MAX-INT FM/MOD -> 0 MAX-INT } + +{ 0 S>D 1 SM/REM -> 0 0 } +{ 1 S>D 1 SM/REM -> 0 1 } +{ 2 S>D 1 SM/REM -> 0 2 } +{ -1 S>D 1 SM/REM -> 0 -1 } +{ -2 S>D 1 SM/REM -> 0 -2 } +{ 0 S>D -1 SM/REM -> 0 0 } +{ 1 S>D -1 SM/REM -> 0 -1 } +{ 2 S>D -1 SM/REM -> 0 -2 } +{ -1 S>D -1 SM/REM -> 0 1 } +{ -2 S>D -1 SM/REM -> 0 2 } +{ 2 S>D 2 SM/REM -> 0 1 } +{ -1 S>D -1 SM/REM -> 0 1 } +{ -2 S>D -2 SM/REM -> 0 1 } +{ 7 S>D 3 SM/REM -> 1 2 } +{ 7 S>D -3 SM/REM -> 1 -2 } +{ -7 S>D 3 SM/REM -> -1 -2 } +{ -7 S>D -3 SM/REM -> -1 2 } +{ MAX-INT S>D 1 SM/REM -> 0 MAX-INT } +{ MIN-INT S>D 1 SM/REM -> 0 MIN-INT } +{ MAX-INT S>D MAX-INT SM/REM -> 0 1 } +{ MIN-INT S>D MIN-INT SM/REM -> 0 1 } +{ 1S 1 4 SM/REM -> 3 MAX-INT } +{ 2 MIN-INT M* 2 SM/REM -> 0 MIN-INT } +{ 2 MIN-INT M* MIN-INT SM/REM -> 0 2 } +{ 2 MAX-INT M* 2 SM/REM -> 0 MAX-INT } +{ 2 MAX-INT M* MAX-INT SM/REM -> 0 2 } +{ MIN-INT MIN-INT M* MIN-INT SM/REM -> 0 MIN-INT } +{ MIN-INT MAX-INT M* MIN-INT SM/REM -> 0 MAX-INT } +{ MIN-INT MAX-INT M* MAX-INT SM/REM -> 0 MIN-INT } +{ MAX-INT MAX-INT M* MAX-INT SM/REM -> 0 MAX-INT } + +{ 0 0 1 UM/MOD -> 0 0 } +{ 1 0 1 UM/MOD -> 0 1 } +{ 1 0 2 UM/MOD -> 1 0 } +{ 3 0 2 UM/MOD -> 1 1 } +{ MAX-UINT 2 UM* 2 UM/MOD -> 0 MAX-UINT } +{ MAX-UINT 2 UM* MAX-UINT UM/MOD -> 0 2 } +{ MAX-UINT MAX-UINT UM* MAX-UINT UM/MOD -> 0 MAX-UINT } + +: IFFLOORED + [ -3 2 / -2 = INVERT ] LITERAL IF POSTPONE \ THEN ; +: IFSYM + [ -3 2 / -1 = INVERT ] LITERAL IF POSTPONE \ THEN ; + +\ THE SYSTEM MIGHT DO EITHER FLOORED OR SYMMETRIC DIVISION. +\ SINCE WE HAVE ALREADY TESTED M*, FM/MOD, AND SM/REM WE CAN USE THEM IN TEST. +IFFLOORED : T/MOD >R S>D R> FM/MOD ; +IFFLOORED : T/ T/MOD SWAP DROP ; +IFFLOORED : TMOD T/MOD DROP ; +IFFLOORED : T*/MOD >R M* R> FM/MOD ; +IFFLOORED : T*/ T*/MOD SWAP DROP ; +IFSYM : T/MOD >R S>D R> SM/REM ; +IFSYM : T/ T/MOD SWAP DROP ; +IFSYM : TMOD T/MOD DROP ; +IFSYM : T*/MOD >R M* R> SM/REM ; +IFSYM : T*/ T*/MOD SWAP DROP ; + +{ 0 1 /MOD -> 0 1 T/MOD } +{ 1 1 /MOD -> 1 1 T/MOD } +{ 2 1 /MOD -> 2 1 T/MOD } +{ -1 1 /MOD -> -1 1 T/MOD } +{ -2 1 /MOD -> -2 1 T/MOD } +{ 0 -1 /MOD -> 0 -1 T/MOD } +{ 1 -1 /MOD -> 1 -1 T/MOD } +{ 2 -1 /MOD -> 2 -1 T/MOD } +{ -1 -1 /MOD -> -1 -1 T/MOD } +{ -2 -1 /MOD -> -2 -1 T/MOD } +{ 2 2 /MOD -> 2 2 T/MOD } +{ -1 -1 /MOD -> -1 -1 T/MOD } +{ -2 -2 /MOD -> -2 -2 T/MOD } +{ 7 3 /MOD -> 7 3 T/MOD } +{ 7 -3 /MOD -> 7 -3 T/MOD } +{ -7 3 /MOD -> -7 3 T/MOD } +{ -7 -3 /MOD -> -7 -3 T/MOD } +{ MAX-INT 1 /MOD -> MAX-INT 1 T/MOD } +{ MIN-INT 1 /MOD -> MIN-INT 1 T/MOD } +{ MAX-INT MAX-INT /MOD -> MAX-INT MAX-INT T/MOD } +{ MIN-INT MIN-INT /MOD -> MIN-INT MIN-INT T/MOD } + +{ 0 1 / -> 0 1 T/ } +{ 1 1 / -> 1 1 T/ } +{ 2 1 / -> 2 1 T/ } +{ -1 1 / -> -1 1 T/ } +{ -2 1 / -> -2 1 T/ } +{ 0 -1 / -> 0 -1 T/ } +{ 1 -1 / -> 1 -1 T/ } +{ 2 -1 / -> 2 -1 T/ } +{ -1 -1 / -> -1 -1 T/ } +{ -2 -1 / -> -2 -1 T/ } +{ 2 2 / -> 2 2 T/ } +{ -1 -1 / -> -1 -1 T/ } +{ -2 -2 / -> -2 -2 T/ } +{ 7 3 / -> 7 3 T/ } +{ 7 -3 / -> 7 -3 T/ } +{ -7 3 / -> -7 3 T/ } +{ -7 -3 / -> -7 -3 T/ } +{ MAX-INT 1 / -> MAX-INT 1 T/ } +{ MIN-INT 1 / -> MIN-INT 1 T/ } +{ MAX-INT MAX-INT / -> MAX-INT MAX-INT T/ } +{ MIN-INT MIN-INT / -> MIN-INT MIN-INT T/ } + +{ 0 1 MOD -> 0 1 TMOD } +{ 1 1 MOD -> 1 1 TMOD } +{ 2 1 MOD -> 2 1 TMOD } +{ -1 1 MOD -> -1 1 TMOD } +{ -2 1 MOD -> -2 1 TMOD } +{ 0 -1 MOD -> 0 -1 TMOD } +{ 1 -1 MOD -> 1 -1 TMOD } +{ 2 -1 MOD -> 2 -1 TMOD } +{ -1 -1 MOD -> -1 -1 TMOD } +{ -2 -1 MOD -> -2 -1 TMOD } +{ 2 2 MOD -> 2 2 TMOD } +{ -1 -1 MOD -> -1 -1 TMOD } +{ -2 -2 MOD -> -2 -2 TMOD } +{ 7 3 MOD -> 7 3 TMOD } +{ 7 -3 MOD -> 7 -3 TMOD } +{ -7 3 MOD -> -7 3 TMOD } +{ -7 -3 MOD -> -7 -3 TMOD } +{ MAX-INT 1 MOD -> MAX-INT 1 TMOD } +{ MIN-INT 1 MOD -> MIN-INT 1 TMOD } +{ MAX-INT MAX-INT MOD -> MAX-INT MAX-INT TMOD } +{ MIN-INT MIN-INT MOD -> MIN-INT MIN-INT TMOD } + +{ 0 2 1 */ -> 0 2 1 T*/ } +{ 1 2 1 */ -> 1 2 1 T*/ } +{ 2 2 1 */ -> 2 2 1 T*/ } +{ -1 2 1 */ -> -1 2 1 T*/ } +{ -2 2 1 */ -> -2 2 1 T*/ } +{ 0 2 -1 */ -> 0 2 -1 T*/ } +{ 1 2 -1 */ -> 1 2 -1 T*/ } +{ 2 2 -1 */ -> 2 2 -1 T*/ } +{ -1 2 -1 */ -> -1 2 -1 T*/ } +{ -2 2 -1 */ -> -2 2 -1 T*/ } +{ 2 2 2 */ -> 2 2 2 T*/ } +{ -1 2 -1 */ -> -1 2 -1 T*/ } +{ -2 2 -2 */ -> -2 2 -2 T*/ } +{ 7 2 3 */ -> 7 2 3 T*/ } +{ 7 2 -3 */ -> 7 2 -3 T*/ } +{ -7 2 3 */ -> -7 2 3 T*/ } +{ -7 2 -3 */ -> -7 2 -3 T*/ } +{ MAX-INT 2 MAX-INT */ -> MAX-INT 2 MAX-INT T*/ } +{ MIN-INT 2 MIN-INT */ -> MIN-INT 2 MIN-INT T*/ } + +{ 0 2 1 */MOD -> 0 2 1 T*/MOD } +{ 1 2 1 */MOD -> 1 2 1 T*/MOD } +{ 2 2 1 */MOD -> 2 2 1 T*/MOD } +{ -1 2 1 */MOD -> -1 2 1 T*/MOD } +{ -2 2 1 */MOD -> -2 2 1 T*/MOD } +{ 0 2 -1 */MOD -> 0 2 -1 T*/MOD } +{ 1 2 -1 */MOD -> 1 2 -1 T*/MOD } +{ 2 2 -1 */MOD -> 2 2 -1 T*/MOD } +{ -1 2 -1 */MOD -> -1 2 -1 T*/MOD } +{ -2 2 -1 */MOD -> -2 2 -1 T*/MOD } +{ 2 2 2 */MOD -> 2 2 2 T*/MOD } +{ -1 2 -1 */MOD -> -1 2 -1 T*/MOD } +{ -2 2 -2 */MOD -> -2 2 -2 T*/MOD } +{ 7 2 3 */MOD -> 7 2 3 T*/MOD } +{ 7 2 -3 */MOD -> 7 2 -3 T*/MOD } +{ -7 2 3 */MOD -> -7 2 3 T*/MOD } +{ -7 2 -3 */MOD -> -7 2 -3 T*/MOD } +{ MAX-INT 2 MAX-INT */MOD -> MAX-INT 2 MAX-INT T*/MOD } +{ MIN-INT 2 MIN-INT */MOD -> MIN-INT 2 MIN-INT T*/MOD } + +\ ------------------------------------------------------------------------ +TESTING HERE , @ ! CELL+ CELLS C, C@ C! CHARS 2@ 2! ALIGN ALIGNED +! ALLOT + +HERE 1 ALLOT +HERE +CONSTANT 2NDA +CONSTANT 1STA +{ 1STA 2NDA U< -> <TRUE> } \ HERE MUST GROW WITH ALLOT +{ 1STA 1+ -> 2NDA } \ ... BY ONE ADDRESS UNIT +( MISSING TEST: NEGATIVE ALLOT ) + +HERE 1 , +HERE 2 , +CONSTANT 2ND +CONSTANT 1ST +{ 1ST 2ND U< -> <TRUE> } \ HERE MUST GROW WITH ALLOT +{ 1ST CELL+ -> 2ND } \ ... BY ONE CELL +{ 1ST 1 CELLS + -> 2ND } +{ 1ST @ 2ND @ -> 1 2 } +{ 5 1ST ! -> } +{ 1ST @ 2ND @ -> 5 2 } +{ 6 2ND ! -> } +{ 1ST @ 2ND @ -> 5 6 } +{ 1ST 2@ -> 6 5 } +{ 2 1 1ST 2! -> } +{ 1ST 2@ -> 2 1 } +{ 1S 1ST ! 1ST @ -> 1S } \ CAN STORE CELL-WIDE VALUE + +HERE 1 C, +HERE 2 C, +CONSTANT 2NDC +CONSTANT 1STC +{ 1STC 2NDC U< -> <TRUE> } \ HERE MUST GROW WITH ALLOT +{ 1STC CHAR+ -> 2NDC } \ ... BY ONE CHAR +{ 1STC 1 CHARS + -> 2NDC } +{ 1STC C@ 2NDC C@ -> 1 2 } +{ 3 1STC C! -> } +{ 1STC C@ 2NDC C@ -> 3 2 } +{ 4 2NDC C! -> } +{ 1STC C@ 2NDC C@ -> 3 4 } + +ALIGN 1 ALLOT HERE ALIGN HERE 3 CELLS ALLOT +CONSTANT A-ADDR CONSTANT UA-ADDR +{ UA-ADDR ALIGNED -> A-ADDR } +{ 1 A-ADDR C! A-ADDR C@ -> 1 } +{ 1234 A-ADDR ! A-ADDR @ -> 1234 } +{ 123 456 A-ADDR 2! A-ADDR 2@ -> 123 456 } +{ 2 A-ADDR CHAR+ C! A-ADDR CHAR+ C@ -> 2 } +{ 3 A-ADDR CELL+ C! A-ADDR CELL+ C@ -> 3 } +{ 1234 A-ADDR CELL+ ! A-ADDR CELL+ @ -> 1234 } +{ 123 456 A-ADDR CELL+ 2! A-ADDR CELL+ 2@ -> 123 456 } + +: BITS ( X -- U ) + 0 SWAP BEGIN DUP WHILE DUP MSB AND IF >R 1+ R> THEN 2* REPEAT DROP ; +( CHARACTERS >= 1 AU, <= SIZE OF CELL, >= 8 BITS ) +{ 1 CHARS 1 < -> <FALSE> } +{ 1 CHARS 1 CELLS > -> <FALSE> } +( TBD: HOW TO FIND NUMBER OF BITS? ) + +( CELLS >= 1 AU, INTEGRAL MULTIPLE OF CHAR SIZE, >= 16 BITS ) +{ 1 CELLS 1 < -> <FALSE> } +{ 1 CELLS 1 CHARS MOD -> 0 } +{ 1S BITS 10 < -> <FALSE> } + +{ 0 1ST ! -> } +{ 1 1ST +! -> } +{ 1ST @ -> 1 } +{ -1 1ST +! 1ST @ -> 0 } + +\ ------------------------------------------------------------------------ +TESTING CHAR [CHAR] [ ] BL S" + +{ BL -> 20 } +{ CHAR X -> 58 } +{ CHAR HELLO -> 48 } +{ : GC1 [CHAR] X ; -> } +{ : GC2 [CHAR] HELLO ; -> } +{ GC1 -> 58 } +{ GC2 -> 48 } +{ : GC3 [ GC1 ] LITERAL ; -> } +{ GC3 -> 58 } +{ : GC4 S" XY" ; -> } +{ GC4 SWAP DROP -> 2 } +{ GC4 DROP DUP C@ SWAP CHAR+ C@ -> 58 59 } + +\ ------------------------------------------------------------------------ +TESTING ' ['] FIND EXECUTE IMMEDIATE COUNT LITERAL POSTPONE STATE + +{ : GT1 123 ; -> } +{ ' GT1 EXECUTE -> 123 } +{ : GT2 ['] GT1 ; IMMEDIATE -> } +{ GT2 EXECUTE -> 123 } +HERE 3 C, CHAR G C, CHAR T C, CHAR 1 C, CONSTANT GT1STRING +HERE 3 C, CHAR G C, CHAR T C, CHAR 2 C, CONSTANT GT2STRING +{ GT1STRING FIND -> ' GT1 -1 } +{ GT2STRING FIND -> ' GT2 1 } +( HOW TO SEARCH FOR NON-EXISTENT WORD? ) +{ : GT3 GT2 LITERAL ; -> } +{ GT3 -> ' GT1 } +{ GT1STRING COUNT -> GT1STRING CHAR+ 3 } + +{ : GT4 POSTPONE GT1 ; IMMEDIATE -> } +{ : GT5 GT4 ; -> } +{ GT5 -> 123 } +{ : GT6 345 ; IMMEDIATE -> } +{ : GT7 POSTPONE GT6 ; -> } +{ GT7 -> 345 } + +{ : GT8 STATE @ ; IMMEDIATE -> } +{ GT8 -> 0 } +{ : GT9 GT8 LITERAL ; -> } +{ GT9 0= -> <FALSE> } + +\ ------------------------------------------------------------------------ +TESTING IF ELSE THEN BEGIN WHILE REPEAT UNTIL RECURSE + +{ : GI1 IF 123 THEN ; -> } +{ : GI2 IF 123 ELSE 234 THEN ; -> } +{ 0 GI1 -> } +{ 1 GI1 -> 123 } +{ -1 GI1 -> 123 } +{ 0 GI2 -> 234 } +{ 1 GI2 -> 123 } +{ -1 GI1 -> 123 } + +{ : GI3 BEGIN DUP 5 < WHILE DUP 1+ REPEAT ; -> } +{ 0 GI3 -> 0 1 2 3 4 5 } +{ 4 GI3 -> 4 5 } +{ 5 GI3 -> 5 } +{ 6 GI3 -> 6 } + +{ : GI4 BEGIN DUP 1+ DUP 5 > UNTIL ; -> } +{ 3 GI4 -> 3 4 5 6 } +{ 5 GI4 -> 5 6 } +{ 6 GI4 -> 6 7 } + +{ : GI5 BEGIN DUP 2 > WHILE DUP 5 < WHILE DUP 1+ REPEAT 123 ELSE 345 THEN ; -> } +{ 1 GI5 -> 1 345 } +{ 2 GI5 -> 2 345 } +{ 3 GI5 -> 3 4 5 123 } +{ 4 GI5 -> 4 5 123 } +{ 5 GI5 -> 5 123 } + +{ : GI6 ( N -- 0,1,..N ) DUP IF DUP >R 1- RECURSE R> THEN ; -> } +{ 0 GI6 -> 0 } +{ 1 GI6 -> 0 1 } +{ 2 GI6 -> 0 1 2 } +{ 3 GI6 -> 0 1 2 3 } +{ 4 GI6 -> 0 1 2 3 4 } + +\ ------------------------------------------------------------------------ +TESTING DO LOOP +LOOP I J UNLOOP LEAVE EXIT + +{ : GD1 DO I LOOP ; -> } +{ 4 1 GD1 -> 1 2 3 } +{ 2 -1 GD1 -> -1 0 1 } +{ MID-UINT+1 MID-UINT GD1 -> MID-UINT } + +{ : GD2 DO I -1 +LOOP ; -> } +{ 1 4 GD2 -> 4 3 2 1 } +{ -1 2 GD2 -> 2 1 0 -1 } +{ MID-UINT MID-UINT+1 GD2 -> MID-UINT+1 MID-UINT } + +{ : GD3 DO 1 0 DO J LOOP LOOP ; -> } +{ 4 1 GD3 -> 1 2 3 } +{ 2 -1 GD3 -> -1 0 1 } +{ MID-UINT+1 MID-UINT GD3 -> MID-UINT } + +{ : GD4 DO 1 0 DO J LOOP -1 +LOOP ; -> } +{ 1 4 GD4 -> 4 3 2 1 } +{ -1 2 GD4 -> 2 1 0 -1 } +{ MID-UINT MID-UINT+1 GD4 -> MID-UINT+1 MID-UINT } + +{ : GD5 123 SWAP 0 DO I 4 > IF DROP 234 LEAVE THEN LOOP ; -> } +{ 1 GD5 -> 123 } +{ 5 GD5 -> 123 } +{ 6 GD5 -> 234 } + +{ : GD6 ( PAT: {0 0},{0 0}{1 0}{1 1},{0 0}{1 0}{1 1}{2 0}{2 1}{2 2} ) + 0 SWAP 0 DO + I 1+ 0 DO I J + 3 = IF I UNLOOP I UNLOOP EXIT THEN 1+ LOOP + LOOP ; -> } +{ 1 GD6 -> 1 } +{ 2 GD6 -> 3 } +{ 3 GD6 -> 4 1 2 } + +\ ------------------------------------------------------------------------ +TESTING DEFINING WORDS: : ; CONSTANT VARIABLE CREATE DOES> >BODY + +{ 123 CONSTANT X123 -> } +{ X123 -> 123 } +{ : EQU CONSTANT ; -> } +{ X123 EQU Y123 -> } +{ Y123 -> 123 } + +{ VARIABLE V1 -> } +{ 123 V1 ! -> } +{ V1 @ -> 123 } + +{ : NOP : POSTPONE ; ; -> } +{ NOP NOP1 NOP NOP2 -> } +{ NOP1 -> } +{ NOP2 -> } + +{ : DOES1 DOES> @ 1 + ; -> } +{ : DOES2 DOES> @ 2 + ; -> } +{ CREATE CR1 -> } +{ CR1 -> HERE } +{ ' CR1 >BODY -> HERE } +{ 1 , -> } +{ CR1 @ -> 1 } +{ DOES1 -> } +{ CR1 -> 2 } +{ DOES2 -> } +{ CR1 -> 3 } + +{ : WEIRD: CREATE DOES> 1 + DOES> 2 + ; -> } +{ WEIRD: W1 -> } +{ ' W1 >BODY -> HERE } +{ W1 -> HERE 1 + } +{ W1 -> HERE 2 + } + +\ ------------------------------------------------------------------------ +TESTING EVALUATE + +: GE1 S" 123" ; IMMEDIATE +: GE2 S" 123 1+" ; IMMEDIATE +: GE3 S" : GE4 345 ;" ; +: GE5 EVALUATE ; IMMEDIATE + +{ GE1 EVALUATE -> 123 } ( TEST EVALUATE IN INTERP. STATE ) +{ GE2 EVALUATE -> 124 } +{ GE3 EVALUATE -> } +{ GE4 -> 345 } + +{ : GE6 GE1 GE5 ; -> } ( TEST EVALUATE IN COMPILE STATE ) +{ GE6 -> 123 } +{ : GE7 GE2 GE5 ; -> } +{ GE7 -> 124 } + +\ ------------------------------------------------------------------------ +TESTING SOURCE >IN WORD + +: GS1 S" SOURCE" 2DUP EVALUATE + >R SWAP >R = R> R> = ; +{ GS1 -> <TRUE> <TRUE> } + +VARIABLE SCANS +: RESCAN? -1 SCANS +! SCANS @ IF 0 >IN ! THEN ; + +{ 2 SCANS ! +345 RESCAN? +-> 345 345 } + +: GS2 5 SCANS ! S" 123 RESCAN?" EVALUATE ; +{ GS2 -> 123 123 123 123 123 } + +: GS3 WORD COUNT SWAP C@ ; +{ BL GS3 HELLO -> 5 CHAR H } +{ CHAR " GS3 GOODBYE" -> 7 CHAR G } +{ BL GS3 +DROP -> 0 } \ BLANK LINE RETURN ZERO-LENGTH STRING + +: GS4 SOURCE >IN ! DROP ; +{ GS4 123 456 +-> } + +\ ------------------------------------------------------------------------ +TESTING <# # #S #> HOLD SIGN BASE >NUMBER HEX DECIMAL + +: S= \ ( ADDR1 C1 ADDR2 C2 -- T/F ) COMPARE TWO STRINGS. + >R SWAP R@ = IF \ MAKE SURE STRINGS HAVE SAME LENGTH + R> ?DUP IF \ IF NON-EMPTY STRINGS + 0 DO + OVER C@ OVER C@ - IF 2DROP <FALSE> UNLOOP EXIT THEN + SWAP CHAR+ SWAP CHAR+ + LOOP + THEN + 2DROP <TRUE> \ IF WE GET HERE, STRINGS MATCH + ELSE + R> DROP 2DROP <FALSE> \ LENGTHS MISMATCH + THEN ; + +: GP1 <# 41 HOLD 42 HOLD 0 0 #> S" BA" S= ; +{ GP1 -> <TRUE> } + +: GP2 <# -1 SIGN 0 SIGN -1 SIGN 0 0 #> S" --" S= ; +{ GP2 -> <TRUE> } + +: GP3 <# 1 0 # # #> S" 01" S= ; +{ GP3 -> <TRUE> } + +: GP4 <# 1 0 #S #> S" 1" S= ; +{ GP4 -> <TRUE> } + +24 CONSTANT MAX-BASE \ BASE 2 .. 36 +: COUNT-BITS + 0 0 INVERT BEGIN DUP WHILE >R 1+ R> 2* REPEAT DROP ; +COUNT-BITS 2* CONSTANT #BITS-UD \ NUMBER OF BITS IN UD + +: GP5 + BASE @ <TRUE> + MAX-BASE 1+ 2 DO \ FOR EACH POSSIBLE BASE + I BASE ! \ TBD: ASSUMES BASE WORKS + I 0 <# #S #> S" 10" S= AND + LOOP + SWAP BASE ! ; +{ GP5 -> <TRUE> } + +: GP6 + BASE @ >R 2 BASE ! + MAX-UINT MAX-UINT <# #S #> \ MAXIMUM UD TO BINARY + R> BASE ! \ S: C-ADDR U + DUP #BITS-UD = SWAP + 0 DO \ S: C-ADDR FLAG + OVER C@ [CHAR] 1 = AND \ ALL ONES + >R CHAR+ R> + LOOP SWAP DROP ; +{ GP6 -> <TRUE> } + +: GP7 + BASE @ >R MAX-BASE BASE ! + <TRUE> + A 0 DO + I 0 <# #S #> + 1 = SWAP C@ I 30 + = AND AND + LOOP + MAX-BASE A DO + I 0 <# #S #> + 1 = SWAP C@ 41 I A - + = AND AND + LOOP + R> BASE ! ; + +{ GP7 -> <TRUE> } + +\ >NUMBER TESTS +CREATE GN-BUF 0 C, +: GN-STRING GN-BUF 1 ; +: GN-CONSUMED GN-BUF CHAR+ 0 ; +: GN' [CHAR] ' WORD CHAR+ C@ GN-BUF C! GN-STRING ; + +{ 0 0 GN' 0' >NUMBER -> 0 0 GN-CONSUMED } +{ 0 0 GN' 1' >NUMBER -> 1 0 GN-CONSUMED } +{ 1 0 GN' 1' >NUMBER -> BASE @ 1+ 0 GN-CONSUMED } +{ 0 0 GN' -' >NUMBER -> 0 0 GN-STRING } \ SHOULD FAIL TO CONVERT THESE +{ 0 0 GN' +' >NUMBER -> 0 0 GN-STRING } +{ 0 0 GN' .' >NUMBER -> 0 0 GN-STRING } + +: >NUMBER-BASED + BASE @ >R BASE ! >NUMBER R> BASE ! ; + +{ 0 0 GN' 2' 10 >NUMBER-BASED -> 2 0 GN-CONSUMED } +{ 0 0 GN' 2' 2 >NUMBER-BASED -> 0 0 GN-STRING } +{ 0 0 GN' F' 10 >NUMBER-BASED -> F 0 GN-CONSUMED } +{ 0 0 GN' G' 10 >NUMBER-BASED -> 0 0 GN-STRING } +{ 0 0 GN' G' MAX-BASE >NUMBER-BASED -> 10 0 GN-CONSUMED } +{ 0 0 GN' Z' MAX-BASE >NUMBER-BASED -> 23 0 GN-CONSUMED } + +: GN1 \ ( UD BASE -- UD' LEN ) UD SHOULD EQUAL UD' AND LEN SHOULD BE ZERO. + BASE @ >R BASE ! + <# #S #> + 0 0 2SWAP >NUMBER SWAP DROP \ RETURN LENGTH ONLY + R> BASE ! ; +{ 0 0 2 GN1 -> 0 0 0 } +{ MAX-UINT 0 2 GN1 -> MAX-UINT 0 0 } +{ MAX-UINT DUP 2 GN1 -> MAX-UINT DUP 0 } +{ 0 0 MAX-BASE GN1 -> 0 0 0 } +{ MAX-UINT 0 MAX-BASE GN1 -> MAX-UINT 0 0 } +{ MAX-UINT DUP MAX-BASE GN1 -> MAX-UINT DUP 0 } + +: GN2 \ ( -- 16 10 ) + BASE @ >R HEX BASE @ DECIMAL BASE @ R> BASE ! ; +{ GN2 -> 10 A } + +\ ------------------------------------------------------------------------ +TESTING FILL MOVE + +CREATE FBUF 00 C, 00 C, 00 C, +CREATE SBUF 12 C, 34 C, 56 C, +: SEEBUF FBUF C@ FBUF CHAR+ C@ FBUF CHAR+ CHAR+ C@ ; + +{ FBUF 0 20 FILL -> } +{ SEEBUF -> 00 00 00 } + +{ FBUF 1 20 FILL -> } +{ SEEBUF -> 20 00 00 } + +{ FBUF 3 20 FILL -> } +{ SEEBUF -> 20 20 20 } + +{ FBUF FBUF 3 CHARS MOVE -> } \ BIZARRE SPECIAL CASE +{ SEEBUF -> 20 20 20 } + +{ SBUF FBUF 0 CHARS MOVE -> } +{ SEEBUF -> 20 20 20 } + +{ SBUF FBUF 1 CHARS MOVE -> } +{ SEEBUF -> 12 20 20 } + +{ SBUF FBUF 3 CHARS MOVE -> } +{ SEEBUF -> 12 34 56 } + +{ FBUF FBUF CHAR+ 2 CHARS MOVE -> } +{ SEEBUF -> 12 12 34 } + +{ FBUF CHAR+ FBUF 2 CHARS MOVE -> } +{ SEEBUF -> 12 34 34 } + +\ ------------------------------------------------------------------------ +TESTING OUTPUT: . ." CR EMIT SPACE SPACES TYPE U. + +: OUTPUT-TEST + ." YOU SHOULD SEE THE STANDARD GRAPHIC CHARACTERS:" CR + 41 BL DO I EMIT LOOP CR + 61 41 DO I EMIT LOOP CR + 7F 61 DO I EMIT LOOP CR + ." YOU SHOULD SEE 0-9 SEPARATED BY A SPACE:" CR + 9 1+ 0 DO I . LOOP CR + ." YOU SHOULD SEE 0-9 (WITH NO SPACES):" CR + [CHAR] 9 1+ [CHAR] 0 DO I 0 SPACES EMIT LOOP CR + ." YOU SHOULD SEE A-G SEPARATED BY A SPACE:" CR + [CHAR] G 1+ [CHAR] A DO I EMIT SPACE LOOP CR + ." YOU SHOULD SEE 0-5 SEPARATED BY TWO SPACES:" CR + 5 1+ 0 DO I [CHAR] 0 + EMIT 2 SPACES LOOP CR + ." YOU SHOULD SEE TWO SEPARATE LINES:" CR + S" LINE 1" TYPE CR S" LINE 2" TYPE CR + ." YOU SHOULD SEE THE NUMBER RANGES OF SIGNED AND UNSIGNED NUMBERS:" CR + ." SIGNED: " MIN-INT . MAX-INT . CR + ." UNSIGNED: " 0 U. MAX-UINT U. CR +; + +{ OUTPUT-TEST -> } + +\ ------------------------------------------------------------------------ +TESTING INPUT: ACCEPT + +CREATE ABUF 80 CHARS ALLOT + +: ACCEPT-TEST + CR ." PLEASE TYPE UP TO 80 CHARACTERS:" CR + ABUF 80 ACCEPT + CR ." RECEIVED: " [CHAR] " EMIT + ABUF SWAP TYPE [CHAR] " EMIT CR +; + +{ ACCEPT-TEST -> } + +\ ------------------------------------------------------------------------ +TESTING DICTIONARY SEARCH RULES + +{ : GDX 123 ; : GDX GDX 234 ; -> } + +{ GDX -> 123 234 } + + +\ test suite finished. leaving engine. + +bye diff --git a/qemu/roms/openbios/forth/bootstrap/interpreter.fs b/qemu/roms/openbios/forth/bootstrap/interpreter.fs new file mode 100644 index 000000000..51870581f --- /dev/null +++ b/qemu/roms/openbios/forth/bootstrap/interpreter.fs @@ -0,0 +1,175 @@ +\ tag: forth interpreter +\ +\ Copyright (C) 2003 Stefan Reinauer +\ +\ See the file "COPYING" for further information about +\ the copyright and warranty status of this work. +\ + + +\ +\ 7.3.4.6 Display pause +\ + +0 value interactive? +0 value terminate? + +: exit? + interactive? 0= if + false exit + then + false \ FIXME we should check whether to interrupt output + \ and ask the user how to proceed. + ; + + +\ +\ 7.3.9.1 Defining words +\ + +: forget + s" This word is obsolescent." type cr + ['] ' execute + cell - dup + @ dup + last ! latest ! + here! + ; + +\ +\ 7.3.9.2.4 Miscellaneous dictionary +\ + +\ interpreter. This word checks whether the interpreted word +\ is a word in dictionary or a number. It honours compile mode +\ and immediate/compile-only words. + +: interpret + 0 >in ! + begin + parse-word dup 0> \ was there a word at all? + while + $find + if + dup flags? 0<> state @ 0= or if + execute + else + , \ compile mode && !immediate + then + else \ word is not known. maybe it's a number + 2dup $number + if + span @ >in ! \ if we encountered an error, don't continue parsing + type 3a emit + -13 throw + else + -rot 2drop 1 handle-lit + then + then + depth 200 >= if -3 throw then + depth 0< if -4 throw then + rdepth 200 >= if -5 throw then + rdepth 0< if -6 throw then + repeat + 2drop + ; + +: refill ( -- ) + ib #ib @ expect 0 >in ! ; + +: print-status ( exception -- ) + space + ?dup if + dup sys-debug \ system debug hook + case + -1 of s" Aborted." type endof + -2 of s" Aborted." type endof + -3 of s" Stack Overflow." type 0 depth! endof + -4 of s" Stack Underflow." type 0 depth! endof + -5 of s" Return Stack Overflow." type endof + -6 of s" Return Stack Underflow." type endof + -13 of s" undefined word." type endof + -15 of s" out of memory." type endof + -21 of s" undefined method." type endof + -22 of s" no such device." type endof + dup s" Exception #" type . + 0 state ! + endcase + else + state @ 0= if + s" ok" + else + s" compiled" + then + type + then + cr + ; + +defer status +['] noop ['] status (to) + +: print-prompt + status + depth . 3e emit space + ; + +defer outer-interpreter +:noname + cr + begin + print-prompt + source 0 fill \ clean input buffer + refill + + ['] interpret catch print-status + terminate? + until +; ['] outer-interpreter (to) + +\ +\ 7.3.8.5 Other control flow commands +\ + +: save-source ( -- ) + r> \ fetch our caller + ib >r #ib @ >r \ save current input buffer + source-id >r \ and all variables + span @ >r \ associated with it. + >in @ >r + >r \ move back our caller + ; + +: restore-source ( -- ) + r> + r> >in ! + r> span ! + r> ['] source-id (to) + r> #ib ! + r> ['] ib (to) + >r + ; + +: (evaluate) ( str len -- ??? ) + save-source + -1 ['] source-id (to) + dup + #ib ! span ! + ['] ib (to) + interpret + restore-source + ; + +: evaluate ( str len -- ?? ) + 2dup + -rot + over + over do + i c@ 0a = if + i over - + (evaluate) + i 1+ + then + loop + swap over - (evaluate) + ; + +: eval evaluate ; diff --git a/qemu/roms/openbios/forth/bootstrap/memory.fs b/qemu/roms/openbios/forth/bootstrap/memory.fs new file mode 100644 index 000000000..6fa4a2cc7 --- /dev/null +++ b/qemu/roms/openbios/forth/bootstrap/memory.fs @@ -0,0 +1,216 @@ +\ tag: forth memory allocation +\ +\ Copyright (C) 2002-2003 Stefan Reinauer +\ +\ See the file "COPYING" for further information about +\ the copyright and warranty status of this work. +\ + +\ 7.3.3.2 memory allocation + +\ these need to be initialized by the forth kernel by now. +variable start-mem 0 start-mem ! \ start of memory +variable end-mem 0 end-mem ! \ end of memory +variable free-list 0 free-list ! \ free list head + +\ initialize necessary variables and write a valid +\ free-list entry containing all of the memory. +\ start-mem: pointer to start of memory. +\ end-mem: pointer to end of memory. +\ free-list: head of linked free list + +: init-mem ( start-addr size ) + over dup + start-mem ! \ write start-mem + free-list ! \ write first freelist entry + 2dup /n - swap ! \ write 'len' entry + over cell+ 0 swap ! \ write 'next' entry + + end-mem ! \ write end-mem + ; + +\ -------------------------------------------------------------------- + +\ return pointer to smallest free block that contains +\ at least nb bytes and the block previous the the +\ actual block. On failure the pointer to the smallest +\ free block is 0. + +: smallest-free-block ( nb -- prev ptr | 0 0 ) + 0 free-list @ + fffffff 0 0 >r >r >r + begin + dup + while + ( nb prev pp R: best_nb best_pp ) + dup @ 3 pick r@ within if + ( nb prev pp ) + r> r> r> 3drop \ drop old smallest + 2dup >r >r dup @ >r \ new smallest + then + nip dup \ prev = pp + cell + @ \ pp = pp->next + repeat + 3drop r> drop r> r> +; + + +\ -------------------------------------------------------------------- + +\ allocate size bytes of memory +\ return pointer to memory (or throws an exception on failure). + +: alloc-mem ( size -- addr ) + + \ make it legal (and fast) to allocate 0 bytes + dup 0= if exit then + + aligned \ keep memory aligned. + dup smallest-free-block \ look up smallest free block. + + dup 0= if + \ 2drop + -15 throw \ out of memory + then + + ( al-size prev addr ) + + \ If the smallest fitting block found is bigger than + \ the size of the requested block plus 2*cellsize we + \ can split the block in 2 parts. otherwise return a + \ slightly bigger block than requested. + + dup @ ( d->len ) 3 pick cell+ cell+ > if + + \ splitting the block in 2 pieces. + \ new block = old block + len field + size of requested mem + dup 3 pick cell+ + ( al-size prev addr nd ) + + \ new block len = old block len - req. mem size - 1 cell + over @ ( al-size prev addr nd addr->len ) + 4 pick ( ... al-size ) + cell+ - ( al-size prev addr nd nd nd->len ) + over ! ( al-size prev addr nd ) + + over cell+ @ ( al-size prev addr nd addr->next ) + \ write addr->next to nd->next + over cell+ ! ( al-size prev addr nd ) + over 4 pick swap ! + else + \ don't split the block, it's too small. + dup cell+ @ + then + + ( al-size prev addr nd ) + + \ If the free block we got is the first one rewrite free-list + \ pointer instead of the previous entry's next field. + rot dup 0= if drop free-list else cell+ then + ( al-size addr nd prev->next|fl ) + ! + nip cell+ \ remove al-size and skip len field of returned pointer + + ; + + +\ -------------------------------------------------------------------- + +\ free block given by addr. The length of the +\ given block is stored at addr - cellsize. +\ +\ merge with blocks to the left and right +\ immediately, if they are free. + +: free-mem ( addr len -- ) + + \ we define that it is legal to free 0-byte areas + 0= if drop exit then + ( addr ) + + \ check if the address to free is somewhere within + \ our available memory. This fails badly on discontigmem + \ architectures. If we need more RAM than fits on one + \ contiguous memory area we are too bloated anyways. ;) + + dup start-mem @ end-mem @ within 0= if + \ ." free-mem: no such memory: 0x" u. cr + exit + then + + /n - \ get real block address + 0 free-list @ ( addr prev l ) + + begin \ now scan the free list + dup 0<> if \ only check len, if block ptr != 0 + dup dup @ cell+ + 3 pick < + else + false + then + while + nip dup \ prev=l + cell+ @ \ l=l->next + repeat + + ( addr prev l ) + + dup 0<> if \ do we have free memory to merge with? + + dup dup @ cell+ + 3 pick = if \ hole hit. adding bytes. + \ freeaddr = end of current block -> merge + ( addr prev l ) + rot @ cell+ ( prev l f->len+cellsize ) + over @ + \ add l->len + over ! ( prev l ) + swap over cell+ @ \ f = l; l = l->next; + + \ The free list is sorted by addresses. When merging at the + \ start of our block we might also want to merge at the end + \ of it. Therefore we fall through to the next border check + \ instead of returning. + true \ fallthrough value + else + false \ no fallthrough + then + >r \ store fallthrough on ret stack + + ( addr prev l ) + + dup 3 pick dup @ cell+ + = if \ hole hit. real merging. + \ current block starts where block to free ends. + \ end of free block addr = current block -> merge and exit + ( addr prev l ) + 2 pick dup @ ( f f->len ) + 2 pick @ cell+ + ( f newlen ) + swap ! ( addr prev l ) + 3dup drop + 0= if + free-list + else + 2 pick cell+ + then ( value prev->next|free-list ) + ! ( addr prev l ) + cell+ @ rot ( prev l->next addr ) + cell+ ! drop + r> drop exit \ clean up return stack + then + + r> if 3drop exit then \ fallthrough? -> exit + then + + \ loose block - hang it before current. + + ( addr prev l ) + + \ hang block to free in front of the current entry. + dup 3 pick cell+ ! \ f->next = l; + free-list @ = if \ is block to free new list head? + over free-list ! + then + + ( addr prev ) + dup 0<> if \ if (prev) prev->next=f + cell+ ! + else + 2drop \ no fixup needed. clean up. + then + + ; diff --git a/qemu/roms/openbios/forth/bootstrap/start.fs b/qemu/roms/openbios/forth/bootstrap/start.fs new file mode 100644 index 000000000..9aabfa2c4 --- /dev/null +++ b/qemu/roms/openbios/forth/bootstrap/start.fs @@ -0,0 +1,69 @@ +\ tag: forth bootstrap starter. +\ +\ Copyright (C) 2003 Patrick Mauritz, Stefan Reinauer +\ +\ See the file "COPYING" for further information about +\ the copyright and warranty status of this work. +\ + +include bootstrap.fs \ all base words +include interpreter.fs \ interpreter +include builtin.fs \ builtin terminal. + +: include ( >filename<eol> -- ) + linefeed parse $include +; + +: encode-file ( >filename< > -- dictptr size ) + parse-word $encode-file +; + +: bye + s" Farewell!" cr type cr cr + 0 rdepth! + ; + +\ quit starts the outer interpreter of the forth system. +\ zech describes quit as being the outer interpreter, but +\ we split it apart to keep the interpreter elsewhere. + +: quit ( -- ) + 2 rdepth! + outer-interpreter +; + +\ initialize is the first forth word run by the kernel. +\ this word is automatically executed by the C core on start +\ and it's never left unless something goes really wrong or +\ the user decides to leave the engine. + +variable init-chain + +\ :noname <definition> ; initializer +: initializer ( xt -- ) + here swap , 0 , \ xt, next + init-chain + begin dup @ while @ na1+ repeat + ! +; + +: initialize-forth ( startmem endmem -- ) + over - init-mem + init-pockets + init-tmp-comp + init-builtin-terminal + + init-chain @ \ execute initializers + begin dup while + dup @ execute + na1+ @ + repeat + drop +; + +\ compiler entrypoint +: initialize ( startmem endmem -- ) + initialize-forth + s" OpenBIOS kernel started." type cr + quit +; diff --git a/qemu/roms/openbios/forth/build.xml b/qemu/roms/openbios/forth/build.xml new file mode 100644 index 000000000..0d699c935 --- /dev/null +++ b/qemu/roms/openbios/forth/build.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" ?> + +<build> + <!-- don't change this order --> + <include href="bootstrap/build.xml"/> + <include href="lib/build.xml"/> + <include href="device/build.xml"/> + <include href="debugging/build.xml"/> + <include href="admin/build.xml"/> + <include href="util/build.xml"/> + <include href="packages/build.xml"/> + <include href="system/build.xml"/> +</build> diff --git a/qemu/roms/openbios/forth/debugging/build.xml b/qemu/roms/openbios/forth/debugging/build.xml new file mode 100644 index 000000000..3b9a0ca44 --- /dev/null +++ b/qemu/roms/openbios/forth/debugging/build.xml @@ -0,0 +1,18 @@ +<build> + + <!-- + build description for forth debugging command group + + Copyright (C) 2004-2005 by Stefan Reinauer + See the file "COPYING" for further information about + the copyright and warranty status of this work. + --> + + <dictionary name="openbios" target="forth"> + <object source="client.fs"/> + <object source="fcode.fs"/> + <object source="firmware.fs"/> + <object source="see.fs"/> + </dictionary> + +</build> diff --git a/qemu/roms/openbios/forth/debugging/client.fs b/qemu/roms/openbios/forth/debugging/client.fs new file mode 100644 index 000000000..f37440445 --- /dev/null +++ b/qemu/roms/openbios/forth/debugging/client.fs @@ -0,0 +1,299 @@ +\ 7.6 Client Program Debugging command group + + +\ 7.6.1 Registers display + +: ctrace ( -- ) + ; + +: .registers ( -- ) + ; + +: .fregisters ( -- ) + ; + +\ to ( param [old-name< >] -- ) + + +\ 7.6.2 Program download and execute + +struct ( saved-program-state ) + /n field >sps.entry + /n field >sps.file-size + /n field >sps.file-type +constant saved-program-state.size +create saved-program-state saved-program-state.size allot + +variable state-valid +0 state-valid ! + +variable file-size + +: !load-size file-size ! ; + +: load-size file-size @ ; + + +\ File types identified by (init-program) + +0 constant elf-boot +1 constant elf +2 constant bootinfo +3 constant xcoff +4 constant pe +5 constant aout +10 constant fcode +11 constant forth +12 constant bootcode + + +: init-program ( -- ) + \ Call down to the lower level for relocation etc. + s" (init-program)" $find if + execute + else + s" Unable to locate (init-program)!" type cr + then + ; + +: (find-bootdevice) ( param-str param-len -- bootpath-str bootpath-len) + \ Parse the <param> string which is a space-separated list of one or + \ more potential boot devices, and return the first one that can be + \ successfully opened. + + \ Space-separated bootpath string + bl left-split \ bootpathstr bootpathstr-len bootdevstr bootdevstr-len + dup 0= if + + \ None specified. As per IEEE-1275 specification, search through each value + \ in boot-device and use the first that returns a valid ihandle on open. + + 2drop \ drop the empty device string as we're going to use our own + + s" boot-device" $find drop execute + bl left-split + begin + dup + while + 2dup s" Trying " type type s" ..." type cr + 2dup open-dev ?dup if + close-dev + 2swap drop 0 \ Fake end of string so we exit loop + else + 2drop + bl left-split + then + repeat + 2drop + then + + \ bootargs + 2swap dup 0= if + \ None specified, use default from nvram + 2drop s" boot-file" $find drop execute + then + + \ Set the bootargs property + encode-string + " /chosen" (find-dev) if + " bootargs" rot (property) + then +; + +\ Locate the boot-device opened by this ihandle (currently taken as being +\ the first non-interposed package in the instance chain) + +: ihandle>boot-device-handle ( ihandle -- 0 | device-ihandle -1 ) + >r 0 + begin r> dup >in.my-parent @ dup >r while + ( result ihandle R: ihandle.parent ) + dup >in.interposed @ 0= if + \ Find the first non-interposed package + over 0= if + swap drop + else + drop + then + else + drop + then + repeat + r> drop drop + + dup 0<> if + -1 + then +; + +: $load ( devstr len ) + open-dev ( ihandle ) + dup 0= if + drop + exit + then + dup >r + " load-base" evaluate swap ( load-base ihandle ) + dup ihandle>phandle " load" rot find-method ( xt 0|1 ) + if swap call-package !load-size else cr ." Cannot find load for this package" 2drop then + + \ If the boot device path doesn't contain an explicit partition id, e.g. cd:,\\:tbxi + \ then the interposed partition package may have auto-probed a suitable partition. If + \ this is the case then it will have set the " selected-partition-args" property in + \ the partition package to contain the new device arguments. + \ + \ In order to ensure that bootpath contains the partition argument, we use the contents + \ of this property if it exists to override the boot device arguments when generating + \ the full bootpath using get-instance-path. + + my-self + r@ to my-self + " selected-partition-args" get-inherited-property 0= if + decode-string 2swap 2drop + ( myself-save partargs-str partargs-len ) + r@ ihandle>boot-device-handle if + ( myself-save partargs-str partargs-len block-ihandle ) + \ Override the arguments before get-instance-path + dup >in.arguments 2@ >r >r dup >r ( R: block-ihandle arg-len arg-str ) + >in.arguments 2! ( myself-save ) + r@ " get-instance-path" $find if + execute ( myself-save bootpathstr bootpathlen ) + then + \ Now write the original arguments back + r> r> r> rot >in.arguments 2! ( myself-save bootpathstr bootpathlen R: ) + rot ( bootpathstr bootpathlen myself-save ) + then + else + my-self " get-instance-path" $find if + execute ( myself-save bootpathstr pathlen ) + rot ( bootpathstr bootpathlen myself-save ) + then + then + to my-self + + \ Set bootpath property in /chosen + encode-string " /chosen" (find-dev) if + " bootpath" rot (property) + then + + r> close-dev + init-program + ; + +: load ( "{params}<cr>" -- ) + linefeed parse + (find-bootdevice) + $load +; + +: dir ( "{paths}<cr>" -- ) + linefeed parse + ascii , split-after + 2dup open-dev dup 0= if + drop + cr ." Unable to locate device " type + 2drop + exit + then + -rot 2drop -rot 2 pick + " dir" rot ['] $call-method catch + if + 3drop + cr ." Cannot find dir for this package" + then + close-dev +; + +: go ( -- ) + state-valid @ not if + s" No valid state has been set by load or init-program" type cr + exit + then + + \ Call the architecture-specific code to launch the client image + s" (go)" $find if + execute + else + ." go is not yet implemented" + 2drop + then + ; + + +\ 7.6.3 Abort and resume + +\ already defined !? +\ : go ( -- ) +\ ; + + +\ 7.6.4 Disassembler + +: dis ( addr -- ) + ; + +: +dis ( -- ) + ; + +\ 7.6.5 Breakpoints +: .bp ( -- ) + ; + +: +bp ( addr -- ) + ; + +: -bp ( addr -- ) + ; + +: --bp ( -- ) + ; + +: bpoff ( -- ) + ; + +: step ( -- ) + ; + +: steps ( n -- ) + ; + +: hop ( -- ) + ; + +: hops ( n -- ) + ; + +\ already defined +\ : go ( -- ) +\ ; + +: gos ( n -- ) + ; + +: till ( addr -- ) + ; + +: return ( -- ) + ; + +: .breakpoint ( -- ) + ; + +: .step ( -- ) + ; + +: .instruction ( -- ) + ; + + +\ 7.6.6 Symbolic debugging +: .adr ( addr -- ) + ; + +: sym ( "name< >" -- n ) + ; + +: sym>value ( addr len -- addr len false | n true ) + ; + +: value>sym ( n1 -- n1 false | n2 addr len true ) + ; diff --git a/qemu/roms/openbios/forth/debugging/fcode.fs b/qemu/roms/openbios/forth/debugging/fcode.fs new file mode 100644 index 000000000..76099558d --- /dev/null +++ b/qemu/roms/openbios/forth/debugging/fcode.fs @@ -0,0 +1,14 @@ +\ 7.7 FCode Debugging command group + +\ The user interface versions of these FCode functions allow +\ the user to debug FCode programs by providing named commands +\ corresponding to FCode functions. + +: headerless ( -- ) + ; + +: headers ( -- ) + ; + +: apply ( ... "method-name< >device-specifier< >" -- ??? ) + ; diff --git a/qemu/roms/openbios/forth/debugging/firmware.fs b/qemu/roms/openbios/forth/debugging/firmware.fs new file mode 100644 index 000000000..5e16a6c57 --- /dev/null +++ b/qemu/roms/openbios/forth/debugging/firmware.fs @@ -0,0 +1,90 @@ +\ 7.5 Firmware Debugging command group + + +\ 7.5.1 Automatic stack display + +: (.s + depth 0 ?do + depth i - 1- pick . + loop + depth 0<> if ascii < emit space then + ; + +: showstack ( -- ) + ['] (.s to status + ; + +: noshowstack ( -- ) + ['] noop to status + ; + +\ 7.5.2 Serial download + +: dl ( -- ) + ; + + +\ 7.5.3 Dictionary + +\ 7.5.3.1 Dictionary search +: .calls ( xt -- ) + ; + +: $sift ( text-addr text-len -- ) + ; + +: sifting ( "text< >" -- ) + ; + +\ : words ( -- ) +\ \ Implemented in forth bootstrap. +\ ; + + +\ 7.5.3.2 Decompiler + +\ implemented in see.fs + +\ : see ( "old-name< >" -- ) +\ ; + +\ : (see) ( xt -- ) +\ ; + + +\ 7.5.3.3 Patch + +: patch ( "new-name< >old-name< >word-to-patch< >" -- ) + ; + +: (patch) ( new-n1 num1? old-n2 num2? xt -- ) + ; + + +\ 7.5.3.4 Forth source-level debugger + +: debug ( "old-name< >" -- ) + parse-word \ Look up word CFA in dictionary + $find + 0 = if + ." could not locate word for debugging" + 2drop + else + (debug + then + ; + +: stepping ( -- ) + ; + +: tracing ( -- ) + ; + +: debug-off ( -- ) + (debug-off) + ; + +: resume ( -- ) + \ Set interpreter termination flag + 1 to terminate? + ; diff --git a/qemu/roms/openbios/forth/debugging/see.fs b/qemu/roms/openbios/forth/debugging/see.fs new file mode 100644 index 000000000..6977d29eb --- /dev/null +++ b/qemu/roms/openbios/forth/debugging/see.fs @@ -0,0 +1,114 @@ +\ tag: Forth Decompiler +\ +\ this code implements IEEE 1275-1994 ch. 7.5.3.2 +\ +\ Copyright (C) 2003 Stefan Reinauer +\ +\ See the file "COPYING" for further information about +\ the copyright and warranty status of this work. +\ + +1 value (see-indent) + +: (see-cr) + cr (see-indent) spaces + ; + +: indent+ + (see-indent) 2+ to (see-indent) + ; + +: indent- + (see-indent) 2- to (see-indent) + ; + +: (see-colon) + dup ." : " cell - lfa2name type (see-cr) + begin + cell+ dup @ dup ['] (semis) <> + while + space + dup + case + + ['] do?branch of + ." if" (see-cr) indent+ + drop cell+ + endof + + ['] dobranch of + ." then" indent- (see-cr) + drop cell+ + endof + + ['] (begin) of + ." begin" indent+ (see-cr) + drop + endof + + ['] (again) of + ." again" (see-cr) + drop + endof + + ['] (until) of + ." until" (see-cr) + drop + endof + + ['] (while) of + indent- (see-cr) + ." while" + indent+ (see-cr) + drop 2 cells + + endof + + ['] (repeat) of + indent- (see-cr) + ." repeat" + (see-cr) + drop 2 cells + + endof + + ['] (lit) of + ." ( lit ) h# " + drop 1 cells + + dup @ u. + endof + + ['] (") of + 22 emit space drop dup cell+ @ + 2dup swap 2 cells + swap type + 22 emit + + aligned cell+ + endof + + cell - lfa2name type + endcase + repeat + cr ." ;" + 2drop + ; + +: (see) ( xt -- ) + cr + dup @ case + 1 of + (see-colon) + endof + 3 of + ." constant " dup cell - lfa2name type ." = " execute . + endof + 4 of + ." variable " dup cell - lfa2name type ." = " execute @ . + endof + 5 of + ." defer " dup cell - lfa2name type cr + ." is " cell+ @ cell - lfa2name type cr + endof + ." primword " swap cell - lfa2name type + endcase + cr + ; + +: see ' (see) ; diff --git a/qemu/roms/openbios/forth/device/README.device b/qemu/roms/openbios/forth/device/README.device new file mode 100644 index 000000000..0d4d6e58d --- /dev/null +++ b/qemu/roms/openbios/forth/device/README.device @@ -0,0 +1,22 @@ +The code you find here implements the IEEE 1275-1994 Open Firmware +device interface. + +Chapter File Comment +<none> structures.fs generic structures used by 5.3 +5.3.2 <none> defined in user interface +5.3.3 fcode.fs complete, partly untested +5.3.4 package.fs incomplete +5.3.5 property.fs incomplete +5.3.6 display.fs incomplete +5.3.7 other.fs incomplete + +H2 and +5.3.1.1.1 preof.fs pre-IEEE-1275-1994 words + split.fs + pathres.fs path resolution + + table.fs fcode evaluator + feval.fs (byte-load) + + +2003/11/12 Stefan Reinauer <stepan@openbios.org> diff --git a/qemu/roms/openbios/forth/device/build.xml b/qemu/roms/openbios/forth/device/build.xml new file mode 100644 index 000000000..11544964a --- /dev/null +++ b/qemu/roms/openbios/forth/device/build.xml @@ -0,0 +1,31 @@ +<build> + + <!-- + build description for open firmware device interface + + Copyright (C) 2004-2005 by Stefan Reinauer + See the file "COPYING" for further information about + the copyright and warranty status of this work. + --> + + <dictionary name="openbios" target="forth"> + <object source="structures.fs"/> + <object source="fcode.fs"/> + <object source="property.fs"/> + <object source="device.fs"/> + <object source="package.fs"/> + <object source="other.fs"/> + <object source="pathres.fs"/> + <object source="preof.fs"/> + <object source="font.fs"/> + <object source="logo.fs"/> + <object source="display.fs"/> + <object source="terminal.fs"/> + <object source="extra.fs"/> + <object source="feval.fs"/> + <object source="table.fs"/> + <object source="tree.fs"/> + <object source="builtin.fs"/> + </dictionary> + +</build> diff --git a/qemu/roms/openbios/forth/device/builtin.fs b/qemu/roms/openbios/forth/device/builtin.fs new file mode 100644 index 000000000..aaefba87b --- /dev/null +++ b/qemu/roms/openbios/forth/device/builtin.fs @@ -0,0 +1,30 @@ +\ tag: builtin devices +\ +\ this code implements IEEE 1275-1994 +\ +\ Copyright (C) 2003 Stefan Reinauer +\ +\ See the file "COPYING" for further information about +\ the copyright and warranty status of this work. +\ + +\ nodes it's children: + +" /" find-device + +new-device + " builtin" device-name + : open true ; + : close ; + +new-device + " console" device-name + : open true ; + : close ; + : write dup >r bounds ?do i c@ (emit) loop r> ; + : read dup >r bounds ?do (key) i c! loop r> ; +finish-device + +\ clean up afterwards +finish-device +0 active-package! diff --git a/qemu/roms/openbios/forth/device/device.fs b/qemu/roms/openbios/forth/device/device.fs new file mode 100644 index 000000000..562c9196e --- /dev/null +++ b/qemu/roms/openbios/forth/device/device.fs @@ -0,0 +1,202 @@ +\ tag: Package creation and deletion +\ +\ this code implements IEEE 1275-1994 +\ +\ Copyright (C) 2003, 2004 Samuel Rydh +\ +\ See the file "COPYING" for further information about +\ the copyright and warranty status of this work. +\ + +variable device-tree + +\ make defined words globally visible +\ +: external ( -- ) + active-package ?dup if + >dn.methods @ set-current + then +; + +\ make the private wordlist active (not an OF word) +\ +: private ( -- ) + active-package ?dup if + >r + forth-wordlist r@ >dn.methods @ r@ >dn.priv-methods @ 3 set-order + r> >dn.priv-methods @ set-current + then +; + +\ set activate package and make the world visible package wordlist +\ the current one. +\ +: active-package! ( phandle -- ) + dup to active-package + \ locally defined words are not available + ?dup if + forth-wordlist over >dn.methods @ 2 set-order + >dn.methods @ set-current + else + forth-wordlist dup 1 set-order set-current + then +; + + +\ new-device ( -- ) +\ +\ Start new package, as child of active package. +\ Create a new device node as a child of the active package and make the +\ new node the active package. Create a new instance and make it the current +\ instance; the instance that invoked new-device becomes the parent instance +\ of the new instance. +\ Subsequently, newly defined Forth words become the methods of the new node +\ and newly defined data items (such as types variable, value, buffer:, and +\ defer) are allocated and stored within the new instance. + +: new-device ( -- ) + align-tree dev-node.size alloc-tree >r + active-package + dup r@ >dn.parent ! + + \ ( parent ) hook up at the end of the peer list + ?dup if + >dn.child + begin dup @ while @ >dn.peer repeat + r@ swap ! + else + \ we are the root node! + r@ to device-tree + then + + \ ( -- ) fill in device node stuff + inst-node.size r@ >dn.isize ! + + \ create two wordlists + wordlist r@ >dn.methods ! + wordlist r@ >dn.priv-methods ! + + \ initialize template data + r@ >dn.itemplate + r@ over >in.device-node ! + my-self over >in.my-parent ! + + \ make it the active package and current instance + to my-self + r@ active-package! + + \ swtich to public wordlist + external + r> drop +; + +\ helpers for finish-device (OF does not actually define words +\ for device node deletion) + +: (delete-device) \ ( phandle ) + >r + r@ >dn.parent @ + ?dup if + >dn.child \ ( &first-child ) + begin dup @ r@ <> while @ >dn.peer repeat + r@ >dn.peer @ swap ! + else + \ root node + 0 to device-tree + then + + \ XXX: free any memory related to this node. + \ we could have a list with free device-node headers... + r> drop +; + +: delete-device \ ( phandle ) + >r + \ first, get rid of any children + begin r@ >dn.child @ dup while + (delete-device) + repeat + drop + + \ then free this node + r> (delete-device) +; + +\ finish-device ( -- ) +\ +\ Finish this package, set active package to parent. +\ Complete a device node that was created by new-device, as follows: If the +\ device node has no "name" property, remove the device node from the device +\ tree. Otherwise, save the current values of the current instance's +\ initialized data items within the active package for later use in +\ initializing the data items of instances created from that node. In any +\ case, destroy the current instance, make its parent instance the current +\ instance, and select the parent node of the device node just completed, +\ making the parent node the active package again. + +: finish-device \ ( -- ) + my-self + dup >in.device-node @ >r + >in.my-parent @ to my-self + + ( -- ) + r@ >dn.parent @ active-package! + s" name" r@ get-package-property if + \ delete the node (and any children) + r@ delete-device + else + 2drop + \ node OK + then + r> drop +; + + +\ helper function which creates and initializes an instance. +\ open is not called. The current instance is not changed. +\ +: create-instance ( phandle -- ihandle|0 ) + dup >dn.isize @ ['] alloc-mem catch if 2drop 0 exit then + >r + \ we need to save the size in order to be able to release it properly + dup >dn.isize @ r@ >in.alloced-size ! + + \ clear memory (we only need to clear the head; all other data is copied) + r@ inst-node.size 0 fill + + ( phandle R: ihandle ) + + \ instantiate data + dup >dn.methods @ r@ instance-init + dup >dn.priv-methods @ r@ instance-init + + \ instantiate + dup >dn.itemplate r@ inst-node.size move + r@ r@ >in.instance-data ! + my-self r@ >in.my-parent ! + drop + + r> +; + +\ helper function which tears down and frees an instance +: destroy-instance ( ihandle ) + ?dup if + \ free arguments + dup >in.arguments 2@ free-mem + \ and the instance block + dup >in.alloced-size @ + free-mem + then +; + +\ Redefine to word so that statements of the form "0 to active-package" +\ are supported for bootloaders that require it +: to + ['] ' execute + dup ['] active-package = if + drop active-package! + else + (to-xt) + then +; immediate diff --git a/qemu/roms/openbios/forth/device/display.fs b/qemu/roms/openbios/forth/device/display.fs new file mode 100644 index 000000000..fff44e00a --- /dev/null +++ b/qemu/roms/openbios/forth/device/display.fs @@ -0,0 +1,421 @@ +\ tag: Display device management +\ +\ this code implements IEEE 1275-1994 ch. 5.3.6 +\ +\ Copyright (C) 2003 Stefan Reinauer +\ +\ See the file "COPYING" for further information about +\ the copyright and warranty status of this work. +\ + +hex + +\ +\ 5.3.6.1 Terminal emulator routines +\ + +\ The following values are used and set by the terminal emulator +\ defined and described in 3.8.4.2 +0 value line# ( -- line# ) +0 value column# ( -- column# ) +0 value inverse? ( -- white-on-black? ) +0 value inverse-screen? ( -- black? ) +0 value #lines ( -- rows ) +0 value #columns ( -- columns ) + +\ The following values are used internally by both the 1-bit and the +\ 8-bit frame-buffer support routines. + +0 value frame-buffer-adr ( -- addr ) +0 value screen-height ( -- height ) +0 value screen-width ( -- width ) +0 value window-top ( -- border-height ) +0 value window-left ( -- border-width ) +0 value char-height ( -- height ) +0 value char-width ( -- width ) +0 value fontbytes ( -- bytes ) + +\ these values are used internally and do not represent any +\ official open firmware words +0 value char-min +0 value char-num +0 value font + +0 value foreground-color +0 value background-color +create color-palette 100 cells allot + +2 value font-spacing +0 value depth-bits +0 value line-bytes +0 value display-ih + +\ internal values +0 value openbios-video-height +0 value openbios-video-width + +\ The following wordset is called the "defer word interface" of the +\ terminal-emulator support package. It gets overloaded by fb1-install +\ or fb8-install (initiated by the framebuffer fcode driver) + +defer draw-character ( char -- ) +defer reset-screen ( -- ) +defer toggle-cursor ( -- ) +defer erase-screen ( -- ) +defer blink-screen ( -- ) +defer invert-screen ( -- ) +defer insert-characters ( n -- ) +defer delete-characters ( n -- ) +defer insert-lines ( n -- ) +defer delete-lines ( n -- ) +defer draw-logo ( line# addr width height -- ) + +defer fb-emit ( x -- ) + +: depth-bytes ( -- bytes ) + depth-bits 1+ 8 / +; + +\ +\ 5.3.6.2 Frame-buffer support routines +\ + +: default-font ( -- addr width height advance min-char #glyphs ) + (romfont) (romfont-width) (romfont-height) (romfont-height) 0 100 + ; + +: set-font ( addr width height advance min-char #glyphs -- ) + to char-num + to char-min + to fontbytes + font-spacing + to char-height + to char-width + to font + ; + +: >font ( char -- addr ) + char-min - + char-num min + fontbytes * + font + + ; + +\ +\ 5.3.6.3 Display device support +\ + +\ +\ 5.3.6.3.1 Frame-buffer package interface +\ + +: is-install ( xt -- ) + external + \ Create open and other methods for this display device. + \ Methods to be created: open, write, draw-logo, restore + s" open" header + 1 , \ colon definition + , + ['] (lit) , + -1 , + ['] (semis) , + reveal + s" : write dup >r bounds do i c@ fb-emit loop r> ; " evaluate + s" : draw-logo draw-logo ; " evaluate + s" : restore reset-screen ; " evaluate + ; + +: is-remove ( xt -- ) + external + \ Create close method for this display device. + s" close" header + 1 , \ colon definition + , + ['] (semis) , + reveal + ; + +: is-selftest ( xt -- ) + external + \ Create selftest method for this display device. + s" selftest" header + 1 , \ colon definition + , + ['] (semis) , + reveal + ; + + +\ 5.3.6.3.2 Generic one-bit frame-buffer support (optional) + +: fb1-nonimplemented + ." Monochrome framebuffer support is not implemented." cr + end0 + ; + +: fb1-draw-character fb1-nonimplemented ; \ historical +: fb1-reset-screen fb1-nonimplemented ; +: fb1-toggle-cursor fb1-nonimplemented ; +: fb1-erase-screen fb1-nonimplemented ; +: fb1-blink-screen fb1-nonimplemented ; +: fb1-invert-screen fb1-nonimplemented ; +: fb1-insert-characters fb1-nonimplemented ; +: fb1-delete-characters fb1-nonimplemented ; +: fb1-insert-lines fb1-nonimplemented ; +: fb1-delete-lines fb1-nonimplemented ; +: fb1-slide-up fb1-nonimplemented ; +: fb1-draw-logo fb1-nonimplemented ; +: fb1-install fb1-nonimplemented ; + + +\ 5.3.6.3.3 Generic eight-bit frame-buffer support + +\ bind to low-level C function later +defer fb8-blitmask +defer fb8-fillrect +defer fb8-invertrect + +: fb8-line2addr ( line -- addr ) + window-top + + screen-width * depth-bytes * + frame-buffer-adr + + window-left depth-bytes * + +; + +: fb8-curpos2addr ( col line -- addr ) + char-height * fb8-line2addr + swap char-width * depth-bytes * + +; + +: fb8-copy-lines ( count from to -- ) + fb8-line2addr swap + fb8-line2addr swap + #columns char-width * depth-bytes * + 3 pick * move drop +; + +: fb8-clear-lines ( count line -- ) + background-color 0 + 2 pick window-top + + #columns char-width * + 5 pick + fb8-fillrect + 2drop +; + +: fb8-draw-character ( char -- ) + \ erase the current character + background-color + column# char-width * window-left + + line# char-height * window-top + + char-width char-height fb8-fillrect + \ draw the character: + >font + line# char-height * window-top + screen-width * depth-bytes * + column# char-width * depth-bytes * + window-left depth-bytes * + + frame-buffer-adr + + swap char-width char-height font-spacing - + \ normal or inverse? + foreground-color background-color + inverse? if + swap + then + fb8-blitmask + ; + +: fb8-reset-screen ( -- ) + false to inverse? + false to inverse-screen? + 0 to foreground-color + d# 15 to background-color + + \ override with OpenBIOS defaults + fe to background-color + 0 to foreground-color + ; + +: fb8-toggle-cursor ( -- ) + column# char-width * window-left + + line# char-height * window-top + + char-width char-height font-spacing - + foreground-color background-color + fb8-invertrect + ; + +: fb8-erase-screen ( -- ) + inverse-screen? if + foreground-color + else + background-color + then + 0 0 screen-width screen-height + fb8-fillrect + ; + +: fb8-invert-screen ( -- ) + 0 0 screen-width screen-height + background-color foreground-color + fb8-invertrect + ; + +: fb8-blink-screen ( -- ) + fb8-invert-screen 2000 ms + fb8-invert-screen + ; + +: fb8-insert-characters ( n -- ) + \ numcopy = ( #columns - column# - n ) + #columns over - column# - + char-width * depth-bytes * ( n numbytescopy ) + + over column# + line# fb8-curpos2addr + column# line# fb8-curpos2addr ( n numbytescopy destaddr srcaddr ) + char-height 0 do + 3dup swap rot move + line-bytes + swap line-bytes + swap + loop 3drop + + background-color + column# char-width * window-left + line# char-height * window-top + + 3 pick char-width * char-height + fb8-fillrect + drop + ; + +: fb8-delete-characters ( n -- ) + \ numcopy = ( #columns - column# - n ) + #columns over - column# - + char-width * depth-bytes * ( n numbytescopy ) + + over column# + line# fb8-curpos2addr + column# line# fb8-curpos2addr swap ( n numbytescopy destaddr srcaddr ) + char-height 0 do + 3dup swap rot move + line-bytes + swap line-bytes + swap + loop 3drop + + background-color + over #columns swap - char-width * window-left + line# char-height * window-top + + 3 pick char-width * char-height + fb8-fillrect + drop + ; + +: fb8-insert-lines ( n -- ) + \ numcopy = ( #lines - n ) + #lines over - char-height * + over line# char-height * + swap char-height * over + + fb8-copy-lines + + char-height * line# char-height * + fb8-clear-lines + ; + +: fb8-delete-lines ( n -- ) + \ numcopy = ( #lines - ( line# + n )) * char-height + #lines over line# + - char-height * + over line# + char-height * + line# char-height * + fb8-copy-lines + + #lines over - char-height * + dup #lines char-height * swap - swap + fb8-clear-lines + drop +; + + +: fb8-draw-logo ( line# addr width height -- ) + 2swap swap + char-height * window-top + + screen-width * window-left + + frame-buffer-adr + + swap 2swap + \ in-fb-start-adr logo-adr logo-width logo-height + + fb8-blitmask ( fbaddr mask-addr width height -- ) +; + + +: fb8-install ( width height #columns #lines -- ) + + \ set state variables + to #lines + to #columns + to screen-height + to screen-width + + screen-width #columns char-width * - 2/ to window-left + screen-height #lines char-height * - 2/ to window-top + + 0 to column# + 0 to line# + 0 to inverse? + 0 to inverse-screen? + + my-self to display-ih + + \ set /chosen display property + my-self active-package 0 to my-self + " /chosen" (find-dev) 0<> if + active-package! + display-ih encode-int " display" property + then + active-package! to my-self + + \ set defer functions to 8bit versions + + ['] fb8-draw-character to draw-character + ['] fb8-toggle-cursor to toggle-cursor + ['] fb8-erase-screen to erase-screen + ['] fb8-blink-screen to blink-screen + ['] fb8-invert-screen to invert-screen + ['] fb8-insert-characters to insert-characters + ['] fb8-delete-characters to delete-characters + ['] fb8-insert-lines to insert-lines + ['] fb8-delete-lines to delete-lines + ['] fb8-draw-logo to draw-logo + ['] fb8-reset-screen to reset-screen + + \ recommended practice + s" iso6429-1983-colors" get-my-property if + 0 ff + else + 2drop d# 15 0 + then + to foreground-color to background-color + + \ setup palette + 10101 ['] color-palette cell+ ff 0 do + dup 2 pick i * swap ! cell+ + loop 2drop + + \ special background color + ffffcc ['] color-palette cell+ fe cells + ! + + \ load palette onto the hardware + ['] color-palette cell+ ff 0 do + dup @ ff0000 and d# 16 rshift + 1 pick @ ff00 and d# 8 rshift + 2 pick @ ff and + i + s" color!" $find if + execute + else + 2drop + then + cell+ + loop drop + + \ ... but let's override with some better defaults + fe to background-color + 0 to foreground-color + + fb8-erase-screen + + \ If we have a startup splash then display it + [IFDEF] CONFIG_MOL + mol-startup-splash 2000 ms + fb8-erase-screen + [THEN] +; diff --git a/qemu/roms/openbios/forth/device/extra.fs b/qemu/roms/openbios/forth/device/extra.fs new file mode 100644 index 000000000..9ca6b78e3 --- /dev/null +++ b/qemu/roms/openbios/forth/device/extra.fs @@ -0,0 +1,103 @@ +\ tag: Useful device related functions +\ +\ Copyright (C) 2003, 2004 Samuel Rydh +\ +\ See the file "COPYING" for further information about +\ the copyright and warranty status of this work. +\ + + +: parent ( phandle -- parent.phandle|0 ) + >dn.parent @ +; + +\ ------------------------------------------------------------------- +\ property helpers +\ ------------------------------------------------------------------- + +: int-property ( value name-str name-len -- ) + rot encode-int 2swap property +; + +\ ------------------------------------------------------------------------- +\ property utils +\ ------------------------------------------------------------------------- + +\ like property (except it takes a phandle as an argument) +: encode-property ( buf len propname propname-len phandle -- ) + dup 0= abort" null phandle" + + my-self >r 0 to my-self + active-package >r active-package! + + property + + r> active-package! + r> to my-self +; + +\ ------------------------------------------------------------------- +\ device tree iteration +\ ------------------------------------------------------------------- + +: iterate-tree ( phandle -- phandle|0 ) + ?dup 0= if device-tree @ exit then + + \ children first + dup child if + child exit + then + + \ then peers + dup peer if + peer exit + then + + \ then peer of a parent + begin >dn.parent @ dup while + dup peer if peer exit then + repeat +; + +: iterate-tree-begin ( -- first_node ) + device-tree @ +; + + +\ ------------------------------------------------------------------- +\ device tree iteration +\ ------------------------------------------------------------------- + +: iterate-device-type ( lastph|0 type-str type-len -- 0|nextph ) + rot + begin iterate-tree ?dup while + >r + 2dup " device_type" r@ get-package-property if 0 0 then + dup 0> if 1- then + strcmp 0= if 2drop r> exit then + r> + repeat + 2drop 0 +; + +\ ------------------------------------------------------------------- +\ device tree "cut and paste" +\ ------------------------------------------------------------------- + +\ add a subtree to the current device node +: link-nodes ( phandle -- ) + \ reparent phandle and peers + dup begin ?dup while + dup >dn.parent active-package ! + >dn.peer @ + repeat + + \ add to list of children + active-package >dn.child + begin dup @ while @ >dn.peer repeat dup . ! +; + +: link-node ( phandle -- ) + 0 over >dn.peer ! + link-nodes +; diff --git a/qemu/roms/openbios/forth/device/fcode.fs b/qemu/roms/openbios/forth/device/fcode.fs new file mode 100644 index 000000000..9083ed0e0 --- /dev/null +++ b/qemu/roms/openbios/forth/device/fcode.fs @@ -0,0 +1,573 @@ +\ tag: FCode implementation functions +\ +\ this code implements IEEE 1275-1994 ch. 5.3.3 +\ +\ Copyright (C) 2003 Stefan Reinauer +\ +\ See the file "COPYING" for further information about +\ the copyright and warranty status of this work. +\ + +hex + +0 value fcode-sys-table \ table with built-in fcodes (0-0x7ff) + +true value ?fcode-offset16 \ fcode offsets are 16 instead of 8 bit? +1 value fcode-spread \ fcode spread (1, 2 or 4) +0 value fcode-table \ pointer to fcode table +false value ?fcode-verbose \ do verbose fcode execution? + +defer _fcode-debug? \ If true, save names for FCodes with headers +true value fcode-headers? \ If true, possibly save names for FCodes. + +0 value fcode-stream-start \ start address of fcode stream +0 value fcode-stream \ current fcode stream address + +variable fcode-end \ state variable, if true, fcode program terminates. +defer fcode-c@ \ get byte + +: fcode-push-state ( -- <state information> ) + ?fcode-offset16 + fcode-spread + fcode-table + fcode-headers? + fcode-stream-start + fcode-stream + fcode-end @ + ['] fcode-c@ behavior +; + +: fcode-pop-state ( <state information> -- ) + to fcode-c@ + fcode-end ! + to fcode-stream + to fcode-stream-start + to fcode-headers? + to fcode-table + to fcode-spread + to ?fcode-offset16 +; + +\ +\ fcode access helper functions +\ + +\ fcode-ptr +\ convert FCode number to pointer to xt in FCode table. + +: fcode-ptr ( u16 -- *xt ) + cells + fcode-table ?dup if + exit then + + \ we are not parsing fcode at the moment + dup 800 cells u>= abort" User FCODE# referenced." + fcode-sys-table + +; + +\ fcode>xt +\ get xt according to an FCode# + +: fcode>xt ( u16 -- xt ) + fcode-ptr @ + ; + +\ fcode-num8 +\ get 8bit from FCode stream, taking spread into regard. + +: fcode-num8 ( -- c ) ( F: c -- ) + fcode-stream + dup fcode-spread + to fcode-stream + fcode-c@ + ; + +\ fcode-num8-signed ( -- c ) ( F: c -- ) +\ get 8bit signed from FCode stream + +: fcode-num8-signed + fcode-num8 + dup 80 and 0> if + ff invert or + then + ; + +\ fcode-num16 +\ get 16bit from FCode stream + +: fcode-num16 ( -- num16 ) + fcode-num8 fcode-num8 swap bwjoin + ; + +\ fcode-num16-signed ( -- c ) ( F: c -- ) +\ get 16bit signed from FCode stream + +: fcode-num16-signed + fcode-num16 + dup 8000 and 0> if + ffff invert or + then + ; + +\ fcode-num32 +\ get 32bit from FCode stream + +: fcode-num32 ( -- num32 ) + fcode-num8 fcode-num8 + fcode-num8 fcode-num8 + swap 2swap swap bljoin + ; + +\ fcode# +\ Get an FCode# from FCode stream + +: fcode# ( -- fcode# ) + fcode-num8 + dup 1 f between if + fcode-num8 swap bwjoin + then + ; + +\ fcode-offset +\ get offset from FCode stream. + +: fcode-offset ( -- offset ) + ?fcode-offset16 if + fcode-num16-signed + else + fcode-num8-signed + then + + \ Display offset in verbose mode + ?fcode-verbose if + dup ." (offset) " . cr + then + ; + +\ fcode-string +\ get a string from FCode stream, store in pocket. + +: fcode-string ( -- addr len ) + pocket dup + fcode-num8 + dup rot c! + 2dup bounds ?do + fcode-num8 i c! + loop + + \ Display string in verbose mode + ?fcode-verbose if + 2dup ." (const) " type cr + then + ; + +\ fcode-header +\ retrieve FCode header from FCode stream + +: fcode-header + fcode-num8 + fcode-num16 + fcode-num32 + ?fcode-verbose if + ." Found FCode header:" cr rot + ." Format : " u. cr swap + ." Checksum : " u. cr + ." Length : " u. cr + else + 3drop + then + \ TODO checksum + ; + +\ writes currently created word as fcode# read from stream +\ + +: fcode! ( F:FCode# -- ) + here fcode# + + \ Display fcode# in verbose mode + ?fcode-verbose if + dup ." (fcode#) " . cr + then + fcode-ptr ! + ; + + +\ +\ 5.3.3.1 Defining new FCode functions. +\ + +\ instance ( -- ) +\ Mark next defining word as instance specific. +\ (defined in bootstrap.fs) + +\ instance-init ( wid buffer -- ) +\ Copy template from specified wordlist to instance +\ + +: instance-init + swap + begin @ dup 0<> while + dup /n + @ instance-cfa? if \ buffer dict + 2dup 2 /n* + @ + \ buffer dict dest + over 3 /n* + @ \ buffer dict dest size + 2 pick 4 /n* + \ buffer dict dest size src + -rot + move + then + repeat + 2drop + ; + + +\ new-token ( F:/FCode#/ -- ) +\ Create a new unnamed FCode function + +: new-token + 0 0 header + fcode! + ; + + +\ named-token (F:FCode-string FCode#/ -- ) +\ Create a new possibly named FCode function. + +: named-token + fcode-string + _fcode-debug? not if + 2drop 0 0 + then + header + fcode! + ; + + +\ external-token (F:/FCode-string FCode#/ -- ) +\ Create a new named FCode function + +: external-token + fcode-string header + fcode! + ; + + +\ b(;) ( -- ) +\ End an FCode colon definition. + +: b(;) + ['] ; execute + ; immediate + + +\ b(:) ( -- ) ( E: ... -- ??? ) +\ Defines type of new FCode function as colon definition. + +: b(:) + 1 , ] + ; + + +\ b(buffer:) ( size -- ) ( E: -- a-addr ) +\ Defines type of new FCode function as buffer:. + +: b(buffer:) + 4 , allot + reveal + ; + +\ b(constant) ( nl -- ) ( E: -- nl ) +\ Defines type of new FCode function as constant. + +: b(constant) + 3 , , + reveal + ; + + +\ b(create) ( -- ) ( E: -- a-addr ) +\ Defines type of new FCode function as create word. + +: b(create) + 6 , + ['] noop , + reveal + ; + + +\ b(defer) ( -- ) ( E: ... -- ??? ) +\ Defines type of new FCode function as defer word. + +: b(defer) + 5 , + ['] (undefined-defer) , + ['] (semis) , + reveal + ; + + +\ b(field) ( offset size -- offset+size ) ( E: addr -- addr+offset ) +\ Defines type of new FCode function as field. + +: b(field) + 6 , + ['] noop , + reveal + over , + + + does> + @ + + ; + + +\ b(value) ( x -- ) (E: -- x ) +\ Defines type of new FCode function as value. + +: b(value) + 3 , , reveal + ; + + +\ b(variable) ( -- ) ( E: -- a-addr ) +\ Defines type of new FCode function as variable. + +: b(variable) + 4 , 0 , + reveal + ; + + +\ (is-user-word) ( name-str name-len xt -- ) ( E: ... -- ??? ) +\ Create a new named user interface command. + +: (is-user-word) + ; + + +\ get-token ( fcode# -- xt immediate? ) +\ Convert FCode number to function execution token. + +: get-token + fcode>xt dup immediate? + ; + + +\ set-token ( xt immediate? fcode# -- ) +\ Assign FCode number to existing function. + +: set-token + nip \ TODO we use the xt's immediate state for now. + fcode-ptr ! + ; + + + + +\ +\ 5.3.3.2 Literals +\ + + +\ b(lit) ( -- n1 ) +\ Numeric literal FCode. Followed by FCode-num32. + +64bit? [IF] +: b(lit) + fcode-num32 32>64 + state @ if + ['] (lit) , , + then + ; immediate +[ELSE] +: b(lit) + fcode-num32 + state @ if + ['] (lit) , , + then + ; immediate +[THEN] + + +\ b(') ( -- xt ) +\ Function literal FCode. Followed by FCode# + +: b(') + fcode# fcode>xt + state @ if + ['] (lit) , , + then + ; immediate + + +\ b(") ( -- str len ) +\ String literal FCode. Followed by FCode-string. + +: b(") + fcode-string + state @ if + \ only run handle-text in compile-mode, + \ otherwise we would waste a pocket. + handle-text + then + ; immediate + + +\ +\ 5.3.3.3 Controlling values and defers +\ + +\ behavior ( defer-xt -- contents-xt ) +\ defined in bootstrap.fs + +\ b(to) ( new-value -- ) +\ FCode for setting values and defers. Followed by FCode#. + +: b(to) + fcode# fcode>xt + 1 handle-lit + ['] (to) + state @ if + , + else + execute + then + ; immediate + + + +\ +\ 5.3.3.4 Control flow +\ + + +\ offset16 ( -- ) +\ Makes subsequent FCode-offsets use 16-bit (not 8-bit) form. + +: offset16 + true to ?fcode-offset16 + ; + + +\ bbranch ( -- ) +\ Unconditional branch FCode. Followed by FCode-offset. + +: bbranch + fcode-offset 0< if \ if we jump backwards, we can forsee where it goes + ['] dobranch , + resolve-dest + execute-tmp-comp + else + setup-tmp-comp ['] dobranch , + here 0 + 0 , + 2swap + then + ; immediate + + +\ b?branch ( continue? -- ) +\ Conditional branch FCode. Followed by FCode-offset. + +: b?branch + fcode-offset 0< if \ if we jump backwards, we can forsee where it goes + ['] do?branch , + resolve-dest + execute-tmp-comp + else + setup-tmp-comp ['] do?branch , + here 0 + 0 , + then + ; immediate + + +\ b(<mark) ( -- ) +\ Target of backward branches. + +: b(<mark) + setup-tmp-comp + here 1 + ; immediate + + +\ b(>resolve) ( -- ) +\ Target of forward branches. + +: b(>resolve) + resolve-orig + execute-tmp-comp + ; immediate + + +\ b(loop) ( -- ) +\ End FCode do..loop. Followed by FCode-offset. + +: b(loop) + fcode-offset drop + postpone loop + ; immediate + + +\ b(+loop) ( delta -- ) +\ End FCode do..+loop. Followed by FCode-offset. + +: b(+loop) + fcode-offset drop + postpone +loop + ; immediate + + +\ b(do) ( limit start -- ) +\ Begin FCode do..loop. Followed by FCode-offset. + +: b(do) + fcode-offset drop + postpone do + ; immediate + + +\ b(?do) ( limit start -- ) +\ Begin FCode ?do..loop. Followed by FCode-offset. + +: b(?do) + fcode-offset drop + postpone ?do + ; immediate + + +\ b(leave) ( -- ) +\ Exit from a do..loop. + +: b(leave) + postpone leave + ; immediate + + +\ b(case) ( sel -- sel ) +\ Begin a case (multiple selection) statement. + +: b(case) + postpone case + ; immediate + + +\ b(endcase) ( sel | <nothing> -- ) +\ End a case (multiple selection) statement. + +: b(endcase) + postpone endcase + ; immediate + + +\ b(of) ( sel of-val -- sel | <nothing> ) +\ FCode for of in case statement. Followed by FCode-offset. + +: b(of) + fcode-offset drop + postpone of + ; immediate + +\ b(endof) ( -- ) +\ FCode for endof in case statement. Followed by FCode-offset. + +: b(endof) + fcode-offset drop + postpone endof + ; immediate diff --git a/qemu/roms/openbios/forth/device/feval.fs b/qemu/roms/openbios/forth/device/feval.fs new file mode 100644 index 000000000..9e2773db2 --- /dev/null +++ b/qemu/roms/openbios/forth/device/feval.fs @@ -0,0 +1,100 @@ +\ tag: FCode evaluator +\ +\ this code implements an fcode evaluator +\ as described in IEEE 1275-1994 +\ +\ Copyright (C) 2003 Stefan Reinauer +\ +\ See the file "COPYING" for further information about +\ the copyright and warranty status of this work. +\ + +defer init-fcode-table + +: alloc-fcode-table + 4096 cells alloc-mem to fcode-table + ?fcode-verbose if + ." fcode-table at 0x" fcode-table . cr + then + init-fcode-table + ; + +: free-fcode-table + fcode-table 4096 cells free-mem + 0 to fcode-table + ; + +: (debug-feval) ( fcode# -- fcode# ) + \ Address + fcode-stream 1 - . ." : " + + \ Indicate if word is compiled + state @ 0<> if + ." (compile) " + then + dup fcode>xt cell - lfa2name type + dup ." [ 0x" . ." ]" cr + ; + +: (feval) ( -- ?? ) + begin + fcode# + ?fcode-verbose if + (debug-feval) + then + fcode>xt + dup flags? 0<> state @ 0= or if + execute + else + , + then + fcode-end @ until + + \ If we've executed incorrect FCode we may have reached the end of the FCode + \ program but still be in compile mode. Make sure that if this has happened + \ then we switch back to immediate mode to prevent internal OpenBIOS errors. + tmp-comp-depth @ -1 <> if + -1 tmp-comp-depth ! + tmp-comp-buf @ @ here! + 0 state ! + then +; + +: byte-load ( addr xt -- ) + ?fcode-verbose if + cr ." byte-load: evaluating fcode at 0x" over . cr + then + + \ save state + >r >r fcode-push-state r> r> + + \ set fcode-c@ defer + dup 1 = if drop ['] c@ then \ FIXME: uses c@ rather than rb@ for now... + to fcode-c@ + dup to fcode-stream-start + to fcode-stream + 1 to fcode-spread + false to ?fcode-offset16 + alloc-fcode-table + false fcode-end ! + + \ protect against stack overflow/underflow + 0 0 0 0 0 0 depth >r + + ['] (feval) catch if + cr ." byte-load: exception caught!" cr + then + + s" fcode-debug?" evaluate if + depth r@ <> if + cr ." byte-load: warning stack overflow, diff " depth r@ - . cr + then + then + + r> depth! 3drop 3drop + + free-fcode-table + + \ restore state + fcode-pop-state +; diff --git a/qemu/roms/openbios/forth/device/font.fs b/qemu/roms/openbios/forth/device/font.fs new file mode 100644 index 000000000..7b742fac4 --- /dev/null +++ b/qemu/roms/openbios/forth/device/font.fs @@ -0,0 +1,17 @@ +\ tag: 8x16 bitmap font +\ +\ Terminus font +\ +\ The Terminus Font is developed by and is a property +\ of Dimitar Toshkov Zhekov <jimmy@is-vn.bg> +\ +\ See the file "COPYING" for further information about +\ the copyright and warranty status of this work. +\ + +0 value (romfont) +0 value (romfont-width) +0 value (romfont-height) + +\ encode-file romfont.bin +\ drop value (romfont-8x16) diff --git a/qemu/roms/openbios/forth/device/logo.fs b/qemu/roms/openbios/forth/device/logo.fs new file mode 100644 index 000000000..4db31ef54 --- /dev/null +++ b/qemu/roms/openbios/forth/device/logo.fs @@ -0,0 +1,98 @@ +\ tag: monochrome logo +\ +\ simple monochrome logo +\ as described in IEEE 1275-1994 +\ +\ Copyright (C) 2003 Stefan Reinauer +\ +\ See the file "COPYING" for further information about +\ the copyright and warranty status of this work. +\ + + +\ FIXME : This is currently just a test file, it contains +\ a Pi symbol of size 64x64, not really nicely streched. + +\ To use an XBM (X Bitmap), the bits in the bitmap array +\ have to be reversed, i.e. like this: +\ +\ int main(void) +\ { +\ int i,j; unsigned char bit, bitnew; +\ for (i=0; i<512; i++) { +\ bit=openbios_bits[i]; bitnew=0; +\ for (j=0; j<8; j++) +\ if (bit & (1<<j)) bitnew |= (1<<(7-j)); +\ printf("%02x c, ", bitnew); if(i%8 == 7) printf("\n"); +\ } +\ return 0; +\ } + +here + +00 c, 00 c, 00 c, 00 c, 00 c, 00 c, 00 c, 00 c, +00 c, 00 c, 00 c, 00 c, 00 c, 00 c, 00 c, 00 c, +07 c, ff c, ff c, ff c, ff c, ff c, ff c, e0 c, +07 c, ff c, ff c, ff c, ff c, ff c, ff c, e0 c, +07 c, ff c, ff c, ff c, ff c, ff c, ff c, e0 c, +07 c, ff c, ff c, ff c, ff c, ff c, ff c, e0 c, +7f c, ff c, ff c, ff c, ff c, ff c, ff c, e0 c, +7f c, ff c, ff c, ff c, ff c, ff c, ff c, e0 c, +7f c, ff c, ff c, ff c, ff c, ff c, ff c, e0 c, +7f c, ff c, ff c, ff c, ff c, ff c, ff c, e0 c, +7f c, df c, ff c, ff c, 7f c, ff c, ff c, 90 c, +78 c, 03 c, fe c, 00 c, 07 c, fc c, 00 c, 00 c, +78 c, 03 c, fe c, 00 c, 07 c, fc c, 00 c, 00 c, +78 c, 03 c, fe c, 00 c, 07 c, fc c, 00 c, 00 c, +70 c, 03 c, fe c, 00 c, 07 c, fc c, 00 c, 00 c, +00 c, 03 c, fe c, 00 c, 07 c, fc c, 00 c, 00 c, +00 c, 03 c, fe c, 00 c, 07 c, fc c, 00 c, 00 c, +00 c, 03 c, fe c, 00 c, 07 c, fc c, 00 c, 00 c, +00 c, 03 c, fe c, 00 c, 07 c, fc c, 00 c, 00 c, +00 c, 03 c, fe c, 00 c, 07 c, fc c, 00 c, 00 c, +00 c, 03 c, fe c, 00 c, 07 c, fc c, 00 c, 00 c, +00 c, 03 c, fe c, 00 c, 07 c, fc c, 00 c, 00 c, +00 c, 03 c, fe c, 00 c, 07 c, fc c, 00 c, 00 c, +00 c, 03 c, fe c, 00 c, 07 c, fc c, 00 c, 00 c, +00 c, 03 c, fe c, 00 c, 07 c, fc c, 00 c, 00 c, +00 c, 03 c, fe c, 00 c, 07 c, fc c, 00 c, 00 c, +00 c, 03 c, fe c, 00 c, 07 c, fc c, 00 c, 00 c, +00 c, 03 c, fe c, 00 c, 07 c, fc c, 00 c, 00 c, +00 c, 03 c, fe c, 00 c, 07 c, fc c, 00 c, 00 c, +00 c, 03 c, fe c, 00 c, 07 c, fc c, 00 c, 00 c, +00 c, 03 c, fe c, 00 c, 07 c, fc c, 00 c, 00 c, +00 c, 03 c, fe c, 00 c, 07 c, fc c, 00 c, 00 c, +00 c, 03 c, fe c, 00 c, 07 c, fc c, 00 c, 00 c, +00 c, 03 c, fe c, 00 c, 07 c, fc c, 00 c, 00 c, +00 c, 03 c, fe c, 00 c, 07 c, fc c, 00 c, 00 c, +00 c, 03 c, fe c, 00 c, 07 c, fc c, 00 c, 00 c, +00 c, 03 c, fe c, 00 c, 07 c, fc c, 00 c, 00 c, +00 c, 03 c, fe c, 00 c, 07 c, fc c, 00 c, 00 c, +00 c, 03 c, fe c, 00 c, 07 c, fc c, 00 c, 00 c, +00 c, 03 c, fe c, 00 c, 07 c, fc c, 00 c, 00 c, +00 c, 03 c, fe c, 00 c, 07 c, fc c, 00 c, 00 c, +00 c, 03 c, fe c, 00 c, 07 c, fc c, 00 c, 00 c, +00 c, 03 c, fe c, 00 c, 07 c, fc c, 00 c, 00 c, +00 c, 03 c, fe c, 00 c, 07 c, fc c, 00 c, 00 c, +00 c, 03 c, fe c, 00 c, 07 c, fc c, 00 c, 00 c, +00 c, 03 c, fe c, 00 c, 07 c, fc c, 00 c, 00 c, +00 c, 03 c, fe c, 00 c, 07 c, fc c, 01 c, 80 c, +00 c, 03 c, fe c, 00 c, 07 c, f8 c, 01 c, e0 c, +00 c, 03 c, fe c, 00 c, 07 c, f8 c, 01 c, e0 c, +00 c, 03 c, fe c, 00 c, 07 c, fc c, 03 c, e0 c, +00 c, 07 c, fe c, 00 c, 07 c, fc c, 07 c, e0 c, +00 c, 3f c, fe c, 00 c, 07 c, ff c, ff c, e0 c, +00 c, 3f c, fe c, 00 c, 07 c, ff c, ff c, e0 c, +00 c, 3f c, fe c, 00 c, 07 c, ff c, ff c, e0 c, +00 c, 3f c, fc c, 00 c, 07 c, ff c, ff c, c0 c, +00 c, 3f c, f8 c, 00 c, 07 c, ff c, ff c, 80 c, +00 c, 7f c, e0 c, 00 c, 0f c, ff c, fe c, 00 c, +00 c, 3f c, e0 c, 00 c, 07 c, ff c, fe c, 00 c, +00 c, 3f c, c0 c, 00 c, 07 c, ff c, fc c, 00 c, +00 c, 00 c, 00 c, 00 c, 00 c, 00 c, 00 c, 00 c, +00 c, 00 c, 00 c, 00 c, 00 c, 00 c, 00 c, 00 c, +00 c, 00 c, 00 c, 00 c, 00 c, 00 c, 00 c, 00 c, +00 c, 00 c, 00 c, 00 c, 00 c, 00 c, 00 c, 00 c, +00 c, 00 c, 00 c, 00 c, 00 c, 00 c, 00 c, 00 c, + +value (romlogo-64x64) diff --git a/qemu/roms/openbios/forth/device/missing b/qemu/roms/openbios/forth/device/missing new file mode 100644 index 000000000..8ea954ed7 --- /dev/null +++ b/qemu/roms/openbios/forth/device/missing @@ -0,0 +1,38 @@ +5.3.3.1 + + * (is-user-word) + +5.3.4 Package access + +5.3.6 Display + * default-font + * set-font + * >font + * is-install + * is-remove + * is-selftest + +5.3.7 Other + * cpeek + * wpeek + * lpeek + * cpoke + * wpoke + * lpoke + * rb@ + * rw@ + * rl@ + * rb! + * rw! + * rl! + * get-msecs + * ms + * alarm + * user-abort + * mac-address + * display-status + * memory-test-suite + * mask + * diagnostic-mode? + * suspend-fcode + * set-args diff --git a/qemu/roms/openbios/forth/device/other.fs b/qemu/roms/openbios/forth/device/other.fs new file mode 100644 index 000000000..b39007301 --- /dev/null +++ b/qemu/roms/openbios/forth/device/other.fs @@ -0,0 +1,233 @@ +\ tag: Other FCode functions +\ +\ this code implements IEEE 1275-1994 ch. 5.3.7 +\ +\ Copyright (C) 2003 Stefan Reinauer +\ +\ See the file "COPYING" for further information about +\ the copyright and warranty status of this work. +\ + +\ The current diagnostic setting +defer _diag-switch? + + +\ +\ 5.3.7 Other FCode functions +\ + +hex + +\ 5.3.7.1 Peek/poke + +defer (peek) +:noname + execute true +; to (peek) + +: cpeek ( addr -- false | byte true ) + ['] c@ (peek) + ; + +: wpeek ( waddr -- false | w true ) + ['] w@ (peek) + ; + +: lpeek ( qaddr -- false | quad true ) + ['] l@ (peek) + ; + +defer (poke) +:noname + execute true +; to (poke) + +: cpoke ( byte addr -- okay? ) + ['] c! (poke) + ; + +: wpoke ( w waddr -- okay? ) + ['] w! (poke) + ; + +: lpoke ( quad qaddr -- okay? ) + ['] l! (poke) + ; + + +\ 5.3.7.2 Device-register access + +: rb@ ( addr -- byte ) + ; + +: rw@ ( waddr -- w ) + ; + +: rl@ ( qaddr -- quad ) + ; + +: rb! ( byte addr -- ) + ; + +: rw! ( w waddr -- ) + ; + +: rl! ( quad qaddr -- ) + ; + +: rx@ ( oaddr - o ) + state @ if + h# 22e get-token if , else execute then + else + h# 22e get-token drop execute + then + ; immediate + +: rx! ( o oaddr -- ) + state @ if + h# 22f get-token if , else execute then + else + h# 22f get-token drop execute + then + ; immediate + +\ 5.3.7.3 Time + +\ Pointer to OBP tick value updated by timer interrupt +variable obp-ticks + +\ Dummy implementation for platforms without a timer interrupt +0 value dummy-msecs + +: get-msecs ( -- n ) + \ If obp-ticks pointer is set, use it. Otherwise fall back to + \ dummy implementation + obp-ticks @ 0<> if + obp-ticks @ + else + dummy-msecs dup 1+ to dummy-msecs + then + ; + +: ms ( n -- ) + get-msecs + + begin dup get-msecs < until + drop + ; + +: alarm ( xt n -- ) + 2drop + ; + +: user-abort ( ... -- ) ( R: ... -- ) + ; + + +\ 5.3.7.4 System information +0003.0000 value fcode-revision ( -- n ) + +: mac-address ( -- mac-str mac-len ) + ; + + +\ 5.3.7.5 FCode self-test +: display-status ( n -- ) + ; + +: memory-test-suite ( addr len -- fail? ) + ; + +: mask ( -- a-addr ) + ; + +: diagnostic-mode? ( -- diag? ) + \ Return the NVRAM diag-switch? setting + _diag-switch? + ; + +\ 5.3.7.6 Start and end. + +\ Begin program with spread 0 followed by FCode-header. +: start0 ( -- ) + 0 fcode-spread ! + offset16 + fcode-header + ; + +\ Begin program with spread 1 followed by FCode-header. +: start1 ( -- ) + 1 to fcode-spread + offset16 + fcode-header + ; + +\ Begin program with spread 2 followed by FCode-header. +: start2 ( -- ) + 2 to fcode-spread + offset16 + fcode-header + ; + +\ Begin program with spread 4 followed by FCode-header. +: start4 ( -- ) + 4 to fcode-spread + offset16 + fcode-header + ; + +\ Begin program with spread 1 followed by FCode-header. +: version1 ( -- ) + 1 to fcode-spread + fcode-header + ; + +\ Cease evaluating this FCode program. +: end0 ( -- ) + true fcode-end ! + ; immediate + +\ Cease evaluating this FCode program. +: end1 ( -- ) + end0 + ; + +\ Standard FCode number for undefined FCode functions. +: ferror ( -- ) + ." undefined fcode# encountered." cr + true fcode-end ! + ; + +\ Pause FCode evaluation if desired; can resume later. +: suspend-fcode ( -- ) + \ NOT YET IMPLEMENTED. + ; + + +\ Evaluate FCode beginning at location addr. + +\ : byte-load ( addr xt -- ) +\ \ this word is implemented in feval.fs +\ ; + +\ Set address and arguments of new device node. +: set-args ( arg-str arg-len unit-str unit-len -- ) + ?my-self drop + + depth 1- >r + " decode-unit" ['] $call-parent catch if + 2drop 2drop + then + + my-self ihandle>phandle >dn.probe-addr \ offset + begin depth r@ > while + dup na1+ >r ! r> + repeat + r> 2drop + + my-self >in.arguments 2@ free-mem + strdup my-self >in.arguments 2! +; + +: dma-alloc + s" dma-alloc" $call-parent + ; diff --git a/qemu/roms/openbios/forth/device/package.fs b/qemu/roms/openbios/forth/device/package.fs new file mode 100644 index 000000000..d5b52c3eb --- /dev/null +++ b/qemu/roms/openbios/forth/device/package.fs @@ -0,0 +1,287 @@ +\ tag: Package access. +\ +\ this code implements IEEE 1275-1994 ch. 5.3.4 +\ +\ Copyright (C) 2003 Stefan Reinauer +\ +\ See the file "COPYING" for further information about +\ the copyright and warranty status of this work. +\ + +\ variable last-package 0 last-package ! +\ 0 value active-package +: current-device active-package ; + +\ +\ 5.3.4.1 Open/Close packages (part 1) +\ + +\ 0 value my-self ( -- ihandle ) +: ?my-self + my-self dup 0= abort" no current instance." + ; + +: my-parent ( -- ihandle ) + ?my-self >in.my-parent @ +; + +: ihandle>non-interposed-phandle ( ihandle -- phandle ) + begin dup >in.interposed @ while + >in.my-parent @ + repeat + >in.device-node @ +; + +: ihandle>phandle ( ihandle -- phandle ) + >in.device-node @ +; + + +\ next-property +\ defined in property.c + +: peer ( phandle -- phandle.sibling ) + ?dup if + >dn.peer @ + else + device-tree @ + then +; + +: child ( phandle.parent -- phandle.child ) + \ Assume phandle == 0 indicates root node (not documented but similar + \ behaviour to "peer"). Used by some versions of Solaris (e.g. 9). + ?dup if else device-tree @ then + + >dn.child @ +; + + +\ +\ 5.3.4.2 Call methods from other packages +\ + +: find-method ( method-str method-len phandle -- false | xt true ) + \ should we search the private wordlist too? I don't think so... + >dn.methods @ find-wordlist if + true + else + 2drop false + then +; + +: call-package ( ... xt ihandle -- ??? ) + my-self >r + to my-self + execute + r> to my-self +; + + +: $call-method ( ... method-str method-len ihandle -- ??? ) + dup >r >in.device-node @ find-method if + r> call-package + else + -21 throw + then +; + +: $call-parent ( ... method-str method-len -- ??? ) + my-parent $call-method +; + + +\ +\ 5.3.4.1 Open/Close packages (part 2) +\ + +\ find-dev ( dev-str dev-len -- false | phandle true ) +\ find-rel-dev ( dev-str dev-len phandle -- false | phandle true ) +\ +\ These function works just like find-device but without +\ any side effects (or exceptions). +\ +defer find-dev + +: find-rel-dev ( dev-str dev-len phandle -- false | phandle true ) + active-package >r active-package! + find-dev + r> active-package! +; + +: find-package ( name-str name-len -- false | phandle true ) +\ Locate the support package named by name string. +\ If the package can be located, return its phandle and true; otherwise, +\ return false. +\ Interpret the name in name string relative to the "packages" device node. +\ If there are multiple packages with the same name (within the "packages" +\ node), return the phandle for the most recently created one. + + \ This does the full path resolution stuff (including + \ alias expansion. If we don't want that, then we should just + \ iterade the children of /packages. + " /packages" find-dev 0= if 2drop false exit then + find-rel-dev 0= if false exit then + + true +; + +: open-package ( arg-str arg-len phandle -- ihandle | 0 ) +\ Open the package indicated by phandle. +\ Create an instance of the package identified by phandle, save in that +\ instance the instance-argument specified by arg-string and invoke the +\ package's open method. +\ Return the instance handle ihandle of the new instance, or 0 if the package +\ could not be opened. This could occur either because that package has no +\ open method, or because its open method returned false, indicating an error. +\ The parent instance of the new instance is the instance that invoked +\ open-package. The current instance is not changed. + + create-instance dup 0= if + 3drop 0 exit + then + >r + + \ clone arg-str + strdup r@ >in.arguments 2! + + \ open the package + " open" r@ ['] $call-method catch if 3drop false then + if + r> + else + r> destroy-instance false + then +; + + +: $open-package ( arg-str arg-len name-str name-len -- ihandle | 0 ) + \ Open the support package named by name string. + find-package if + open-package + else + 2drop false + then +; + + +: close-package ( ihandle -- ) +\ Close the instance identified by ihandle by calling the package's close +\ method and then destroying the instance. + dup " close" rot ['] $call-method catch if 3drop then + destroy-instance +; + +\ +\ 5.3.4.3 Get local arguments +\ + +: my-address ( -- phys.lo ... ) + ?my-self >in.device-node @ + >dn.probe-addr + my-#acells tuck /l* + swap 1- 0 + ?do + /l - dup l@ swap + loop + drop + ; + +: my-space ( -- phys.hi ) + ?my-self >in.device-node @ + >dn.probe-addr @ + ; + +: my-unit ( -- phys.lo ... phys.hi ) + ?my-self >in.my-unit + my-#acells tuck /l* + swap 0 ?do + /l - dup l@ swap + loop + drop + ; + +: my-args ( -- arg-str arg-len ) + ?my-self >in.arguments 2@ + ; + +\ char is not included. If char is not found, then R-len is zero +: left-parse-string ( str len char -- R-str R-len L-str L-len ) + left-split +; + +\ parse ints "hi,...,lo" separated by comma +: parse-ints ( str len num -- val.lo .. val.hi ) + -rot 2 pick -rot + begin + rot 1- -rot 2 pick 0>= + while + ( num n str len ) + 2dup ascii , strchr ?dup if + ( num n str len p ) + 1+ -rot + 2 pick 2 pick - ( num n p str len len1+1 ) + dup -rot - ( num n p str len1+1 len2 ) + -rot 1- ( num n p len2 str len1 ) + else + 0 0 2swap + then + $number if 0 then >r + repeat + 3drop + + ( num ) + begin 1- dup 0>= while r> swap repeat + drop +; + +: parse-2int ( str len -- val.lo val.hi ) + 2 parse-ints +; + + +\ +\ 5.3.4.4 Mapping tools +\ + +: map-low ( phys.lo ... size -- virt ) + my-space swap s" map-in" $call-parent + ; + +: free-virtual ( virt size -- ) + over s" address" get-my-property 0= if + decode-int -rot 2drop = if + s" address" delete-property + then + else + drop + then + s" map-out" $call-parent + ; + + +\ Deprecated functions (required for compatibility with older loaders) + +variable package-stack-pos 0 package-stack-pos ! +create package-stack 8 cells allot + +: push-package ( phandle -- ) + \ Throw an error if we attempt to push a full stack + package-stack-pos @ 8 >= if + ." cannot push-package onto full stack" cr + -99 throw + then + active-package + package-stack-pos @ /n * package-stack + ! + package-stack-pos @ 1 + package-stack-pos ! + active-package! + ; + +: pop-package ( -- ) + \ Throw an error if we attempt to pop an empty stack + package-stack-pos @ 0 = if + ." cannot pop-package from empty stack" cr + -99 throw + then + package-stack-pos @ 1 - package-stack-pos ! + package-stack-pos @ /n * package-stack + @ + active-package! + ; diff --git a/qemu/roms/openbios/forth/device/pathres.fs b/qemu/roms/openbios/forth/device/pathres.fs new file mode 100644 index 000000000..a185b95a1 --- /dev/null +++ b/qemu/roms/openbios/forth/device/pathres.fs @@ -0,0 +1,522 @@ +\ tag: Path resolution +\ +\ this code implements IEEE 1275-1994 path resolution +\ +\ Copyright (C) 2003 Samuel Rydh +\ +\ See the file "COPYING" for further information about +\ the copyright and warranty status of this work. +\ + +0 value interpose-ph +0 0 create interpose-args , , + +: expand-alias ( alias-addr alias-len -- exp-addr exp-len expanded? ) + 2dup + " /aliases" find-dev 0= if 2drop false exit then + get-package-property if + false + else + 2swap 2drop + \ drop trailing 0 from string + dup if 1- then + true + then +; + +\ +\ 4.3.1 Resolve aliases +\ + +\ the returned string is allocated with alloc-mem +: pathres-resolve-aliases ( path-addr path-len -- path-addr path-len ) + over c@ 2f <> if + 200 here + >r \ abuse dictionary for temporary storage + + \ If the pathname does not begin with "/", and its first node name + \ component is an alias, replace the alias with its expansion. + ascii / split-before \ (PATH_NAME, "/") -> (TAIL HEAD) + ascii : split-before \ (HEAD, ":") -> (ALIAS_ARGS AL_NAME) + expand-alias ( TAIL ALIAS_ARGS EXP_ALIAS_NAME expanded? ) + if + 2 pick 0<> if \ If ALIAS_ARGS is not empty + ascii / split-after \ (ALIAS_NAME, "/") -> (AL_TAIL AL_HEAD/) + 2swap ( TAIL AL_HEAD/ AL_TAIL ) + ascii : split-before \ (AL_TAIL, ":") -> (DEAD_ARGS AL_TAIL) + 2swap 2drop ( TAIL AL_ARGS AL_HEAD ALIAS_TAIL ) + 2swap ( TAIL AL_ARGS AL_TAIL AL_HEAD ) + r> tmpstrcat tmpstrcat >r + else + 2swap 2drop \ drop ALIAS_ARGS + then + r> tmpstrcat drop + else + \ put thing back together again + r> tmpstrcat tmpstrcat drop + then + then + + strdup + ( path-addr path-len ) +; + +\ +\ search struct +\ + +struct ( search information ) + 2 cells field >si.path + 2 cells field >si.arguments + 2 cells field >si.unit_addr + 2 cells field >si.node_name + 2 cells field >si.free_me + 4 cells field >si.unit_phys + /n field >si.unit_phys_len + /n field >si.save-ihandle + /n field >si.save-phandle + /n field >si.top-ihandle + /n field >si.top-opened \ set after successful open + /n field >si.child \ node to match +constant sinfo.size + + +\ +\ 4.3.6 node name match criteria +\ + +: match-nodename ( childname len sinfo -- match? ) + >r + 2dup r@ >si.node_name 2@ + ( [childname] [childname] [nodename] ) + strcmp 0= if r> 3drop true exit then + + \ does NODE_NAME contain a comma? + r@ >si.node_name 2@ ascii , strchr + if r> 3drop false exit then + + ( [childname] ) + ascii , left-split 2drop r@ >si.node_name 2@ + r> drop + strcmp if false else true then +; + + +\ +\ 4.3.4 exact match child node +\ + +\ If NODE_NAME is not empty, make sure it matches the name property +: common-match ( sinfo -- ) + >r + \ a) NODE_NAME nonempty + r@ >si.node_name 2@ nip if + " name" r@ >si.child @ get-package-property if -1 throw then + \ name is supposed to be null-terminated + dup 0> if 1- then + \ exit if NODE_NAME does not match + r@ match-nodename 0= if -2 throw then + then + r> drop +; + +: (exact-match) ( sinfo -- ) + >r + \ a) If NODE_NAME is not empty, make sure it matches the name property + r@ common-match + + \ b) UNIT_PHYS nonempty? + r@ >si.unit_phys_len @ /l* ?dup if + \ check if unit_phys matches + " reg" r@ >si.child @ get-package-property if -3 throw then + ( unitbytes propaddr proplen ) + rot r@ >si.unit_phys -rot + ( propaddr unit_phys proplen unitbytes ) + swap over < if -4 throw then + comp if -5 throw then + else + \ c) both NODE_NAME and UNIT_PHYS empty? + r@ >si.node_name 2@ nip 0= if -6 throw then + then + + r> drop +; + +: exact-match ( sinfo -- match? ) + ['] (exact-match) catch if drop false exit then + true +; + +\ +\ 4.3.5 wildcard match child node +\ + +: (wildcard-match) ( sinfo -- match? ) + >r + \ a) If NODE_NAME is not empty, make sure it matches the name property + r@ common-match + + \ b) Fail if "reg" property exist + " reg" r@ >si.child @ get-package-property 0= if -7 throw then + + \ c) Fail if both NODE_NAME and UNIT_ADDR are both empty + r@ >si.unit_phys_len @ + r@ >si.node_name 2@ nip + or 0= if -1 throw then + + \ SUCCESS + r> drop +; + +: wildcard-match ( sinfo -- match? ) + ['] (wildcard-match) catch if drop false exit then + true +; + + +\ +\ 4.3.3 match child node +\ + +\ used if package lacks a decode-unit method +: def-decode-unit ( str len -- unitaddr ... ) + parse-hex +; + +: get-decode-unit-xt ( phandle -- xt ) + " decode-unit" rot find-method + 0= if ['] def-decode-unit then +; + +: find-child ( sinfo -- phandle ) + >r + \ decode unit address string + r@ >si.unit_addr 2@ dup if + ( str len ) + active-package get-decode-unit-xt + depth 3 - >r execute depth r@ - r> swap + ( ... a_lo ... a_hi olddepth n ) + 4 min 0 max + dup r@ >si.unit_phys_len ! + ( ... a_lo ... a_hi olddepth n ) + r@ >si.unit_phys >r + begin 1- dup 0>= while + rot r> dup la1+ >r l!-be + repeat + r> 2drop + depth! + else + 2drop + \ clear unit_phys + 0 r@ >si.unit_phys_len ! + \ r@ >si.unit_phys 4 cells 0 fill + then + + ( R: sinfo ) + ['] exact-match + begin dup while + active-package >dn.child @ + begin ?dup while + dup r@ >si.child ! + ( xt phandle R: sinfo ) + r@ 2 pick execute if 2drop r> >si.child @ exit then + >dn.peer @ + repeat + ['] exact-match = if ['] wildcard-match else 0 then + repeat + + -99 throw +; + + +\ +\ 4.3.2 Create new linked instance procedure +\ + +: link-one ( sinfo -- ) + >r + active-package create-instance + dup 0= if -99 throw then + + \ change instance parent + r@ >si.top-ihandle @ over >in.my-parent ! + dup r@ >si.top-ihandle ! + to my-self + + \ b) set my-args field + r@ >si.arguments 2@ strdup my-self >in.arguments 2! + + \ e) set my-unit field + r@ >si.unit_addr 2@ nip if + \ copy UNIT_PHYS to the my-unit field + r@ >si.unit_phys my-self >in.my-unit 4 cells move + else + \ set unit-addr from reg property + " reg" active-package get-package-property 0= if + \ ( ihandle prop proplen ) + \ copy address to my-unit + 4 cells min my-self >in.my-unit swap move + else + \ clear my-unit + my-self >in.my-unit 4 cells 0 fill + then + then + + \ top instance has not been opened (yet) + false r> >si.top-opened ! +; + +: invoke-open ( sinfo -- ) + " open" my-self ['] $call-method + catch if 3drop false then + 0= if -99 throw then + + true swap >si.top-opened ! +; + +\ +\ 4.3.7 Handle interposers procedure (supplement) +\ + +: handle-interposers ( sinfo -- ) + >r + begin + interpose-ph ?dup + while + 0 to interpose-ph + active-package swap active-package! + + \ clear unit address and set arguments + 0 0 r@ >si.unit_addr 2! + interpose-args 2@ r@ >si.arguments 2! + r@ link-one + true my-self >in.interposed ! + interpose-args 2@ free-mem + r@ invoke-open + + active-package! + repeat + + r> drop +; + +\ +\ 4.3.1 Path resolution procedure +\ + +\ close-dev ( ihandle -- ) +\ +: close-dev + begin + dup + while + dup >in.my-parent @ + swap close-package + repeat + drop +; + +: path-res-cleanup ( sinfo close? ) + + \ tear down all instances if close? is set + if + dup >si.top-opened @ if + dup >si.top-ihandle @ + ?dup if close-dev then + else + dup >si.top-ihandle @ dup + ( sinfo ihandle ihandle ) + dup if >in.my-parent @ swap then + ( sinfo parent ihandle ) + ?dup if destroy-instance then + ?dup if close-dev then + then + then + + \ restore active-package and my-self + dup >si.save-ihandle @ to my-self + dup >si.save-phandle @ active-package! + + \ free any allocated memory + dup >si.free_me 2@ free-mem + sinfo.size free-mem +; + +: (path-resolution) ( context sinfo -- ) + >r r@ >si.path 2@ + ( context pathstr pathlen ) + + \ this allocates a copy of the string + pathres-resolve-aliases + 2dup r@ >si.free_me 2! + + \ If the pathname, after possible alias expansion, begins with "/", + \ begin the search at the root node. Otherwise, begin at the active + \ package. + + dup if \ make sure string is not empty + over c@ 2f = if + swap char+ swap /c - \ Remove the "/" from PATH_NAME. + \ Set the active package to the root node. + device-tree @ active-package! + then + then + + r@ >si.path 2! + 0 0 r@ >si.unit_addr 2! + 0 0 r@ >si.arguments 2! + 0 r@ >si.top-ihandle ! + + \ If there is no active package, exit this procedure, returning false. + ( context ) + active-package 0= if -99 throw then + + \ Begin the creation of an instance chain. + \ NOTE--If, at this step, the active package is not the root node and + \ we are in open-dev or execute-device-method contexts, the instance + \ chain that results from the path resolution process may be incomplete. + + active-package swap + ( virt-active-node context ) + begin + r@ >si.path 2@ nip \ nonzero path? + while + \ ( active-node context ) + \ is this open-dev or execute-device-method context? + dup if + r@ link-one + over active-package <> my-self >in.interposed ! + r@ invoke-open + r@ handle-interposers + then + over active-package! + + r@ >si.path 2@ ( PATH ) + + ascii / left-split ( PATH COMPONENT ) + ascii : left-split ( PATH ARGS NODE_ADDR ) + ascii @ left-split ( PATH ARGS UNIT_ADDR NODE_NAME ) + + r@ >si.node_name 2! + r@ >si.unit_addr 2! + r@ >si.arguments 2! + r@ >si.path 2! + + ( virt-active-node context ) + + \ 4.3.1 i) pathname has a leading %? + r@ >si.node_name 2@ 2dup 2dup ascii % strchr nip = if + 1- swap 1+ swap r@ >si.node_name 2! + " /packages" find-dev drop active-package! + r@ find-child + else + 2drop + nip r@ find-child swap over + ( new-node context new-node ) + then + + \ (optional: open any nodes between parent and child ) + + active-package! + repeat + + ( virt-active-node type ) + dup if r@ link-one then + 1 = if + dup active-package <> my-self >in.interposed ! + r@ invoke-open + r@ handle-interposers + then + active-package! + + r> drop +; + +: path-resolution ( context path-addr path-len -- sinfo true | false ) + \ allocate and clear the search block + sinfo.size alloc-mem >r + r@ sinfo.size 0 fill + + \ store path + r@ >si.path 2! + + \ save ihandle and phandle + my-self r@ >si.save-ihandle ! + active-package r@ >si.save-phandle ! + + \ save context (if we take an exception) + dup + + r@ ['] (path-resolution) + catch ?dup if + ( context xxx xxx error ) + r> true path-res-cleanup + + \ rethrow everything except our "cleanup throw" + dup -99 <> if throw then + 3drop + + \ ( context ) throw an exception if this is find-device context + if false else -22 throw then + exit + then + + \ ( context ) + drop r> true + ( sinfo true ) +; + + +: open-dev ( dev-str dev-len -- ihandle | 0 ) + 1 -rot path-resolution 0= if false exit then + + ( sinfo ) + my-self swap + false path-res-cleanup + + ( ihandle ) +; + +: execute-device-method +( ... dev-str dev-len met-str met-len -- ... false | ?? true ) + 2swap + 2 -rot path-resolution 0= if 2drop false exit then + ( method-str method-len sinfo ) + >r + my-self ['] $call-method catch + if 3drop false else true then + r> true path-res-cleanup +; + +: find-device ( dev-str dev-len -- ) + 2dup " .." strcmp 0= if + 2drop + active-package dup if >dn.parent @ then + \ ".." in root note? + dup 0= if -22 throw then + active-package! + exit + then + 0 -rot path-resolution 0= if false exit then + ( sinfo ) + active-package swap + true path-res-cleanup + active-package! +; + +\ find-device, but without side effects +: (find-dev) ( dev-str dev-len -- phandle true | false ) + active-package -rot + ['] find-device catch if 3drop false exit then + active-package swap active-package! true +; + +\ Tuck on a node at the end of the chain being created. +\ This implementation follows the interpose recommended practice +\ (v0.2 draft). + +: interpose ( arg-str arg-len phandle -- ) + to interpose-ph + strdup interpose-args 2! +; + +['] (find-dev) to find-dev diff --git a/qemu/roms/openbios/forth/device/preof.fs b/qemu/roms/openbios/forth/device/preof.fs new file mode 100644 index 000000000..131beacd3 --- /dev/null +++ b/qemu/roms/openbios/forth/device/preof.fs @@ -0,0 +1,49 @@ +\ tag: historical and pre open firmware fcode functions +\ +\ this code implements IEEE 1275-1994 ch. H.2.2 and 5.3.1.1.1 +\ +\ Copyright (C) 2003 Stefan Reinauer +\ +\ See the file "COPYING" for further information about +\ the copyright and warranty status of this work. +\ + +\ H.2.2 Non-implemented FCodes +\ Pre-Open Firmware systems assigned the following FCode numbers, +\ but the functions were not supported. These FCode numbers stay +\ reserved to avoid confusion. + +: non-implemented + ." Non-implemented historical or pre-Open Firmware FCode occured." cr + end0 + ; + +: adr-mask non-implemented ; +: b(code) non-implemented ; +: 4-byte-id non-implemented ; +: convert non-implemented ; +: frame-buffer-busy? non-implemented ; +: poll-packet non-implemented ; +: return-buffer non-implemented ; +: set-token-table non-implemented ; +: set-table non-implemented ; +: xmit-packet non-implemented ; + +\ historical fcode words defined by 5.3.1.1.1 + +30000 constant fcode-version \ this opcode is considered obsolete +30000 constant firmware-version \ this opcode is considered obsolete + +\ historical - Returns the type of processor. +\ 0x5 indicates SPARC, other values are not used. +\ ?? this could be set by the kernel during bootstrap. +deadbeef constant processor-type ( -- processor-type ) + +: memmap non-implemented ; +: >physical non-implemented ; +: my-params non-implemented ; +: intr non-implemented ; +: driver non-implemented ; +: group-code non-implemented ; +: probe non-implemented ; +: probe-virtual non-implemented ; diff --git a/qemu/roms/openbios/forth/device/property.fs b/qemu/roms/openbios/forth/device/property.fs new file mode 100644 index 000000000..1d54e3ec3 --- /dev/null +++ b/qemu/roms/openbios/forth/device/property.fs @@ -0,0 +1,335 @@ +\ tag: Property management +\ +\ this code implements IEEE 1275-1994 ch. 5.3.5 +\ +\ Copyright (C) 2003 Stefan Reinauer +\ +\ See the file "COPYING" for further information about +\ the copyright and warranty status of this work. +\ + +\ small helpers.. these should go elsewhere. +: bigendian? + 10 here ! here c@ 10 <> + ; + +: l!-be ( val addr ) + 3 bounds swap do + dup ff and i c! + 8 rshift + -1 +loop + drop + ; + +: l@-be ( addr ) + 0 swap 4 bounds do + i c@ swap 8 << or + loop + ; + +\ allocate n bytes for device tree information +\ until I know where to put this, I put it in the +\ dictionary. + +: alloc-tree ( n -- addr ) + dup >r \ save len + here swap allot + dup r> 0 fill \ clear memory + ; + +: align-tree ( -- ) + null-align + ; + +: no-active true abort" no active package." ; + +\ +\ 5.3.5 Property management +\ + +\ Helper function +: find-property ( name len phandle -- &&prop|0 ) + >dn.properties + begin + dup @ + while + dup @ >prop.name @ ( name len prop propname ) + 2over comp0 ( name len prop equal? ) + 0= if nip nip exit then + >prop.next @ + repeat + ( name len false ) + 3drop false + ; + +\ From package (5.3.4.1) +: next-property +( previous-str previous-len phandle -- false | name-str name-len true ) + >r + 2dup 0= swap 0= or if + 2drop r> >dn.properties @ + else + r> find-property dup if @ then + dup if >prop.next @ then + then + + ?dup if + >prop.name @ dup cstrlen true + ( phandle name-str name-len true ) + else + false + then +; + + +\ +\ 5.3.5.4 Property value access +\ + +\ Return value for name string property in package phandle. +: get-package-property + ( name-str name-len phandle -- true | prop-addr prop-len false ) + find-property ?dup if + @ dup >prop.addr @ + swap >prop.len @ + false + else + true + then + ; + +\ Return value for given property in the current instance or its parents. +: get-inherited-property + ( name-str name-len -- true | prop-addr prop-len false ) + my-self + begin + ?dup + while + dup >in.device-node @ ( str len ihandle phandle ) + 2over rot find-property ?dup if + @ + ( str len ihandle prop ) + nip nip nip ( prop ) + dup >prop.addr @ swap >prop.len @ + false + exit + then + ( str len ihandle ) + >in.my-parent @ + repeat + 2drop + true + ; + +\ Return value for given property in this package. +: get-my-property ( name-str name-len -- true | prop-addr prop-len false ) + my-self >in.device-node @ ( -- phandle ) + get-package-property + ; + + +\ +\ 5.3.5.2 Property array decoding +\ + +: decode-int ( prop-addr1 prop-len1 -- prop-addr2 prop-len2 n ) + dup 0> if + dup 4 min >r ( addr1 len1 R:minlen ) + over r@ + swap ( addr1 addr2 len1 R:minlen ) + r> - ( addr1 addr2 len2 ) + rot l@-be + else + 0 + then + ; + +\ HELPER: get #address-cell value (from parent) +\ Legal values are 1..4 (we may optionally support longer addresses) +: my-#acells ( -- #address-cells ) + my-self ?dup if >in.device-node @ else active-package then + ?dup if >dn.parent @ then + ?dup if + " #address-cells" rot get-package-property if 2 exit then + \ we don't have to support more than 4 (and 0 is illegal) + decode-int nip nip 4 min 1 max + else + 2 + then +; + +\ HELPER: get #size-cells value (from parent) +: my-#scells ( -- #size-cells ) + my-self ?dup if >in.device-node @ else active-package then + ?dup if >dn.parent @ then + ?dup if + " #size-cells" rot get-package-property if 1 exit then + decode-int nip nip + else + 1 + then +; + +: decode-string ( prop-addr1 prop-len1 -- prop-addr2 prop-len2 str len ) + dup 0> if + 2dup bounds \ check property for 0 bytes + 0 -rot \ initial string len is 0 + do + i c@ 0= if + leave + then + 1+ + loop ( prop-addr1 prop-len1 len ) + 1+ rot >r ( prop-len1 len R: prop-addr1 ) + over min 2dup - ( prop-len1 nlen prop-len2 R: prop-addr1 ) + r@ 2 pick + ( prop-len1 nlen prop-len2 prop-addr2 ) + >r >r >r ( R: prop-addr1 prop-addr2 prop-len2 nlen ) + drop + r> r> r> ( nlen prop-len2 prop-addr2 ) + -rot swap 1- ( prop-addr2 prop-len2 nlen ) + r> swap ( prop-addr2 prop-len2 str len ) + else + 0 0 + then + ; + +: decode-bytes ( addr1 len1 #bytes -- addr len2 addr1 #bytes ) + tuck - ( addr1 #bytes len2 ) + r> 2dup + ( addr1 #bytes addr2 ) ( R: len2 ) + r> 2swap + ; + +: decode-phys + ( prop-addr1 prop-len1 -- prop-addr2 prop-len2 phys.lo ... phys.hi ) + my-#acells 0 ?do + decode-int r> r> rot >r >r >r + loop + my-#acells 0 ?do + r> r> r> -rot >r >r + loop + ; + + +\ +\ 5.3.5.1 Property array encoding +\ + +: encode-int ( n -- prop-addr prop-len ) + /l alloc-tree tuck l!-be /l + ; + +: encode-string ( str len -- prop-addr prop-len ) + \ we trust len here. should probably check string? + tuck char+ alloc-tree ( len str prop-addr ) + tuck 3 pick move ( len prop-addr ) + swap 1+ + ; + +: encode-bytes ( data-addr data-len -- prop-addr prop-len ) + tuck alloc-tree ( len str prop-addr ) + tuck 3 pick move + swap + ; + +: encode+ ( prop-addr1 prop-len1 prop-addr2 prop-len2 -- prop-addr3 prop-len3 ) + nip + + ; + +: encode-phys ( phys.lo ... phys.hi -- prop-addr prop-len ) + encode-int my-#acells 1- 0 ?do + rot encode-int encode+ + loop + ; + +defer sbus-intr>cpu ( sbus-intr# -- cpu-intr# ) +: (sbus-intr>cpu) ." No SBUS present on this machine." cr ; +['] (sbus-intr>cpu) to sbus-intr>cpu + + +\ +\ 5.3.5.3 Property declaration +\ + +: (property) ( prop-addr prop-len name-str name-len dnode -- ) + >r 2dup r@ + align-tree + find-property ?dup if + \ If a property with that property name already exists in the + \ package in which the property would be created, replace its + \ value with the new value. + @ r> drop \ don't need the device node anymore. + -rot 2drop tuck \ drop property name + >prop.len ! \ overwrite old values + >prop.addr ! + exit + then + + ( prop-addr prop-len name-str name-len R: dn ) + prop-node.size alloc-tree + dup >prop.next off + + dup r> >dn.properties + begin dup @ while @ >prop.next repeat ! + >r + + ( prop-addr prop-len name-str name-len R: prop ) + + \ create copy of property name + dup char+ alloc-tree + dup >r swap move r> + ( prop-addr prop-len new-name R: prop ) + r@ >prop.name ! + r@ >prop.len ! + r> >prop.addr ! + align-tree + ; + +: property ( prop-addr prop-len name-str name-len -- ) + my-self ?dup if + >in.device-node @ + else + active-package + then + dup if + (property) + else + no-active + then + ; + +: (delete-property) ( name len dnode -- ) + find-property ?dup if + dup @ >prop.next @ swap ! + \ maybe we should try to reclaim the space? + then +; + +: delete-property ( name-str name-len -- ) + active-package ?dup if + (delete-property) + else + 2drop + then + ; + +\ Create the "name" property; value is indicated string. +: device-name ( str len -- ) + encode-string " name" property + ; + +\ Create "device_type" property, value is indicated string. +: device-type ( str len -- ) + encode-string " device_type" property + ; + +\ Create the "reg" property with the given values. +: reg ( phys.lo ... phys.hi size -- ) + >r ( phys.lo ... phys.hi ) encode-phys ( addr len ) + r> ( addr1 len1 size ) encode-int ( addr1 len1 addr2 len2 ) + encode+ ( addr len ) + " reg" property + ; + +\ Create the "model" property; value is indicated string. +: model ( str len -- ) + encode-string " model" property + ; diff --git a/qemu/roms/openbios/forth/device/romfont.bin b/qemu/roms/openbios/forth/device/romfont.bin Binary files differnew file mode 100644 index 000000000..0b60b6fb4 --- /dev/null +++ b/qemu/roms/openbios/forth/device/romfont.bin diff --git a/qemu/roms/openbios/forth/device/structures.fs b/qemu/roms/openbios/forth/device/structures.fs new file mode 100644 index 000000000..14dd881e5 --- /dev/null +++ b/qemu/roms/openbios/forth/device/structures.fs @@ -0,0 +1,54 @@ +\ tag: device interface structures +\ +\ this code implements data structures used by the +\ IEEE 1275-1994 Open Firmware Device Interface. +\ +\ Copyright (C) 2003 Stefan Reinauer +\ +\ See the file "COPYING" for further information about +\ the copyright and warranty status of this work. +\ + +\ this file contains the struct definitions for the following +\ device tree structures: +\ device-node +\ active-package +\ property +\ instance + + +struct ( instance ) + /n field >in.instance-data \ must go first + /n field >in.alloced-size \ alloced size + /n field >in.device-node + /n field >in.my-parent + /n field >in.interposed + 4 cells field >in.my-unit + 2 cells field >in.arguments + \ instance-data should be null during packet initialization + \ this diverts access to instance variables to the dictionary +constant inst-node.size + +struct ( device node ) + /n field >dn.isize \ instance size (must go first) + /n field >dn.parent + /n field >dn.child + /n field >dn.peer + /n field >dn.properties + /n field >dn.methods + /n field >dn.priv-methods + /n field >dn.#acells + /n field >dn.probe-addr + inst-node.size field >dn.itemplate +constant dev-node.size + +struct ( property ) + /n field >prop.next + /n field >prop.name + /n field >prop.addr + /n field >prop.len +constant prop-node.size + +struct ( active package ) + /n field >ap.device-str +constant active-package.size diff --git a/qemu/roms/openbios/forth/device/table.fs b/qemu/roms/openbios/forth/device/table.fs new file mode 100644 index 000000000..5c58f2d9d --- /dev/null +++ b/qemu/roms/openbios/forth/device/table.fs @@ -0,0 +1,462 @@ +\ tag: FCode table setup +\ +\ this code implements an fcode evaluator +\ as described in IEEE 1275-1994 +\ +\ Copyright (C) 2003 Stefan Reinauer +\ +\ See the file "COPYING" for further information about +\ the copyright and warranty status of this work. +\ + +hex + +: undefined-fcode ." undefined fcode word." cr ; +: reserved-fcode ." reserved fcode word." cr ; + +: ['], ( <word> -- ) + ' , +; + +: n['], ( n <word> -- ) + ' swap 0 do + dup , + loop + drop +; + +\ the table used +create fcode-master-table + ['], end0 + f n['], reserved-fcode + ['], b(lit) + ['], b(') + ['], b(") + ['], bbranch + ['], b?branch + ['], b(loop) + ['], b(+loop) + ['], b(do) + ['], b(?do) + ['], i + ['], j + ['], b(leave) + ['], b(of) + ['], execute + ['], + + ['], - + ['], * + ['], / + ['], mod + ['], and + ['], or + ['], xor + ['], invert + ['], lshift + ['], rshift + ['], >>a + ['], /mod + ['], u/mod + ['], negate + ['], abs + ['], min + ['], max + ['], >r + ['], r> + ['], r@ + ['], exit + ['], 0= + ['], 0<> + ['], 0< + ['], 0<= + ['], 0> + ['], 0>= + ['], < + ['], > + ['], = + ['], <> + ['], u> + ['], u<= + ['], u< + ['], u>= + ['], >= + ['], <= + ['], between + ['], within + ['], drop + ['], dup + ['], over + ['], swap + ['], rot + ['], -rot + ['], tuck + ['], nip + ['], pick + ['], roll + ['], ?dup + ['], depth + ['], 2drop + ['], 2dup + ['], 2over + ['], 2swap + ['], 2rot + ['], 2/ + ['], u2/ + ['], 2* + ['], /c + ['], /w + ['], /l + ['], /n + ['], ca+ + ['], wa+ + ['], la+ + ['], na+ + ['], char+ + ['], wa1+ + ['], la1+ + ['], cell+ + ['], chars + ['], /w* + ['], /l* + ['], cells + ['], on + ['], off + ['], +! + ['], @ + ['], l@ + ['], w@ + ['], <w@ + ['], c@ + ['], ! + ['], l! + ['], w! + ['], c! + ['], 2@ + ['], 2! + ['], move + ['], fill + ['], comp + ['], noop + ['], lwsplit + ['], wljoin + ['], lbsplit + ['], bljoin + ['], wbflip + ['], upc + ['], lcc + ['], pack + ['], count + ['], body> + ['], >body + ['], fcode-revision + ['], span + ['], unloop + ['], expect + ['], alloc-mem + ['], free-mem + ['], key? + ['], key + ['], emit + ['], type + ['], (cr + ['], cr + ['], #out + ['], #line + ['], hold + ['], <# + ['], u#> + ['], sign + ['], u# + ['], u#s + ['], u. + ['], u.r + ['], . + ['], .r + ['], .s + ['], base + ['], convert \ reserved (compatibility) + ['], $number + ['], digit + ['], -1 + ['], 0 + ['], 1 + ['], 2 + ['], 3 + ['], bl + ['], bs + ['], bell + ['], bounds + ['], here + ['], aligned + ['], wbsplit + ['], bwjoin + ['], b(<mark) + ['], b(>resolve) + ['], set-token-table + ['], set-table + ['], new-token + ['], named-token + ['], b(:) + ['], b(value) + ['], b(variable) + ['], b(constant) + ['], b(create) + ['], b(defer) + ['], b(buffer:) + ['], b(field) + ['], b(code) + ['], instance + ['], reserved-fcode + ['], b(;) + ['], b(to) + ['], b(case) + ['], b(endcase) + ['], b(endof) + ['], # + ['], #s + ['], #> + ['], external-token + ['], $find + ['], offset16 + ['], evaluate + ['], reserved-fcode + ['], reserved-fcode + ['], c, + ['], w, + ['], l, + ['], , + ['], um* + ['], um/mod + ['], reserved-fcode + ['], reserved-fcode + ['], d+ + ['], d- + ['], get-token + ['], set-token + ['], state + ['], compile, + ['], behavior + 11 n['], reserved-fcode + ['], start0 + ['], start1 + ['], start2 + ['], start4 + 8 n['], reserved-fcode + ['], ferror + ['], version1 + ['], 4-byte-id + ['], end1 + ['], reserved-fcode + ['], dma-alloc + ['], my-address + ['], my-space + ['], memmap + ['], free-virtual + ['], >physical + 8 n['], reserved-fcode + ['], my-params + ['], property + ['], encode-int + ['], encode+ + ['], encode-phys + ['], encode-string + ['], encode-bytes + ['], reg + ['], intr + ['], driver + ['], model + ['], device-type + ['], parse-2int + ['], is-install + ['], is-remove + ['], is-selftest + ['], new-device + ['], diagnostic-mode? + ['], display-status + ['], memory-test-suite + ['], group-code + ['], mask + ['], get-msecs + ['], ms + ['], finish-device + ['], decode-phys \ 128 + ['], push-package + ['], pop-package + ['], interpose \ extension (recommended practice) + 4 n['], reserved-fcode + ['], map-low + ['], sbus-intr>cpu + 1e n['], reserved-fcode + ['], #lines + ['], #columns + ['], line# + ['], column# + ['], inverse? + ['], inverse-screen? + ['], frame-buffer-busy? + ['], draw-character + ['], reset-screen + ['], toggle-cursor + ['], erase-screen + ['], blink-screen + ['], invert-screen + ['], insert-characters + ['], delete-characters + ['], insert-lines + ['], delete-lines + ['], draw-logo + ['], frame-buffer-adr + ['], screen-height + ['], screen-width + ['], window-top + ['], window-left + 3 n['], reserved-fcode + ['], default-font + ['], set-font + ['], char-height + ['], char-width + ['], >font + ['], fontbytes + 10 n['], reserved-fcode \ fb1 words + ['], fb8-draw-character + ['], fb8-reset-screen + ['], fb8-toggle-cursor + ['], fb8-erase-screen + ['], fb8-blink-screen + ['], fb8-invert-screen + ['], fb8-insert-characters + ['], fb8-delete-characters + ['], fb8-insert-lines + ['], fb8-delete-lines + ['], fb8-draw-logo + ['], fb8-install + 4 n['], reserved-fcode \ reserved + 7 n['], reserved-fcode \ VME-bus support + 9 n['], reserved-fcode \ reserved + ['], return-buffer + ['], xmit-packet + ['], poll-packet + ['], reserved-fcode + ['], mac-address + 5c n['], reserved-fcode \ 1a5-200 reserved + ['], device-name + ['], my-args + ['], my-self + ['], find-package + ['], open-package + ['], close-package + ['], find-method + ['], call-package + ['], $call-parent + ['], my-parent + ['], ihandle>phandle + ['], reserved-fcode + ['], my-unit + ['], $call-method + ['], $open-package + ['], processor-type + ['], firmware-version + ['], fcode-version + ['], alarm + ['], (is-user-word) + ['], suspend-fcode + ['], abort + ['], catch + ['], throw + ['], user-abort + ['], get-my-property + ['], decode-int + ['], decode-string + ['], get-inherited-property + ['], delete-property + ['], get-package-property + ['], cpeek + ['], wpeek + ['], lpeek + ['], cpoke + ['], wpoke + ['], lpoke + ['], lwflip + ['], lbflip + ['], lbflips + ['], adr-mask + 4 n['], reserved-fcode \ 22a-22d +64bit? [IF] + ['], (rx@) + ['], (rx!) +[ELSE] + 2 n['], reserved-fcode \ 22e-22f +[THEN] + ['], rb@ + ['], rb! + ['], rw@ + ['], rw! + ['], rl@ + ['], rl! + ['], wbflips + ['], lwflips + ['], probe + ['], probe-virtual + ['], reserved-fcode + ['], child + ['], peer + ['], next-property + ['], byte-load + ['], set-args + ['], left-parse-string \ 240 +64bit? [IF] + ['], bxjoin + ['], <l@ + ['], lxjoin + ['], wxjoin + ['], x, + ['], x@ + ['], x! + ['], /x + ['], /x* +\ ['], /xa+ +\ ['], /xa1+ + ['], xbflip + ['], xbflips + ['], xbsplit + ['], xlflip + ['], xlflips + ['], xlsplit + ['], xwflip + ['], xwflips + ['], xwsplit +[ELSE] + 7 n['], reserved-fcode \ 241-247 (Part of IEEE1275 64-bit draft standard) + ['], /x + c n['], reserved-fcode \ 249-254 (Part of IEEE1275 64-bit draft standard) +[THEN] + + +here fcode-master-table - constant fcode-master-table-size + + +: nreserved ( fcode-table-ptr first last xt -- ) + -rot 1+ swap do + 2dup swap i cells + ! + loop + 2drop +; + +:noname + 800 cells alloc-mem to fcode-sys-table + + fcode-sys-table + dup 0 5ff ['] reserved-fcode nreserved \ built-in fcodes + dup 600 7ff ['] undefined-fcode nreserved \ vendor fcodes + + \ copy built-in fcodes + fcode-master-table swap fcode-master-table-size move +; initializer + +: (init-fcode-table) ( -- ) + fcode-sys-table fcode-table 800 cells move + \ clear local fcodes + fcode-table 800 fff ['] undefined-fcode nreserved +; + +['] (init-fcode-table) to init-fcode-table diff --git a/qemu/roms/openbios/forth/device/terminal.fs b/qemu/roms/openbios/forth/device/terminal.fs new file mode 100644 index 000000000..24b2d10c9 --- /dev/null +++ b/qemu/roms/openbios/forth/device/terminal.fs @@ -0,0 +1,302 @@ +\ tag: terminal emulation +\ +\ this code implements IEEE 1275-1994 ANNEX B +\ +\ Copyright (C) 2003 Stefan Reinauer +\ +\ See the file "COPYING" for further information about +\ the copyright and warranty status of this work. +\ + +0 value (escseq) +10 buffer: (sequence) + +: (match-number) ( x y [1|2] [1|2] -- x [z] ) + 2dup = if \ 1 1 | 2 2 + drop exit + then + 2dup > if + 2drop drop 1 exit + then + 2drop 0 + ; + +: (esc-number) ( maxchar -- ?? ?? num ) + >r depth >r ( R: depth maxchar ) + 0 (sequence) 2+ (escseq) 2- ( 0 seq+2 seqlen-2 ) + \ if numerical, scan until non-numerical + 0 ?do + ( 0 seq+2 ) + dup i + c@ a + digit if + ( 0 ptr n ) + rot a * + ( ptr val ) + swap + else + ( 0 ptr asc ) + ascii ; = if + 0 swap + else + drop leave + then + then + + loop + depth r> - r> + 0 to (escseq) + (match-number) + ; + +: (match-seq) + (escseq) 1- (sequence) + c@ \ get last character in sequence + \ dup draw-character + case + ascii A of \ CUU - cursor up + 1 (esc-number) + 0> if + 1 max + else + 1 + then + negate line# + + 0 max to line# + endof + ascii B of \ CUD - cursor down + 1 (esc-number) + 0> if + 1 max + line# + + #lines 1- min to line# + then + endof + ascii C of \ CUF - cursor forward + 1 (esc-number) + 0> if + 1 max + column# + + #columns 1- min to column# + then + endof + ascii D of \ CUB - cursor backward + 1 (esc-number) + 0> if + 1 max + negate column# + + 0 max to column# + then + endof + ascii E of \ Cursor next line (CNL) + \ FIXME - check agains ANSI3.64 + 1 (esc-number) + 0> if + 1 max + line# + + #lines 1- min to line# + then + 0 to column# + endof + ascii f of + 2 (esc-number) + case + 2 of + 1- #columns 1- min to column# + 1- #lines 1- min to line# + endof + 1 of + 0 to column# + 1- #lines 1- min to line# + endof + 0 of + 0 to column# + 0 to line# + drop + endof + endcase + endof + ascii H of + 2 (esc-number) + case + 2 of + 1- #columns 1- min to column# + 1- #lines 1- min to line# + endof + 1 of + 0 to column# + 1- #lines 1- min to line# + endof + 0 of + 0 to column# + 0 to line# + drop + endof + endcase + endof + ascii J of + 0 to (escseq) + #columns column# - delete-characters + #lines line# - delete-lines + endof + ascii K of + 0 to (escseq) + #columns column# - delete-characters + endof + ascii L of + 1 (esc-number) + 0> if + 1 max + insert-lines + then + endof + ascii M of + 1 (esc-number) + 1 = if + 1 max + delete-lines + then + endof + ascii @ of + 1 (esc-number) + 1 = if + 1 max + insert-characters + then + endof + ascii P of + 1 (esc-number) + 1 = if + 1 max + delete-characters + then + endof + ascii m of + 1 (esc-number) + 1 = if + 7 = if + true to inverse? + else + false to inverse? + then + then + endof + ascii p of \ normal text colors + 0 to (escseq) + inverse-screen? if + false to inverse-screen? + inverse? 0= to inverse? + invert-screen + then + endof + ascii q of \ inverse text colors + 0 to (escseq) + inverse-screen? not if + true to inverse-screen? + inverse? 0= to inverse? + invert-screen + then + endof + ascii s of + \ Resets the display device associated with the terminal emulator. + 0 to (escseq) + reset-screen + endof + endcase + ; + +: (term-emit) ( char -- ) + toggle-cursor + + (escseq) 0> if + (escseq) 10 = if + 0 to (escseq) + ." overflow in esc" cr + drop + then + (escseq) 1 = if + dup ascii [ = if \ not a [ + (sequence) 1+ c! + 2 to (escseq) + else + 0 to (escseq) \ break out of ESC sequence + ." out of ESC" cr + drop \ don't print breakout character + then + toggle-cursor exit + else + (sequence) (escseq) + c! + (escseq) 1+ to (escseq) + (match-seq) + toggle-cursor exit + then + then + + case + 0 of \ NULL + toggle-cursor exit + endof + 7 of \ BEL + blink-screen + s" /screen" s" ring-bell" + execute-device-method + endof + 8 of \ BS + column# 0<> if + column# 1- to column# + toggle-cursor exit + then + endof + 9 of \ TAB + column# dup #columns = if + drop + else + 8 + -8 and ff and to column# + then + toggle-cursor exit + endof + a of \ LF + line# 1+ to line# + 0 to column# + line# #lines >= if + 0 to line# + 1 delete-lines + #lines 1- to line# + toggle-cursor exit + then + endof + b of \ VT + line# 0<> if + line# 1- to line# + then + toggle-cursor exit + endof + c of \ FF + 0 to column# 0 to line# + erase-screen + endof + d of \ CR + 0 to column# + toggle-cursor exit + endof + 1b of \ ESC + 1b (sequence) c! + 1 to (escseq) + endof + + \ draw character and advance position + column# #columns >= if + 0 to column# + line# 1+ to line# + line# #lines >= if + 0 to line# + 1 delete-lines + #lines 1- to line# + then + then + + dup draw-character + column# 1+ to column# + + endcase + toggle-cursor + ; + +['] (term-emit) to fb-emit diff --git a/qemu/roms/openbios/forth/device/tree.fs b/qemu/roms/openbios/forth/device/tree.fs new file mode 100644 index 000000000..04f85b5c1 --- /dev/null +++ b/qemu/roms/openbios/forth/device/tree.fs @@ -0,0 +1,59 @@ +\ tag: Device Tree +\ +\ this code implements IEEE 1275-1994 ch. 3.5 +\ +\ Copyright (C) 2003 Stefan Reinauer +\ +\ See the file "COPYING" for further information about +\ the copyright and warranty status of this work. +\ + + +\ root node +new-device + " OpenBiosTeam,OpenBIOS" device-name + 1 encode-int " #address-cells" property + : open true ; + : close ; + : decode-unit parse-hex ; + : encode-unit ( addr -- str len ) + pocket tohexstr + ; + +new-device + " aliases" device-name + : open true ; + : close ; +finish-device + +new-device + " openprom" device-name + " BootROM" device-type + " OpenFirmware 3" model + 0 0 " relative-addressing" property + 0 0 " supports-bootinfo" property + 1 encode-int " boot-syntax" property + + : selftest + ." OpenBIOS selftest... succeded" cr + true + ; + : open true ; + : close ; + +finish-device + +new-device + " options" device-name +finish-device + +new-device + " chosen" device-name + 0 encode-int " stdin" property + 0 encode-int " stdout" property + \ " hda1:/boot/vmunix" encode-string " bootpath" property + \ " -as" encode-string " bootargs" property +finish-device + +\ END +finish-device diff --git a/qemu/roms/openbios/forth/lib/64bit.fs b/qemu/roms/openbios/forth/lib/64bit.fs new file mode 100644 index 000000000..239ddd028 --- /dev/null +++ b/qemu/roms/openbios/forth/lib/64bit.fs @@ -0,0 +1,128 @@ +\ +\ Copyright (C) 2009 Stefan Reinauer +\ +\ See the file "COPYING" for further information about +\ the copyright and warranty status of this work. +\ + +\ Implementation of IEEE Draft Std P1275.6/D5 +\ Standard for Boot (Initialization Configuration) Firmware +\ 64 Bit Extensions + + +cell /x = constant 64bit? + +64bit? [IF] + +: 32>64 ( 32bitsigned -- 64bitsigned ) + dup 80000000 and if \ is it negative? + ffffffff00000000 or \ then set all high bits + then +; + +: 64>32 ( 64bitsigned -- 32bitsigned ) + h# ffffffff and +; + +: lxjoin ( quad.lo quad.hi -- o ) + d# 32 lshift or +; + +: wxjoin ( w.lo w.2 w.3 w.hi -- o ) + wljoin >r wljoin r> lxjoin +; + +: bxjoin ( b.lo b.2 b.3 b.4 b.5 b.6 b.7 b.hi -- o ) + bljoin >r bljoin r> lxjoin +; + +: <l@ ( qaddr -- n ) + l@ 32>64 +; + +: unaligned-x@ ( addr - o ) + dup la1+ unaligned-l@ 64>32 swap unaligned-l@ 64>32 lxjoin +; + +: unaligned-x! ( o oaddr -- ) + >r dup d# 32 rshift r@ unaligned-l! + h# ffffffff and r> la1+ unaligned-l! +; + +: x@ ( oaddr -- o ) + unaligned-x@ \ for now +; + +: x! ( o oaddr -- ) + unaligned-x! \ for now +; + +: (rx@) ( oaddr - o ) + x@ +; + +: (rx!) ( o oaddr -- ) + x! +; + +: x, ( o -- ) + here /x allot x! +; + +: /x* ( nu1 -- nu2 ) + /x * +; + +: xa+ ( addr1 index -- addr2 ) + /x* + +; + +: xa1+ ( addr1 -- addr2 ) + /x + +; + +: xlsplit ( o -- quad.lo quad.hi ) + dup h# ffffffff and swap d# 32 rshift +; + +: xwsplit ( o -- w.lo w.2 w.3 w.hi ) + xlsplit >r lwsplit r> lwsplit +; + +: xbsplit ( o -- b.lo b.2 b.3 b.4 b.5 b.6 b.7 b.hi ) + xlsplit >r lbsplit r> lbsplit +; + +: xlflip ( oct1 -- oct2 ) + xlsplit swap lxjoin +; + +: xlflips ( oaddr len -- ) + bounds ?do + i unaligned-x@ xlflip i unaligned-x! + /x +loop +; + +: xwflip ( oct1 -- oct2 ) + xlsplit lwflip swap lwflip lxjoin +; + +: xwflips ( oaddr len -- ) + bounds ?do + i unaligned-x@ xwflip i unaligned-x! /x + +loop +; + +: xbflip ( oct1 -- oct2 ) + xlsplit lbflip swap lbflip lxjoin +; + +: xbflips ( oaddr len -- ) + bounds ?do + i unaligned-x@ xbflip i unaligned-x! + /x +loop +; + +\ : b(lit) b(lit) 32>64 ; + +[THEN] diff --git a/qemu/roms/openbios/forth/lib/build.xml b/qemu/roms/openbios/forth/lib/build.xml new file mode 100644 index 000000000..34eee4072 --- /dev/null +++ b/qemu/roms/openbios/forth/lib/build.xml @@ -0,0 +1,22 @@ +<build> + <!-- + build description for openbios forth library functions + + Copyright (C) 2003-2005 by Stefan Reinauer + See the file "COPYING" for further information about + the copyright and warranty status of this work. + --> + + <dictionary name="openbios" target="forth"> + <object source="vocabulary.fs"/> + <object source="string.fs"/> + <object source="preprocessor.fs"/> + <object source="preinclude.fs" /> <!-- FIXME dependencies --> + <object source="creation.fs"/> + <object source="split.fs"/> + <object source="lists.fs"/> + <object source="64bit.fs"/> + <object source="locals.fs"/> + </dictionary> + +</build> diff --git a/qemu/roms/openbios/forth/lib/creation.fs b/qemu/roms/openbios/forth/lib/creation.fs new file mode 100644 index 000000000..c3d0db84c --- /dev/null +++ b/qemu/roms/openbios/forth/lib/creation.fs @@ -0,0 +1,52 @@ +\ tag: misc useful functions +\ +\ C bindings +\ +\ Copyright (C) 2003, 2004 Samuel Rydh +\ +\ See the file "COPYING" for further information about +\ the copyright and warranty status of this work. +\ + +\ return xt of the word just defined +: last-xt ( -- xt ) + latest @ na1+ +; + +\ ------------------------------------------------------------------------- +\ word creation +\ ------------------------------------------------------------------------- + +: $is-ibuf ( size name name-len -- xt ) + instance $buffer: drop + last-xt +; + +: is-ibuf ( size -- xt ) + 0 0 $is-ibuf +; + +: is-ivariable ( size name len -- xt ) + 4 -rot instance $buffer: drop + last-xt +; + +: is-xt-func ( xt|0 wordstr len ) + header 1 , + ?dup if , then + ['] (semis) , reveal +; + +: is-2xt-func ( xt1 xt2 wordstr len ) + header 1 , + swap , , + ['] (semis) , reveal +; + +: is-func-begin ( wordstr len ) + header 1 , +; + +: is-func-end ( wordstr len ) + ['] (semis) , reveal +; diff --git a/qemu/roms/openbios/forth/lib/lists.fs b/qemu/roms/openbios/forth/lib/lists.fs new file mode 100644 index 000000000..91f7867b9 --- /dev/null +++ b/qemu/roms/openbios/forth/lib/lists.fs @@ -0,0 +1,26 @@ +\ tag: misc useful functions +\ +\ Misc useful functions +\ +\ Copyright (C) 2003 Samuel Rydh +\ +\ See the file "COPYING" for further information about +\ the copyright and warranty status of this work. +\ + +\ ------------------------------------------------------------------------- +\ statically allocated lists +\ ------------------------------------------------------------------------- +\ list-head should be a variable + +: list-add ( listhead -- ) + here 0 , swap \ next, [data...] + ( here listhead ) + begin dup @ while @ repeat ! +; + +: list-get ( listptr -- nextlistptr dictptr true | false ) + @ dup if + dup na1+ true + then +; diff --git a/qemu/roms/openbios/forth/lib/locals.fs b/qemu/roms/openbios/forth/lib/locals.fs new file mode 100644 index 000000000..e697383b6 --- /dev/null +++ b/qemu/roms/openbios/forth/lib/locals.fs @@ -0,0 +1,197 @@ +\ tag: local variables +\ +\ Copyright (C) 2012 Mark Cave-Ayland +\ +\ See the file "COPYING" for further information about +\ the copyright and warranty status of this work. +\ + +[IFDEF] CONFIG_LOCALS + +\ Init local variable stack +variable locals-var-stack +here 200 cells allot locals-var-stack ! + +\ Set initial stack pointer +\ +\ Stack looks like this: +\ ... (sp n-2) local1 ... localm-1 localm (sp n-1) <-- sp + +locals-var-stack @ value locals-var-sp +locals-var-sp locals-var-stack @ ! + +0 value locals-var-count +0 value locals-flags + +here 200 cells allot locals-dict-buf ! + +8 constant #locals + +: (local1) locals-var-sp @ /n + ; +: (local2) locals-var-sp @ 2 cells + ; +: (local3) locals-var-sp @ 3 cells + ; +: (local4) locals-var-sp @ 4 cells + ; +: (local5) locals-var-sp @ 5 cells + ; +: (local6) locals-var-sp @ 6 cells + ; +: (local7) locals-var-sp @ 7 cells + ; +: (local8) locals-var-sp @ 8 cells + ; + +: local1@ (local1) @ ; +: local2@ (local2) @ ; +: local3@ (local3) @ ; +: local4@ (local4) @ ; +: local5@ (local5) @ ; +: local6@ (local6) @ ; +: local7@ (local7) @ ; +: local8@ (local8) @ ; + +: local1! (local1) ! ; +: local2! (local2) ! ; +: local3! (local3) ! ; +: local4! (local4) ! ; +: local5! (local5) ! ; +: local6! (local6) ! ; +: local7! (local7) ! ; +: local8! (local8) ! ; + +create locals-read-table +['] local1@ , +['] local2@ , +['] local3@ , +['] local4@ , +['] local5@ , +['] local6@ , +['] local7@ , +['] local8@ , + +create locals-write-table +['] local1! , +['] local2! , +['] local3! , +['] local4! , +['] local5! , +['] local6! , +['] local7! , +['] local8! , + + +: locals-push ( n -- ) + locals-var-sp /n + to locals-var-sp + locals-var-sp ! +; + +: locals-0-push ( -- ) + 0 locals-push +; + +: (apply-local-flags) ( lfa -- ) + 1 - dup c@ locals-flags or swap c! +; + +: locals-no-pop? ( lfa -- ? ) + 1 - c@ 8 and 0<> +; + +: locals-drop \ Destroy current stack frame + locals-var-sp @ to locals-var-sp +; + +['] locals-drop to locals-end + +: (local-init) ( str len -- ) + header 1 , \ DOCOL + ['] (lit) , ['] noop , \ read-xt + ['] (lit) , ['] noop , \ write-xt + ['] 2drop , \ do nothing + ['] (lit) , + here 5 cells - , + ['] @ , ['] , , \ store read-xt + ['] (semis) , + reveal + immediate + last @ (apply-local-flags) +; + +: (local-noop) ( str len -- ) + 2drop +; + +\ Word called when consuming a local variable +defer (local) + +: } ( C: current latest here -- ) + here! latest ! current ! \ Switch back to normal dict + locals-dict-buf @ to locals-dict \ Make locals-dict visible to $find + 0 to locals-var-count + ['] locals-var-sp , \ save previous sp on rstack + ['] >r , + locals-dict @ \ ( last -- ) + begin + ?dup 0<> + while + >r + locals-var-count /n * + locals-read-table + @ r@ 3 cells + ! \ set read-xt + locals-var-count /n * + locals-write-table + @ r@ 5 cells + ! \ set write-xt + locals-var-count 1+ to locals-var-count + r@ locals-no-pop? if + ['] locals-0-push , \ initialise with 0 + else + ['] locals-push , \ initialise from stack + then + r> @ \ next lfa + repeat + ['] r> , + ['] locals-push , \ write previous sp +; immediate + +: { ( C: -- current latest here ) + current @ latest @ here + ['] (local-init) to (local) + 0 to locals-flags + 0 to locals-var-count + locals-dict-buf @ 200 cells 0 fill \ Zero out temporary dictionary + locals-dict-buf @ current ! \ Switch to locals dictionary + locals-dict-buf @ /n + here! + + begin + parse-word + 2dup s" }" strcmp 0= if + 2drop + ['] } execute -1 + else + 2dup s" ;" strcmp 0= if + 2drop + 8 to locals-flags 0 \ Don't init from stack + else + 2dup s" |" strcmp 0= if + 2drop + 8 to locals-flags 0 \ Don't init from stack + else + 2dup s" --" strcmp 0= if + 2drop + ['] (local-noop) to (local) 0 + else + locals-var-count #locals < if + (local) 0 \ accept local + else + s" maximum locals used ignoring " type type cr 0 + then + locals-var-count 1+ to locals-var-count + then + then + then + then + until +; immediate + +: -> ( n -- ) + parse-word $find if + 4 cells + @ , + else + s" unable to find word " type type + then +; immediate + +[THEN] diff --git a/qemu/roms/openbios/forth/lib/preinclude.fs b/qemu/roms/openbios/forth/lib/preinclude.fs new file mode 100644 index 000000000..6f20ea8f7 --- /dev/null +++ b/qemu/roms/openbios/forth/lib/preinclude.fs @@ -0,0 +1,11 @@ +\ +\ config and build date includes +\ +\ Copyright (C) 2005 Stefan Reinauer +\ +\ See the file "COPYING" for further information about +\ the copyright and warranty status of this work. +\ + +include config.fs +include version.fs diff --git a/qemu/roms/openbios/forth/lib/preprocessor.fs b/qemu/roms/openbios/forth/lib/preprocessor.fs new file mode 100644 index 000000000..89d478cff --- /dev/null +++ b/qemu/roms/openbios/forth/lib/preprocessor.fs @@ -0,0 +1,76 @@ +\ tag: Forth preprocessor +\ +\ Forth preprocessor +\ +\ Copyright (C) 2003, 2004 Samuel Rydh +\ +\ See the file "COPYING" for further information about +\ the copyright and warranty status of this work. +\ + +0 value prep-wid +0 value prep-dict +0 value prep-here + +: ([IF]) + begin + begin parse-word dup 0= while + 2drop refill + repeat + + 2dup " [IF]" strcmp 0= if 1 throw then + 2dup " [IFDEF]" strcmp 0= if 1 throw then + 2dup " [ELSE]" strcmp 0= if 2 throw then + 2dup " [THEN]" strcmp 0= if 3 throw then + " \\" strcmp 0= if linefeed parse 2drop then + again +; + +: [IF] ( flag -- ) + if exit then + 1 begin + ['] ([IF]) catch case + \ EOF (FIXME: this does not work) + \ -1 of ." Missing [THEN]" abort exit endof + \ [IF] + 1 of 1+ endof + \ [ELSE] + 2 of dup 1 = if 1- then endof + \ [THEN] + 3 of 1- endof + endcase + dup 0 <= + until drop +; immediate + +: [ELSE] 0 [ ['] [IF] , ] ; immediate +: [THEN] ; immediate + +:noname + 0 to prep-wid + 0 to prep-dict +; initializer + +: [IFDEF] ( <word> -- ) + prep-wid if + parse-word prep-wid search-wordlist dup if nip then + else 0 then + [ ['] [IF] , ] +; immediate + +: [DEFINE] ( <word> -- ) + parse-word here get-current >r >r + prep-dict 0= if + 2000 alloc-mem here! + here to prep-dict + wordlist to prep-wid + here to prep-here + then + prep-wid set-current prep-here here! + $create + here to prep-here + r> r> set-current here! +; immediate + +: [0] 0 ; immediate +: [1] 1 ; immediate diff --git a/qemu/roms/openbios/forth/lib/split.fs b/qemu/roms/openbios/forth/lib/split.fs new file mode 100644 index 000000000..1a7ac3a0a --- /dev/null +++ b/qemu/roms/openbios/forth/lib/split.fs @@ -0,0 +1,49 @@ +\ implements split-before, split-after and left-split +\ as described in 4.3 (Path resolution) + +\ delimeter returned in R-string +: split-before ( addr len delim -- addr-R len-R addr-L len-L ) + 0 rot dup >r 0 ?do + ( str char cnt R: len <sys> ) + 2 pick over + c@ 2 pick = if leave then + 1+ + loop + nip + 2dup + r> 2 pick - + 2swap +; + +\ delimeter returned in L-string +: split-after ( addr len delim -- addr-R len-R addr-L len-L ) + over 1- rot dup >r 0 ?do + ( str char cnt R: len <sys> ) + 2 pick over + c@ 2 pick = if leave then + 1- + loop + nip + dup 0 >= if 1+ else drop r@ then + 2dup + r> 2 pick - + 2swap +; + +\ delimiter not returned +: left-split ( addr len delim -- addr-R len-R addr-L len-L ) + 0 rot dup >r 0 ?do + ( str char cnt R: len <sys> ) + 2 pick i + c@ 2 pick = if leave then + 1+ + loop + nip + 2dup + 1+ r> 2 pick - + dup if 1- then + 2swap +; + +\ delimiter not returned [THIS FUNCTION IS NOT NEEDED] +: right-split ( addr len delim -- addr-R len-R addr-L len-L ) + dup >r + split-after + dup if 2dup + 1- + c@ r@ = if 1- then then + r> drop +; diff --git a/qemu/roms/openbios/forth/lib/string.fs b/qemu/roms/openbios/forth/lib/string.fs new file mode 100644 index 000000000..eb6474917 --- /dev/null +++ b/qemu/roms/openbios/forth/lib/string.fs @@ -0,0 +1,127 @@ +\ tag: misc useful functions +\ +\ Misc useful functions +\ +\ Copyright (C) 2003 Samuel Rydh +\ +\ See the file "COPYING" for further information about +\ the copyright and warranty status of this work. +\ + +\ compare c-string with (str len) pair +: comp0 ( cstr str len -- 0|-1|1 ) + 3dup + comp ?dup if >r 3drop r> exit then + nip + c@ 0<> if 1 else 0 then +; + +\ returns 0 if the strings match +: strcmp ( str1 len1 str2 len2 -- 0|1 ) + rot over <> if 3drop 1 exit then + comp if 1 else 0 then +; + +: strchr ( str len char -- where|0 ) + >r + begin + 1- dup 0>= + while + ( str len ) + over c@ r@ = if r> 2drop exit then + swap 1+ swap + repeat + r> 3drop 0 +; + +: cstrlen ( cstr -- len ) + dup + begin dup c@ while 1+ repeat + swap - +; + +: strdup ( str len -- newstr len ) + dup if + dup >r + dup alloc-mem dup >r swap move + r> r> + else + 2drop 0 0 + then +; + +: dict-strdup ( str len -- dict-addr len ) + dup here swap allot null-align + swap 2dup >r >r move r> r> +; + +\ ----------------------------------------------------- +\ string copy and cat variants +\ ----------------------------------------------------- + +: tmpstrcat ( addr2 len2 addr1 len1 tmpbuf -- buf len1+len2 tmpbuf+l1+l2 ) + \ save return arguments + dup 2 pick + 4 pick + >r ( R: buf+l1+l2 ) + over 4 pick + >r + dup >r + \ copy... + 2dup + >r + swap move r> swap move + r> r> r> +; + +: tmpstrcpy ( addr1 len1 tmpbuf -- tmpbuf len1 tmpbuf+len1 ) + swap 2dup >r >r move + r> r> 2dup + +; + + + +\ ----------------------------------------------------- +\ number to string conversion +\ ----------------------------------------------------- + +: numtostr ( num buf -- buf len ) + swap rdepth -rot + ( rdepth buf num ) + begin + base @ u/mod swap + \ dup 0< if base @ + then + dup a < if ascii 0 else ascii a a - then + >r + ?dup 0= + until + + rdepth rot - 0 + ( buf len cnt ) + begin + r> over 4 pick + c! + 1+ 2dup <= + until + drop +; + +: tohexstr ( num buf -- buf len ) + base @ hex -rot numtostr rot base ! +; + +: toudecstr ( num buf -- buf len ) + base @ decimal -rot numtostr rot base ! +; + +: todecstr ( num buf -- buf len ) + over 0< if + swap negate over ascii - over c! 1+ + ( buf num buf+1 ) + toudecstr 1+ nip + else + toudecstr + then +; + + +\ ----------------------------------------------------- +\ string to number conversion +\ ----------------------------------------------------- + +: parse-hex ( str len -- value ) + base @ hex -rot $number if 0 then swap base ! +; diff --git a/qemu/roms/openbios/forth/lib/vocabulary.fs b/qemu/roms/openbios/forth/lib/vocabulary.fs new file mode 100644 index 000000000..faa75ea87 --- /dev/null +++ b/qemu/roms/openbios/forth/lib/vocabulary.fs @@ -0,0 +1,153 @@ +\ tag: vocabulary implementation for openbios +\ +\ Copyright (C) 2003 Stefan Reinauer +\ +\ See the file "COPYING" for further information about +\ the copyright and warranty status of this work. +\ + +\ +\ this is an implementation of DPANS94 wordlists (SEARCH EXT) +\ + + +16 constant #vocs +create vocabularies #vocs cells allot \ word lists +['] vocabularies to context + +: search-wordlist ( c-addr u wid -- 0 | xt 1 | xt -1 ) + \ Find the definition identified by the string c-addr u in the word + \ list identified by wid. If the definition is not found, return zero. + \ If the definition is found, return its execution token xt and + \ one (1) if the definition is immediate, minus-one (-1) otherwise. + find-wordlist + if + true over immediate? if + negate + then + else + 2drop false + then + ; + +: wordlist ( -- wid ) + \ Creates a new empty word list, returning its word list identifier + \ wid. The new word list may be returned from a pool of preallocated + \ word lists or may be dynamically allocated in data space. A system + \ shall allow the creation of at least 8 new word lists in addition + \ to any provided as part of the system. + here 0 , + ; + +: get-order ( -- wid1 .. widn n ) + #order @ 0 ?do + #order @ i - 1- cells context + @ + loop + #order @ + ; + +: set-order ( wid1 .. widn n -- ) + dup -1 = if + drop forth-last 1 \ push system default word list and number of lists + then + dup #order ! + 0 ?do + i cells context + ! + loop + ; + +: order ( -- ) + \ display word lists in the search order in their search order sequence + \ from the first searched to last searched. Also display word list into + \ which new definitions will be placed. + cr + get-order 0 ?do + ." wordlist " i (.) type 2e emit space u. cr + loop + cr ." definitions: " current @ u. cr + ; + + +: previous ( -- ) + \ Transform the search order consisting of widn, ... wid2, wid1 (where + \ wid1 is searched first) into widn, ... wid2. An ambiguous condition + \ exists if the search order was empty before PREVIOUS was executed. + get-order nip 1- set-order + ; + + +: do-vocabulary ( -- ) \ implementation factor + does> + @ >r ( ) ( R: widnew ) + get-order swap drop ( wid1 ... widn-1 n ) + r> swap set-order + ; + +: discard ( x1 .. xu u - ) \ implementation factor + 0 ?do + drop + loop + ; + +: vocabulary ( >name -- ) + wordlist create , do-vocabulary + ; + +: also ( -- ) + get-order over swap 1+ set-order + ; + +: only ( -- ) + -1 set-order also + ; + +only + +\ create forth forth-wordlist , do-vocabulary +create forth get-order over , discard do-vocabulary + +: findw ( c-addr -- c-addr 0 | w 1 | w -1 ) + 0 ( c-addr 0 ) + #order @ 0 ?do + over count ( c-addr 0 c-addr' u ) + i cells context + @ ( c-addr 0 c-addr' u wid ) + search-wordlist ( c-addr 0; 0 | w 1 | w -1 ) + ?dup if ( c-addr 0; w 1 | w -1 ) + 2swap 2drop leave ( w 1 | w -1 ) + then ( c-addr 0 ) + loop ( c-addr 0 | w 1 | w -1 ) + ; + +: get-current ( -- wid ) + current @ + ; + +: set-current ( wid -- ) + current ! + ; + +: definitions ( -- ) + \ Make the compilation word list the same as the first word list in + \ the search order. Specifies that the names of subsequent definitions + \ will be placed in the compilation word list. + \ Subsequent changes in the search order will not affect the + \ compilation word list. + context @ set-current + ; + +: forth-wordlist ( -- wid ) + forth-last + ; + +: #words ( -- ) + 0 last + begin + @ ?dup + while + swap 1+ swap + repeat + + cr + ; + +true to vocabularies? diff --git a/qemu/roms/openbios/forth/packages/Kconfig b/qemu/roms/openbios/forth/packages/Kconfig new file mode 100644 index 000000000..16fa30657 --- /dev/null +++ b/qemu/roms/openbios/forth/packages/Kconfig @@ -0,0 +1,16 @@ + +config PKG_DEBLOCKER + bool "Deblocker" + default y + +config PKG_DISKLABEL + bool "Disk Label" + default y + +config PKG_OBP_TFTP + bool "OBP-TFTP" + default y + +config PKG_TERMINAL_EMULATOR + bool "Terminal Emulator" + default y diff --git a/qemu/roms/openbios/forth/packages/README b/qemu/roms/openbios/forth/packages/README new file mode 100644 index 000000000..009f9ec35 --- /dev/null +++ b/qemu/roms/openbios/forth/packages/README @@ -0,0 +1,11 @@ +IEEE 1275-1994 support packages +------------------------------- + +These files create the sub nodes of the /packages node. The nodes +do normally not need an open or close method since their methods are +called statically. + +Currently there are the following support packages: +* deblocker +* obp-tftp +* diff --git a/qemu/roms/openbios/forth/packages/build.xml b/qemu/roms/openbios/forth/packages/build.xml new file mode 100644 index 000000000..16184717e --- /dev/null +++ b/qemu/roms/openbios/forth/packages/build.xml @@ -0,0 +1,19 @@ +<build> + + <!-- + build description for Open Firmware support packages + + Copyright (C) 2004-2005 by Stefan Reinauer + See the file "COPYING" for further information about + the copyright and warranty status of this work. + --> + + <dictionary name="openbios" target="forth"> + <object source="packages.fs"/> + <object source="deblocker.fs" condition="PKG_DEBLOCKER"/> + <object source="disklabel.fs" condition="PKG_DISKLABEL"/> + <object source="terminal-emulator.fs" condition="PKG_TERM_EMUL"/> + <object source="obp-tftp.fs" condition="OBP_TFTP"/> + </dictionary> + +</build> diff --git a/qemu/roms/openbios/forth/packages/deblocker.fs b/qemu/roms/openbios/forth/packages/deblocker.fs new file mode 100644 index 000000000..31a37d002 --- /dev/null +++ b/qemu/roms/openbios/forth/packages/deblocker.fs @@ -0,0 +1,63 @@ +\ tag: deblocker support package +\ +\ Copyright (C) 2003 Stefan Reinauer +\ +\ See the file "COPYING" for further information about +\ the copyright and warranty status of this work. +\ + +" /packages" find-device + +\ The deblocker package makes it easy to implement byte-oriented device +\ methods, using the block-oriented or record-oriented methods defined by +\ devices such as disks or tapes. It provides a layer of buffering between +\ the high-level byte-oriented interface and the low-level block-oriented +\ interface. deblocker uses the max-transfer, block-size, read-blocks and +\ write-blocks methods of its parent. + +new-device + " deblocker" device-name + \ open ( -- flag ) + \ Prepares the package for subsequent use, allocating the buffers used + \ by the deblocking process based upon the values returned by the parent + \ instance's max-transfer and block-size methods. Returns -1 if the + \ operation succeeds, 0 otherwise. + : open ( -- flag ) + + ; + + \ close ( -- ) + \ Frees all resources that were allocated by open. + : close ( -- ) + ; + + \ read ( adr len -- actual ) + \ Reads at most len bytes from the device into the memory buffer + \ beginning at adr. Returns actual, the number of bytes actually + \ read, or 0 if the read operation failed. Uses the parent's read- + \ blocks method as necessary to satisfy the request, buffering any + \ unused bytes for the next request. + + : read ( adr len -- actual ) + ; + + \ Writes at most len bytes from the device into the memory buffer + \ beginning at adr. Returns actual, the number of bytes actually + \ read, or 0 if the write operation failed. Uses the parent's write- + \ blocks method as necessary to satisfy the request, buffering any + \ unused bytes for the next request. + + : write ( adr len -- actual ) + ; + + \ Sets the device position at which the next read or write will take + \ place. The position is specified by the 64-bit number x.position. + \ Returns 0 if the operation succeeds or -1 if it fails. + + : seek ( x.position -- flag ) + ; + +finish-device + +\ clean up afterwards +device-end diff --git a/qemu/roms/openbios/forth/packages/disklabel.fs b/qemu/roms/openbios/forth/packages/disklabel.fs new file mode 100644 index 000000000..39aa13e50 --- /dev/null +++ b/qemu/roms/openbios/forth/packages/disklabel.fs @@ -0,0 +1,22 @@ +\ tag: disklabel support package +\ +\ Copyright (C) 2003 Stefan Reinauer +\ +\ See the file "COPYING" for further information about +\ the copyright and warranty status of this work. +\ + +" /packages" find-device + +\ +\ IEEE 1275 disklabel package +\ + +new-device + " disklabel" device-name + \ now the methods... + +finish-device + +\ clean up afterwards +device-end diff --git a/qemu/roms/openbios/forth/packages/obp-tftp.fs b/qemu/roms/openbios/forth/packages/obp-tftp.fs new file mode 100644 index 000000000..62f0e72e5 --- /dev/null +++ b/qemu/roms/openbios/forth/packages/obp-tftp.fs @@ -0,0 +1,22 @@ +\ tag: tftp support package +\ +\ Copyright (C) 2003 Stefan Reinauer +\ +\ See the file "COPYING" for further information about +\ the copyright and warranty status of this work. +\ + +" /packages" find-device + +\ +\ IEEE 1275 obp-tftp package +\ + +new-device + " obp-tftp" device-name + \ now the methods... + +finish-device + +\ clean up afterwards +device-end diff --git a/qemu/roms/openbios/forth/packages/packages.fs b/qemu/roms/openbios/forth/packages/packages.fs new file mode 100644 index 000000000..9f79f9e5f --- /dev/null +++ b/qemu/roms/openbios/forth/packages/packages.fs @@ -0,0 +1,17 @@ +\ tag: /packages sub device tree +\ +\ Copyright (C) 2003 Stefan Reinauer +\ +\ See the file "COPYING" for further information about +\ the copyright and warranty status of this work. +\ + +" /" find-device + +new-device + " packages" device-name + : open true ; + : close ; +finish-device + +device-end diff --git a/qemu/roms/openbios/forth/packages/terminal-emulator.fs b/qemu/roms/openbios/forth/packages/terminal-emulator.fs new file mode 100644 index 000000000..0ecd348be --- /dev/null +++ b/qemu/roms/openbios/forth/packages/terminal-emulator.fs @@ -0,0 +1,23 @@ +\ tag: terminal emulator support package +\ +\ Copyright (C) 2003 Stefan Reinauer +\ +\ See the file "COPYING" for further information about +\ the copyright and warranty status of this work. +\ + +" /packages" find-device + +\ +\ IEEE 1275 terminal-emulator package +\ + +new-device + " terminal-emulator" device-name + \ now the methods... + +finish-device + +\ clean up afterwards + +device-end diff --git a/qemu/roms/openbios/forth/system/build.xml b/qemu/roms/openbios/forth/system/build.xml new file mode 100644 index 000000000..f15440a07 --- /dev/null +++ b/qemu/roms/openbios/forth/system/build.xml @@ -0,0 +1,16 @@ +<build> + + <!-- + build description for openbios system bindings + + Copyright (C) 2004-2005 by Stefan Reinauer + See the file "COPYING" for further information about + the copyright and warranty status of this work. + --> + + <dictionary name="openbios" target="forth"> + <object source="main.fs"/> + <object source="ciface.fs"/> + </dictionary> + +</build> diff --git a/qemu/roms/openbios/forth/system/ciface.fs b/qemu/roms/openbios/forth/system/ciface.fs new file mode 100644 index 000000000..fd6c54efd --- /dev/null +++ b/qemu/roms/openbios/forth/system/ciface.fs @@ -0,0 +1,363 @@ + +0 value ciface-ph + +dev /openprom/ +new-device +" client-services" device-name + +active-package to ciface-ph + +\ ------------------------------------------------------------- +\ private stuff +\ ------------------------------------------------------------- + +private + +variable callback-function + +: ?phandle ( phandle -- phandle ) + dup 0= if ." NULL phandle" -1 throw then +; +: ?ihandle ( ihandle -- ihandle ) + dup 0= if ." NULL ihandle" -2 throw then +; + +\ copy and null terminate return string +: ci-strcpy ( buf buflen str len -- len ) + >r -rot dup + ( str buf buflen buflen R: len ) + r@ min swap + ( str buf n buflen R: len ) + over > if + ( str buf n ) + 2dup + 0 swap c! + then + move r> +; + +0 value memory-ih +0 value mmu-ih + +:noname ( -- ) + " /chosen" find-device + + " mmu" active-package get-package-property 0= if + decode-int nip nip to mmu-ih + then + + " memory" active-package get-package-property 0= if + decode-int nip nip to memory-ih + then + device-end +; SYSTEM-initializer + +: safetype + ." <" dup cstrlen dup 20 < if type else 2drop ." BAD" then ." >" +; + +: phandle-exists? ( phandle -- found? ) + false swap 0 + begin iterate-tree ?dup while + ( found? find-ph current-ph ) + over over = if + rot drop true -rot + then + repeat + drop +; + +\ ------------------------------------------------------------- +\ public interface +\ ------------------------------------------------------------- + +external + +\ ------------------------------------------------------------- +\ 6.3.2.1 Client interface +\ ------------------------------------------------------------- + +\ returns -1 if missing +: test ( name -- 0|-1 ) + dup cstrlen ciface-ph find-method + if drop 0 else -1 then +; + +\ ------------------------------------------------------------- +\ 6.3.2.2 Device tree +\ ------------------------------------------------------------- + +: peer peer ; +: child child ; +: parent parent ; + +: getproplen ( name phandle -- len|-1 ) + over cstrlen swap + ?phandle get-package-property + if -1 else nip then +; + +: getprop ( buflen buf name phandle -- size|-1 ) + \ detect phandle == -1 + dup -1 = if + 2drop 2drop -1 exit + then + + \ return -1 if phandle is 0 (MacOS actually does this) + ?dup 0= if drop 2drop -1 exit then + + over cstrlen swap + ?phandle get-package-property if 2drop -1 exit then + ( buflen buf prop proplen ) + >r swap rot r> + ( prop buf buflen proplen ) + dup >r min move r> +; + +\ 1 OK, 0 no more prop, -1 prev invalid +: nextprop ( buf prev phandle -- 1|0|-1 ) + >r + dup 0= if 0 else dup cstrlen then + + ( buf prev prev_len ) + + \ verify that prev exists (overkill...) + dup if + 2dup r@ get-package-property if + r> 2drop drop + 0 swap c! + -1 exit + else + 2drop + then + then + + ( buf prev prev_len ) + + r> next-property if + ( buf name name_len ) + dup 1+ -rot ci-strcpy drop 1 + else + ( buf ) + 0 swap c! + 0 + then +; + +: setprop ( len buf name phandle -- size ) + 3 pick >r + >r >r swap encode-bytes \ ( prop-addr prop-len R: phandle name ) + r> dup cstrlen r> + (property) + r> +; + +: finddevice ( dev_spec -- phandle|-1 ) + dup cstrlen + \ ." FIND-DEVICE " 2dup type + find-dev 0= if -1 then + \ ." -- " dup . cr +; + +: instance-to-package ( ihandle -- phandle ) + ?ihandle ihandle>phandle +; + +: package-to-path ( buflen buf phandle -- length ) + \ XXX improve error checking + dup 0= if 3drop -1 exit then + >r swap r> + get-package-path + ( buf buflen str len ) + ci-strcpy +; + +: canon ( buflen buf dev_specifier -- len ) + dup cstrlen find-dev if + ( buflen buf phandle ) + package-to-path + else + 2drop -1 + then +; + +: instance-to-path ( buflen buf ihandle -- length ) + \ XXX improve error checking + dup 0= if 3drop -1 exit then + >r swap r> + get-instance-path + \ ." INSTANCE: " 2dup type cr dup . + ( buf buflen str len ) + ci-strcpy +; + +: instance-to-interposed-path ( buflen buf ihandle -- length ) + \ XXX improve error checking + dup 0= if 3drop -1 exit then + >r swap r> + get-instance-interposed-path + ( buf buflen str len ) + ci-strcpy +; + +: call-method ( ihandle method -- xxxx catch-result ) + dup 0= if ." call of null method" -1 exit then + dup >r + dup cstrlen + \ ." call-method " 2dup type cr + rot ?ihandle ['] $call-method catch dup if + \ not necessary an error but very useful for debugging... + ." call-method " r@ dup cstrlen type ." : exception " dup . cr + then + r> drop +; + + +\ ------------------------------------------------------------- +\ 6.3.2.3 Device I/O +\ ------------------------------------------------------------- + +: open ( dev_spec -- ihandle|0 ) + dup cstrlen open-dev +; + +: close ( ihandle -- ) + close-dev +; + +: read ( len addr ihandle -- actual ) + >r swap r> + dup ihandle>phandle " read" rot find-method + if swap call-package else 3drop -1 then +; + +: write ( len addr ihandle -- actual ) + >r swap r> + dup ihandle>phandle " write" rot find-method + if swap call-package else 3drop -1 then +; + +: seek ( pos_lo pos_hi ihandle -- status ) + dup ihandle>phandle " seek" rot find-method + if swap call-package else 3drop -1 then +; + + +\ ------------------------------------------------------------- +\ 6.3.2.4 Memory +\ ------------------------------------------------------------- + +: claim ( align size virt -- baseaddr|-1 ) + -rot swap + ciface-ph " cif-claim" rot find-method + if execute else 3drop -1 then +; + +: release ( size virt -- ) + swap + ciface-ph " cif-release" rot find-method + if execute else 2drop -1 then +; + +\ ------------------------------------------------------------- +\ 6.3.2.5 Control transfer +\ ------------------------------------------------------------- + +: boot ( bootspec -- ) + ." BOOT" +; + +: enter ( -- ) + ." ENTER" +; + +\ exit ( -- ) is defined later (clashes with builtin exit) + +: chain ( virt size entry args len -- ) + ." CHAIN" +; + +\ ------------------------------------------------------------- +\ 6.3.2.6 User interface +\ ------------------------------------------------------------- + +: interpret ( xxx cmdstring -- ??? catch-reult ) + dup cstrlen + \ ." INTERPRETE: --- " 2dup type + ['] evaluate catch dup if + \ this is not necessary an error... + ." interpret: exception " dup . ." caught" cr + + \ Force back to interpret state on error, otherwise the next call to + \ interpret gets confused if the error occurred in compile mode + 0 state ! + then + \ ." --- " cr +; + +: set-callback ( newfunc -- oldfunc ) + callback-function @ + swap + callback-function ! +; + +\ : set-symbol-lookup ( sym-to-value -- value-to-sym ) ; + + +\ ------------------------------------------------------------- +\ 6.3.2.7 Time +\ ------------------------------------------------------------- + +: milliseconds ( -- ms ) + get-msecs +; + +\ ------------------------------------------------------------- +\ arch? +\ ------------------------------------------------------------- + +: start-cpu ( xxx xxx xxx --- ) + ." Start CPU unimplemented" cr + 3drop +; + +\ ------------------------------------------------------------- +\ special +\ ------------------------------------------------------------- + +: exit ( -- ) + ." EXIT" + outer-interpreter +; + +: test-method ( cstring-method phandle -- missing? ) + swap dup cstrlen rot + + \ Check for incorrect phandle + dup phandle-exists? false = if + -1 throw + then + + find-method 0= if -1 else drop 0 then +; + +finish-device +device-end + + +\ ------------------------------------------------------------- +\ entry point +\ ------------------------------------------------------------- + +: client-iface ( [args] name len -- [args] -1 | [rets] 0 ) + ciface-ph find-method 0= if -1 exit then + catch ?dup if + cr ." Unexpected client interface exception: " . -2 cr exit + then + 0 +; + +: client-call-iface ( [args] name len -- [args] -1 | [rets] 0 ) + ciface-ph find-method 0= if -1 exit then + execute + 0 +; diff --git a/qemu/roms/openbios/forth/system/main.fs b/qemu/roms/openbios/forth/system/main.fs new file mode 100644 index 000000000..122ab1fa3 --- /dev/null +++ b/qemu/roms/openbios/forth/system/main.fs @@ -0,0 +1,60 @@ +\ tag: misc useful functions +\ +\ Open Firmware Startup +\ +\ Copyright (C) 2003 Samuel Rydh +\ +\ See the file "COPYING" for further information about +\ the copyright and warranty status of this work. +\ + +variable PREPOST-list +variable POST-list +variable SYSTEM-list +variable DIAG-list + +: PREPOST-initializer ( xt -- ) + PREPOST-list list-add , +; + +: POST-initializer ( xt -- ) + POST-list list-add , +; + +: SYSTEM-initializer ( xt -- ) + SYSTEM-list list-add , +; + +: DIAG-initializer ( xt -- ) + DIAG-list list-add , +; + + +\ OpenFirmware entrypoint +: initialize-of ( startmem endmem -- ) + initialize-forth + + PREPOST-list begin list-get while @ execute repeat + POST-list begin list-get while @ execute repeat + SYSTEM-list begin list-get while @ execute repeat + + \ evaluate nvramrc script + use-nvramrc? if + nvramrc evaluate + then + + \ probe-all etc. + suppress-banner? 0= if + probe-all + install-console + banner + then + + DIAG-list begin list-get while @ execute repeat + + auto-boot? if + boot-command evaluate + then + + outer-interpreter +; diff --git a/qemu/roms/openbios/forth/testsuite/README b/qemu/roms/openbios/forth/testsuite/README new file mode 100644 index 000000000..7aa98dea3 --- /dev/null +++ b/qemu/roms/openbios/forth/testsuite/README @@ -0,0 +1,8 @@ +TESTSUITES +---------- + +This directory contains additional testsuites for some open +firmware components. They are not built per default. + + +tag: testsuites readme diff --git a/qemu/roms/openbios/forth/testsuite/build.xml b/qemu/roms/openbios/forth/testsuite/build.xml new file mode 100644 index 000000000..7b7d62bcf --- /dev/null +++ b/qemu/roms/openbios/forth/testsuite/build.xml @@ -0,0 +1,16 @@ +<build> + + <!-- + build description for OpenBIOS test suite + + Copyright (C) 2004-2005 by Stefan Reinauer + See the file "COPYING" for further information about + the copyright and warranty status of this work. + --> + + <dictionary name="testsuite" target="forth"> + <object source="memory-testsuite.fs"/> + <object source="splitfunc-testsuite.fs"/> + </dictionary> + +</build> diff --git a/qemu/roms/openbios/forth/testsuite/fract.fs b/qemu/roms/openbios/forth/testsuite/fract.fs new file mode 100644 index 000000000..39c984056 --- /dev/null +++ b/qemu/roms/openbios/forth/testsuite/fract.fs @@ -0,0 +1,35 @@ +\ tag: forth fractal example +\ +\ Copyright (C) 2002, 2003 Volker Poplawski <volker@poplawski.de> +\ Stefan Reinauer + +\ This example even fits in a signature ;-) + +\ hex 4666 dup negate do i 4000 dup 2* negate do 2a 0 dup 2dup 1e 0 do +\ 2swap * d >>a 4 pick + -rot - j + dup dup * e >>a rot dup dup * e >>a +\ rot swap 2dup + 10000 > if 3drop 2drop 20 0 dup 2dup leave then loop +\ 2drop 2drop type 268 +loop cr drop 5de +loop + + +: fract +4666 dup negate +do + i 4000 dup 2* negate + do + 2a 0 dup 2dup 1e 0 + do + 2swap * d >>a 4 pick + + -rot - j + + dup dup * e >>a rot + dup dup * e >>a rot + swap + 2dup + 10000 > if + 3drop 2drop 20 0 dup 2dup leave + then + loop + 2drop 2drop + emit + 268 +loop + cr drop +5de +loop +; diff --git a/qemu/roms/openbios/forth/testsuite/framebuffer-test.fs b/qemu/roms/openbios/forth/testsuite/framebuffer-test.fs new file mode 100644 index 000000000..110993259 --- /dev/null +++ b/qemu/roms/openbios/forth/testsuite/framebuffer-test.fs @@ -0,0 +1,10 @@ + +: test-screen + 10 10 pci-l@ + f0 0 do + dup d# 1280 i * + + 500 i fill + loop + ; + + test-screen diff --git a/qemu/roms/openbios/forth/testsuite/memory-testsuite.fs b/qemu/roms/openbios/forth/testsuite/memory-testsuite.fs new file mode 100644 index 000000000..9dace5117 --- /dev/null +++ b/qemu/roms/openbios/forth/testsuite/memory-testsuite.fs @@ -0,0 +1,106 @@ +\ this is the memory management testsuite. +\ +\ run it with paflof < memory-testsuite.fs 2>/dev/null + +s" memory.fs" included + +\ dumps all free-list entries +\ useful for debugging. + +: dump-freelist ( -- ) + ." Dumping freelist:" cr + free-list @ + + \ If the free list is empty we notify the user. + dup 0= if ." empty." drop cr exit then + + begin dup 0<> while + dup ." entry 0x" . \ print pointer to entry + dup cell+ @ ." , next=0x" u. \ pointer to next entry + dup @ ." , size=0x" u. cr \ len of current entry + + cell+ @ + repeat + cr drop + ; + +\ simple testsuite. run testsuite-init to initialize +\ with some dummy memory in the dictionary. +\ run testsuite-test[1..3] for different tests. + +: testsuite-init ( -- ) + here 40000 cell+ dup allot ( -- ptr len ) + init-mem + + ." start-mem = 0x" start-mem @ . cr + ." end-mem = 0x" end-mem @ . cr + ." free-list = 0x" free-list @ . cr + + ." Memory management initialized." cr + dump-freelist + ; + +: testsuite-test1 ( -- ) + ." Test No. 1: Allocating all available memory (256k)" cr + + 40000 alloc-mem + dup 0<> if + ." worked, ptr=0x" dup . + else + ." did not work." + then + cr + + dump-freelist + ." Freeing memory." cr + ." stack=" .s cr + free-mem + dump-freelist + ; + +: testsuite-test2 ( -- ) + ." Test No. 2: Allocating 5 blocks" cr + 4000 alloc-mem + 4000 alloc-mem + 4000 alloc-mem + 4000 alloc-mem + 4000 alloc-mem + + ." Allocated 5 blocks. Stack:" cr .s cr + + dump-freelist + + ." Freeing Block 2" cr + 3 pick free-mem dump-freelist + + ." Freeing Block 4" cr + over free-mem dump-freelist + + ." Freeing Block 3" cr + 2 pick free-mem dump-freelist + + ." Cleaning up blocks 1 and 5" cr + free-mem \ Freeing block 5 + dump-freelist + 3drop \ blocks 4, 3, 2 + free-mem + + dump-freelist + ; + +: testsuite-test3 ( -- ) + ." Test No. 3: freeing illegal address 0xdeadbeef." cr + deadbeef free-mem + dump-freelist + ; + +: testsuite ( -- ) + testsuite-init + testsuite-test1 + testsuite-test2 + testsuite-test3 + ; + +testsuite + +bye diff --git a/qemu/roms/openbios/forth/testsuite/splitfunc-testsuite.fs b/qemu/roms/openbios/forth/testsuite/splitfunc-testsuite.fs new file mode 100644 index 000000000..00469bb57 --- /dev/null +++ b/qemu/roms/openbios/forth/testsuite/splitfunc-testsuite.fs @@ -0,0 +1,38 @@ +\ this is the splitfunc testsuite. +\ +\ run it with paflof < splitfunc-testsuite.fs 2>/dev/null + +\ implements split-before, split-after and left-split +\ as described in 4.3 (Path resolution) + +s" splitfunc.fs" included + +: test-split + s" var/log/messages" 2dup + + cr ." split-before test:" cr + 2dup ." String: " type cr + 2f split-before + 2swap + ." initial: " type cr ." remainder:" type cr + cr + ." split-after test:" cr + 2f split-after cr + 2swap + ." initial: " type cr ." remainder:" type cr + + ." foobar test" cr + + s" foobar" 2dup + + 2f split-after cr + 2swap + ." initial: " type cr ." remainder:" type cr + + 2f split-after cr + 2swap + ." initial: " type cr ." remainder:" type cr + ; + + + diff --git a/qemu/roms/openbios/forth/util/apic.fs b/qemu/roms/openbios/forth/util/apic.fs new file mode 100644 index 000000000..82a62aa7b --- /dev/null +++ b/qemu/roms/openbios/forth/util/apic.fs @@ -0,0 +1,62 @@ +\ +\ ioapic and local apic tester +\ +\ Copyright (C) 2003 Stefan Reinauer +\ +\ See the file "COPYING" for further information about +\ the copyright and warranty status of this work. +\ + +hex + +fee00000 constant lapic_base +fec00000 constant ioapic_base + +: read_lapic ( regoffset -- value ) + lapic_base + l@ + ; + +: write_lapic ( value regoffset -- ) + lapic_base + l! + ; + +: read_ioapic ( regoffset -- low_value high_value ) + 2* 10 + dup + ioapic_base l! ioapic_base 4 cells + l@ + swap 1+ + ioapic_base l! ioapic_base 4 cells + l@ + ; + +: write_ioapic ( low high regoffset -- ) + 2* 10 + dup ( low high offs offs ) + ioapic_base l! rot ioapic_base 4 cells + l! ( high offs ) + 1+ + ioapic_base l! ioapic_base 4 cells + l! ( high offs ) + ; + +: test-lapic + s" Dumping local apic:" type cr + 3f0 0 do + i dup ( lapic_base + ) s" 0x" type . s" = 0x" type read_lapic space . + i 30 and 0= if cr then + 10 +loop + cr + ; + +: test-ioapic + s" Dumping io apic:" type cr + 17 0 do + i dup s" irq=" type . read_ioapic s" = 0x" type . s" ." type . + i 1 and 0<> if + cr + then + loop + cr + ; + +: dump-apics + test-lapic + test-ioapic + ; + +\ tag: apic test utility diff --git a/qemu/roms/openbios/forth/util/build.xml b/qemu/roms/openbios/forth/util/build.xml new file mode 100644 index 000000000..4839d2cd3 --- /dev/null +++ b/qemu/roms/openbios/forth/util/build.xml @@ -0,0 +1,19 @@ +<build> + + <!-- + build description for OpenBIOS utility functions + + Copyright (C) 2004-2005 by Stefan Reinauer + See the file "COPYING" for further information about + the copyright and warranty status of this work. + --> + + <dictionary name="openbios" target="forth"> + <object source="util.fs"/> + <object source="pci.fs"/> + <!-- We don't want/need these at the moment + <object source="apic.fs"/> + --> + </dictionary> + +</build> diff --git a/qemu/roms/openbios/forth/util/pci.fs b/qemu/roms/openbios/forth/util/pci.fs new file mode 100644 index 000000000..57ded6265 --- /dev/null +++ b/qemu/roms/openbios/forth/util/pci.fs @@ -0,0 +1,92 @@ +\ tag: PCI helper functions +\ +\ Copyright (C) 2003-2004 Stefan Reinauer +\ Copyright (C) 2003 Samuel Rydh +\ +\ See the file "COPYING" for further information about +\ the copyright and warranty status of this work. +\ + +\ simple set of words for pci access, these are not +\ compliant to the PCI bus binding of OpenFirmware. + +\ only forth +\ vocabulary pci +\ also pci definitions + +hex + +: busdevfn ( bus dev fn -- busdevfn ) + 7 and swap + 1f and 3 << or ( dev fn -- devfn ) + swap 8 << or ( bus devfn -- busdevfn ) + ; + +: config-command ( busdevfn reg -- reg addr ) + dup -rot + 3 invert and + swap 8 << or + 80000000 or + ; + +: pci-c@ ( busdevfn reg -- x ) + config-command + cf8 iol! + 3 and cfc + + ioc@ + ; + +: pci-w@ ( busdevfn reg -- x ) + config-command + cf8 iol! + 2 and cfc + iow@ + ; + +: pci-l@ ( busdevfn reg -- x ) + config-command + cf8 iol! + drop + cfc iol@ + ; + +: pci-c! ( busdevfn reg val -- ) + -rot config-command + cf8 iol! + 3 and cfc + ioc! + ; + +: pci-w! ( busdevfn reg val -- ) + -rot config-command + cf8 iol! + 2 and cfc + iow! + ; + +: pci-l! ( busdevfn reg val -- ) + -rot config-command + cf8 iol! + drop + cfc iol! + ; + +: dump-pci-device ( bus dev fn -- ) + 2 pick (.) type 3a emit over + (.) type 2e emit dup (.) type 20 emit 5b emit \ 0:18.0 [ + busdevfn >r + r@ 0 pci-w@ u. 2f emit r@ 2 pci-w@ u. 5d emit \ 1022/1100] + r> + \ now we iterate + 10 0 do + cr i todigit emit 30 emit 3a emit 20 emit + 10 0 do + dup i j 4 << or pci-c@ + dup 4 >> todigit emit f and todigit emit + 20 emit + loop + loop + drop + cr cr + ; + +\ : test-pci +\ 0 2 0 dump-pci-device +\ ; diff --git a/qemu/roms/openbios/forth/util/util.fs b/qemu/roms/openbios/forth/util/util.fs new file mode 100644 index 000000000..6f549bf54 --- /dev/null +++ b/qemu/roms/openbios/forth/util/util.fs @@ -0,0 +1,95 @@ +\ tag: Utility functions +\ +\ Utility functions +\ +\ Copyright (C) 2003, 2004 Samuel Rydh +\ +\ See the file "COPYING" for further information about +\ the copyright and warranty status of this work. +\ + +\ ------------------------------------------------------------------------- +\ package utils +\ ------------------------------------------------------------------------- + +( method-str method-len package-str package-len -- xt|0 ) +: $find-package-method + find-package 0= if 2drop false exit then + find-method 0= if 0 then +; + +\ like $call-parent but takes an xt +: call-parent ( ... xt -- ??? ) + my-parent call-package +; + +: [active-package], + ['] (lit) , active-package , +; immediate + +\ ------------------------------------------------------------------------- +\ word creation +\ ------------------------------------------------------------------------- + +: ?mmissing ( name len -- 1 name len | 0 ) + 2dup active-package find-method + if 3drop false else true then +; + +\ install trivial open and close functions +: is-open ( -- ) + " open" ?mmissing if ['] true -rot is-xt-func then + " close" ?mmissing if 0 -rot is-xt-func then +; + +\ is-relay installs a relay function (a function that calls +\ a function with the same name but belonging to a different node). +\ The execution behaviour of xt should be ( -- ptr-to-ihandle ). +\ +: is-relay ( xt ph name-str name-len -- ) + rot >r 2dup r> find-method 0= if + \ function missing (not necessarily an error) + 3drop exit + then + + -rot is-func-begin + ( xt method-xt ) + ['] (lit) , , \ ['] method + , ['] @ , \ xt @ + ['] call-package , \ call-package + is-func-end +; + +\ ------------------------------------------------------------------------- +\ install deblocker bindings +\ ------------------------------------------------------------------------- + +: (open-deblocker) ( varaddr -- ) + " deblocker" find-package if + 0 0 rot open-package + else 0 then + swap ! +; + +: is-deblocker ( -- ) + " deblocker" find-package 0= if exit then >r + " deblocker" is-ivariable + + \ create open-deblocker + " open-deblocker" is-func-begin + dup , ['] (open-deblocker) , + is-func-end + + \ create close-deblocker + " close-deblocker" is-func-begin + dup , ['] @ , ['] close-package , + is-func-end + + ( save-ph deblk-xt R: deblocker-ph ) + r> + 2dup " read" is-relay + 2dup " seek" is-relay + 2dup " write" is-relay + 2dup " tell" is-relay + 2drop +; diff --git a/qemu/roms/openbios/fs/build.xml b/qemu/roms/openbios/fs/build.xml new file mode 100644 index 000000000..9ecc00553 --- /dev/null +++ b/qemu/roms/openbios/fs/build.xml @@ -0,0 +1,14 @@ +<?xml version="1.0"?> +<build> + + <library name="fs" type="static" target="target"> + <object source="ioglue.c"/> + </library> + + <include href="grubfs/build.xml"/> + <include href="hfs/build.xml"/> + <include href="hfsplus/build.xml"/> + <include href="iso9660/build.xml"/> + <include href="ext2/build.xml"/> + +</build> diff --git a/qemu/roms/openbios/fs/ext2/build.xml b/qemu/roms/openbios/fs/ext2/build.xml new file mode 100644 index 000000000..98e9e0569 --- /dev/null +++ b/qemu/roms/openbios/fs/ext2/build.xml @@ -0,0 +1,14 @@ +<build> + <library name="fs" type="static" target="target"> + <object source="ext2_close.c" condition="EXT2"/> + <object source="ext2_closedir.c" condition="EXT2"/> + <object source="ext2_fs.c" condition="EXT2"/> + <object source="ext2_lseek.c" condition="EXT2"/> + <object source="ext2_mount.c" condition="EXT2"/> + <object source="ext2_open.c" condition="EXT2"/> + <object source="ext2_opendir.c" condition="EXT2"/> + <object source="ext2_read.c" condition="EXT2"/> + <object source="ext2_readdir.c" condition="EXT2"/> + <object source="ext2_utils.c" condition="EXT2"/> + </library> +</build> diff --git a/qemu/roms/openbios/fs/ext2/ext2.h b/qemu/roms/openbios/fs/ext2/ext2.h new file mode 100644 index 000000000..ad8589284 --- /dev/null +++ b/qemu/roms/openbios/fs/ext2/ext2.h @@ -0,0 +1,33 @@ +/* + * + * (c) 2008-2009 Laurent Vivier <Laurent@lvivier.info> + * + * This file has been copied from EMILE, http://emile.sf.net + * + */ + +#ifndef __EXT2_H__ +#define __EXT2_H__ + +#include "ext2_fs.h" + +typedef struct ext2_VOLUME { + int fd; + struct ext2_super_block *super; + unsigned int current; + char *buffer; +} ext2_VOLUME; + +typedef struct ext2_DIR { + ext2_VOLUME *volume; + struct ext2_inode *inode; + off_t index; +} ext2_DIR; + +typedef struct ext2_FILE { + ext2_VOLUME *volume; + struct ext2_inode *inode; + off_t offset; + char *path; +} ext2_FILE; +#endif /* __LIBEXT2_H__ */ diff --git a/qemu/roms/openbios/fs/ext2/ext2_close.c b/qemu/roms/openbios/fs/ext2/ext2_close.c new file mode 100644 index 000000000..f370e181e --- /dev/null +++ b/qemu/roms/openbios/fs/ext2/ext2_close.c @@ -0,0 +1,18 @@ +/* + * + * (c) 2008-2009 Laurent Vivier <Laurent@lvivier.info> + * + * This file has been copied from EMILE, http://emile.sf.net + * + */ + +#include "libext2.h" + +void ext2_close(ext2_FILE *file) +{ + if (file == NULL) + return; + free(file->inode); + free(file->path); + free(file); +} diff --git a/qemu/roms/openbios/fs/ext2/ext2_closedir.c b/qemu/roms/openbios/fs/ext2/ext2_closedir.c new file mode 100644 index 000000000..e9f06319c --- /dev/null +++ b/qemu/roms/openbios/fs/ext2/ext2_closedir.c @@ -0,0 +1,18 @@ +/* + * + * (c) 2008-2009 Laurent Vivier <Laurent@lvivier.info> + * + * This file has been copied from EMILE, http://emile.sf.net + * + */ + +#include "libext2.h" +#include "ext2.h" + +void ext2_closedir(ext2_DIR *dir) +{ + if (dir == NULL) + return; + free(dir->inode); + free(dir); +} diff --git a/qemu/roms/openbios/fs/ext2/ext2_fs.c b/qemu/roms/openbios/fs/ext2/ext2_fs.c new file mode 100644 index 000000000..66eb0b438 --- /dev/null +++ b/qemu/roms/openbios/fs/ext2/ext2_fs.c @@ -0,0 +1,309 @@ +/* + * /packages/ext2-files + * + * (c) 2008-2009 Laurent Vivier <Laurent@lvivier.info> + * (c) 2010 Mark Cave-Ayland <mark.cave-ayland@siriusit.co.uk> + * + * This file has been copied from EMILE, http://emile.sf.net + * + */ + +#include "config.h" +#include "libopenbios/bindings.h" +#include "libext2.h" +#include "ext2_utils.h" +#include "fs/fs.h" +#include "libc/vsprintf.h" +#include "libc/diskio.h" + +extern void ext2_init( void ); + +typedef struct { + enum { FILE, DIR } type; + union { + ext2_FILE *file; + ext2_DIR *dir; + }; +} ext2_COMMON; + +typedef struct { + ext2_VOLUME *volume; + ext2_COMMON *common; +} ext2_info_t; + +DECLARE_NODE( ext2, 0, sizeof(ext2_info_t), "+/packages/ext2-files" ); + + +static const int days_month[12] = + { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; +static const int days_month_leap[12] = + { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + +static inline int is_leap(int year) +{ + return ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0); +} + +static void +print_date(time_t sec) +{ + unsigned int second, minute, hour, month, day, year; + int current; + const int *days; + + second = sec % 60; + sec /= 60; + + minute = sec % 60; + sec /= 60; + + hour = sec % 24; + sec /= 24; + + year = sec * 100 / 36525; + sec -= year * 36525 / 100; + year += 1970; + + days = is_leap(year) ? days_month_leap : days_month; + + current = 0; + month = 0; + while (month < 12) { + if (sec <= current + days[month]) { + break; + } + current += days[month]; + month++; + } + month++; + + day = sec - current + 1; + + forth_printf("%d-%02d-%02d %02d:%02d:%02d ", + year, month, day, hour, minute, second); +} + + +/************************************************************************/ +/* Standard package methods */ +/************************************************************************/ + +/* ( -- success? ) */ +static void +ext2_files_open( ext2_info_t *mi ) +{ + int fd; + char *path = my_args_copy(); + + fd = open_ih( my_parent() ); + if ( fd == -1 ) { + free( path ); + RET( 0 ); + } + + mi->volume = ext2_mount(fd); + if (!mi->volume) { + RET( 0 ); + } + + mi->common = (ext2_COMMON*)malloc(sizeof(ext2_COMMON)); + if (mi->common == NULL) + RET( 0 ); + + mi->common->dir = ext2_opendir(mi->volume, path); + if (mi->common->dir == NULL) { + mi->common->file = ext2_open(mi->volume, path); + if (mi->common->file == NULL) { + free(mi->common); + RET( 0 ); + } + mi->common->type = FILE; + RET( -1 ); + } + mi->common->type = DIR; + RET( -1 ); +} + +/* ( -- ) */ +static void +ext2_files_close( ext2_info_t *mi ) +{ + ext2_COMMON *common = mi->common; + + if (common->type == FILE) + ext2_close(common->file); + else if (common->type == DIR) + ext2_closedir(common->dir); + free(common); + + ext2_umount(mi->volume); +} + +/* ( buf len -- actlen ) */ +static void +ext2_files_read( ext2_info_t *mi ) +{ + int count = POP(); + char *buf = (char *)cell2pointer(POP()); + + ext2_COMMON *common = mi->common; + if (common->type != FILE) + RET( -1 ); + + RET ( ext2_read( common->file, buf, count ) ); +} + +/* ( pos.d -- status ) */ +static void +ext2_files_seek( ext2_info_t *mi ) +{ + long long pos = DPOP(); + int offs = (int)pos; + int whence = SEEK_SET; + int ret; + ext2_COMMON *common = mi->common; + + if (common->type != FILE) + RET( -1 ); + + ret = ext2_lseek(common->file, offs, whence); + if (ret) + RET( -1 ); + else + RET( 0 ); +} + +/* ( addr -- size ) */ +static void +ext2_files_load( ext2_info_t *mi ) +{ + char *buf = (char *)cell2pointer(POP()); + int count; + + ext2_COMMON *common = mi->common; + if (common->type != FILE) + RET( -1 ); + + /* Seek to the end in order to get the file size */ + ext2_lseek(common->file, 0, SEEK_END); + count = common->file->offset; + ext2_lseek(common->file, 0, SEEK_SET); + + RET ( ext2_read( common->file, buf, count ) ); +} + +/* ( -- cstr ) */ +static void +ext2_files_get_path( ext2_info_t *mi ) +{ + ext2_COMMON *common = mi->common; + + if (common->type != FILE) + RET( 0 ); + + RET( pointer2cell(strdup(common->file->path)) ); +} + +/* ( -- cstr ) */ +static void +ext2_files_get_fstype( ext2_info_t *mi ) +{ + PUSH( pointer2cell(strdup("ext2")) ); +} + +/* static method, ( pathstr len ihandle -- ) */ +static void +ext2_files_dir( ext2_info_t *dummy ) +{ + ext2_COMMON *common; + ext2_VOLUME *volume; + struct ext2_dir_entry_2 *entry; + struct ext2_inode inode; + int fd; + + ihandle_t ih = POP(); + char *path = pop_fstr_copy(); + + fd = open_ih( ih ); + if ( fd == -1 ) { + free( path ); + return; + } + + volume = ext2_mount(fd); + if (!volume) { + return; + } + + common = (ext2_COMMON*)malloc(sizeof(ext2_COMMON)); + common->dir = ext2_opendir(volume, path); + + forth_printf("\n"); + while ( (entry = ext2_readdir(common->dir)) ) { + ext2_get_inode(common->dir->volume, entry->inode, &inode); + forth_printf("% 10d ", inode.i_size); + print_date(inode.i_mtime); + if (S_ISDIR(inode.i_mode)) + forth_printf("%s\\\n", entry->name); + else + forth_printf("%s\n", entry->name); + } + + ext2_closedir( common->dir ); + ext2_umount( volume ); + + close_io( fd ); + + free( common ); + free( path ); +} + +/* static method, ( pos.d ih -- flag? ) */ +static void +ext2_files_probe( ext2_info_t *dummy ) +{ + ihandle_t ih = POP_ih(); + long long offs = DPOP(); + int fd, ret = 0; + + fd = open_ih(ih); + if (fd >= 0) { + if (ext2_probe(fd, offs)) { + ret = -1; + } + close_io(fd); + } else { + ret = -1; + } + + RET (ret); +} + + +static void +ext2_initializer( ext2_info_t *dummy ) +{ + fword("register-fs-package"); +} + +NODE_METHODS( ext2 ) = { + { "probe", ext2_files_probe }, + { "open", ext2_files_open }, + { "close", ext2_files_close }, + { "read", ext2_files_read }, + { "seek", ext2_files_seek }, + { "load", ext2_files_load }, + { "dir", ext2_files_dir }, + + /* special */ + { "get-path", ext2_files_get_path }, + { "get-fstype", ext2_files_get_fstype }, + + { NULL, ext2_initializer }, +}; + +void +ext2_init( void ) +{ + REGISTER_NODE( ext2 ); +} diff --git a/qemu/roms/openbios/fs/ext2/ext2_fs.h b/qemu/roms/openbios/fs/ext2/ext2_fs.h new file mode 100644 index 000000000..4a7adff7d --- /dev/null +++ b/qemu/roms/openbios/fs/ext2/ext2_fs.h @@ -0,0 +1,534 @@ +/* + * This file has been copied from + * linux/include/linux/ext2_fs.h + * + * Copyright (C) 1992, 1993, 1994, 1995 + * Remy Card (card@masi.ibp.fr) + * Laboratoire MASI - Institut Blaise Pascal + * Universite Pierre et Marie Curie (Paris VI) + * + * from + * + * linux/include/linux/minix_fs.h + * + * Copyright (C) 1991, 1992 Linus Torvalds + */ + +#ifndef _EXT2_FS_H +#define _EXT2_FS_H + +/* from /usr/include/linux/magic.h */ + +#define EXT2_SUPER_MAGIC 0xEF53 + +/* + * The second extended filesystem constants/structures + */ + +/* + * Define EXT2FS_DEBUG to produce debug messages + */ +#undef EXT2FS_DEBUG + +/* + * Define EXT2_RESERVATION to reserve data blocks for expanding files + */ +#define EXT2_DEFAULT_RESERVE_BLOCKS 8 +/*max window size: 1024(direct blocks) + 3([t,d]indirect blocks) */ +#define EXT2_MAX_RESERVE_BLOCKS 1027 +#define EXT2_RESERVE_WINDOW_NOT_ALLOCATED 0 +/* + * The second extended file system version + */ +#define EXT2FS_DATE "95/08/09" +#define EXT2FS_VERSION "0.5b" + +/* + * Debug code + */ +#ifdef EXT2FS_DEBUG +# define ext2_debug(f, a...) { \ + printk ("EXT2-fs DEBUG (%s, %d): %s:", \ + __FILE__, __LINE__, __FUNCTION__); \ + printk (f, ## a); \ + } +#else +# define ext2_debug(f, a...) /**/ +#endif + +/* + * Special inode numbers + */ +#define EXT2_BAD_INO 1 /* Bad blocks inode */ +#define EXT2_ROOT_INO 2 /* Root inode */ +#define EXT2_BOOT_LOADER_INO 5 /* Boot loader inode */ +#define EXT2_UNDEL_DIR_INO 6 /* Undelete directory inode */ + +/* First non-reserved inode for old ext2 filesystems */ +#define EXT2_GOOD_OLD_FIRST_INO 11 + +/* Assume that user mode programs are passing in an ext2fs superblock, not + * a kernel struct super_block. This will allow us to call the feature-test + * macros from user land. */ +#define EXT2_SB(sb) (sb) + +/* + * Maximal count of links to a file + */ +#define EXT2_LINK_MAX 32000 + +/* + * Macro-instructions used to manage several block sizes + */ +#define EXT2_MIN_BLOCK_SIZE 1024 +#define EXT2_MAX_BLOCK_SIZE 4096 +#define EXT2_MIN_BLOCK_LOG_SIZE 10 +# define EXT2_BLOCK_SIZE(s) (EXT2_MIN_BLOCK_SIZE << (s)->s_log_block_size) +#define EXT2_ADDR_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (uint32_t)) +# define EXT2_BLOCK_SIZE_BITS(s) ((s)->s_log_block_size + 10) +#define EXT2_INODE_SIZE(s) (((s)->s_rev_level == EXT2_GOOD_OLD_REV) ? \ + EXT2_GOOD_OLD_INODE_SIZE : \ + (s)->s_inode_size) +#define EXT2_FIRST_INO(s) (((s)->s_rev_level == EXT2_GOOD_OLD_REV) ? \ + EXT2_GOOD_OLD_FIRST_INO : \ + (s)->s_first_ino) + +/* + * Macro-instructions used to manage fragments + */ +#define EXT2_MIN_FRAG_SIZE 1024 +#define EXT2_MAX_FRAG_SIZE 4096 +#define EXT2_MIN_FRAG_LOG_SIZE 10 +# define EXT2_FRAG_SIZE(s) (EXT2_MIN_FRAG_SIZE << (s)->s_log_frag_size) +# define EXT2_FRAGS_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / EXT2_FRAG_SIZE(s)) + +/* + * Structure of a blocks group descriptor + */ +struct ext2_group_desc +{ + uint32_t bg_block_bitmap; /* Blocks bitmap block */ + uint32_t bg_inode_bitmap; /* Inodes bitmap block */ + uint32_t bg_inode_table; /* Inodes table block */ + uint16_t bg_free_blocks_count; /* Free blocks count */ + uint16_t bg_free_inodes_count; /* Free inodes count */ + uint16_t bg_used_dirs_count; /* Directories count */ + uint16_t bg_pad; + uint32_t bg_reserved[3]; +}; + +/* + * Macro-instructions used to manage group descriptors + */ +# define EXT2_BLOCKS_PER_GROUP(s) ((s)->s_blocks_per_group) +# define EXT2_DESC_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_group_desc)) +# define EXT2_INODES_PER_GROUP(s) ((s)->s_inodes_per_group) + +/* + * Constants relative to the data blocks + */ +#define EXT2_NDIR_BLOCKS 12 +#define EXT2_IND_BLOCK EXT2_NDIR_BLOCKS +#define EXT2_DIND_BLOCK (EXT2_IND_BLOCK + 1) +#define EXT2_TIND_BLOCK (EXT2_DIND_BLOCK + 1) +#define EXT2_N_BLOCKS (EXT2_TIND_BLOCK + 1) + +/* + * Inode flags (GETFLAGS/SETFLAGS) + */ +#define EXT2_SECRM_FL FS_SECRM_FL /* Secure deletion */ +#define EXT2_UNRM_FL FS_UNRM_FL /* Undelete */ +#define EXT2_COMPR_FL FS_COMPR_FL /* Compress file */ +#define EXT2_SYNC_FL FS_SYNC_FL /* Synchronous updates */ +#define EXT2_IMMUTABLE_FL FS_IMMUTABLE_FL /* Immutable file */ +#define EXT2_APPEND_FL FS_APPEND_FL /* writes to file may only append */ +#define EXT2_NODUMP_FL FS_NODUMP_FL /* do not dump file */ +#define EXT2_NOATIME_FL FS_NOATIME_FL /* do not update atime */ +/* Reserved for compression usage... */ +#define EXT2_DIRTY_FL FS_DIRTY_FL +#define EXT2_COMPRBLK_FL FS_COMPRBLK_FL /* One or more compressed clusters */ +#define EXT2_NOCOMP_FL FS_NOCOMP_FL /* Don't compress */ +#define EXT2_ECOMPR_FL FS_ECOMPR_FL /* Compression error */ +/* End compression flags --- maybe not all used */ +#define EXT2_BTREE_FL FS_BTREE_FL /* btree format dir */ +#define EXT2_INDEX_FL FS_INDEX_FL /* hash-indexed directory */ +#define EXT2_IMAGIC_FL FS_IMAGIC_FL /* AFS directory */ +#define EXT2_JOURNAL_DATA_FL FS_JOURNAL_DATA_FL /* Reserved for ext3 */ +#define EXT2_NOTAIL_FL FS_NOTAIL_FL /* file tail should not be merged */ +#define EXT2_DIRSYNC_FL FS_DIRSYNC_FL /* dirsync behaviour (directories only) */ +#define EXT2_TOPDIR_FL FS_TOPDIR_FL /* Top of directory hierarchies*/ +#define EXT2_RESERVED_FL FS_RESERVED_FL /* reserved for ext2 lib */ + +#define EXT2_FL_USER_VISIBLE FS_FL_USER_VISIBLE /* User visible flags */ +#define EXT2_FL_USER_MODIFIABLE FS_FL_USER_MODIFIABLE /* User modifiable flags */ + +/* + * ioctl commands + */ +#define EXT2_IOC_GETFLAGS FS_IOC_GETFLAGS +#define EXT2_IOC_SETFLAGS FS_IOC_SETFLAGS +#define EXT2_IOC_GETVERSION FS_IOC_GETVERSION +#define EXT2_IOC_SETVERSION FS_IOC_SETVERSION +#define EXT2_IOC_GETRSVSZ _IOR('f', 5, long) +#define EXT2_IOC_SETRSVSZ _IOW('f', 6, long) + +/* + * ioctl commands in 32 bit emulation + */ +#define EXT2_IOC32_GETFLAGS FS_IOC32_GETFLAGS +#define EXT2_IOC32_SETFLAGS FS_IOC32_SETFLAGS +#define EXT2_IOC32_GETVERSION FS_IOC32_GETVERSION +#define EXT2_IOC32_SETVERSION FS_IOC32_SETVERSION + +/* + * Structure of an inode on the disk + */ +struct ext2_inode { + uint16_t i_mode; /* File mode */ + uint16_t i_uid; /* Low 16 bits of Owner Uid */ + uint32_t i_size; /* Size in bytes */ + uint32_t i_atime; /* Access time */ + uint32_t i_ctime; /* Creation time */ + uint32_t i_mtime; /* Modification time */ + uint32_t i_dtime; /* Deletion Time */ + uint16_t i_gid; /* Low 16 bits of Group Id */ + uint16_t i_links_count; /* Links count */ + uint32_t i_blocks; /* Blocks count */ + uint32_t i_flags; /* File flags */ + union { + struct { + uint32_t l_i_reserved1; + } linux1; + struct { + uint32_t h_i_translator; + } hurd1; + struct { + uint32_t m_i_reserved1; + } masix1; + } osd1; /* OS dependent 1 */ + uint32_t i_block[EXT2_N_BLOCKS];/* Pointers to blocks */ + uint32_t i_generation; /* File version (for NFS) */ + uint32_t i_file_acl; /* File ACL */ + uint32_t i_dir_acl; /* Directory ACL */ + uint32_t i_faddr; /* Fragment address */ + union { + struct { + uint8_t l_i_frag; /* Fragment number */ + uint8_t l_i_fsize; /* Fragment size */ + uint16_t i_pad1; + uint16_t l_i_uid_high; /* these 2 fields */ + uint16_t l_i_gid_high; /* were reserved2[0] */ + uint32_t l_i_reserved2; + } linux2; + struct { + uint8_t h_i_frag; /* Fragment number */ + uint8_t h_i_fsize; /* Fragment size */ + uint16_t h_i_mode_high; + uint16_t h_i_uid_high; + uint16_t h_i_gid_high; + uint32_t h_i_author; + } hurd2; + struct { + uint8_t m_i_frag; /* Fragment number */ + uint8_t m_i_fsize; /* Fragment size */ + uint16_t m_pad1; + uint32_t m_i_reserved2[2]; + } masix2; + } osd2; /* OS dependent 2 */ +}; + +#define i_size_high i_dir_acl + +#if defined(__KERNEL__) || defined(__linux__) +#define i_reserved1 osd1.linux1.l_i_reserved1 +#define i_frag osd2.linux2.l_i_frag +#define i_fsize osd2.linux2.l_i_fsize +#define i_uid_low i_uid +#define i_gid_low i_gid +#define i_uid_high osd2.linux2.l_i_uid_high +#define i_gid_high osd2.linux2.l_i_gid_high +#define i_reserved2 osd2.linux2.l_i_reserved2 +#endif + +#ifdef __hurd__ +#define i_translator osd1.hurd1.h_i_translator +#define i_frag osd2.hurd2.h_i_frag; +#define i_fsize osd2.hurd2.h_i_fsize; +#define i_uid_high osd2.hurd2.h_i_uid_high +#define i_gid_high osd2.hurd2.h_i_gid_high +#define i_author osd2.hurd2.h_i_author +#endif + +#ifdef __masix__ +#define i_reserved1 osd1.masix1.m_i_reserved1 +#define i_frag osd2.masix2.m_i_frag +#define i_fsize osd2.masix2.m_i_fsize +#define i_reserved2 osd2.masix2.m_i_reserved2 +#endif + +/* + * File system states + */ +#define EXT2_VALID_FS 0x0001 /* Unmounted cleanly */ +#define EXT2_ERROR_FS 0x0002 /* Errors detected */ + +/* + * Mount flags + */ +#define EXT2_MOUNT_CHECK 0x000001 /* Do mount-time checks */ +#define EXT2_MOUNT_OLDALLOC 0x000002 /* Don't use the new Orlov allocator */ +#define EXT2_MOUNT_GRPID 0x000004 /* Create files with directory's group */ +#define EXT2_MOUNT_DEBUG 0x000008 /* Some debugging messages */ +#define EXT2_MOUNT_ERRORS_CONT 0x000010 /* Continue on errors */ +#define EXT2_MOUNT_ERRORS_RO 0x000020 /* Remount fs ro on errors */ +#define EXT2_MOUNT_ERRORS_PANIC 0x000040 /* Panic on errors */ +#define EXT2_MOUNT_MINIX_DF 0x000080 /* Mimics the Minix statfs */ +#define EXT2_MOUNT_NOBH 0x000100 /* No buffer_heads */ +#define EXT2_MOUNT_NO_UID32 0x000200 /* Disable 32-bit UIDs */ +#define EXT2_MOUNT_XATTR_USER 0x004000 /* Extended user attributes */ +#define EXT2_MOUNT_POSIX_ACL 0x008000 /* POSIX Access Control Lists */ +#define EXT2_MOUNT_XIP 0x010000 /* Execute in place */ +#define EXT2_MOUNT_USRQUOTA 0x020000 /* user quota */ +#define EXT2_MOUNT_GRPQUOTA 0x040000 /* group quota */ +#define EXT2_MOUNT_RESERVATION 0x080000 /* Preallocation */ + + +#define clear_opt(o, opt) o &= ~EXT2_MOUNT_##opt +#define set_opt(o, opt) o |= EXT2_MOUNT_##opt +#define test_opt(sb, opt) (EXT2_SB(sb)->s_mount_opt & \ + EXT2_MOUNT_##opt) +/* + * Maximal mount counts between two filesystem checks + */ +#define EXT2_DFL_MAX_MNT_COUNT 20 /* Allow 20 mounts */ +#define EXT2_DFL_CHECKINTERVAL 0 /* Don't use interval check */ + +/* + * Behaviour when detecting errors + */ +#define EXT2_ERRORS_CONTINUE 1 /* Continue execution */ +#define EXT2_ERRORS_RO 2 /* Remount fs read-only */ +#define EXT2_ERRORS_PANIC 3 /* Panic */ +#define EXT2_ERRORS_DEFAULT EXT2_ERRORS_CONTINUE + +/* + * Structure of the super block + */ +struct ext2_super_block { + uint32_t s_inodes_count; /* Inodes count */ + uint32_t s_blocks_count; /* Blocks count */ + uint32_t s_r_blocks_count; /* Reserved blocks count */ + uint32_t s_free_blocks_count; /* Free blocks count */ + uint32_t s_free_inodes_count; /* Free inodes count */ + uint32_t s_first_data_block; /* First Data Block */ + uint32_t s_log_block_size; /* Block size */ + uint32_t s_log_frag_size; /* Fragment size */ + uint32_t s_blocks_per_group; /* # Blocks per group */ + uint32_t s_frags_per_group; /* # Fragments per group */ + uint32_t s_inodes_per_group; /* # Inodes per group */ + uint32_t s_mtime; /* Mount time */ + uint32_t s_wtime; /* Write time */ + uint16_t s_mnt_count; /* Mount count */ + uint16_t s_max_mnt_count; /* Maximal mount count */ + uint16_t s_magic; /* Magic signature */ + uint16_t s_state; /* File system state */ + uint16_t s_errors; /* Behaviour when detecting errors */ + uint16_t s_minor_rev_level; /* minor revision level */ + uint32_t s_lastcheck; /* time of last check */ + uint32_t s_checkinterval; /* max. time between checks */ + uint32_t s_creator_os; /* OS */ + uint32_t s_rev_level; /* Revision level */ + uint16_t s_def_resuid; /* Default uid for reserved blocks */ + uint16_t s_def_resgid; /* Default gid for reserved blocks */ + /* + * These fields are for EXT2_DYNAMIC_REV superblocks only. + * + * Note: the difference between the compatible feature set and + * the incompatible feature set is that if there is a bit set + * in the incompatible feature set that the kernel doesn't + * know about, it should refuse to mount the filesystem. + * + * e2fsck's requirements are more strict; if it doesn't know + * about a feature in either the compatible or incompatible + * feature set, it must abort and not try to meddle with + * things it doesn't understand... + */ + uint32_t s_first_ino; /* First non-reserved inode */ + uint16_t s_inode_size; /* size of inode structure */ + uint16_t s_block_group_nr; /* block group # of this superblock */ + uint32_t s_feature_compat; /* compatible feature set */ + uint32_t s_feature_incompat; /* incompatible feature set */ + uint32_t s_feature_ro_compat; /* readonly-compatible feature set */ + uint8_t s_uuid[16]; /* 128-bit uuid for volume */ + char s_volume_name[16]; /* volume name */ + char s_last_mounted[64]; /* directory where last mounted */ + uint32_t s_algorithm_usage_bitmap; /* For compression */ + /* + * Performance hints. Directory preallocation should only + * happen if the EXT2_COMPAT_PREALLOC flag is on. + */ + uint8_t s_prealloc_blocks; /* Nr of blocks to try to preallocate*/ + uint8_t s_prealloc_dir_blocks; /* Nr to preallocate for dirs */ + uint16_t s_padding1; + /* + * Journaling support valid if EXT3_FEATURE_COMPAT_HAS_JOURNAL set. + */ + uint8_t s_journal_uuid[16]; /* uuid of journal superblock */ + uint32_t s_journal_inum; /* inode number of journal file */ + uint32_t s_journal_dev; /* device number of journal file */ + uint32_t s_last_orphan; /* start of list of inodes to delete */ + uint32_t s_hash_seed[4]; /* HTREE hash seed */ + uint8_t s_def_hash_version; /* Default hash version to use */ + uint8_t s_reserved_char_pad; + uint16_t s_reserved_word_pad; + uint32_t s_default_mount_opts; + uint32_t s_first_meta_bg; /* First metablock block group */ + uint32_t s_reserved[190]; /* Padding to the end of the block */ +}; + +/* + * Codes for operating systems + */ +#define EXT2_OS_LINUX 0 +#define EXT2_OS_HURD 1 +#define EXT2_OS_MASIX 2 +#define EXT2_OS_FREEBSD 3 +#define EXT2_OS_LITES 4 + +/* + * Revision levels + */ +#define EXT2_GOOD_OLD_REV 0 /* The good old (original) format */ +#define EXT2_DYNAMIC_REV 1 /* V2 format w/ dynamic inode sizes */ + +#define EXT2_CURRENT_REV EXT2_GOOD_OLD_REV +#define EXT2_MAX_SUPP_REV EXT2_DYNAMIC_REV + +#define EXT2_GOOD_OLD_INODE_SIZE 128 + +/* + * Feature set definitions + */ + +#define EXT2_HAS_COMPAT_FEATURE(sb,mask) \ + ( EXT2_SB(sb)->s_es->s_feature_compat & cpu_to_le32(mask) ) +#define EXT2_HAS_RO_COMPAT_FEATURE(sb,mask) \ + ( EXT2_SB(sb)->s_es->s_feature_ro_compat & cpu_to_le32(mask) ) +#define EXT2_HAS_INCOMPAT_FEATURE(sb,mask) \ + ( EXT2_SB(sb)->s_es->s_feature_incompat & cpu_to_le32(mask) ) +#define EXT2_SET_COMPAT_FEATURE(sb,mask) \ + EXT2_SB(sb)->s_es->s_feature_compat |= cpu_to_le32(mask) +#define EXT2_SET_RO_COMPAT_FEATURE(sb,mask) \ + EXT2_SB(sb)->s_es->s_feature_ro_compat |= cpu_to_le32(mask) +#define EXT2_SET_INCOMPAT_FEATURE(sb,mask) \ + EXT2_SB(sb)->s_es->s_feature_incompat |= cpu_to_le32(mask) +#define EXT2_CLEAR_COMPAT_FEATURE(sb,mask) \ + EXT2_SB(sb)->s_es->s_feature_compat &= ~cpu_to_le32(mask) +#define EXT2_CLEAR_RO_COMPAT_FEATURE(sb,mask) \ + EXT2_SB(sb)->s_es->s_feature_ro_compat &= ~cpu_to_le32(mask) +#define EXT2_CLEAR_INCOMPAT_FEATURE(sb,mask) \ + EXT2_SB(sb)->s_es->s_feature_incompat &= ~cpu_to_le32(mask) + +#define EXT2_FEATURE_COMPAT_DIR_PREALLOC 0x0001 +#define EXT2_FEATURE_COMPAT_IMAGIC_INODES 0x0002 +#define EXT3_FEATURE_COMPAT_HAS_JOURNAL 0x0004 +#define EXT2_FEATURE_COMPAT_EXT_ATTR 0x0008 +#define EXT2_FEATURE_COMPAT_RESIZE_INO 0x0010 +#define EXT2_FEATURE_COMPAT_DIR_INDEX 0x0020 +#define EXT2_FEATURE_COMPAT_ANY 0xffffffff + +#define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001 +#define EXT2_FEATURE_RO_COMPAT_LARGE_FILE 0x0002 +#define EXT2_FEATURE_RO_COMPAT_BTREE_DIR 0x0004 +#define EXT2_FEATURE_RO_COMPAT_ANY 0xffffffff + +#define EXT2_FEATURE_INCOMPAT_COMPRESSION 0x0001 +#define EXT2_FEATURE_INCOMPAT_FILETYPE 0x0002 +#define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004 +#define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 +#define EXT2_FEATURE_INCOMPAT_META_BG 0x0010 +#define EXT2_FEATURE_INCOMPAT_ANY 0xffffffff + +#define EXT2_FEATURE_COMPAT_SUPP EXT2_FEATURE_COMPAT_EXT_ATTR +#define EXT2_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE| \ + EXT2_FEATURE_INCOMPAT_META_BG) +#define EXT2_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \ + EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \ + EXT2_FEATURE_RO_COMPAT_BTREE_DIR) +#define EXT2_FEATURE_RO_COMPAT_UNSUPPORTED ~EXT2_FEATURE_RO_COMPAT_SUPP +#define EXT2_FEATURE_INCOMPAT_UNSUPPORTED ~EXT2_FEATURE_INCOMPAT_SUPP + +/* + * Default values for user and/or group using reserved blocks + */ +#define EXT2_DEF_RESUID 0 +#define EXT2_DEF_RESGID 0 + +/* + * Default mount options + */ +#define EXT2_DEFM_DEBUG 0x0001 +#define EXT2_DEFM_BSDGROUPS 0x0002 +#define EXT2_DEFM_XATTR_USER 0x0004 +#define EXT2_DEFM_ACL 0x0008 +#define EXT2_DEFM_UID16 0x0010 + /* Not used by ext2, but reserved for use by ext3 */ +#define EXT3_DEFM_JMODE 0x0060 +#define EXT3_DEFM_JMODE_DATA 0x0020 +#define EXT3_DEFM_JMODE_ORDERED 0x0040 +#define EXT3_DEFM_JMODE_WBACK 0x0060 + +/* + * Structure of a directory entry + */ +#define EXT2_NAME_LEN 255 + +struct ext2_dir_entry { + uint32_t inode; /* Inode number */ + uint16_t rec_len; /* Directory entry length */ + uint16_t name_len; /* Name length */ + char name[EXT2_NAME_LEN]; /* File name */ +}; + +/* + * The new version of the directory entry. Since EXT2 structures are + * stored in intel byte order, and the name_len field could never be + * bigger than 255 chars, it's safe to reclaim the extra byte for the + * file_type field. + */ +struct ext2_dir_entry_2 { + uint32_t inode; /* Inode number */ + uint16_t rec_len; /* Directory entry length */ + uint8_t name_len; /* Name length */ + uint8_t file_type; + char name[EXT2_NAME_LEN]; /* File name */ +}; + +/* + * Ext2 directory file types. Only the low 3 bits are used. The + * other bits are reserved for now. + */ +enum { + EXT2_FT_UNKNOWN, + EXT2_FT_REG_FILE, + EXT2_FT_DIR, + EXT2_FT_CHRDEV, + EXT2_FT_BLKDEV, + EXT2_FT_FIFO, + EXT2_FT_SOCK, + EXT2_FT_SYMLINK, + EXT2_FT_MAX +}; + +/* + * EXT2_DIR_PAD defines the directory entries boundaries + * + * NOTE: It must be a multiple of 4 + */ +#define EXT2_DIR_PAD 4 +#define EXT2_DIR_ROUND (EXT2_DIR_PAD - 1) +#define EXT2_DIR_REC_LEN(name_len) (((name_len) + 8 + EXT2_DIR_ROUND) & \ + ~EXT2_DIR_ROUND) +#define EXT2_MAX_REC_LEN ((1<<16)-1) + +#endif /* _EXT2_FS_H */ diff --git a/qemu/roms/openbios/fs/ext2/ext2_lseek.c b/qemu/roms/openbios/fs/ext2/ext2_lseek.c new file mode 100644 index 000000000..e837d89b4 --- /dev/null +++ b/qemu/roms/openbios/fs/ext2/ext2_lseek.c @@ -0,0 +1,38 @@ +/* + * + * (c) 2008-2009 Laurent Vivier <Laurent@lvivier.info> + * + * This file has been copied from EMILE, http://emile.sf.net + * + */ + +#include "libext2.h" +#include "ext2.h" + +int ext2_lseek(ext2_FILE *file, long offset, int whence) +{ + long new_offset; + + switch(whence) + { + case SEEK_SET: + new_offset = offset; + break; + case SEEK_CUR: + new_offset = file->offset + offset; + break; + case SEEK_END: + new_offset = file->inode->i_size + offset; + break; + default: + return -1; + } + + if ( (new_offset < 0) || + (new_offset > file->inode->i_size) ) + return -1; + + file->offset = new_offset; + + return new_offset; +} diff --git a/qemu/roms/openbios/fs/ext2/ext2_mount.c b/qemu/roms/openbios/fs/ext2/ext2_mount.c new file mode 100644 index 000000000..06b63deca --- /dev/null +++ b/qemu/roms/openbios/fs/ext2/ext2_mount.c @@ -0,0 +1,62 @@ +/* + * + * (c) 2008-2009 Laurent Vivier <Laurent@lvivier.info> + * + * This file has been copied from EMILE, http://emile.sf.net + * + */ + +#include "libext2.h" +#include "ext2.h" +#include "ext2_utils.h" + +#define SB_OFFSET (2) + +ext2_VOLUME* ext2_mount(int fd) +{ + ext2_VOLUME *volume; + struct ext2_super_block *super; + char *buffer; + + super = (struct ext2_super_block*)malloc(sizeof(struct ext2_super_block)); + if (super == NULL) + return NULL; + + ext2_get_super(fd, super); + if (super->s_magic != EXT2_SUPER_MAGIC) { + free(super); + return NULL; + } + + buffer = (char*)malloc(EXT2_BLOCK_SIZE(super)); + if (buffer == NULL) { + free(super); + return NULL; + } + + volume = (ext2_VOLUME*)malloc(sizeof(ext2_VOLUME)); + if (volume == NULL) { + free(super); + free(buffer); + return NULL; + } + + volume->buffer = buffer; + volume->fd = fd; + volume->super = super; + + volume->current = -1; + ext2_read_block(volume, 0); + + return volume; +} + +int ext2_umount(ext2_VOLUME* volume) +{ + if (volume == NULL) + return -1; + free(volume->super); + free(volume->buffer); + free(volume); + return 0; +} diff --git a/qemu/roms/openbios/fs/ext2/ext2_open.c b/qemu/roms/openbios/fs/ext2/ext2_open.c new file mode 100644 index 000000000..03a89bbd0 --- /dev/null +++ b/qemu/roms/openbios/fs/ext2/ext2_open.c @@ -0,0 +1,65 @@ +/* + * + * (c) 2008-2009 Laurent Vivier <Laurent@lvivier.info> + * + * This file has been copied from EMILE, http://emile.sf.net + * + */ + +#include "libext2.h" +#include "ext2.h" +#include "ext2_utils.h" + +ext2_FILE* ext2_open(ext2_VOLUME *volume, const char* pathname) +{ + ext2_FILE *file; + struct ext2_inode *inode; + int ino; + int ret; + + ino = ext2_seek_name(volume, pathname); + if (ino == 0) + return NULL; + + inode = (struct ext2_inode*)malloc(sizeof(struct ext2_inode)); + if (inode == NULL) + return NULL; + + ret = ext2_get_inode(volume, ino, inode); + if (ret == -1) { + free(inode); + return NULL; + } + if (S_ISLNK(inode->i_mode)) { + static char buffer[1024]; + int i, last = 0; + strcpy(buffer, pathname); + for (i = 0; buffer[i]; i++) + if (buffer[i] == '\\') + last = i; + buffer[last] = '\\'; + strcpy(buffer + last + 1, (char*)inode->i_block); + ino = ext2_seek_name((ext2_VOLUME*)volume, buffer); + if (ino == 0) { + free(inode); + return NULL; + } + ret = ext2_get_inode((ext2_VOLUME*)volume, ino, inode); + if (ret == -1) { + free(inode); + return NULL; + } + } + + file = (ext2_FILE*)malloc(sizeof(ext2_FILE)); + if (file == NULL) { + free(inode); + return NULL; + } + file->volume = volume; + file->inode = inode; + file->offset = 0; + file->path = strdup(pathname); + + return file; +} diff --git a/qemu/roms/openbios/fs/ext2/ext2_opendir.c b/qemu/roms/openbios/fs/ext2/ext2_opendir.c new file mode 100644 index 000000000..3363e0b3a --- /dev/null +++ b/qemu/roms/openbios/fs/ext2/ext2_opendir.c @@ -0,0 +1,49 @@ +/* + * + * (c) 2008-2009 Laurent Vivier <Laurent@lvivier.info> + * + * This file has been copied from EMILE, http://emile.sf.net + * + */ + +#include "libext2.h" +#include "ext2.h" +#include "ext2_utils.h" + +ext2_DIR* ext2_opendir(ext2_VOLUME *volume, const char *name) +{ + ext2_DIR* dir; + int ino; + struct ext2_inode *inode; + int ret; + + ino = ext2_seek_name(volume, name); + if (ino == 0) + return NULL; + + inode = (struct ext2_inode*)malloc(sizeof(struct ext2_inode)); + if (inode == NULL) + return NULL; + + ret = ext2_get_inode(volume, ino, inode); + if (ret == -1) { + free(inode); + return NULL; + } + + if (!S_ISDIR(inode->i_mode)) { + free(inode); + return NULL; + } + + dir = (ext2_DIR*)malloc(sizeof(ext2_DIR)); + if (dir == NULL) { + free(inode); + return NULL; + } + dir->volume = (ext2_VOLUME*)volume; + dir->inode = inode; + dir->index = 0; + + return dir; +} diff --git a/qemu/roms/openbios/fs/ext2/ext2_read.c b/qemu/roms/openbios/fs/ext2/ext2_read.c new file mode 100644 index 000000000..975b3675b --- /dev/null +++ b/qemu/roms/openbios/fs/ext2/ext2_read.c @@ -0,0 +1,23 @@ +/* + * + * (c) 2008-2009 Laurent Vivier <Laurent@lvivier.info> + * + * This file has been copied from EMILE, http://emile.sf.net + * + */ + +#include "libext2.h" +#include "ext2.h" +#include "ext2_utils.h" + +size_t ext2_read(ext2_FILE *file, void *buf, size_t count) +{ + int ret; + + ret = ext2_read_data(file->volume, file->inode, file->offset, + buf, count); + if (ret == -1) + return -1; + file->offset += ret; + return ret; +} diff --git a/qemu/roms/openbios/fs/ext2/ext2_readdir.c b/qemu/roms/openbios/fs/ext2/ext2_readdir.c new file mode 100644 index 000000000..09ba95c9d --- /dev/null +++ b/qemu/roms/openbios/fs/ext2/ext2_readdir.c @@ -0,0 +1,25 @@ +/* + * + * (c) 2008-2009 Laurent Vivier <Laurent@lvivier.info> + * + * This file has been copied from EMILE, http://emile.sf.net + * + */ + +#include "libext2.h" +#include "ext2_utils.h" + +static struct ext2_dir_entry_2 entry; + +struct ext2_dir_entry_2 *ext2_readdir(ext2_DIR *dir) +{ + int ret; + + ret = ext2_dir_entry(dir->volume, dir->inode, dir->index, &entry); + if (ret == -1) + return NULL; + dir->index = ret; + + entry.name[entry.name_len] = 0; + return &entry; +} diff --git a/qemu/roms/openbios/fs/ext2/ext2_utils.c b/qemu/roms/openbios/fs/ext2/ext2_utils.c new file mode 100644 index 000000000..64563c826 --- /dev/null +++ b/qemu/roms/openbios/fs/ext2/ext2_utils.c @@ -0,0 +1,332 @@ +/* + * + * (c) 2008-2009 Laurent Vivier <Laurent@lvivier.info> + * + * This file has been copied from EMILE, http://emile.sf.net + * + */ + +#include "libext2.h" +#include "ext2_utils.h" +#include "libopenbios/bindings.h" +#include "libc/diskio.h" +#include "libc/byteorder.h" + +int ext2_probe(int fd, long long offset) +{ + struct ext2_super_block *super; + + super = (struct ext2_super_block*)malloc(sizeof(struct ext2_super_block)); + seek_io(fd, 2 * 512 + offset); + read_io(fd, super, sizeof (*super)); + + if (__le16_to_cpu(super->s_magic) != EXT2_SUPER_MAGIC) { + free(super); + return 0; + } + + free(super); + return -1; +} + +void ext2_get_super(int fd, struct ext2_super_block *super) +{ + seek_io(fd, 2 * 512); + read_io(fd, super, sizeof (*super)); + + super->s_inodes_count = __le32_to_cpu(super->s_inodes_count); + super->s_blocks_count = __le32_to_cpu(super->s_blocks_count); + super->s_r_blocks_count = __le32_to_cpu(super->s_r_blocks_count); + super->s_free_blocks_count = __le32_to_cpu(super->s_free_blocks_count); + super->s_free_inodes_count = __le32_to_cpu(super->s_free_inodes_count); + super->s_first_data_block = __le32_to_cpu(super->s_first_data_block); + super->s_log_block_size = __le32_to_cpu(super->s_log_block_size); + super->s_log_frag_size = __le32_to_cpu(super->s_log_frag_size); + super->s_blocks_per_group = __le32_to_cpu(super->s_blocks_per_group); + super->s_frags_per_group = __le32_to_cpu(super->s_frags_per_group); + super->s_inodes_per_group = __le32_to_cpu(super->s_inodes_per_group); + super->s_mtime = __le32_to_cpu(super->s_mtime); + super->s_wtime = __le32_to_cpu(super->s_wtime); + super->s_mnt_count = __le16_to_cpu(super->s_mnt_count); + super->s_max_mnt_count = __le16_to_cpu(super->s_max_mnt_count); + super->s_magic = __le16_to_cpu(super->s_magic); + super->s_state = __le16_to_cpu(super->s_state); + super->s_errors = __le16_to_cpu(super->s_errors); + super->s_minor_rev_level = __le16_to_cpu(super->s_minor_rev_level); + super->s_lastcheck = __le32_to_cpu(super->s_lastcheck); + super->s_checkinterval = __le32_to_cpu(super->s_checkinterval); + super->s_creator_os = __le32_to_cpu(super->s_creator_os); + super->s_rev_level = __le32_to_cpu(super->s_rev_level); + super->s_def_resuid = __le16_to_cpu(super->s_def_resuid); + super->s_def_resgid = __le16_to_cpu(super->s_def_resgid); + super->s_first_ino = __le32_to_cpu(super->s_first_ino); + super->s_inode_size = __le16_to_cpu(super->s_inode_size); + super->s_block_group_nr = __le16_to_cpu(super->s_block_group_nr); + super->s_feature_compat = __le32_to_cpu(super->s_feature_compat); + super->s_feature_incompat = __le32_to_cpu(super->s_feature_incompat); + super->s_feature_ro_compat = __le32_to_cpu(super->s_feature_ro_compat); + super->s_algorithm_usage_bitmap = + __le32_to_cpu(super->s_algorithm_usage_bitmap); + super->s_journal_inum = __le32_to_cpu(super->s_journal_inum); + super->s_journal_dev = __le32_to_cpu(super->s_journal_dev); + super->s_last_orphan = __le32_to_cpu(super->s_last_orphan); + super->s_hash_seed[0] = __le32_to_cpu(super->s_hash_seed[0]); + super->s_hash_seed[1] = __le32_to_cpu(super->s_hash_seed[1]); + super->s_hash_seed[2] = __le32_to_cpu(super->s_hash_seed[2]); + super->s_hash_seed[3] = __le32_to_cpu(super->s_hash_seed[3]); + super->s_default_mount_opts = + __le32_to_cpu(super->s_default_mount_opts); + super->s_first_meta_bg = __le32_to_cpu(super->s_first_meta_bg); +} + +void ext2_read_block(ext2_VOLUME* volume, unsigned int fsblock) +{ + long long offset; + + if (fsblock == volume->current) + return; + + volume->current = fsblock; + offset = fsblock * EXT2_BLOCK_SIZE(volume->super); + + seek_io(volume->fd, offset); + read_io(volume->fd, volume->buffer, EXT2_BLOCK_SIZE(volume->super)); +} + +void ext2_get_group_desc(ext2_VOLUME* volume, + int group_id, struct ext2_group_desc *gdp) +{ + unsigned int block, offset; + struct ext2_group_desc *le_gdp; + + block = 1 + volume->super->s_first_data_block; + block += group_id / EXT2_DESC_PER_BLOCK(volume->super); + ext2_read_block(volume, block); + + offset = group_id % EXT2_DESC_PER_BLOCK(volume->super); + offset *= sizeof(*gdp); + + le_gdp = (struct ext2_group_desc *)(volume->buffer + offset); + + gdp->bg_block_bitmap = __le32_to_cpu(le_gdp->bg_block_bitmap); + gdp->bg_inode_bitmap = __le32_to_cpu(le_gdp->bg_inode_bitmap); + gdp->bg_inode_table = __le32_to_cpu(le_gdp->bg_inode_table); + gdp->bg_free_blocks_count = __le16_to_cpu(le_gdp->bg_free_blocks_count); + gdp->bg_free_inodes_count = __le16_to_cpu(le_gdp->bg_free_inodes_count); + gdp->bg_used_dirs_count = __le16_to_cpu(le_gdp->bg_used_dirs_count); +} + +int ext2_get_inode(ext2_VOLUME* volume, + unsigned int ino, struct ext2_inode *inode) +{ + struct ext2_group_desc desc; + unsigned int block; + unsigned int group_id; + unsigned int offset; + struct ext2_inode *le_inode; + int i; + + ino--; + + group_id = ino / EXT2_INODES_PER_GROUP(volume->super); + ext2_get_group_desc(volume, group_id, &desc); + + ino %= EXT2_INODES_PER_GROUP(volume->super); + + block = desc.bg_inode_table; + block += ino / (EXT2_BLOCK_SIZE(volume->super) / + EXT2_INODE_SIZE(volume->super)); + ext2_read_block(volume, block); + + offset = ino % (EXT2_BLOCK_SIZE(volume->super) / + EXT2_INODE_SIZE(volume->super)); + offset *= EXT2_INODE_SIZE(volume->super); + + le_inode = (struct ext2_inode *)(volume->buffer + offset); + + inode->i_mode = __le16_to_cpu(le_inode->i_mode); + inode->i_uid = __le16_to_cpu(le_inode->i_uid); + inode->i_size = __le32_to_cpu(le_inode->i_size); + inode->i_atime = __le32_to_cpu(le_inode->i_atime); + inode->i_ctime = __le32_to_cpu(le_inode->i_ctime); + inode->i_mtime = __le32_to_cpu(le_inode->i_mtime); + inode->i_dtime = __le32_to_cpu(le_inode->i_dtime); + inode->i_gid = __le16_to_cpu(le_inode->i_gid); + inode->i_links_count = __le16_to_cpu(le_inode->i_links_count); + inode->i_blocks = __le32_to_cpu(le_inode->i_blocks); + inode->i_flags = __le32_to_cpu(le_inode->i_flags); + if (S_ISLNK(inode->i_mode)) { + memcpy(inode->i_block, le_inode->i_block, EXT2_N_BLOCKS * 4); + } else { + for (i = 0; i < EXT2_N_BLOCKS; i++) + inode->i_block[i] = __le32_to_cpu(le_inode->i_block[i]); + } + inode->i_generation = __le32_to_cpu(le_inode->i_generation); + inode->i_file_acl = __le32_to_cpu(le_inode->i_file_acl); + inode->i_dir_acl = __le32_to_cpu(le_inode->i_dir_acl); + inode->i_faddr = __le32_to_cpu(le_inode->i_faddr); + inode->osd2.linux2.l_i_frag = le_inode->osd2.linux2.l_i_frag; + inode->osd2.linux2.l_i_fsize = le_inode->osd2.linux2.l_i_fsize; + inode->osd2.linux2.l_i_uid_high = + __le16_to_cpu(le_inode->osd2.linux2.l_i_uid_high); + inode->osd2.linux2.l_i_gid_high = + __le16_to_cpu(le_inode->osd2.linux2.l_i_gid_high); + return 0; +} + +unsigned int ext2_get_block_addr(ext2_VOLUME* volume, struct ext2_inode *inode, + unsigned int logical) +{ + unsigned int physical; + unsigned int addr_per_block; + + /* direct */ + + if (logical < EXT2_NDIR_BLOCKS) { + physical = inode->i_block[logical]; + return physical; + } + + /* indirect */ + + logical -= EXT2_NDIR_BLOCKS; + + addr_per_block = EXT2_ADDR_PER_BLOCK (volume->super); + if (logical < addr_per_block) { + ext2_read_block(volume, inode->i_block[EXT2_IND_BLOCK]); + physical = __le32_to_cpu(((unsigned int *)volume->buffer)[logical]); + return physical; + } + + /* double indirect */ + + logical -= addr_per_block; + + if (logical < addr_per_block * addr_per_block) { + ext2_read_block(volume, inode->i_block[EXT2_DIND_BLOCK]); + physical = __le32_to_cpu(((unsigned int *)volume->buffer) + [logical / addr_per_block]); + ext2_read_block(volume, physical); + physical = __le32_to_cpu(((unsigned int *)volume->buffer) + [logical % addr_per_block]); + return physical; + } + + /* triple indirect */ + + logical -= addr_per_block * addr_per_block; + ext2_read_block(volume, inode->i_block[EXT2_DIND_BLOCK]); + physical = __le32_to_cpu(((unsigned int *)volume->buffer) + [logical / (addr_per_block * addr_per_block)]); + ext2_read_block(volume, physical); + logical = logical % (addr_per_block * addr_per_block); + physical = __le32_to_cpu(((unsigned int *)volume->buffer)[logical / addr_per_block]); + ext2_read_block(volume, physical); + physical = __le32_to_cpu(((unsigned int *)volume->buffer)[logical % addr_per_block]); + return physical; +} + +int ext2_read_data(ext2_VOLUME* volume, struct ext2_inode *inode, + off_t offset, char *buffer, size_t length) +{ + unsigned int logical, physical; + int blocksize = EXT2_BLOCK_SIZE(volume->super); + int shift; + size_t read; + + if (offset >= inode->i_size) + return -1; + + if (offset + length >= inode->i_size) + length = inode->i_size - offset; + + read = 0; + logical = offset / blocksize; + shift = offset % blocksize; + + if (shift) { + physical = ext2_get_block_addr(volume, inode, logical); + ext2_read_block(volume, physical); + + if (length < blocksize - shift) { + memcpy(buffer, volume->buffer + shift, length); + return length; + } + read += blocksize - shift; + memcpy(buffer, volume->buffer + shift, read); + + buffer += read; + length -= read; + logical++; + } + + while (length) { + physical = ext2_get_block_addr(volume, inode, logical); + ext2_read_block(volume, physical); + + if (length < blocksize) { + memcpy(buffer, volume->buffer, length); + read += length; + return read; + } + memcpy(buffer, volume->buffer, blocksize); + + buffer += blocksize; + length -= blocksize; + read += blocksize; + logical++; + } + + return read; +} + +off_t ext2_dir_entry(ext2_VOLUME *volume, struct ext2_inode *inode, + off_t index, struct ext2_dir_entry_2 *entry) +{ + int ret; + + ret = ext2_read_data(volume, inode, index, + (char*)entry, sizeof(*entry)); + if (ret == -1) + return -1; + + entry->inode = __le32_to_cpu(entry->inode); + entry->rec_len = __le16_to_cpu(entry->rec_len); + return index + entry->rec_len; +} + +unsigned int ext2_seek_name(ext2_VOLUME *volume, const char *name) +{ + struct ext2_inode inode; + int ret; + unsigned int ino; + off_t index; + struct ext2_dir_entry_2 entry; + + ino = EXT2_ROOT_INO; + while(1) { + while (*name == '\\') + name++; + if (!*name) + break; + ret = ext2_get_inode(volume, ino, &inode); + if (ret == -1) + return 0; + index = 0; + while (1) { + index = ext2_dir_entry(volume, &inode, index, &entry); + if (index == -1) + return 0; + ret = strncmp(name, entry.name, entry.name_len); + if (ret == 0 && + (name[entry.name_len] == 0 || + name[entry.name_len] == '\\')) { + ino = entry.inode; + break; + } + } + name += entry.name_len; + } + + return ino; +} diff --git a/qemu/roms/openbios/fs/ext2/ext2_utils.h b/qemu/roms/openbios/fs/ext2/ext2_utils.h new file mode 100644 index 000000000..43544d870 --- /dev/null +++ b/qemu/roms/openbios/fs/ext2/ext2_utils.h @@ -0,0 +1,54 @@ +/* + * + * (c) 2008-2009 Laurent Vivier <Laurent@lvivier.info> + * + * This file has been copied from EMILE, http://emile.sf.net + * + */ + +#ifndef __EXT2_UTILS_H__ +#define __EXT2_UTILS_H__ + +#include "ext2_fs.h" +#include "ext2.h" + +/* from linux/stat.h */ + +#define S_IFMT 00170000 +#define S_IFSOCK 0140000 +#define S_IFLNK 0120000 +#define S_IFREG 0100000 +#define S_IFBLK 0060000 +#define S_IFDIR 0040000 +#define S_IFCHR 0020000 +#define S_IFIFO 0010000 +#define S_ISUID 0004000 +#define S_ISGID 0002000 +#define S_ISVTX 0001000 + +#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) +#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) +#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) +#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) +#define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK) +#define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO) +#define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK) + +/* utilities */ + +extern int ext2_probe(int fd, long long offset); +extern void ext2_get_super(int fd, struct ext2_super_block *super); +extern void ext2_read_block(ext2_VOLUME* volume, unsigned int fsblock); +extern void ext2_get_group_desc(ext2_VOLUME* volume, + int group_id, struct ext2_group_desc *gdp); +extern int ext2_get_inode(ext2_VOLUME* volume, + unsigned int ino, struct ext2_inode *inode); +extern unsigned int ext2_get_block_addr(ext2_VOLUME* volume, + struct ext2_inode *inode, + unsigned int logical); +extern int ext2_read_data(ext2_VOLUME* volume, struct ext2_inode *inode, + off_t offset, char *buffer, size_t length); +extern off_t ext2_dir_entry(ext2_VOLUME *volume, struct ext2_inode *inode, + off_t offset, struct ext2_dir_entry_2 *entry); +extern unsigned int ext2_seek_name(ext2_VOLUME *volume, const char *name); +#endif /* __EXT2_UTILS_H__ */ diff --git a/qemu/roms/openbios/fs/ext2/libext2.h b/qemu/roms/openbios/fs/ext2/libext2.h new file mode 100644 index 000000000..12d22a44b --- /dev/null +++ b/qemu/roms/openbios/fs/ext2/libext2.h @@ -0,0 +1,25 @@ +/* + * + * (c) 2008-2009 Laurent Vivier <Laurent@lvivier.info> + * + * This file has been copied from EMILE, http://emile.sf.net + * + */ + +#ifndef __LIBEXT2_H__ +#define __LIBEXT2_H__ + +#include "config.h" +#include "ext2.h" + +extern ext2_VOLUME* ext2_mount(int fd); +extern int ext2_umount(ext2_VOLUME *volume); +extern ext2_DIR* ext2_opendir(ext2_VOLUME *, const char *name); +extern struct ext2_dir_entry_2* ext2_readdir(ext2_DIR* dir); +extern void ext2_closedir(ext2_DIR *dir); +extern ext2_FILE* ext2_open(ext2_VOLUME *, const char* pathname); +extern size_t ext2_read(ext2_FILE *file, void *buf, size_t count); +extern void ext2_close(ext2_FILE *file); +extern int ext2_lseek(ext2_FILE *file, long offset, int whence); + +#endif /* __LIBEXT2_H__ */ diff --git a/qemu/roms/openbios/fs/grubfs/Kconfig b/qemu/roms/openbios/fs/grubfs/Kconfig new file mode 100644 index 000000000..55fec8b72 --- /dev/null +++ b/qemu/roms/openbios/fs/grubfs/Kconfig @@ -0,0 +1,83 @@ +config FSYS_EXT2FS + depends on GRUBFS + bool "EXT2 support" + default n + help + Include EXT2 filesystem support + +config FSYS_FAT + depends on GRUBFS + bool "(V)FAT support" + default n + help + Include VFAT/FAT (MSDOS / Windows95) filesystem support + +config FSYS_JFS + depends on GRUBFS + bool "JFS support" + default n + help + Include JFS support + +config FSYS_MINIX + depends on GRUBFS + bool "Minix filesystem support" + default n + help + Include Minix filesystem support + +config FSYS_REISERFS + depends on GRUBFS + bool "Reiser filesystem support" + default n + help + Include Reiser filesystem support + +config FSYS_XFS + depends on GRUBFS + bool "XFS support" + default n + help + Include XFS support + +config FSYS_UFS + depends on GRUBFS + bool "UFS/UFS2 support" + default n + help + Include UFS/UFS2 support + +config FSYS_ISO9660 + depends on GRUBFS + bool "ISO 9660 support" + default n + help + Include ISO9660 (cdrom) filesystem support + +config FSYS_FFS + depends on GRUBFS + bool "FreeBSD FFS support" + default n + help + Include FreeBSD FFS filesystem support + +config FSYS_VSTAFS + depends on GRUBFS + bool "VSTA filesystem support" + default n + help + Include VSTA filesystem support + +config FSYS_NTFS + depends on GRUBFS + bool "NT filesystem support" + default n + help + Include NTFS filesystem support + +config FSYS_AFFS + depends on GRUBFS + bool "Amiga fast filesystem support" + default n + help + Include Amiga FFS filesystem support diff --git a/qemu/roms/openbios/fs/grubfs/build.xml b/qemu/roms/openbios/fs/grubfs/build.xml new file mode 100644 index 000000000..e5fb64a5f --- /dev/null +++ b/qemu/roms/openbios/fs/grubfs/build.xml @@ -0,0 +1,17 @@ +<build> + <library name="fs" type="static" target="target"> + <object source="grubfs_fs.c"/> + <object source="fsys_ext2fs.c" condition="FSYS_EXT2FS" flags="-DFSYS_EXT2FS -fno-strict-aliasing"/> + <object source="fsys_fat.c" condition="FSYS_FAT" flags="-DFSYS_FAT -fno-strict-aliasing"/> + <object source="fsys_jfs.c" condition="FSYS_JFS" flags="-DFSYS_JFS -fno-strict-aliasing"/> + <object source="fsys_minix.c" condition="FSYS_MINIX" flags="-DFSYS_MINIX -fno-strict-aliasing"/> + <object source="fsys_reiserfs.c" condition="FSYS_REISERFS" flags="-DFSYS_REISERFS -fno-strict-aliasing"/> + <object source="fsys_xfs.c" condition="FSYS_XFS" flags="-DFSYS_XFS -fno-strict-aliasing"/> + <object source="fsys_ufs.c" condition="FSYS_UFS" flags="-DFSYS_UFS -fno-strict-aliasing"/> + <object source="fsys_ffs.c" condition="FSYS_FFS" flags="-DFSYS_FFS -fno-strict-aliasing"/> + <object source="fsys_vstafs.c" condition="FSYS_VSTAFS" flags="-DFSYS_VSTAFS -fno-strict-aliasing"/> + <object source="fsys_iso9660.c" condition="FSYS_ISO9660" flags="-DFSYS_ISO9660 -fno-strict-aliasing"/> + <object source="fsys_ntfs.c" condition="FSYS_NTFS" flags="-DFSYS_NTFS -fno-strict-aliasing"/> + <object source="fsys_affs.c" condition="FSYS_AFFS" flags="-DFSYS_AFFS -fno-strict-aliasing"/> + </library> +</build> diff --git a/qemu/roms/openbios/fs/grubfs/debug.h b/qemu/roms/openbios/fs/grubfs/debug.h new file mode 100644 index 000000000..7494d3169 --- /dev/null +++ b/qemu/roms/openbios/fs/grubfs/debug.h @@ -0,0 +1 @@ +/* for grub compatibility */ diff --git a/qemu/roms/openbios/fs/grubfs/defs.h b/qemu/roms/openbios/fs/grubfs/defs.h new file mode 100644 index 000000000..3a3128ce1 --- /dev/null +++ b/qemu/roms/openbios/fs/grubfs/defs.h @@ -0,0 +1,86 @@ +/* + * Mach Operating System + * Copyright (c) 1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ +/* + * Common definitions for Berkeley Fast File System. + */ + +/* + * Compatibility definitions for disk IO. + */ + +/* + * Disk devices do all IO in 512-byte blocks. + */ +#define DEV_BSIZE 512 + +/* + * Conversion between bytes and disk blocks. + */ +#define btodb(byte_offset) ((byte_offset) >> 9) +#define dbtob(block_number) ((block_number) << 9) + +typedef struct _quad_ + { + unsigned int val[2]; /* 2 int values make... */ + } +quad; /* an 8-byte item */ + +typedef unsigned int mach_time_t; /* an unsigned int */ +typedef unsigned int mach_daddr_t; /* an unsigned int */ +typedef unsigned int mach_off_t; /* another unsigned int */ + +typedef unsigned short mach_uid_t; +typedef unsigned short mach_gid_t; +typedef unsigned int mach_ino_t; + +#define NBBY 8 + +/* + * The file system is made out of blocks of at most MAXBSIZE units, + * with smaller units (fragments) only in the last direct block. + * MAXBSIZE primarily determines the size of buffers in the buffer + * pool. It may be made larger without any effect on existing + * file systems; however, making it smaller may make some file + * systems unmountable. + * + * Note that the disk devices are assumed to have DEV_BSIZE "sectors" + * and that fragments must be some multiple of this size. + */ +#define MAXBSIZE 8192 +#define MAXFRAG 8 + +/* + * MAXPATHLEN defines the longest permissible path length + * after expanding symbolic links. + * + * MAXSYMLINKS defines the maximum number of symbolic links + * that may be expanded in a path name. It should be set + * high enough to allow all legitimate uses, but halt infinite + * loops reasonably quickly. + */ + +#define MAXPATHLEN 1024 +#define MAXSYMLINKS 8 diff --git a/qemu/roms/openbios/fs/grubfs/dir.h b/qemu/roms/openbios/fs/grubfs/dir.h new file mode 100644 index 000000000..a775cab8c --- /dev/null +++ b/qemu/roms/openbios/fs/grubfs/dir.h @@ -0,0 +1,141 @@ + +/* + * Mach Operating System + * Copyright (c) 1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ +/* + * Copyright (c) 1982, 1986, 1989 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * @(#)dir.h 7.6 (Berkeley) 5/9/89 + */ + +#ifndef _BOOT_UFS_DIR_H_ +#define _BOOT_UFS_DIR_H_ + +/* + * A directory consists of some number of blocks of DIRBLKSIZ + * bytes, where DIRBLKSIZ is chosen such that it can be transferred + * to disk in a single atomic operation (e.g. 512 bytes on most machines). + * + * Each DIRBLKSIZ byte block contains some number of directory entry + * structures, which are of variable length. Each directory entry has + * a struct direct at the front of it, containing its inode number, + * the length of the entry, and the length of the name contained in + * the entry. These are followed by the name padded to a 4 byte boundary + * with null bytes. All names are guaranteed null terminated. + * The maximum length of a name in a directory is MAXNAMLEN. + * + * The macro DIRSIZ(dp) gives the amount of space required to represent + * a directory entry. Free space in a directory is represented by + * entries which have dp->d_reclen > DIRSIZ(dp). All DIRBLKSIZ bytes + * in a directory block are claimed by the directory entries. This + * usually results in the last entry in a directory having a large + * dp->d_reclen. When entries are deleted from a directory, the + * space is returned to the previous entry in the same directory + * block by increasing its dp->d_reclen. If the first entry of + * a directory block is free, then its dp->d_ino is set to 0. + * Entries other than the first in a directory do not normally have + * dp->d_ino set to 0. + */ +#define DIRBLKSIZ DEV_BSIZE +#define MAXNAMLEN 255 + +struct direct + { + unsigned int d_ino; /* inode number of entry */ + unsigned short d_reclen; /* length of this record */ + unsigned short d_namlen; /* length of string in d_name */ + char d_name[MAXNAMLEN + 1]; /* name with length <= MAXNAMLEN */ + }; + +/* + * The DIRSIZ macro gives the minimum record length which will hold + * the directory entry. This requires the amount of space in struct direct + * without the d_name field, plus enough space for the name with a terminating + * null byte (dp->d_namlen+1), rounded up to a 4 byte boundary. + */ +#undef DIRSIZ +#define DIRSIZ(dp) \ + ((sizeof (struct direct) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3)) + +#ifdef KERNEL +/* + * Template for manipulating directories. + * Should use struct direct's, but the name field + * is MAXNAMLEN - 1, and this just won't do. + */ +struct dirtemplate + { + unsigned int dot_ino; + short dot_reclen; + short dot_namlen; + char dot_name[4]; /* must be multiple of 4 */ + unsigned int dotdot_ino; + short dotdot_reclen; + short dotdot_namlen; + char dotdot_name[4]; /* ditto */ + }; +#endif + +/* + * The following information should be obtained from <dirent.h> + * and is provided solely (and temporarily) for backward compatibility. + */ +#ifndef KERNEL +#define d_fileno d_ino /* compatibility with POSIX */ +#ifndef DEV_BSIZE +#define DEV_BSIZE 512 +#endif +/* + * Definitions for library routines operating on directories. + */ +typedef struct _dirdesc + { + int dd_fd; + int dd_loc; + int dd_size; + char dd_buf[DIRBLKSIZ]; + } +DIR; + +#define dirfd(dirp) ((dirp)->dd_fd) + +#ifndef NULL +#define NULL 0 +#endif +#endif /* not KERNEL */ +#endif /* _BOOT_UFS_DIR_H_ */ diff --git a/qemu/roms/openbios/fs/grubfs/disk_inode.h b/qemu/roms/openbios/fs/grubfs/disk_inode.h new file mode 100644 index 000000000..68a61c7a4 --- /dev/null +++ b/qemu/roms/openbios/fs/grubfs/disk_inode.h @@ -0,0 +1,110 @@ +/* + * Mach Operating System + * Copyright (c) 1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ +/* + * Copyright (c) 1982, 1989 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * @(#)inode.h 7.5 (Berkeley) 7/3/89 + */ + +#ifndef _BOOT_UFS_DISK_INODE_H_ +#define _BOOT_UFS_DISK_INODE_H_ + +/* + * The I node is the focus of all file activity in the BSD Fast File System. + * There is a unique inode allocated for each active file, + * each current directory, each mounted-on file, text file, and the root. + * An inode is 'named' by its dev/inumber pair. (iget/iget.c) + * Data in icommon is read in from permanent inode on volume. + */ + +#define FFS_NDADDR 12 /* direct addresses in inode */ +#define FFS_NIADDR 3 /* indirect addresses in inode */ + +#define FFS_MAX_FASTLINK_SIZE ((FFS_NDADDR + FFS_NIADDR) \ + * sizeof (mach_daddr_t)) + +struct icommon + { + unsigned short ic_mode; /* 0: mode and type of file */ + short ic_nlink; /* 2: number of links to file */ + mach_uid_t ic_uid; /* 4: owner's user id */ + mach_gid_t ic_gid; /* 6: owner's group id */ + quad ic_size; /* 8: number of bytes in file */ + mach_time_t ic_atime; /* 16: time last accessed */ + int ic_atspare; + mach_time_t ic_mtime; /* 24: time last modified */ + int ic_mtspare; + mach_time_t ic_ctime; /* 32: last time inode changed */ + int ic_ctspare; + union + { + struct + { + mach_daddr_t Mb_db[FFS_NDADDR]; /* 40: disk block addresses */ + mach_daddr_t Mb_ib[FFS_NIADDR]; /* 88: indirect blocks */ + } + ic_Mb; + char ic_Msymlink[FFS_MAX_FASTLINK_SIZE]; + /* 40: symbolic link name */ + } + ic_Mun; +#define ic_db ic_Mun.ic_Mb.Mb_db +#define ic_ib ic_Mun.ic_Mb.Mb_ib +#define ic_symlink ic_Mun.ic_Msymlink + int ic_flags; /* 100: status, currently unused */ + int ic_blocks; /* 104: blocks actually held */ + int ic_gen; /* 108: generation number */ + int ic_spare[4]; /* 112: reserved, currently unused */ + }; + +/* + * Same structure, but on disk. + */ +struct dinode + { + union + { + struct icommon di_com; + char di_char[128]; + } + di_un; + }; +#define di_ic di_un.di_com + +#endif /* _BOOT_UFS_DISK_INODE_H_ */ diff --git a/qemu/roms/openbios/fs/grubfs/disk_inode_ffs.h b/qemu/roms/openbios/fs/grubfs/disk_inode_ffs.h new file mode 100644 index 000000000..3a2cfc6d1 --- /dev/null +++ b/qemu/roms/openbios/fs/grubfs/disk_inode_ffs.h @@ -0,0 +1,101 @@ +/* + * Mach Operating System + * Copyright (c) 1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ +/* + * Copyright (c) 1982, 1989 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * @(#)inode.h 7.5 (Berkeley) 7/3/89 + */ + +#ifndef _BOOT_UFS_DISK_INODE_FFS_H_ +#define _BOOT_UFS_DISK_INODE_FFS_H_ + +#define NDADDR FFS_NDADDR +#define NIADDR FFS_NIADDR + +#define MAX_FASTLINK_SIZE FFS_MAX_FASTLINK_SIZE + +#define IC_FASTLINK 0x0001 /* Symbolic link in inode */ + +#define i_mode ic_mode +#define i_nlink ic_nlink +#define i_uid ic_uid +#define i_gid ic_gid +#if defined(BYTE_MSF) && BYTE_MSF +#define i_size ic_size.val[1] +#else /* BYTE_LSF */ +#define i_size ic_size.val[0] +#endif +#define i_db ic_db +#define i_ib ic_ib +#define i_atime ic_atime +#define i_mtime ic_mtime +#define i_ctime ic_ctime +#define i_blocks ic_blocks +#define i_rdev ic_db[0] +#define i_symlink ic_symlink +#define i_flags ic_flags +#define i_gen ic_gen + +/* modes */ +#define IFMT 0xf000 /* type of file */ +#define IFCHR 0x2000 /* character special */ +#define IFDIR 0x4000 /* directory */ +#define IFBLK 0x6000 /* block special */ +#define IFREG 0x8000 /* regular */ +#define IFLNK 0xa000 /* symbolic link */ +#define IFSOCK 0xc000 /* socket */ + + +#define ISUID 0x0800 /* set user id on execution */ +#define ISGID 0x0400 /* set group id on execution */ +#define ISVTX 0x0200 /* save swapped text even after use */ +#define IREAD 0x0100 /* read, write, execute permissions */ +#define IWRITE 0x0080 +#define IEXEC 0x0040 + +#ifdef EEK +#define f_fs u.ffs.ffs_fs +#define i_ic u.ffs.ffs_ic +#define f_nindir u.ffs.ffs_nindir +#define f_blk u.ffs.ffs_blk +#define f_blksize u.ffs.ffs_blksize +#define f_blkno u.ffs.ffs_blkno +#endif /* EEK */ + +#endif /* _BOOT_UFS_DISK_INODE_FFS_H_ */ diff --git a/qemu/roms/openbios/fs/grubfs/fat.h b/qemu/roms/openbios/fs/grubfs/fat.h new file mode 100644 index 000000000..43d38aefc --- /dev/null +++ b/qemu/roms/openbios/fs/grubfs/fat.h @@ -0,0 +1,99 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2001 Free Software Foundation, Inc. + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + + +/* + * Defines for the FAT BIOS Parameter Block (embedded in the first block + * of the partition. + */ + +typedef __signed__ char __s8; +typedef unsigned char __u8; +typedef __signed__ short __s16; +typedef unsigned short __u16; +typedef __signed__ int __s32; +typedef unsigned int __u32; + +/* Note that some shorts are not aligned, and must therefore + * be declared as array of two bytes. + */ +struct fat_bpb { + __s8 ignored[3]; /* Boot strap short or near jump */ + __s8 system_id[8]; /* Name - can be used to special case + partition manager volumes */ + __u16 bytes_per_sect; /* bytes per logical sector */ + __u8 sects_per_clust;/* sectors/cluster */ + __u16 reserved_sects; /* reserved sectors */ + __u8 num_fats; /* number of FATs */ + __u16 dir_entries; /* root directory entries */ + __u16 short_sectors; /* number of sectors */ + __u8 media; /* media code (unused) */ + __u16 fat_length; /* sectors/FAT */ + __u16 secs_track; /* sectors per track */ + __u16 heads; /* number of heads */ + __u32 hidden; /* hidden sectors (unused) */ + __u32 long_sectors; /* number of sectors (if short_sectors == 0) */ + + /* The following fields are only used by FAT32 */ + __u32 fat32_length; /* sectors/FAT */ + __u16 flags; /* bit 8: fat mirroring, low 4: active fat */ + __u16 version; /* major, minor filesystem version */ + __u32 root_cluster; /* first cluster in root directory */ + __u16 info_sector; /* filesystem info sector */ + __u16 backup_boot; /* backup boot sector */ + __u16 reserved2[6]; /* Unused */ +} __attribute__ ((packed)); + +/* + * Defines how to differentiate a 12-bit and 16-bit FAT. + */ + +#define FAT_MAX_12BIT_CLUST 4087 /* 4085 + 2 */ + +/* + * Defines for the file "attribute" byte + */ + +#define FAT_ATTRIB_OK_MASK 0x37 +#define FAT_ATTRIB_NOT_OK_MASK 0xC8 +#define FAT_ATTRIB_DIR 0x10 +#define FAT_ATTRIB_LONGNAME 0x0F + +/* + * Defines for FAT directory entries + */ + +#define FAT_DIRENTRY_LENGTH 32 + +#define FAT_DIRENTRY_ATTRIB(entry) \ + (*((unsigned char *) (entry+11))) +#define FAT_DIRENTRY_VALID(entry) \ + ( ((*((unsigned char *) entry)) != 0) \ + && ((*((unsigned char *) entry)) != 0xE5) \ + && !(FAT_DIRENTRY_ATTRIB(entry) & FAT_ATTRIB_NOT_OK_MASK) ) +#define FAT_DIRENTRY_FIRST_CLUSTER(entry) \ + ((*((unsigned short *) (entry+26)))+(*((unsigned short *) (entry+20)) << 16)) +#define FAT_DIRENTRY_FILELENGTH(entry) \ + (*((unsigned long *) (entry+28))) + +#define FAT_LONGDIR_ID(entry) \ + (*((unsigned char *) (entry))) +#define FAT_LONGDIR_ALIASCHECKSUM(entry) \ + (*((unsigned char *) (entry+13))) diff --git a/qemu/roms/openbios/fs/grubfs/filesys.h b/qemu/roms/openbios/fs/grubfs/filesys.h new file mode 100644 index 000000000..6b6f97603 --- /dev/null +++ b/qemu/roms/openbios/fs/grubfs/filesys.h @@ -0,0 +1,303 @@ +/* GRUB compatibility header + * + * taken from filo and grub. + */ + +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 1999,2000,2001,2003 Free Software Foundation, Inc. + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +/* This disables some portion of code */ +#define STAGE1_5 1 + +#if defined CONFIG_X86 +/* + * ffz = Find First Zero in word. Undefined if no zero exists, + * so code should check against ~0UL first.. + */ +static __inline__ unsigned int +ffz (unsigned int word) +{ + __asm__ ("bsfl %1,%0" + : "=r" (word) + : "r" (~word)); + return word; +} + +static __inline__ unsigned int +log2 (unsigned int word) +{ + __asm__ ("bsfl %1,%0" + : "=r" (word) + : "r" (word)); + return word; +} + +#elif defined (CONFIG_PPC) +static __inline__ unsigned long + __ilog2(unsigned long x) +{ + unsigned long lz; + + asm ("cntlzw %0,%1" : "=r" (lz) : "r" (x)); + return 31 - lz; +} + +static __inline__ unsigned long +ffz(unsigned long x) +{ + if ((x = ~x) == 0) + return 32; + + return __ilog2(x & -x); +} + +#define log2(n) ffz(~(n)) + +#else + +static __inline__ unsigned int log2(unsigned int word) +{ + /* assume 8 bits per byte. */ + unsigned int i = 1 << (sizeof(word)*8 - 1); + unsigned int pow = sizeof(word) * 8 - 1; + + if (! word) { + /* invalid parameter */ + return -1; + } + for(; i > word; i >>= 1, pow--) ; + + return pow; +} + +#define ffz(n) log2(~(n)) + +#endif + +static inline int +substring (const char *s1, const char *s2) +{ + while (*s1 == *s2) + { + /* The strings match exactly. */ + if (! *(s1++)) + return 0; + s2 ++; + } + + /* S1 is a substring of S2. */ + if (*s1 == 0) + return -1; + + /* S1 isn't a substring. */ + return 1; +} + +#define grub_memmove memmove +#define grub_strcmp strcmp + +#define MAXINT 0x7fffffff + +/* This is only used by fsys_* to determine if it's hard disk. If it is, + * they try to guess filesystem type by partition type. I guess it is + * not necessory, so hardcoded to 0 (first floppy) --ts1 */ +#define current_drive 0 +#define current_slice 0 +#define current_partition 0 + +/* we fake this for now, assuming that the filesystem is not corrupt */ +#define part_length -1 +extern int filepos; +extern int filemax; +extern int fsmax; + +/* Error codes (descriptions are in common.c) */ +typedef enum +{ + ERR_NONE = 0, + ERR_BAD_FILENAME, + ERR_BAD_FILETYPE, + ERR_BAD_GZIP_DATA, + ERR_BAD_GZIP_HEADER, + ERR_BAD_PART_TABLE, + ERR_BAD_VERSION, + ERR_BELOW_1MB, + ERR_BOOT_COMMAND, + ERR_BOOT_FAILURE, + ERR_BOOT_FEATURES, + ERR_DEV_FORMAT, + ERR_DEV_VALUES, + ERR_EXEC_FORMAT, + ERR_FILELENGTH, + ERR_FILE_NOT_FOUND, + ERR_FSYS_CORRUPT, + ERR_FSYS_MOUNT, + ERR_GEOM, + ERR_NEED_LX_KERNEL, + ERR_NEED_MB_KERNEL, + ERR_NO_DISK, + ERR_NO_PART, + ERR_NUMBER_PARSING, + ERR_OUTSIDE_PART, + ERR_READ, + ERR_SYMLINK_LOOP, + ERR_UNRECOGNIZED, + ERR_WONT_FIT, + ERR_WRITE, + ERR_BAD_ARGUMENT, + ERR_UNALIGNED, + ERR_PRIVILEGED, + ERR_DEV_NEED_INIT, + ERR_NO_DISK_SPACE, + ERR_NUMBER_OVERFLOW, + + MAX_ERR_NUM +} grub_error_t; + +extern grub_error_t errnum; + +#define grub_open file_open +#define grub_read file_read +#define grub_seek file_seek +#define grub_close file_close + +/* instrumentation variables */ +/* (Not used in FILO) */ +extern void (*disk_read_hook) (int, int, int); +extern void (*disk_read_func) (int, int, int); + +#define FSYS_BUFLEN 0x8000 +extern char FSYS_BUF[FSYS_BUFLEN]; + +#define print_possibilities 0 + +#define SECTOR_SIZE 512 +#define SECTOR_BITS 9 + +#ifdef CONFIG_FSYS_FAT +int fat_mount (void); +int fat_read (char *buf, int len); +int fat_dir (char *dirname); +#endif + +#ifdef CONFIG_FSYS_EXT2FS +int ext2fs_mount (void); +int ext2fs_read (char *buf, int len); +int ext2fs_dir (char *dirname); +#endif + +#ifdef CONFIG_FSYS_MINIX +int minix_mount (void); +int minix_read (char *buf, int len); +int minix_dir (char *dirname); +#endif + +#ifdef CONFIG_FSYS_REISERFS +int reiserfs_mount (void); +int reiserfs_read (char *buf, int len); +int reiserfs_dir (char *dirname); +int reiserfs_embed (int *start_sector, int needed_sectors); +#endif + +#ifdef CONFIG_FSYS_JFS +int jfs_mount (void); +int jfs_read (char *buf, int len); +int jfs_dir (char *dirname); +int jfs_embed (int *start_sector, int needed_sectors); +#endif + +#ifdef CONFIG_FSYS_XFS +int xfs_mount (void); +int xfs_read (char *buf, int len); +int xfs_dir (char *dirname); +#endif + +#ifdef CONFIG_FSYS_UFS +int ufs_mount (void); +int ufs_read (char *buf, int len); +int ufs_dir (char *dirname); +int ufs_embed (int *start_sector, int needed_sectors); +#endif + +#ifdef CONFIG_FSYS_ISO9660 +int iso9660_mount (void); +int iso9660_read (char *buf, int len); +int iso9660_dir (char *dirname); +#endif + +/* This is not a flag actually, but used as if it were a flag. */ +#define PC_SLICE_TYPE_HIDDEN_FLAG 0x10 + +#define PC_SLICE_TYPE_NONE 0 +#define PC_SLICE_TYPE_FAT12 1 +#define PC_SLICE_TYPE_FAT16_LT32M 4 +#define PC_SLICE_TYPE_EXTENDED 5 +#define PC_SLICE_TYPE_FAT16_GT32M 6 +#define PC_SLICE_TYPE_FAT32 0xb +#define PC_SLICE_TYPE_FAT32_LBA 0xc +#define PC_SLICE_TYPE_FAT16_LBA 0xe +#define PC_SLICE_TYPE_WIN95_EXTENDED 0xf +#define PC_SLICE_TYPE_EZD 0x55 +#define PC_SLICE_TYPE_MINIX 0x80 +#define PC_SLICE_TYPE_LINUX_MINIX 0x81 +#define PC_SLICE_TYPE_EXT2FS 0x83 +#define PC_SLICE_TYPE_LINUX_EXTENDED 0x85 +#define PC_SLICE_TYPE_VSTAFS 0x9e +#define PC_SLICE_TYPE_DELL_UTIL 0xde +#define PC_SLICE_TYPE_LINUX_RAID 0xfd + +/* For convinience. */ +/* Check if TYPE is a FAT partition type. Clear the hidden flag before + the check, to allow the user to mount a hidden partition in GRUB. */ +#define IS_PC_SLICE_TYPE_FAT(type) \ + ({ int _type = (type) & ~PC_SLICE_TYPE_HIDDEN_FLAG; \ + _type == PC_SLICE_TYPE_FAT12 \ + || _type == PC_SLICE_TYPE_FAT16_LT32M \ + || _type == PC_SLICE_TYPE_FAT16_GT32M \ + || _type == PC_SLICE_TYPE_FAT16_LBA \ + || _type == PC_SLICE_TYPE_FAT32 \ + || _type == PC_SLICE_TYPE_FAT32_LBA \ + || _type == PC_SLICE_TYPE_DELL_UTIL; }) + +#define IS_PC_SLICE_TYPE_MINIX(type) \ + (((type) == PC_SLICE_TYPE_MINIX) \ + || ((type) == PC_SLICE_TYPE_LINUX_MINIX)) + +#define IS_PC_SLICE_TYPE_BSD_WITH_FS(type,fs) 0 + +/* possible values for the *BSD-style partition type */ +#define FS_UNUSED 0 /* unused */ +#define FS_SWAP 1 /* swap */ +#define FS_V6 2 /* Sixth Edition */ +#define FS_V7 3 /* Seventh Edition */ +#define FS_SYSV 4 /* System V */ +#define FS_V71K 5 /* V7 with 1K blocks (4.1, 2.9) */ +#define FS_V8 6 /* Eighth Edition, 4K blocks */ +#define FS_BSDFFS 7 /* 4.2BSD fast file system */ +#define FS_MSDOS 8 /* MSDOS file system */ +#define FS_BSDLFS 9 /* 4.4BSD log-structured file system */ +#define FS_OTHER 10 /* in use, but unknown/unsupported */ +#define FS_HPFS 11 /* OS/2 high-performance file system */ +#define FS_ISO9660 12 /* ISO 9660, normally CD-ROM */ +#define FS_BOOT 13 /* partition contains bootstrap */ +#define FS_ADOS 14 /* AmigaDOS fast file system */ +#define FS_HFS 15 /* Macintosh HFS */ +#define FS_FILECORE 16 /* Acorn Filecore Filing System */ +#define FS_EXT2FS 17 /* Linux Extended 2 file system */ diff --git a/qemu/roms/openbios/fs/grubfs/fs.h b/qemu/roms/openbios/fs/grubfs/fs.h new file mode 100644 index 000000000..260e92647 --- /dev/null +++ b/qemu/roms/openbios/fs/grubfs/fs.h @@ -0,0 +1,457 @@ +/* + * Mach Operating System + * Copyright (c) 1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ +/* + * Copyright (c) 1982, 1986 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * @(#)fs.h 7.7 (Berkeley) 5/9/89 + */ + +/* + * Each disk drive contains some number of file systems. + * A file system consists of a number of cylinder groups. + * Each cylinder group has inodes and data. + * + * A file system is described by its super-block, which in turn + * describes the cylinder groups. The super-block is critical + * data and is replicated in each cylinder group to protect against + * catastrophic loss. This is done at `newfs' time and the critical + * super-block data does not change, so the copies need not be + * referenced further unless disaster strikes. + * + * For file system fs, the offsets of the various blocks of interest + * are given in the super block as: + * [fs->fs_sblkno] Super-block + * [fs->fs_cblkno] Cylinder group block + * [fs->fs_iblkno] Inode blocks + * [fs->fs_dblkno] Data blocks + * The beginning of cylinder group cg in fs, is given by + * the ``cgbase(fs, cg)'' macro. + * + * The first boot and super blocks are given in absolute disk addresses. + * The byte-offset forms are preferred, as they don't imply a sector size. + */ +#define BBSIZE 8192 +#define SBSIZE 8192 +#define BBOFF ((mach_off_t)(0)) +#define SBOFF ((mach_off_t)(BBOFF + BBSIZE)) +#define BBLOCK ((mach_daddr_t)(0)) +#define SBLOCK ((mach_daddr_t)(BBLOCK + BBSIZE / DEV_BSIZE)) + +/* + * Addresses stored in inodes are capable of addressing fragments + * of `blocks'. File system blocks of at most size MAXBSIZE can + * be optionally broken into 2, 4, or 8 pieces, each of which is + * addressible; these pieces may be DEV_BSIZE, or some multiple of + * a DEV_BSIZE unit. + * + * Large files consist of exclusively large data blocks. To avoid + * undue wasted disk space, the last data block of a small file may be + * allocated as only as many fragments of a large block as are + * necessary. The file system format retains only a single pointer + * to such a fragment, which is a piece of a single large block that + * has been divided. The size of such a fragment is determinable from + * information in the inode, using the ``blksize(fs, ip, lbn)'' macro. + * + * The file system records space availability at the fragment level; + * to determine block availability, aligned fragments are examined. + * + * The root inode is the root of the file system. + * Inode 0 can't be used for normal purposes and + * historically bad blocks were linked to inode 1, + * thus the root inode is 2. (inode 1 is no longer used for + * this purpose, however numerous dump tapes make this + * assumption, so we are stuck with it) + */ +#define ROOTINO ((mach_ino_t)2) /* i number of all roots */ + +/* + * MINBSIZE is the smallest allowable block size. + * In order to insure that it is possible to create files of size + * 2^32 with only two levels of indirection, MINBSIZE is set to 4096. + * MINBSIZE must be big enough to hold a cylinder group block, + * thus changes to (struct cg) must keep its size within MINBSIZE. + * Note that super blocks are always of size SBSIZE, + * and that both SBSIZE and MAXBSIZE must be >= MINBSIZE. + */ +#define MINBSIZE 4096 + +/* + * The path name on which the file system is mounted is maintained + * in fs_fsmnt. MAXMNTLEN defines the amount of space allocated in + * the super block for this name. + * The limit on the amount of summary information per file system + * is defined by MAXCSBUFS. It is currently parameterized for a + * maximum of two million cylinders. + */ +#define MAXMNTLEN 512 +#define MAXCSBUFS 32 + +/* + * Per cylinder group information; summarized in blocks allocated + * from first cylinder group data blocks. These blocks have to be + * read in from fs_csaddr (size fs_cssize) in addition to the + * super block. + * + * N.B. sizeof(struct csum) must be a power of two in order for + * the ``fs_cs'' macro to work (see below). + */ +struct csum + { + int cs_ndir; /* number of directories */ + int cs_nbfree; /* number of free blocks */ + int cs_nifree; /* number of free inodes */ + int cs_nffree; /* number of free frags */ + }; + +/* + * Super block for a file system. + */ +#define FS_MAGIC 0x011954 +struct fs + { + int xxx1; /* struct fs *fs_link; */ + int xxx2; /* struct fs *fs_rlink; */ + mach_daddr_t fs_sblkno; /* addr of super-block in filesys */ + mach_daddr_t fs_cblkno; /* offset of cyl-block in filesys */ + mach_daddr_t fs_iblkno; /* offset of inode-blocks in filesys */ + mach_daddr_t fs_dblkno; /* offset of first data after cg */ + int fs_cgoffset; /* cylinder group offset in cylinder */ + int fs_cgmask; /* used to calc mod fs_ntrak */ + mach_time_t fs_time; /* last time written */ + int fs_size; /* number of blocks in fs */ + int fs_dsize; /* number of data blocks in fs */ + int fs_ncg; /* number of cylinder groups */ + int fs_bsize; /* size of basic blocks in fs */ + int fs_fsize; /* size of frag blocks in fs */ + int fs_frag; /* number of frags in a block in fs */ +/* these are configuration parameters */ + int fs_minfree; /* minimum percentage of free blocks */ + int fs_rotdelay; /* num of ms for optimal next block */ + int fs_rps; /* disk revolutions per second */ +/* these fields can be computed from the others */ + int fs_bmask; /* ``blkoff'' calc of blk offsets */ + int fs_fmask; /* ``fragoff'' calc of frag offsets */ + int fs_bshift; /* ``lblkno'' calc of logical blkno */ + int fs_fshift; /* ``numfrags'' calc number of frags */ +/* these are configuration parameters */ + int fs_maxcontig; /* max number of contiguous blks */ + int fs_maxbpg; /* max number of blks per cyl group */ +/* these fields can be computed from the others */ + int fs_fragshift; /* block to frag shift */ + int fs_fsbtodb; /* fsbtodb and dbtofsb shift constant */ + int fs_sbsize; /* actual size of super block */ + int fs_csmask; /* csum block offset */ + int fs_csshift; /* csum block number */ + int fs_nindir; /* value of NINDIR */ + int fs_inopb; /* value of INOPB */ + int fs_nspf; /* value of NSPF */ +/* yet another configuration parameter */ + int fs_optim; /* optimization preference, see below */ +/* these fields are derived from the hardware */ + int fs_npsect; /* # sectors/track including spares */ + int fs_interleave; /* hardware sector interleave */ + int fs_trackskew; /* sector 0 skew, per track */ + int fs_headswitch; /* head switch time, usec */ + int fs_trkseek; /* track-to-track seek, usec */ +/* sizes determined by number of cylinder groups and their sizes */ + mach_daddr_t fs_csaddr; /* blk addr of cyl grp summary area */ + int fs_cssize; /* size of cyl grp summary area */ + int fs_cgsize; /* cylinder group size */ +/* these fields are derived from the hardware */ + int fs_ntrak; /* tracks per cylinder */ + int fs_nsect; /* sectors per track */ + int fs_spc; /* sectors per cylinder */ +/* this comes from the disk driver partitioning */ + int fs_ncyl; /* cylinders in file system */ +/* these fields can be computed from the others */ + int fs_cpg; /* cylinders per group */ + int fs_ipg; /* inodes per group */ + int fs_fpg; /* blocks per group * fs_frag */ +/* this data must be re-computed after crashes */ + struct csum fs_cstotal; /* cylinder summary information */ +/* these fields are cleared at mount time */ + char fs_fmod; /* super block modified flag */ + char fs_clean; /* file system is clean flag */ + char fs_ronly; /* mounted read-only flag */ + char fs_flags; /* currently unused flag */ + char fs_fsmnt[MAXMNTLEN]; /* name mounted on */ +/* these fields retain the current block allocation info */ + int fs_cgrotor; /* last cg searched */ +#if 1 + int was_fs_csp[MAXCSBUFS]; +#else + struct csum *fs_csp[MAXCSBUFS]; /* list of fs_cs info buffers */ +#endif + int fs_cpc; /* cyl per cycle in postbl */ + short fs_opostbl[16][8]; /* old rotation block list head */ + long fs_sparecon[50]; /* reserved for future constants */ + long fs_contigsumsize; /* size of cluster summary array */ + long fs_maxsymlinklen; /* max length of an internal symlink */ + long fs_inodefmt; /* format of on-disk inodes */ + quad fs_maxfilesize; /* maximum representable file size */ + quad fs_qbmask; /* ~fs_bmask - for use with quad size */ + quad fs_qfmask; /* ~fs_fmask - for use with quad size */ + long fs_state; /* validate fs_clean field */ + int fs_postblformat; /* format of positional layout tables */ + int fs_nrpos; /* number of rotaional positions */ + int fs_postbloff; /* (short) rotation block list head */ + int fs_rotbloff; /* (char) blocks for each rotation */ + int fs_magic; /* magic number */ + unsigned char fs_space[1]; /* list of blocks for each rotation */ +/* actually longer */ + }; +/* + * Preference for optimization. + */ +#define FS_OPTTIME 0 /* minimize allocation time */ +#define FS_OPTSPACE 1 /* minimize disk fragmentation */ + +/* + * Rotational layout table format types + */ +#define FS_42POSTBLFMT -1 /* 4.2BSD rotational table format */ +#define FS_DYNAMICPOSTBLFMT 1 /* dynamic rotational table format */ +/* + * Macros for access to superblock array structures + */ +#define fs_postbl(fs, cylno) \ + (((fs)->fs_postblformat == FS_42POSTBLFMT) \ + ? ((fs)->fs_opostbl[cylno]) \ + : ((short *)((char *)(fs) + (fs)->fs_postbloff) + (cylno) * (fs)->fs_nrpos)) +#define fs_rotbl(fs) \ + (((fs)->fs_postblformat == FS_42POSTBLFMT) \ + ? ((fs)->fs_space) \ + : ((unsigned char *)((char *)(fs) + (fs)->fs_rotbloff))) + +/* + * Convert cylinder group to base address of its global summary info. + * + * N.B. This macro assumes that sizeof(struct csum) is a power of two. + */ +#define fs_cs(fs, indx) \ + fs_csp[(indx) >> (fs)->fs_csshift][(indx) & ~(fs)->fs_csmask] + +/* + * Cylinder group block for a file system. + */ +#define CG_MAGIC 0x090255 +struct cg + { + int xxx1; /* struct cg *cg_link; */ + int cg_magic; /* magic number */ + mach_time_t cg_time; /* time last written */ + int cg_cgx; /* we are the cgx'th cylinder group */ + short cg_ncyl; /* number of cyl's this cg */ + short cg_niblk; /* number of inode blocks this cg */ + int cg_ndblk; /* number of data blocks this cg */ + struct csum cg_cs; /* cylinder summary information */ + int cg_rotor; /* position of last used block */ + int cg_frotor; /* position of last used frag */ + int cg_irotor; /* position of last used inode */ + int cg_frsum[MAXFRAG]; /* counts of available frags */ + int cg_btotoff; /* (long) block totals per cylinder */ + int cg_boff; /* (short) free block positions */ + int cg_iusedoff; /* (char) used inode map */ + int cg_freeoff; /* (char) free block map */ + int cg_nextfreeoff; /* (char) next available space */ + int cg_sparecon[16]; /* reserved for future use */ + unsigned char cg_space[1]; /* space for cylinder group maps */ +/* actually longer */ + }; +/* + * Macros for access to cylinder group array structures + */ +#define cg_blktot(cgp) \ + (((cgp)->cg_magic != CG_MAGIC) \ + ? (((struct ocg *)(cgp))->cg_btot) \ + : ((int *)((char *)(cgp) + (cgp)->cg_btotoff))) +#define cg_blks(fs, cgp, cylno) \ + (((cgp)->cg_magic != CG_MAGIC) \ + ? (((struct ocg *)(cgp))->cg_b[cylno]) \ + : ((short *)((char *)(cgp) + (cgp)->cg_boff) + (cylno) * (fs)->fs_nrpos)) +#define cg_inosused(cgp) \ + (((cgp)->cg_magic != CG_MAGIC) \ + ? (((struct ocg *)(cgp))->cg_iused) \ + : ((char *)((char *)(cgp) + (cgp)->cg_iusedoff))) +#define cg_blksfree(cgp) \ + (((cgp)->cg_magic != CG_MAGIC) \ + ? (((struct ocg *)(cgp))->cg_free) \ + : ((unsigned char *)((char *)(cgp) + (cgp)->cg_freeoff))) +#define cg_chkmagic(cgp) \ + ((cgp)->cg_magic == CG_MAGIC || ((struct ocg *)(cgp))->cg_magic == CG_MAGIC) + +/* + * The following structure is defined + * for compatibility with old file systems. + */ +struct ocg + { + int xxx1; /* struct ocg *cg_link; */ + int xxx2; /* struct ocg *cg_rlink; */ + mach_time_t cg_time; /* time last written */ + int cg_cgx; /* we are the cgx'th cylinder group */ + short cg_ncyl; /* number of cyl's this cg */ + short cg_niblk; /* number of inode blocks this cg */ + int cg_ndblk; /* number of data blocks this cg */ + struct csum cg_cs; /* cylinder summary information */ + int cg_rotor; /* position of last used block */ + int cg_frotor; /* position of last used frag */ + int cg_irotor; /* position of last used inode */ + int cg_frsum[8]; /* counts of available frags */ + int cg_btot[32]; /* block totals per cylinder */ + short cg_b[32][8]; /* positions of free blocks */ + char cg_iused[256]; /* used inode map */ + int cg_magic; /* magic number */ + unsigned char cg_free[1]; /* free block map */ +/* actually longer */ + }; + +/* + * Turn file system block numbers into disk block addresses. + * This maps file system blocks to device size blocks. + */ +#define fsbtodb(fs, b) ((b) << (fs)->fs_fsbtodb) +#define dbtofsb(fs, b) ((b) >> (fs)->fs_fsbtodb) + +/* + * Cylinder group macros to locate things in cylinder groups. + * They calc file system addresses of cylinder group data structures. + */ +#define cgbase(fs, c) ((mach_daddr_t)((fs)->fs_fpg * (c))) +#define cgstart(fs, c) \ + (cgbase(fs, c) + (fs)->fs_cgoffset * ((c) & ~((fs)->fs_cgmask))) +#define cgsblock(fs, c) (cgstart(fs, c) + (fs)->fs_sblkno) /* super blk */ +#define cgtod(fs, c) (cgstart(fs, c) + (fs)->fs_cblkno) /* cg block */ +#define cgimin(fs, c) (cgstart(fs, c) + (fs)->fs_iblkno) /* inode blk */ +#define cgdmin(fs, c) (cgstart(fs, c) + (fs)->fs_dblkno) /* 1st data */ + +/* + * Macros for handling inode numbers: + * inode number to file system block offset. + * inode number to cylinder group number. + * inode number to file system block address. + */ +#define itoo(fs, x) ((x) % INOPB(fs)) +#define itog(fs, x) ((x) / (fs)->fs_ipg) +#define itod(fs, x) \ + ((mach_daddr_t)(cgimin(fs, itog(fs, x)) + \ + (blkstofrags((fs), (((x) % (fs)->fs_ipg) / INOPB(fs)))))) + +/* + * Give cylinder group number for a file system block. + * Give cylinder group block number for a file system block. + */ +#define dtog(fs, d) ((d) / (fs)->fs_fpg) +#define dtogd(fs, d) ((d) % (fs)->fs_fpg) + +/* + * Extract the bits for a block from a map. + * Compute the cylinder and rotational position of a cyl block addr. + */ +#define blkmap(fs, map, loc) \ + (((map)[(loc) / NBBY] >> ((loc) % NBBY)) & (0xff >> (NBBY - (fs)->fs_frag))) +#define cbtocylno(fs, bno) \ + ((bno) * NSPF(fs) / (fs)->fs_spc) +#define cbtorpos(fs, bno) \ + (((bno) * NSPF(fs) % (fs)->fs_spc / (fs)->fs_nsect * (fs)->fs_trackskew + \ + (bno) * NSPF(fs) % (fs)->fs_spc % (fs)->fs_nsect * (fs)->fs_interleave) % \ + (fs)->fs_nsect * (fs)->fs_nrpos / (fs)->fs_npsect) + +/* + * The following macros optimize certain frequently calculated + * quantities by using shifts and masks in place of divisions + * modulos and multiplications. + */ +#define blkoff(fs, loc) /* calculates (loc % fs->fs_bsize) */ \ + ((loc) & ~(fs)->fs_bmask) +#define fragoff(fs, loc) /* calculates (loc % fs->fs_fsize) */ \ + ((loc) & ~(fs)->fs_fmask) +#define lblkno(fs, loc) /* calculates (loc / fs->fs_bsize) */ \ + ((loc) >> (fs)->fs_bshift) +#define numfrags(fs, loc) /* calculates (loc / fs->fs_fsize) */ \ + ((loc) >> (fs)->fs_fshift) +#define blkroundup(fs, size) /* calculates roundup(size, fs->fs_bsize) */ \ + (((size) + (fs)->fs_bsize - 1) & (fs)->fs_bmask) +#define fragroundup(fs, size) /* calculates roundup(size, fs->fs_fsize) */ \ + (((size) + (fs)->fs_fsize - 1) & (fs)->fs_fmask) +#define fragstoblks(fs, frags) /* calculates (frags / fs->fs_frag) */ \ + ((frags) >> (fs)->fs_fragshift) +#define blkstofrags(fs, blks) /* calculates (blks * fs->fs_frag) */ \ + ((blks) << (fs)->fs_fragshift) +#define fragnum(fs, fsb) /* calculates (fsb % fs->fs_frag) */ \ + ((fsb) & ((fs)->fs_frag - 1)) +#define blknum(fs, fsb) /* calculates rounddown(fsb, fs->fs_frag) */ \ + ((fsb) &~ ((fs)->fs_frag - 1)) + +/* + * Determine the number of available frags given a + * percentage to hold in reserve + */ +#define freespace(fs, percentreserved) \ + (blkstofrags((fs), (fs)->fs_cstotal.cs_nbfree) + \ + (fs)->fs_cstotal.cs_nffree - ((fs)->fs_dsize * (percentreserved) / 100)) + +/* + * Determining the size of a file block in the file system. + */ +#define blksize(fs, ip, lbn) \ + (((lbn) >= NDADDR || (ip)->i_size >= ((lbn) + 1) << (fs)->fs_bshift) \ + ? (fs)->fs_bsize \ + : (fragroundup(fs, blkoff(fs, (ip)->i_size)))) +#define dblksize(fs, dip, lbn) \ + (((lbn) >= NDADDR || (dip)->di_size >= ((lbn) + 1) << (fs)->fs_bshift) \ + ? (fs)->fs_bsize \ + : (fragroundup(fs, blkoff(fs, (dip)->di_size)))) + +/* + * Number of disk sectors per block; assumes DEV_BSIZE byte sector size. + */ +#define NSPB(fs) ((fs)->fs_nspf << (fs)->fs_fragshift) +#define NSPF(fs) ((fs)->fs_nspf) + +/* + * INOPB is the number of inodes in a secondary storage block. + */ +#define INOPB(fs) ((fs)->fs_inopb) +#define INOPF(fs) ((fs)->fs_inopb >> (fs)->fs_fragshift) + +/* + * NINDIR is the number of indirects in a file system block. + */ +#define NINDIR(fs) ((fs)->fs_nindir) diff --git a/qemu/roms/openbios/fs/grubfs/fsys_affs.c b/qemu/roms/openbios/fs/grubfs/fsys_affs.c new file mode 100644 index 000000000..c4a76322b --- /dev/null +++ b/qemu/roms/openbios/fs/grubfs/fsys_affs.c @@ -0,0 +1,712 @@ +#ifdef FSYS_AFFS +#include "shared.h" +#include "filesys.h" + +/******************************** RDB definitions */ +#define RDB_LOCATION_LIMIT 16 +#define IDNAME_RIGIDDISK 0x5244534B /* 'RDSK' */ + +struct RigidDiskBlock +{ + unsigned long rdb_ID; + unsigned long rdb_SummedLongs; + long rdb_ChkSum; + unsigned long rdb_HostID; + unsigned long rdb_BlockBytes; + unsigned long rdb_Flags; + unsigned long rdb_BadBlockList; + unsigned long rdb_PartitionList; + unsigned long rdb_FileSysHeaderList; + unsigned long rdb_DriveInit; + unsigned long rdb_Reserved1[6]; + unsigned long rdb_Cylinders; + unsigned long rdb_Sectors; + unsigned long rdb_Heads; + unsigned long rdb_Interleave; + unsigned long rdb_Park; + unsigned long rdb_Reserved2[3]; + unsigned long rdb_WritePreComp; + unsigned long rdb_ReducedWrite; + unsigned long rdb_StepRate; + unsigned long rdb_Reserved3[5]; + unsigned long rdb_RDBBlocksLo; + unsigned long rdb_RDBBlocksHi; + unsigned long rdb_LoCylinder; + unsigned long rdb_HiCylinder; + unsigned long rdb_CylBlocks; + unsigned long rdb_AutoParkSeconds; + unsigned long rdb_HighRDSKBlock; + unsigned long rdb_Reserved4; + char rdb_DiskVendor[8]; + char rdb_DiskProduct[16]; + char rdb_DiskRevision[4]; + char rdb_ControllerVendor[8]; + char rdb_ControllerProduct[16]; + char rdb_ControllerRevision[4]; + char rdb_DriveInitName[40]; +}; + +struct PartitionBlock +{ + unsigned long pb_ID; + unsigned long pb_SummedLongs; + long pb_ChkSum; + unsigned long pb_HostID; + unsigned long pb_Next; + unsigned long pb_Flags; + unsigned long pb_Reserved1[2]; + unsigned long pb_DevFlags; + char pb_DriveName[32]; + unsigned long pb_Reserved2[15]; + unsigned long pb_Environment[20]; + unsigned long pb_EReserved[12]; +}; + +#define DE_TABLESIZE 0 +#define DE_SIZEBLOCK 1 +#define DE_BLOCKSIZE 2 +#define DE_NUMHEADS 3 +#define DE_SECSPERBLOCK 4 +#define DE_BLKSPERTRACK 5 +#define DE_RESERVEDBLKS 6 +#define DE_PREFAC 7 +#define DE_INTERLEAVE 8 +#define DE_LOWCYL 9 +#define DE_HIGHCYL 10 +#define DE_UPPERCYL DE_HIGHCYL +#define DE_NUMBUFFERS 11 +#define DE_BUFMEMTYPE 12 +#define DE_MEMBUFTYPE DE_BUFMEMTYPE +#define DE_MAXTRANSFER 13 +#define DE_MASK 14 +#define DE_BOOTPRI 15 +#define DE_DOSTYPE 16 +#define DE_BAUD 17 +#define DE_CONTROL 18 +#define DE_BOOTBLOCKS 19 + + +/******************************** AFFS definitions */ +#define T_SHORT 2 +#define T_LIST 16 + +#define ST_FILE -3 +#define ST_ROOT 1 +#define ST_USERDIR 2 + +struct BootBlock{ + int id; + int chksum; + int rootblock; + int data[127]; +}; + +struct RootBlock{ + int p_type; //0 + int n1[2]; //1-2 + int hashtable_size; //3 + int n2; //4 + int checksum; //5 + int hashtable[72]; //6-77 + int bitmap_valid_flag; //78 + int bitmap_ptrs[25]; //79-103 + int bitmap_extension; //104 + int root_days; //105 + int root_mins; //106 + int root_ticks; //107; + char diskname[32]; //108-115 + int n3[2]; //116-117 + int volume_days; //118 + int volume_mins; //119 + int volume_ticks; //120 + int creation_days; //121 + int creation_mins; //122 + int creation_ticks; //123 + int n4[3]; //124-126 + int s_type; //127 +}; + +struct DirHeader { + int p_type; //0 + int own_key; //1 + int n1[3]; //2-4 + int checksum; //5 + int hashtable[72]; //6-77 + int n2; //78 + int owner; //79 + int protection; //80 + int n3; //81 + char comment[92]; //82-104 + int days; //105 + int mins; //106 + int ticks; //107 + char name[32]; //108-115 + int n4[2]; //116-117 + int linkchain; //118 + int n5[5]; //119-123 + int hashchain; //124 + int parent; //125 + int n6; //126 + int s_type; //127 +}; + +struct FileHeader { + int p_type; //0 + int own_key; //1 + int n1[3]; //2-4 + int checksum; //5 + int filekey_table[72]; //6-77 + int n2; //78 + int owner; //79 + int protection; //80 + int bytesize; //81 + char comment[92]; //82-104 + int days; //105 + int mins; //106 + int ticks; //107 + char name[32]; //108-115 + int n3[2]; //116-117 + int linkchain; //118 + int n4[5]; //119-123 + int hashchain; //124 + int parent; //125 + int extension; //126 + int s_type; //127 +}; + +struct FileKeyExtension{ + int p_type; //0 + int own_key; //1 + int table_size; //2 + int n1[2]; //3-4 + int checksum; //5 + int filekey_table[72]; //6-77 + int info[46]; //78-123 + int n2; //124 + int parent; //125 + int extension; //126 + int s_type; //127 +}; + +struct Position { + unsigned int block; + short filekey; + unsigned short byte; + unsigned int offset; +}; + +struct ReadData { + unsigned int header_block; + struct Position current; + unsigned int filesize; +}; + +//#warning "Big vs. little endian for configure needed" +#define AROS_BE2LONG(l) \ + ( \ + ((((unsigned long)(l)) >> 24) & 0x000000FFUL) | \ + ((((unsigned long)(l)) >> 8) & 0x0000FF00UL) | \ + ((((unsigned long)(l)) << 8) & 0x00FF0000UL) | \ + ((((unsigned long)(l)) << 24) & 0xFF000000UL) \ + ) + +struct CacheBlock { + int blocknum; + unsigned short flags; + unsigned short access_count; + unsigned int blockbuffer[128]; +}; +#define LockBuffer(x) (((struct CacheBlock *)(x))->flags |= 0x0001) +#define UnLockBuffer(x) (((struct CacheBlock *)(x))->flags &= ~0x0001) + +#define MAX_CACHE_BLOCKS 10 + +struct FSysBuffer { + struct ReadData file; + struct CacheBlock blocks[MAX_CACHE_BLOCKS]; +}; + +#define bootBlock(x) ((struct BootBlock *)(x)->blockbuffer) +#define rootBlock(x) ((struct RootBlock *)(x)->blockbuffer) +#define dirHeader(x) ((struct DirHeader *)(x)->blockbuffer) +#define fileHeader(x) ((struct FileHeader *)(x)->blockbuffer) +#define extensionBlock(x) ((struct FileKeyExtension *)(x)->blockbuffer) + +#define rdsk(x) ((struct RigidDiskBlock *)(x)->blockbuffer) +#define part(x) ((struct PartitionBlock *)(x)->blockbuffer) + +static struct FSysBuffer *fsysb; +static int blockoffset; /* offset if there is an embedded RDB partition */ +static int rootb; /* block number of root block */ +static int rdbb; /* block number of rdb block */ + +static void initCache(void) +{ +int i; + + for (i=0;i<MAX_CACHE_BLOCKS;i++) + { + fsysb->blocks[i].blocknum = -1; + fsysb->blocks[i].flags = 0; + fsysb->blocks[i].access_count = 0; + } +} + +static struct CacheBlock *getBlock(unsigned int block) +{ +struct CacheBlock *freeblock; +int i; + + /* get first unlocked block */ + i = 0; + do + { + freeblock = &fsysb->blocks[i++]; + } while (freeblock->flags & 0x0001); + /* search through list if block is already loaded in */ + for (i=0;i<MAX_CACHE_BLOCKS;i++) + { + if (fsysb->blocks[i].blocknum == block) + { + fsysb->blocks[i].access_count++; + return &fsysb->blocks[i]; + } + if (!(fsysb->blocks[i].flags & 0x0001)) + if (freeblock->access_count>fsysb->blocks[i].access_count) + freeblock = &fsysb->blocks[i]; + } + freeblock->blocknum = block; + devread(block+blockoffset, 0, 512, (char *)freeblock->blockbuffer); + return freeblock; +} + +static unsigned int calcChkSum(unsigned short SizeBlock, unsigned int *buffer) +{ +unsigned int sum=0,count=0; + + for (count=0;count<SizeBlock;count++) + sum += AROS_BE2LONG(buffer[count]); + return sum; +} + +int affs_mount(void) { +struct CacheBlock *cblock; +int i; + + if ( + (current_drive & 0x80) && + (current_partition != 0xFFFFFF) && + (current_slice != 0x30) + ) + return 0; + fsysb = (struct FSysBuffer *)FSYS_BUF; + blockoffset = 0; + initCache(); + /* check for rdb partitiontable */ + for (i=0;i<RDB_LOCATION_LIMIT;i++) + { + cblock = getBlock(i); + if ( + ( + ((AROS_BE2LONG(bootBlock(cblock)->id) & 0xFFFFFF00)==0x444F5300) && + ((AROS_BE2LONG(bootBlock(cblock)->id) & 0xFF)>0) + ) || + (AROS_BE2LONG(cblock->blockbuffer[0]) == IDNAME_RIGIDDISK) + ) + break; + } + if (i == RDB_LOCATION_LIMIT) + return 0; + if (AROS_BE2LONG(cblock->blockbuffer[0]) == IDNAME_RIGIDDISK) + { + /* we have an RDB partition table within a MBR-Partition */ + rdbb = i; + } + else if (i<2) + { + /* partition type is 0x30 = AROS and AFFS formatted */ + rdbb = RDB_LOCATION_LIMIT; + rootb = (part_length-1+2)/2; + cblock = getBlock(rootb); + if ( + (AROS_BE2LONG(rootBlock(cblock)->p_type) != T_SHORT) || + (AROS_BE2LONG(rootBlock(cblock)->s_type) != ST_ROOT) || + calcChkSum(128, cblock->blockbuffer) + ) + return 0; + } + else + return 0; + return 1; +} + +static int seek(unsigned long offset) +{ +struct CacheBlock *cblock; +unsigned long block; +unsigned long togo; + + block = fsysb->file.header_block; + + togo = offset / 512; + fsysb->file.current.filekey = 71-(togo % 72); + togo /= 72; + fsysb->file.current.byte = offset % 512; + fsysb->file.current.offset = offset; + while ((togo) && (block)) + { + disk_read_func = disk_read_hook; + cblock = getBlock(block); + disk_read_func = NULL; + block = AROS_BE2LONG(extensionBlock(cblock)->extension); + togo--; + } + if (togo) + return 1; + fsysb->file.current.block = block; + return 0; +} + +int affs_read(char *buf, int len) { +struct CacheBlock *cblock; +unsigned short size; +unsigned int readbytes = 0; + + if (fsysb->file.current.offset != filepos) + { + if (seek(filepos)) + return ERR_FILELENGTH; + } + if (fsysb->file.current.block == 0) + return 0; + if (len>(fsysb->file.filesize-fsysb->file.current.offset)) + len=fsysb->file.filesize-fsysb->file.current.offset; + disk_read_func = disk_read_hook; + cblock = getBlock(fsysb->file.current.block); + disk_read_func = NULL; + while (len) + { + disk_read_func = disk_read_hook; + if (fsysb->file.current.filekey<0) + { + fsysb->file.current.filekey = 71; + fsysb->file.current.block = AROS_BE2LONG(extensionBlock(cblock)->extension); + if (fsysb->file.current.block) + { + cblock = getBlock(fsysb->file.current.block); + } + //#warning "else shouldn't occour" + } + size = 512; + size -= fsysb->file.current.byte; + if (size>len) + { + size = len; + devread + ( + AROS_BE2LONG + ( + extensionBlock(cblock)->filekey_table + [fsysb->file.current.filekey] + )+blockoffset, + fsysb->file.current.byte, size, (char *)((long)buf+readbytes) + ); + fsysb->file.current.byte += size; + } + else + { + devread + ( + AROS_BE2LONG + ( + extensionBlock(cblock)->filekey_table + [fsysb->file.current.filekey] + )+blockoffset, + fsysb->file.current.byte, size, (char *)((long)buf+readbytes) + ); + fsysb->file.current.byte = 0; + fsysb->file.current.filekey--; + } + disk_read_func = NULL; + len -= size; + readbytes += size; + } + fsysb->file.current.offset += readbytes; + filepos = fsysb->file.current.offset; + return readbytes; +} + +static unsigned char capitalch(unsigned char ch, unsigned char flags) +{ + + if ((flags==0) || (flags==1)) + return (unsigned char)((ch>='a') && (ch<='z') ? ch-('a'-'A') : ch); + else // DOS\(>=2) + return (unsigned char)(((ch>=224) && (ch<=254) && (ch!=247)) || + ((ch>='a') && (ch<='z')) ? ch-('a'-'A') : ch); +} + +// str2 is a BCPL string +static int noCaseStrCmp(char *str1, char *str2, unsigned char flags) +{ +unsigned char length; + + length=str2++[0]; + do { + if ((*str1==0) && (length==0)) + return 0; + length--; +// if ((*str1==0) && (*str2==0)) return 1; + } while (capitalch(*str1++,flags)==capitalch(*str2++,flags)); + str1--; + return (*str1) ? 1 : -1; +} + +static unsigned int getHashKey(char *name,unsigned int tablesize, unsigned char flags) +{ +unsigned int length; + + length=0; + while (name[length] != 0) + length++; + while (*name!=0) + length=(length * 13 +capitalch(*name++,flags)) & 0x7FF; + return length%tablesize; +} + +static grub_error_t getHeaderBlock(char *name, struct CacheBlock **dirh) +{ +int key; + + key = getHashKey(name, 72, 1); + if (!dirHeader(*dirh)->hashtable[key]) + return ERR_FILE_NOT_FOUND; + *dirh = getBlock(AROS_BE2LONG(dirHeader(*dirh)->hashtable[key])); + if (calcChkSum(128, (*dirh)->blockbuffer)) + { +#ifdef DEBUG_AFFS +printf("ghb: %d\n", (*dirh)->blocknum); +#endif + return ERR_FSYS_CORRUPT; + } + if (AROS_BE2LONG(dirHeader(*dirh)->p_type) != T_SHORT) + return ERR_BAD_FILETYPE; + while (noCaseStrCmp(name,dirHeader(*dirh)->name,1) != 0) + { + if (!dirHeader(*dirh)->hashchain) + return ERR_FILE_NOT_FOUND; + *dirh = getBlock(AROS_BE2LONG(dirHeader(*dirh)->hashchain)); + if (calcChkSum(128, (*dirh)->blockbuffer)) + { +#ifdef DEBUG_AFFS +printf("ghb2: %d\n", (*dirh)->blocknum); +#endif + return ERR_FSYS_CORRUPT; + } + if (AROS_BE2LONG(dirHeader(*dirh)->p_type) != T_SHORT) + return ERR_BAD_FILETYPE; + } + return 0; +} + +static char *copyPart(char *src, char *dst) +{ + while ((*src != '/') && (*src)) + *dst++ = *src++; + if (*src == '/') + src++; + *dst-- = 0; + /* cut off spaces at the end */ + while (*dst == ' ') + *dst-- = 0; + return src; +} + +static grub_error_t findBlock(char *name, struct CacheBlock **dirh) +{ +char dname[32]; +int block; + + name++; /* skip "/" */ + /* partition table part */ + if (rdbb < RDB_LOCATION_LIMIT) + { + int bpc; + + blockoffset = 0; + *dirh = getBlock(rdbb); + if (*name==0) + return 0; + name = copyPart(name, dname); + bpc = AROS_BE2LONG(rdsk(*dirh)->rdb_Sectors)*AROS_BE2LONG(rdsk(*dirh)->rdb_Heads); + block = AROS_BE2LONG(rdsk(*dirh)->rdb_PartitionList); + while (block != -1) + { + *dirh = getBlock(block); + if (noCaseStrCmp(dname, part(*dirh)->pb_DriveName, 1) == 0) + break; + block = AROS_BE2LONG(part(*dirh)->pb_Next); + } + if (block == -1) + return ERR_FILE_NOT_FOUND; + if ( + ((AROS_BE2LONG(part(*dirh)->pb_Environment[DE_DOSTYPE]) & 0xFFFFFF00)!=0x444F5300) || + ((AROS_BE2LONG(part(*dirh)->pb_Environment[DE_DOSTYPE]) & 0xFF)==0) + ) + return ERR_BAD_FILETYPE; + blockoffset = AROS_BE2LONG(part(*dirh)->pb_Environment[DE_LOWCYL]); + rootb = AROS_BE2LONG(part(*dirh)->pb_Environment[DE_HIGHCYL]); + rootb = rootb-blockoffset+1; /* highcyl-lowcyl+1 */ + rootb *= bpc; + rootb = rootb-1+AROS_BE2LONG(part(*dirh)->pb_Environment[DE_RESERVEDBLKS]); + rootb /= 2; + blockoffset *= bpc; + } + + /* filesystem part */ + *dirh = getBlock(rootb); + while (*name) + { + if ( + (AROS_BE2LONG(dirHeader(*dirh)->s_type) != ST_ROOT) && + (AROS_BE2LONG(dirHeader(*dirh)->s_type) != ST_USERDIR) + ) + return ERR_BAD_FILETYPE; + name = copyPart(name, dname); + errnum = getHeaderBlock(dname, dirh); + if (errnum) + return errnum; + } + return 0; +} + +#ifndef STAGE1_5 +static void checkPossibility(char *filename, char *bstr) +{ + char cstr[32]; + + if (noCaseStrCmp(filename, bstr, 1)<=0) + { + if (print_possibilities>0) + print_possibilities = -print_possibilities; + memcpy(cstr, bstr+1, bstr[0]); + cstr[bstr[0]]=0; + print_a_completion(cstr); + } +} +#else +#define checkPossibility(a, b) do { } while(0) +#endif + +int affs_dir(char *dirname) +{ + struct CacheBlock *buffer1; + struct CacheBlock *buffer2; + char *current = dirname; + char filename[128]; + char *fname = filename; + int i,block; + + if (print_possibilities) + { + while (*current) + current++; + while (*current != '/') + current--; + current++; + while (*current) + { + *fname++ = *current; + *current++ = 0; + } + *fname=0; + errnum = findBlock(dirname, &buffer1); + if (errnum) + return 0; + if (AROS_BE2LONG(dirHeader(buffer1)->p_type) == IDNAME_RIGIDDISK) + { + block = AROS_BE2LONG(rdsk(buffer1)->rdb_PartitionList); + while (block != -1) + { + buffer1 = getBlock(block); + checkPossibility(filename, part(buffer1)->pb_DriveName); + block = AROS_BE2LONG(part(buffer1)->pb_Next); + } +#ifndef STAGE1_5 + if (*filename == 0) + if (print_possibilities>0) + print_possibilities = -print_possibilities; +#endif + } + else if (AROS_BE2LONG(dirHeader(buffer1)->p_type) == T_SHORT) + { + LockBuffer(buffer1); + for (i=0;i<72;i++) + { + block = dirHeader(buffer1)->hashtable[i]; + while (block) + { + buffer2 = getBlock(AROS_BE2LONG(block)); + if (calcChkSum(128, buffer2->blockbuffer)) + { + errnum = ERR_FSYS_CORRUPT; + return 0; + } + if (AROS_BE2LONG(dirHeader(buffer2)->p_type) != T_SHORT) + { + errnum = ERR_BAD_FILETYPE; + return 0; + } + checkPossibility(filename, dirHeader(buffer2)->name); + block = dirHeader(buffer2)->hashchain; + } + } + UnLockBuffer(buffer1); +#ifndef STAGE1_5 + if (*filename == 0) + if (print_possibilities>0) + print_possibilities = -print_possibilities; +#endif + } + else + { + errnum = ERR_BAD_FILETYPE; + return 0; + } + while (*current != '/') + current--; + current++; + fname = filename; + while (*fname) + *current++ = *fname++; + //#warning "TODO: add some more chars until possibilities differ" + if (print_possibilities>0) + errnum = ERR_FILE_NOT_FOUND; + return (print_possibilities<0); + } + else + { + while (*current && !isspace(*current)) + *fname++ = *current++; + *fname = 0; + + errnum = findBlock(filename, &buffer2); + if (errnum) + return 0; + if (AROS_BE2LONG(fileHeader(buffer2)->s_type)!=ST_FILE) + { + errnum = ERR_BAD_FILETYPE; + return 0; + } + fsysb->file.header_block = AROS_BE2LONG(fileHeader(buffer2)->own_key); + fsysb->file.current.block = AROS_BE2LONG(fileHeader(buffer2)->own_key); + fsysb->file.current.filekey = 71; + fsysb->file.current.byte = 0; + fsysb->file.current.offset = 0; + fsysb->file.filesize = AROS_BE2LONG(fileHeader(buffer2)->bytesize); + filepos = 0; + filemax = fsysb->file.filesize; + return 1; + } +} +#endif diff --git a/qemu/roms/openbios/fs/grubfs/fsys_ext2fs.c b/qemu/roms/openbios/fs/grubfs/fsys_ext2fs.c new file mode 100644 index 000000000..05425bbd3 --- /dev/null +++ b/qemu/roms/openbios/fs/grubfs/fsys_ext2fs.c @@ -0,0 +1,794 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 1999, 2001 Free Software Foundation, Inc. + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#ifdef FSYS_EXT2FS + +#include "config.h" +#include "shared.h" +#include "filesys.h" +#include "libc/byteorder.h" + +#ifdef CONFIG_DEBUG_EXT2FS +#define E2DEBUG +#endif + +static int mapblock1, mapblock2; + +/* sizes are always in bytes, BLOCK values are always in DEV_BSIZE (sectors) */ +#define DEV_BSIZE 512 + +/* include/linux/fs.h */ +#define BLOCK_SIZE 1024 /* initial block size for superblock read */ +/* made up, defaults to 1 but can be passed via mount_opts */ +#define WHICH_SUPER 1 +/* kind of from fs/ext2/super.c */ +#define SBLOCK (WHICH_SUPER * BLOCK_SIZE / DEV_BSIZE) /* = 2 */ + +/* include/asm-i386/types.h */ +typedef __signed__ char __s8; +typedef unsigned char __u8; +typedef __signed__ short __s16; +typedef unsigned short __u16; +typedef __signed__ int __s32; +typedef unsigned int __u32; + +/* + * Constants relative to the data blocks, from ext2_fs.h + */ +#define EXT2_NDIR_BLOCKS 12 +#define EXT2_IND_BLOCK EXT2_NDIR_BLOCKS +#define EXT2_DIND_BLOCK (EXT2_IND_BLOCK + 1) +#define EXT2_TIND_BLOCK (EXT2_DIND_BLOCK + 1) +#define EXT2_N_BLOCKS (EXT2_TIND_BLOCK + 1) + +/* include/linux/ext2_fs.h */ +struct ext2_super_block + { + __u32 s_inodes_count; /* Inodes count */ + __u32 s_blocks_count; /* Blocks count */ + __u32 s_r_blocks_count; /* Reserved blocks count */ + __u32 s_free_blocks_count; /* Free blocks count */ + __u32 s_free_inodes_count; /* Free inodes count */ + __u32 s_first_data_block; /* First Data Block */ + __u32 s_log_block_size; /* Block size */ + __s32 s_log_frag_size; /* Fragment size */ + __u32 s_blocks_per_group; /* # Blocks per group */ + __u32 s_frags_per_group; /* # Fragments per group */ + __u32 s_inodes_per_group; /* # Inodes per group */ + __u32 s_mtime; /* Mount time */ + __u32 s_wtime; /* Write time */ + __u16 s_mnt_count; /* Mount count */ + __s16 s_max_mnt_count; /* Maximal mount count */ + __u16 s_magic; /* Magic signature */ + __u16 s_state; /* File system state */ + __u16 s_errors; /* Behaviour when detecting errors */ + __u16 s_pad; + __u32 s_lastcheck; /* time of last check */ + __u32 s_checkinterval; /* max. time between checks */ + __u32 s_creator_os; /* OS */ + __u32 s_rev_level; /* Revision level */ + __u16 s_def_resuid; /* Default uid for reserved blocks */ + __u16 s_def_resgid; /* Default gid for reserved blocks */ + __u32 s_reserved[235]; /* Padding to the end of the block */ + }; + +struct ext2_group_desc + { + __u32 bg_block_bitmap; /* Blocks bitmap block */ + __u32 bg_inode_bitmap; /* Inodes bitmap block */ + __u32 bg_inode_table; /* Inodes table block */ + __u16 bg_free_blocks_count; /* Free blocks count */ + __u16 bg_free_inodes_count; /* Free inodes count */ + __u16 bg_used_dirs_count; /* Directories count */ + __u16 bg_pad; + __u32 bg_reserved[3]; + }; + +struct ext2_inode + { + __u16 i_mode; /* File mode */ + __u16 i_uid; /* Owner Uid */ + __u32 i_size; /* 4: Size in bytes */ + __u32 i_atime; /* Access time */ + __u32 i_ctime; /* 12: Creation time */ + __u32 i_mtime; /* Modification time */ + __u32 i_dtime; /* 20: Deletion Time */ + __u16 i_gid; /* Group Id */ + __u16 i_links_count; /* 24: Links count */ + __u32 i_blocks; /* Blocks count */ + __u32 i_flags; /* 32: File flags */ + union + { + struct + { + __u32 l_i_reserved1; + } + linux1; + struct + { + __u32 h_i_translator; + } + hurd1; + struct + { + __u32 m_i_reserved1; + } + masix1; + } + osd1; /* OS dependent 1 */ + __u32 i_block[EXT2_N_BLOCKS]; /* 40: Pointers to blocks */ + __u32 i_version; /* File version (for NFS) */ + __u32 i_file_acl; /* File ACL */ + __u32 i_dir_acl; /* Directory ACL */ + __u32 i_faddr; /* Fragment address */ + union + { + struct + { + __u8 l_i_frag; /* Fragment number */ + __u8 l_i_fsize; /* Fragment size */ + __u16 i_pad1; + __u32 l_i_reserved2[2]; + } + linux2; + struct + { + __u8 h_i_frag; /* Fragment number */ + __u8 h_i_fsize; /* Fragment size */ + __u16 h_i_mode_high; + __u16 h_i_uid_high; + __u16 h_i_gid_high; + __u32 h_i_author; + } + hurd2; + struct + { + __u8 m_i_frag; /* Fragment number */ + __u8 m_i_fsize; /* Fragment size */ + __u16 m_pad1; + __u32 m_i_reserved2[2]; + } + masix2; + } + osd2; /* OS dependent 2 */ + }; + +/* linux/posix_type.h */ +typedef long linux_off_t; + +/* linux/ext2fs.h */ +#define EXT2_NAME_LEN 255 +struct ext2_dir_entry + { + __u32 inode; /* Inode number */ + __u16 rec_len; /* Directory entry length */ + __u8 name_len; /* Name length */ + __u8 file_type; + char name[EXT2_NAME_LEN]; /* File name */ + }; + +/* ext2/super.c */ +#define EXT2_SUPER_MAGIC 0xEF53 /* include/linux/ext2_fs.h */ +#define EXT2_ROOT_INO 2 /* include/linux/ext2_fs.h */ +#define PATH_MAX 1024 /* include/linux/limits.h */ +#define MAX_LINK_COUNT 5 /* number of symbolic links to follow */ + +/* made up, these are pointers into FSYS_BUF */ +/* read once, always stays there: */ +#define SUPERBLOCK \ + ((struct ext2_super_block *)(FSYS_BUF)) +#define GROUP_DESC \ + ((struct ext2_group_desc *) \ + ((char *)SUPERBLOCK + sizeof(struct ext2_super_block))) +#define INODE \ + ((struct ext2_inode *)((char *)GROUP_DESC + EXT2_BLOCK_SIZE(SUPERBLOCK))) +#define DATABLOCK1 \ + ((char *)((char *)INODE + sizeof(struct ext2_inode))) +#define DATABLOCK2 \ + ((char *)((char *)DATABLOCK1 + EXT2_BLOCK_SIZE(SUPERBLOCK))) + +/* linux/ext2_fs.h */ +#define EXT2_ADDR_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (__u32)) +#define EXT2_ADDR_PER_BLOCK_BITS(s) (log2(EXT2_ADDR_PER_BLOCK(s))) + +/* linux/ext2_fs.h */ +#define EXT2_BLOCK_SIZE_BITS(s) (__le32_to_cpu((s)->s_log_block_size) + 10) +/* kind of from ext2/super.c */ +#define EXT2_BLOCK_SIZE(s) (1 << EXT2_BLOCK_SIZE_BITS(s)) +/* linux/ext2fs.h */ +#define EXT2_DESC_PER_BLOCK(s) \ + (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_group_desc)) +/* linux/stat.h */ +#define S_IFMT 00170000 +#define S_IFLNK 0120000 +#define S_IFREG 0100000 +#define S_IFDIR 0040000 +#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) +#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) +#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) + +#ifdef E2DEBUG +void +dump_super(struct ext2_super_block *s) +{ + printf(" superblock 0x%x:\n", s); + printf(" inodes=%d\n", __le32_to_cpu(s->s_inodes_count)); + printf(" blocks=%d\n", __le32_to_cpu(s->s_blocks_count)); + printf(" reserved=%d\n", __le32_to_cpu(s->s_r_blocks_count)); + printf(" i_free=%d\n", __le32_to_cpu(s->s_free_inodes_count)); + printf(" b_free=%d\n", __le32_to_cpu(s->s_free_blocks_count)); + printf(" first=%d\n", __le32_to_cpu(s->s_first_data_block)); + printf(" log_b_size=%d, b_size=%d\n", __le32_to_cpu(s->s_log_block_size), EXT2_BLOCK_SIZE(s)); + printf(" log_f_size=%d\n", __le32_to_cpu(s->s_log_frag_size)); + printf(" bpg=%d\n", __le32_to_cpu(s->s_blocks_per_group)); + printf(" fpg=%d\n", __le32_to_cpu(s->s_frags_per_group)); + printf(" ipg=%d\n", __le32_to_cpu(s->s_inodes_per_group)); +} + +void +dump_group_desc(struct ext2_group_desc *g) +{ + printf(" group_desc 0x%x:\n", g); + printf(" b_bmap block=%d\n", __le32_to_cpu(g->bg_block_bitmap)); + printf(" i_bmap block=%d\n", __le32_to_cpu(g->bg_inode_bitmap)); + printf(" i_tab block=%d\n", __le32_to_cpu(g->bg_inode_table)); + printf(" free_blks=%d\n", __le16_to_cpu(g->bg_free_blocks_count)); + printf(" free_inodes=%d\n", __le16_to_cpu(g->bg_free_inodes_count)); + printf(" used_dirs=%d\n", __le16_to_cpu(g->bg_used_dirs_count)); +} + +void +dump_inode(struct ext2_inode *i) +{ + printf(" inode 0x%x:\n", i); + printf(" mode=%o\n", __le16_to_cpu(i->i_mode)); + printf(" uid=%d\n", __le16_to_cpu(i->i_uid)); + printf(" gid=%d\n", __le16_to_cpu(i->i_gid)); + printf(" size=%d\n", __le32_to_cpu(i->i_size)); + printf(" atime=%d\n", __le32_to_cpu(i->i_atime)); + printf(" ctime=%d\n", __le32_to_cpu(i->i_ctime)); + printf(" mtime=%d\n", __le32_to_cpu(i->i_mtime)); + printf(" dtime=%d\n", __le32_to_cpu(i->i_dtime)); + printf(" links=%d\n", __le16_to_cpu(i->i_links_count)); + printf(" blocks=%d\n", __le32_to_cpu(i->i_blocks)); + printf(" flags=%d\n", __le32_to_cpu(i->i_flags)); +} + +void +dump_inode_data(unsigned char *inode, int len) +{ + static char hexdigit[] = "0123456789abcdef"; + unsigned char *i; + for (i = inode; + i < (inode + len); + i++) + { + printf ("%c", hexdigit[*i >> 4]); + printf ("%c", hexdigit[*i % 16]); + if (!((i + 1 - inode) % 16)) + { + printf ("\n"); + } + else + { + printf (" "); + } + } +} +#endif + +/* check filesystem types and read superblock into memory buffer */ +int +ext2fs_mount (void) +{ + int retval = 1; + + if ((((current_drive & 0x80) || (current_slice != 0)) + && (current_slice != PC_SLICE_TYPE_EXT2FS) + && (current_slice != PC_SLICE_TYPE_LINUX_RAID) + && (! IS_PC_SLICE_TYPE_BSD_WITH_FS (current_slice, FS_EXT2FS)) + && (! IS_PC_SLICE_TYPE_BSD_WITH_FS (current_slice, FS_OTHER))) + || part_length < (SBLOCK + (sizeof (struct ext2_super_block) / DEV_BSIZE)) + || !devread (SBLOCK, 0, sizeof (struct ext2_super_block), + (char *) SUPERBLOCK) + || __le16_to_cpu(SUPERBLOCK->s_magic) != EXT2_SUPER_MAGIC) + retval = 0; + + return retval; +} + +/* Takes a file system block number and reads it into BUFFER. */ +static int +ext2_rdfsb (int fsblock, char * buffer) +{ +#ifdef E2DEBUG + printf ("ext2_rdfsb: fsblock %d, devblock %d, size %d\n", fsblock, + fsblock * (EXT2_BLOCK_SIZE (SUPERBLOCK) / DEV_BSIZE), + EXT2_BLOCK_SIZE (SUPERBLOCK)); +#endif /* E2DEBUG */ + return devread (fsblock * (EXT2_BLOCK_SIZE (SUPERBLOCK) / DEV_BSIZE), 0, + EXT2_BLOCK_SIZE (SUPERBLOCK), (char *) buffer); +} + +/* from + ext2/inode.c:ext2_bmap() +*/ +/* Maps LOGICAL_BLOCK (the file offset divided by the blocksize) into + a physical block (the location in the file system) via an inode. */ +static int +ext2fs_block_map (int logical_block) +{ + +#ifdef E2DEBUG + printf ("ext2fs_block_map(%d)\n", logical_block); +#endif /* E2DEBUG */ + + /* if it is directly pointed to by the inode, return that physical addr */ + if (logical_block < EXT2_NDIR_BLOCKS) + { +#ifdef E2DEBUG + printf ("ext2fs_block_map: returning %d\n", __le32_to_cpu(INODE->i_block[logical_block])); +#endif /* E2DEBUG */ + return __le32_to_cpu(INODE->i_block[logical_block]); + } + /* else */ + logical_block -= EXT2_NDIR_BLOCKS; + /* try the indirect block */ + if (logical_block < EXT2_ADDR_PER_BLOCK (SUPERBLOCK)) + { + if (mapblock1 != 1 + && !ext2_rdfsb (__le32_to_cpu(INODE->i_block[EXT2_IND_BLOCK]), DATABLOCK1)) + { + errnum = ERR_FSYS_CORRUPT; + return -1; + } + mapblock1 = 1; + return __le32_to_cpu(((__u32 *) DATABLOCK1)[logical_block]); + } + /* else */ + logical_block -= EXT2_ADDR_PER_BLOCK (SUPERBLOCK); + /* now try the double indirect block */ + if (logical_block < (1 << (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK) * 2))) + { + int bnum; + if (mapblock1 != 2 + && !ext2_rdfsb (__le32_to_cpu(INODE->i_block[EXT2_DIND_BLOCK]), DATABLOCK1)) + { + errnum = ERR_FSYS_CORRUPT; + return -1; + } + mapblock1 = 2; + if ((bnum = __le32_to_cpu(((__u32 *) DATABLOCK1) + [logical_block >> EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK)])) + != mapblock2 + && !ext2_rdfsb (bnum, DATABLOCK2)) + { + errnum = ERR_FSYS_CORRUPT; + return -1; + } + mapblock2 = bnum; + return __le32_to_cpu(((__u32 *) DATABLOCK2) + [logical_block & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)]); + } + /* else */ + mapblock2 = -1; + logical_block -= (1 << (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK) * 2)); + if (mapblock1 != 3 + && !ext2_rdfsb (__le32_to_cpu(INODE->i_block[EXT2_TIND_BLOCK]), DATABLOCK1)) + { + errnum = ERR_FSYS_CORRUPT; + return -1; + } + mapblock1 = 3; + if (!ext2_rdfsb (__le32_to_cpu(((__u32 *) DATABLOCK1) + [logical_block >> (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK) + * 2)]), + DATABLOCK2)) + { + errnum = ERR_FSYS_CORRUPT; + return -1; + } + if (!ext2_rdfsb (__le32_to_cpu(((__u32 *) DATABLOCK2) + [(logical_block >> EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK)) + & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)]), + DATABLOCK2)) + { + errnum = ERR_FSYS_CORRUPT; + return -1; + } + return __le32_to_cpu(((__u32 *) DATABLOCK2) + [logical_block & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)]); +} + +/* preconditions: all preconds of ext2fs_block_map */ +int +ext2fs_read (char *buf, int len) +{ + int logical_block; + int offset; + int map; + int ret = 0; + int size = 0; + +#ifdef E2DEBUG + printf("ext2fs_read(0x%x, %d)\n", buf, len); + dump_inode(INODE); + dump_inode_data((unsigned char *)INODE, sizeof (struct ext2_inode)); +#endif /* E2DEBUG */ + while (len > 0) + { + /* find the (logical) block component of our location */ + logical_block = filepos >> EXT2_BLOCK_SIZE_BITS (SUPERBLOCK); + offset = filepos & (EXT2_BLOCK_SIZE (SUPERBLOCK) - 1); + map = ext2fs_block_map (logical_block); +#ifdef E2DEBUG + printf ("map=%d\n", map); +#endif /* E2DEBUG */ + if (map < 0) + break; + + size = EXT2_BLOCK_SIZE (SUPERBLOCK); + size -= offset; + if (size > len) + size = len; + + disk_read_func = disk_read_hook; + + devread (map * (EXT2_BLOCK_SIZE (SUPERBLOCK) / DEV_BSIZE), + offset, size, buf); + + disk_read_func = NULL; + + buf += size; + len -= size; + filepos += size; + ret += size; + } + + if (errnum) + ret = 0; + + return ret; +} + + +/* Based on: + def_blk_fops points to + blkdev_open, which calls (I think): + sys_open() + do_open() + open_namei() + dir_namei() which accesses current->fs->root + fs->root was set during original mount: + (something)... which calls (I think): + ext2_read_super() + iget() + __iget() + read_inode() + ext2_read_inode() + uses desc_per_block_bits, which is set in ext2_read_super() + also uses group descriptors loaded during ext2_read_super() + lookup() + ext2_lookup() + ext2_find_entry() + ext2_getblk() + +*/ + +/* preconditions: ext2fs_mount already executed, therefore supblk in buffer + * known as SUPERBLOCK + * returns: 0 if error, nonzero iff we were able to find the file successfully + * postconditions: on a nonzero return, buffer known as INODE contains the + * inode of the file we were trying to look up + * side effects: messes up GROUP_DESC buffer area + */ +int +ext2fs_dir (char *dirname) +{ + int current_ino = EXT2_ROOT_INO; /* start at the root */ + int updir_ino = current_ino; /* the parent of the current directory */ + int group_id; /* which group the inode is in */ + int group_desc; /* fs pointer to that group */ + int desc; /* index within that group */ + int ino_blk; /* fs pointer of the inode's information */ + int str_chk = 0; /* used to hold the results of a string compare */ + struct ext2_group_desc *gdp; + struct ext2_inode *raw_inode; /* inode info corresponding to current_ino */ + + char linkbuf[PATH_MAX]; /* buffer for following symbolic links */ + int link_count = 0; + + char *rest; + char ch; /* temp char holder */ + + int off; /* offset within block of directory entry (off mod blocksize) */ + int loc; /* location within a directory */ + int blk; /* which data blk within dir entry (off div blocksize) */ + long map; /* fs pointer of a particular block from dir entry */ + struct ext2_dir_entry *dp; /* pointer to directory entry */ + + /* loop invariants: + current_ino = inode to lookup + dirname = pointer to filename component we are cur looking up within + the directory known pointed to by current_ino (if any) + */ + +#ifdef E2DEBUG + printf("****** ext2fs_dir(%s)\n", dirname); + dump_super(SUPERBLOCK); +#endif /* E2DEBUG */ + + while (1) + { +#ifdef E2DEBUG + printf ("ext2fs_dir: inode %d\n", current_ino); + printf ("ext2fs_dir: dirname=%s\n", dirname); +#endif /* E2DEBUG */ + + /* look up an inode */ + group_id = (current_ino - 1) / __le32_to_cpu(SUPERBLOCK->s_inodes_per_group); + group_desc = group_id >> log2 (EXT2_DESC_PER_BLOCK (SUPERBLOCK)); + desc = group_id & (EXT2_DESC_PER_BLOCK (SUPERBLOCK) - 1); +#ifdef E2DEBUG + printf ("ext2fs_dir: ipg=%d, dpb=%d\n", __le32_to_cpu(SUPERBLOCK->s_inodes_per_group), + EXT2_DESC_PER_BLOCK (SUPERBLOCK)); + printf ("ext2fs_dir: group_id=%d group_desc=%d desc=%d\n", group_id, group_desc, desc); +#endif /* E2DEBUG */ + if (!ext2_rdfsb ( + (WHICH_SUPER + group_desc + __le32_to_cpu(SUPERBLOCK->s_first_data_block)), + (char*) GROUP_DESC)) + { + return 0; + } + +#ifdef E2DEBUG + dump_group_desc(GROUP_DESC); +#endif /* E2DEBUG */ + + gdp = GROUP_DESC; + ino_blk = __le32_to_cpu(gdp[desc].bg_inode_table) + + (((current_ino - 1) % __le32_to_cpu(SUPERBLOCK->s_inodes_per_group)) + >> log2 (EXT2_BLOCK_SIZE (SUPERBLOCK) / sizeof (struct ext2_inode))); +#ifdef E2DEBUG + printf ("ext2fs_dir: itab_blk=%d, i_in_grp=%d, log2=%d\n", + __le32_to_cpu(gdp[desc].bg_inode_table), + ((current_ino - 1) % __le32_to_cpu(SUPERBLOCK->s_inodes_per_group)), + log2 (EXT2_BLOCK_SIZE (SUPERBLOCK) / sizeof (struct ext2_inode))); + printf ("ext2fs_dir: inode table fsblock=%d\n", ino_blk); +#endif /* E2DEBUG */ + if (!ext2_rdfsb (ino_blk, (char *)INODE)) + { + return 0; + } + + /* reset indirect blocks! */ + mapblock2 = mapblock1 = -1; + + raw_inode = INODE + + ((current_ino - 1) + & (EXT2_BLOCK_SIZE (SUPERBLOCK) / sizeof (struct ext2_inode) - 1)); +#ifdef E2DEBUG + printf ("ext2fs_dir: ipb=%d, sizeof(inode)=%d\n", + (EXT2_BLOCK_SIZE (SUPERBLOCK) / sizeof (struct ext2_inode)), + sizeof (struct ext2_inode)); + printf ("ext2fs_dir: inode=%x, raw_inode=%x\n", INODE, raw_inode); + printf ("ext2fs_dir: offset into inode table block=%d\n", (int) raw_inode - (int) INODE); + dump_inode(raw_inode); + dump_inode_data((unsigned char *)INODE, EXT2_BLOCK_SIZE(SUPERBLOCK)); + printf ("ext2fs_dir: first word=%x\n", *((int *) raw_inode)); +#endif /* E2DEBUG */ + + /* copy inode to fixed location */ + memmove ((void *) INODE, (void *) raw_inode, sizeof (struct ext2_inode)); + +#ifdef E2DEBUG + dump_inode(INODE); + printf ("ext2fs_dir: first word=%x\n", *((int *) INODE)); +#endif /* E2DEBUG */ + + /* If we've got a symbolic link, then chase it. */ + if (S_ISLNK (__le16_to_cpu(INODE->i_mode))) + { + int len; + if (++link_count > MAX_LINK_COUNT) + { + errnum = ERR_SYMLINK_LOOP; + return 0; + } + + /* Find out how long our remaining name is. */ + len = 0; + while (dirname[len] && !isspace (dirname[len])) + len++; + + /* Get the symlink size. */ + filemax = __le32_to_cpu(INODE->i_size); + if (filemax + len > sizeof (linkbuf) - 2) + { + errnum = ERR_FILELENGTH; + return 0; + } + + if (len) + { + /* Copy the remaining name to the end of the symlink data. + Note that DIRNAME and LINKBUF may overlap! */ + memmove (linkbuf + filemax, dirname, len); + } + linkbuf[filemax + len] = '\0'; + + /* Read the symlink data. */ + if (__le32_to_cpu(INODE->i_blocks)) + { + /* Read the necessary blocks, and reset the file pointer. */ + len = file_read (linkbuf, filemax); + filepos = 0; + if (!len) + return 0; + } + else + { + /* Copy the data directly from the inode. */ + len = filemax; + memmove (linkbuf, (char *) INODE->i_block, len); + } + +#ifdef E2DEBUG + printf ("ext2fs_dir: symlink=%s\n", linkbuf); +#endif + + dirname = linkbuf; + if (*dirname == '/') + { + /* It's an absolute link, so look it up in root. */ + current_ino = EXT2_ROOT_INO; + updir_ino = current_ino; + } + else + { + /* Relative, so look it up in our parent directory. */ + current_ino = updir_ino; + } + + /* Try again using the new name. */ + continue; + } + + /* if end of filename, INODE points to the file's inode */ + if (!*dirname || isspace (*dirname)) + { + if (!S_ISREG (__le16_to_cpu(INODE->i_mode))) + { + errnum = ERR_BAD_FILETYPE; + return 0; + } + + filemax = __le32_to_cpu(INODE->i_size); + return 1; + } + + /* else we have to traverse a directory */ + updir_ino = current_ino; + + /* skip over slashes */ + while (*dirname == '/') + dirname++; + + /* if this isn't a directory of sufficient size to hold our file, abort */ + if (!(__le32_to_cpu(INODE->i_size)) || !S_ISDIR (__le16_to_cpu(INODE->i_mode))) + { + errnum = ERR_BAD_FILETYPE; + return 0; + } + + /* skip to next slash or end of filename (space) */ + for (rest = dirname; (ch = *rest) && !isspace (ch) && ch != '/'; + rest++); + + /* look through this directory and find the next filename component */ + /* invariant: rest points to slash after the next filename component */ + *rest = 0; + loc = 0; + + do + { + +#ifdef E2DEBUG + printf ("ext2fs_dir: dirname=%s, rest=%s, loc=%d\n", dirname, rest, loc); +#endif /* E2DEBUG */ + + /* if our location/byte offset into the directory exceeds the size, + give up */ + if (loc >= __le32_to_cpu(INODE->i_size)) + { + if (print_possibilities < 0) + { +# if 0 + putchar ('\n'); +# endif + } + else + { + errnum = ERR_FILE_NOT_FOUND; + *rest = ch; + } + return (print_possibilities < 0); + } + + /* else, find the (logical) block component of our location */ + blk = loc >> EXT2_BLOCK_SIZE_BITS (SUPERBLOCK); + + /* we know which logical block of the directory entry we are looking + for, now we have to translate that to the physical (fs) block on + the disk */ + map = ext2fs_block_map (blk); +#ifdef E2DEBUG + printf ("ext2fs_dir: fs block=%d\n", map); +#endif /* E2DEBUG */ + mapblock2 = -1; + if ((map < 0) || !ext2_rdfsb (map, DATABLOCK2)) + { + errnum = ERR_FSYS_CORRUPT; + *rest = ch; + return 0; + } + off = loc & (EXT2_BLOCK_SIZE (SUPERBLOCK) - 1); + dp = (struct ext2_dir_entry *) (DATABLOCK2 + off); + /* advance loc prematurely to next on-disk directory entry */ + loc += __le16_to_cpu(dp->rec_len); + + /* NOTE: ext2fs filenames are NOT null-terminated */ + +#ifdef E2DEBUG + printf ("ext2fs_dir: directory entry ino=%d\n", __le32_to_cpu(dp->inode)); + if (__le32_to_cpu(dp->inode)) + printf ("entry=%s\n", dp->name); +#endif /* E2DEBUG */ + + if (__le32_to_cpu(dp->inode)) + { + int saved_c = dp->name[dp->name_len]; + + dp->name[dp->name_len] = 0; + str_chk = substring (dirname, dp->name); + +# ifndef STAGE1_5 + if (print_possibilities && ch != '/' + && (!*dirname || str_chk <= 0)) + { + if (print_possibilities > 0) + print_possibilities = -print_possibilities; + print_a_completion (dp->name); + } +# endif + + dp->name[dp->name_len] = saved_c; + } + + } + while (!__le32_to_cpu(dp->inode) || (str_chk || (print_possibilities && ch != '/'))); + + current_ino = __le32_to_cpu(dp->inode); + *(dirname = rest) = ch; + } + /* never get here */ +} + +#endif /* FSYS_EXT2_FS */ diff --git a/qemu/roms/openbios/fs/grubfs/fsys_fat.c b/qemu/roms/openbios/fs/grubfs/fsys_fat.c new file mode 100644 index 000000000..a7e160d1d --- /dev/null +++ b/qemu/roms/openbios/fs/grubfs/fsys_fat.c @@ -0,0 +1,477 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2000, 2001 Free Software Foundation, Inc. + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#ifdef FSYS_FAT + +#include "shared.h" +#include "filesys.h" +#include "fat.h" + +struct fat_superblock +{ + int fat_offset; + int fat_length; + int fat_size; + int root_offset; + int root_max; + int data_offset; + + int num_sectors; + int num_clust; + int clust_eof_marker; + int sects_per_clust; + int sectsize_bits; + int clustsize_bits; + int root_cluster; + + int cached_fat; + int file_cluster; + int current_cluster_num; + int current_cluster; +}; + +/* pointer(s) into filesystem info buffer for DOS stuff */ +#define FAT_SUPER ( (struct fat_superblock *) \ + ( FSYS_BUF + 32256) )/* 512 bytes long */ +#define FAT_BUF ( FSYS_BUF + 30208 ) /* 4 sector FAT buffer */ +#define NAME_BUF ( FSYS_BUF + 29184 ) /* Filename buffer (833 bytes) */ + +#define FAT_CACHE_SIZE 2048 + +int +fat_mount (void) +{ + struct fat_bpb bpb; + __u32 magic, first_fat; + + /* Check partition type for harddisk */ + if (((current_drive & 0x80) || (current_slice != 0)) + && ! IS_PC_SLICE_TYPE_FAT (current_slice) + && (! IS_PC_SLICE_TYPE_BSD_WITH_FS (current_slice, FS_MSDOS))) + return 0; + + /* Read bpb */ + if (! devread (0, 0, sizeof (bpb), (char *) &bpb)) + return 0; + + /* Check if the number of sectors per cluster is zero here, to avoid + zero division. */ + if (bpb.sects_per_clust == 0) + return 0; + + FAT_SUPER->sectsize_bits = log2 (bpb.bytes_per_sect); + FAT_SUPER->clustsize_bits + = FAT_SUPER->sectsize_bits + log2 (bpb.sects_per_clust); + + /* Fill in info about super block */ + FAT_SUPER->num_sectors = bpb.short_sectors + ? bpb.short_sectors : bpb.long_sectors; + + /* FAT offset and length */ + FAT_SUPER->fat_offset = bpb.reserved_sects; + FAT_SUPER->fat_length = + bpb.fat_length ? bpb.fat_length : bpb.fat32_length; + + /* Rootdir offset and length for FAT12/16 */ + FAT_SUPER->root_offset = + FAT_SUPER->fat_offset + bpb.num_fats * FAT_SUPER->fat_length; + FAT_SUPER->root_max = FAT_DIRENTRY_LENGTH * bpb.dir_entries; + + /* Data offset and number of clusters */ + FAT_SUPER->data_offset = + FAT_SUPER->root_offset + + ((FAT_SUPER->root_max - 1) >> FAT_SUPER->sectsize_bits) + 1; + FAT_SUPER->num_clust = + 2 + ((FAT_SUPER->num_sectors - FAT_SUPER->data_offset) + / bpb.sects_per_clust); + FAT_SUPER->sects_per_clust = bpb.sects_per_clust; + + if (!bpb.fat_length) + { + /* This is a FAT32 */ + if (bpb.dir_entries) + return 0; + + if (bpb.flags & 0x0080) + { + /* FAT mirroring is disabled, get active FAT */ + int active_fat = bpb.flags & 0x000f; + if (active_fat >= bpb.num_fats) + return 0; + FAT_SUPER->fat_offset += active_fat * FAT_SUPER->fat_length; + } + + FAT_SUPER->fat_size = 8; + FAT_SUPER->root_cluster = bpb.root_cluster; + + /* Yes the following is correct. FAT32 should be called FAT28 :) */ + FAT_SUPER->clust_eof_marker = 0xffffff8; + } + else + { + if (!FAT_SUPER->root_max) + return 0; + + FAT_SUPER->root_cluster = -1; + if (FAT_SUPER->num_clust > FAT_MAX_12BIT_CLUST) + { + FAT_SUPER->fat_size = 4; + FAT_SUPER->clust_eof_marker = 0xfff8; + } + else + { + FAT_SUPER->fat_size = 3; + FAT_SUPER->clust_eof_marker = 0xff8; + } + } + + + /* Now do some sanity checks */ + + if (bpb.bytes_per_sect != (1 << FAT_SUPER->sectsize_bits) + || bpb.bytes_per_sect != SECTOR_SIZE + || bpb.sects_per_clust != (1 << (FAT_SUPER->clustsize_bits + - FAT_SUPER->sectsize_bits)) + || FAT_SUPER->num_clust <= 2 + || (FAT_SUPER->fat_size * FAT_SUPER->num_clust / (2 * SECTOR_SIZE) + > FAT_SUPER->fat_length)) + return 0; + + /* kbs: Media check on first FAT entry [ported from PUPA] */ + + if (!devread(FAT_SUPER->fat_offset, 0, + sizeof(first_fat), (char *)&first_fat)) + return 0; + + if (FAT_SUPER->fat_size == 8) + { + first_fat &= 0x0fffffff; + magic = 0x0fffff00; + } + else if (FAT_SUPER->fat_size == 4) + { + first_fat &= 0x0000ffff; + magic = 0xff00; + } + else + { + first_fat &= 0x00000fff; + magic = 0x0f00; + } + + if (first_fat != (magic | bpb.media)) + return 0; + + FAT_SUPER->cached_fat = - 2 * FAT_CACHE_SIZE; + return 1; +} + +int +fat_read (char *buf, int len) +{ + int logical_clust; + int offset; + int ret = 0; + int size; + + if (FAT_SUPER->file_cluster < 0) + { + /* root directory for fat16 */ + size = FAT_SUPER->root_max - filepos; + if (size > len) + size = len; + if (!devread(FAT_SUPER->root_offset, filepos, size, buf)) + return 0; + filepos += size; + return size; + } + + logical_clust = filepos >> FAT_SUPER->clustsize_bits; + offset = (filepos & ((1 << FAT_SUPER->clustsize_bits) - 1)); + if (logical_clust < FAT_SUPER->current_cluster_num) + { + FAT_SUPER->current_cluster_num = 0; + FAT_SUPER->current_cluster = FAT_SUPER->file_cluster; + } + + while (len > 0) + { + int sector; + while (logical_clust > FAT_SUPER->current_cluster_num) + { + /* calculate next cluster */ + int fat_entry = + FAT_SUPER->current_cluster * FAT_SUPER->fat_size; + int next_cluster; + int cached_pos = (fat_entry - FAT_SUPER->cached_fat); + + if (cached_pos < 0 || + (cached_pos + FAT_SUPER->fat_size) > 2*FAT_CACHE_SIZE) + { + FAT_SUPER->cached_fat = (fat_entry & ~(2*SECTOR_SIZE - 1)); + cached_pos = (fat_entry - FAT_SUPER->cached_fat); + sector = FAT_SUPER->fat_offset + + FAT_SUPER->cached_fat / (2*SECTOR_SIZE); + if (!devread (sector, 0, FAT_CACHE_SIZE, (char*) FAT_BUF)) + return 0; + } + next_cluster = * (unsigned long *) (FAT_BUF + (cached_pos >> 1)); + if (FAT_SUPER->fat_size == 3) + { + if (cached_pos & 1) + next_cluster >>= 4; + next_cluster &= 0xFFF; + } + else if (FAT_SUPER->fat_size == 4) + next_cluster &= 0xFFFF; + + if (next_cluster >= FAT_SUPER->clust_eof_marker) + return ret; + if (next_cluster < 2 || next_cluster >= FAT_SUPER->num_clust) + { + errnum = ERR_FSYS_CORRUPT; + return 0; + } + + FAT_SUPER->current_cluster = next_cluster; + FAT_SUPER->current_cluster_num++; + } + + sector = FAT_SUPER->data_offset + + ((FAT_SUPER->current_cluster - 2) << (FAT_SUPER->clustsize_bits + - FAT_SUPER->sectsize_bits)); + size = (1 << FAT_SUPER->clustsize_bits) - offset; + if (size > len) + size = len; + + disk_read_func = disk_read_hook; + + devread(sector, offset, size, buf); + + disk_read_func = NULL; + + len -= size; + buf += size; + ret += size; + filepos += size; + logical_clust++; + offset = 0; + } + return errnum ? 0 : ret; +} + +int +fat_dir (char *dirname) +{ + char *rest, ch, dir_buf[FAT_DIRENTRY_LENGTH]; + char *filename = (char *) NAME_BUF; + int attrib = FAT_ATTRIB_DIR; +#ifndef STAGE1_5 + int do_possibilities = 0; +#endif + + /* XXX I18N: + * the positions 2,4,6 etc are high bytes of a 16 bit unicode char + */ + static unsigned char longdir_pos[] = + { 1, 3, 5, 7, 9, 14, 16, 18, 20, 22, 24, 28, 30 }; + int slot = -2; + int alias_checksum = -1; + + FAT_SUPER->file_cluster = FAT_SUPER->root_cluster; + filepos = 0; + FAT_SUPER->current_cluster_num = MAXINT; + + /* main loop to find desired directory entry */ + loop: + + /* if we have a real file (and we're not just printing possibilities), + then this is where we want to exit */ + + if (!*dirname || isspace (*dirname)) + { + if (attrib & FAT_ATTRIB_DIR) + { + errnum = ERR_BAD_FILETYPE; + return 0; + } + + return 1; + } + + /* continue with the file/directory name interpretation */ + + while (*dirname == '/') + dirname++; + + if (!(attrib & FAT_ATTRIB_DIR)) + { + errnum = ERR_BAD_FILETYPE; + return 0; + } + /* Directories don't have a file size */ + filemax = MAXINT; + + for (rest = dirname; (ch = *rest) && !isspace (ch) && ch != '/'; rest++); + + *rest = 0; + +# ifndef STAGE1_5 + if (print_possibilities && ch != '/') + do_possibilities = 1; +# endif + + while (1) + { + if (fat_read (dir_buf, FAT_DIRENTRY_LENGTH) != FAT_DIRENTRY_LENGTH + || dir_buf[0] == 0) + { + if (!errnum) + { +# ifndef STAGE1_5 + if (print_possibilities < 0) + { +#if 0 + putchar ('\n'); +#endif + return 1; + } +# endif /* STAGE1_5 */ + + errnum = ERR_FILE_NOT_FOUND; + *rest = ch; + } + + return 0; + } + + if (FAT_DIRENTRY_ATTRIB (dir_buf) == FAT_ATTRIB_LONGNAME) + { + /* This is a long filename. The filename is build from back + * to front and may span multiple entries. To bind these + * entries together they all contain the same checksum over + * the short alias. + * + * The id field tells if this is the first entry (the last + * part) of the long filename, and also at which offset this + * belongs. + * + * We just write the part of the long filename this entry + * describes and continue with the next dir entry. + */ + int i, offset; + unsigned char id = FAT_LONGDIR_ID(dir_buf); + + if ((id & 0x40)) + { + id &= 0x3f; + slot = id; + filename[slot * 13] = 0; + alias_checksum = FAT_LONGDIR_ALIASCHECKSUM(dir_buf); + } + + if (id != slot || slot == 0 + || alias_checksum != FAT_LONGDIR_ALIASCHECKSUM(dir_buf)) + { + alias_checksum = -1; + continue; + } + + slot--; + offset = slot * 13; + + for (i=0; i < 13; i++) + filename[offset+i] = dir_buf[longdir_pos[i]]; + continue; + } + + if (!FAT_DIRENTRY_VALID (dir_buf)) + continue; + + if (alias_checksum != -1 && slot == 0) + { + int i; + unsigned char sum; + + slot = -2; + for (sum = 0, i = 0; i< 11; i++) + sum = ((sum >> 1) | (sum << 7)) + dir_buf[i]; + + if (sum == alias_checksum) + { +# ifndef STAGE1_5 + if (do_possibilities) + goto print_filename; +# endif /* STAGE1_5 */ + + if (substring (dirname, filename) == 0) + break; + } + } + + /* XXX convert to 8.3 filename format here */ + { + int i, j, c; + + for (i = 0; i < 8 && (c = filename[i] = tolower (dir_buf[i])) + && !isspace (c); i++); + + filename[i++] = '.'; + + for (j = 0; j < 3 && (c = filename[i + j] = tolower (dir_buf[8 + j])) + && !isspace (c); j++); + + if (j == 0) + i--; + + filename[i + j] = 0; + } + +# ifndef STAGE1_5 + if (do_possibilities) + { + print_filename: + if (substring (dirname, filename) <= 0) + { + if (print_possibilities > 0) + print_possibilities = -print_possibilities; + print_a_completion (filename); + } + continue; + } +# endif /* STAGE1_5 */ + + if (substring (dirname, filename) == 0) + break; + } + + *(dirname = rest) = ch; + + attrib = FAT_DIRENTRY_ATTRIB (dir_buf); + filemax = FAT_DIRENTRY_FILELENGTH (dir_buf); + filepos = 0; + FAT_SUPER->file_cluster = FAT_DIRENTRY_FIRST_CLUSTER (dir_buf); + FAT_SUPER->current_cluster_num = MAXINT; + + /* go back to main loop at top of function */ + goto loop; +} + +#endif /* FSYS_FAT */ diff --git a/qemu/roms/openbios/fs/grubfs/fsys_ffs.c b/qemu/roms/openbios/fs/grubfs/fsys_ffs.c new file mode 100644 index 000000000..c6804b8ba --- /dev/null +++ b/qemu/roms/openbios/fs/grubfs/fsys_ffs.c @@ -0,0 +1,311 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2000, 2001 Free Software Foundation, Inc. + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +/* + * Elements of this file were originally from the FreeBSD "biosboot" + * bootloader file "disk.c" dated 4/12/95. + * + * The license and header comments from that file are included here. + */ + +/* + * Mach Operating System + * Copyright (c) 1992, 1991 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + * + * from: Mach, Revision 2.2 92/04/04 11:35:49 rpd + * $Id: fsys_ffs.c,v 1.10 2001/11/12 06:57:29 okuji Exp $ + */ + +#ifdef FSYS_FFS + +#include "shared.h" + +#include "filesys.h" + +#include "defs.h" +#include "disk_inode.h" +#include "disk_inode_ffs.h" +#include "dir.h" +#include "fs.h" + +/* used for filesystem map blocks */ +static int mapblock; +static int mapblock_offset; +static int mapblock_bsize; + +/* pointer to superblock */ +#define SUPERBLOCK ((struct fs *) ( FSYS_BUF + 8192 )) +#define INODE ((struct icommon *) ( FSYS_BUF + 16384 )) +#define MAPBUF ( FSYS_BUF + 24576 ) +#define MAPBUF_LEN 8192 + + +int +ffs_mount (void) +{ + int retval = 1; + + if ((((current_drive & 0x80) || (current_slice != 0)) + && ! IS_PC_SLICE_TYPE_BSD_WITH_FS (current_slice, FS_BSDFFS)) + || part_length < (SBLOCK + (SBSIZE / DEV_BSIZE)) + || !devread (SBLOCK, 0, SBSIZE, (char *) SUPERBLOCK) + || SUPERBLOCK->fs_magic != FS_MAGIC) + retval = 0; + + mapblock = -1; + mapblock_offset = -1; + + return retval; +} + +static int +block_map (int file_block) +{ + int bnum, offset, bsize; + + if (file_block < NDADDR) + return (INODE->i_db[file_block]); + + /* If the blockmap loaded does not include FILE_BLOCK, + load a new blockmap. */ + if ((bnum = fsbtodb (SUPERBLOCK, INODE->i_ib[0])) != mapblock + || (mapblock_offset <= bnum && bnum <= mapblock_offset + mapblock_bsize)) + { + if (MAPBUF_LEN < SUPERBLOCK->fs_bsize) + { + offset = ((file_block - NDADDR) % NINDIR (SUPERBLOCK)); + bsize = MAPBUF_LEN; + + if (offset + MAPBUF_LEN > SUPERBLOCK->fs_bsize) + offset = (SUPERBLOCK->fs_bsize - MAPBUF_LEN) / sizeof (int); + } + else + { + bsize = SUPERBLOCK->fs_bsize; + offset = 0; + } + + if (! devread (bnum, offset * sizeof (int), bsize, (char *) MAPBUF)) + { + mapblock = -1; + mapblock_bsize = -1; + mapblock_offset = -1; + errnum = ERR_FSYS_CORRUPT; + return -1; + } + + mapblock = bnum; + mapblock_bsize = bsize; + mapblock_offset = offset; + } + + return (((int *) MAPBUF)[((file_block - NDADDR) % NINDIR (SUPERBLOCK)) + - mapblock_offset]); +} + + +int +ffs_read (char *buf, int len) +{ + int logno, off, size, map, ret = 0; + + while (len && !errnum) + { + off = blkoff (SUPERBLOCK, filepos); + logno = lblkno (SUPERBLOCK, filepos); + size = blksize (SUPERBLOCK, INODE, logno); + + if ((map = block_map (logno)) < 0) + break; + + size -= off; + + if (size > len) + size = len; + + disk_read_func = disk_read_hook; + + devread (fsbtodb (SUPERBLOCK, map), off, size, buf); + + disk_read_func = NULL; + + buf += size; + len -= size; + filepos += size; + ret += size; + } + + if (errnum) + ret = 0; + + return ret; +} + + +int +ffs_dir (char *dirname) +{ + char *rest, ch; + int block, off, loc, map, ino = ROOTINO; + struct direct *dp; + +/* main loop to find destination inode */ +loop: + + /* load current inode (defaults to the root inode) */ + + if (!devread (fsbtodb (SUPERBLOCK, itod (SUPERBLOCK, ino)), + ino % (SUPERBLOCK->fs_inopb) * sizeof (struct dinode), + sizeof (struct dinode), (char *) INODE)) + return 0; /* XXX what return value? */ + + /* if we have a real file (and we're not just printing possibilities), + then this is where we want to exit */ + + if (!*dirname || isspace (*dirname)) + { + if ((INODE->i_mode & IFMT) != IFREG) + { + errnum = ERR_BAD_FILETYPE; + return 0; + } + + filemax = INODE->i_size; + + /* incomplete implementation requires this! */ + fsmax = (NDADDR + NINDIR (SUPERBLOCK)) * SUPERBLOCK->fs_bsize; + return 1; + } + + /* continue with file/directory name interpretation */ + + while (*dirname == '/') + dirname++; + + if (!(INODE->i_size) || ((INODE->i_mode & IFMT) != IFDIR)) + { + errnum = ERR_BAD_FILETYPE; + return 0; + } + + for (rest = dirname; (ch = *rest) && !isspace (ch) && ch != '/'; rest++); + + *rest = 0; + loc = 0; + + /* loop for reading a the entries in a directory */ + + do + { + if (loc >= INODE->i_size) + { +#if 0 + putchar ('\n'); +#endif + + if (print_possibilities < 0) + return 1; + + errnum = ERR_FILE_NOT_FOUND; + *rest = ch; + return 0; + } + + if (!(off = blkoff (SUPERBLOCK, loc))) + { + block = lblkno (SUPERBLOCK, loc); + + if ((map = block_map (block)) < 0 + || !devread (fsbtodb (SUPERBLOCK, map), 0, + blksize (SUPERBLOCK, INODE, block), + (char *) FSYS_BUF)) + { + errnum = ERR_FSYS_CORRUPT; + *rest = ch; + return 0; + } + } + + dp = (struct direct *) (FSYS_BUF + off); + loc += dp->d_reclen; + +#ifndef STAGE1_5 + if (dp->d_ino && print_possibilities && ch != '/' + && (!*dirname || substring (dirname, dp->d_name) <= 0)) + { + if (print_possibilities > 0) + print_possibilities = -print_possibilities; + + print_a_completion (dp->d_name); + } +#endif /* STAGE1_5 */ + } + while (!dp->d_ino || (substring (dirname, dp->d_name) != 0 + || (print_possibilities && ch != '/'))); + + /* only get here if we have a matching directory entry */ + + ino = dp->d_ino; + *(dirname = rest) = ch; + + /* go back to main loop at top of function */ + goto loop; +} + +int +ffs_embed (int *start_sector, int needed_sectors) +{ + /* XXX: I don't know if this is really correct. Someone who is + familiar with BSD should check for this. */ + if (needed_sectors > 14) + return 0; + + *start_sector = 1; +#if 1 + /* FIXME: Disable the embedding in FFS until someone checks if + the code above is correct. */ + return 0; +#else + return 1; +#endif +} + +#endif /* FSYS_FFS */ diff --git a/qemu/roms/openbios/fs/grubfs/fsys_iso9660.c b/qemu/roms/openbios/fs/grubfs/fsys_iso9660.c new file mode 100644 index 000000000..12f94b734 --- /dev/null +++ b/qemu/roms/openbios/fs/grubfs/fsys_iso9660.c @@ -0,0 +1,342 @@ +/* + * ISO 9660 filesystem backend for GRUB (GRand Unified Bootloader) + * including Rock Ridge Extensions support + * + * Copyright (C) 1998, 1999 Kousuke Takai <tak@kmc.kyoto-u.ac.jp> + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +/* + * References: + * linux/fs/isofs/rock.[ch] + * mkisofs-1.11.1/diag/isoinfo.c + * mkisofs-1.11.1/iso9660.h + * (all are written by Eric Youngdale) + * + * Modifications by: + * Leonid Lisovskiy <lly@pisem.net> 2003 + */ + +/* + * Modified to make it work with FILO + * 2003-10 by SONE Takeshi + */ + +#ifdef FSYS_ISO9660 + +#include "shared.h" +#include "filesys.h" +#include "iso9660.h" +#include "debug.h" + +#if defined(__sparc__) || defined(__PPC__) +#define ENDIAN b +#else +#define ENDIAN l +#endif + +struct iso_superblock { + unsigned long vol_sector; + + unsigned long file_start; +}; + +#define ISO_SUPER ((struct iso_superblock *)(FSYS_BUF)) +#define PRIMDESC ((struct iso_primary_descriptor *)(FSYS_BUF + 2048)) +#define DIRREC ((struct iso_directory_record *)(FSYS_BUF + 4096)) +#define RRCONT_BUF ((unsigned char *)(FSYS_BUF + 6144)) +#define NAME_BUF ((unsigned char *)(FSYS_BUF + 8192)) + +static int +iso9660_devread (int sector, int byte_offset, int byte_len, char *buf) +{ + /* FILO uses 512-byte "soft" sector, and ISO-9660 uses 2048-byte + * CD-ROM sector */ + return devread(sector<<2, byte_offset, byte_len, buf); +} + +int +iso9660_mount (void) +{ + unsigned int sector; + + /* + * Because there is no defined slice type ID for ISO-9660 filesystem, + * this test will pass only either (1) if entire disk is used, or + * (2) if current partition is BSD style sub-partition whose ID is + * ISO-9660. + */ + /*if ((current_partition != 0xFFFFFF) + && !IS_PC_SLICE_TYPE_BSD_WITH_FS(current_slice, FS_ISO9660)) + return 0;*/ + + /* + * Currently, only FIRST session of MultiSession disks are supported !!! + */ + for (sector = 16 ; sector < 32 ; sector++) + { + if (!iso9660_devread(sector, 0, sizeof(*PRIMDESC), (char *)PRIMDESC)) + break; + /* check ISO_VD_PRIMARY and ISO_STANDARD_ID */ + if (CHECK4(&PRIMDESC->type, ISO_VD_PRIMARY, 'C', 'D', '0') + && CHECK2(PRIMDESC->id + 3, '0', '1')) + { + ISO_SUPER->vol_sector = sector; + ISO_SUPER->file_start = 0; + fsmax = PRIMDESC->volume_space_size.ENDIAN; + return 1; + } + } + + return 0; +} + +int +iso9660_dir (char *dirname) +{ + struct iso_directory_record *idr; + RR_ptr_t rr_ptr; + struct rock_ridge *ce_ptr; + unsigned int pathlen; + int size; + unsigned int extent; + unsigned int rr_len; + unsigned char file_type; + unsigned char rr_flag; + + idr = &PRIMDESC->root_directory_record; + ISO_SUPER->file_start = 0; + + do + { + while (*dirname == '/') /* skip leading slashes */ + dirname++; + /* pathlen = strcspn(dirname, "/\n\t "); */ + for (pathlen = 0 ; + dirname[pathlen] + && !isspace(dirname[pathlen]) && dirname[pathlen] != '/' ; + pathlen++) + ; + + size = idr->size.ENDIAN; + extent = idr->extent.ENDIAN; + + while (size > 0) + { + if (!iso9660_devread(extent, 0, ISO_SECTOR_SIZE, (char *)DIRREC)) + { + errnum = ERR_FSYS_CORRUPT; + return 0; + } + extent++; + + idr = (struct iso_directory_record *)DIRREC; + for (; idr->length.ENDIAN > 0; + idr = (struct iso_directory_record *)((char *)idr + idr->length.ENDIAN) ) + { + const char *name = (char *)idr->name; + unsigned int name_len = idr->name_len.ENDIAN; + + file_type = (idr->flags.ENDIAN & 2) ? ISO_DIRECTORY : ISO_REGULAR; + if (name_len == 1) + { + if ((name[0] == 0) || /* self */ + (name[0] == 1)) /* parent */ + continue; + } + if (name_len > 2 && CHECK2(name + name_len - 2, ';', '1')) + { + name_len -= 2; /* truncate trailing file version */ + if (name_len > 1 && name[name_len - 1] == '.') + name_len--; /* truncate trailing dot */ + } + + /* + * Parse Rock-Ridge extension + */ + rr_len = (idr->length.ENDIAN - idr->name_len.ENDIAN + - (unsigned char)sizeof(struct iso_directory_record) + + (unsigned char)sizeof(idr->name)); + rr_ptr.ptr = ((char *)idr + idr->name_len.ENDIAN + + sizeof(struct iso_directory_record) + - sizeof(idr->name)); + if (rr_len & 1) + rr_ptr.ptr++, rr_len--; + ce_ptr = NULL; + rr_flag = RR_FLAG_NM | RR_FLAG_PX; + + while (rr_len >= 4) + { + if (rr_ptr.rr->version != 1) + { +#ifndef STAGE1_5 + if (debug) + printf( + "Non-supported version (%d) RockRidge chunk " + "`%c%c'\n", rr_ptr.rr->version, + rr_ptr.rr->signature & 0xFF, + rr_ptr.rr->signature >> 8); +#endif + } + else if (CHECK2(&rr_ptr.rr->signature, 'R', 'R') + && rr_ptr.rr->len >= 5) + rr_flag &= rr_ptr.rr->u.rr.flags.ENDIAN; + else if (CHECK2(&rr_ptr.rr->signature, 'N', 'M')) + { + name = (char *)rr_ptr.rr->u.nm.name; + name_len = rr_ptr.rr->len - 5; + rr_flag &= ~RR_FLAG_NM; + } + else if (CHECK2(&rr_ptr.rr->signature, 'P', 'X') + && rr_ptr.rr->len >= 36) + { + file_type = ((rr_ptr.rr->u.px.mode.ENDIAN & POSIX_S_IFMT) + == POSIX_S_IFREG + ? ISO_REGULAR + : ((rr_ptr.rr->u.px.mode.ENDIAN & POSIX_S_IFMT) + == POSIX_S_IFDIR + ? ISO_DIRECTORY : ISO_OTHER)); + rr_flag &= ~RR_FLAG_PX; + } + else if (CHECK2(&rr_ptr.rr->signature, 'C', 'E') + && rr_ptr.rr->len >= 28) + ce_ptr = rr_ptr.rr; + if (!rr_flag) + /* + * There is no more extension we expects... + */ + break; + rr_len -= rr_ptr.rr->len; + rr_ptr.ptr += rr_ptr.rr->len; + if (rr_len < 4 && ce_ptr != NULL) + { + /* preserve name before loading new extent. */ + if( RRCONT_BUF <= (unsigned char *)name + && (unsigned char *)name < RRCONT_BUF + ISO_SECTOR_SIZE ) + { + memcpy(NAME_BUF, name, name_len); + name = (char *)NAME_BUF; + } + rr_ptr.ptr = (char *)(RRCONT_BUF + ce_ptr->u.ce.offset.ENDIAN); + rr_len = ce_ptr->u.ce.size.ENDIAN; + if (!iso9660_devread(ce_ptr->u.ce.extent.ENDIAN, 0, + ISO_SECTOR_SIZE, (char *)RRCONT_BUF)) + { + errnum = 0; /* this is not fatal. */ + break; + } + ce_ptr = NULL; + } + } /* rr_len >= 4 */ + + filemax = MAXINT; + if (name_len >= pathlen + && !strnicmp(name, dirname, pathlen)) + { + if (dirname[pathlen] == '/' || !print_possibilities) + { + /* + * DIRNAME is directory component of pathname, + * or we are to open a file. + */ + if (pathlen == name_len) + { + if (dirname[pathlen] == '/') + { + if (file_type != ISO_DIRECTORY) + { + errnum = ERR_BAD_FILETYPE; + return 0; + } + goto next_dir_level; + } + if (file_type != ISO_REGULAR) + { + errnum = ERR_BAD_FILETYPE; + return 0; + } + ISO_SUPER->file_start = idr->extent.ENDIAN; + filepos = 0; + filemax = idr->size.ENDIAN; + return 1; + } + } + else /* Completion */ + { +#ifndef STAGE1_5 + if (print_possibilities > 0) + print_possibilities = -print_possibilities; + memcpy(NAME_BUF, name, name_len); + NAME_BUF[name_len] = '\0'; + print_a_completion (NAME_BUF); +#endif + } + } + } /* for */ + + size -= ISO_SECTOR_SIZE; + } /* size>0 */ + + if (dirname[pathlen] == '/' || print_possibilities >= 0) + { + errnum = ERR_FILE_NOT_FOUND; + return 0; + } + +next_dir_level: + dirname += pathlen; + + } while (*dirname == '/'); + + return 1; +} + +int +iso9660_read (char *buf, int len) +{ + int sector, blkoffset, size, ret; + + if (ISO_SUPER->file_start == 0) + return 0; + + ret = 0; + blkoffset = filepos & (ISO_SECTOR_SIZE - 1); + sector = filepos >> ISO_SECTOR_BITS; + while (len > 0) + { + size = ISO_SECTOR_SIZE - blkoffset; + if (size > len) + size = len; + + disk_read_func = disk_read_hook; + + if (!iso9660_devread(ISO_SUPER->file_start + sector, blkoffset, size, buf)) + return 0; + + disk_read_func = NULL; + + len -= size; + buf += size; + ret += size; + filepos += size; + sector++; + blkoffset = 0; + } + + return ret; +} + +#endif /* FSYS_ISO9660 */ diff --git a/qemu/roms/openbios/fs/grubfs/fsys_jfs.c b/qemu/roms/openbios/fs/grubfs/fsys_jfs.c new file mode 100644 index 000000000..66469e686 --- /dev/null +++ b/qemu/roms/openbios/fs/grubfs/fsys_jfs.c @@ -0,0 +1,404 @@ +/* fsys_jfs.c - an implementation for the IBM JFS file system */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2001,2002 Free Software Foundation, Inc. + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#ifdef FSYS_JFS + +#include "shared.h" +#include "filesys.h" +#include "jfs.h" + +#define MAX_LINK_COUNT 8 + +#define DTTYPE_INLINE 0 +#define DTTYPE_PAGE 1 + +struct jfs_info +{ + int bsize; + int l2bsize; + int bdlog; + int xindex; + int xlastindex; + int sindex; + int slastindex; + int de_index; + int dttype; + xad_t *xad; + ldtentry_t *de; +}; + +static struct jfs_info jfs; + +#define xtpage ((xtpage_t *)FSYS_BUF) +#define dtpage ((dtpage_t *)((char *)FSYS_BUF + 4096)) +#define fileset ((dinode_t *)((char *)FSYS_BUF + 8192)) +#define inode ((dinode_t *)((char *)FSYS_BUF + 8192 + sizeof(dinode_t))) +#define dtroot ((dtroot_t *)(&inode->di_btroot)) + +static ldtentry_t de_always[2] = { + {1, -1, 2, {'.', '.'}, 0}, + {1, -1, 1, {'.'}, 0} +}; + +static int +isinxt (s64 key, s64 offset, s64 len) +{ + return (key >= offset) ? (key < offset + len ? 1 : 0) : 0; +} + +static xad_t * +first_extent (dinode_t *di) +{ + xtpage_t *xtp; + + jfs.xindex = 2; + xtp = (xtpage_t *)&di->di_btroot; + jfs.xad = &xtp->xad[2]; + if (xtp->header.flag & BT_LEAF) { + jfs.xlastindex = xtp->header.nextindex; + } else { + do { + devread (addressXAD (jfs.xad) << jfs.bdlog, 0, + sizeof(xtpage_t), (char *)xtpage); + jfs.xad = &xtpage->xad[2]; + } while (!(xtpage->header.flag & BT_LEAF)); + jfs.xlastindex = xtpage->header.nextindex; + } + + return jfs.xad; +} + +static xad_t * +next_extent (void) +{ + if (++jfs.xindex < jfs.xlastindex) { + } else if (xtpage->header.next) { + devread (xtpage->header.next << jfs.bdlog, 0, + sizeof(xtpage_t), (char *)xtpage); + jfs.xlastindex = xtpage->header.nextindex; + jfs.xindex = XTENTRYSTART; + jfs.xad = &xtpage->xad[XTENTRYSTART]; + } else { + return NULL; + } + return ++jfs.xad; +} + + +static void +di_read (u32 inum, dinode_t *di) +{ + s64 key; + u32 xd, ioffset; + s64 offset; + xad_t *xad; + pxd_t pxd; + + key = (((inum >> L2INOSPERIAG) << L2INOSPERIAG) + 4096) >> jfs.l2bsize; + xd = (inum & (INOSPERIAG - 1)) >> L2INOSPEREXT; + ioffset = ((inum & (INOSPERIAG - 1)) & (INOSPEREXT - 1)) << L2DISIZE; + xad = first_extent (fileset); + do { + offset = offsetXAD (xad); + if (isinxt (key, offset, lengthXAD (xad))) { + devread ((addressXAD (xad) + key - offset) << jfs.bdlog, + 3072 + xd*sizeof(pxd_t), sizeof(pxd_t), (char *)&pxd); + devread (addressPXD (&pxd) << jfs.bdlog, + ioffset, DISIZE, (char *)di); + break; + } + } while ((xad = next_extent ())); +} + +static ldtentry_t * +next_dentry (void) +{ + ldtentry_t *de; + s8 *stbl; + + if (jfs.dttype == DTTYPE_INLINE) { + if (jfs.sindex < jfs.slastindex) { + return (ldtentry_t *)&dtroot->slot[(int)dtroot->header.stbl[jfs.sindex++]]; + } + } else { + de = (ldtentry_t *)dtpage->slot; + stbl = (s8 *)&de[(int)dtpage->header.stblindex]; + if (jfs.sindex < jfs.slastindex) { + return &de[(int)stbl[jfs.sindex++]]; + } else if (dtpage->header.next) { + devread (dtpage->header.next << jfs.bdlog, 0, + sizeof(dtpage_t), (char *)dtpage); + jfs.slastindex = dtpage->header.nextindex; + jfs.sindex = 1; + return &de[(int)((s8 *)&de[(int)dtpage->header.stblindex])[0]]; + } + } + + return (jfs.de_index < 2) ? &de_always[jfs.de_index++] : NULL; +} + +static ldtentry_t * +first_dentry (void) +{ + dtroot_t *dtr; + pxd_t *xd; + idtentry_t *de; + + dtr = (dtroot_t *)&inode->di_btroot; + jfs.sindex = 0; + jfs.de_index = 0; + + de_always[0].inumber = inode->di_parent; + de_always[1].inumber = inode->di_number; + if (dtr->header.flag & BT_LEAF) { + jfs.dttype = DTTYPE_INLINE; + jfs.slastindex = dtr->header.nextindex; + } else { + de = (idtentry_t *)dtpage->slot; + jfs.dttype = DTTYPE_PAGE; + xd = &((idtentry_t *)dtr->slot)[(int)dtr->header.stbl[0]].xd; + for (;;) { + devread (addressPXD (xd) << jfs.bdlog, 0, + sizeof(dtpage_t), (char *)dtpage); + if (dtpage->header.flag & BT_LEAF) + break; + xd = &de[(int)((s8 *)&de[(int)dtpage->header.stblindex])[0]].xd; + } + jfs.slastindex = dtpage->header.nextindex; + } + + return next_dentry (); +} + + +static dtslot_t * +next_dslot (int next) +{ + return (jfs.dttype == DTTYPE_INLINE) + ? (dtslot_t *)&dtroot->slot[next] + : &((dtslot_t *)dtpage->slot)[next]; +} + +static void +uni2ansi (UniChar *uni, char *ansi, int len) +{ + for (; len; len--, uni++) + *ansi++ = (*uni & 0xff80) ? '?' : *(char *)uni; +} + +int +jfs_mount (void) +{ + struct jfs_superblock super; + + if (part_length < MINJFS >> SECTOR_BITS + || !devread (SUPER1_OFF >> SECTOR_BITS, 0, + sizeof(struct jfs_superblock), (char *)&super) + || (super.s_magic != JFS_MAGIC) + || !devread ((AITBL_OFF >> SECTOR_BITS) + FILESYSTEM_I, + 0, DISIZE, (char*)fileset)) { + return 0; + } + + jfs.bsize = super.s_bsize; + jfs.l2bsize = super.s_l2bsize; + jfs.bdlog = jfs.l2bsize - SECTOR_BITS; + + return 1; +} + +int +jfs_read (char *buf, int len) +{ + xad_t *xad; + s64 endofprev, endofcur; + s64 offset, xadlen; + int toread, startpos, endpos; + + startpos = filepos; + endpos = filepos + len; + endofprev = (1ULL << 62) - 1; + xad = first_extent (inode); + do { + offset = offsetXAD (xad); + xadlen = lengthXAD (xad); + if (isinxt (filepos >> jfs.l2bsize, offset, xadlen)) { + endofcur = (offset + xadlen) << jfs.l2bsize; + toread = (endofcur >= endpos) + ? len : (endofcur - filepos); + + disk_read_func = disk_read_hook; + devread (addressXAD (xad) << jfs.bdlog, + filepos - (offset << jfs.l2bsize), toread, buf); + disk_read_func = NULL; + + buf += toread; + len -= toread; + filepos += toread; + } else if (offset > endofprev) { + toread = ((offset << jfs.l2bsize) >= endpos) + ? len : ((offset - endofprev) << jfs.l2bsize); + len -= toread; + filepos += toread; + for (; toread; toread--) { + *buf++ = 0; + } + continue; + } + endofprev = offset + xadlen; + xad = next_extent (); + } while (len > 0 && xad); + + return filepos - startpos; +} + +int +jfs_dir (char *dirname) +{ + char *ptr, *rest, ch; + ldtentry_t *de; + dtslot_t *ds; + u32 inum, parent_inum; + s64 di_size; + u32 di_mode; + int namlen, cmp, n, link_count; + char namebuf[JFS_NAME_MAX + 1], linkbuf[JFS_PATH_MAX]; + + parent_inum = inum = ROOT_I; + link_count = 0; + for (;;) { + di_read (inum, inode); + di_size = inode->di_size; + di_mode = inode->di_mode; + + if ((di_mode & IFMT) == IFLNK) { + if (++link_count > MAX_LINK_COUNT) { + errnum = ERR_SYMLINK_LOOP; + return 0; + } + if (di_size < (di_mode & INLINEEA ? 256 : 128)) { + grub_memmove (linkbuf, inode->di_fastsymlink, di_size); + n = di_size; + } else if (di_size < JFS_PATH_MAX - 1) { + filepos = 0; + filemax = di_size; + n = jfs_read (linkbuf, filemax); + } else { + errnum = ERR_FILELENGTH; + return 0; + } + + inum = (linkbuf[0] == '/') ? ROOT_I : parent_inum; + while (n < (JFS_PATH_MAX - 1) && (linkbuf[n++] = *dirname++)); + linkbuf[n] = 0; + dirname = linkbuf; + continue; + } + + if (!*dirname || isspace (*dirname)) { + if ((di_mode & IFMT) != IFREG) { + errnum = ERR_BAD_FILETYPE; + return 0; + } + filepos = 0; + filemax = di_size; + return 1; + } + + if ((di_mode & IFMT) != IFDIR) { + errnum = ERR_BAD_FILETYPE; + return 0; + } + + for (; *dirname == '/'; dirname++); + + for (rest = dirname; (ch = *rest) && !isspace (ch) && ch != '/'; rest++); + *rest = 0; + + de = first_dentry (); + for (;;) { + namlen = de->namlen; + if (de->next == -1) { + uni2ansi (de->name, namebuf, namlen); + namebuf[namlen] = 0; + } else { + uni2ansi (de->name, namebuf, DTLHDRDATALEN); + ptr = namebuf; + ptr += DTLHDRDATALEN; + namlen -= DTLHDRDATALEN; + ds = next_dslot (de->next); + while (ds->next != -1) { + uni2ansi (ds->name, ptr, DTSLOTDATALEN); + ptr += DTSLOTDATALEN; + namlen -= DTSLOTDATALEN; + ds = next_dslot (ds->next); + } + uni2ansi (ds->name, ptr, namlen); + ptr += namlen; + *ptr = 0; + } + + cmp = (!*dirname) ? -1 : substring (dirname, namebuf); +#ifndef STAGE1_5 + if (print_possibilities && ch != '/' + && cmp <= 0) { + if (print_possibilities > 0) + print_possibilities = -print_possibilities; + print_a_completion (namebuf); + } else +#endif + if (cmp == 0) { + parent_inum = inum; + inum = de->inumber; + *(dirname = rest) = ch; + break; + } + de = next_dentry (); + if (de == NULL) { + if (print_possibilities < 0) + return 1; + + errnum = ERR_FILE_NOT_FOUND; + *rest = ch; + return 0; + } + } + } +} + +int +jfs_embed (int *start_sector, int needed_sectors) +{ + struct jfs_superblock super; + + if (needed_sectors > 63 + || !devread (SUPER1_OFF >> SECTOR_BITS, 0, + sizeof (struct jfs_superblock), + (char *)&super) + || (super.s_magic != JFS_MAGIC)) { + return 0; + } + + *start_sector = 1; + return 1; +} + +#endif /* FSYS_JFS */ diff --git a/qemu/roms/openbios/fs/grubfs/fsys_minix.c b/qemu/roms/openbios/fs/grubfs/fsys_minix.c new file mode 100644 index 000000000..d16b58c87 --- /dev/null +++ b/qemu/roms/openbios/fs/grubfs/fsys_minix.c @@ -0,0 +1,535 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 1999,2000,2001,2002 Free Software Foundation, Inc. + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +/* Restrictions: + This is MINIX V1 only (yet) + Disk creation is like: + mkfs.minix -c DEVICE +*/ + +#ifdef FSYS_MINIX + +#include "shared.h" +#include "filesys.h" + +/* #define DEBUG_MINIX */ + +/* indirect blocks */ +static int mapblock1, mapblock2, namelen; + +/* sizes are always in bytes, BLOCK values are always in DEV_BSIZE (sectors) */ +#define DEV_BSIZE 512 + +/* include/linux/fs.h */ +#define BLOCK_SIZE_BITS 10 +#define BLOCK_SIZE (1<<BLOCK_SIZE_BITS) + +/* made up, defaults to 1 but can be passed via mount_opts */ +#define WHICH_SUPER 1 +/* kind of from fs/ext2/super.c (is OK for minix) */ +#define SBLOCK (WHICH_SUPER * BLOCK_SIZE / DEV_BSIZE) /* = 2 */ + +/* include/asm-i386/type.h */ +typedef __signed__ char __s8; +typedef unsigned char __u8; +typedef __signed__ short __s16; +typedef unsigned short __u16; +typedef __signed__ int __s32; +typedef unsigned int __u32; + +/* include/linux/minix_fs.h */ +#define MINIX_ROOT_INO 1 + +/* Not the same as the bogus LINK_MAX in <linux/limits.h>. Oh well. */ +#define MINIX_LINK_MAX 250 +#define MINIX2_LINK_MAX 65530 + +#define MINIX_I_MAP_SLOTS 8 +#define MINIX_Z_MAP_SLOTS 64 +#define MINIX_SUPER_MAGIC 0x137F /* original minix fs */ +#define MINIX_SUPER_MAGIC2 0x138F /* minix fs, 30 char names */ +#define MINIX2_SUPER_MAGIC 0x2468 /* minix V2 fs */ +#define MINIX2_SUPER_MAGIC2 0x2478 /* minix V2 fs, 30 char names */ +#define MINIX_VALID_FS 0x0001 /* Clean fs. */ +#define MINIX_ERROR_FS 0x0002 /* fs has errors. */ + +#define MINIX_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct minix_inode))) +#define MINIX2_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct minix2_inode))) + +#define MINIX_V1 0x0001 /* original minix fs */ +#define MINIX_V2 0x0002 /* minix V2 fs */ + +/* originally this is : +#define INODE_VERSION(inode) inode->i_sb->u.minix_sb.s_version + here we have */ +#define INODE_VERSION(inode) (SUPERBLOCK->s_version) + +/* + * This is the original minix inode layout on disk. + * Note the 8-bit gid and atime and ctime. + */ +struct minix_inode { + __u16 i_mode; + __u16 i_uid; + __u32 i_size; + __u32 i_time; + __u8 i_gid; + __u8 i_nlinks; + __u16 i_zone[9]; +}; + +/* + * The new minix inode has all the time entries, as well as + * long block numbers and a third indirect block (7+1+1+1 + * instead of 7+1+1). Also, some previously 8-bit values are + * now 16-bit. The inode is now 64 bytes instead of 32. + */ +struct minix2_inode { + __u16 i_mode; + __u16 i_nlinks; + __u16 i_uid; + __u16 i_gid; + __u32 i_size; + __u32 i_atime; + __u32 i_mtime; + __u32 i_ctime; + __u32 i_zone[10]; +}; + +/* + * minix super-block data on disk + */ +struct minix_super_block { + __u16 s_ninodes; + __u16 s_nzones; + __u16 s_imap_blocks; + __u16 s_zmap_blocks; + __u16 s_firstdatazone; + __u16 s_log_zone_size; + __u32 s_max_size; + __u16 s_magic; + __u16 s_state; + __u32 s_zones; +}; + +struct minix_dir_entry { + __u16 inode; + char name[0]; +}; + +/* made up, these are pointers into FSYS_BUF */ +/* read once, always stays there: */ +#define SUPERBLOCK \ + ((struct minix_super_block *)(FSYS_BUF)) +#define INODE \ + ((struct minix_inode *)((char *) SUPERBLOCK + BLOCK_SIZE)) +#define DATABLOCK1 \ + ((char *)((char *)INODE + sizeof(struct minix_inode))) +#define DATABLOCK2 \ + ((char *)((char *)DATABLOCK1 + BLOCK_SIZE)) + +/* linux/stat.h */ +#define S_IFMT 00170000 +#define S_IFLNK 0120000 +#define S_IFREG 0100000 +#define S_IFDIR 0040000 +#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) +#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) +#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) + +#define PATH_MAX 1024 /* include/linux/limits.h */ +#define MAX_LINK_COUNT 5 /* number of symbolic links to follow */ + +/* check filesystem types and read superblock into memory buffer */ +int +minix_mount (void) +{ + if (((current_drive & 0x80) || current_slice != 0) + && ! IS_PC_SLICE_TYPE_MINIX (current_slice) + && ! IS_PC_SLICE_TYPE_BSD_WITH_FS (current_slice, FS_OTHER)) + return 0; /* The partition is not of MINIX type */ + + if (part_length < (SBLOCK + + (sizeof (struct minix_super_block) / DEV_BSIZE))) + return 0; /* The partition is too short */ + + if (!devread (SBLOCK, 0, sizeof (struct minix_super_block), + (char *) SUPERBLOCK)) + return 0; /* Cannot read superblock */ + + switch (SUPERBLOCK->s_magic) + { + case MINIX_SUPER_MAGIC: + namelen = 14; + break; + case MINIX_SUPER_MAGIC2: + namelen = 30; + break; + default: + return 0; /* Unsupported type */ + } + + return 1; +} + +/* Takes a file system block number and reads it into BUFFER. */ +static int +minix_rdfsb (int fsblock, char *buffer) +{ + return devread (fsblock * (BLOCK_SIZE / DEV_BSIZE), 0, + BLOCK_SIZE, buffer); +} + +/* Maps LOGICAL_BLOCK (the file offset divided by the blocksize) into + a physical block (the location in the file system) via an inode. */ +static int +minix_block_map (int logical_block) +{ + int i; + + if (logical_block < 7) + return INODE->i_zone[logical_block]; + + logical_block -= 7; + if (logical_block < 512) + { + i = INODE->i_zone[7]; + + if (!i || ((mapblock1 != 1) + && !minix_rdfsb (i, DATABLOCK1))) + { + errnum = ERR_FSYS_CORRUPT; + return -1; + } + mapblock1 = 1; + return ((__u16 *) DATABLOCK1) [logical_block]; + } + + logical_block -= 512; + i = INODE->i_zone[8]; + if (!i || ((mapblock1 != 2) + && !minix_rdfsb (i, DATABLOCK1))) + { + errnum = ERR_FSYS_CORRUPT; + return -1; + } + mapblock1 = 2; + i = ((__u16 *) DATABLOCK1)[logical_block >> 9]; + if (!i || ((mapblock2 != i) + && !minix_rdfsb (i, DATABLOCK2))) + { + errnum = ERR_FSYS_CORRUPT; + return -1; + } + mapblock2 = i; + return ((__u16 *) DATABLOCK2)[logical_block & 511]; +} + +/* read from INODE into BUF */ +int +minix_read (char *buf, int len) +{ + int logical_block; + int offset; + int map; + int ret = 0; + int size = 0; + + while (len > 0) + { + /* find the (logical) block component of our location */ + logical_block = filepos >> BLOCK_SIZE_BITS; + offset = filepos & (BLOCK_SIZE - 1); + map = minix_block_map (logical_block); +#ifdef DEBUG_MINIX + printf ("map=%d\n", map); +#endif + if (map < 0) + break; + + size = BLOCK_SIZE; + size -= offset; + if (size > len) + size = len; + + disk_read_func = disk_read_hook; + + devread (map * (BLOCK_SIZE / DEV_BSIZE), + offset, size, buf); + + disk_read_func = NULL; + + buf += size; + len -= size; + filepos += size; + ret += size; + } + + if (errnum) + ret = 0; + + return ret; +} + +/* preconditions: minix_mount already executed, therefore supblk in buffer + known as SUPERBLOCK + returns: 0 if error, nonzero iff we were able to find the file successfully + postconditions: on a nonzero return, buffer known as INODE contains the + inode of the file we were trying to look up + side effects: none yet */ +int +minix_dir (char *dirname) +{ + int current_ino = MINIX_ROOT_INO; /* start at the root */ + int updir_ino = current_ino; /* the parent of the current directory */ + int ino_blk; /* fs pointer of the inode's info */ + + int str_chk = 0; /* used ot hold the results of a string + compare */ + + struct minix_inode * raw_inode; /* inode info for current_ino */ + + char linkbuf[PATH_MAX]; /* buffer for following sym-links */ + int link_count = 0; + + char * rest; + char ch; + + int off; /* offset within block of directory + entry */ + int loc; /* location within a directory */ + int blk; /* which data blk within dir entry */ + long map; /* fs pointer of a particular block from + dir entry */ + struct minix_dir_entry * dp; /* pointer to directory entry */ + + /* loop invariants: + current_ino = inode to lookup + dirname = pointer to filename component we are cur looking up within + the directory known pointed to by current_ino (if any) */ + +#ifdef DEBUG_MINIX + printf ("\n"); +#endif + + while (1) + { +#ifdef DEBUG_MINIX + printf ("inode %d, dirname %s\n", current_ino, dirname); +#endif + + ino_blk = (2 + SUPERBLOCK->s_imap_blocks + SUPERBLOCK->s_zmap_blocks + + (current_ino - 1) / MINIX_INODES_PER_BLOCK); + if (! minix_rdfsb (ino_blk, (char *) INODE)) + return 0; + + /* reset indirect blocks! */ + mapblock2 = mapblock1 = -1; + + raw_inode = INODE + ((current_ino - 1) % MINIX_INODES_PER_BLOCK); + + /* copy inode to fixed location */ + memmove ((void *) INODE, (void *) raw_inode, + sizeof (struct minix_inode)); + + /* If we've got a symbolic link, then chase it. */ + if (S_ISLNK (INODE->i_mode)) + { + int len; + + if (++link_count > MAX_LINK_COUNT) + { + errnum = ERR_SYMLINK_LOOP; + return 0; + } +#ifdef DEBUG_MINIX + printf ("S_ISLNK (%s)\n", dirname); +#endif + + /* Find out how long our remaining name is. */ + len = 0; + while (dirname[len] && !isspace (dirname[len])) + len++; + + /* Get the symlink size. */ + filemax = (INODE->i_size); + if (filemax + len > sizeof (linkbuf) - 2) + { + errnum = ERR_FILELENGTH; + return 0; + } + + if (len) + { + /* Copy the remaining name to the end of the symlink data. + Note that DIRNAME and LINKBUF may overlap! */ + memmove (linkbuf + filemax, dirname, len); + } + linkbuf[filemax + len] = '\0'; + + /* Read the necessary blocks, and reset the file pointer. */ + len = grub_read (linkbuf, filemax); + filepos = 0; + if (!len) + return 0; + +#ifdef DEBUG_MINIX + printf ("symlink=%s\n", linkbuf); +#endif + + dirname = linkbuf; + if (*dirname == '/') + { + /* It's an absolute link, so look it up in root. */ + current_ino = MINIX_ROOT_INO; + updir_ino = current_ino; + } + else + { + /* Relative, so look it up in our parent directory. */ + current_ino = updir_ino; + } + + /* Try again using the new name. */ + continue; + } + + /* If end of filename, INODE points to the file's inode */ + if (!*dirname || isspace (*dirname)) + { + if (!S_ISREG (INODE->i_mode)) + { + errnum = ERR_BAD_FILETYPE; + return 0; + } + + filemax = (INODE->i_size); + return 1; + } + + /* else we have to traverse a directory */ + updir_ino = current_ino; + + /* skip over slashes */ + while (*dirname == '/') + dirname++; + + /* if this isn't a directory of sufficient size to hold our file, + abort */ + if (!(INODE->i_size) || !S_ISDIR (INODE->i_mode)) + { + errnum = ERR_BAD_FILETYPE; + return 0; + } + + /* skip to next slash or end of filename (space) */ + for (rest = dirname; (ch = *rest) && !isspace (ch) && ch != '/'; + rest++); + + /* look through this directory and find the next filename component */ + /* invariant: rest points to slash after the next filename component */ + *rest = 0; + loc = 0; + + do + { +#ifdef DEBUG_MINIX + printf ("dirname=`%s', rest=`%s', loc=%d\n", dirname, rest, loc); +#endif + + /* if our location/byte offset into the directory exceeds the size, + give up */ + if (loc >= INODE->i_size) + { + if (print_possibilities < 0) + { +#if 0 + putchar ('\n'); +#endif + } + else + { + errnum = ERR_FILE_NOT_FOUND; + *rest = ch; + } + return (print_possibilities < 0); + } + + /* else, find the (logical) block component of our location */ + blk = loc >> BLOCK_SIZE_BITS; + + /* we know which logical block of the directory entry we are looking + for, now we have to translate that to the physical (fs) block on + the disk */ + map = minix_block_map (blk); +#ifdef DEBUG_MINIX + printf ("fs block=%d\n", map); +#endif + mapblock2 = -1; + if ((map < 0) || !minix_rdfsb (map, DATABLOCK2)) + { + errnum = ERR_FSYS_CORRUPT; + *rest = ch; + return 0; + } + off = loc & (BLOCK_SIZE - 1); + dp = (struct minix_dir_entry *) (DATABLOCK2 + off); + /* advance loc prematurely to next on-disk directory entry */ + loc += sizeof (dp->inode) + namelen; + + /* NOTE: minix filenames are NULL terminated if < NAMELEN + else exact */ + +#ifdef DEBUG_MINIX + printf ("directory entry ino=%d\n", dp->inode); + if (dp->inode) + printf ("entry=%s\n", dp->name); +#endif + + if (dp->inode) + { + int saved_c = dp->name[namelen]; + + dp->name[namelen] = 0; + str_chk = substring (dirname, dp->name); + +# ifndef STAGE1_5 + if (print_possibilities && ch != '/' + && (!*dirname || str_chk <= 0)) + { + if (print_possibilities > 0) + print_possibilities = -print_possibilities; + print_a_completion (dp->name); + } +# endif + + dp->name[namelen] = saved_c; + } + + } + while (!dp->inode || (str_chk || (print_possibilities && ch != '/'))); + + current_ino = dp->inode; + *(dirname = rest) = ch; + } + /* never get here */ +} + +#endif /* FSYS_MINIX */ diff --git a/qemu/roms/openbios/fs/grubfs/fsys_ntfs.c b/qemu/roms/openbios/fs/grubfs/fsys_ntfs.c new file mode 100644 index 000000000..a244f5c6b --- /dev/null +++ b/qemu/roms/openbios/fs/grubfs/fsys_ntfs.c @@ -0,0 +1,1255 @@ +/* vim: set sw=4 :*/ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 1999 Free Software Foundation, Inc. + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +/* + * Samuel Leo <samuel@_.remove.me._szonline.net> + * Limitations: + * 1. Only 32 bit size support + * 2. don't support >1k MFT record size, >16k INDEX record size + * 3. don't support recursive at_attribute_list + * 4. don't support compressed attribute other than Datastream + * 5. all MFT's at_attribute_list must resident at first run list + * 6. don't support journaling + * 7. don't support EFS encryption + * 8. don't support mount point and junction + */ +#ifdef FSYS_NTFS + +//#define DEBUG_NTFS 1 + +/* +#define NO_ATTRIBUTE_LIST 1 + totally disable at_attribute_list support, + if no compressed/fragment file and MFT, + not recommended +#define NO_NON_RESIDENT_ATTRIBUTE_LIST 1 + disable non-resident at_attribute_list support, + if no huge compressed/fragment file and MFT +#define NO_NTFS_DECOMPRESSION 1 + disable ntfs compressed file support +#define NO_ALTERNATE_DATASTREAM 1 + disable ntfs alternate datastream support +*/ + +#include "shared.h" +#include "filesys.h" + +#ifdef STAGE1_5 +/* safe turn off non-resident attribute list if MFT fragments < 4000 */ +//#define NO_NON_RESIDENT_ATTRIBUTE_LIST 1 +#define NO_NTFS_DECOMPRESSION 1 +#endif + +#define MAX_MFT_RECORD_SIZE 1024 +#define MAX_INDEX_RECORD_SIZE 16384 +#define MAX_INDEX_BITMAP_SIZE 4096 +#define DECOMP_DEST_BUFFER_SIZE 16384 +#define DECOMP_SOURCE_BUFFER_SIZE (8192+2) +#define MAX_DIR_DEPTH 64 + +/* sizes are always in bytes, BLOCK values are always in DEV_BSIZE (sectors) */ +#define DEV_BSIZE 512 + +/* include/linux/fs.h */ +#define BLOCK_SIZE 512 + +#define WHICH_SUPER 1 +#define SBLOCK (WHICH_SUPER * BLOCK_SIZE / DEV_BSIZE) /* = 2 */ + +/* include/asm-i386/type.h */ +typedef __signed__ char __s8; +typedef unsigned char __u8; +typedef __signed__ short __s16; +typedef unsigned short __u16; +typedef __signed__ int __s32; +typedef unsigned int __u32; +typedef __signed__ long long __s64; +typedef unsigned long long __u64; + +#define FILE_MFT 0 +#define FILE_MFTMIRR 1 +#define FILE_LOGFILE 2 +#define FILE_VOLUME 3 +#define FILE_ATTRDEF 4 +#define FILE_ROOT 5 +#define FILE_BITMAP 6 +#define FILE_BOOT 7 +#define FILE_BADCLUS 8 +#define FILE_QUOTA 9 +#define FILE_UPCASE 10 + +#define at_standard_information 0x10 +#define at_attribute_list 0x20 +#define at_filename 0x30 +#define at_security_descriptor 0x50 +#define at_data 0x80 +#define at_index_root 0x90 +#define at_index_allocation 0xa0 +#define at_bitmap 0xb0 +#define at_symlink 0xc0 + +#define NONAME "" +#define ATTR_NORMAL 0 +#define ATTR_COMPRESSED 1 +#define ATTR_RESIDENT 2 +#define ATTR_ENCRYPTED 16384 +#define ATTR_SPARSE 32768 + +typedef struct run_list { + char *start; + char *ptr; + int svcn; + int evcn; + int vcn; + int cnum0; + int cnum; + int clen; +} RUNL; + +typedef struct ntfs_mft_record { + char mft[MAX_MFT_RECORD_SIZE]; + char mft2[MAX_MFT_RECORD_SIZE]; + int attr_type; + char *attr_name; + int attr_flag; + int attr_size; + char *attr; + int attr_len; + RUNL runl; + char *attr_list; + int attr_list_len; + int attr_list_size; + int attr_list_off; + int attr_inited; + char attr_list_buf[2*BLOCK_SIZE]; + RUNL attr_list_runl; +} MFTR; + + +#define index_data ((char *)FSYS_BUF) +#define bitmap_data ((__u8 *)(FSYS_BUF+MAX_INDEX_RECORD_SIZE)) +#define dcdbuf ((__u8 *)index_data) +#define dcsbuf (bitmap_data) +#define dcend (dcsbuf+DECOMP_SOURCE_BUFFER_SIZE) +#define fnbuf ((char *)(bitmap_data+MAX_INDEX_BITMAP_SIZE)) +#define mmft ((MFTR *)dcend) +#define cmft ((MFTR *)(dcend+sizeof(MFTR))) +#define mft_run ((RUNL *)(dcend+2*sizeof(MFTR))) +#define path_ino ((int *)(dcend+2*sizeof(MFTR)+sizeof(RUNL))) +#define cluster16 (path_ino+MAX_DIR_DEPTH) +#define index16 cluster16[16] +#define blocksize cluster16[17] +#define clustersize cluster16[18] +#define mft_record_size cluster16[19] +#define index_record_size cluster16[20] +#define dcvcn cluster16[21] +#define dcoff cluster16[22] +#define dclen cluster16[23] +#define dcrem cluster16[24] +#define dcslen cluster16[25] +#define dcsptr ((__u8 *)cluster16[26]) +#define is_ads_completion cluster16[27] + +static int read_mft_record(int mftno, char *mft, int self); +static int read_attribute(MFTR *mftr, int offset, char *buf, int len, RUNL *from_rl); +static int get_next_run(RUNL *runl); + +static inline int +nsubstring (char *s1, char *s2) +{ + while (tolower(*s1) == tolower(*s2)) + { + /* The strings match exactly. */ + if (! *(s1++)) + return 0; + s2 ++; + } + + /* S1 is a substring of S2. */ + if (*s1 == 0) + return -1; + + /* S1 isn't a substring. */ + return 1; +} + +static int fixup_record(char *record, char *magic, int size) +{ + int start, count, offset; + __u16 fixup; + + if(*(int *)record != *(int *)magic) + return 0; + start=*(__u16 *)(record+4); + count=*(__u16 *)(record+6); + count--; + if(size && blocksize*count != size) + return 0; + fixup = *(__u16 *)(record+start); + start+=2; + offset=blocksize-2; + while(count--){ + if(*(__u16 *)(record+offset)!=fixup) + return 0; + *(__u16 *)(record+offset) = *(__u16 *)(record+start); + start+=2; + offset+=blocksize; + } + return 1; +} + +static void rewind_run_list( RUNL *runl) { + runl->vcn = runl->svcn; + runl->ptr = runl->start; + runl->cnum0 = 0; + runl->cnum = 0; + runl->clen = 0; +} + +static int get_next_run(RUNL *runl){ + int t, n, v; + +#ifdef DEBUG_NTFS + printf("get_next_run: s=%d e=%d c=%d start=%x ptr=%x\n", + runl->svcn, runl->evcn, runl->vcn, runl->start, runl->ptr); +#endif + + runl->vcn += runl->clen; + if(runl->vcn > runl->evcn) { + return 0; + } + + t = *(runl->ptr)++; + n = t&0xf; + runl->clen = 0; v = 1; + while(n--) { + runl->clen += v * *((__u8 *)runl->ptr)++; + v <<= 8; + } + n = (t>>4)&0xf; + if(n==0) + runl->cnum = 0; + else { + int c = 0; + v = 1; + while(n--) { + c += v * *((__u8 *)runl->ptr)++; + v <<= 8; + } + if(c & (v>>1)) c -= v; + runl->cnum0 += c; + runl->cnum = runl->cnum0; + } +#ifdef DEBUG_NTFS + printf("got_next_run: t=%x cluster %x len %x vcn=%x ecn=%x\n", + t, runl->cnum, runl->clen, runl->vcn, runl->evcn); +#endif + return 1; +} + +#ifndef NO_ATTRIBUTE_LIST +static void init_run_list(char *attr, int len, RUNL *runl, __u32 *initp) { + int allocated; + + runl->svcn = *(__u32 *)(attr+0x10); /* only support 32 bit */ + runl->evcn = *(__u32 *)(attr+0x18); /* only support 32 bit */ + runl->start = attr + *(__u16 *)(attr+0x20); + allocated = *(__u32 *)(attr+0x28); + if(initp) *initp = *(__u32 *)(attr+0x38); + if(!runl->evcn) runl->evcn = (allocated - 1) / clustersize; +#ifdef DEBUG_NTFS + printf("size %d allocated=%d inited=%d cegin=%x csize=%d vcn=%d-%d\n", + /*attr_size*/ *(__u32 *)(attr+0x30), + /*allocated*/ *(__u32 *)(attr+0x28), + /*attr_inited*/ *(__u32 *)(attr+0x38), + /*cengin*/ *(__u16 *)(attr+0x22), + /*csize*/ *(__u16 *)(attr+0x40), + runl->svcn, runl->evcn); +#endif + rewind_run_list(runl); +} +#endif + + +static int find_attribute(char *mft, int type, char *name, char **attr, int *size, int *len, int *flag) { + int t, l, r, n, i, namelen; + unsigned short *attr_name; + + n = strlen(name); + r = mft_record_size - *(__u16 *)(mft+0x14); + mft += *(__u16 *)(mft+0x14); + while( (t = *(__s32 *)mft) != -1 ) { + l = *(__u32 *)(mft+4); + if(l>r) break; +#ifdef DEBUG_NTFS + printf("type = %x len = %d namelen=%d resident=%d compresed=%d attrno=%d\n", + t, l, + /*namelen*/ *(mft+9), + //name = (__u16 *)(mft + *(__u16 *)(mft+10)), + /*resident */ (*(mft+8) == 0), + /*compressed*/ *(__u16 *)(mft+12), + /*attrno*/ *(__u16 *)(mft+14)); +#endif + namelen = *(mft+9); + if(t == type) { +#ifndef STAGE1_5 +#ifndef NO_ALTERNATE_DATASTREAM + if(is_ads_completion && type == at_data) { + if(namelen && namelen >= n && + (!*(mft+8)/*resident*/ || !*(__u32 *)(attr+0x10)/*svcn==0*/)) + { + for(i=0, attr_name=(__u16 *)(mft + *(__u16 *)(mft+10)); i < n; i++) + if(tolower(name[i]) != tolower(attr_name[i])) + break; + if(i >= n) { + for(; i < namelen; i++) + name[i] = attr_name[i]; + name[i] = '\0'; + if(print_possibilities > 0) + print_possibilities = -print_possibilities; + print_a_completion(fnbuf); + name[n] = '\0'; + } + } + } else +#endif +#endif + if(namelen == n) { + + for(i=0, attr_name=(__u16 *)(mft + *(__u16 *)(mft+10)); i<n; i++) + if(tolower(name[i]) != tolower(attr_name[i])) + break; + if(i>=n) { + if(flag) *flag = *(__u16 *)(mft+12); + if(*(mft+8) == 0) { + if(flag) *flag |= ATTR_RESIDENT; +#ifdef DEBUG_NTFS + printf("resident data at %x size %x indexed=%d\n", + /*data*/ *(__u16 *)(mft+0x14), + /*attr_size*/ *(__u16 *)(mft+0x10), + /*indexed*/ *(__u16 *)(mft+0x16)); +#endif + if(attr) *attr = mft + *(__u16 *)(mft+0x14); + if(size) *size = *(__u16 *)(mft+0x10); + if(len) *len = *(__u16 *)(mft+0x10); + } else { + if(attr) *attr = mft; + if(size) *size = *(__u32 *)(mft+0x30); + if(len) *len = l; + } + return 1; + } + } + } + mft += l; + r -= l; + } + return 0; +} + +#ifndef NO_ATTRIBUTE_LIST +static __u32 get_next_attribute_list(MFTR *mftr, int *size) { + int l, t, mftno; +#ifdef DEBUG_NTFS + printf("get_next_attribute_list: type=%x\n",mftr->attr_type); +#endif +again: + while(mftr->attr_list_len>0x14) { + t = *(__u32 *)(mftr->attr_list + 0); + l = *(__u16 *)(mftr->attr_list + 4); +#ifdef DEBUG_NTFS + printf("attr_list type=%x len=%x remain=%x\n", t, l, mftr->attr_list_len); +#endif + if(l==0 || l>mftr->attr_list_len) return 0; + mftno = *(__u32 *)(mftr->attr_list + 0x10); + mftr->attr_list_len -= l; + mftr->attr_list += l; + if(t==mftr->attr_type) + { +#ifdef DEBUG_NTFS + printf("attr_list mftno=%x\n", mftno); +#endif + if(read_mft_record(mftno, mftr->mft2, (mftr==mmft))==0) + break; + if(find_attribute(mftr->mft2, mftr->attr_type, mftr->attr_name, + &mftr->attr, size, &mftr->attr_len, &mftr->attr_flag)) + return 1; + } + } +#ifndef NO_NON_RESIDENT_ATTRIBUTE_LIST + if(mftr->attr_list_off < mftr->attr_list_size) { + int len = mftr->attr_list_size - mftr->attr_list_off; + if(len > BLOCK_SIZE) len = BLOCK_SIZE; + + if(mftr->attr_list_len) + memmove(mftr->attr_list_buf, mftr->attr_list, mftr->attr_list_len); + mftr->attr_list = mftr->attr_list_buf; + + if(read_attribute( NULL, mftr->attr_list_off, + mftr->attr_list_buf + mftr->attr_list_len, + len, &mftr->attr_list_runl) != len) + { +#ifdef DEBUG_NTFS + printf("CORRUPT NON-RESIDENT ATTRIBUTE_LIST\n"); +#endif + /* corrupt */ + errnum = ERR_FSYS_CORRUPT; + mftr->attr_list_size = 0; + mftr->attr_len = 0; + mftr->attr_list = NULL; + return 0; + } + + mftr->attr_list_len += len; + mftr->attr_list_off += len; + goto again; + } +#endif + mftr->attr_list = NULL; + return 0; +} +#endif + +static int search_attribute( MFTR *mftr, int type, char *name) +{ +#ifdef DEBUG_NTFS + printf("searching attribute %x <%s>\n", type, name); +#endif + + mftr->attr_type = type; + mftr->attr_name = name; + mftr->attr_list = NULL; + mftr->attr_list_len = 0; + mftr->attr_list_size = 0; + mftr->attr_list_off = 0; + dcrem = dclen = 0; + +#ifndef NO_ATTRIBUTE_LIST + if(find_attribute(mftr->mft, at_attribute_list, NONAME, + &mftr->attr_list, &mftr->attr_list_size, + &mftr->attr_list_len, &mftr->attr_list_off)) { + if(mftr->attr_list_off&ATTR_RESIDENT) { + /* resident at_attribute_list */ + mftr->attr_list_size = 0; +#ifdef DEBUG_NTFS + printf("resident attribute_list len=%x\n", mftr->attr_list_len); +#endif + } else { +#ifdef DEBUG_NTFS + printf("non-resident attribute_list len=%x size=%x\n", + mftr->attr_list_len, mftr->attr_list_size); +#endif +#ifndef NO_NON_RESIDENT_ATTRIBUTE_LIST + init_run_list(mftr->attr_list, mftr->attr_list_len, &mftr->attr_list_runl, NULL); + if(get_next_run(&mftr->attr_list_runl)==0 || + mftr->attr_list_runl.cnum==0) + mftr->attr_list_size = 0; +#endif + mftr->attr_list = NULL; + mftr->attr_list_len = 0; + } + } +#endif + + if(find_attribute(mftr->mft, type, name, + &mftr->attr, &mftr->attr_size, &mftr->attr_len, + &mftr->attr_flag) +#ifndef NO_ATTRIBUTE_LIST + || get_next_attribute_list(mftr, &mftr->attr_size) +#endif + ) + { +#ifndef NO_ATTRIBUTE_LIST + if(!(mftr->attr_flag&ATTR_RESIDENT)){ + init_run_list(mftr->attr, mftr->attr_len, &mftr->runl, &mftr->attr_inited); + if(mftr->attr_inited > mftr->attr_size) + mftr->attr_inited = mftr->attr_size; + if(get_next_run(&mftr->runl)==0) { + mftr->attr_flag |= ATTR_RESIDENT; + mftr->attr_len = 0; + } + } else + mftr->attr_inited = mftr->attr_size; +#endif + + return 1; + } + + mftr->attr_type = 0; + return 0; +} + +static int get_run( RUNL *rl, int vcn, int *clp, int *lenp) { + if(rl->evcn < vcn) + return 0; + + if(rl->vcn > vcn) { + rewind_run_list(rl); + get_next_run(rl); + } + + while(rl->vcn+rl->clen <= vcn) + { + if(get_next_run(rl)==0) + return 0; + } + + if(clp) *clp = rl->cnum == 0 ? 0 : rl->cnum + vcn - rl->vcn; + if(lenp) *lenp = rl->clen - vcn + rl->vcn; + return 1; +} + +static int search_run(MFTR *mftr, int vcn) { + + if( mftr->attr==NULL && !search_attribute(mftr, mftr->attr_type, mftr->attr_name)) + return 0; + + if(mftr->runl.svcn > vcn) + search_attribute(mftr, mftr->attr_type, mftr->attr_name); + +#ifdef NO_ATTRIBUTE_LIST + if(mftr->runl.evcn < vcn) + return 0; +#else + while(mftr->runl.evcn < vcn) { + if(get_next_attribute_list(mftr, NULL)==0) { + mftr->attr = NULL; + return 0; + } + init_run_list(mftr->attr, mftr->attr_len, &mftr->runl, NULL); + if(get_next_run(&mftr->runl)==0) { + mftr->attr = NULL; + return 0; + } + } +#endif + + return 1; +} + +static int read_attribute(MFTR *mftr, int offset, char *buf, int len, RUNL *from_rl) { + int vcn; + int cnum, clen; + int done = 0; + int n; + RUNL *rl; + + if(!from_rl && (mftr->attr_flag & ATTR_RESIDENT)) { + /* resident attribute */ + if(offset > mftr->attr_len) + return 0; + if(offset+len > mftr->attr_len) + len = mftr->attr_len - offset; + memmove( buf, mftr->attr + offset, len); + return len; + } + + vcn = offset / clustersize; + offset %= clustersize; + + while(len>0) { + if(from_rl) + rl = from_rl; + else if(search_run(mftr, vcn) == 0) + break; + else + rl = &mftr->runl; + if(get_run(rl, vcn, &cnum, &clen) == 0) + break; + if(cnum==0 && from_rl) + break; + n = clen * clustersize - offset; + if(n > len) n = len; + if(cnum==0) { + memset( buf, 0, n); + } else if(!devread(cnum*(clustersize>>9)+(offset>>9), offset&0x1ff, n, buf)) + break; + + buf += n; + vcn += (offset+n)/clustersize; + done += n; + offset = 0; + len -= n; + } + return done; +} + +static int read_mft_record(int mftno, char *mft, int self){ +#ifdef DEBUG_NTFS + printf("Reading MFT record: mftno=%d\n", mftno); +#endif + if( read_attribute( mmft, mftno * mft_record_size, + mft, mft_record_size, self?mft_run:NULL) != mft_record_size) + return 0; + if(!fixup_record( mft, "FILE", mft_record_size)) + return 0; + return 1; +} + +#ifndef NO_NTFS_DECOMPRESSION +static int get_16_cluster(MFTR *mftr, int vcn) { + int n = 0, cnum, clen; + while(n < 16 && search_run(mftr, vcn) && get_run(&mftr->runl, vcn, &cnum, &clen) && cnum) { + if(clen > 16 - n) + clen = 16 - n; + vcn += clen; + while(clen--) + cluster16[n++] = cnum++; + } + cluster16[n] = 0; + return n; +} + +static inline int compressed_block_size( unsigned char *src ) { + return 3 + (*(__u16 *)src & 0xfff); +} + +static int decompress_block(unsigned char *dest, unsigned char *src) { + int head; + int copied=0; + unsigned char *last; + int bits; + int tag=0; + + /* high bit indicates that compression was performed */ + if(!(*(__u16 *)src & 0x8000)) { + memmove(dest,src+2,0x1000); + return 0x1000; + } + + if((head = *(__u16 *)src & 0xFFF)==0) + /* block is not used */ + return 0; + + src += 2; + last = src+head; + bits = 0; + + while(src<=last) + { + if(copied>4096) + { +#ifdef DEBUG_NTFS + printf("decompress error 1\n"); +#endif + errnum = ERR_FSYS_CORRUPT; + return 0; + } + if(!bits){ + tag=*(__u8 *)src; + bits=8; + src++; + if(src>last) + break; + } + if(tag & 1){ + int i,len,delta,code,lmask,dshift; + code = *(__u16 *)src; + src+=2; + if(!copied) + { +#ifdef DEBUG_NTFS + printf("decompress error 2\n"); +#endif + errnum = ERR_FSYS_CORRUPT; + return 0; + } + for(i=copied-1,lmask=0xFFF,dshift=12;i>=0x10;i>>=1) + { + lmask >>= 1; + dshift--; + } + delta = code >> dshift; + len = (code & lmask) + 3; + for(i=0; i<len; i++) + { + dest[copied]=dest[copied-delta-1]; + copied++; + } + } else + dest[copied++]=*(__u8 *)src++; + tag>>=1; + bits--; + } + + return copied; +} +#endif + +int ntfs_read(char *buf, int len){ + int ret; +#ifdef STAGE1_5 +/* stage2 can't be resident/compressed/encrypted files, + * but does sparse flag, cause stage2 never sparsed + */ + if((cmft->attr_flag&~ATTR_SPARSE) != ATTR_NORMAL) + return 0; + disk_read_func = disk_read_hook; + ret = read_attribute(cmft, filepos, buf, len, 0); + disk_read_func = NULL; + filepos += ret; +#else + +#ifndef NO_NTFS_DECOMPRESSION + int off; + int vcn; + int size; + int len0; +#endif + + if(len<=0 || filepos >= cmft->attr_size || (cmft->attr_flag&ATTR_ENCRYPTED)) + return 0; + + if(filepos+len > cmft->attr_size) + len = cmft->attr_size - filepos; + if(filepos >= cmft->attr_inited) { +#ifdef DEBUG_NTFS +printf("reading uninitialized data 1\n"); +#endif + memset(buf, 0, len); + return len; + } else if(filepos+len > cmft->attr_inited) { + len0 = len; + len = cmft->attr_inited - filepos; + len0 -= len; + } else + len0 = 0; +#ifdef DEBUG_NTFS +printf("read filepos=%x filemax=%x inited=%x len=%x len0=%x\n",filepos,filemax,cmft->attr_inited,len,len0); +#endif + + if((cmft->attr_flag&(ATTR_COMPRESSED|ATTR_RESIDENT)) != ATTR_COMPRESSED) { + if(cmft->attr_flag==ATTR_NORMAL) + disk_read_func = disk_read_hook; + ret = read_attribute(cmft, filepos, buf, len, 0); + if(cmft->attr_flag==ATTR_NORMAL) + disk_read_func = NULL; + filepos += ret; + if(ret==len && len0) { + memset(buf+len, 0, len0); + filepos += len0; + ret += len0; + } + return ret; + } + + ret = 0; + +#ifndef NO_NTFS_DECOMPRESSION + /* NTFS don't support compression if cluster size > 4k */ + if(clustersize > 4096) { + errnum = ERR_FSYS_CORRUPT; + return 0; + } + + while(len > 0){ +#ifdef DEBUG_NTFS +printf("Reading filepos=%x len=%x\n", filepos, len); +#endif + if(filepos >= dcoff && filepos < (dcoff+dclen)) { +#ifdef DEBUG_NTFS +printf("decompress cache %x+%x\n", dcoff, dclen); +#endif + size = dcoff + dclen - filepos; + if(size > len) size = len; + memmove( buf, dcdbuf + filepos - dcoff, size); + filepos += size; + len -= size; + ret += size; + buf += size; + if(len==0) { + if(len0) { +#ifdef DEBUG_NTFS +printf("reading uninitialized data 2\n"); +#endif + memset(buf, 0, len0); + filepos += len0; + ret += len0; + } + return ret; + } + } + + vcn = filepos / clustersize / 16; + vcn *= 16; + off = filepos % (16 * clustersize); + if( dcvcn != vcn || filepos < dcoff) + dcrem = 0; + +#ifdef DEBUG_NTFS +printf("vcn %x off %x dcrem %x\n", vcn, off, dcrem); +#endif + if(dcrem) { + int head; + + /* reading source */ + if(dcslen < 2 || compressed_block_size(dcsptr) > dcslen) { + if(cluster16[index16]==0) { + errnum = ERR_FSYS_CORRUPT; + return ret; + } + if(dcslen) + memmove(dcsbuf, dcsptr, dcslen); + dcsptr = dcsbuf; + while((dcslen+clustersize) < DECOMP_SOURCE_BUFFER_SIZE) { + if(cluster16[index16]==0) + break; +#ifdef DEBUG_NTFS +printf("reading dcslen=%x cluster %x\n", dcslen, cluster16[index16]); +#endif + if(!devread(cluster16[index16]*(clustersize>>9), 0, clustersize, dcsbuf+dcslen)) + return ret; + dcslen += clustersize; + index16++; + } + } + /* flush destination */ + dcoff += dclen; + dclen = 0; + + while(dcrem && dclen < DECOMP_DEST_BUFFER_SIZE && + dcslen >= 2 && (head=compressed_block_size(dcsptr)) <= dcslen) { + size = decompress_block(dcdbuf+dclen, dcsptr); + if(dcrem>=0x1000 && size!=0x1000) { + errnum = ERR_FSYS_CORRUPT; + return ret; + } + dcrem -= size; + dclen += size; + dcsptr += head; + dcslen -= head; + } + continue; + } + dclen = dcrem = 0; +#ifdef DEBUG_NTFS +printf("get next 16 clusters\n"); +#endif + switch(get_16_cluster(cmft, vcn)) { + case 0: +#ifdef DEBUG_NTFS +printf("sparse\n"); +#endif + /* sparse */ + size = 16 * clustersize - off; + if( len < size ) + size = len; +#ifndef STAGE1_5 + memset( buf, 0, size); +#endif + filepos += size; + len -= size; + ret += size; + buf += size; + break; + + case 16: +#ifdef DEBUG_NTFS +printf("uncompressed\n"); +#endif + /* uncompressed */ + index16 = off / clustersize; + off %= clustersize; + while(index16 < 16) { + size = clustersize - off; + if( len < size ) + size = len; + if(!devread(cluster16[index16]*(clustersize>>9)+(off>>9), off&0x1ff, size, buf)) + return ret; + filepos += size; + len -= size; + ret += size; + if(len==0) + return ret; + off = 0; + buf += size; + index16++; + } + break; + + default: +#ifdef DEBUG_NTFS +printf("compressed\n"); +#endif + index16 = 0; + dcvcn = vcn; + dcoff = vcn * clustersize; + dcrem = cmft->attr_inited - dcoff; + if(dcrem > 16 * clustersize) + dcrem = 16 * clustersize; + dcsptr = dcsbuf; + dcslen = 0; + } + } + if(len0) { +#ifdef DEBUG_NTFS +printf("reading uninitialized data 3\n"); +#endif + memset(buf, 0, len0); + filepos += len0; + ret += len0; + } +#else + errnum = FSYS_CORRUPT; +#endif /*NO_NTFS_DECOMPRESSION*/ +#endif /*STAGE1_5*/ + return ret; +} + +int ntfs_mount (void) +{ + char *sb = (char *)FSYS_BUF; + int mft_record; + int spc; + + if (((current_drive & 0x80) || (current_slice != 0)) + && (current_slice != /*PC_SLICE_TYPE_NTFS*/7) + && (current_slice != /*PC_SLICE_TYPE_NTFS*/0x17)) + return 0; + + if (!devread (0, 0, 512, (char *) FSYS_BUF)) + return 0; /* Cannot read superblock */ + + if(sb[3]!='N' || sb[4]!='T' || sb[5]!='F' || sb[6]!='S') + return 0; + blocksize = *(__u16 *)(sb+0xb); + spc = *(unsigned char *)(sb+0xd); + clustersize = spc * blocksize; + mft_record_size = *(char *)(sb+0x40); + index_record_size = *(char *)(sb+0x44); + if(mft_record_size>0) + mft_record_size *= clustersize; + else + mft_record_size = 1 << (-mft_record_size); + + index_record_size *= clustersize; + mft_record = *(__u32 *)(sb+0x30); /* only support 32 bit */ + spc = clustersize / 512; + + if(mft_record_size > MAX_MFT_RECORD_SIZE || index_record_size > MAX_INDEX_RECORD_SIZE) { + /* only support 1k MFT record, 4k INDEX record */ + return 0; + } + +#ifdef DEBUG_NTFS + printf("spc=%x mft_record=%x:%x\n", spc, *(__s64 *)(sb+0x30)); +#endif + + if (!devread (mft_record*spc, 0, mft_record_size, mmft->mft)) + return 0; /* Cannot read superblock */ + + if(!fixup_record( mmft->mft, "FILE", mft_record_size)) + return 0; + +#ifndef NO_ALTERNATE_DATASTREAM + is_ads_completion = 0; +#endif + if(!search_attribute(mmft, at_data, NONAME)) return 0; + + *mft_run = mmft->runl; + + *path_ino = FILE_ROOT; + + return 1; +} + +int +ntfs_dir (char *dirname) +{ + char *rest, ch; + int namelen; + int depth = 0; + int chk_sfn = 1; + int flag = 0; + int record_offset; + int my_index_record_size; + unsigned char *index_entry = 0, *entry, *index_end; + int i; + + /* main loop to find desired directory entry */ +loop: + +#ifdef DEBUG_NTFS + printf("dirname=%s\n", dirname); +#endif + if(!read_mft_record(path_ino[depth], cmft->mft, 0)) + { +#ifdef DEBUG_NTFS + printf("MFT error 1\n"); +#endif + errnum = ERR_FSYS_CORRUPT; + return 0; + } + + /* if we have a real file (and we're not just printing possibilities), + then this is where we want to exit */ + + if (!*dirname || isspace (*dirname) || *dirname==':') + { +#ifndef STAGE1_5 +#ifndef NO_ALTERNATE_DATASTREAM + if (*dirname==':' && print_possibilities) { + char *tmp; + + /* preparing ADS name completion */ + for(tmp = dirname; *tmp != '/'; tmp--); + for(tmp++, rest=fnbuf; *tmp && !isspace(*tmp); *rest++ = *tmp++) + if(*tmp==':') dirname = rest; + *rest++ = '\0'; + + is_ads_completion = 1; + search_attribute(cmft, at_data, dirname+1); + is_ads_completion = 0; + + if(errnum==0) { + if(print_possibilities < 0) + return 1; + errnum = ERR_FILE_NOT_FOUND; + } + return 0; + } +#endif +#endif + + if (*dirname==':') dirname++; + for (rest = dirname; (ch = *rest) && !isspace (ch); rest++); + *rest = 0; + +#ifdef DEBUG_NTFS + printf("got file: search at_data\n"); +#endif + + if (!search_attribute(cmft, at_data, dirname)) { + errnum = *(dirname-1)==':'?ERR_FILE_NOT_FOUND:ERR_BAD_FILETYPE; + *rest = ch; + return 0; + } + *rest = ch; + + filemax = cmft->attr_size; +#ifdef DEBUG_NTFS + printf("filemax=%x\n", filemax); +#endif + return 1; + } + + if(depth >= (MAX_DIR_DEPTH-1)) { + errnum = ERR_FSYS_CORRUPT; + return 0; + } + + /* continue with the file/directory name interpretation */ + + while (*dirname == '/') + dirname++; + + for (rest = dirname; (ch = *rest) && !isspace (ch) && ch != '/' && ch != ':'; rest++); + + *rest = 0; + + if (!search_attribute(cmft, at_index_root, "$I30")) + { + errnum = ERR_BAD_FILETYPE; + return 0; + } + + read_attribute(cmft, 0, fnbuf, 16, 0); + my_index_record_size = *(__u32 *)(fnbuf+8); + + if(my_index_record_size > MAX_INDEX_RECORD_SIZE) { + errnum = ERR_FSYS_CORRUPT; + return 0; + } + +#ifdef DEBUG_NTFS + printf("index_record_size=%x\n", my_index_record_size); +#endif + + if(cmft->attr_size > MAX_INDEX_RECORD_SIZE) { + errnum = ERR_FSYS_CORRUPT; + return 0; + } + read_attribute(cmft, 0, index_data, cmft->attr_size, 0); + index_end = index_data + cmft->attr_size; + index_entry = index_data + 0x20; + record_offset = -1; + +#ifndef STAGE1_5 + if (print_possibilities && ch != '/' && ch != ':' && !*dirname) + { + print_possibilities = -print_possibilities; + /* fake '.' for empty directory */ + print_a_completion ("."); + } +#endif + + if (search_attribute(cmft, at_bitmap, "$I30")) { + if(cmft->attr_size > MAX_INDEX_BITMAP_SIZE) { + errnum = ERR_FSYS_CORRUPT; + return 0; + } + + read_attribute(cmft, 0, bitmap_data, cmft->attr_size, 0); + + if (search_attribute(cmft, at_index_allocation, "$I30")==0) { + errnum = ERR_FSYS_CORRUPT; + return 0; + } + + for(record_offset = 0; record_offset*my_index_record_size<cmft->attr_size; record_offset++){ + int bit = 1 << (record_offset&3); + int byte = record_offset>>3; +#ifdef DEBUG_NTFS + printf("record_offset=%x\n", record_offset); +#endif + if((bitmap_data[byte]&bit)) + break; + } + + if(record_offset*my_index_record_size>=cmft->attr_size) record_offset = -1; + } + + do + { + entry = index_entry; index_entry += *(__u16 *)(entry+8); + if(entry+0x50>=index_entry||entry>=index_end|| + index_entry>=index_end||(entry[0x12]&2)){ + if(record_offset < 0 || + !read_attribute(cmft, record_offset*my_index_record_size, index_data, my_index_record_size, 0)){ + if (!errnum) + { + if (print_possibilities < 0) + { +#if 0 + putchar ('\n'); +#endif + return 1; + } + + errnum = ERR_FILE_NOT_FOUND; + *rest = ch; + } + + return 0; + } + if(!fixup_record( index_data, "INDX", my_index_record_size)) + { +#ifdef DEBUG_NTFS + printf("index error\n"); +#endif + errnum = ERR_FSYS_CORRUPT; + return 0; + } + entry = index_data + 0x18 + *(__u16 *)(index_data+0x18); + index_entry = entry + *(__u16 *)(entry+8); + index_end = index_data + my_index_record_size - 0x52; + for(record_offset++; record_offset*my_index_record_size<cmft->attr_size; record_offset++){ + int bit = 1 << (record_offset&3); + int byte = record_offset>>3; + if((bitmap_data[byte]&bit)) break; + } + if(record_offset*my_index_record_size>=cmft->attr_size) record_offset = -1; +#ifdef DEBUG_NTFS + printf("record_offset=%x\n", record_offset); +#endif + } + flag = entry[0x51]; + path_ino[depth+1] = *(__u32 *)entry; + if(path_ino[depth+1] < 16) + continue; + namelen = entry[0x50]; + //if(index_data[0x48]&2) printf("hidden file\n"); +#ifndef STAGE1_5 + /* skip short file name */ + if( flag == 2 && print_possibilities && ch != '/' && ch != ':' ) + continue; +#endif + + for( i = 0, entry+=0x52; i < namelen; i++, entry+=2 ) + { + int c = *(__u16 *)entry; + if(c==' '||c>=0x100) + fnbuf[i] = '_'; + else + fnbuf[i] = c; + } + fnbuf[namelen] = 0; +#ifdef DEBUG_NTFS + printf("FLAG: %d NAME: %s inum=%d\n", flag,fnbuf,path_ino[depth+1]); +#endif + + //uncntrl(fnbuf); + + chk_sfn = nsubstring(dirname,fnbuf); +#ifndef STAGE1_5 + if (print_possibilities && ch != '/' && ch != ':' + && (!*dirname || chk_sfn <= 0)) + { + if (print_possibilities > 0) + print_possibilities = -print_possibilities; + print_a_completion (fnbuf); + } +#endif /* STAGE1_5 */ + } + while (chk_sfn != 0 || + (print_possibilities && ch != '/' && ch != ':')); + + *(dirname = rest) = ch; + + depth++; + + /* go back to main loop at top of function */ + goto loop; +} + +#ifdef DEBUG_NTFS +int dump_block(char *msg, char *buf, int size){ + int l = (size+15)/16; + int off; + int i, j; + int c; + printf("----- %s -----\n", msg); + for( i = 0, off = 0; i < l; i++, off+=16) + { + if(off<16) + printf("000%x:", off); + else if(off<256) + printf("00%x:", off); + else + printf("0%x:", off); + for(j=0;j<16;j++) + { + c = buf[off+j]&0xff; + if( c >= 16 ) + printf("%c%x",j==8?'-':' ',c); + else + printf("%c0%x",j==8?'-':' ',c); + } + printf(" "); + for(j=0;j<16;j++) { + char c = buf[off+j]; + printf("%c",c<' '||c>='\x7f'?'.':c); + } + printf("\n"); + } +} +#endif +#endif /* FSYS_NTFS */ diff --git a/qemu/roms/openbios/fs/grubfs/fsys_reiserfs.c b/qemu/roms/openbios/fs/grubfs/fsys_reiserfs.c new file mode 100644 index 000000000..b94a33529 --- /dev/null +++ b/qemu/roms/openbios/fs/grubfs/fsys_reiserfs.c @@ -0,0 +1,1220 @@ +/* fsys_reiserfs.c - an implementation for the ReiserFS filesystem */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2000, 2001 Free Software Foundation, Inc. + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#ifdef FSYS_REISERFS +#include "shared.h" +#include "filesys.h" + +#undef REISERDEBUG + +/* Some parts of this code (mainly the structures and defines) are + * from the original reiser fs code, as found in the linux kernel. + */ + +/* include/asm-i386/types.h */ +typedef __signed__ char __s8; +typedef unsigned char __u8; +typedef __signed__ short __s16; +typedef unsigned short __u16; +typedef __signed__ int __s32; +typedef unsigned int __u32; +typedef unsigned long long __u64; + +/* linux/posix_type.h */ +typedef long linux_off_t; + +#include "libc/byteorder.h" + +/* include/linux/reiser_fs.h */ +/* This is the new super block of a journaling reiserfs system */ +struct reiserfs_super_block +{ + __u32 s_block_count; /* blocks count */ + __u32 s_free_blocks; /* free blocks count */ + __u32 s_root_block; /* root block number */ + __u32 s_journal_block; /* journal block number */ + __u32 s_journal_dev; /* journal device number */ + __u32 s_journal_size; /* size of the journal on FS creation. used to make sure they don't overflow it */ + __u32 s_journal_trans_max; /* max number of blocks in a transaction. */ + __u32 s_journal_magic; /* random value made on fs creation */ + __u32 s_journal_max_batch; /* max number of blocks to batch into a trans */ + __u32 s_journal_max_commit_age; /* in seconds, how old can an async commit be */ + __u32 s_journal_max_trans_age; /* in seconds, how old can a transaction be */ + __u16 s_blocksize; /* block size */ + __u16 s_oid_maxsize; /* max size of object id array */ + __u16 s_oid_cursize; /* current size of object id array */ + __u16 s_state; /* valid or error */ + char s_magic[16]; /* reiserfs magic string indicates that file system is reiserfs */ + __u16 s_tree_height; /* height of disk tree */ + __u16 s_bmap_nr; /* amount of bitmap blocks needed to address each block of file system */ + __u16 s_version; + char s_unused[128]; /* zero filled by mkreiserfs */ +}; + +#define REISERFS_MAX_SUPPORTED_VERSION 2 +#define REISERFS_SUPER_MAGIC_STRING "ReIsErFs" +#define REISER2FS_SUPER_MAGIC_STRING "ReIsEr2Fs" + +#define MAX_HEIGHT 7 + +/* must be correct to keep the desc and commit structs at 4k */ +#define JOURNAL_TRANS_HALF 1018 + +/* first block written in a commit. */ +struct reiserfs_journal_desc { + __u32 j_trans_id; /* id of commit */ + __u32 j_len; /* length of commit. len +1 is the commit block */ + __u32 j_mount_id; /* mount id of this trans*/ + __u32 j_realblock[JOURNAL_TRANS_HALF]; /* real locations for the first blocks */ + char j_magic[12]; +}; + +/* last block written in a commit */ +struct reiserfs_journal_commit { + __u32 j_trans_id; /* must match j_trans_id from the desc block */ + __u32 j_len; /* ditto */ + __u32 j_realblock[JOURNAL_TRANS_HALF]; /* real locations for the last blocks */ + char j_digest[16]; /* md5 sum of all the blocks involved, including desc and commit. not used, kill it */ +}; + +/* this header block gets written whenever a transaction is considered + fully flushed, and is more recent than the last fully flushed + transaction. + fully flushed means all the log blocks and all the real blocks are + on disk, and this transaction does not need to be replayed. +*/ +struct reiserfs_journal_header { + /* id of last fully flushed transaction */ + __u32 j_last_flush_trans_id; + /* offset in the log of where to start replay after a crash */ + __u32 j_first_unflushed_offset; + /* mount id to detect very old transactions */ + __u32 j_mount_id; +}; + +/* magic string to find desc blocks in the journal */ +#define JOURNAL_DESC_MAGIC "ReIsErLB" + + +/* + * directories use this key as well as old files + */ +struct offset_v1 +{ + /* + * for regular files this is the offset to the first byte of the + * body, contained in the object-item, as measured from the start of + * the entire body of the object. + * + * for directory entries, k_offset consists of hash derived from + * hashing the name and using few bits (23 or more) of the resulting + * hash, and generation number that allows distinguishing names with + * hash collisions. If number of collisions overflows generation + * number, we return EEXIST. High order bit is 0 always + */ + __u32 k_offset; + __u32 k_uniqueness; +}; + +struct offset_v2 +{ + /* + * for regular files this is the offset to the first byte of the + * body, contained in the object-item, as measured from the start of + * the entire body of the object. + * + * for directory entries, k_offset consists of hash derived from + * hashing the name and using few bits (23 or more) of the resulting + * hash, and generation number that allows distinguishing names with + * hash collisions. If number of collisions overflows generation + * number, we return EEXIST. High order bit is 0 always + */ + __u64 k_offset:60; + __u64 k_type: 4; +}; + + +struct key +{ + /* packing locality: by default parent directory object id */ + __u32 k_dir_id; + /* object identifier */ + __u32 k_objectid; + /* the offset and node type (old and new form) */ + union + { + struct offset_v1 v1; + struct offset_v2 v2; + } + u; +}; + +#define KEY_SIZE (sizeof (struct key)) + +/* Header of a disk block. More precisely, header of a formatted leaf + or internal node, and not the header of an unformatted node. */ +struct block_head +{ + __u16 blk_level; /* Level of a block in the tree. */ + __u16 blk_nr_item; /* Number of keys/items in a block. */ + __u16 blk_free_space; /* Block free space in bytes. */ + struct key blk_right_delim_key; /* Right delimiting key for this block (supported for leaf level nodes + only) */ +}; +#define BLKH_SIZE (sizeof (struct block_head)) +#define DISK_LEAF_NODE_LEVEL 1 /* Leaf node level. */ + +struct item_head +{ + struct key ih_key; /* Everything in the tree is found by searching for it based on its key.*/ + + union + { + __u16 ih_free_space; /* The free space in the last unformatted node of an indirect item if this + is an indirect item. This equals 0xFFFF iff this is a direct item or + stat data item. Note that the key, not this field, is used to determine + the item type, and thus which field this union contains. */ + __u16 ih_entry_count; /* Iff this is a directory item, this field equals the number of directory + entries in the directory item. */ + } + u; + __u16 ih_item_len; /* total size of the item body */ + __u16 ih_item_location; /* an offset to the item body within the block */ + __u16 ih_version; /* ITEM_VERSION_1 for all old items, + ITEM_VERSION_2 for new ones. + Highest bit is set by fsck + temporary, cleaned after all done */ +}; +/* size of item header */ +#define IH_SIZE (sizeof (struct item_head)) + +#define ITEM_VERSION_1 0 +#define ITEM_VERSION_2 1 +#define IH_KEY_OFFSET(ih) ((ih)->ih_version == ITEM_VERSION_1 \ + ? (ih)->ih_key.u.v1.k_offset \ + : (ih)->ih_key.u.v2.k_offset) + +#define IH_KEY_ISTYPE(ih, type) ((ih)->ih_version == ITEM_VERSION_1 \ + ? (ih)->ih_key.u.v1.k_uniqueness == V1_##type \ + : (ih)->ih_key.u.v2.k_type == V2_##type) + +/* FIXME these types look wrong. */ +struct disk_child +{ + unsigned long dc_block_number; /* Disk child's block number. */ + unsigned short dc_size; /* Disk child's used space. */ +}; + +#define DC_SIZE (sizeof (struct disk_child)) + +/* Stat Data on disk. + * + * Note that reiserfs has two different forms of stat data. Luckily + * the fields needed by grub are at the same position. + */ +struct stat_data +{ + __u16 sd_mode; /* file type, permissions */ + __u16 sd_notused1[3]; /* fields not needed by reiserfs */ + __u32 sd_size; /* file size */ + __u32 sd_size_hi; /* file size high 32 bits (since version 2) */ +}; + +struct reiserfs_de_head +{ + __u32 deh_offset; /* third component of the directory entry key */ + __u32 deh_dir_id; /* objectid of the parent directory of the + object, that is referenced by directory entry */ + __u32 deh_objectid;/* objectid of the object, that is referenced by + directory entry */ + __u16 deh_location;/* offset of name in the whole item */ + __u16 deh_state; /* whether 1) entry contains stat data (for + future), and 2) whether entry is hidden + (unlinked) */ +}; + +#define DEH_SIZE (sizeof (struct reiserfs_de_head)) + +#define DEH_Statdata (1 << 0) /* not used now */ +#define DEH_Visible (1 << 2) + +#define SD_OFFSET 0 +#define SD_UNIQUENESS 0 +#define DOT_OFFSET 1 +#define DOT_DOT_OFFSET 2 +#define DIRENTRY_UNIQUENESS 500 + +#define V1_TYPE_STAT_DATA 0x0 +#define V1_TYPE_DIRECT 0xffffffff +#define V1_TYPE_INDIRECT 0xfffffffe +#define V1_TYPE_DIRECTORY_MAX 0xfffffffd +#define V2_TYPE_STAT_DATA 0 +#define V2_TYPE_INDIRECT 1 +#define V2_TYPE_DIRECT 2 +#define V2_TYPE_DIRENTRY 3 + +#define REISERFS_ROOT_OBJECTID 2 +#define REISERFS_ROOT_PARENT_OBJECTID 1 +#define REISERFS_DISK_OFFSET_IN_BYTES (64 * 1024) +/* the spot for the super in versions 3.5 - 3.5.11 (inclusive) */ +#define REISERFS_OLD_DISK_OFFSET_IN_BYTES (8 * 1024) +#define REISERFS_OLD_BLOCKSIZE 4096 + +#define S_ISREG(mode) (((mode) & 0170000) == 0100000) +#define S_ISDIR(mode) (((mode) & 0170000) == 0040000) +#define S_ISLNK(mode) (((mode) & 0170000) == 0120000) + +#define PATH_MAX 1024 /* include/linux/limits.h */ +#define MAX_LINK_COUNT 5 /* number of symbolic links to follow */ + +/* The size of the node cache */ +#define FSYSREISER_CACHE_SIZE 24*1024 +#define FSYSREISER_MIN_BLOCKSIZE SECTOR_SIZE +#define FSYSREISER_MAX_BLOCKSIZE FSYSREISER_CACHE_SIZE / 3 + +/* Info about currently opened file */ +struct fsys_reiser_fileinfo +{ + __u32 k_dir_id; + __u32 k_objectid; +}; + +/* In memory info about the currently mounted filesystem */ +struct fsys_reiser_info +{ + /* The last read item head */ + struct item_head *current_ih; + /* The last read item */ + char *current_item; + /* The information for the currently opened file */ + struct fsys_reiser_fileinfo fileinfo; + /* The start of the journal */ + __u32 journal_block; + /* The size of the journal */ + __u32 journal_block_count; + /* The first valid descriptor block in journal + (relative to journal_block) */ + __u32 journal_first_desc; + + /* The ReiserFS version. */ + __u16 version; + /* The current depth of the reiser tree. */ + __u16 tree_depth; + /* SECTOR_SIZE << blocksize_shift == blocksize. */ + __u8 blocksize_shift; + /* 1 << full_blocksize_shift == blocksize. */ + __u8 fullblocksize_shift; + /* The reiserfs block size (must be a power of 2) */ + __u16 blocksize; + /* The number of cached tree nodes */ + __u16 cached_slots; + /* The number of valid transactions in journal */ + __u16 journal_transactions; + + unsigned int blocks[MAX_HEIGHT]; + unsigned int next_key_nr[MAX_HEIGHT]; +}; + +/* The cached s+tree blocks in FSYS_BUF, see below + * for a more detailed description. + */ +#define ROOT ((char *)FSYS_BUF) +#define CACHE(i) (ROOT + ((i) << INFO->fullblocksize_shift)) +#define LEAF CACHE (DISK_LEAF_NODE_LEVEL) + +#define BLOCKHEAD(cache) ((struct block_head *) cache) +#define ITEMHEAD ((struct item_head *) ((char *) LEAF + BLKH_SIZE)) +#define KEY(cache) ((struct key *) ((char *) cache + BLKH_SIZE)) +#define DC(cache) ((struct disk_child *) \ + ((char *) cache + BLKH_SIZE + KEY_SIZE * nr_item)) +/* The fsys_reiser_info block. + */ +#define INFO \ + ((struct fsys_reiser_info *) ((char *) FSYS_BUF + FSYSREISER_CACHE_SIZE)) +/* + * The journal cache. For each transaction it contains the number of + * blocks followed by the real block numbers of this transaction. + * + * If the block numbers of some transaction won't fit in this space, + * this list is stopped with a 0xffffffff marker and the remaining + * uncommitted transactions aren't cached. + */ +#define JOURNAL_START ((__u32 *) (INFO + 1)) +#define JOURNAL_END ((__u32 *) (FSYS_BUF + FSYS_BUFLEN)) + +static __inline__ int +is_power_of_two (unsigned long word) +{ + return (word & -word) == word; +} + +static int +journal_read (int block, int len, char *buffer) +{ + return devread ((INFO->journal_block + block) << INFO->blocksize_shift, + 0, len, buffer); +} + +/* Read a block from ReiserFS file system, taking the journal into + * account. If the block nr is in the journal, the block from the + * journal taken. + */ +static int +block_read (int blockNr, int start, int len, char *buffer) +{ + int transactions = INFO->journal_transactions; + int desc_block = INFO->journal_first_desc; + int journal_mask = INFO->journal_block_count - 1; + int translatedNr = blockNr; + __u32 *journal_table = JOURNAL_START; + while (transactions-- > 0) + { + int i = 0; + int j_len; + if (*journal_table != 0xffffffff) + { + /* Search for the blockNr in cached journal */ + j_len = *journal_table++; + while (i++ < j_len) + { + if (*journal_table++ == blockNr) + { + journal_table += j_len - i; + goto found; + } + } + } + else + { + /* This is the end of cached journal marker. The remaining + * transactions are still on disk. + */ + struct reiserfs_journal_desc desc; + struct reiserfs_journal_commit commit; + + if (! journal_read (desc_block, sizeof (desc), (char *) &desc)) + return 0; + + j_len = desc.j_len; + while (i < j_len && i < JOURNAL_TRANS_HALF) + if (desc.j_realblock[i++] == blockNr) + goto found; + + if (j_len >= JOURNAL_TRANS_HALF) + { + int commit_block = (desc_block + 1 + j_len) & journal_mask; + if (! journal_read (commit_block, + sizeof (commit), (char *) &commit)) + return 0; + while (i < j_len) + if (commit.j_realblock[i++ - JOURNAL_TRANS_HALF] == blockNr) + goto found; + } + } + goto not_found; + + found: + translatedNr = INFO->journal_block + ((desc_block + i) & journal_mask); +#ifdef REISERDEBUG + printf ("block_read: block %d is mapped to journal block %d.\n", + blockNr, translatedNr - INFO->journal_block); +#endif + /* We must continue the search, as this block may be overwritten + * in later transactions. + */ + not_found: + desc_block = (desc_block + 2 + j_len) & journal_mask; + } + return devread (translatedNr << INFO->blocksize_shift, start, len, buffer); +} + +/* Init the journal data structure. We try to cache as much as + * possible in the JOURNAL_START-JOURNAL_END space, but if it is full + * we can still read the rest from the disk on demand. + * + * The first number of valid transactions and the descriptor block of the + * first valid transaction are held in INFO. The transactions are all + * adjacent, but we must take care of the journal wrap around. + */ +static int +journal_init (void) +{ + unsigned int block_count = INFO->journal_block_count; + unsigned int desc_block; + unsigned int commit_block; + unsigned int next_trans_id; + struct reiserfs_journal_header header; + struct reiserfs_journal_desc desc; + struct reiserfs_journal_commit commit; + __u32 *journal_table = JOURNAL_START; + + journal_read (block_count, sizeof (header), (char *) &header); + desc_block = header.j_first_unflushed_offset; + if (desc_block >= block_count) + return 0; + + INFO->journal_first_desc = desc_block; + next_trans_id = header.j_last_flush_trans_id + 1; + +#ifdef REISERDEBUG + printf ("journal_init: last flushed %d\n", + header.j_last_flush_trans_id); +#endif + + while (1) + { + journal_read (desc_block, sizeof (desc), (char *) &desc); + if (substring (JOURNAL_DESC_MAGIC, desc.j_magic) > 0 + || desc.j_trans_id != next_trans_id + || desc.j_mount_id != header.j_mount_id) + /* no more valid transactions */ + break; + + commit_block = (desc_block + desc.j_len + 1) & (block_count - 1); + journal_read (commit_block, sizeof (commit), (char *) &commit); + if (desc.j_trans_id != commit.j_trans_id + || desc.j_len != commit.j_len) + /* no more valid transactions */ + break; + +#ifdef REISERDEBUG + printf ("Found valid transaction %d/%d at %d.\n", + desc.j_trans_id, desc.j_mount_id, desc_block); +#endif + + next_trans_id++; + if (journal_table < JOURNAL_END) + { + if ((journal_table + 1 + desc.j_len) >= JOURNAL_END) + { + /* The table is almost full; mark the end of the cached + * journal.*/ + *journal_table = 0xffffffff; + journal_table = JOURNAL_END; + } + else + { + int i; + /* Cache the length and the realblock numbers in the table. + * The block number of descriptor can easily be computed. + * and need not to be stored here. + */ + *journal_table++ = desc.j_len; + for (i = 0; i < desc.j_len && i < JOURNAL_TRANS_HALF; i++) + { + *journal_table++ = desc.j_realblock[i]; +#ifdef REISERDEBUG + printf ("block %d is in journal %d.\n", + desc.j_realblock[i], desc_block); +#endif + } + for ( ; i < desc.j_len; i++) + { + *journal_table++ = commit.j_realblock[i-JOURNAL_TRANS_HALF]; +#ifdef REISERDEBUG + printf ("block %d is in journal %d.\n", + commit.j_realblock[i-JOURNAL_TRANS_HALF], + desc_block); +#endif + } + } + } + desc_block = (commit_block + 1) & (block_count - 1); + } +#ifdef REISERDEBUG + printf ("Transaction %d/%d at %d isn't valid.\n", + desc.j_trans_id, desc.j_mount_id, desc_block); +#endif + + INFO->journal_transactions + = next_trans_id - header.j_last_flush_trans_id - 1; + return errnum == 0; +} + +/* check filesystem types and read superblock into memory buffer */ +int +reiserfs_mount (void) +{ + struct reiserfs_super_block super; + int superblock = REISERFS_DISK_OFFSET_IN_BYTES >> SECTOR_BITS; + + if (part_length < superblock + (sizeof (super) >> SECTOR_BITS) + || ! devread (superblock, 0, sizeof (struct reiserfs_super_block), + (char *) &super) + || (substring (REISER2FS_SUPER_MAGIC_STRING, super.s_magic) > 0 + && substring (REISERFS_SUPER_MAGIC_STRING, super.s_magic) > 0) + || (/* check that this is not a copy inside the journal log */ + super.s_journal_block * super.s_blocksize + <= REISERFS_DISK_OFFSET_IN_BYTES)) + { + /* Try old super block position */ + superblock = REISERFS_OLD_DISK_OFFSET_IN_BYTES >> SECTOR_BITS; + if (part_length < superblock + (sizeof (super) >> SECTOR_BITS) + || ! devread (superblock, 0, sizeof (struct reiserfs_super_block), + (char *) &super)) + return 0; + + if (substring (REISER2FS_SUPER_MAGIC_STRING, super.s_magic) > 0 + && substring (REISERFS_SUPER_MAGIC_STRING, super.s_magic) > 0) + { + /* pre journaling super block ? */ + if (substring (REISERFS_SUPER_MAGIC_STRING, + (char*) ((char *) &super + 20)) > 0) + return 0; + + super.s_blocksize = REISERFS_OLD_BLOCKSIZE; + super.s_journal_block = 0; + super.s_version = 0; + } + } + + /* check the version number. */ + if (super.s_version > REISERFS_MAX_SUPPORTED_VERSION) + return 0; + + INFO->version = super.s_version; + INFO->blocksize = super.s_blocksize; + INFO->fullblocksize_shift = log2 (super.s_blocksize); + INFO->blocksize_shift = INFO->fullblocksize_shift - SECTOR_BITS; + INFO->cached_slots = + (FSYSREISER_CACHE_SIZE >> INFO->fullblocksize_shift) - 1; + +#ifdef REISERDEBUG + printf ("reiserfs_mount: version=%d, blocksize=%d\n", + INFO->version, INFO->blocksize); +#endif /* REISERDEBUG */ + + /* Clear node cache. */ + memset (INFO->blocks, 0, sizeof (INFO->blocks)); + + if (super.s_blocksize < FSYSREISER_MIN_BLOCKSIZE + || super.s_blocksize > FSYSREISER_MAX_BLOCKSIZE + || (SECTOR_SIZE << INFO->blocksize_shift) != super.s_blocksize) + return 0; + + /* Initialize journal code. If something fails we end with zero + * journal_transactions, so we don't access the journal at all. + */ + INFO->journal_transactions = 0; + if (super.s_journal_block != 0 && super.s_journal_dev == 0) + { + INFO->journal_block = super.s_journal_block; + INFO->journal_block_count = super.s_journal_size; + if (is_power_of_two (INFO->journal_block_count)) + journal_init (); + + /* Read in super block again, maybe it is in the journal */ + block_read (superblock >> INFO->blocksize_shift, + 0, sizeof (struct reiserfs_super_block), (char *) &super); + } + + if (! block_read (super.s_root_block, 0, INFO->blocksize, (char*) ROOT)) + return 0; + + INFO->tree_depth = BLOCKHEAD (ROOT)->blk_level; + +#ifdef REISERDEBUG + printf ("root read_in: block=%d, depth=%d\n", + super.s_root_block, INFO->tree_depth); +#endif /* REISERDEBUG */ + + if (INFO->tree_depth >= MAX_HEIGHT) + return 0; + if (INFO->tree_depth == DISK_LEAF_NODE_LEVEL) + { + /* There is only one node in the whole filesystem, + * which is simultanously leaf and root */ + memcpy (LEAF, ROOT, INFO->blocksize); + } + return 1; +} + +/***************** TREE ACCESSING METHODS *****************************/ + +/* I assume you are familiar with the ReiserFS tree, if not go to + * http://www.namesys.com/content_table.html + * + * My tree node cache is organized as following + * 0 ROOT node + * 1 LEAF node (if the ROOT is also a LEAF it is copied here + * 2-n other nodes on current path from bottom to top. + * if there is not enough space in the cache, the top most are + * omitted. + * + * I have only two methods to find a key in the tree: + * search_stat(dir_id, objectid) searches for the stat entry (always + * the first entry) of an object. + * next_key() gets the next key in tree order. + * + * This means, that I can only sequential reads of files are + * efficient, but this really doesn't hurt for grub. + */ + +/* Read in the node at the current path and depth into the node cache. + * You must set INFO->blocks[depth] before. + */ +static char * +read_tree_node (unsigned int blockNr, int depth) +{ + char* cache = CACHE(depth); + int num_cached = INFO->cached_slots; + if (depth < num_cached) + { + /* This is the cached part of the path. Check if same block is + * needed. + */ + if (blockNr == INFO->blocks[depth]) + return cache; + } + else + cache = CACHE(num_cached); + +#ifdef REISERDEBUG + printf (" next read_in: block=%d (depth=%d)\n", + blockNr, depth); +#endif /* REISERDEBUG */ + if (! block_read (blockNr, 0, INFO->blocksize, cache)) + return NULL; + /* Make sure it has the right node level */ + if (BLOCKHEAD (cache)->blk_level != depth) + { + errnum = ERR_FSYS_CORRUPT; + return NULL; + } + + INFO->blocks[depth] = blockNr; + return cache; +} + +/* Get the next key, i.e. the key following the last retrieved key in + * tree order. INFO->current_ih and + * INFO->current_info are adapted accordingly. */ +static int +next_key (void) +{ + int depth; + struct item_head *ih = INFO->current_ih + 1; + char *cache; + +#ifdef REISERDEBUG + printf ("next_key:\n old ih: key %d:%d:%d:%d version:%d\n", + INFO->current_ih->ih_key.k_dir_id, + INFO->current_ih->ih_key.k_objectid, + INFO->current_ih->ih_key.u.v1.k_offset, + INFO->current_ih->ih_key.u.v1.k_uniqueness, + INFO->current_ih->ih_version); +#endif /* REISERDEBUG */ + + if (ih == &ITEMHEAD[BLOCKHEAD (LEAF)->blk_nr_item]) + { + depth = DISK_LEAF_NODE_LEVEL; + /* The last item, was the last in the leaf node. + * Read in the next block + */ + do + { + if (depth == INFO->tree_depth) + { + /* There are no more keys at all. + * Return a dummy item with MAX_KEY */ + ih = (struct item_head *) &BLOCKHEAD (LEAF)->blk_right_delim_key; + goto found; + } + depth++; +#ifdef REISERDEBUG + printf (" depth=%d, i=%d\n", depth, INFO->next_key_nr[depth]); +#endif /* REISERDEBUG */ + } + while (INFO->next_key_nr[depth] == 0); + + if (depth == INFO->tree_depth) + cache = ROOT; + else if (depth <= INFO->cached_slots) + cache = CACHE (depth); + else + { + cache = read_tree_node (INFO->blocks[depth], depth); + if (! cache) + return 0; + } + + do + { + int nr_item = BLOCKHEAD (cache)->blk_nr_item; + int key_nr = INFO->next_key_nr[depth]++; +#ifdef REISERDEBUG + printf (" depth=%d, i=%d/%d\n", depth, key_nr, nr_item); +#endif /* REISERDEBUG */ + if (key_nr == nr_item) + /* This is the last item in this block, set the next_key_nr to 0 */ + INFO->next_key_nr[depth] = 0; + + cache = read_tree_node (DC (cache)[key_nr].dc_block_number, --depth); + if (! cache) + return 0; + } + while (depth > DISK_LEAF_NODE_LEVEL); + + ih = ITEMHEAD; + } + found: + INFO->current_ih = ih; + INFO->current_item = &LEAF[ih->ih_item_location]; +#ifdef REISERDEBUG + printf (" new ih: key %d:%d:%d:%d version:%d\n", + INFO->current_ih->ih_key.k_dir_id, + INFO->current_ih->ih_key.k_objectid, + INFO->current_ih->ih_key.u.v1.k_offset, + INFO->current_ih->ih_key.u.v1.k_uniqueness, + INFO->current_ih->ih_version); +#endif /* REISERDEBUG */ + return 1; +} + +/* preconditions: reiserfs_mount already executed, therefore + * INFO block is valid + * returns: 0 if error (errnum is set), + * nonzero iff we were able to find the key successfully. + * postconditions: on a nonzero return, the current_ih and + * current_item fields describe the key that equals the + * searched key. INFO->next_key contains the next key after + * the searched key. + * side effects: messes around with the cache. + */ +static int +search_stat (__u32 dir_id, __u32 objectid) +{ + char *cache; + int depth; + int nr_item; + int i; + struct item_head *ih; +#ifdef REISERDEBUG + printf ("search_stat:\n key %d:%d:0:0\n", dir_id, objectid); +#endif /* REISERDEBUG */ + + depth = INFO->tree_depth; + cache = ROOT; + + while (depth > DISK_LEAF_NODE_LEVEL) + { + struct key *key; + nr_item = BLOCKHEAD (cache)->blk_nr_item; + + key = KEY (cache); + + for (i = 0; i < nr_item; i++) + { + if (key->k_dir_id > dir_id + || (key->k_dir_id == dir_id + && (key->k_objectid > objectid + || (key->k_objectid == objectid + && (key->u.v1.k_offset + | key->u.v1.k_uniqueness) > 0)))) + break; + key++; + } + +#ifdef REISERDEBUG + printf (" depth=%d, i=%d/%d\n", depth, i, nr_item); +#endif /* REISERDEBUG */ + INFO->next_key_nr[depth] = (i == nr_item) ? 0 : i+1; + cache = read_tree_node (DC (cache)[i].dc_block_number, --depth); + if (! cache) + return 0; + } + + /* cache == LEAF */ + nr_item = BLOCKHEAD (LEAF)->blk_nr_item; + ih = ITEMHEAD; + for (i = 0; i < nr_item; i++) + { + if (ih->ih_key.k_dir_id == dir_id + && ih->ih_key.k_objectid == objectid + && ih->ih_key.u.v1.k_offset == 0 + && ih->ih_key.u.v1.k_uniqueness == 0) + { +#ifdef REISERDEBUG + printf (" depth=%d, i=%d/%d\n", depth, i, nr_item); +#endif /* REISERDEBUG */ + INFO->current_ih = ih; + INFO->current_item = &LEAF[ih->ih_item_location]; + return 1; + } + ih++; + } + errnum = ERR_FSYS_CORRUPT; + return 0; +} + +int +reiserfs_read (char *buf, int len) +{ + unsigned int blocksize; + unsigned int offset; + unsigned int to_read; + char *prev_buf = buf; + +#ifdef REISERDEBUG + printf ("reiserfs_read: filepos=%d len=%d, offset=%x:%x\n", + filepos, len, (__u64) IH_KEY_OFFSET (INFO->current_ih) - 1); +#endif /* REISERDEBUG */ + + if (INFO->current_ih->ih_key.k_objectid != INFO->fileinfo.k_objectid + || IH_KEY_OFFSET (INFO->current_ih) > filepos + 1) + { + search_stat (INFO->fileinfo.k_dir_id, INFO->fileinfo.k_objectid); + goto get_next_key; + } + + while (! errnum) + { + if (INFO->current_ih->ih_key.k_objectid != INFO->fileinfo.k_objectid) + break; + + offset = filepos - IH_KEY_OFFSET (INFO->current_ih) + 1; + blocksize = INFO->current_ih->ih_item_len; + +#ifdef REISERDEBUG + printf (" loop: filepos=%d len=%d, offset=%d blocksize=%d\n", + filepos, len, offset, blocksize); +#endif /* REISERDEBUG */ + + if (IH_KEY_ISTYPE(INFO->current_ih, TYPE_DIRECT) + && offset < blocksize) + { +#ifdef REISERDEBUG + printf ("direct_read: offset=%d, blocksize=%d\n", + offset, blocksize); +#endif /* REISERDEBUG */ + to_read = blocksize - offset; + if (to_read > len) + to_read = len; + + if (disk_read_hook != NULL) + { + disk_read_func = disk_read_hook; + + block_read (INFO->blocks[DISK_LEAF_NODE_LEVEL], + (INFO->current_item - LEAF + offset), to_read, buf); + + disk_read_func = NULL; + } + else + memcpy (buf, INFO->current_item + offset, to_read); + goto update_buf_len; + } + else if (IH_KEY_ISTYPE(INFO->current_ih, TYPE_INDIRECT)) + { + blocksize = (blocksize >> 2) << INFO->fullblocksize_shift; +#ifdef REISERDEBUG + printf ("indirect_read: offset=%d, blocksize=%d\n", + offset, blocksize); +#endif /* REISERDEBUG */ + + while (offset < blocksize) + { + __u32 blocknr = ((__u32 *) INFO->current_item) + [offset >> INFO->fullblocksize_shift]; + int blk_offset = offset & (INFO->blocksize-1); + + to_read = INFO->blocksize - blk_offset; + if (to_read > len) + to_read = len; + + disk_read_func = disk_read_hook; + + /* Journal is only for meta data. Data blocks can be read + * directly without using block_read + */ + devread (blocknr << INFO->blocksize_shift, + blk_offset, to_read, buf); + + disk_read_func = NULL; + update_buf_len: + len -= to_read; + buf += to_read; + offset += to_read; + filepos += to_read; + if (len == 0) + goto done; + } + } + get_next_key: + next_key (); + } + done: + return errnum ? 0 : buf - prev_buf; +} + + +/* preconditions: reiserfs_mount already executed, therefore + * INFO block is valid + * returns: 0 if error, nonzero iff we were able to find the file successfully + * postconditions: on a nonzero return, INFO->fileinfo contains the info + * of the file we were trying to look up, filepos is 0 and filemax is + * the size of the file. + */ +int +reiserfs_dir (char *dirname) +{ + struct reiserfs_de_head *de_head; + char *rest, ch; + __u32 dir_id, objectid, parent_dir_id = 0, parent_objectid = 0; +#ifndef STAGE1_5 + int do_possibilities = 0; +#endif /* ! STAGE1_5 */ + char linkbuf[PATH_MAX]; /* buffer for following symbolic links */ + int link_count = 0; + int mode; + + dir_id = REISERFS_ROOT_PARENT_OBJECTID; + objectid = REISERFS_ROOT_OBJECTID; + + while (1) + { +#ifdef REISERDEBUG + printf ("dirname=%s\n", dirname); +#endif /* REISERDEBUG */ + + /* Search for the stat info first. */ + if (! search_stat (dir_id, objectid)) + return 0; + +#ifdef REISERDEBUG + printf ("sd_mode=%x sd_size=%d\n", + ((struct stat_data *) INFO->current_item)->sd_mode, + ((struct stat_data *) INFO->current_item)->sd_size); +#endif /* REISERDEBUG */ + + mode = ((struct stat_data *) INFO->current_item)->sd_mode; + + /* If we've got a symbolic link, then chase it. */ + if (S_ISLNK (mode)) + { + int len; + if (++link_count > MAX_LINK_COUNT) + { + errnum = ERR_SYMLINK_LOOP; + return 0; + } + + /* Get the symlink size. */ + filemax = ((struct stat_data *) INFO->current_item)->sd_size; + + /* Find out how long our remaining name is. */ + len = 0; + while (dirname[len] && !isspace (dirname[len])) + len++; + + if (filemax + len > sizeof (linkbuf) - 1) + { + errnum = ERR_FILELENGTH; + return 0; + } + + /* Copy the remaining name to the end of the symlink data. + Note that DIRNAME and LINKBUF may overlap! */ + grub_memmove (linkbuf + filemax, dirname, len+1); + + INFO->fileinfo.k_dir_id = dir_id; + INFO->fileinfo.k_objectid = objectid; + filepos = 0; + if (! next_key () + || reiserfs_read (linkbuf, filemax) != filemax) + { + if (! errnum) + errnum = ERR_FSYS_CORRUPT; + return 0; + } + +#ifdef REISERDEBUG + printf ("symlink=%s\n", linkbuf); +#endif /* REISERDEBUG */ + + dirname = linkbuf; + if (*dirname == '/') + { + /* It's an absolute link, so look it up in root. */ + dir_id = REISERFS_ROOT_PARENT_OBJECTID; + objectid = REISERFS_ROOT_OBJECTID; + } + else + { + /* Relative, so look it up in our parent directory. */ + dir_id = parent_dir_id; + objectid = parent_objectid; + } + + /* Now lookup the new name. */ + continue; + } + + /* if we have a real file (and we're not just printing possibilities), + then this is where we want to exit */ + + if (! *dirname || isspace (*dirname)) + { + if (! S_ISREG (mode)) + { + errnum = ERR_BAD_FILETYPE; + return 0; + } + + filepos = 0; + filemax = ((struct stat_data *) INFO->current_item)->sd_size; + + /* If this is a new stat data and size is > 4GB set filemax to + * maximum + */ + if (INFO->current_ih->ih_version == ITEM_VERSION_2 + && ((struct stat_data *) INFO->current_item)->sd_size_hi > 0) + filemax = 0xffffffff; + + INFO->fileinfo.k_dir_id = dir_id; + INFO->fileinfo.k_objectid = objectid; + return next_key (); + } + + /* continue with the file/directory name interpretation */ + while (*dirname == '/') + dirname++; + if (! S_ISDIR (mode)) + { + errnum = ERR_BAD_FILETYPE; + return 0; + } + for (rest = dirname; (ch = *rest) && ! isspace (ch) && ch != '/'; rest++); + *rest = 0; + +# ifndef STAGE1_5 + if (print_possibilities && ch != '/') + do_possibilities = 1; +# endif /* ! STAGE1_5 */ + + while (1) + { + char *name_end; + int num_entries; + + if (! next_key ()) + return 0; +#ifdef REISERDEBUG + printf ("ih: key %d:%d:%d:%d version:%d\n", + INFO->current_ih->ih_key.k_dir_id, + INFO->current_ih->ih_key.k_objectid, + INFO->current_ih->ih_key.u.v1.k_offset, + INFO->current_ih->ih_key.u.v1.k_uniqueness, + INFO->current_ih->ih_version); +#endif /* REISERDEBUG */ + + if (INFO->current_ih->ih_key.k_objectid != objectid) + break; + + name_end = INFO->current_item + INFO->current_ih->ih_item_len; + de_head = (struct reiserfs_de_head *) INFO->current_item; + num_entries = INFO->current_ih->u.ih_entry_count; + while (num_entries > 0) + { + char *filename = INFO->current_item + de_head->deh_location; + char tmp = *name_end; + if ((de_head->deh_state & DEH_Visible)) + { + int cmp; + /* Directory names in ReiserFS are not null + * terminated. We write a temporary 0 behind it. + * NOTE: that this may overwrite the first block in + * the tree cache. That doesn't hurt as long as we + * don't call next_key () in between. + */ + *name_end = 0; + cmp = substring (dirname, filename); + *name_end = tmp; +# ifndef STAGE1_5 + if (do_possibilities) + { + if (cmp <= 0) + { + if (print_possibilities > 0) + print_possibilities = -print_possibilities; + *name_end = 0; + print_a_completion (filename); + *name_end = tmp; + } + } + else +# endif /* ! STAGE1_5 */ + if (cmp == 0) + goto found; + } + /* The beginning of this name marks the end of the next name. + */ + name_end = filename; + de_head++; + num_entries--; + } + } + +# ifndef STAGE1_5 + if (print_possibilities < 0) + return 1; +# endif /* ! STAGE1_5 */ + + errnum = ERR_FILE_NOT_FOUND; + *rest = ch; + return 0; + + found: + + *rest = ch; + dirname = rest; + + parent_dir_id = dir_id; + parent_objectid = objectid; + dir_id = de_head->deh_dir_id; + objectid = de_head->deh_objectid; + } +} + +int +reiserfs_embed (int *start_sector, int needed_sectors) +{ + struct reiserfs_super_block super; + int num_sectors; + + if (! devread (REISERFS_DISK_OFFSET_IN_BYTES >> SECTOR_BITS, 0, + sizeof (struct reiserfs_super_block), (char *) &super)) + return 0; + + *start_sector = 1; /* reserve first sector for stage1 */ + if ((substring (REISERFS_SUPER_MAGIC_STRING, super.s_magic) <= 0 + || substring (REISER2FS_SUPER_MAGIC_STRING, super.s_magic) <= 0) + && (/* check that this is not a super block copy inside + * the journal log */ + super.s_journal_block * super.s_blocksize + > REISERFS_DISK_OFFSET_IN_BYTES)) + num_sectors = (REISERFS_DISK_OFFSET_IN_BYTES >> SECTOR_BITS) - 1; + else + num_sectors = (REISERFS_OLD_DISK_OFFSET_IN_BYTES >> SECTOR_BITS) - 1; + + return (needed_sectors <= num_sectors); +} +#endif /* FSYS_REISERFS */ diff --git a/qemu/roms/openbios/fs/grubfs/fsys_ufs.c b/qemu/roms/openbios/fs/grubfs/fsys_ufs.c new file mode 100644 index 000000000..8e0a0f776 --- /dev/null +++ b/qemu/roms/openbios/fs/grubfs/fsys_ufs.c @@ -0,0 +1,391 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (c) 2000, 2001 Free Software Foundation, Inc. + * Copyright (c) 2005 Rink Springer + * + * This file is based on FreeBSD 5.4-RELEASE's /sys/boot/common/ufsread.c, + * and has some minor patches so it'll work with Cromwell/GRUB. + * + */ +/*- + * Copyright (c) 2002 McAfee, Inc. + * All rights reserved. + * + * This software was developed for the FreeBSD Project by Marshall + * Kirk McKusick and McAfee Research,, the Security Research Division of + * McAfee, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as + * part of the DARPA CHATS research program + * + * 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 AUTHOR 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 AUTHOR 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. + */ +/*- + * Copyright (c) 1998 Robert Nordier + * All rights reserved. + * + * Redistribution and use in source and binary forms are freely + * permitted provided that the above copyright notice and this + * paragraph and the following disclaimer are duplicated in all + * such forms. + * + * This software is provided "AS IS" and without any express or + * implied warranties, including, without limitation, the implied + * warranties of merchantability and fitness for a particular + * purpose. + */ +#ifdef FSYS_UFS + +#include "asm/types.h" + +#include "shared.h" +#include "filesys.h" + +#include "ufs_dinode.h" +#include "ufs_fs.h" + +#ifdef __i386__ +/* XXX: Revert to old (broken for over 1.5Tb filesystems) version of cgbase + (see sys/ufs/ffs/fs.h rev 1.39) so that i386 boot loader (boot2) can + support both UFS1 and UFS2 again. */ +#undef cgbase +#define cgbase(fs, c) ((ufs2_daddr_t)((fs)->fs_fpg * (c))) +#endif + +/* + * We use 4k `virtual' blocks for filesystem data, whatever the actual + * filesystem block size. FFS blocks are always a multiple of 4k. + */ +#define VBLKSHIFT 12 +#define VBLKSIZE (1 << VBLKSHIFT) +#define VBLKMASK (VBLKSIZE - 1) +#define DBPERVBLK (VBLKSIZE / DEV_BSIZE) +#define INDIRPERVBLK(fs) (NINDIR(fs) / ((fs)->fs_bsize >> VBLKSHIFT)) +#define IPERVBLK(fs) (INOPB(fs) / ((fs)->fs_bsize >> VBLKSHIFT)) +#define INO_TO_VBA(fs, ipervblk, x) \ + (fsbtodb(fs, cgimin(fs, ino_to_cg(fs, x))) + \ + (((x) % (fs)->fs_ipg) / (ipervblk) * DBPERVBLK)) +#define INO_TO_VBO(ipervblk, x) ((x) % ipervblk) +#define FS_TO_VBA(fs, fsb, off) (fsbtodb(fs, fsb) + \ + ((off) / VBLKSIZE) * DBPERVBLK) +#define FS_TO_VBO(fs, fsb, off) ((off) & VBLKMASK) + +/* Buffers that must not span a 64k boundary. */ +struct dmadat { + char blkbuf[VBLKSIZE]; /* filesystem blocks */ + char indbuf[VBLKSIZE]; /* indir blocks */ + char sbbuf[SBLOCKSIZE]; /* superblock */ + char secbuf[DEV_BSIZE]; /* for MBR/disklabel */ +}; +static struct dmadat *dmadat = (struct dmadat*)FSYS_BUF; + +#define SUPERBLOCK ((struct fs*)dmadat->sbbuf) + +ino_t lookup(const char *); +ssize_t fsread(ino_t, void *, size_t); + +static int dsk_meta; +static uint32_t fs_off; +static ino_t cur_ino = 0; + +static inline int +dskread (void* buf, unsigned lba, unsigned nblk) +{ + return !devread (lba, 0, nblk * DEV_BSIZE, buf) ? -1 : 0; +} + +#if defined(UFS2_ONLY) +#define DIP(field) dp2.field +#elif defined(UFS1_ONLY) +#define DIP(field) dp1.field +#else +#define DIP(field) fs->fs_magic == FS_UFS1_MAGIC ? dp1.field : dp2.field +#endif + +static __inline int +fsfind(const char *name, ino_t * ino) +{ + char buf[DEV_BSIZE]; + struct ufs_dirent *d; + char *s; + ssize_t n; +#ifndef UFS2_ONLY + static struct ufs1_dinode dp1; +#endif +#ifndef UFS1_ONLY + static struct ufs2_dinode dp2; +#endif + char* blkbuf = dmadat->blkbuf; + struct fs* fs = (struct fs *)dmadat->sbbuf; + + fs_off = 0; + while ((n = fsread(*ino, buf, DEV_BSIZE)) > 0) + for (s = buf; s < buf + DEV_BSIZE;) { + d = (void *)s; + if (!strcmp(name, d->d_name)) { + *ino = d->d_fileno; + + /* below is for grub, which wants the file size + */ + n = IPERVBLK(fs); + if (dskread(blkbuf, INO_TO_VBA(fs, n, (*ino)), DBPERVBLK)) + return -1; + n = INO_TO_VBO(n, (*ino)); +#if defined(UFS1_ONLY) + dp1 = ((struct ufs1_dinode *)blkbuf)[n]; +#elif defined(UFS2_ONLY) + dp2 = ((struct ufs2_dinode *)blkbuf)[n]; +#else + if (fs->fs_magic == FS_UFS1_MAGIC) + dp1 = ((struct ufs1_dinode *)blkbuf)[n]; + else + dp2 = ((struct ufs2_dinode *)blkbuf)[n]; +#endif + + filemax = DIP(di_size); + return d->d_type; + } + s += d->d_reclen; + } + return 0; +} + +ino_t +lookup(const char *path) +{ + char name[MAXNAMLEN + 1]; + const char *s; + ino_t ino; + ssize_t n; + int dt; + + ino = ROOTINO; + dt = DT_DIR; + name[0] = '/'; + name[1] = '\0'; + for (;;) { + if (*path == '/') + path++; + if (!*path) + break; + for (s = path; *s && *s != '/'; s++); + if ((n = s - path) > MAXNAMLEN) + return 0; + memcpy(name, path, n); + name[n] = 0; + if (dt != DT_DIR) { + printk("%s: not a directory.\n", name); + return (0); + } + if ((dt = fsfind(name, &ino)) <= 0) + break; + path = s; + } + return dt == DT_REG ? ino : 0; +} + +/* + * Possible superblock locations ordered from most to least likely. + */ +static const int sblock_try[] = SBLOCKSEARCH; + +ssize_t +fsread(ino_t inode, void *buf, size_t nbyte) +{ +#ifndef UFS2_ONLY + static struct ufs1_dinode dp1; +#endif +#ifndef UFS1_ONLY + static struct ufs2_dinode dp2; +#endif + static ino_t inomap; + char *blkbuf; + void *indbuf; + struct fs *fs; + char *s; + size_t n, nb, size, off, vboff; + ufs_lbn_t lbn; + ufs2_daddr_t addr, vbaddr; + static ufs2_daddr_t blkmap, indmap; + unsigned int u; + + + blkbuf = dmadat->blkbuf; + indbuf = dmadat->indbuf; + fs = (struct fs *)dmadat->sbbuf; + if (!dsk_meta) { + inomap = 0; + for (n = 0; sblock_try[n] != -1; n++) { + if (dskread(fs, sblock_try[n] / DEV_BSIZE, + SBLOCKSIZE / DEV_BSIZE)) + return -1; + if (( +#if defined(UFS1_ONLY) + fs->fs_magic == FS_UFS1_MAGIC +#elif defined(UFS2_ONLY) + (fs->fs_magic == FS_UFS2_MAGIC && + fs->fs_sblockloc == sblock_try[n]) +#else + fs->fs_magic == FS_UFS1_MAGIC || + (fs->fs_magic == FS_UFS2_MAGIC && + fs->fs_sblockloc == sblock_try[n]) +#endif + ) && + fs->fs_bsize <= MAXBSIZE && + fs->fs_bsize >= sizeof(struct fs)) + break; + } + if (sblock_try[n] == -1) { + printk("Not ufs\n"); + return -1; + } + dsk_meta++; + } + if (!inode) + return 0; + if (inomap != inode) { + n = IPERVBLK(fs); + if (dskread(blkbuf, INO_TO_VBA(fs, n, inode), DBPERVBLK)) + return -1; + n = INO_TO_VBO(n, inode); +#if defined(UFS1_ONLY) + dp1 = ((struct ufs1_dinode *)blkbuf)[n]; +#elif defined(UFS2_ONLY) + dp2 = ((struct ufs2_dinode *)blkbuf)[n]; +#else + if (fs->fs_magic == FS_UFS1_MAGIC) + dp1 = ((struct ufs1_dinode *)blkbuf)[n]; + else + dp2 = ((struct ufs2_dinode *)blkbuf)[n]; +#endif + inomap = inode; + fs_off = 0; + blkmap = indmap = 0; + } + s = buf; + size = DIP(di_size); + n = size - fs_off; + if (nbyte > n) + nbyte = n; + nb = nbyte; + while (nb) { + lbn = lblkno(fs, fs_off); + off = blkoff(fs, fs_off); + if (lbn < NDADDR) { + addr = DIP(di_db[lbn]); + } else if (lbn < NDADDR + NINDIR(fs)) { + n = INDIRPERVBLK(fs); + addr = DIP(di_ib[0]); + u = (unsigned int)(lbn - NDADDR) / (n * DBPERVBLK); + vbaddr = fsbtodb(fs, addr) + u; + if (indmap != vbaddr) { + if (dskread(indbuf, vbaddr, DBPERVBLK)) + return -1; + indmap = vbaddr; + } + n = (lbn - NDADDR) & (n - 1); +#if defined(UFS1_ONLY) + addr = ((ufs1_daddr_t *)indbuf)[n]; +#elif defined(UFS2_ONLY) + addr = ((ufs2_daddr_t *)indbuf)[n]; +#else + if (fs->fs_magic == FS_UFS1_MAGIC) + addr = ((ufs1_daddr_t *)indbuf)[n]; + else + addr = ((ufs2_daddr_t *)indbuf)[n]; +#endif + } else { + return -1; + } + vbaddr = fsbtodb(fs, addr) + (off >> VBLKSHIFT) * DBPERVBLK; + vboff = off & VBLKMASK; + n = sblksize(fs, size, lbn) - (off & ~VBLKMASK); + if (n > VBLKSIZE) + n = VBLKSIZE; + if (blkmap != vbaddr) { + if (dskread(blkbuf, vbaddr, n >> DEV_BSHIFT)) + return -1; + blkmap = vbaddr; + } + n -= vboff; + if (n > nb) + n = nb; + memcpy(s, blkbuf + vboff, n); + s += n; + fs_off += n; + nb -= n; + } + return nbyte; +} + +int +ufs_mount (void) +{ + int i, retval = 0; + + /* + * We don't care about stuff being in disklabels or not. If the magic + * matches, we're good to go. + */ + for (i = 0; sblock_try[i] != -1; ++i) + { + if (! (part_length < (sblock_try[i] + (SBLOCKSIZE / DEV_BSIZE)) + || ! devread (0, sblock_try[i], SBLOCKSIZE, (char *) SUPERBLOCK))) + { + if ( +#if defined(UFS1_ONLY) + SUPERBLOCK->fs_magic == FS_UFS1_MAGIC +#elif defined(UFS2_ONLY) + (SUPERBLOCK->fs_magic == FS_UFS2_MAGIC && + SUPERBLOCK->fs_sblockloc == sblock_try[i]) +#else + SUPERBLOCK->fs_magic == FS_UFS1_MAGIC || + (SUPERBLOCK->fs_magic == FS_UFS2_MAGIC && + SUPERBLOCK->fs_sblockloc == sblock_try[i]) +#endif + ) { + retval = 1; break; + } + } + } + return retval; +} + +int +ufs_read (char *buf, int len) +{ + return fsread(cur_ino, buf, len); +} + +int +ufs_dir (char *dirname) +{ + cur_ino = lookup(dirname); + return cur_ino & 0xffffffff; +} + +int +ufs_embed (int* start_sector, int needed_sectors) +{ + /* TODO; unused by Cromwell */ + return 0; +} + +#endif /* FSYS_UFS */ diff --git a/qemu/roms/openbios/fs/grubfs/fsys_vstafs.c b/qemu/roms/openbios/fs/grubfs/fsys_vstafs.c new file mode 100644 index 000000000..e06d3e73e --- /dev/null +++ b/qemu/roms/openbios/fs/grubfs/fsys_vstafs.c @@ -0,0 +1,254 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2001 Free Software Foundation, Inc. + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#ifdef FSYS_VSTAFS + +#include "shared.h" +#include "filesys.h" +#include "vstafs.h" + + +static void get_file_info (int sector); +static struct dir_entry *vstafs_readdir (long sector); +static struct dir_entry *vstafs_nextdir (void); + + +#define FIRST_SECTOR ((struct first_sector *) FSYS_BUF) +#define FILE_INFO ((struct fs_file *) (long) FIRST_SECTOR + 8192) +#define DIRECTORY_BUF ((struct dir_entry *) (long) FILE_INFO + 512) + +#define ROOT_SECTOR 1 + +/* + * In f_sector we store the sector number in which the information about + * the found file is. + */ +static int f_sector; + +int +vstafs_mount (void) +{ + int retval = 1; + + if( (((current_drive & 0x80) || (current_slice != 0)) + && current_slice != PC_SLICE_TYPE_VSTAFS) + || ! devread (0, 0, BLOCK_SIZE, (char *) FSYS_BUF) + || FIRST_SECTOR->fs_magic != 0xDEADFACE) + retval = 0; + + return retval; +} + +static void +get_file_info (int sector) +{ + devread (sector, 0, BLOCK_SIZE, (char *) FILE_INFO); +} + +static int curr_ext, current_direntry, current_blockpos; +static struct alloc *a1; + +static struct dir_entry * +vstafs_readdir (long sector) +{ + /* + * Get some information from the current directory + */ + get_file_info (sector); + if (FILE_INFO->type != 2) + { + errnum = ERR_FILE_NOT_FOUND; + return NULL; + } + + a1 = FILE_INFO->blocks; + curr_ext = 0; + devread (a1[curr_ext].a_start, 0, 512, (char *) DIRECTORY_BUF); + current_direntry = 11; + current_blockpos = 0; + + return &DIRECTORY_BUF[10]; +} + +static struct dir_entry * +vstafs_nextdir (void) +{ + if (current_direntry > 15) + { + current_direntry = 0; + if (++current_blockpos > (a1[curr_ext].a_len - 1)) + { + current_blockpos = 0; + curr_ext++; + } + + if (curr_ext < FILE_INFO->extents) + { + devread (a1[curr_ext].a_start + current_blockpos, 0, + 512, (char *) DIRECTORY_BUF); + } + else + { + /* errnum =ERR_FILE_NOT_FOUND; */ + return NULL; + } + } + + return &DIRECTORY_BUF[current_direntry++]; +} + +int +vstafs_dir (char *dirname) +{ + char *fn, ch; + struct dir_entry *d; + /* int l, i, s; */ + + /* + * Read in the entries of the current directory. + */ + f_sector = ROOT_SECTOR; + do + { + if (! (d = vstafs_readdir (f_sector))) + { + return 0; + } + + /* + * Find the file in the path + */ + while (*dirname == '/') dirname++; + fn = dirname; + while ((ch = *fn) && ch != '/' && ! isspace (ch)) fn++; + *fn = 0; + + do + { + if (d->name[0] == 0 || d->name[0] & 0x80) + continue; + +#ifndef STAGE1_5 + if (print_possibilities && ch != '/' + && (! *dirname || strcmp (dirname, d->name) <= 0)) + { + if (print_possibilities > 0) + print_possibilities = -print_possibilities; + + printf (" %s", d->name); + } +#endif + if (! grub_strcmp (dirname, d->name)) + { + f_sector = d->start; + get_file_info (f_sector); + filemax = FILE_INFO->len; + break; + } + } + while ((d =vstafs_nextdir ())); + + *(dirname = fn) = ch; + if (! d) + { + if (print_possibilities < 0) + { +#ifndef STAGE1_5 + putchar ('\n'); +#endif + return 1; + } + + errnum = ERR_FILE_NOT_FOUND; + return 0; + } + } + while (*dirname && ! isspace (ch)); + + return 1; +} + +int +vstafs_read (char *addr, int len) +{ + struct alloc *a2; + int size, ret = 0, offset, curr_len = 0; + int curr_ext2; + char extent; + int ext_size; + char *curr_pos; + + get_file_info (f_sector); + size = FILE_INFO->len-VSTAFS_START_DATA; + a2 = FILE_INFO->blocks; + + if (filepos > 0) + { + if (filepos < a2[0].a_len * 512 - VSTAFS_START_DATA) + { + offset = filepos + VSTAFS_START_DATA; + extent = 0; + curr_len = a2[0].a_len * 512 - offset - filepos; + } + else + { + ext_size = a2[0].a_len * 512 - VSTAFS_START_DATA; + offset = filepos - ext_size; + extent = 1; + do + { + curr_len -= ext_size; + offset -= ext_size; + ext_size = a2[extent+1].a_len * 512; + } + while (extent < FILE_INFO->extents && offset>ext_size); + } + } + else + { + offset = VSTAFS_START_DATA; + extent = 0; + curr_len = a2[0].a_len * 512 - offset; + } + + curr_pos = addr; + if (curr_len > len) + curr_len = len; + + for (curr_ext2=extent; + curr_ext2 < FILE_INFO->extents; + curr_len = a2[curr_ext].a_len * 512, curr_pos += curr_len, curr_ext2++) + { + ret += curr_len; + size -= curr_len; + if (size < 0) + { + ret += size; + curr_len += size; + } + + devread (a2[curr_ext2].a_start,offset, curr_len, curr_pos); + offset = 0; + } + + return ret; +} + +#endif /* FSYS_VSTAFS */ diff --git a/qemu/roms/openbios/fs/grubfs/fsys_xfs.c b/qemu/roms/openbios/fs/grubfs/fsys_xfs.c new file mode 100644 index 000000000..b082621c7 --- /dev/null +++ b/qemu/roms/openbios/fs/grubfs/fsys_xfs.c @@ -0,0 +1,639 @@ +/* fsys_xfs.c - an implementation for the SGI XFS file system */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2001,2002 Free Software Foundation, Inc. + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#ifdef FSYS_XFS + +#include "shared.h" +#include "filesys.h" +#include "xfs.h" + +#define MAX_LINK_COUNT 8 + +typedef struct xad { + xfs_fileoff_t offset; + xfs_fsblock_t start; + xfs_filblks_t len; +} xad_t; + +struct xfs_info { + int bsize; + int dirbsize; + int isize; + unsigned int agblocks; + int bdlog; + int blklog; + int inopblog; + int agblklog; + int agnolog; + unsigned int nextents; + xfs_daddr_t next; + xfs_daddr_t daddr; + xfs_dablk_t forw; + xfs_dablk_t dablk; + xfs_bmbt_rec_32_t *xt; + xfs_bmbt_ptr_t ptr0; + int btnode_ptr0_off; + int i8param; + int dirpos; + int dirmax; + int blkoff; + int fpos; + xfs_ino_t rootino; +}; + +static struct xfs_info xfs; + +#define dirbuf ((char *)FSYS_BUF) +#define filebuf ((char *)FSYS_BUF + 4096) +#define inode ((xfs_dinode_t *)((char *)FSYS_BUF + 8192)) +#define icore (inode->di_core) + +#define mask32lo(n) (((__uint32_t)1 << (n)) - 1) + +#define XFS_INO_MASK(k) ((__uint32_t)((1ULL << (k)) - 1)) +#define XFS_INO_OFFSET_BITS xfs.inopblog +#define XFS_INO_AGBNO_BITS xfs.agblklog +#define XFS_INO_AGINO_BITS (xfs.agblklog + xfs.inopblog) +#define XFS_INO_AGNO_BITS xfs.agnolog + +static inline xfs_agblock_t +agino2agbno (xfs_agino_t agino) +{ + return agino >> XFS_INO_OFFSET_BITS; +} + +static inline xfs_agnumber_t +ino2agno (xfs_ino_t ino) +{ + return ino >> XFS_INO_AGINO_BITS; +} + +static inline xfs_agino_t +ino2agino (xfs_ino_t ino) +{ + return ino & XFS_INO_MASK(XFS_INO_AGINO_BITS); +} + +static inline int +ino2offset (xfs_ino_t ino) +{ + return ino & XFS_INO_MASK(XFS_INO_OFFSET_BITS); +} + +static inline __uint16_t +le16 (__uint16_t x) +{ +#ifdef __i386__ + __asm__("xchgb %b0,%h0" \ + : "=q" (x) \ + : "0" (x)); \ + return x; +#else + return __be16_to_cpu(x); +#endif +} + +static inline __uint32_t +le32 (__uint32_t x) +{ +#ifdef __i386__ +#if 1 + /* 386 doesn't have bswap. So what. */ + __asm__("bswap %0" : "=r" (x) : "0" (x)); +#else + /* This is slower but this works on all x86 architectures. */ + __asm__("xchgb %b0, %h0" \ + "\n\troll $16, %0" \ + "\n\txchgb %b0, %h0" \ + : "=q" (x) : "0" (x)); +#endif + return x; +#else + return __be32_to_cpu(x); +#endif +} + +static inline __uint64_t +le64 (__uint64_t x) +{ + __uint32_t h = x >> 32; + __uint32_t l = x & ((1ULL<<32)-1); + return (((__uint64_t)le32(l)) << 32) | ((__uint64_t)(le32(h))); +} + + +static xfs_fsblock_t +xt_start (xfs_bmbt_rec_32_t *r) +{ + return (((xfs_fsblock_t)(le32 (r->l1) & mask32lo(9))) << 43) | + (((xfs_fsblock_t)le32 (r->l2)) << 11) | + (((xfs_fsblock_t)le32 (r->l3)) >> 21); +} + +static xfs_fileoff_t +xt_offset (xfs_bmbt_rec_32_t *r) +{ + return (((xfs_fileoff_t)le32 (r->l0) & + mask32lo(31)) << 23) | + (((xfs_fileoff_t)le32 (r->l1)) >> 9); +} + +static xfs_filblks_t +xt_len (xfs_bmbt_rec_32_t *r) +{ + return le32(r->l3) & mask32lo(21); +} + +static inline int +xfs_highbit32(__uint32_t v) +{ + int i; + + if (--v) { + for (i = 0; i < 31; i++, v >>= 1) { + if (v == 0) + return i; + } + } + return 0; +} + +static int +isinxt (xfs_fileoff_t key, xfs_fileoff_t offset, xfs_filblks_t len) +{ + return (key >= offset) ? (key < offset + len ? 1 : 0) : 0; +} + +static xfs_daddr_t +agb2daddr (xfs_agnumber_t agno, xfs_agblock_t agbno) +{ + return ((xfs_fsblock_t)agno*xfs.agblocks + agbno) << xfs.bdlog; +} + +static xfs_daddr_t +fsb2daddr (xfs_fsblock_t fsbno) +{ + return agb2daddr ((xfs_agnumber_t)(fsbno >> xfs.agblklog), + (xfs_agblock_t)(fsbno & mask32lo(xfs.agblklog))); +} + +#undef offsetof +#define offsetof(t,m) ((long)&(((t *)0)->m)) + +static inline int +btroot_maxrecs (void) +{ + int tmp = icore.di_forkoff ? (icore.di_forkoff << 3) : xfs.isize; + + return (tmp - sizeof(xfs_bmdr_block_t) - offsetof(xfs_dinode_t, di_u)) / + (sizeof (xfs_bmbt_key_t) + sizeof (xfs_bmbt_ptr_t)); +} + +static int +di_read (xfs_ino_t ino) +{ + xfs_agino_t agino; + xfs_agnumber_t agno; + xfs_agblock_t agbno; + xfs_daddr_t daddr; + int offset; + + agno = ino2agno (ino); + agino = ino2agino (ino); + agbno = agino2agbno (agino); + offset = ino2offset (ino); + daddr = agb2daddr (agno, agbno); + + devread (daddr, offset*xfs.isize, xfs.isize, (char *)inode); + + xfs.ptr0 = *(xfs_bmbt_ptr_t *) + (inode->di_u.di_c + sizeof(xfs_bmdr_block_t) + + btroot_maxrecs ()*sizeof(xfs_bmbt_key_t)); + + return 1; +} + +static void +init_extents (void) +{ + xfs_bmbt_ptr_t ptr0; + xfs_btree_lblock_t h; + + switch (icore.di_format) { + case XFS_DINODE_FMT_EXTENTS: + xfs.xt = inode->di_u.di_bmx; + xfs.nextents = le32 (icore.di_nextents); + break; + case XFS_DINODE_FMT_BTREE: + ptr0 = xfs.ptr0; + for (;;) { + xfs.daddr = fsb2daddr (le64(ptr0)); + devread (xfs.daddr, 0, + sizeof(xfs_btree_lblock_t), (char *)&h); + if (!h.bb_level) { + xfs.nextents = le16(h.bb_numrecs); + xfs.next = fsb2daddr (le64(h.bb_rightsib)); + xfs.fpos = sizeof(xfs_btree_block_t); + return; + } + devread (xfs.daddr, xfs.btnode_ptr0_off, + sizeof(xfs_bmbt_ptr_t), (char *)&ptr0); + } + } +} + +static xad_t * +next_extent (void) +{ + static xad_t xad; + + switch (icore.di_format) { + case XFS_DINODE_FMT_EXTENTS: + if (xfs.nextents == 0) + return NULL; + break; + case XFS_DINODE_FMT_BTREE: + if (xfs.nextents == 0) { + xfs_btree_lblock_t h; + if (xfs.next == 0) + return NULL; + xfs.daddr = xfs.next; + devread (xfs.daddr, 0, sizeof(xfs_btree_lblock_t), (char *)&h); + xfs.nextents = le16(h.bb_numrecs); + xfs.next = fsb2daddr (le64(h.bb_rightsib)); + xfs.fpos = sizeof(xfs_btree_block_t); + } + /* Yeah, I know that's slow, but I really don't care */ + devread (xfs.daddr, xfs.fpos, sizeof(xfs_bmbt_rec_t), filebuf); + xfs.xt = (xfs_bmbt_rec_32_t *)filebuf; + xfs.fpos += sizeof(xfs_bmbt_rec_32_t); + } + xad.offset = xt_offset (xfs.xt); + xad.start = xt_start (xfs.xt); + xad.len = xt_len (xfs.xt); + ++xfs.xt; + --xfs.nextents; + + return &xad; +} + +/* + * Name lies - the function reads only first 100 bytes + */ +static void +xfs_dabread (void) +{ + xad_t *xad; + xfs_fileoff_t offset;; + + init_extents (); + while ((xad = next_extent ())) { + offset = xad->offset; + if (isinxt (xfs.dablk, offset, xad->len)) { + devread (fsb2daddr (xad->start + xfs.dablk - offset), + 0, 100, dirbuf); + break; + } + } +} + +static inline xfs_ino_t +sf_ino (char *sfe, int namelen) +{ + void *p = sfe + namelen + 3; + + return (xfs.i8param == 0) + ? le64(*(xfs_ino_t *)p) : le32(*(__uint32_t *)p); +} + +static inline xfs_ino_t +sf_parent_ino (void) +{ + return (xfs.i8param == 0) + ? le64(*(xfs_ino_t *)(&inode->di_u.di_dir2sf.hdr.parent)) + : le32(*(__uint32_t *)(&inode->di_u.di_dir2sf.hdr.parent)); +} + +static inline int +roundup8 (int n) +{ + return ((n+7)&~7); +} + +static char * +next_dentry (xfs_ino_t *ino) +{ + int namelen = 1; + int toread; + static char *usual[2]; + static xfs_dir2_sf_entry_t *sfe; + char *name; + + if (!usual[0]) { + usual[0] = strdup("."); + usual[1] = strdup(".."); + } + name = usual[0]; + + if (xfs.dirpos >= xfs.dirmax) { + if (xfs.forw == 0) + return NULL; + xfs.dablk = xfs.forw; + xfs_dabread (); +#define h ((xfs_dir2_leaf_hdr_t *)dirbuf) + xfs.dirmax = le16 (h->count) - le16 (h->stale); + xfs.forw = le32 (h->info.forw); +#undef h + xfs.dirpos = 0; + } + + switch (icore.di_format) { + case XFS_DINODE_FMT_LOCAL: + switch (xfs.dirpos) { + case -2: + *ino = 0; + break; + case -1: + *ino = sf_parent_ino (); + ++name; + ++namelen; + sfe = (xfs_dir2_sf_entry_t *) + (inode->di_u.di_c + + sizeof(xfs_dir2_sf_hdr_t) + - xfs.i8param); + break; + default: + namelen = sfe->namelen; + *ino = sf_ino ((char *)sfe, namelen); + name = (char *)sfe->name; + sfe = (xfs_dir2_sf_entry_t *) + ((char *)sfe + namelen + 11 - xfs.i8param); + } + break; + case XFS_DINODE_FMT_BTREE: + case XFS_DINODE_FMT_EXTENTS: +#define dau ((xfs_dir2_data_union_t *)dirbuf) + for (;;) { + if (xfs.blkoff >= xfs.dirbsize) { + xfs.blkoff = sizeof(xfs_dir2_data_hdr_t); + filepos &= ~(xfs.dirbsize - 1); + filepos |= xfs.blkoff; + } + xfs_read (dirbuf, 4); + xfs.blkoff += 4; + if (dau->unused.freetag == XFS_DIR2_DATA_FREE_TAG) { + toread = roundup8 (le16(dau->unused.length)) - 4; + xfs.blkoff += toread; + filepos += toread; + continue; + } + break; + } + xfs_read ((char *)dirbuf + 4, 5); + *ino = le64 (dau->entry.inumber); + namelen = dau->entry.namelen; +#undef dau + toread = roundup8 (namelen + 11) - 9; + xfs_read (dirbuf, toread); + name = (char *)dirbuf; + xfs.blkoff += toread + 5; + } + ++xfs.dirpos; + name[namelen] = 0; + + return name; +} + +static char * +first_dentry (xfs_ino_t *ino) +{ + xfs.forw = 0; + switch (icore.di_format) { + case XFS_DINODE_FMT_LOCAL: + xfs.dirmax = inode->di_u.di_dir2sf.hdr.count; + xfs.i8param = inode->di_u.di_dir2sf.hdr.i8count ? 0 : 4; + xfs.dirpos = -2; + break; + case XFS_DINODE_FMT_EXTENTS: + case XFS_DINODE_FMT_BTREE: + filepos = 0; + xfs_read (dirbuf, sizeof(xfs_dir2_data_hdr_t)); + if (((xfs_dir2_data_hdr_t *)dirbuf)->magic == le32(XFS_DIR2_BLOCK_MAGIC)) { +#define tail ((xfs_dir2_block_tail_t *)dirbuf) + filepos = xfs.dirbsize - sizeof(*tail); + xfs_read (dirbuf, sizeof(*tail)); + xfs.dirmax = le32 (tail->count) - le32 (tail->stale); +#undef tail + } else { + xfs.dablk = (1ULL << 35) >> xfs.blklog; +#define h ((xfs_dir2_leaf_hdr_t *)dirbuf) +#define n ((xfs_da_intnode_t *)dirbuf) + for (;;) { + xfs_dabread (); + if ((n->hdr.info.magic == le16(XFS_DIR2_LEAFN_MAGIC)) + || (n->hdr.info.magic == le16(XFS_DIR2_LEAF1_MAGIC))) { + xfs.dirmax = le16 (h->count) - le16 (h->stale); + xfs.forw = le32 (h->info.forw); + break; + } + xfs.dablk = le32 (n->btree[0].before); + } +#undef n +#undef h + } + xfs.blkoff = sizeof(xfs_dir2_data_hdr_t); + filepos = xfs.blkoff; + xfs.dirpos = 0; + } + return next_dentry (ino); +} + +int +xfs_mount (void) +{ + xfs_sb_t super; + + if (!devread (0, 0, sizeof(super), (char *)&super) + || (le32(super.sb_magicnum) != XFS_SB_MAGIC) + || ((le16(super.sb_versionnum) + & XFS_SB_VERSION_NUMBITS) != XFS_SB_VERSION_4) ) { + return 0; + } + + xfs.bsize = le32 (super.sb_blocksize); + xfs.blklog = super.sb_blocklog; + xfs.bdlog = xfs.blklog - SECTOR_BITS; + xfs.rootino = le64 (super.sb_rootino); + xfs.isize = le16 (super.sb_inodesize); + xfs.agblocks = le32 (super.sb_agblocks); + xfs.dirbsize = xfs.bsize << super.sb_dirblklog; + + xfs.inopblog = super.sb_inopblog; + xfs.agblklog = super.sb_agblklog; + xfs.agnolog = xfs_highbit32 (le32(super.sb_agcount)); + + xfs.btnode_ptr0_off = + ((xfs.bsize - sizeof(xfs_btree_block_t)) / + (sizeof (xfs_bmbt_key_t) + sizeof (xfs_bmbt_ptr_t))) + * sizeof(xfs_bmbt_key_t) + sizeof(xfs_btree_block_t); + + return 1; +} + +int +xfs_read (char *buf, int len) +{ + xad_t *xad; + xfs_fileoff_t endofprev, endofcur, offset; + xfs_filblks_t xadlen; + int toread, startpos, endpos; + + if (icore.di_format == XFS_DINODE_FMT_LOCAL) { + grub_memmove (buf, inode->di_u.di_c + filepos, len); + filepos += len; + return len; + } + + startpos = filepos; + endpos = filepos + len; + endofprev = (xfs_fileoff_t)-1; + init_extents (); + while (len > 0 && (xad = next_extent ())) { + offset = xad->offset; + xadlen = xad->len; + if (isinxt (filepos >> xfs.blklog, offset, xadlen)) { + endofcur = (offset + xadlen) << xfs.blklog; + toread = (endofcur >= endpos) + ? len : (endofcur - filepos); + + disk_read_func = disk_read_hook; + devread (fsb2daddr (xad->start), + filepos - (offset << xfs.blklog), toread, buf); + disk_read_func = NULL; + + buf += toread; + len -= toread; + filepos += toread; + } else if (offset > endofprev) { + toread = ((offset << xfs.blklog) >= endpos) + ? len : ((offset - endofprev) << xfs.blklog); + len -= toread; + filepos += toread; + for (; toread; toread--) { + *buf++ = 0; + } + continue; + } + endofprev = offset + xadlen; + } + + return filepos - startpos; +} + +int +xfs_dir (char *dirname) +{ + xfs_ino_t ino, parent_ino, new_ino; + xfs_fsize_t di_size; + int di_mode; + int cmp, n, link_count; + char linkbuf[xfs.bsize]; + char *rest, *name, ch; + + parent_ino = ino = xfs.rootino; + link_count = 0; + for (;;) { + di_read (ino); + di_size = le64 (icore.di_size); + di_mode = le16 (icore.di_mode); + + if ((di_mode & IFMT) == IFLNK) { + if (++link_count > MAX_LINK_COUNT) { + errnum = ERR_SYMLINK_LOOP; + return 0; + } + if (di_size < xfs.bsize - 1) { + filepos = 0; + filemax = di_size; + n = xfs_read (linkbuf, filemax); + } else { + errnum = ERR_FILELENGTH; + return 0; + } + + ino = (linkbuf[0] == '/') ? xfs.rootino : parent_ino; + while (n < (xfs.bsize - 1) && (linkbuf[n++] = *dirname++)); + linkbuf[n] = 0; + dirname = linkbuf; + continue; + } + + if (!*dirname || isspace (*dirname)) { + if ((di_mode & IFMT) != IFREG) { + errnum = ERR_BAD_FILETYPE; + return 0; + } + filepos = 0; + filemax = di_size; + return 1; + } + + if ((di_mode & IFMT) != IFDIR) { + errnum = ERR_BAD_FILETYPE; + return 0; + } + + for (; *dirname == '/'; dirname++); + + for (rest = dirname; (ch = *rest) && !isspace (ch) && ch != '/'; rest++); + *rest = 0; + + name = first_dentry (&new_ino); + for (;;) { + cmp = (!*dirname) ? -1 : substring (dirname, name); +#ifndef STAGE1_5 + if (print_possibilities && ch != '/' && cmp <= 0) { + if (print_possibilities > 0) + print_possibilities = -print_possibilities; + print_a_completion (name); + } else +#endif + if (cmp == 0) { + parent_ino = ino; + if (new_ino) + ino = new_ino; + *(dirname = rest) = ch; + break; + } + name = next_dentry (&new_ino); + if (name == NULL) { + if (print_possibilities < 0) + return 1; + + errnum = ERR_FILE_NOT_FOUND; + *rest = ch; + return 0; + } + } + } +} + +#endif /* FSYS_XFS */ diff --git a/qemu/roms/openbios/fs/grubfs/glue.h b/qemu/roms/openbios/fs/grubfs/glue.h new file mode 100644 index 000000000..7f2129372 --- /dev/null +++ b/qemu/roms/openbios/fs/grubfs/glue.h @@ -0,0 +1,48 @@ +#ifndef __GLUE_H +#define __GLUE_H + +#include "asm/types.h" +#include "config.h" +#include "libc/byteorder.h" + +typedef uint64_t sector_t; + +int devopen(void); + +int devread(unsigned long sector, unsigned long byte_offset, + unsigned long byte_len, void *buf); + +int file_open(const char *filename); +int file_read(void *buf, unsigned long len); +int file_seek(unsigned long offset); +unsigned long file_size(void); +void file_close(void); + +int mount_fs(void); + +extern int using_devsize; + +/* + * some of the filesystem drivers don't correctly provide their + * prototypes. we fix this here so we can leave them untouched. + */ + +int ffs_mount (void); +int ffs_read (char *buf, int len); +int ffs_dir (char *dirname); +int ffs_embed (int *start_sector, int needed_sectors); + +int vstafs_mount (void); +int vstafs_dir (char *dirname); +int vstafs_read (char *addr, int len); + +int ntfs_mount (void); +int ntfs_dir (char *dirname); +int ntfs_read (char *addr, int len); + +int affs_mount (void); +int affs_dir (char *dirname); +int affs_read (char *addr, int len); + + +#endif /* FS_H */ diff --git a/qemu/roms/openbios/fs/grubfs/grubfs_fs.c b/qemu/roms/openbios/fs/grubfs/grubfs_fs.c new file mode 100644 index 000000000..acd2a6441 --- /dev/null +++ b/qemu/roms/openbios/fs/grubfs/grubfs_fs.c @@ -0,0 +1,398 @@ +/* + * /packages/grubfs-files + * + * grub vfs + * + * Copyright (C) 2004 Stefan Reinauer + * Copyright (C) 2004 Samuel Rydh + * Copyright (C) 2010 Mark Cave-Ayland + * + * inspired by HFS code from Samuel Rydh + * + * 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 + * + */ + +#include "config.h" +#include "libopenbios/bindings.h" +#include "fs/fs.h" +#include "filesys.h" +#include "glue.h" +#include "libc/diskio.h" +#include "libc/vsprintf.h" + +extern void grubfs_init( void ); + +/************************************************************************/ +/* grub GLOBALS (horrible... but difficult to fix) */ +/************************************************************************/ + +/* the grub drivers want these: */ +int filepos; +int filemax; +grub_error_t errnum; +char FSYS_BUF[FSYS_BUFLEN]; + +/* these are not even used by us, instead + * the grub fs drivers want them: + */ +int fsmax; +void (*disk_read_hook) (int, int, int); +void (*disk_read_func) (int, int, int); + + +/************************************************************************/ +/* filsystem table */ +/************************************************************************/ + +typedef struct fsys_entry { + const char *name; + int (*mount_func) (void); + int (*read_func) (char *buf, int len); + int (*dir_func) (char *dirname); + void (*close_func) (void); + int (*embed_func) (int *start_sector, int needed_sectors); +} fsys_entry_t; + +static const struct fsys_entry fsys_table[] = { +# ifdef CONFIG_FSYS_FAT + {"fat", fat_mount, fat_read, fat_dir, NULL, NULL}, +# endif +# ifdef CONFIG_FSYS_EXT2FS + {"ext2fs", ext2fs_mount, ext2fs_read, ext2fs_dir, NULL, NULL}, +# endif +# ifdef CONFIG_FSYS_MINIX + {"minix", minix_mount, minix_read, minix_dir, NULL, NULL}, +# endif +# ifdef CONFIG_FSYS_REISERFS + {"reiserfs", reiserfs_mount, reiserfs_read, reiserfs_dir, NULL, reiserfs_embed}, +# endif +# ifdef CONFIG_FSYS_JFS + {"jfs", jfs_mount, jfs_read, jfs_dir, NULL, jfs_embed}, +# endif +# ifdef CONFIG_FSYS_XFS + {"xfs", xfs_mount, xfs_read, xfs_dir, NULL, NULL}, +# endif +# ifdef CONFIG_FSYS_UFS + {"ufs", ufs_mount, ufs_read, ufs_dir, NULL, ufs_embed}, +# endif +# ifdef CONFIG_FSYS_ISO9660 + {"iso9660", iso9660_mount, iso9660_read, iso9660_dir, NULL, NULL}, +# endif +# ifdef CONFIG_FSYS_NTFS + {"ntfs", ntfs_mount, ntfs_read, ntfs_dir, NULL, NULL}, +# endif +# ifdef CONFIG_FSYS_AFFS + {"affs", affs_mount, affs_read, affs_dir, NULL, NULL}, +# endif +}; + +/* We don't provide a file search mechanism (yet) */ +typedef struct { + unsigned long pos; + unsigned long len; + const char *path; +} grubfile_t; + +typedef struct { + const struct fsys_entry *fsys; + grubfile_t *fd; + int dev_fd; + long long offset; /* Offset added onto each device read; should only ever be non-zero + when probing a partition for a filesystem */ +} grubfs_t; + +typedef struct { + grubfs_t *gfs; +} grubfs_info_t; + +/* Static block and global pointer required for I/O glue */ +static grubfs_t dummy_fs; +static grubfs_t *curfs = &dummy_fs; + +DECLARE_NODE( grubfs, 0, sizeof(grubfs_info_t), "+/packages/grubfs-files" ); + + +/************************************************************************/ +/* I/O glue (called by grub source) */ +/************************************************************************/ + +int +devread( unsigned long sector, unsigned long byte_offset, + unsigned long byte_len, void *buf ) +{ + long long offs = (long long)sector * 512 + byte_offset; + +#ifdef CONFIG_DEBUG_FS + //printk("devread s=%x buf=%x, fd=%x\n",sector, buf, curfs->dev_fd); +#endif + + if( !curfs ) { +#ifdef CONFIG_DEBUG_FS + printk("devread: fsys == NULL!\n"); +#endif + return -1; + } + + if( seek_io(curfs->dev_fd, offs + curfs->offset) ) { +#ifdef CONFIG_DEBUG_FS + printk("seek failure\n"); +#endif + return -1; + } + return (read_io(curfs->dev_fd, buf, byte_len) == byte_len) ? 1:0; +} + +int +file_read( void *buf, unsigned long len ) +{ + if (filepos < 0 || filepos > filemax) + filepos = filemax; + if (len > filemax-filepos) + len = filemax - filepos; + errnum = 0; + return curfs->fsys->read_func( buf, len ); +} + + +/************************************************************************/ +/* Standard package methods */ +/************************************************************************/ + +/* ( -- success? ) */ +static void +grubfs_files_open( grubfs_info_t *mi ) +{ + int fd, i; + char *path = my_args_copy(); + char *s; + + fd = open_ih( my_parent() ); + if ( fd == -1 ) { + free( path ); + RET( 0 ); + } + + mi->gfs = &dummy_fs; + + for (i = 0; i < sizeof(fsys_table)/sizeof(fsys_table[0]); i++) { +#ifdef CONFIG_DEBUG_FS + printk("Trying %s\n", fsys_table[i].name); +#endif + if (fsys_table[i].mount_func()) { + const fsys_entry_t *fsys = &fsys_table[i]; +#ifdef CONFIG_DEBUG_FS + printk("Mounted %s\n", fsys->name); +#endif + mi->gfs = malloc(sizeof(grubfs_t)); + mi->gfs->fsys = fsys; + mi->gfs->dev_fd = fd; + mi->gfs->offset = 0; + + s = path; + while (*s) { + if(*s=='\\') *s='/'; + s++; + } +#ifdef CONFIG_DEBUG_FS + printk("Path=%s\n",path); +#endif + if (!mi->gfs->fsys->dir_func((char *) path)) { + forth_printf("File not found\n"); + RET( 0 ); + } + + mi->gfs->fd = malloc(sizeof(grubfile_t)); + mi->gfs->fd->pos = filepos; + mi->gfs->fd->len = filemax; + mi->gfs->fd->path = strdup(path); + + RET( -1 ); + } + } +#ifdef CONFIG_DEBUG_FS + printk("Unknown filesystem type\n"); +#endif + + RET( 0 ); +} + +/* ( -- ) */ +static void +grubfs_files_close( grubfs_info_t *mi ) +{ + grubfile_t *gf = mi->gfs->fd; + + if (gf->path) + free((void *)(gf->path)); + free(gf); + + filepos = 0; + filemax = 0; +} + +/* ( buf len -- actlen ) */ +static void +grubfs_files_read( grubfs_info_t *mi ) +{ + int count = POP(); + char *buf = (char *)cell2pointer(POP()); + + grubfile_t *file = mi->gfs->fd; + int ret; + + filepos = file->pos; + filemax = file->len; + + if (count > filemax - filepos) + count = filemax - filepos; + + ret = mi->gfs->fsys->read_func(buf, count); + + file->pos = filepos; + + RET( ret ); +} + +/* ( pos.d -- status ) */ +static void +grubfs_files_seek( grubfs_info_t *mi ) +{ + long long pos = DPOP(); + int offs = (int)pos; + int whence = SEEK_SET; + + grubfile_t *file = mi->gfs->fd; + unsigned long newpos; + + switch( whence ) { + case SEEK_END: + if (offs < 0 && (unsigned long) -offs > file->len) + newpos = 0; + else + newpos = file->len + offs; + break; + default: + case SEEK_SET: + newpos = (offs < 0) ? 0 : offs; + break; + } + + if (newpos > file->len) + newpos = file->len; + + file->pos = newpos; + + if (newpos) + RET( -1 ); + else + RET( 0 ); +} + +/* ( addr -- size ) */ +static void +grubfs_files_load( grubfs_info_t *mi ) +{ + char *buf = (char *)cell2pointer(POP()); + int count, ret; + + grubfile_t *file = mi->gfs->fd; + count = file->len; + + ret = mi->gfs->fsys->read_func(buf, count); + file->pos = filepos; + + RET( ret ); +} + +/* ( -- cstr ) */ +static void +grubfs_files_get_path( grubfs_info_t *mi ) +{ + grubfile_t *file = mi->gfs->fd; + const char *path = file->path; + + RET( pointer2cell(strdup(path)) ); +} + +/* ( -- cstr ) */ +static void +grubfs_files_get_fstype( grubfs_info_t *mi ) +{ + grubfs_t *gfs = mi->gfs; + + PUSH( pointer2cell(strdup(gfs->fsys->name)) ); +} + + +/* static method, ( pos.d ih -- flag? ) */ +static void +grubfs_files_probe( grubfs_info_t *dummy ) +{ + ihandle_t ih = POP_ih(); + long long offs = DPOP(); + int i; + + curfs->dev_fd = open_ih(ih); + if (curfs->dev_fd == -1) { + RET( -1 ); + } + curfs->offset = offs; + + for (i = 0; i < sizeof(fsys_table)/sizeof(fsys_table[0]); i++) { +#ifdef CONFIG_DEBUG_FS + printk("Probing for %s\n", fsys_table[i].name); +#endif + if (fsys_table[i].mount_func()) { + RET( -1 ); + } + } + +#ifdef CONFIG_DEBUG_FS + printk("Unknown filesystem type\n"); +#endif + + close_io(curfs->dev_fd); + + RET ( 0 ); +} + +/* static method, ( pathstr len ihandle -- ) */ +static void +grubfs_files_dir( grubfs_info_t *dummy ) +{ + forth_printf("dir method not implemented for grubfs filesystem\n"); + POP(); + POP(); + POP(); +} + +static void +grubfs_initializer( grubfs_info_t *dummy ) +{ + fword("register-fs-package"); +} + +NODE_METHODS( grubfs ) = { + { "probe", grubfs_files_probe }, + { "open", grubfs_files_open }, + { "close", grubfs_files_close }, + { "read", grubfs_files_read }, + { "seek", grubfs_files_seek }, + { "load", grubfs_files_load }, + { "dir", grubfs_files_dir }, + + /* special */ + { "get-path", grubfs_files_get_path }, + { "get-fstype", grubfs_files_get_fstype }, + + { NULL, grubfs_initializer }, +}; + +void +grubfs_init( void ) +{ + REGISTER_NODE( grubfs ); +} diff --git a/qemu/roms/openbios/fs/grubfs/iso9660.h b/qemu/roms/openbios/fs/grubfs/iso9660.h new file mode 100644 index 000000000..6423a8f68 --- /dev/null +++ b/qemu/roms/openbios/fs/grubfs/iso9660.h @@ -0,0 +1,167 @@ +/* + * ISO 9660 filesystem backend for GRUB (GRand Unified Bootloader) + * including Rock Ridge Extensions support + * + * Copyright (C) 1998, 1999 Kousuke Takai <tak@kmc.kyoto-u.ac.jp> + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +/* + * References: + * linux/fs/isofs/rock.[ch] + * mkisofs-1.11.1/diag/isoinfo.c + * mkisofs-1.11.1/iso9660.h + * (all are written by Eric Youngdale) + */ + +/* + * Modified by SONE Takeshi to work with FILO + */ + +#ifndef _ISO9660_H_ +#define _ISO9660_H_ + +#define ISO_SECTOR_BITS (11) +#define ISO_SECTOR_SIZE (1<<ISO_SECTOR_BITS) + +#define ISO_REGULAR 1 /* regular file */ +#define ISO_DIRECTORY 2 /* directory */ +#define ISO_OTHER 0 /* other file (with Rock Ridge) */ + +#define RR_FLAG_PX 0x01 /* have POSIX file attributes */ +#define RR_FLAG_NM 0x08 /* have alternate file name */ + +/* POSIX file attributes for Rock Ridge extensions */ +#define POSIX_S_IFMT 0xF000 +#define POSIX_S_IFREG 0x8000 +#define POSIX_S_IFDIR 0x4000 + +/* volume descriptor types */ +#define ISO_VD_PRIMARY 1 +#define ISO_VD_END 255 + +#define ISO_STANDARD_ID "CD001" + +#ifndef ASM_FILE + +typedef union { + uint8_t l,b; +} iso_8bit_t; + +typedef struct __iso_16bit { + uint16_t l, b; +} iso_16bit_t; + +typedef struct __iso_32bit { + uint32_t l, b; +} iso_32bit_t; + +typedef uint8_t iso_date_t[7]; + +struct iso_directory_record { + iso_8bit_t length; + iso_8bit_t ext_attr_length; + iso_32bit_t extent; + iso_32bit_t size; + iso_date_t date; + iso_8bit_t flags; + iso_8bit_t file_unit_size; + iso_8bit_t interleave; + iso_16bit_t volume_seq_number; + iso_8bit_t name_len; + uint8_t name[1]; +} __attribute__ ((packed)); + +struct iso_primary_descriptor { + iso_8bit_t type; + uint8_t id[5]; + iso_8bit_t version; + uint8_t _unused1[1]; + uint8_t system_id[32]; + uint8_t volume_id[32]; + uint8_t _unused2[8]; + iso_32bit_t volume_space_size; + uint8_t _unused3[32]; + iso_16bit_t volume_set_size; + iso_16bit_t volume_seq_number; + iso_16bit_t logical_block_size; + iso_32bit_t path_table_size; + uint8_t type_l_path_table[4]; + uint8_t opt_type_l_path_table[4]; + uint8_t type_m_path_table[4]; + uint8_t opt_type_m_path_table[4]; + struct iso_directory_record root_directory_record; + uint8_t volume_set_id[128]; + uint8_t publisher_id[128]; + uint8_t preparer_id[128]; + uint8_t application_id[128]; + uint8_t copyright_file_id[37]; + uint8_t abstract_file_id[37]; + uint8_t bibliographic_file_id[37]; + uint8_t creation_date[17]; + uint8_t modification_date[17]; + uint8_t expiration_date[17]; + uint8_t effective_date[17]; + iso_8bit_t file_structure_version; + uint8_t _unused4[1]; + uint8_t application_data[512]; + uint8_t _unused5[653]; +} __attribute__ ((packed)); + +struct rock_ridge { + uint16_t signature; + uint8_t len; + uint8_t version; + union { + struct CE { + iso_32bit_t extent; + iso_32bit_t offset; + iso_32bit_t size; + } ce; + struct NM { + iso_8bit_t flags; + uint8_t name[0]; + } nm; + struct PX { + iso_32bit_t mode; + iso_32bit_t nlink; + iso_32bit_t uid; + iso_32bit_t gid; + } px; + struct RR { + iso_8bit_t flags; + } rr; + } u; +} __attribute__ ((packed)); + +typedef union RR_ptr { + struct rock_ridge *rr; + char *ptr; + int i; +} RR_ptr_t; + +#define CHECK2(ptr, c1, c2) \ + (*(unsigned char *)(ptr) == (c1) && \ + *((unsigned char *)(ptr) + 1) == (c2)) +#define CHECK4(ptr, c1, c2, c3, c4) \ + (*(unsigned char *)(ptr) == (c1) && \ + *((unsigned char *)(ptr) + 1) == (c2) && \ + *((unsigned char *)(ptr) + 2) == (c3) && \ + *((unsigned char *)(ptr) + 3) == (c4)) + +#endif /* !ASM_FILE */ + +#endif /* _ISO9660_H_ */ diff --git a/qemu/roms/openbios/fs/grubfs/jfs.h b/qemu/roms/openbios/fs/grubfs/jfs.h new file mode 100644 index 000000000..afe7263d2 --- /dev/null +++ b/qemu/roms/openbios/fs/grubfs/jfs.h @@ -0,0 +1,604 @@ +/* jfs.h - an extractions from linux/include/linux/jfs/jfs* into one file */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2000 International Business Machines Corp. + * Copyright (C) 2001 Free Software Foundation, Inc. + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#ifndef _JFS_H_ +#define _JFS_H_ + +/* those are from jfs_filsys.h */ + +/* + * file system option (superblock flag) + */ +/* platform option (conditional compilation) */ +#define JFS_AIX 0x80000000 /* AIX support */ +/* POSIX name/directory support */ + +#define JFS_OS2 0x40000000 /* OS/2 support */ +/* case-insensitive name/directory support */ + +#define JFS_LINUX 0x10000000 /* Linux support */ +/* case-sensitive name/directory support */ + +/* directory option */ +#define JFS_UNICODE 0x00000001 /* unicode name */ + +/* bba */ +#define JFS_SWAP_BYTES 0x00100000 /* running on big endian computer */ + + +/* + * buffer cache configuration + */ +/* page size */ +#ifdef PSIZE +#undef PSIZE +#endif +#define PSIZE 4096 /* page size (in byte) */ + +/* + * fs fundamental size + * + * PSIZE >= file system block size >= PBSIZE >= DISIZE + */ +#define PBSIZE 512 /* physical block size (in byte) */ +#define DISIZE 512 /* on-disk inode size (in byte) */ +#define L2DISIZE 9 +#define INOSPERIAG 4096 /* number of disk inodes per iag */ +#define L2INOSPERIAG 12 +#define INOSPEREXT 32 /* number of disk inode per extent */ +#define L2INOSPEREXT 5 + +/* Minimum number of bytes supported for a JFS partition */ +#define MINJFS (0x1000000) + +/* + * fixed byte offset address + */ +#define SUPER1_OFF 0x8000 /* primary superblock */ + +#define AITBL_OFF (SUPER1_OFF + PSIZE + (PSIZE << 1)) + +/* + * fixed reserved inode number + */ +/* aggregate inode */ +#define AGGREGATE_I 1 /* aggregate inode map inode */ +#define FILESYSTEM_I 16 /* 1st/only fileset inode in ait: + * fileset inode map inode + */ + +/* per fileset inode */ +#define ROOT_I 2 /* fileset root inode */ + +/* + * directory configuration + */ +#define JFS_NAME_MAX 255 +#define JFS_PATH_MAX PSIZE + +#if 0 +typedef unsigned char u8; +typedef char s8; +typedef unsigned short u16; +typedef short s16; +typedef unsigned int u32; +typedef int s32; +typedef unsigned long long u64; +typedef long long s64; +#endif + +typedef u16 UniChar; + +/* these from jfs_btree.h */ + +/* btpaget_t flag */ +#define BT_TYPE 0x07 /* B+-tree index */ +#define BT_ROOT 0x01 /* root page */ +#define BT_LEAF 0x02 /* leaf page */ +#define BT_INTERNAL 0x04 /* internal page */ +#define BT_RIGHTMOST 0x10 /* rightmost page */ +#define BT_LEFTMOST 0x20 /* leftmost page */ + +/* those are from jfs_types.h */ + +struct timestruc_t { + u32 tv_sec; + u32 tv_nsec; +}; + +/* + * physical xd (pxd) + */ +typedef struct { + unsigned len:24; + unsigned addr1:8; + u32 addr2; +} pxd_t; + +/* xd_t field extraction */ +#define lengthPXD(pxd) ((pxd)->len) +#define addressPXD(pxd) (((s64)((pxd)->addr1)) << 32 | ((pxd)->addr2)) + +/* + * data extent descriptor (dxd) + */ +typedef struct { + unsigned flag:8; /* 1: flags */ + unsigned rsrvd:24; /* 3: */ + u32 size; /* 4: size in byte */ + unsigned len:24; /* 3: length in unit of fsblksize */ + unsigned addr1:8; /* 1: address in unit of fsblksize */ + u32 addr2; /* 4: address in unit of fsblksize */ +} dxd_t; /* - 16 - */ + +/* + * DASD limit information - stored in directory inode + */ +typedef struct dasd { + u8 thresh; /* Alert Threshold (in percent) */ + u8 delta; /* Alert Threshold delta (in percent) */ + u8 rsrvd1; + u8 limit_hi; /* DASD limit (in logical blocks) */ + u32 limit_lo; /* DASD limit (in logical blocks) */ + u8 rsrvd2[3]; + u8 used_hi; /* DASD usage (in logical blocks) */ + u32 used_lo; /* DASD usage (in logical blocks) */ +} dasd_t; + + +/* from jfs_superblock.h */ + +#define JFS_MAGIC 0x3153464A /* "JFS1" */ + +struct jfs_superblock +{ + u32 s_magic; /* 4: magic number */ + u32 s_version; /* 4: version number */ + + s64 s_size; /* 8: aggregate size in hardware/LVM blocks; + * VFS: number of blocks + */ + s32 s_bsize; /* 4: aggregate block size in bytes; + * VFS: fragment size + */ + s16 s_l2bsize; /* 2: log2 of s_bsize */ + s16 s_l2bfactor; /* 2: log2(s_bsize/hardware block size) */ + s32 s_pbsize; /* 4: hardware/LVM block size in bytes */ + s16 s_l2pbsize; /* 2: log2 of s_pbsize */ + s16 pad; /* 2: padding necessary for alignment */ + + u32 s_agsize; /* 4: allocation group size in aggr. blocks */ + + u32 s_flag; /* 4: aggregate attributes: + * see jfs_filsys.h + */ + u32 s_state; /* 4: mount/unmount/recovery state: + * see jfs_filsys.h + */ + s32 s_compress; /* 4: > 0 if data compression */ + + pxd_t s_ait2; /* 8: first extent of secondary + * aggregate inode table + */ + + pxd_t s_aim2; /* 8: first extent of secondary + * aggregate inode map + */ + u32 s_logdev; /* 4: device address of log */ + s32 s_logserial; /* 4: log serial number at aggregate mount */ + pxd_t s_logpxd; /* 8: inline log extent */ + + pxd_t s_fsckpxd; /* 8: inline fsck work space extent */ + + struct timestruc_t s_time; /* 8: time last updated */ + + s32 s_fsckloglen; /* 4: Number of filesystem blocks reserved for + * the fsck service log. + * N.B. These blocks are divided among the + * versions kept. This is not a per + * version size. + * N.B. These blocks are included in the + * length field of s_fsckpxd. + */ + s8 s_fscklog; /* 1: which fsck service log is most recent + * 0 => no service log data yet + * 1 => the first one + * 2 => the 2nd one + */ + char s_fpack[11]; /* 11: file system volume name + * N.B. This must be 11 bytes to + * conform with the OS/2 BootSector + * requirements + */ + + /* extendfs() parameter under s_state & FM_EXTENDFS */ + s64 s_xsize; /* 8: extendfs s_size */ + pxd_t s_xfsckpxd; /* 8: extendfs fsckpxd */ + pxd_t s_xlogpxd; /* 8: extendfs logpxd */ + /* - 128 byte boundary - */ + + /* + * DFS VFS support (preliminary) + */ + char s_attach; /* 1: VFS: flag: set when aggregate is attached + */ + u8 rsrvd4[7]; /* 7: reserved - set to 0 */ + + u64 totalUsable; /* 8: VFS: total of 1K blocks which are + * available to "normal" (non-root) users. + */ + u64 minFree; /* 8: VFS: # of 1K blocks held in reserve for + * exclusive use of root. This value can be 0, + * and if it is then totalUsable will be equal + * to # of blocks in aggregate. I believe this + * means that minFree + totalUsable = # blocks. + * In that case, we don't need to store both + * totalUsable and minFree since we can compute + * one from the other. I would guess minFree + * would be the one we should store, and + * totalUsable would be the one we should + * compute. (Just a guess...) + */ + + u64 realFree; /* 8: VFS: # of free 1K blocks can be used by + * "normal" users. It may be this is something + * we should compute when asked for instead of + * storing in the superblock. I don't know how + * often this information is needed. + */ + /* + * graffiti area + */ +}; + +/* from jfs_dtree.h */ + +/* + * entry segment/slot + * + * an entry consists of type dependent head/only segment/slot and + * additional segments/slots linked vi next field; + * N.B. last/only segment of entry is terminated by next = -1; + */ +/* + * directory page slot + */ +typedef struct { + s8 next; /* 1: */ + s8 cnt; /* 1: */ + UniChar name[15]; /* 30: */ +} dtslot_t; /* (32) */ + +#define DTSLOTDATALEN 15 + +/* + * internal node entry head/only segment + */ +typedef struct { + pxd_t xd; /* 8: child extent descriptor */ + + s8 next; /* 1: */ + u8 namlen; /* 1: */ + UniChar name[11]; /* 22: 2-byte aligned */ +} idtentry_t; /* (32) */ + +/* + * leaf node entry head/only segment + * + * For legacy filesystems, name contains 13 unichars -- no index field + */ +typedef struct { + u32 inumber; /* 4: 4-byte aligned */ + s8 next; /* 1: */ + u8 namlen; /* 1: */ + UniChar name[11]; /* 22: 2-byte aligned */ + u32 index; /* 4: index into dir_table */ +} ldtentry_t; /* (32) */ + +#define DTLHDRDATALEN 11 + +/* + * dir_table used for directory traversal during readdir +*/ + +/* + * Maximum entry in inline directory table + */ + +typedef struct dir_table_slot { + u8 rsrvd; /* 1: */ + u8 flag; /* 1: 0 if free */ + u8 slot; /* 1: slot within leaf page of entry */ + u8 addr1; /* 1: upper 8 bits of leaf page address */ + u32 addr2; /* 4: lower 32 bits of leaf page address -OR- + index of next entry when this entry was deleted */ +} dir_table_slot_t; /* (8) */ + +/* + * directory root page (in-line in on-disk inode): + * + * cf. dtpage_t below. + */ +typedef union { + struct { + dasd_t DASD; /* 16: DASD limit/usage info F226941 */ + + u8 flag; /* 1: */ + s8 nextindex; /* 1: next free entry in stbl */ + s8 freecnt; /* 1: free count */ + s8 freelist; /* 1: freelist header */ + + u32 idotdot; /* 4: parent inode number */ + + s8 stbl[8]; /* 8: sorted entry index table */ + } header; /* (32) */ + + dtslot_t slot[9]; +} dtroot_t; + +/* + * directory regular page: + * + * entry slot array of 32 byte slot + * + * sorted entry slot index table (stbl): + * contiguous slots at slot specified by stblindex, + * 1-byte per entry + * 512 byte block: 16 entry tbl (1 slot) + * 1024 byte block: 32 entry tbl (1 slot) + * 2048 byte block: 64 entry tbl (2 slot) + * 4096 byte block: 128 entry tbl (4 slot) + * + * data area: + * 512 byte block: 16 - 2 = 14 slot + * 1024 byte block: 32 - 2 = 30 slot + * 2048 byte block: 64 - 3 = 61 slot + * 4096 byte block: 128 - 5 = 123 slot + * + * N.B. index is 0-based; index fields refer to slot index + * except nextindex which refers to entry index in stbl; + * end of entry stot list or freelist is marked with -1. + */ +typedef union { + struct { + s64 next; /* 8: next sibling */ + s64 prev; /* 8: previous sibling */ + + u8 flag; /* 1: */ + s8 nextindex; /* 1: next entry index in stbl */ + s8 freecnt; /* 1: */ + s8 freelist; /* 1: slot index of head of freelist */ + + u8 maxslot; /* 1: number of slots in page slot[] */ + s8 stblindex; /* 1: slot index of start of stbl */ + u8 rsrvd[2]; /* 2: */ + + pxd_t self; /* 8: self pxd */ + } header; /* (32) */ + + dtslot_t slot[128]; +} dtpage_t; + +/* from jfs_xtree.h */ + +/* + * extent allocation descriptor (xad) + */ +typedef struct xad { + unsigned flag:8; /* 1: flag */ + unsigned rsvrd:16; /* 2: reserved */ + unsigned off1:8; /* 1: offset in unit of fsblksize */ + u32 off2; /* 4: offset in unit of fsblksize */ + unsigned len:24; /* 3: length in unit of fsblksize */ + unsigned addr1:8; /* 1: address in unit of fsblksize */ + u32 addr2; /* 4: address in unit of fsblksize */ +} xad_t; /* (16) */ + +/* xad_t field extraction */ +#define offsetXAD(xad) (((s64)((xad)->off1)) << 32 | ((xad)->off2)) +#define addressXAD(xad) (((s64)((xad)->addr1)) << 32 | ((xad)->addr2)) +#define lengthXAD(xad) ((xad)->len) + +/* possible values for maxentry */ +#define XTPAGEMAXSLOT 256 +#define XTENTRYSTART 2 + +/* + * xtree page: + */ +typedef union { + struct xtheader { + s64 next; /* 8: */ + s64 prev; /* 8: */ + + u8 flag; /* 1: */ + u8 rsrvd1; /* 1: */ + s16 nextindex; /* 2: next index = number of entries */ + s16 maxentry; /* 2: max number of entries */ + s16 rsrvd2; /* 2: */ + + pxd_t self; /* 8: self */ + } header; /* (32) */ + + xad_t xad[XTPAGEMAXSLOT]; /* 16 * maxentry: xad array */ +} xtpage_t; + +/* from jfs_dinode.h */ + +struct dinode { + /* + * I. base area (128 bytes) + * ------------------------ + * + * define generic/POSIX attributes + */ + u32 di_inostamp; /* 4: stamp to show inode belongs to fileset */ + s32 di_fileset; /* 4: fileset number */ + u32 di_number; /* 4: inode number, aka file serial number */ + u32 di_gen; /* 4: inode generation number */ + + pxd_t di_ixpxd; /* 8: inode extent descriptor */ + + s64 di_size; /* 8: size */ + s64 di_nblocks; /* 8: number of blocks allocated */ + + u32 di_nlink; /* 4: number of links to the object */ + + u32 di_uid; /* 4: user id of owner */ + u32 di_gid; /* 4: group id of owner */ + + u32 di_mode; /* 4: attribute, format and permission */ + + struct timestruc_t di_atime; /* 8: time last data accessed */ + struct timestruc_t di_ctime; /* 8: time last status changed */ + struct timestruc_t di_mtime; /* 8: time last data modified */ + struct timestruc_t di_otime; /* 8: time created */ + + dxd_t di_acl; /* 16: acl descriptor */ + + dxd_t di_ea; /* 16: ea descriptor */ + + s32 di_next_index; /* 4: Next available dir_table index */ + + s32 di_acltype; /* 4: Type of ACL */ + + /* + * Extension Areas. + * + * Historically, the inode was partitioned into 4 128-byte areas, + * the last 3 being defined as unions which could have multiple + * uses. The first 96 bytes had been completely unused until + * an index table was added to the directory. It is now more + * useful to describe the last 3/4 of the inode as a single + * union. We would probably be better off redesigning the + * entire structure from scratch, but we don't want to break + * commonality with OS/2's JFS at this time. + */ + union { + struct { + /* + * This table contains the information needed to + * find a directory entry from a 32-bit index. + * If the index is small enough, the table is inline, + * otherwise, an x-tree root overlays this table + */ + dir_table_slot_t _table[12]; /* 96: inline */ + + dtroot_t _dtroot; /* 288: dtree root */ + } _dir; /* (384) */ +#define di_dirtable u._dir._table +#define di_dtroot u._dir._dtroot +#define di_parent di_dtroot.header.idotdot +#define di_DASD di_dtroot.header.DASD + + struct { + union { + u8 _data[96]; /* 96: unused */ + struct { + void *_imap; /* 4: unused */ + u32 _gengen; /* 4: generator */ + } _imap; + } _u1; /* 96: */ +#define di_gengen u._file._u1._imap._gengen + + union { + xtpage_t _xtroot; + struct { + u8 unused[16]; /* 16: */ + dxd_t _dxd; /* 16: */ + union { + u32 _rdev; /* 4: */ + u8 _fastsymlink[128]; + } _u; + u8 _inlineea[128]; + } _special; + } _u2; + } _file; +#define di_xtroot u._file._u2._xtroot +#define di_dxd u._file._u2._special._dxd +#define di_btroot di_xtroot +#define di_inlinedata u._file._u2._special._u +#define di_rdev u._file._u2._special._u._rdev +#define di_fastsymlink u._file._u2._special._u._fastsymlink +#define di_inlineea u._file._u2._special._inlineea + } u; +}; + +typedef struct dinode dinode_t; + +/* di_mode */ +#define IFMT 0xF000 /* S_IFMT - mask of file type */ +#define IFDIR 0x4000 /* S_IFDIR - directory */ +#define IFREG 0x8000 /* S_IFREG - regular file */ +#define IFLNK 0xA000 /* S_IFLNK - symbolic link */ + +/* extended mode bits (on-disk inode di_mode) */ +#define INLINEEA 0x00040000 /* inline EA area free */ + +/* from jfs_imap.h */ + +#define EXTSPERIAG 128 /* number of disk inode extent per iag */ +#define SMAPSZ 4 /* number of words per summary map */ +#define MAXAG 128 /* maximum number of allocation groups */ + +/* + * inode allocation map: + * + * inode allocation map consists of + * . the inode map control page and + * . inode allocation group pages (per 4096 inodes) + * which are addressed by standard JFS xtree. + */ +/* + * inode allocation group page (per 4096 inodes of an AG) + */ +typedef struct { + s64 agstart; /* 8: starting block of ag */ + s32 iagnum; /* 4: inode allocation group number */ + s32 inofreefwd; /* 4: ag inode free list forward */ + s32 inofreeback; /* 4: ag inode free list back */ + s32 extfreefwd; /* 4: ag inode extent free list forward */ + s32 extfreeback; /* 4: ag inode extent free list back */ + s32 iagfree; /* 4: iag free list */ + + /* summary map: 1 bit per inode extent */ + s32 inosmap[SMAPSZ]; /* 16: sum map of mapwords w/ free inodes; + * note: this indicates free and backed + * inodes, if the extent is not backed the + * value will be 1. if the extent is + * backed but all inodes are being used the + * value will be 1. if the extent is + * backed but at least one of the inodes is + * free the value will be 0. + */ + s32 extsmap[SMAPSZ]; /* 16: sum map of mapwords w/ free extents */ + s32 nfreeinos; /* 4: number of free inodes */ + s32 nfreeexts; /* 4: number of free extents */ + /* (72) */ + u8 pad[1976]; /* 1976: pad to 2048 bytes */ + /* allocation bit map: 1 bit per inode (0 - free, 1 - allocated) */ + u32 wmap[EXTSPERIAG]; /* 512: working allocation map */ + u32 pmap[EXTSPERIAG]; /* 512: persistent allocation map */ + pxd_t inoext[EXTSPERIAG]; /* 1024: inode extent addresses */ +} iag_t; /* (4096) */ + +#endif /* _JFS_H_ */ diff --git a/qemu/roms/openbios/fs/grubfs/shared.h b/qemu/roms/openbios/fs/grubfs/shared.h new file mode 100644 index 000000000..b3034e03c --- /dev/null +++ b/qemu/roms/openbios/fs/grubfs/shared.h @@ -0,0 +1,3 @@ +/* Sorry, nothing is shared here ;) Just for GRUB compatibility. */ + +#include "glue.h" diff --git a/qemu/roms/openbios/fs/grubfs/ufs_dinode.h b/qemu/roms/openbios/fs/grubfs/ufs_dinode.h new file mode 100644 index 000000000..f3f7fca02 --- /dev/null +++ b/qemu/roms/openbios/fs/grubfs/ufs_dinode.h @@ -0,0 +1,191 @@ +/*- + * Copyright (c) 2002 Networks Associates Technology, Inc. + * All rights reserved. + * + * This software was developed for the FreeBSD Project by Marshall + * Kirk McKusick and Network Associates Laboratories, the Security + * Research Division of Network Associates, Inc. under DARPA/SPAWAR + * contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS + * research program + * + * 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 AUTHOR 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 AUTHOR 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. + * + * Copyright (c) 1982, 1989, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * 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. + * 3. The names of the authors may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + * + * @(#)dinode.h 8.3 (Berkeley) 1/21/94 + * $FreeBSD: src/sys/ufs/ufs/dinode.h,v 1.13.2.1 2005/01/31 23:27:01 imp Exp $ + */ + +#ifndef _UFS_UFS_DINODE_H_ +#define _UFS_UFS_DINODE_H_ + +/* + * The root inode is the root of the filesystem. Inode 0 can't be used for + * normal purposes and historically bad blocks were linked to inode 1, thus + * the root inode is 2. (Inode 1 is no longer used for this purpose, however + * numerous dump tapes make this assumption, so we are stuck with it). + */ +#define ROOTINO ((ino_t)2) + +/* + * The Whiteout inode# is a dummy non-zero inode number which will + * never be allocated to a real file. It is used as a place holder + * in the directory entry which has been tagged as a DT_W entry. + * See the comments about ROOTINO above. + */ +#define WINO ((ino_t)1) + +/* + * The size of physical and logical block numbers and time fields in UFS. + */ +typedef int32_t ufs1_daddr_t; +typedef int64_t ufs2_daddr_t; +typedef int64_t ufs_lbn_t; +typedef int64_t ufs_time_t; + +/* File permissions. */ +#define IEXEC 0000100 /* Executable. */ +#define IWRITE 0000200 /* Writeable. */ +#define IREAD 0000400 /* Readable. */ +#define ISVTX 0001000 /* Sticky bit. */ +#define ISGID 0002000 /* Set-gid. */ +#define ISUID 0004000 /* Set-uid. */ + +/* File types. */ +#define IFMT 0170000 /* Mask of file type. */ +#define IFIFO 0010000 /* Named pipe (fifo). */ +#define IFCHR 0020000 /* Character device. */ +#define IFDIR 0040000 /* Directory file. */ +#define IFBLK 0060000 /* Block device. */ +#define IFREG 0100000 /* Regular file. */ +#define IFLNK 0120000 /* Symbolic link. */ +#define IFSOCK 0140000 /* UNIX domain socket. */ +#define IFWHT 0160000 /* Whiteout. */ + +/* + * A dinode contains all the meta-data associated with a UFS2 file. + * This structure defines the on-disk format of a dinode. Since + * this structure describes an on-disk structure, all its fields + * are defined by types with precise widths. + */ + +#define NXADDR 2 /* External addresses in inode. */ +#define NDADDR 12 /* Direct addresses in inode. */ +#define NIADDR 3 /* Indirect addresses in inode. */ + +struct ufs2_dinode { + uint16_t di_mode; /* 0: IFMT, permissions; see below. */ + int16_t di_nlink; /* 2: File link count. */ + uint32_t di_uid; /* 4: File owner. */ + uint32_t di_gid; /* 8: File group. */ + uint32_t di_blksize; /* 12: Inode blocksize. */ + uint64_t di_size; /* 16: File byte count. */ + uint64_t di_blocks; /* 24: Bytes actually held. */ + ufs_time_t di_atime; /* 32: Last access time. */ + ufs_time_t di_mtime; /* 40: Last modified time. */ + ufs_time_t di_ctime; /* 48: Last inode change time. */ + ufs_time_t di_birthtime; /* 56: Inode creation time. */ + int32_t di_mtimensec; /* 64: Last modified time. */ + int32_t di_atimensec; /* 68: Last access time. */ + int32_t di_ctimensec; /* 72: Last inode change time. */ + int32_t di_birthnsec; /* 76: Inode creation time. */ + int32_t di_gen; /* 80: Generation number. */ + uint32_t di_kernflags; /* 84: Kernel flags. */ + uint32_t di_flags; /* 88: Status flags (chflags). */ + int32_t di_extsize; /* 92: External attributes block. */ + ufs2_daddr_t di_extb[NXADDR];/* 96: External attributes block. */ + ufs2_daddr_t di_db[NDADDR]; /* 112: Direct disk blocks. */ + ufs2_daddr_t di_ib[NIADDR]; /* 208: Indirect disk blocks. */ + int64_t di_spare[3]; /* 232: Reserved; currently unused */ +}; + +/* + * The di_db fields may be overlaid with other information for + * file types that do not have associated disk storage. Block + * and character devices overlay the first data block with their + * dev_t value. Short symbolic links place their path in the + * di_db area. + */ +#define di_rdev di_db[0] + +/* + * A UFS1 dinode contains all the meta-data associated with a UFS1 file. + * This structure defines the on-disk format of a UFS1 dinode. Since + * this structure describes an on-disk structure, all its fields + * are defined by types with precise widths. + */ +struct ufs1_dinode { + uint16_t di_mode; /* 0: IFMT, permissions; see below. */ + int16_t di_nlink; /* 2: File link count. */ + union { + uint16_t oldids[2]; /* 4: Ffs: old user and group ids. */ + } di_u; + uint64_t di_size; /* 8: File byte count. */ + int32_t di_atime; /* 16: Last access time. */ + int32_t di_atimensec; /* 20: Last access time. */ + int32_t di_mtime; /* 24: Last modified time. */ + int32_t di_mtimensec; /* 28: Last modified time. */ + int32_t di_ctime; /* 32: Last inode change time. */ + int32_t di_ctimensec; /* 36: Last inode change time. */ + ufs1_daddr_t di_db[NDADDR]; /* 40: Direct disk blocks. */ + ufs1_daddr_t di_ib[NIADDR]; /* 88: Indirect disk blocks. */ + uint32_t di_flags; /* 100: Status flags (chflags). */ + int32_t di_blocks; /* 104: Blocks actually held. */ + int32_t di_gen; /* 108: Generation number. */ + uint32_t di_uid; /* 112: File owner. */ + uint32_t di_gid; /* 116: File group. */ + int32_t di_spare[2]; /* 120: Reserved; currently unused */ +}; +#define di_ogid di_u.oldids[1] +#define di_ouid di_u.oldids[0] + +#endif /* _UFS_UFS_DINODE_H_ */ diff --git a/qemu/roms/openbios/fs/grubfs/ufs_fs.h b/qemu/roms/openbios/fs/grubfs/ufs_fs.h new file mode 100644 index 000000000..bd11cc968 --- /dev/null +++ b/qemu/roms/openbios/fs/grubfs/ufs_fs.h @@ -0,0 +1,635 @@ +/*- + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * 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. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + * + * @(#)fs.h 8.13 (Berkeley) 3/21/95 + * $FreeBSD: src/sys/ufs/ffs/fs.h,v 1.43.2.3 2005/02/28 16:04:53 delphij Exp $ + */ + +#ifndef _UFS_FFS_FS_H_ +#define _UFS_FFS_FS_H_ + +/* + * Each disk drive contains some number of filesystems. + * A filesystem consists of a number of cylinder groups. + * Each cylinder group has inodes and data. + * + * A filesystem is described by its super-block, which in turn + * describes the cylinder groups. The super-block is critical + * data and is replicated in each cylinder group to protect against + * catastrophic loss. This is done at `newfs' time and the critical + * super-block data does not change, so the copies need not be + * referenced further unless disaster strikes. + * + * For filesystem fs, the offsets of the various blocks of interest + * are given in the super block as: + * [fs->fs_sblkno] Super-block + * [fs->fs_cblkno] Cylinder group block + * [fs->fs_iblkno] Inode blocks + * [fs->fs_dblkno] Data blocks + * The beginning of cylinder group cg in fs, is given by + * the ``cgbase(fs, cg)'' macro. + * + * Depending on the architecture and the media, the superblock may + * reside in any one of four places. For tiny media where every block + * counts, it is placed at the very front of the partition. Historically, + * UFS1 placed it 8K from the front to leave room for the disk label and + * a small bootstrap. For UFS2 it got moved to 64K from the front to leave + * room for the disk label and a bigger bootstrap, and for really piggy + * systems we check at 256K from the front if the first three fail. In + * all cases the size of the superblock will be SBLOCKSIZE. All values are + * given in byte-offset form, so they do not imply a sector size. The + * SBLOCKSEARCH specifies the order in which the locations should be searched. + */ +#define SBLOCK_FLOPPY 0 +#define SBLOCK_UFS1 8192 +#define SBLOCK_UFS2 65536 +#define SBLOCK_PIGGY 262144 +#define SBLOCKSIZE 8192 +#define SBLOCKSEARCH \ + { SBLOCK_UFS2, SBLOCK_UFS1, SBLOCK_FLOPPY, SBLOCK_PIGGY, -1 } + +/* + * Max number of fragments per block. This value is NOT tweakable. + */ +#define MAXFRAG 8 + +/* + * Addresses stored in inodes are capable of addressing fragments + * of `blocks'. File system blocks of at most size MAXBSIZE can + * be optionally broken into 2, 4, or 8 pieces, each of which is + * addressable; these pieces may be DEV_BSIZE, or some multiple of + * a DEV_BSIZE unit. + * + * Large files consist of exclusively large data blocks. To avoid + * undue wasted disk space, the last data block of a small file may be + * allocated as only as many fragments of a large block as are + * necessary. The filesystem format retains only a single pointer + * to such a fragment, which is a piece of a single large block that + * has been divided. The size of such a fragment is determinable from + * information in the inode, using the ``blksize(fs, ip, lbn)'' macro. + * + * The filesystem records space availability at the fragment level; + * to determine block availability, aligned fragments are examined. + */ + +/* + * MINBSIZE is the smallest allowable block size. + * In order to insure that it is possible to create files of size + * 2^32 with only two levels of indirection, MINBSIZE is set to 4096. + * MINBSIZE must be big enough to hold a cylinder group block, + * thus changes to (struct cg) must keep its size within MINBSIZE. + * Note that super blocks are always of size SBSIZE, + * and that both SBSIZE and MAXBSIZE must be >= MINBSIZE. + */ +#define MINBSIZE 4096 + +/* + * The path name on which the filesystem is mounted is maintained + * in fs_fsmnt. MAXMNTLEN defines the amount of space allocated in + * the super block for this name. + */ +#define MAXMNTLEN 468 + +/* + * The volume name for this filesystem is maintained in fs_volname. + * MAXVOLLEN defines the length of the buffer allocated. + */ +#define MAXVOLLEN 32 + +/* + * There is a 128-byte region in the superblock reserved for in-core + * pointers to summary information. Originally this included an array + * of pointers to blocks of struct csum; now there are just a few + * pointers and the remaining space is padded with fs_ocsp[]. + * + * NOCSPTRS determines the size of this padding. One pointer (fs_csp) + * is taken away to point to a contiguous array of struct csum for + * all cylinder groups; a second (fs_maxcluster) points to an array + * of cluster sizes that is computed as cylinder groups are inspected, + * and the third points to an array that tracks the creation of new + * directories. A fourth pointer, fs_active, is used when creating + * snapshots; it points to a bitmap of cylinder groups for which the + * free-block bitmap has changed since the snapshot operation began. + */ +#define NOCSPTRS ((128 / sizeof(void *)) - 4) + +/* + * A summary of contiguous blocks of various sizes is maintained + * in each cylinder group. Normally this is set by the initial + * value of fs_maxcontig. To conserve space, a maximum summary size + * is set by FS_MAXCONTIG. + */ +#define FS_MAXCONTIG 16 + +/* + * MINFREE gives the minimum acceptable percentage of filesystem + * blocks which may be free. If the freelist drops below this level + * only the superuser may continue to allocate blocks. This may + * be set to 0 if no reserve of free blocks is deemed necessary, + * however throughput drops by fifty percent if the filesystem + * is run at between 95% and 100% full; thus the minimum default + * value of fs_minfree is 5%. However, to get good clustering + * performance, 10% is a better choice. hence we use 10% as our + * default value. With 10% free space, fragmentation is not a + * problem, so we choose to optimize for time. + */ +#define MINFREE 8 +#define DEFAULTOPT FS_OPTTIME + +/* + * Grigoriy Orlov <gluk@ptci.ru> has done some extensive work to fine + * tune the layout preferences for directories within a filesystem. + * His algorithm can be tuned by adjusting the following parameters + * which tell the system the average file size and the average number + * of files per directory. These defaults are well selected for typical + * filesystems, but may need to be tuned for odd cases like filesystems + * being used for squid caches or news spools. + */ +#define AVFILESIZ 16384 /* expected average file size */ +#define AFPDIR 64 /* expected number of files per directory */ + +/* + * The maximum number of snapshot nodes that can be associated + * with each filesystem. This limit affects only the number of + * snapshot files that can be recorded within the superblock so + * that they can be found when the filesystem is mounted. However, + * maintaining too many will slow the filesystem performance, so + * having this limit is a good idea. + */ +#define FSMAXSNAP 20 + +/* + * Used to identify special blocks in snapshots: + * + * BLK_NOCOPY - A block that was unallocated at the time the snapshot + * was taken, hence does not need to be copied when written. + * BLK_SNAP - A block held by another snapshot that is not needed by this + * snapshot. When the other snapshot is freed, the BLK_SNAP entries + * are converted to BLK_NOCOPY. These are needed to allow fsck to + * identify blocks that are in use by other snapshots (which are + * expunged from this snapshot). + */ +#define BLK_NOCOPY ((ufs2_daddr_t)(1)) +#define BLK_SNAP ((ufs2_daddr_t)(2)) + +/* + * Sysctl values for the fast filesystem. + */ +#define FFS_ADJ_REFCNT 1 /* adjust inode reference count */ +#define FFS_ADJ_BLKCNT 2 /* adjust inode used block count */ +#define FFS_BLK_FREE 3 /* free range of blocks in map */ +#define FFS_DIR_FREE 4 /* free specified dir inodes in map */ +#define FFS_FILE_FREE 5 /* free specified file inodes in map */ +#define FFS_SET_FLAGS 6 /* set filesystem flags */ +#define FFS_ADJ_NDIR 7 /* adjust number of directories */ +#define FFS_ADJ_NBFREE 8 /* adjust number of free blocks */ +#define FFS_ADJ_NIFREE 9 /* adjust number of free inodes */ +#define FFS_ADJ_NFFREE 10 /* adjust number of free frags */ +#define FFS_ADJ_NUMCLUSTERS 11 /* adjust number of free clusters */ +#define FFS_MAXID 12 /* number of valid ffs ids */ + +/* + * Command structure passed in to the filesystem to adjust filesystem values. + */ +#define FFS_CMD_VERSION 0x19790518 /* version ID */ +struct fsck_cmd { + int32_t version; /* version of command structure */ + int32_t handle; /* reference to filesystem to be changed */ + int64_t value; /* inode or block number to be affected */ + int64_t size; /* amount or range to be adjusted */ + int64_t spare; /* reserved for future use */ +}; + +/* + * Per cylinder group information; summarized in blocks allocated + * from first cylinder group data blocks. These blocks have to be + * read in from fs_csaddr (size fs_cssize) in addition to the + * super block. + */ +struct csum { + int32_t cs_ndir; /* number of directories */ + int32_t cs_nbfree; /* number of free blocks */ + int32_t cs_nifree; /* number of free inodes */ + int32_t cs_nffree; /* number of free frags */ +}; +struct csum_total { + int64_t cs_ndir; /* number of directories */ + int64_t cs_nbfree; /* number of free blocks */ + int64_t cs_nifree; /* number of free inodes */ + int64_t cs_nffree; /* number of free frags */ + int64_t cs_numclusters; /* number of free clusters */ + int64_t cs_spare[3]; /* future expansion */ +}; + +/* + * Super block for an FFS filesystem. + */ +struct fs { + int32_t fs_firstfield; /* historic filesystem linked list, */ + int32_t fs_unused_1; /* used for incore super blocks */ + int32_t fs_sblkno; /* offset of super-block in filesys */ + int32_t fs_cblkno; /* offset of cyl-block in filesys */ + int32_t fs_iblkno; /* offset of inode-blocks in filesys */ + int32_t fs_dblkno; /* offset of first data after cg */ + int32_t fs_old_cgoffset; /* cylinder group offset in cylinder */ + int32_t fs_old_cgmask; /* used to calc mod fs_ntrak */ + int32_t fs_old_time; /* last time written */ + int32_t fs_old_size; /* number of blocks in fs */ + int32_t fs_old_dsize; /* number of data blocks in fs */ + int32_t fs_ncg; /* number of cylinder groups */ + int32_t fs_bsize; /* size of basic blocks in fs */ + int32_t fs_fsize; /* size of frag blocks in fs */ + int32_t fs_frag; /* number of frags in a block in fs */ +/* these are configuration parameters */ + int32_t fs_minfree; /* minimum percentage of free blocks */ + int32_t fs_old_rotdelay; /* num of ms for optimal next block */ + int32_t fs_old_rps; /* disk revolutions per second */ +/* these fields can be computed from the others */ + int32_t fs_bmask; /* ``blkoff'' calc of blk offsets */ + int32_t fs_fmask; /* ``fragoff'' calc of frag offsets */ + int32_t fs_bshift; /* ``lblkno'' calc of logical blkno */ + int32_t fs_fshift; /* ``numfrags'' calc number of frags */ +/* these are configuration parameters */ + int32_t fs_maxcontig; /* max number of contiguous blks */ + int32_t fs_maxbpg; /* max number of blks per cyl group */ +/* these fields can be computed from the others */ + int32_t fs_fragshift; /* block to frag shift */ + int32_t fs_fsbtodb; /* fsbtodb and dbtofsb shift constant */ + int32_t fs_sbsize; /* actual size of super block */ + int32_t fs_spare1[2]; /* old fs_csmask */ + /* old fs_csshift */ + int32_t fs_nindir; /* value of NINDIR */ + int32_t fs_inopb; /* value of INOPB */ + int32_t fs_old_nspf; /* value of NSPF */ +/* yet another configuration parameter */ + int32_t fs_optim; /* optimization preference, see below */ + int32_t fs_old_npsect; /* # sectors/track including spares */ + int32_t fs_old_interleave; /* hardware sector interleave */ + int32_t fs_old_trackskew; /* sector 0 skew, per track */ + int32_t fs_id[2]; /* unique filesystem id */ +/* sizes determined by number of cylinder groups and their sizes */ + int32_t fs_old_csaddr; /* blk addr of cyl grp summary area */ + int32_t fs_cssize; /* size of cyl grp summary area */ + int32_t fs_cgsize; /* cylinder group size */ + int32_t fs_spare2; /* old fs_ntrak */ + int32_t fs_old_nsect; /* sectors per track */ + int32_t fs_old_spc; /* sectors per cylinder */ + int32_t fs_old_ncyl; /* cylinders in filesystem */ + int32_t fs_old_cpg; /* cylinders per group */ + int32_t fs_ipg; /* inodes per group */ + int32_t fs_fpg; /* blocks per group * fs_frag */ +/* this data must be re-computed after crashes */ + struct csum fs_old_cstotal; /* cylinder summary information */ +/* these fields are cleared at mount time */ + int8_t fs_fmod; /* super block modified flag */ + int8_t fs_clean; /* filesystem is clean flag */ + int8_t fs_ronly; /* mounted read-only flag */ + int8_t fs_old_flags; /* old FS_ flags */ + char fs_fsmnt[MAXMNTLEN]; /* name mounted on */ + char fs_volname[MAXVOLLEN]; /* volume name */ + uint64_t fs_swuid; /* system-wide uid */ + int32_t fs_pad; /* due to alignment of fs_swuid */ +/* these fields retain the current block allocation info */ + int32_t fs_cgrotor; /* last cg searched */ + void *fs_ocsp[NOCSPTRS]; /* padding; was list of fs_cs buffers */ + uint8_t *fs_contigdirs; /* # of contiguously allocated dirs */ + struct csum *fs_csp; /* cg summary info buffer for fs_cs */ + int32_t *fs_maxcluster; /* max cluster in each cyl group */ + unsigned int *fs_active; /* used by snapshots to track fs */ + int32_t fs_old_cpc; /* cyl per cycle in postbl */ + int32_t fs_maxbsize; /* maximum blocking factor permitted */ + int64_t fs_sparecon64[17]; /* old rotation block list head */ + int64_t fs_sblockloc; /* byte offset of standard superblock */ + struct csum_total fs_cstotal; /* cylinder summary information */ + ufs_time_t fs_time; /* last time written */ + int64_t fs_size; /* number of blocks in fs */ + int64_t fs_dsize; /* number of data blocks in fs */ + ufs2_daddr_t fs_csaddr; /* blk addr of cyl grp summary area */ + int64_t fs_pendingblocks; /* blocks in process of being freed */ + int32_t fs_pendinginodes; /* inodes in process of being freed */ + int32_t fs_snapinum[FSMAXSNAP];/* list of snapshot inode numbers */ + int32_t fs_avgfilesize; /* expected average file size */ + int32_t fs_avgfpdir; /* expected # of files per directory */ + int32_t fs_save_cgsize; /* save real cg size to use fs_bsize */ + int32_t fs_sparecon32[26]; /* reserved for future constants */ + int32_t fs_flags; /* see FS_ flags below */ + int32_t fs_contigsumsize; /* size of cluster summary array */ + int32_t fs_maxsymlinklen; /* max length of an internal symlink */ + int32_t fs_old_inodefmt; /* format of on-disk inodes */ + uint64_t fs_maxfilesize; /* maximum representable file size */ + int64_t fs_qbmask; /* ~fs_bmask for use with 64-bit size */ + int64_t fs_qfmask; /* ~fs_fmask for use with 64-bit size */ + int32_t fs_state; /* validate fs_clean field */ + int32_t fs_old_postblformat; /* format of positional layout tables */ + int32_t fs_old_nrpos; /* number of rotational positions */ + int32_t fs_spare5[2]; /* old fs_postbloff */ + /* old fs_rotbloff */ + int32_t fs_magic; /* magic number */ +}; + +/* Sanity checking. */ +#ifdef CTASSERT +CTASSERT(sizeof(struct fs) == 1376); +#endif + +/* + * Filesystem identification + */ +#define FS_UFS1_MAGIC 0x011954 /* UFS1 fast filesystem magic number */ +#define FS_UFS2_MAGIC 0x19540119 /* UFS2 fast filesystem magic number */ +#define FS_BAD_MAGIC 0x19960408 /* UFS incomplete newfs magic number */ +#define FS_OKAY 0x7c269d38 /* superblock checksum */ +#define FS_42INODEFMT -1 /* 4.2BSD inode format */ +#define FS_44INODEFMT 2 /* 4.4BSD inode format */ + +/* + * Preference for optimization. + */ +#define FS_OPTTIME 0 /* minimize allocation time */ +#define FS_OPTSPACE 1 /* minimize disk fragmentation */ + +/* + * Filesystem flags. + * + * The FS_UNCLEAN flag is set by the kernel when the filesystem was + * mounted with fs_clean set to zero. The FS_DOSOFTDEP flag indicates + * that the filesystem should be managed by the soft updates code. + * Note that the FS_NEEDSFSCK flag is set and cleared only by the + * fsck utility. It is set when background fsck finds an unexpected + * inconsistency which requires a traditional foreground fsck to be + * run. Such inconsistencies should only be found after an uncorrectable + * disk error. A foreground fsck will clear the FS_NEEDSFSCK flag when + * it has successfully cleaned up the filesystem. The kernel uses this + * flag to enforce that inconsistent filesystems be mounted read-only. + * The FS_INDEXDIRS flag when set indicates that the kernel maintains + * on-disk auxiliary indexes (such as B-trees) for speeding directory + * accesses. Kernels that do not support auxiliary indicies clear the + * flag to indicate that the indicies need to be rebuilt (by fsck) before + * they can be used. + * + * FS_ACLS indicates that ACLs are administratively enabled for the + * file system, so they should be loaded from extended attributes, + * observed for access control purposes, and be administered by object + * owners. FS_MULTILABEL indicates that the TrustedBSD MAC Framework + * should attempt to back MAC labels into extended attributes on the + * file system rather than maintain a single mount label for all + * objects. + */ +#define FS_UNCLEAN 0x01 /* filesystem not clean at mount */ +#define FS_DOSOFTDEP 0x02 /* filesystem using soft dependencies */ +#define FS_NEEDSFSCK 0x04 /* filesystem needs sync fsck before mount */ +#define FS_INDEXDIRS 0x08 /* kernel supports indexed directories */ +#define FS_ACLS 0x10 /* file system has ACLs enabled */ +#define FS_MULTILABEL 0x20 /* file system is MAC multi-label */ +#define FS_FLAGS_UPDATED 0x80 /* flags have been moved to new location */ + +/* + * Macros to access bits in the fs_active array. + */ +#define ACTIVECGNUM(fs, cg) ((fs)->fs_active[(cg) / (NBBY * sizeof(int))]) +#define ACTIVECGOFF(cg) (1 << ((cg) % (NBBY * sizeof(int)))) + +/* + * The size of a cylinder group is calculated by CGSIZE. The maximum size + * is limited by the fact that cylinder groups are at most one block. + * Its size is derived from the size of the maps maintained in the + * cylinder group and the (struct cg) size. + */ +#define CGSIZE(fs) \ + /* base cg */ (sizeof(struct cg) + sizeof(int32_t) + \ + /* old btotoff */ (fs)->fs_old_cpg * sizeof(int32_t) + \ + /* old boff */ (fs)->fs_old_cpg * sizeof(uint16_t) + \ + /* inode map */ howmany((fs)->fs_ipg, NBBY) + \ + /* block map */ howmany((fs)->fs_fpg, NBBY) +\ + /* if present */ ((fs)->fs_contigsumsize <= 0 ? 0 : \ + /* cluster sum */ (fs)->fs_contigsumsize * sizeof(int32_t) + \ + /* cluster map */ howmany(fragstoblks(fs, (fs)->fs_fpg), NBBY))) + +/* + * The minimal number of cylinder groups that should be created. + */ +#define MINCYLGRPS 4 + +/* + * Convert cylinder group to base address of its global summary info. + */ +#define fs_cs(fs, indx) fs_csp[indx] + +/* + * Cylinder group block for a filesystem. + */ +#define CG_MAGIC 0x090255 +struct cg { + int32_t cg_firstfield; /* historic cyl groups linked list */ + int32_t cg_magic; /* magic number */ + int32_t cg_old_time; /* time last written */ + int32_t cg_cgx; /* we are the cgx'th cylinder group */ + int16_t cg_old_ncyl; /* number of cyl's this cg */ + int16_t cg_old_niblk; /* number of inode blocks this cg */ + int32_t cg_ndblk; /* number of data blocks this cg */ + struct csum cg_cs; /* cylinder summary information */ + int32_t cg_rotor; /* position of last used block */ + int32_t cg_frotor; /* position of last used frag */ + int32_t cg_irotor; /* position of last used inode */ + int32_t cg_frsum[MAXFRAG]; /* counts of available frags */ + int32_t cg_old_btotoff; /* (int32) block totals per cylinder */ + int32_t cg_old_boff; /* (uint16) free block positions */ + int32_t cg_iusedoff; /* (uint8) used inode map */ + int32_t cg_freeoff; /* (uint8) free block map */ + int32_t cg_nextfreeoff; /* (uint8) next available space */ + int32_t cg_clustersumoff; /* (uint32) counts of avail clusters */ + int32_t cg_clusteroff; /* (uint8) free cluster map */ + int32_t cg_nclusterblks; /* number of clusters this cg */ + int32_t cg_niblk; /* number of inode blocks this cg */ + int32_t cg_initediblk; /* last initialized inode */ + int32_t cg_sparecon32[3]; /* reserved for future use */ + ufs_time_t cg_time; /* time last written */ + int64_t cg_sparecon64[3]; /* reserved for future use */ + uint8_t cg_space[1]; /* space for cylinder group maps */ +/* actually longer */ +}; + +/* + * Macros for access to cylinder group array structures + */ +#define cg_chkmagic(cgp) ((cgp)->cg_magic == CG_MAGIC) +#define cg_inosused(cgp) \ + ((uint8_t *)((uint8_t *)(cgp) + (cgp)->cg_iusedoff)) +#define cg_blksfree(cgp) \ + ((uint8_t *)((uint8_t *)(cgp) + (cgp)->cg_freeoff)) +#define cg_clustersfree(cgp) \ + ((uint8_t *)((uint8_t *)(cgp) + (cgp)->cg_clusteroff)) +#define cg_clustersum(cgp) \ + ((int32_t *)((uintptr_t)(cgp) + (cgp)->cg_clustersumoff)) + +/* + * Turn filesystem block numbers into disk block addresses. + * This maps filesystem blocks to device size blocks. + */ +#define fsbtodb(fs, b) ((b) << (fs)->fs_fsbtodb) +#define dbtofsb(fs, b) ((b) >> (fs)->fs_fsbtodb) + +/* + * Cylinder group macros to locate things in cylinder groups. + * They calc filesystem addresses of cylinder group data structures. + */ +#define cgbase(fs, c) (((ufs2_daddr_t)(fs)->fs_fpg) * (c)) +#define cgdmin(fs, c) (cgstart(fs, c) + (fs)->fs_dblkno) /* 1st data */ +#define cgimin(fs, c) (cgstart(fs, c) + (fs)->fs_iblkno) /* inode blk */ +#define cgsblock(fs, c) (cgstart(fs, c) + (fs)->fs_sblkno) /* super blk */ +#define cgtod(fs, c) (cgstart(fs, c) + (fs)->fs_cblkno) /* cg block */ +#define cgstart(fs, c) \ + ((fs)->fs_magic == FS_UFS2_MAGIC ? cgbase(fs, c) : \ + (cgbase(fs, c) + (fs)->fs_old_cgoffset * ((c) & ~((fs)->fs_old_cgmask)))) + +/* + * Macros for handling inode numbers: + * inode number to filesystem block offset. + * inode number to cylinder group number. + * inode number to filesystem block address. + */ +#define ino_to_cg(fs, x) ((x) / (fs)->fs_ipg) +#define ino_to_fsba(fs, x) \ + ((ufs2_daddr_t)(cgimin(fs, ino_to_cg(fs, x)) + \ + (blkstofrags((fs), (((x) % (fs)->fs_ipg) / INOPB(fs)))))) +#define ino_to_fsbo(fs, x) ((x) % INOPB(fs)) + +/* + * Give cylinder group number for a filesystem block. + * Give cylinder group block number for a filesystem block. + */ +#define dtog(fs, d) ((d) / (fs)->fs_fpg) +#define dtogd(fs, d) ((d) % (fs)->fs_fpg) + +/* + * Extract the bits for a block from a map. + * Compute the cylinder and rotational position of a cyl block addr. + */ +#define blkmap(fs, map, loc) \ + (((map)[(loc) / NBBY] >> ((loc) % NBBY)) & (0xff >> (NBBY - (fs)->fs_frag))) + +/* + * The following macros optimize certain frequently calculated + * quantities by using shifts and masks in place of divisions + * modulos and multiplications. + */ +#define blkoff(fs, loc) /* calculates (loc % fs->fs_bsize) */ \ + ((loc) & (fs)->fs_qbmask) +#define fragoff(fs, loc) /* calculates (loc % fs->fs_fsize) */ \ + ((loc) & (fs)->fs_qfmask) +#define lfragtosize(fs, frag) /* calculates ((off_t)frag * fs->fs_fsize) */ \ + (((off_t)(frag)) << (fs)->fs_fshift) +#define lblktosize(fs, blk) /* calculates ((off_t)blk * fs->fs_bsize) */ \ + (((off_t)(blk)) << (fs)->fs_bshift) +/* Use this only when `blk' is known to be small, e.g., < NDADDR. */ +#define smalllblktosize(fs, blk) /* calculates (blk * fs->fs_bsize) */ \ + ((blk) << (fs)->fs_bshift) +#define lblkno(fs, loc) /* calculates (loc / fs->fs_bsize) */ \ + ((loc) >> (fs)->fs_bshift) +#define numfrags(fs, loc) /* calculates (loc / fs->fs_fsize) */ \ + ((loc) >> (fs)->fs_fshift) +#define blkroundup(fs, size) /* calculates roundup(size, fs->fs_bsize) */ \ + (((size) + (fs)->fs_qbmask) & (fs)->fs_bmask) +#define fragroundup(fs, size) /* calculates roundup(size, fs->fs_fsize) */ \ + (((size) + (fs)->fs_qfmask) & (fs)->fs_fmask) +#define fragstoblks(fs, frags) /* calculates (frags / fs->fs_frag) */ \ + ((frags) >> (fs)->fs_fragshift) +#define blkstofrags(fs, blks) /* calculates (blks * fs->fs_frag) */ \ + ((blks) << (fs)->fs_fragshift) +#define fragnum(fs, fsb) /* calculates (fsb % fs->fs_frag) */ \ + ((fsb) & ((fs)->fs_frag - 1)) +#define blknum(fs, fsb) /* calculates rounddown(fsb, fs->fs_frag) */ \ + ((fsb) &~ ((fs)->fs_frag - 1)) + +/* + * Determine the number of available frags given a + * percentage to hold in reserve. + */ +#define freespace(fs, percentreserved) \ + (blkstofrags((fs), (fs)->fs_cstotal.cs_nbfree) + \ + (fs)->fs_cstotal.cs_nffree - \ + (((off_t)((fs)->fs_dsize)) * (percentreserved) / 100)) + +/* + * Determining the size of a file block in the filesystem. + */ +#define blksize(fs, ip, lbn) \ + (((lbn) >= NDADDR || (ip)->i_size >= smalllblktosize(fs, (lbn) + 1)) \ + ? (fs)->fs_bsize \ + : (fragroundup(fs, blkoff(fs, (ip)->i_size)))) +#define sblksize(fs, size, lbn) \ + (((lbn) >= NDADDR || (size) >= ((lbn) + 1) << (fs)->fs_bshift) \ + ? (fs)->fs_bsize \ + : (fragroundup(fs, blkoff(fs, (size))))) + + +/* + * Number of inodes in a secondary storage block/fragment. + */ +#define INOPB(fs) ((fs)->fs_inopb) +#define INOPF(fs) ((fs)->fs_inopb >> (fs)->fs_fragshift) + +/* + * Number of indirects in a filesystem block. + */ +#define NINDIR(fs) ((fs)->fs_nindir) + +extern int inside[], around[]; +extern char *fragtbl[]; + +struct ufs_dirent { + uint32_t d_fileno; /* file number of entry */ + uint16_t d_reclen; /* length of this record */ + uint8_t d_type; /* file type, see below */ + uint8_t d_namlen; /* length of string in d_name */ +#define MAXNAMLEN 255 + char d_name[MAXNAMLEN + 1]; /* name must be no longer than this */ +}; + +/* + * File types + */ +#define DT_UNKNOWN 0 +#define DT_FIFO 1 +#define DT_CHR 2 +#define DT_DIR 4 +#define DT_BLK 6 +#define DT_REG 8 +#define DT_LNK 10 +#define DT_SOCK 12 +#define DT_WHT 14 + +/* XXX: We hardcode BSIZE and BSIZE_SHIFT here. fsys_ffs seems to do the same, + * so we should get away with it :-) */ +#define DEV_BSIZE 512 +#define DEV_BSHIFT 9 /* 2**9 = 512 */ +#define MAXBSIZE 8192 + +typedef unsigned int ino_t; + +#endif diff --git a/qemu/roms/openbios/fs/grubfs/vstafs.h b/qemu/roms/openbios/fs/grubfs/vstafs.h new file mode 100644 index 000000000..f240ffc4a --- /dev/null +++ b/qemu/roms/openbios/fs/grubfs/vstafs.h @@ -0,0 +1,89 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2001 Free Software Foundation, Inc. + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + + +#ifndef VSTAFS_H +#define VSTAFS_H 1 + + +#define LINE 16 +#define BLOCK_SIZE 512 +#define VSTAFS_START_DATA 320 + +struct bootrecord +{ + unsigned char flag; + unsigned char s_sector; + unsigned char s_head; + unsigned char s_cylinder; + unsigned char p_type; + unsigned char e_sector; + unsigned char e_head; + unsigned char e_cylinder; + unsigned long start_lba; + unsigned long nr_sector_lba; +}; + +struct alloc +{ + unsigned long a_start; + unsigned long a_len; +}; + +struct first_sector +{ + unsigned long fs_magic; + unsigned long fs_size; + unsigned long fs_extsize; + unsigned long fs_free; + struct alloc fs_freesecs[0]; +}; + +struct prot +{ + unsigned char len; + unsigned char pdefault; + unsigned char id[7]; + unsigned char bits[7]; +}; + +struct fs_file +{ + unsigned long prev; + unsigned long rev; + unsigned long len; + unsigned short type; + unsigned short nlink; + struct prot pprot; + unsigned int owner; + unsigned int extents; + struct alloc blocks[32]; + long fs_ctime, fs_mtime; /* it is not lon but time_t */ + char pad[16]; + char data[0]; +}; + +struct dir_entry +{ + char name[28]; + unsigned long start; +}; + +#endif /* ! VSTAFS_H */ diff --git a/qemu/roms/openbios/fs/grubfs/xfs.h b/qemu/roms/openbios/fs/grubfs/xfs.h new file mode 100644 index 000000000..0ed07042c --- /dev/null +++ b/qemu/roms/openbios/fs/grubfs/xfs.h @@ -0,0 +1,546 @@ +/* xfs.h - an extraction from xfsprogs-1.3.5/include/xfs* into one file */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2000 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (C) 2001 Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, + * Mountain View, CA 94043, or: + * + * http://www.sgi.com + * + * For further information regarding this notice, see: + * + * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ + */ + +#ifndef _BITS_TYPES_H +typedef signed char __int8_t; +typedef unsigned char __uint8_t; +typedef short __int16_t; +typedef unsigned short __uint16_t; +typedef int __int32_t; +typedef unsigned int __uint32_t; +typedef long long __int64_t; +typedef unsigned long long __uint64_t; +#endif + +typedef __uint64_t xfs_ino_t; +typedef __uint32_t xfs_agino_t; +typedef __int64_t xfs_daddr_t; +typedef __int64_t xfs_off_t; +typedef __uint8_t uuid_t[16]; + + +/* those are from xfs_types.h */ + +typedef __uint32_t xfs_agblock_t; /* blockno in alloc. group */ +typedef __uint32_t xfs_extlen_t; /* extent length in blocks */ +typedef __uint32_t xfs_agnumber_t; /* allocation group number */ +typedef __int32_t xfs_extnum_t; /* # of extents in a file */ +typedef __int16_t xfs_aextnum_t; /* # extents in an attribute fork */ +typedef __int64_t xfs_fsize_t; /* bytes in a file */ + +typedef __uint32_t xfs_dablk_t; /* dir/attr block number (in file) */ +typedef __uint32_t xfs_dahash_t; /* dir/attr hash value */ + +/* + * Disk based types: + */ +typedef __uint64_t xfs_dfsbno_t; /* blockno in filesystem (agno|agbno) */ +typedef __uint64_t xfs_drfsbno_t; /* blockno in filesystem (raw) */ +typedef __uint64_t xfs_drtbno_t; /* extent (block) in realtime area */ +typedef __uint64_t xfs_dfiloff_t; /* block number in a file */ + +typedef __uint64_t xfs_fsblock_t; /* blockno in filesystem (agno|agbno) */ +typedef __uint64_t xfs_fileoff_t; /* block number in a file */ +typedef __uint64_t xfs_filblks_t; /* number of blocks in a file */ + + +/* those are from xfs_sb.h */ + +#define XFS_SB_MAGIC 0x58465342 /* 'XFSB'*/ +#define XFS_SB_VERSION_4 4 /* 6.2+ - bitmask version */ +#define XFS_SB_VERSION_NUMBITS 0x000f + +typedef struct xfs_sb +{ + __uint32_t sb_magicnum; /* magic number == XFS_SB_MAGIC */ + __uint32_t sb_blocksize; /* logical block size, bytes */ + xfs_drfsbno_t sb_dblocks; /* number of data blocks */ + xfs_drfsbno_t sb_rblocks; /* number of realtime blocks */ + xfs_drtbno_t sb_rextents; /* number of realtime extents */ + uuid_t sb_uuid; /* file system unique id */ + xfs_dfsbno_t sb_logstart; /* starting block of log if internal */ + xfs_ino_t sb_rootino; /* root inode number */ + xfs_ino_t sb_rbmino; /* bitmap inode for realtime extents */ + xfs_ino_t sb_rsumino; /* summary inode for rt bitmap */ + xfs_agblock_t sb_rextsize; /* realtime extent size, blocks */ + xfs_agblock_t sb_agblocks; /* size of an allocation group */ + xfs_agnumber_t sb_agcount; /* number of allocation groups */ + xfs_extlen_t sb_rbmblocks; /* number of rt bitmap blocks */ + xfs_extlen_t sb_logblocks; /* number of log blocks */ + __uint16_t sb_versionnum; /* header version == XFS_SB_VERSION */ + __uint16_t sb_sectsize; /* volume sector size, bytes */ + __uint16_t sb_inodesize; /* inode size, bytes */ + __uint16_t sb_inopblock; /* inodes per block */ + char sb_fname[12]; /* file system name */ + __uint8_t sb_blocklog; /* log2 of sb_blocksize */ + __uint8_t sb_sectlog; /* log2 of sb_sectsize */ + __uint8_t sb_inodelog; /* log2 of sb_inodesize */ + __uint8_t sb_inopblog; /* log2 of sb_inopblock */ + __uint8_t sb_agblklog; /* log2 of sb_agblocks (rounded up) */ + __uint8_t sb_rextslog; /* log2 of sb_rextents */ + __uint8_t sb_inprogress; /* mkfs is in progress, don't mount */ + __uint8_t sb_imax_pct; /* max % of fs for inode space */ + /* statistics */ + /* + * These fields must remain contiguous. If you really + * want to change their layout, make sure you fix the + * code in xfs_trans_apply_sb_deltas(). + */ + __uint64_t sb_icount; /* allocated inodes */ + __uint64_t sb_ifree; /* free inodes */ + __uint64_t sb_fdblocks; /* free data blocks */ + __uint64_t sb_frextents; /* free realtime extents */ + /* + * End contiguous fields. + */ + xfs_ino_t sb_uquotino; /* user quota inode */ + xfs_ino_t sb_gquotino; /* group quota inode */ + __uint16_t sb_qflags; /* quota flags */ + __uint8_t sb_flags; /* misc. flags */ + __uint8_t sb_shared_vn; /* shared version number */ + xfs_extlen_t sb_inoalignmt; /* inode chunk alignment, fsblocks */ + __uint32_t sb_unit; /* stripe or raid unit */ + __uint32_t sb_width; /* stripe or raid width */ + __uint8_t sb_dirblklog; /* log2 of dir block size (fsbs) */ + __uint8_t sb_dummy[7]; /* padding */ +} xfs_sb_t; + + +/* those are from xfs_btree.h */ + +/* + * Long form header: bmap btrees. + */ +typedef struct xfs_btree_lblock +{ + __uint32_t bb_magic; /* magic number for block type */ + __uint16_t bb_level; /* 0 is a leaf */ + __uint16_t bb_numrecs; /* current # of data records */ + xfs_dfsbno_t bb_leftsib; /* left sibling block or NULLDFSBNO */ + xfs_dfsbno_t bb_rightsib; /* right sibling block or NULLDFSBNO */ +} xfs_btree_lblock_t; + +/* + * Combined header and structure, used by common code. + */ +typedef struct xfs_btree_hdr +{ + __uint32_t bb_magic; /* magic number for block type */ + __uint16_t bb_level; /* 0 is a leaf */ + __uint16_t bb_numrecs; /* current # of data records */ +} xfs_btree_hdr_t; + +typedef struct xfs_btree_block +{ + xfs_btree_hdr_t bb_h; /* header */ + union { + struct { + xfs_agblock_t bb_leftsib; + xfs_agblock_t bb_rightsib; + } s; /* short form pointers */ + struct { + xfs_dfsbno_t bb_leftsib; + xfs_dfsbno_t bb_rightsib; + } l; /* long form pointers */ + } bb_u; /* rest */ +} xfs_btree_block_t; + +/* those are from xfs_bmap_btree.h */ + +/* + * Bmap root header, on-disk form only. + */ +typedef struct xfs_bmdr_block +{ + __uint16_t bb_level; /* 0 is a leaf */ + __uint16_t bb_numrecs; /* current # of data records */ +} xfs_bmdr_block_t; + +/* + * Bmap btree record and extent descriptor. + * For 32-bit kernels, + * l0:31 is an extent flag (value 1 indicates non-normal). + * l0:0-30 and l1:9-31 are startoff. + * l1:0-8, l2:0-31, and l3:21-31 are startblock. + * l3:0-20 are blockcount. + * For 64-bit kernels, + * l0:63 is an extent flag (value 1 indicates non-normal). + * l0:9-62 are startoff. + * l0:0-8 and l1:21-63 are startblock. + * l1:0-20 are blockcount. + */ + +#define BMBT_USE_64 1 + +typedef struct xfs_bmbt_rec_32 +{ + __uint32_t l0, l1, l2, l3; +} xfs_bmbt_rec_32_t; +typedef struct xfs_bmbt_rec_64 +{ + __uint64_t l0, l1; +} xfs_bmbt_rec_64_t; + +#if BMBT_USE_64 +typedef __uint64_t xfs_bmbt_rec_base_t; /* use this for casts */ +typedef xfs_bmbt_rec_64_t xfs_bmbt_rec_t, xfs_bmdr_rec_t; +#else /* !BMBT_USE_64 */ +typedef __uint32_t xfs_bmbt_rec_base_t; /* use this for casts */ +typedef xfs_bmbt_rec_32_t xfs_bmbt_rec_t, xfs_bmdr_rec_t; +#endif /* BMBT_USE_64 */ + +/* + * Key structure for non-leaf levels of the tree. + */ +typedef struct xfs_bmbt_key +{ + xfs_dfiloff_t br_startoff; /* starting file offset */ +} xfs_bmbt_key_t, xfs_bmdr_key_t; + +typedef xfs_dfsbno_t xfs_bmbt_ptr_t, xfs_bmdr_ptr_t; /* btree pointer type */ + /* btree block header type */ +typedef struct xfs_btree_lblock xfs_bmbt_block_t; + + +/* those are from xfs_dir2.h */ +/* + * Directory version 2. + * There are 4 possible formats: + * shortform + * single block - data with embedded leaf at the end + * multiple data blocks, single leaf+freeindex block + * data blocks, node&leaf blocks (btree), freeindex blocks + * + * The shortform format is in xfs_dir2_sf.h. + * The single block format is in xfs_dir2_block.h. + * The data block format is in xfs_dir2_data.h. + * The leaf and freeindex block formats are in xfs_dir2_leaf.h. + * Node blocks are the same as the other version, in xfs_da_btree.h. + */ + +/* + * Byte offset in data block and shortform entry. + */ +typedef __uint16_t xfs_dir2_data_off_t; + +/* + * Byte offset in a directory. + */ +typedef xfs_off_t xfs_dir2_off_t; + +/* those are from xfs_da_btree.h */ +/*======================================================================== + * Directory Structure when greater than XFS_LBSIZE(mp) bytes. + *========================================================================*/ + +/* + * This structure is common to both leaf nodes and non-leaf nodes in the Btree. + * + * Is is used to manage a doubly linked list of all blocks at the same + * level in the Btree, and to identify which type of block this is. + */ +#define XFS_DIR2_LEAF1_MAGIC 0xd2f1 /* magic number: v2 dirlf single blks */ +#define XFS_DIR2_LEAFN_MAGIC 0xd2ff /* magic number: v2 dirlf multi blks */ + +typedef struct xfs_da_blkinfo { + xfs_dablk_t forw; /* previous block in list */ + xfs_dablk_t back; /* following block in list */ + __uint16_t magic; /* validity check on block */ + __uint16_t pad; /* unused */ +} xfs_da_blkinfo_t; + +/* + * This is the structure of the root and intermediate nodes in the Btree. + * The leaf nodes are defined above. + * + * Entries are not packed. + * + * Since we have duplicate keys, use a binary search but always follow + * all match in the block, not just the first match found. + */ + +typedef struct xfs_da_intnode { + struct xfs_da_node_hdr { /* constant-structure header block */ + xfs_da_blkinfo_t info; /* block type, links, etc. */ + __uint16_t count; /* count of active entries */ + __uint16_t level; /* level above leaves (leaf == 0) */ + } hdr; + struct xfs_da_node_entry { + xfs_dahash_t hashval; /* hash value for this descendant */ + xfs_dablk_t before; /* Btree block before this key */ + } btree[1]; /* variable sized array of keys */ +} xfs_da_intnode_t; + + +/* those are from xfs_dir2_data.h */ +/* + * Directory format 2, data block structures. + */ + +/* + * Constants. + */ +#define XFS_DIR2_DATA_FREE_TAG 0xffff +#define XFS_DIR2_DATA_FD_COUNT 3 + +/* + * Structures. + */ + +/* + * Describe a free area in the data block. + * The freespace will be formatted as a xfs_dir2_data_unused_t. + */ +typedef struct xfs_dir2_data_free { + xfs_dir2_data_off_t offset; /* start of freespace */ + xfs_dir2_data_off_t length; /* length of freespace */ +} xfs_dir2_data_free_t; + +/* + * Header for the data blocks. + * Always at the beginning of a directory-sized block. + * The code knows that XFS_DIR2_DATA_FD_COUNT is 3. + */ +typedef struct xfs_dir2_data_hdr { + __uint32_t magic; /* XFS_DIR2_DATA_MAGIC */ + /* or XFS_DIR2_BLOCK_MAGIC */ + xfs_dir2_data_free_t bestfree[XFS_DIR2_DATA_FD_COUNT]; +} xfs_dir2_data_hdr_t; + +/* + * Active entry in a data block. Aligned to 8 bytes. + * Tag appears as the last 2 bytes. + */ +typedef struct xfs_dir2_data_entry { + xfs_ino_t inumber; /* inode number */ + __uint8_t namelen; /* name length */ + __uint8_t name[1]; /* name bytes, no null */ + /* variable offset */ + xfs_dir2_data_off_t tag; /* starting offset of us */ +} xfs_dir2_data_entry_t; + +/* + * Unused entry in a data block. Aligned to 8 bytes. + * Tag appears as the last 2 bytes. + */ +typedef struct xfs_dir2_data_unused { + __uint16_t freetag; /* XFS_DIR2_DATA_FREE_TAG */ + xfs_dir2_data_off_t length; /* total free length */ + /* variable offset */ + xfs_dir2_data_off_t tag; /* starting offset of us */ +} xfs_dir2_data_unused_t; + +typedef union { + xfs_dir2_data_entry_t entry; + xfs_dir2_data_unused_t unused; +} xfs_dir2_data_union_t; + + +/* those are from xfs_dir2_leaf.h */ +/* + * Directory version 2, leaf block structures. + */ + +/* + * Leaf block header. + */ +typedef struct xfs_dir2_leaf_hdr { + xfs_da_blkinfo_t info; /* header for da routines */ + __uint16_t count; /* count of entries */ + __uint16_t stale; /* count of stale entries */ +} xfs_dir2_leaf_hdr_t; + + +/* those are from xfs_dir2_block.h */ +/* + * xfs_dir2_block.h + * Directory version 2, single block format structures + */ + +/* + * The single block format is as follows: + * xfs_dir2_data_hdr_t structure + * xfs_dir2_data_entry_t and xfs_dir2_data_unused_t structures + * xfs_dir2_leaf_entry_t structures + * xfs_dir2_block_tail_t structure + */ + +#define XFS_DIR2_BLOCK_MAGIC 0x58443242 /* XD2B: for one block dirs */ + +typedef struct xfs_dir2_block_tail { + __uint32_t count; /* count of leaf entries */ + __uint32_t stale; /* count of stale lf entries */ +} xfs_dir2_block_tail_t; + + +/* those are from xfs_dir2_sf.h */ + +/* + * Directory layout when stored internal to an inode. + * + * Small directories are packed as tightly as possible so as to + * fit into the literal area of the inode. + */ + +/* + * Inode number stored as 8 8-bit values. + */ +typedef struct { __uint8_t i[8]; } xfs_dir2_ino8_t; + +/* + * Inode number stored as 4 8-bit values. + * Works a lot of the time, when all the inode numbers in a directory + * fit in 32 bits. + */ +typedef struct { __uint8_t i[4]; } xfs_dir2_ino4_t; + +typedef union { + xfs_dir2_ino8_t i8; + xfs_dir2_ino4_t i4; +} xfs_dir2_inou_t; + +/* + * Normalized offset (in a data block) of the entry, really xfs_dir2_data_off_t. + * Only need 16 bits, this is the byte offset into the single block form. + */ +typedef struct { __uint8_t i[2]; } xfs_dir2_sf_off_t; + +/* + * The parent directory has a dedicated field, and the self-pointer must + * be calculated on the fly. + * + * Entries are packed toward the top as tightly as possible. The header + * and the elements must be bcopy()'d out into a work area to get correct + * alignment for the inode number fields. + */ +typedef struct xfs_dir2_sf_hdr { + __uint8_t count; /* count of entries */ + __uint8_t i8count; /* count of 8-byte inode #s */ + xfs_dir2_inou_t parent; /* parent dir inode number */ +} xfs_dir2_sf_hdr_t; + +typedef struct xfs_dir2_sf_entry { + __uint8_t namelen; /* actual name length */ + xfs_dir2_sf_off_t offset; /* saved offset */ + __uint8_t name[1]; /* name, variable size */ + xfs_dir2_inou_t inumber; /* inode number, var. offset */ +} xfs_dir2_sf_entry_t; + +typedef struct xfs_dir2_sf { + xfs_dir2_sf_hdr_t hdr; /* shortform header */ + xfs_dir2_sf_entry_t list[1]; /* shortform entries */ +} xfs_dir2_sf_t; + +/* those are from xfs_dinode.h */ + +#define XFS_DINODE_VERSION_1 1 +#define XFS_DINODE_VERSION_2 2 +#define XFS_DINODE_MAGIC 0x494e /* 'IN' */ + +/* + * Disk inode structure. + * This is just the header; the inode is expanded to fill a variable size + * with the last field expanding. It is split into the core and "other" + * because we only need the core part in the in-core inode. + */ +typedef struct xfs_timestamp { + __int32_t t_sec; /* timestamp seconds */ + __int32_t t_nsec; /* timestamp nanoseconds */ +} xfs_timestamp_t; + +/* + * Note: Coordinate changes to this structure with the XFS_DI_* #defines + * below and the offsets table in xfs_ialloc_log_di(). + */ +typedef struct xfs_dinode_core +{ + __uint16_t di_magic; /* inode magic # = XFS_DINODE_MAGIC */ + __uint16_t di_mode; /* mode and type of file */ + __int8_t di_version; /* inode version */ + __int8_t di_format; /* format of di_c data */ + __uint16_t di_onlink; /* old number of links to file */ + __uint32_t di_uid; /* owner's user id */ + __uint32_t di_gid; /* owner's group id */ + __uint32_t di_nlink; /* number of links to file */ + __uint16_t di_projid; /* owner's project id */ + __uint8_t di_pad[10]; /* unused, zeroed space */ + xfs_timestamp_t di_atime; /* time last accessed */ + xfs_timestamp_t di_mtime; /* time last modified */ + xfs_timestamp_t di_ctime; /* time created/inode modified */ + xfs_fsize_t di_size; /* number of bytes in file */ + xfs_drfsbno_t di_nblocks; /* # of direct & btree blocks used */ + xfs_extlen_t di_extsize; /* basic/minimum extent size for file */ + xfs_extnum_t di_nextents; /* number of extents in data fork */ + xfs_aextnum_t di_anextents; /* number of extents in attribute fork*/ + __uint8_t di_forkoff; /* attr fork offs, <<3 for 64b align */ + __int8_t di_aformat; /* format of attr fork's data */ + __uint32_t di_dmevmask; /* DMIG event mask */ + __uint16_t di_dmstate; /* DMIG state info */ + __uint16_t di_flags; /* random flags, XFS_DIFLAG_... */ + __uint32_t di_gen; /* generation number */ +} xfs_dinode_core_t; + +typedef struct xfs_dinode +{ + xfs_dinode_core_t di_core; + xfs_agino_t di_next_unlinked;/* agi unlinked list ptr */ + union { + xfs_bmdr_block_t di_bmbt; /* btree root block */ + xfs_bmbt_rec_32_t di_bmx[1]; /* extent list */ + xfs_dir2_sf_t di_dir2sf; /* shortform directory v2 */ + char di_c[1]; /* local contents */ + } di_u; +} xfs_dinode_t; + +/* + * Values for di_format + */ +typedef enum xfs_dinode_fmt +{ + XFS_DINODE_FMT_DEV, /* CHR, BLK: di_dev */ + XFS_DINODE_FMT_LOCAL, /* DIR, REG: di_c */ + /* LNK: di_symlink */ + XFS_DINODE_FMT_EXTENTS, /* DIR, REG, LNK: di_bmx */ + XFS_DINODE_FMT_BTREE, /* DIR, REG, LNK: di_bmbt */ + XFS_DINODE_FMT_UUID /* MNT: di_uuid */ +} xfs_dinode_fmt_t; + +/* + * File types (mode field) + */ +#define IFMT 0170000 /* type of file */ +#define IFDIR 0040000 /* directory */ +#define IFREG 0100000 /* regular */ +#define IFLNK 0120000 /* symbolic link */ diff --git a/qemu/roms/openbios/fs/hfs/block.c b/qemu/roms/openbios/fs/hfs/block.c new file mode 100644 index 000000000..0b65a1f3b --- /dev/null +++ b/qemu/roms/openbios/fs/hfs/block.c @@ -0,0 +1,612 @@ +/* +* libhfs - library for reading and writing Macintosh HFS volumes +* Copyright (C) 1996-1998 Robert Leslie +* +* 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 2 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, write to the Free Software +* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +* MA 02110-1301, USA. +* +* $Id: block.c,v 1.11 1998/11/02 22:08:52 rob Exp $ +*/ + +#include "config.h" + +#include "libhfs.h" +#include "volume.h" +#include "block.h" +#include "os.h" + +#define INUSE(b) ((b)->flags & HFS_BUCKET_INUSE) +#define DIRTY(b) ((b)->flags & HFS_BUCKET_DIRTY) + +/* + * NAME: block->init() + * DESCRIPTION: initialize a volume's block cache + */ +int b_init(hfsvol *vol) +{ + bcache *cache; + int i; + + ASSERT(vol->cache == 0); + + cache = ALLOC(bcache, 1); + if (cache == NULL) + ERROR(ENOMEM, NULL); + + vol->cache = cache; + + cache->vol = vol; + cache->tail = &cache->chain[HFS_CACHESZ - 1]; + + cache->hits = 0; + cache->misses = 0; + + for (i = 0; i < HFS_CACHESZ; ++i) + { + bucket *b = &cache->chain[i]; + + b->flags = 0; + b->count = 0; + + b->bnum = 0; + b->data = &cache->pool[i]; + + b->cnext = b + 1; + b->cprev = b - 1; + + b->hnext = NULL; + b->hprev = NULL; + } + + cache->chain[0].cprev = cache->tail; + cache->tail->cnext = &cache->chain[0]; + + for (i = 0; i < HFS_HASHSZ; ++i) + cache->hash[i] = NULL; + + return 0; + +fail: + return -1; +} + +# ifdef DEBUG +/* + * NAME: block->showstats() + * DESCRIPTION: output cache hit/miss ratio + */ +void b_showstats(const bcache *cache) +{ + fprintf(stderr, "BLOCK: CACHE vol 0x%lx \"%s\" hit/miss ratio = %.3f\n", + (unsigned long) cache->vol, cache->vol->mdb.drVN, + (float) cache->hits / (float) cache->misses); +} + +/* + * NAME: block->dumpcache() + * DESCRIPTION: dump the cache tables for a volume + */ +void b_dumpcache(const bcache *cache) +{ + const bucket *b; + int i; + + fprintf(stderr, "BLOCK CACHE DUMP:\n"); + + for (i = 0, b = cache->tail->cnext; i < HFS_CACHESZ; ++i, b = b->cnext) + { + if (INUSE(b)) + { + fprintf(stderr, "\t %lu", b->bnum); + if (DIRTY(b)) + fprintf(stderr, "*"); + + fprintf(stderr, ":%u", b->count); + } + } + + fprintf(stderr, "\n"); + + fprintf(stderr, "BLOCK HASH DUMP:\n"); + + for (i = 0; i < HFS_HASHSZ; ++i) + { + int seen = 0; + + for (b = cache->hash[i]; b; b = b->hnext) + { + if (! seen) + fprintf(stderr, " %d:", i); + + if (INUSE(b)) + { + fprintf(stderr, " %lu", b->bnum); + if (DIRTY(b)) + fprintf(stderr, "*"); + + fprintf(stderr, ":%u", b->count); + } + + seen = 1; + } + + if (seen) + fprintf(stderr, "\n"); + } +} +# endif + +/* + * NAME: fillchain() + * DESCRIPTION: fill a chain of bucket buffers with a single read + */ +static +int fillchain(hfsvol *vol, bucket **bptr, unsigned int *count) +{ + bucket *blist[HFS_BLOCKBUFSZ], **start = bptr; + unsigned long bnum=-2; // XXX + unsigned int len, i; + + for (len = 0; len < HFS_BLOCKBUFSZ && + (unsigned int) (bptr - start) < *count; ++bptr) + { + if (INUSE(*bptr)) + continue; + + if (len > 0 && (*bptr)->bnum != bnum) + break; + + blist[len++] = *bptr; + bnum = (*bptr)->bnum + 1; + } + + *count = bptr - start; + + if (len == 0) + goto done; + else if (len == 1) + { + if (b_readpb(vol, vol->vstart + blist[0]->bnum, + blist[0]->data, 1) == -1) + goto fail; + } + else + { + block buffer[HFS_BLOCKBUFSZ]; + + if (b_readpb(vol, vol->vstart + blist[0]->bnum, buffer, len) == -1) + goto fail; + + for (i = 0; i < len; ++i) + memcpy(blist[i]->data, buffer[i], HFS_BLOCKSZ); + } + + for (i = 0; i < len; ++i) + { + blist[i]->flags |= HFS_BUCKET_INUSE; + blist[i]->flags &= ~HFS_BUCKET_DIRTY; + } + +done: + return 0; + +fail: + return -1; +} + + +/* + * NAME: compare() + * DESCRIPTION: comparison function for qsort of cache bucket pointers + */ +static +int compare(const bucket **b1, const bucket **b2) +{ + long diff; + + diff = (*b1)->bnum - (*b2)->bnum; + + if (diff < 0) + return -1; + else if (diff > 0) + return 1; + else + return 0; +} + +/* + * NAME: dobuckets() + * DESCRIPTION: fill or flush an array of cache buckets to a volume + */ +static +int dobuckets(hfsvol *vol, bucket **chain, unsigned int len, + int (*func)(hfsvol *, bucket **, unsigned int *)) +{ + unsigned int count, i; + int result = 0; + + qsort(chain, len, sizeof(*chain), + (int (*)(const void *, const void *)) compare); + + for (i = 0; i < len; i += count) + { + count = len - i; + if (func(vol, chain + i, &count) == -1) + result = -1; + } + + return result; +} + +# define fillbuckets(vol, chain, len) dobuckets(vol, chain, len, fillchain) + +/* + * NAME: block->finish() + * DESCRIPTION: commit and free a volume's block cache + */ +int b_finish(hfsvol *vol) +{ + int result = 0; + + if (vol->cache == NULL) + goto done; + +# ifdef DEBUG + b_dumpcache(vol->cache); +# endif + + FREE(vol->cache); + vol->cache = NULL; + +done: + return result; +} + +/* + * NAME: findbucket() + * DESCRIPTION: locate a bucket in the cache, and/or its hash slot + */ +static +bucket *findbucket(bcache *cache, unsigned long bnum, bucket ***hslot) +{ + bucket *b; + + *hslot = &cache->hash[bnum & (HFS_HASHSZ - 1)]; + + for (b = **hslot; b; b = b->hnext) + { + if (INUSE(b) && b->bnum == bnum) + break; + } + + return b; +} + +/* + * NAME: reuse() + * DESCRIPTION: free a bucket for reuse, flushing if necessary + */ +static +int reuse(bcache *cache, bucket *b, unsigned long bnum) +{ + bucket *bptr; + int i; + +# ifdef DEBUG + if (INUSE(b)) + fprintf(stderr, "BLOCK: CACHE reusing bucket containing " + "vol 0x%lx block %lu:%u\n", + (unsigned long) cache->vol, b->bnum, b->count); +# endif + + if (INUSE(b) && DIRTY(b)) + { + /* flush most recently unused buckets */ + + for (bptr = b, i = 0; i < HFS_BLOCKBUFSZ; ++i) + { + bptr = bptr->cprev; + } + } + + b->flags &= ~HFS_BUCKET_INUSE; + b->count = 1; + b->bnum = bnum; + + return 0; +} + +/* + * NAME: cplace() + * DESCRIPTION: move a bucket to an appropriate place near head of the chain + */ +static +void cplace(bcache *cache, bucket *b) +{ + bucket *p; + + for (p = cache->tail->cnext; p->count > 1; p = p->cnext) + --p->count; + + b->cnext->cprev = b->cprev; + b->cprev->cnext = b->cnext; + + if (cache->tail == b) + cache->tail = b->cprev; + + b->cprev = p->cprev; + b->cnext = p; + + p->cprev->cnext = b; + p->cprev = b; +} + +/* + * NAME: hplace() + * DESCRIPTION: move a bucket to the head of its hash slot + */ +static +void hplace(bucket **hslot, bucket *b) +{ + if (*hslot != b) + { + if (b->hprev) + *b->hprev = b->hnext; + if (b->hnext) + b->hnext->hprev = b->hprev; + + b->hprev = hslot; + b->hnext = *hslot; + + if (*hslot) + (*hslot)->hprev = &b->hnext; + + *hslot = b; + } +} + +/* + * NAME: getbucket() + * DESCRIPTION: fetch a bucket from the cache, or an empty one to be filled + */ +static +bucket *getbucket(bcache *cache, unsigned long bnum, int fill) +{ + bucket **hslot, *b, *p, *bptr, + *chain[HFS_BLOCKBUFSZ], **slots[HFS_BLOCKBUFSZ]; + + b = findbucket(cache, bnum, &hslot); + + if (b) + { + /* cache hit; move towards head of cache chain */ + + ++cache->hits; + + if (++b->count > b->cprev->count && + b != cache->tail->cnext) + { + p = b->cprev; + + p->cprev->cnext = b; + b->cnext->cprev = p; + + p->cnext = b->cnext; + b->cprev = p->cprev; + + p->cprev = b; + b->cnext = p; + + if (cache->tail == b) + cache->tail = p; + } + } + else + { + /* cache miss; reuse least-used cache bucket */ + + ++cache->misses; + + b = cache->tail; + + if (reuse(cache, b, bnum) == -1) + goto fail; + + if (fill) + { + unsigned int len = 0; + + chain[len] = b; + slots[len++] = hslot; + + for (bptr = b->cprev; + len < (HFS_BLOCKBUFSZ >> 1) && ++bnum < cache->vol->vlen; + bptr = bptr->cprev) + { + if (findbucket(cache, bnum, &hslot)) + break; + + if (reuse(cache, bptr, bnum) == -1) + goto fail; + + chain[len] = bptr; + slots[len++] = hslot; + } + + if (fillbuckets(cache->vol, chain, len) == -1) + goto fail; + + while (--len) + { + cplace(cache, chain[len]); + hplace(slots[len], chain[len]); + } + + hslot = slots[0]; + } + + /* move bucket to appropriate place in chain */ + + cplace(cache, b); + } + + /* insert at front of hash chain */ + + hplace(hslot, b); + + return b; + +fail: + return NULL; +} + +/* + * NAME: block->readpb() + * DESCRIPTION: read blocks from the physical medium (bypassing cache) + */ +int b_readpb(hfsvol *vol, unsigned long bnum, block *bp, unsigned int blen) +{ + unsigned long nblocks; + +# ifdef DEBUG + fprintf(stderr, "BLOCK: READ vol 0x%lx block %lu", + (unsigned long) vol, bnum); + if (blen > 1) + fprintf(stderr, "+%u[..%lu]\n", blen - 1, bnum + blen - 1); + else + fprintf(stderr, "\n"); +# endif + + nblocks = os_seek(vol->os_fd, bnum, HFS_BLOCKSZ_BITS ); + if (nblocks == (unsigned long) -1) + goto fail; + + if (nblocks != bnum) + ERROR(EIO, "block seek failed for read"); + + nblocks = os_read(vol->os_fd, bp, blen, HFS_BLOCKSZ_BITS); + if (nblocks == (unsigned long) -1) + goto fail; + + if (nblocks != blen) + ERROR(EIO, "incomplete block read"); + + return 0; + +fail: + return -1; +} + + +/* + * NAME: block->readlb() + * DESCRIPTION: read a logical block from a volume (or from the cache) + */ +int b_readlb(hfsvol *vol, unsigned long bnum, block *bp) +{ + if (vol->vlen > 0 && bnum >= vol->vlen) + ERROR(EIO, "read nonexistent logical block"); + + if (vol->cache) + { + bucket *b; + + b = getbucket(vol->cache, bnum, 1); + if (b == NULL) + goto fail; + + memcpy(bp, b->data, HFS_BLOCKSZ); + } + else + { + if (b_readpb(vol, vol->vstart + bnum, bp, 1) == -1) + goto fail; + } + + return 0; + +fail: + return -1; +} + +/* + * NAME: block->readab() + * DESCRIPTION: read a block from an allocation block from a volume + */ +int b_readab(hfsvol *vol, unsigned int anum, unsigned int index, block *bp) +{ + /* verify the allocation block exists and is marked as in-use */ + + if (anum >= vol->mdb.drNmAlBlks) + ERROR(EIO, "read nonexistent allocation block"); + else if (vol->vbm && ! BMTST(vol->vbm, anum)) + ERROR(EIO, "read unallocated block"); + + return b_readlb(vol, vol->mdb.drAlBlSt + anum * vol->lpa + index, bp); + +fail: + return -1; +} + + +/* + * NAME: block->size() + * DESCRIPTION: return the number of physical blocks on a volume's medium + */ +unsigned long b_size(hfsvol *vol) +{ + unsigned long low, high, mid; + block b; + + high = os_seek(vol->os_fd, -1, HFS_BLOCKSZ_BITS); + + if (high != (unsigned long) -1 && high > 0) + return high; + + /* manual size detection: first check there is at least 1 block in medium */ + + if (b_readpb(vol, 0, &b, 1) == -1) + ERROR(EIO, "size of medium indeterminable or empty"); + + for (low = 0, high = 2880; + high > 0 && b_readpb(vol, high - 1, &b, 1) != -1; + high <<= 1) + low = high - 1; + + if (high == 0) + ERROR(EIO, "size of medium indeterminable or too large"); + + /* common case: 1440K floppy */ + + if (low == 2879 && b_readpb(vol, 2880, &b, 1) == -1) + return 2880; + + /* binary search for other sizes */ + + while (low < high - 1) + { + mid = (low + high) >> 1; + + if (b_readpb(vol, mid, &b, 1) == -1) + high = mid; + else + low = mid; + } + + return low + 1; + +fail: + return 0; +} diff --git a/qemu/roms/openbios/fs/hfs/btree.c b/qemu/roms/openbios/fs/hfs/btree.c new file mode 100644 index 000000000..cd5c85347 --- /dev/null +++ b/qemu/roms/openbios/fs/hfs/btree.c @@ -0,0 +1,230 @@ +/* + * libhfs - library for reading and writing Macintosh HFS volumes + * Copyright (C) 1996-1998 Robert Leslie + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * $Id: btree.c,v 1.10 1998/11/02 22:08:54 rob Exp $ + */ + +#include "config.h" + +#include "libhfs.h" +#include "btree.h" +#include "data.h" +#include "file.h" +#include "block.h" +#include "node.h" + +/* + * NAME: btree->getnode() + * DESCRIPTION: retrieve a numbered node from a B*-tree file + */ +int bt_getnode(node *np, btree *bt, unsigned long nnum) +{ + block *bp = &np->data; + const byte *ptr; + int i; + + np->bt = bt; + np->nnum = nnum; + +# if 0 + fprintf(stderr, "BTREE: GET vol \"%s\" btree \"%s\" node %lu\n", + bt->f.vol->mdb.drVN, bt->f.name, np->nnum); +# endif + + /* verify the node exists and is marked as in-use */ + + if (nnum > 0 && nnum >= bt->hdr.bthNNodes) + ERROR(EIO, "read nonexistent b*-tree node"); + else if (bt->map && ! BMTST(bt->map, nnum)) + ERROR(EIO, "read unallocated b*-tree node"); + + if (f_getblock(&bt->f, nnum, bp) == -1) + goto fail; + + ptr = *bp; + + d_fetchul(&ptr, &np->nd.ndFLink); + d_fetchul(&ptr, &np->nd.ndBLink); + d_fetchsb(&ptr, &np->nd.ndType); + d_fetchsb(&ptr, &np->nd.ndNHeight); + d_fetchuw(&ptr, &np->nd.ndNRecs); + d_fetchsw(&ptr, &np->nd.ndResv2); + + if (np->nd.ndNRecs > HFS_MAX_NRECS) + ERROR(EIO, "too many b*-tree node records"); + + i = np->nd.ndNRecs + 1; + + ptr = *bp + HFS_BLOCKSZ - (2 * i); + + while (i--) + d_fetchuw(&ptr, &np->roff[i]); + + return 0; + +fail: + return -1; +} + + +/* + * NAME: btree->readhdr() + * DESCRIPTION: read the header node of a B*-tree + */ +int bt_readhdr(btree *bt) +{ + const byte *ptr; + byte *map = NULL; + int i; + unsigned long nnum; + + if (bt_getnode(&bt->hdrnd, bt, 0) == -1) + goto fail; + + if (bt->hdrnd.nd.ndType != ndHdrNode || + bt->hdrnd.nd.ndNRecs != 3 || + bt->hdrnd.roff[0] != 0x00e || + bt->hdrnd.roff[1] != 0x078 || + bt->hdrnd.roff[2] != 0x0f8 || + bt->hdrnd.roff[3] != 0x1f8) + ERROR(EIO, "malformed b*-tree header node"); + + /* read header record */ + + ptr = HFS_NODEREC(bt->hdrnd, 0); + + d_fetchuw(&ptr, &bt->hdr.bthDepth); + d_fetchul(&ptr, &bt->hdr.bthRoot); + d_fetchul(&ptr, &bt->hdr.bthNRecs); + d_fetchul(&ptr, &bt->hdr.bthFNode); + d_fetchul(&ptr, &bt->hdr.bthLNode); + d_fetchuw(&ptr, &bt->hdr.bthNodeSize); + d_fetchuw(&ptr, &bt->hdr.bthKeyLen); + d_fetchul(&ptr, &bt->hdr.bthNNodes); + d_fetchul(&ptr, &bt->hdr.bthFree); + + for (i = 0; i < 76; ++i) + d_fetchsb(&ptr, &bt->hdr.bthResv[i]); + + if (bt->hdr.bthNodeSize != HFS_BLOCKSZ) + ERROR(EINVAL, "unsupported b*-tree node size"); + + /* read map record; construct btree bitmap */ + /* don't set bt->map until we're done, since getnode() checks it */ + + map = ALLOC(byte, HFS_MAP1SZ); + if (map == NULL) + ERROR(ENOMEM, NULL); + + memcpy(map, HFS_NODEREC(bt->hdrnd, 2), HFS_MAP1SZ); + bt->mapsz = HFS_MAP1SZ; + + /* read continuation map records, if any */ + + nnum = bt->hdrnd.nd.ndFLink; + + while (nnum) + { + node n; + byte *newmap; + + if (bt_getnode(&n, bt, nnum) == -1) + goto fail; + + if (n.nd.ndType != ndMapNode || + n.nd.ndNRecs != 1 || + n.roff[0] != 0x00e || + n.roff[1] != 0x1fa) + ERROR(EIO, "malformed b*-tree map node"); + + newmap = REALLOC(map, byte, bt->mapsz + HFS_MAPXSZ); + if (newmap == NULL) + ERROR(ENOMEM, NULL); + + map = newmap; + + memcpy(map + bt->mapsz, HFS_NODEREC(n, 0), HFS_MAPXSZ); + bt->mapsz += HFS_MAPXSZ; + + nnum = n.nd.ndFLink; + } + + bt->map = map; + + return 0; + +fail: + FREE(map); + return -1; +} + + +/* + * NAME: btree->search() + * DESCRIPTION: locate a data record given a search key + */ +int bt_search(btree *bt, const byte *key, node *np) +{ + int found = 0; + unsigned long nnum; + + nnum = bt->hdr.bthRoot; + + if (nnum == 0) + ERROR(ENOENT, NULL); + + while (1) + { + const byte *rec; + + if (bt_getnode(np, bt, nnum) == -1) + { + found = -1; + goto fail; + } + + found = n_search(np, key); + + switch (np->nd.ndType) + { + case ndIndxNode: + if (np->rnum == -1) + ERROR(ENOENT, NULL); + + rec = HFS_NODEREC(*np, np->rnum); + nnum = d_getul(HFS_RECDATA(rec)); + + break; + + case ndLeafNode: + if (! found) + ERROR(ENOENT, NULL); + + goto done; + + default: + found = -1; + ERROR(EIO, "unexpected b*-tree node"); + } + } + +done: +fail: + return found; +} diff --git a/qemu/roms/openbios/fs/hfs/build.xml b/qemu/roms/openbios/fs/hfs/build.xml new file mode 100644 index 000000000..2ac6fdbb3 --- /dev/null +++ b/qemu/roms/openbios/fs/hfs/build.xml @@ -0,0 +1,15 @@ +<build> + <library name="fs" type="static" target="target"> + <object source="block.c" flags="-I$(SRCDIR)/fs/hfs/include -I$(SRCDIR)/fs/ -fno-strict-aliasing" condition="HFS"/> + <object source="btree.c" flags="-I$(SRCDIR)/fs/hfs/include -I$(SRCDIR)/fs/ -fno-strict-aliasing" condition="HFS"/> + <object source="data.c" flags="-I$(SRCDIR)/fs/hfs/include -I$(SRCDIR)/fs/ -fno-strict-aliasing" condition="HFS"/> + <object source="file.c" flags="-I$(SRCDIR)/fs/hfs/include -I$(SRCDIR)/fs/ -fno-strict-aliasing" condition="HFS"/> + <object source="hfs.c" flags="-I$(SRCDIR)/fs/hfs/include -I$(SRCDIR)/fs/ -fno-strict-aliasing" condition="HFS"/> + <object source="low.c" flags="-I$(SRCDIR)/fs/hfs/include -I$(SRCDIR)/fs/ -fno-strict-aliasing" condition="HFS"/> + <object source="medium.c" flags="-I$(SRCDIR)/fs/hfs/include -I$(SRCDIR)/fs/ -fno-strict-aliasing" condition="HFS"/> + <object source="node.c" flags="-I$(SRCDIR)/fs/hfs/include -I$(SRCDIR)/fs/ -fno-strict-aliasing" condition="HFS"/> + <object source="record.c" flags="-I$(SRCDIR)/fs/hfs/include -I$(SRCDIR)/fs/ -fno-strict-aliasing" condition="HFS"/> + <object source="volume.c" flags="-I$(SRCDIR)/fs/hfs/include -I$(SRCDIR)/fs/ -fno-strict-aliasing" condition="HFS"/> + <object source="hfs_fs.c" flags="-I$(SRCDIR)/fs/hfs/include -I$(SRCDIR)/fs/ -fno-strict-aliasing" condition="HFS"/> + </library> +</build> diff --git a/qemu/roms/openbios/fs/hfs/data.c b/qemu/roms/openbios/fs/hfs/data.c new file mode 100644 index 000000000..a0e4a8ea7 --- /dev/null +++ b/qemu/roms/openbios/fs/hfs/data.c @@ -0,0 +1,476 @@ +/* + * libhfs - library for reading and writing Macintosh HFS volumes + * Copyright (C) 1996-1998 Robert Leslie + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * $Id: data.c,v 1.7 1998/11/02 22:08:57 rob Exp $ + */ + +#include "config.h" +#include "data.h" + +#define TIMEDIFF 2082844800UL + +static +time_t tzdiff = -1; + +static const +unsigned char hfs_charorder[256] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + + 0x20, 0x22, 0x23, 0x28, 0x29, 0x2a, 0x2b, 0x2c, + 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, + 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, + 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, + + 0x47, 0x48, 0x58, 0x5a, 0x5e, 0x60, 0x67, 0x69, + 0x6b, 0x6d, 0x73, 0x75, 0x77, 0x79, 0x7b, 0x7f, + 0x8d, 0x8f, 0x91, 0x93, 0x96, 0x98, 0x9f, 0xa1, + 0xa3, 0xa5, 0xa8, 0xaa, 0xab, 0xac, 0xad, 0xae, + + 0x54, 0x48, 0x58, 0x5a, 0x5e, 0x60, 0x67, 0x69, + 0x6b, 0x6d, 0x73, 0x75, 0x77, 0x79, 0x7b, 0x7f, + 0x8d, 0x8f, 0x91, 0x93, 0x96, 0x98, 0x9f, 0xa1, + 0xa3, 0xa5, 0xa8, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, + + 0x4c, 0x50, 0x5c, 0x62, 0x7d, 0x81, 0x9a, 0x55, + 0x4a, 0x56, 0x4c, 0x4e, 0x50, 0x5c, 0x62, 0x64, + 0x65, 0x66, 0x6f, 0x70, 0x71, 0x72, 0x7d, 0x89, + 0x8a, 0x8b, 0x81, 0x83, 0x9c, 0x9d, 0x9e, 0x9a, + + 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0x95, + 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0x52, 0x85, + 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, + 0xc9, 0xca, 0xcb, 0x57, 0x8c, 0xcc, 0x52, 0x85, + + 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0x26, + 0x27, 0xd4, 0x20, 0x4a, 0x4e, 0x83, 0x87, 0x87, + 0xd5, 0xd6, 0x24, 0x25, 0x2d, 0x2e, 0xd7, 0xd8, + 0xa7, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff +}; + +/* + * NAME: data->getsb() + * DESCRIPTION: marshal 1 signed byte into local host format + */ +signed char d_getsb(register const unsigned char *ptr) +{ + return ptr[0]; +} + +/* + * NAME: data->getub() + * DESCRIPTION: marshal 1 unsigned byte into local host format + */ +unsigned char d_getub(register const unsigned char *ptr) +{ + return ptr[0]; +} + +/* + * NAME: data->getsw() + * DESCRIPTION: marshal 2 signed bytes into local host format + */ +signed short d_getsw(register const unsigned char *ptr) +{ + return + ((( signed short) ptr[0] << 8) | + ((unsigned short) ptr[1] << 0)); +} + +/* + * NAME: data->getuw() + * DESCRIPTION: marshal 2 unsigned bytes into local host format + */ +unsigned short d_getuw(register const unsigned char *ptr) +{ + return + (((unsigned short) ptr[0] << 8) | + ((unsigned short) ptr[1] << 0)); +} + +/* + * NAME: data->getsl() + * DESCRIPTION: marshal 4 signed bytes into local host format + */ +signed long d_getsl(register const unsigned char *ptr) +{ + return + ((( signed long) ptr[0] << 24) | + ((unsigned long) ptr[1] << 16) | + ((unsigned long) ptr[2] << 8) | + ((unsigned long) ptr[3] << 0)); +} + +/* + * NAME: data->getul() + * DESCRIPTION: marshal 4 unsigned bytes into local host format + */ +unsigned long d_getul(register const unsigned char *ptr) +{ + return + (((unsigned long) ptr[0] << 24) | + ((unsigned long) ptr[1] << 16) | + ((unsigned long) ptr[2] << 8) | + ((unsigned long) ptr[3] << 0)); +} + +/* + * NAME: data->putsb() + * DESCRIPTION: marshal 1 signed byte out in big-endian format + */ +void d_putsb(register unsigned char *ptr, + register signed char data) +{ + *ptr = data; +} + +/* + * NAME: data->putub() + * DESCRIPTION: marshal 1 unsigned byte out in big-endian format + */ +void d_putub(register unsigned char *ptr, + register unsigned char data) +{ + *ptr = data; +} + +/* + * NAME: data->putsw() + * DESCRIPTION: marshal 2 signed bytes out in big-endian format + */ +void d_putsw(register unsigned char *ptr, + register signed short data) +{ + *ptr++ = ((unsigned short) data & 0xff00) >> 8; + *ptr = ((unsigned short) data & 0x00ff) >> 0; +} + +/* + * NAME: data->putuw() + * DESCRIPTION: marshal 2 unsigned bytes out in big-endian format + */ +void d_putuw(register unsigned char *ptr, + register unsigned short data) +{ + *ptr++ = (data & 0xff00) >> 8; + *ptr = (data & 0x00ff) >> 0; +} + +/* + * NAME: data->putsl() + * DESCRIPTION: marshal 4 signed bytes out in big-endian format + */ +void d_putsl(register unsigned char *ptr, + register signed long data) +{ + *ptr++ = ((unsigned long) data & 0xff000000UL) >> 24; + *ptr++ = ((unsigned long) data & 0x00ff0000UL) >> 16; + *ptr++ = ((unsigned long) data & 0x0000ff00UL) >> 8; + *ptr = ((unsigned long) data & 0x000000ffUL) >> 0; +} + +/* + * NAME: data->putul() + * DESCRIPTION: marshal 4 unsigned bytes out in big-endian format + */ +void d_putul(register unsigned char *ptr, + register unsigned long data) +{ + *ptr++ = (data & 0xff000000UL) >> 24; + *ptr++ = (data & 0x00ff0000UL) >> 16; + *ptr++ = (data & 0x0000ff00UL) >> 8; + *ptr = (data & 0x000000ffUL) >> 0; +} + +/* + * NAME: data->fetchsb() + * DESCRIPTION: incrementally retrieve a signed byte of data + */ +void d_fetchsb(register const unsigned char **ptr, + register signed char *dest) +{ + *dest = *(*ptr)++; +} + +/* + * NAME: data->fetchub() + * DESCRIPTION: incrementally retrieve an unsigned byte of data + */ +void d_fetchub(register const unsigned char **ptr, + register unsigned char *dest) +{ + *dest = *(*ptr)++; +} + +/* + * NAME: data->fetchsw() + * DESCRIPTION: incrementally retrieve a signed word of data + */ +void d_fetchsw(register const unsigned char **ptr, + register signed short *dest) +{ + *dest = + ((( signed short) (*ptr)[0] << 8) | + ((unsigned short) (*ptr)[1] << 0)); + *ptr += 2; +} + +/* + * NAME: data->fetchuw() + * DESCRIPTION: incrementally retrieve an unsigned word of data + */ +void d_fetchuw(register const unsigned char **ptr, + register unsigned short *dest) +{ + *dest = + (((unsigned short) (*ptr)[0] << 8) | + ((unsigned short) (*ptr)[1] << 0)); + *ptr += 2; +} + +/* + * NAME: data->fetchsl() + * DESCRIPTION: incrementally retrieve a signed long word of data + */ +void d_fetchsl(register const unsigned char **ptr, + register signed long *dest) +{ + *dest = + ((( signed long) (*ptr)[0] << 24) | + ((unsigned long) (*ptr)[1] << 16) | + ((unsigned long) (*ptr)[2] << 8) | + ((unsigned long) (*ptr)[3] << 0)); + *ptr += 4; +} + +/* + * NAME: data->fetchul() + * DESCRIPTION: incrementally retrieve an unsigned long word of data + */ +void d_fetchul(register const unsigned char **ptr, + register unsigned long *dest) +{ + *dest = + (((unsigned long) (*ptr)[0] << 24) | + ((unsigned long) (*ptr)[1] << 16) | + ((unsigned long) (*ptr)[2] << 8) | + ((unsigned long) (*ptr)[3] << 0)); + *ptr += 4; +} + +/* + * NAME: data->storesb() + * DESCRIPTION: incrementally store a signed byte of data + */ +void d_storesb(register unsigned char **ptr, + register signed char data) +{ + *(*ptr)++ = data; +} + +/* + * NAME: data->storeub() + * DESCRIPTION: incrementally store an unsigned byte of data + */ +void d_storeub(register unsigned char **ptr, + register unsigned char data) +{ + *(*ptr)++ = data; +} + +/* + * NAME: data->storesw() + * DESCRIPTION: incrementally store a signed word of data + */ +void d_storesw(register unsigned char **ptr, + register signed short data) +{ + *(*ptr)++ = ((unsigned short) data & 0xff00) >> 8; + *(*ptr)++ = ((unsigned short) data & 0x00ff) >> 0; +} + +/* + * NAME: data->storeuw() + * DESCRIPTION: incrementally store an unsigned word of data + */ +void d_storeuw(register unsigned char **ptr, + register unsigned short data) +{ + *(*ptr)++ = (data & 0xff00) >> 8; + *(*ptr)++ = (data & 0x00ff) >> 0; +} + +/* + * NAME: data->storesl() + * DESCRIPTION: incrementally store a signed long word of data + */ +void d_storesl(register unsigned char **ptr, + register signed long data) +{ + *(*ptr)++ = ((unsigned long) data & 0xff000000UL) >> 24; + *(*ptr)++ = ((unsigned long) data & 0x00ff0000UL) >> 16; + *(*ptr)++ = ((unsigned long) data & 0x0000ff00UL) >> 8; + *(*ptr)++ = ((unsigned long) data & 0x000000ffUL) >> 0; +} + +/* + * NAME: data->storeul() + * DESCRIPTION: incrementally store an unsigned long word of data + */ +void d_storeul(register unsigned char **ptr, + register unsigned long data) +{ + *(*ptr)++ = (data & 0xff000000UL) >> 24; + *(*ptr)++ = (data & 0x00ff0000UL) >> 16; + *(*ptr)++ = (data & 0x0000ff00UL) >> 8; + *(*ptr)++ = (data & 0x000000ffUL) >> 0; +} + +/* + * NAME: data->fetchstr() + * DESCRIPTION: incrementally retrieve a string + */ +void d_fetchstr(const unsigned char **ptr, char *dest, unsigned size) +{ + unsigned len; + + len = d_getub(*ptr); + + if (len > 0 && len < size) + memcpy(dest, *ptr + 1, len); + else + len = 0; + + dest[len] = 0; + + *ptr += size; +} + +/* + * NAME: data->storestr() + * DESCRIPTION: incrementally store a string + */ +void d_storestr(unsigned char **ptr, const char *src, unsigned size) +{ + unsigned len; + + len = strlen(src); + if (len > --size) + len = 0; + + d_storeub(ptr, len); + + memcpy(*ptr, src, len); + memset(*ptr + len, 0, size - len); + + *ptr += size; +} + +/* + * NAME: data->relstring() + * DESCRIPTION: compare two strings as per MacOS for HFS + */ +int d_relstring(const char *str1, const char *str2) +{ + register int diff; + + while (*str1 && *str2) + { + diff = hfs_charorder[(unsigned char) *str1] - + hfs_charorder[(unsigned char) *str2]; + + if (diff) + return diff; + + ++str1, ++str2; + } + + if (! *str1 && *str2) + return -1; + else if (*str1 && ! *str2) + return 1; + + return 0; +} + +/* + * NAME: calctzdiff() + * DESCRIPTION: calculate the timezone difference between local time and UTC + */ +static +void calctzdiff(void) +{ +# ifdef HAVE_MKTIME + + time_t t; + int isdst; + struct tm tm; + const struct tm *tmp; + + time(&t); + isdst = localtime(&t)->tm_isdst; + + tmp = gmtime(&t); + if (tmp) + { + tm = *tmp; + tm.tm_isdst = isdst; + + tzdiff = t - mktime(&tm); + } + else + tzdiff = 0; + +# else + + tzdiff = 0; + +# endif +} + +/* + * NAME: data->ltime() + * DESCRIPTION: convert MacOS time to local time + */ +time_t d_ltime(unsigned long mtime) +{ + if (tzdiff == -1) + calctzdiff(); + + return (time_t) (mtime - TIMEDIFF) - tzdiff; +} + +/* + * NAME: data->mtime() + * DESCRIPTION: convert local time to MacOS time + */ +unsigned long d_mtime(time_t ltime) +{ + if (tzdiff == -1) + calctzdiff(); + + return (unsigned long) (ltime + tzdiff) + TIMEDIFF; +} diff --git a/qemu/roms/openbios/fs/hfs/file.c b/qemu/roms/openbios/fs/hfs/file.c new file mode 100644 index 000000000..a6ddb893a --- /dev/null +++ b/qemu/roms/openbios/fs/hfs/file.c @@ -0,0 +1,191 @@ +/* + * libhfs - library for reading and writing Macintosh HFS volumes + * Copyright (C) 1996-1998 Robert Leslie + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * $Id: file.c,v 1.9 1998/11/02 22:08:59 rob Exp $ + */ + +#include "config.h" +#include "libhfs.h" +#include "file.h" +#include "btree.h" +#include "record.h" +#include "volume.h" + +/* + * NAME: file->init() + * DESCRIPTION: initialize file structure + */ +void f_init(hfsfile *file, hfsvol *vol, long cnid, const char *name) +{ + int i; + + file->vol = vol; + file->parid = 0; + + strcpy(file->name, name); + + file->cat.cdrType = cdrFilRec; + file->cat.cdrResrv2 = 0; + + file->cat.u.fil.filFlags = 0; + file->cat.u.fil.filTyp = 0; + + file->cat.u.fil.filUsrWds.fdType = 0; + file->cat.u.fil.filUsrWds.fdCreator = 0; + file->cat.u.fil.filUsrWds.fdFlags = 0; + file->cat.u.fil.filUsrWds.fdLocation.v = 0; + file->cat.u.fil.filUsrWds.fdLocation.h = 0; + file->cat.u.fil.filUsrWds.fdFldr = 0; + + file->cat.u.fil.filFlNum = cnid; + file->cat.u.fil.filStBlk = 0; + file->cat.u.fil.filLgLen = 0; + file->cat.u.fil.filPyLen = 0; + file->cat.u.fil.filRStBlk = 0; + file->cat.u.fil.filRLgLen = 0; + file->cat.u.fil.filRPyLen = 0; + file->cat.u.fil.filCrDat = 0; + file->cat.u.fil.filMdDat = 0; + file->cat.u.fil.filBkDat = 0; + + file->cat.u.fil.filFndrInfo.fdIconID = 0; + for (i = 0; i < 4; ++i) + file->cat.u.fil.filFndrInfo.fdUnused[i] = 0; + file->cat.u.fil.filFndrInfo.fdComment = 0; + file->cat.u.fil.filFndrInfo.fdPutAway = 0; + + file->cat.u.fil.filClpSize = 0; + + for (i = 0; i < 3; ++i) + { + file->cat.u.fil.filExtRec[i].xdrStABN = 0; + file->cat.u.fil.filExtRec[i].xdrNumABlks = 0; + + file->cat.u.fil.filRExtRec[i].xdrStABN = 0; + file->cat.u.fil.filRExtRec[i].xdrNumABlks = 0; + } + + file->cat.u.fil.filResrv = 0; + + f_selectfork(file, fkData); + + file->flags = 0; + + file->prev = NULL; + file->next = NULL; +} + +/* + * NAME: file->selectfork() + * DESCRIPTION: choose a fork for file operations + */ +void f_selectfork(hfsfile *file, int fork) +{ + file->fork = fork; + + memcpy(&file->ext, fork == fkData ? + &file->cat.u.fil.filExtRec : &file->cat.u.fil.filRExtRec, + sizeof(ExtDataRec)); + + file->fabn = 0; + file->pos = 0; +} + +/* + * NAME: file->getptrs() + * DESCRIPTION: make pointers to the current fork's lengths and extents + */ +void f_getptrs(hfsfile *file, ExtDataRec **extrec, + unsigned long **lglen, unsigned long **pylen) +{ + if (file->fork == fkData) + { + if (extrec) + *extrec = &file->cat.u.fil.filExtRec; + if (lglen) + *lglen = &file->cat.u.fil.filLgLen; + if (pylen) + *pylen = &file->cat.u.fil.filPyLen; + } + else + { + if (extrec) + *extrec = &file->cat.u.fil.filRExtRec; + if (lglen) + *lglen = &file->cat.u.fil.filRLgLen; + if (pylen) + *pylen = &file->cat.u.fil.filRPyLen; + } +} + +/* + * NAME: file->doblock() + * DESCRIPTION: read or write a numbered block from a file + */ +int f_doblock(hfsfile *file, unsigned long num, block *bp, + int (*func)(hfsvol *, unsigned int, unsigned int, block *)) +{ + unsigned int abnum; + unsigned int blnum; + unsigned int fabn; + int i; + + abnum = num / file->vol->lpa; + blnum = num % file->vol->lpa; + + /* locate the appropriate extent record */ + + fabn = file->fabn; + + if (abnum < fabn) + { + ExtDataRec *extrec; + + f_getptrs(file, &extrec, NULL, NULL); + + fabn = file->fabn = 0; + memcpy(&file->ext, extrec, sizeof(ExtDataRec)); + } + else + abnum -= fabn; + + while (1) + { + unsigned int n; + + for (i = 0; i < 3; ++i) + { + n = file->ext[i].xdrNumABlks; + + if (abnum < n) + return func(file->vol, file->ext[i].xdrStABN + abnum, blnum, bp); + + fabn += n; + abnum -= n; + } + + if (v_extsearch(file, fabn, &file->ext, NULL) <= 0) + goto fail; + + file->fabn = fabn; + } + +fail: + return -1; +} diff --git a/qemu/roms/openbios/fs/hfs/hfs.c b/qemu/roms/openbios/fs/hfs/hfs.c new file mode 100644 index 000000000..0c5fefb47 --- /dev/null +++ b/qemu/roms/openbios/fs/hfs/hfs.c @@ -0,0 +1,747 @@ +/* + * libhfs - library for reading and writing Macintosh HFS volumes + * Copyright (C) 1996-1998 Robert Leslie + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * $Id: hfs.c,v 1.15 1998/11/02 22:09:00 rob Exp $ + */ + +#include "config.h" +#include "libhfs.h" +#include "data.h" +#include "block.h" +#include "medium.h" +#include "file.h" +#include "btree.h" +#include "node.h" +#include "record.h" +#include "volume.h" + +const char *hfs_error = "no error"; /* static error string */ + +hfsvol *hfs_mounts; /* linked list of mounted volumes */ + +static +hfsvol *curvol; /* current volume */ + + +/* + * NAME: getvol() + * DESCRIPTION: validate a volume reference + */ +static +int getvol(hfsvol **vol) +{ + if (*vol == NULL) + { + if (curvol == NULL) + ERROR(EINVAL, "no volume is current"); + + *vol = curvol; + } + + return 0; + +fail: + return -1; +} + +/* High-Level Volume Routines ============================================== */ + +/* + * NAME: hfs->mount() + * DESCRIPTION: open an HFS volume; return volume descriptor or 0 (error) + */ +hfsvol *hfs_mount( int os_fd, int pnum) +{ + hfsvol *vol, *check; + int mode = HFS_MODE_RDONLY; + + /* see if the volume is already mounted */ + for (check = hfs_mounts; check; check = check->next) + { + if (check->pnum == pnum && v_same(check, os_fd) == 1) + { + vol = check; + goto done; + } + } + + vol = ALLOC(hfsvol, 1); + if (vol == NULL) + ERROR(ENOMEM, NULL); + + v_init(vol, mode); + + vol->flags |= HFS_VOL_READONLY; + if( v_open(vol, os_fd) == -1 ) + goto fail; + + /* mount the volume */ + + if (v_geometry(vol, pnum) == -1 || + v_mount(vol) == -1) + goto fail; + + /* add to linked list of volumes */ + + vol->prev = NULL; + vol->next = hfs_mounts; + + if (hfs_mounts) + hfs_mounts->prev = vol; + + hfs_mounts = vol; + +done: + ++vol->refs; + curvol = vol; + + return vol; + +fail: + if (vol) + { + v_close(vol); + FREE(vol); + } + + return NULL; +} + + +/* + * NAME: hfs->umount() + * DESCRIPTION: close an HFS volume + */ +int hfs_umount(hfsvol *vol) +{ + int result = 0; + + if (getvol(&vol) == -1) + goto fail; + + if (--vol->refs) + { + goto done; + } + + /* close all open files and directories */ + + while (vol->files) + { + if (hfs_close(vol->files) == -1) + result = -1; + } + + while (vol->dirs) + { + if (hfs_closedir(vol->dirs) == -1) + result = -1; + } + + /* close medium */ + + if (v_close(vol) == -1) + result = -1; + + /* remove from linked list of volumes */ + + if (vol->prev) + vol->prev->next = vol->next; + if (vol->next) + vol->next->prev = vol->prev; + + if (vol == hfs_mounts) + hfs_mounts = vol->next; + if (vol == curvol) + curvol = NULL; + + FREE(vol); + +done: + return result; + +fail: + return -1; +} + +/* + * NAME: hfs->umountall() + * DESCRIPTION: unmount all mounted volumes + */ +void hfs_umountall(void) +{ + while (hfs_mounts) + hfs_umount(hfs_mounts); +} + +/* + * NAME: hfs->getvol() + * DESCRIPTION: return a pointer to a mounted volume + */ +hfsvol *hfs_getvol(const char *name) +{ + hfsvol *vol; + + if (name == NULL) + return curvol; + + for (vol = hfs_mounts; vol; vol = vol->next) + { + if (d_relstring(name, vol->mdb.drVN) == 0) + return vol; + } + + return NULL; +} + +/* + * NAME: hfs->setvol() + * DESCRIPTION: change the current volume + */ +void hfs_setvol(hfsvol *vol) +{ + curvol = vol; +} + +/* + * NAME: hfs->vstat() + * DESCRIPTION: return volume statistics + */ +int hfs_vstat(hfsvol *vol, hfsvolent *ent) +{ + if (getvol(&vol) == -1) + goto fail; + + strcpy(ent->name, vol->mdb.drVN); + + ent->flags = (vol->flags & HFS_VOL_READONLY) ? HFS_ISLOCKED : 0; + + ent->totbytes = vol->mdb.drNmAlBlks * vol->mdb.drAlBlkSiz; + ent->freebytes = vol->mdb.drFreeBks * vol->mdb.drAlBlkSiz; + + ent->alblocksz = vol->mdb.drAlBlkSiz; + ent->clumpsz = vol->mdb.drClpSiz; + + ent->numfiles = vol->mdb.drFilCnt; + ent->numdirs = vol->mdb.drDirCnt; + + ent->crdate = d_ltime(vol->mdb.drCrDate); + ent->mddate = d_ltime(vol->mdb.drLsMod); + ent->bkdate = d_ltime(vol->mdb.drVolBkUp); + + ent->blessed = vol->mdb.drFndrInfo[0]; + + return 0; + +fail: + return -1; +} + + +/* High-Level Directory Routines =========================================== */ + +/* + * NAME: hfs->chdir() + * DESCRIPTION: change current HFS directory + */ +int hfs_chdir(hfsvol *vol, const char *path) +{ + CatDataRec data; + + if (getvol(&vol) == -1 || + v_resolve(&vol, path, &data, NULL, NULL, NULL) <= 0) + goto fail; + + if (data.cdrType != cdrDirRec) + ERROR(ENOTDIR, NULL); + + vol->cwd = data.u.dir.dirDirID; + + return 0; + +fail: + return -1; +} + +/* + * NAME: hfs->getcwd() + * DESCRIPTION: return the current working directory ID + */ +unsigned long hfs_getcwd(hfsvol *vol) +{ + if (getvol(&vol) == -1) + return 0; + + return vol->cwd; +} + +/* + * NAME: hfs->setcwd() + * DESCRIPTION: set the current working directory ID + */ +int hfs_setcwd(hfsvol *vol, unsigned long id) +{ + if (getvol(&vol) == -1) + goto fail; + + if (id == vol->cwd) + goto done; + + /* make sure the directory exists */ + + if (v_getdthread(vol, id, NULL, NULL) <= 0) + goto fail; + + vol->cwd = id; + +done: + return 0; + +fail: + return -1; +} + +/* + * NAME: hfs->dirinfo() + * DESCRIPTION: given a directory ID, return its (name and) parent ID + */ +int hfs_dirinfo(hfsvol *vol, unsigned long *id, char *name) +{ + CatDataRec thread; + + if (getvol(&vol) == -1 || + v_getdthread(vol, *id, &thread, NULL) <= 0) + goto fail; + + *id = thread.u.dthd.thdParID; + + if (name) + strcpy(name, thread.u.dthd.thdCName); + + return 0; + +fail: + return -1; +} + +/* + * NAME: hfs->opendir() + * DESCRIPTION: prepare to read the contents of a directory + */ +hfsdir *hfs_opendir(hfsvol *vol, const char *path) +{ + hfsdir *dir = NULL; + CatKeyRec key; + CatDataRec data; + byte pkey[HFS_CATKEYLEN]; + + if (getvol(&vol) == -1) + goto fail; + + dir = ALLOC(hfsdir, 1); + if (dir == NULL) + ERROR(ENOMEM, NULL); + + dir->vol = vol; + + if (*path == 0) + { + /* meta-directory containing root dirs from all mounted volumes */ + + dir->dirid = 0; + dir->vptr = hfs_mounts; + } + else + { + if (v_resolve(&vol, path, &data, NULL, NULL, NULL) <= 0) + goto fail; + + if (data.cdrType != cdrDirRec) + ERROR(ENOTDIR, NULL); + + dir->dirid = data.u.dir.dirDirID; + dir->vptr = NULL; + + r_makecatkey(&key, dir->dirid, ""); + r_packcatkey(&key, pkey, NULL); + + if (bt_search(&vol->cat, pkey, &dir->n) <= 0) + goto fail; + } + + dir->prev = NULL; + dir->next = vol->dirs; + + if (vol->dirs) + vol->dirs->prev = dir; + + vol->dirs = dir; + + return dir; + +fail: + FREE(dir); + return NULL; +} + +/* + * NAME: hfs->readdir() + * DESCRIPTION: return the next entry in the directory + */ +int hfs_readdir(hfsdir *dir, hfsdirent *ent) +{ + CatKeyRec key; + CatDataRec data; + const byte *ptr; + + if (dir->dirid == 0) + { + hfsvol *vol; + char cname[HFS_MAX_FLEN + 1]; + + for (vol = hfs_mounts; vol; vol = vol->next) + { + if (vol == dir->vptr) + break; + } + + if (vol == NULL) + ERROR(ENOENT, "no more entries"); + + if (v_getdthread(vol, HFS_CNID_ROOTDIR, &data, NULL) <= 0 || + v_catsearch(vol, HFS_CNID_ROOTPAR, data.u.dthd.thdCName, + &data, cname, NULL) <= 0) + goto fail; + + r_unpackdirent(HFS_CNID_ROOTPAR, cname, &data, ent); + + dir->vptr = vol->next; + + goto done; + } + + if (dir->n.rnum == -1) + ERROR(ENOENT, "no more entries"); + + while (1) + { + ++dir->n.rnum; + + while (dir->n.rnum >= dir->n.nd.ndNRecs) + { + if (dir->n.nd.ndFLink == 0) + { + dir->n.rnum = -1; + ERROR(ENOENT, "no more entries"); + } + + if (bt_getnode(&dir->n, dir->n.bt, dir->n.nd.ndFLink) == -1) + { + dir->n.rnum = -1; + goto fail; + } + + dir->n.rnum = 0; + } + + ptr = HFS_NODEREC(dir->n, dir->n.rnum); + + r_unpackcatkey(ptr, &key); + + if (key.ckrParID != dir->dirid) + { + dir->n.rnum = -1; + ERROR(ENOENT, "no more entries"); + } + + r_unpackcatdata(HFS_RECDATA(ptr), &data); + + switch (data.cdrType) + { + case cdrDirRec: + case cdrFilRec: + r_unpackdirent(key.ckrParID, key.ckrCName, &data, ent); + goto done; + + case cdrThdRec: + case cdrFThdRec: + break; + + default: + dir->n.rnum = -1; + ERROR(EIO, "unexpected directory entry found"); + } + } + +done: + return 0; + +fail: + return -1; +} + +/* + * NAME: hfs->closedir() + * DESCRIPTION: stop reading a directory + */ +int hfs_closedir(hfsdir *dir) +{ + hfsvol *vol = dir->vol; + + if (dir->prev) + dir->prev->next = dir->next; + if (dir->next) + dir->next->prev = dir->prev; + if (dir == vol->dirs) + vol->dirs = dir->next; + + FREE(dir); + + return 0; +} + +/* High-Level File Routines ================================================ */ + +/* + * NAME: hfs->open() + * DESCRIPTION: prepare a file for I/O + */ +hfsfile *hfs_open(hfsvol *vol, const char *path) +{ + hfsfile *file = NULL; + + if (getvol(&vol) == -1) + goto fail; + + file = ALLOC(hfsfile, 1); + if (file == NULL) + ERROR(ENOMEM, NULL); + + if (v_resolve(&vol, path, &file->cat, &file->parid, file->name, NULL) <= 0) + goto fail; + + if (file->cat.cdrType != cdrFilRec) + ERROR(EISDIR, NULL); + + /* package file handle for user */ + + file->vol = vol; + file->flags = 0; + + f_selectfork(file, fkData); + + file->prev = NULL; + file->next = vol->files; + + if (vol->files) + vol->files->prev = file; + + vol->files = file; + + return file; + +fail: + FREE(file); + return NULL; +} + +/* + * NAME: hfs->setfork() + * DESCRIPTION: select file fork for I/O operations + */ +int hfs_setfork(hfsfile *file, int fork) +{ + int result = 0; + + f_selectfork(file, fork ? fkRsrc : fkData); + + return result; +} + +/* + * NAME: hfs->getfork() + * DESCRIPTION: return the current fork for I/O operations + */ +int hfs_getfork(hfsfile *file) +{ + return file->fork != fkData; +} + +/* + * NAME: hfs->read() + * DESCRIPTION: read from an open file + */ +unsigned long hfs_read(hfsfile *file, void *buf, unsigned long len) +{ + unsigned long *lglen, count; + byte *ptr = buf; + + f_getptrs(file, NULL, &lglen, NULL); + + if (file->pos + len > *lglen) + len = *lglen - file->pos; + + count = len; + while (count) + { + unsigned long bnum, offs, chunk; + + bnum = file->pos >> HFS_BLOCKSZ_BITS; + offs = file->pos & (HFS_BLOCKSZ - 1); + + chunk = HFS_BLOCKSZ - offs; + if (chunk > count) + chunk = count; + + if (offs == 0 && chunk == HFS_BLOCKSZ) + { + if (f_getblock(file, bnum, (block *) ptr) == -1) + goto fail; + } + else + { + block b; + + if (f_getblock(file, bnum, &b) == -1) + goto fail; + + memcpy(ptr, b + offs, chunk); + } + + ptr += chunk; + + file->pos += chunk; + count -= chunk; + } + + return len; + +fail: + return -1; +} + +/* + * NAME: hfs->seek() + * DESCRIPTION: change file seek pointer + */ +unsigned long hfs_seek(hfsfile *file, long offset, int from) +{ + unsigned long *lglen, newpos; + + f_getptrs(file, NULL, &lglen, NULL); + + switch (from) + { + case HFS_SEEK_SET: + newpos = (offset < 0) ? 0 : offset; + break; + + case HFS_SEEK_CUR: + if (offset < 0 && (unsigned long) -offset > file->pos) + newpos = 0; + else + newpos = file->pos + offset; + break; + + case HFS_SEEK_END: + if (offset < 0 && (unsigned long) -offset > *lglen) + newpos = 0; + else + newpos = *lglen + offset; + break; + + default: + ERROR(EINVAL, NULL); + } + + if (newpos > *lglen) + newpos = *lglen; + + file->pos = newpos; + + return newpos; + +fail: + return -1; +} + +/* + * NAME: hfs->close() + * DESCRIPTION: close a file + */ +int hfs_close(hfsfile *file) +{ + hfsvol *vol = file->vol; + int result = 0; + + if (file->prev) + file->prev->next = file->next; + if (file->next) + file->next->prev = file->prev; + if (file == vol->files) + vol->files = file->next; + + FREE(file); + + return result; +} + +/* High-Level Catalog Routines ============================================= */ + +/* + * NAME: hfs->stat() + * DESCRIPTION: return catalog information for an arbitrary path + */ +int hfs_stat(hfsvol *vol, const char *path, hfsdirent *ent) +{ + CatDataRec data; + unsigned long parid; + char name[HFS_MAX_FLEN + 1]; + + if (getvol(&vol) == -1 || + v_resolve(&vol, path, &data, &parid, name, NULL) <= 0) + goto fail; + + r_unpackdirent(parid, name, &data, ent); + + return 0; + +fail: + return -1; +} + +/* + * NAME: hfs->fstat() + * DESCRIPTION: return catalog information for an open file + */ +int hfs_fstat(hfsfile *file, hfsdirent *ent) +{ + r_unpackdirent(file->parid, file->name, &file->cat, ent); + + return 0; +} + +/* + * NAME: hfs->probe() + * DESCRIPTION: return whether a HFS filesystem is present at the given offset + */ +int hfs_probe(int fd, long long offset) +{ + return v_probe(fd, offset); +} diff --git a/qemu/roms/openbios/fs/hfs/hfs_fs.c b/qemu/roms/openbios/fs/hfs/hfs_fs.c new file mode 100644 index 000000000..2d62ec0c6 --- /dev/null +++ b/qemu/roms/openbios/fs/hfs/hfs_fs.c @@ -0,0 +1,593 @@ +/* + * Creation Date: <2001/05/06 22:47:23 samuel> + * Time-stamp: <2004/01/12 10:24:35 samuel> + * + * /packages/hfs-files + * + * HFS world interface + * + * Copyright (C) 2001-2004 Samuel Rydh (samuel@ibrium.se) + * Copyright (C) 2010 Mark Cave-Ayland (mark.cave-ayland@siriusit.co.uk) + * + * 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 + * + */ + +#include "config.h" +#include "libopenbios/bindings.h" +#include "fs/fs.h" +#include "libc/vsprintf.h" +#include "libc/diskio.h" +#include "libhfs.h" + +#define MAC_OS_ROM_CREATOR 0x63687270 /* 'chrp' */ +#define MAC_OS_ROM_TYPE 0x74627869 /* 'tbxi' */ +#define MAC_OS_ROM_NAME "Mac OS ROM" + +#define FINDER_TYPE 0x464E4452 /* 'FNDR' */ +#define FINDER_CREATOR 0x4D414353 /* 'MACS' */ +#define SYSTEM_TYPE 0x7A737973 /* 'zsys' */ +#define SYSTEM_CREATOR 0x4D414353 /* 'MACS' */ + +#define VOLNAME_SIZE 64 + +extern void hfs_init( void ); + +typedef struct { + enum { FILE, DIR } type; + union { + hfsdir *dir; + hfsfile *file; + }; +} hfscommon; + +typedef struct { + hfsvol *vol; + hfscommon *common; +} hfs_info_t; + +DECLARE_NODE( hfs, 0, sizeof(hfs_info_t), "+/packages/hfs-files" ); + +/************************************************************************/ +/* Search Functions */ +/************************************************************************/ + +static int +_find_file( hfsvol *vol, const char *path, unsigned long type, unsigned long creator ) +{ + hfsdirent ent; + hfsdir *dir; + int ret=1; + + if( !(dir=hfs_opendir(vol, path)) ) + return 1; + + while( ret && !hfs_readdir(dir, &ent) ) { + if( ent.flags & HFS_ISDIR ) + continue; + ret = !(*(unsigned long*)ent.u.file.type == type && *(unsigned long*)ent.u.file.creator == creator ); + } + + hfs_closedir( dir ); + return ret; +} + + +/* ret: 0=success, 1=not_found, 2=not_a_dir */ +static int +_search( hfsvol *vol, const char *path, const char *sname, hfsfile **ret_fd ) +{ + hfsdir *dir; + hfsdirent ent; + int topdir=0, status = 1; + char *p, buf[256]; + + strncpy( buf, path, sizeof(buf) ); + if( buf[strlen(buf)-1] != ':' ) + strncat( buf, ":", sizeof(buf) ); + buf[sizeof(buf)-1] = 0; + p = buf + strlen( buf ); + + if( !(dir=hfs_opendir(vol, path)) ) + return 2; + + /* printk("DIRECTORY: %s\n", path ); */ + + while( status && !hfs_readdir(dir, &ent) ) { + unsigned long type, creator; + + *p = 0; + topdir = 0; + + strncat( buf, ent.name, sizeof(buf) ); + if( (status=_search(vol, buf, sname, ret_fd)) != 2 ) + continue; + topdir = 1; + + /* name search? */ + if( sname ) { + status = strcasecmp( ent.name, sname ); + continue; + } + + type = *(unsigned long*)ent.u.file.type; + creator = *(unsigned long*)ent.u.file.creator; + + /* look for Mac OS ROM, System and Finder in the same directory */ + if( type == MAC_OS_ROM_TYPE && creator == MAC_OS_ROM_CREATOR ) { + if( strcasecmp(ent.name, MAC_OS_ROM_NAME) ) + continue; + + status = _find_file( vol, path, FINDER_TYPE, FINDER_CREATOR ) + || _find_file( vol, path, SYSTEM_TYPE, SYSTEM_CREATOR ); + } + } + if( !status && topdir && ret_fd && !(*ret_fd=hfs_open(vol, buf)) ) { + printk("Unexpected error: failed to open matched ROM\n"); + status = 1; + } + + hfs_closedir( dir ); + return status; +} + +static hfsfile * +_do_search( hfs_info_t *mi, const char *sname ) +{ + hfsvol *vol = hfs_getvol( NULL ); + + mi->common->type = FILE; + (void)_search( vol, ":", sname, &mi->common->file ); + + return mi->common->file; +} + + +static const int days_month[12] = + { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; +static const int days_month_leap[12] = + { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + +static inline int is_leap(int year) +{ + return ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0); +} + +static void +print_date(time_t sec) +{ + unsigned int second, minute, hour, month, day, year; + int current; + const int *days; + + second = sec % 60; + sec /= 60; + + minute = sec % 60; + sec /= 60; + + hour = sec % 24; + sec /= 24; + + year = sec * 100 / 36525; + sec -= year * 36525 / 100; + year += 1970; + + days = is_leap(year) ? days_month_leap : days_month; + + current = 0; + month = 0; + while (month < 12) { + if (sec <= current + days[month]) { + break; + } + current += days[month]; + month++; + } + month++; + + day = sec - current + 1; + + forth_printf("%d-%02d-%02d %02d:%02d:%02d ", + year, month, day, hour, minute, second); +} + +/* +static void +dir_fs( file_desc_t *fd ) +{ + hfscommon *common = (hfscommon*)fd; + hfsdirent ent; + + if (common->type != DIR) + return; + + forth_printf("\n"); + while( !hfs_readdir(common->dir, &ent) ) { + forth_printf("% 10d ", ent.u.file.dsize); + print_date(ent.mddate); + if( ent.flags & HFS_ISDIR ) + forth_printf("%s\\\n", ent.name); + else + forth_printf("%s\n", ent.name); + } +} +*/ + +/************************************************************************/ +/* Standard package methods */ +/************************************************************************/ + +/* ( -- success? ) */ +static void +hfs_files_open( hfs_info_t *mi ) +{ + int fd; + char *path = my_args_copy(); + + const char *s; + char buf[256]; + + fd = open_ih( my_parent() ); + if ( fd == -1 ) { + free( path ); + RET( 0 ); + } + + mi->vol = hfs_mount(fd, 0); + if (!mi->vol) { + RET( 0 ); + } + + if( !strncmp(path, "\\\\", 2) ) { + hfsvolent ent; + + /* \\ is an alias for the (blessed) system folder */ + if( hfs_vstat(mi->vol, &ent) < 0 || hfs_setcwd(mi->vol, ent.blessed) ) { + free(path); + RET( -1 ); + } + path += 2; + } else { + hfs_chdir( mi->vol, ":" ); + } + + mi->common = malloc(sizeof(hfscommon)); + if (!mi->common) { + free(path); + RET( 0 ); + } + + if (strcmp(path, "\\") == 0) { + /* root directory is in fact ":" */ + mi->common->dir = hfs_opendir(mi->vol, ":"); + mi->common->type = DIR; + free(path); + RET( -1 ); + } + + if (path[strlen(path) - 1] == '\\') { + path[strlen(path) - 1] = 0; + } + + for( path-- ;; ) { + int n; + + s = ++path; + path = strchr(s, '\\'); + if( !path || !path[1]) + break; + n = MIN( sizeof(buf)-1, (path-s) ); + if( !n ) + continue; + + strncpy( buf, s, n ); + buf[n] = 0; + if( hfs_chdir(mi->vol, buf) ) { + free(mi->common); + free(path); + RET( 0 ); + } + } + + /* support the ':filetype' syntax */ + if( *s == ':' ) { + unsigned long id, oldid = hfs_getcwd(mi->vol); + hfsdirent ent; + hfsdir *dir; + + s++; + id = oldid; + hfs_dirinfo( mi->vol, &id, buf ); + hfs_setcwd( mi->vol, id ); + + if( !(dir=hfs_opendir(mi->vol, buf)) ) { + free(mi->common); + free(path); + RET( 0 ); + } + hfs_setcwd( mi->vol, oldid ); + + while( !hfs_readdir(dir, &ent) ) { + if( ent.flags & HFS_ISDIR ) + continue; + if( !strncmp(s, ent.u.file.type, 4) ) { + mi->common->type = FILE; + mi->common->file = hfs_open( mi->vol, ent.name ); + break; + } + } + hfs_closedir( dir ); + free(path); + RET( -1 ); + } + + mi->common->dir = hfs_opendir(mi->vol, s); + if (!mi->common->dir) { + mi->common->file = hfs_open( mi->vol, s ); + if (mi->common->file == NULL) { + free(mi->common); + free(path); + RET( 0 ); + } + mi->common->type = FILE; + free(path); + RET( -1 ); + } + mi->common->type = DIR; + free(path); + + RET( -1 ); +} + +/* ( -- ) */ +static void +hfs_files_close( hfs_info_t *mi ) +{ + hfscommon *common = mi->common; + if (common->type == FILE) + hfs_close( common->file ); + else if (common->type == DIR) + hfs_closedir( common->dir ); + free(common); +} + +/* ( buf len -- actlen ) */ +static void +hfs_files_read( hfs_info_t *mi ) +{ + int count = POP(); + char *buf = (char *)cell2pointer(POP()); + + hfscommon *common = mi->common; + if (common->type != FILE) + RET( -1 ); + + RET ( hfs_read( common->file, buf, count ) ); +} + +/* ( pos.d -- status ) */ +static void +hfs_files_seek( hfs_info_t *mi ) +{ + long long pos = DPOP(); + int offs = (int)pos; + int whence = SEEK_SET; + int ret; + hfscommon *common = mi->common; + + if (common->type != FILE) + RET( -1 ); + + switch( whence ) { + case SEEK_END: + whence = HFS_SEEK_END; + break; + default: + case SEEK_SET: + whence = HFS_SEEK_SET; + break; + } + + ret = hfs_seek( common->file, offs, whence ); + if (ret != -1) + RET( 0 ); + else + RET( -1 ); +} + +/* ( addr -- size ) */ +static void +hfs_files_load( hfs_info_t *mi ) +{ + char *buf = (char *)cell2pointer(POP()); + int count; + + hfscommon *common = mi->common; + if (common->type != FILE) + RET( -1 ); + + /* Seek to the end in order to get the file size */ + hfs_seek(common->file, 0, HFS_SEEK_END); + count = common->file->pos; + hfs_seek(common->file, 0, HFS_SEEK_SET); + + RET ( hfs_read( common->file, buf, count ) ); +} + +/* ( -- success? ) */ +static void +hfs_files_open_nwrom( hfs_info_t *mi ) +{ + /* Switch to an existing ROM image file on the fs! */ + if ( _do_search( mi, NULL ) ) + RET( -1 ); + + RET( 0 ); +} + +/* ( -- cstr ) */ +static void +hfs_files_get_path( hfs_info_t *mi ) +{ + char buf[256], buf2[256]; + hfscommon *common = mi->common; + hfsvol *vol = hfs_getvol( NULL ); + hfsdirent ent; + int start, ns; + unsigned long id; + + if (common->type != FILE) + RET( 0 ); + + hfs_fstat( common->file, &ent ); + start = sizeof(buf) - strlen(ent.name) - 1; + if( start <= 0 ) + RET ( 0 ); + strcpy( buf+start, ent.name ); + buf[--start] = '\\'; + + ns = start; + for( id=ent.parid ; !hfs_dirinfo(vol, &id, buf2) ; ) { + start = ns; + ns -= strlen(buf2); + if( ns <= 0 ) + RET( 0 ); + strcpy( buf+ns, buf2 ); + buf[--ns] = buf[start] = '\\'; + } + if( strlen(buf) >= sizeof(buf) ) + RET( 0 ); + + RET( pointer2cell(strdup(buf+start)) ); +} + +/* ( -- cstr ) */ +static void +hfs_files_get_fstype( hfs_info_t *mi ) +{ + PUSH( pointer2cell(strdup("HFS")) ); +} + +/* ( -- cstr|0 ) */ +static void +hfs_files_volume_name( hfs_info_t *mi ) +{ + int fd; + char *volname = malloc(VOLNAME_SIZE); + + fd = open_ih(my_self()); + if (fd >= 0) { + get_hfs_vol_name(fd, volname, VOLNAME_SIZE); + close_io(fd); + } else { + volname[0] = '\0'; + } + + PUSH(pointer2cell(volname)); +} + +/* static method, ( pathstr len ihandle -- ) */ +static void +hfs_files_dir( hfs_info_t *dummy ) +{ + hfsvol *volume; + hfscommon *common; + hfsdirent ent; + int i; + int fd; + + ihandle_t ih = POP(); + char *path = pop_fstr_copy(); + + fd = open_ih( ih ); + if ( fd == -1 ) { + free( path ); + return; + } + + volume = hfs_mount(fd, 0); + if (!volume) { + return; + } + + common = malloc(sizeof(hfscommon)); + + /* HFS paths are colon separated, not backslash separated */ + for (i = 0; i < strlen(path); i++) + if (path[i] == '\\') + path[i] = ':'; + + common->dir = hfs_opendir(volume, path); + + forth_printf("\n"); + while( !hfs_readdir(common->dir, &ent) ) { + forth_printf("% 10ld ", ent.u.file.dsize); + print_date(ent.mddate); + if( ent.flags & HFS_ISDIR ) + forth_printf("%s\\\n", ent.name); + else + forth_printf("%s\n", ent.name); + } + + hfs_closedir( common->dir ); + hfs_umount( volume ); + + close_io( fd ); + + free( common ); + free( path ); +} + +/* static method, ( pos.d ih -- flag? ) */ +static void +hfs_files_probe( hfs_info_t *dummy ) +{ + ihandle_t ih = POP_ih(); + long long offs = DPOP(); + int fd, ret = 0; + + fd = open_ih(ih); + if (fd >= 0) { + if (hfs_probe(fd, offs)) { + ret = -1; + } + close_io(fd); + } else { + ret = -1; + } + + RET (ret); +} + +static void +hfs_initializer( hfs_info_t *dummy ) +{ + fword("register-fs-package"); +} + +NODE_METHODS( hfs ) = { + { "probe", hfs_files_probe }, + { "open", hfs_files_open }, + { "close", hfs_files_close }, + { "read", hfs_files_read }, + { "seek", hfs_files_seek }, + { "load", hfs_files_load }, + { "dir", hfs_files_dir }, + + /* special */ + { "open-nwrom", hfs_files_open_nwrom }, + { "get-path", hfs_files_get_path }, + { "get-fstype", hfs_files_get_fstype }, + { "volume-name", hfs_files_volume_name }, + + { NULL, hfs_initializer }, +}; + +void +hfs_init( void ) +{ + REGISTER_NODE( hfs ); +} diff --git a/qemu/roms/openbios/fs/hfs/include/apple.h b/qemu/roms/openbios/fs/hfs/include/apple.h new file mode 100644 index 000000000..3de581d82 --- /dev/null +++ b/qemu/roms/openbios/fs/hfs/include/apple.h @@ -0,0 +1,273 @@ +/* + * libhfs - library for reading and writing Macintosh HFS volumes + * Copyright (C) 1996-1998 Robert Leslie + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * $Id: apple.h,v 1.1 1998/04/11 08:27:11 rob Exp $ + */ + +typedef signed char Char; +typedef unsigned char UChar; +typedef signed char SignedByte; +typedef signed short Integer; +typedef unsigned short UInteger; +typedef signed long LongInt; +typedef unsigned long ULongInt; +typedef char Str15[16]; +typedef char Str31[32]; +typedef long OSType; + +typedef struct { + Integer sbSig; /* device signature (should be 0x4552) */ + Integer sbBlkSize; /* block size of the device (in bytes) */ + LongInt sbBlkCount; /* number of blocks on the device */ + Integer sbDevType; /* reserved */ + Integer sbDevId; /* reserved */ + LongInt sbData; /* reserved */ + Integer sbDrvrCount; /* number of driver descriptor entries */ + LongInt ddBlock; /* first driver's starting block */ + Integer ddSize; /* size of the driver, in 512-byte blocks */ + Integer ddType; /* driver operating system type (MacOS = 1) */ + Integer ddPad[243]; /* additional drivers, if any */ +} Block0; + +typedef struct { + Integer pmSig; /* partition signature (0x504d or 0x5453) */ + Integer pmSigPad; /* reserved */ + LongInt pmMapBlkCnt; /* number of blocks in partition map */ + LongInt pmPyPartStart; /* first physical block of partition */ + LongInt pmPartBlkCnt; /* number of blocks in partition */ + Char pmPartName[33]; /* partition name */ + Char pmParType[33]; /* partition type */ + LongInt pmLgDataStart; /* first logical block of data area */ + LongInt pmDataCnt; /* number of blocks in data area */ + LongInt pmPartStatus; /* partition status information */ + LongInt pmLgBootStart; /* first logical block of boot code */ + LongInt pmBootSize; /* size of boot code, in bytes */ + LongInt pmBootAddr; /* boot code load address */ + LongInt pmBootAddr2; /* reserved */ + LongInt pmBootEntry; /* boot code entry point */ + LongInt pmBootEntry2; /* reserved */ + LongInt pmBootCksum; /* boot code checksum */ + Char pmProcessor[17];/* processor type */ + Integer pmPad[188]; /* reserved */ +} Partition; + +typedef struct { + Integer bbID; /* boot blocks signature */ + LongInt bbEntry; /* entry point to boot code */ + Integer bbVersion; /* boot blocks version number */ + Integer bbPageFlags; /* used internally */ + Str15 bbSysName; /* System filename */ + Str15 bbShellName; /* Finder filename */ + Str15 bbDbg1Name; /* debugger filename */ + Str15 bbDbg2Name; /* debugger filename */ + Str15 bbScreenName; /* name of startup screen */ + Str15 bbHelloName; /* name of startup program */ + Str15 bbScrapName; /* name of system scrap file */ + Integer bbCntFCBs; /* number of FCBs to allocate */ + Integer bbCntEvts; /* number of event queue elements */ + LongInt bb128KSHeap; /* system heap size on 128K Mac */ + LongInt bb256KSHeap; /* used internally */ + LongInt bbSysHeapSize; /* system heap size on all machines */ + Integer filler; /* reserved */ + LongInt bbSysHeapExtra; /* additional system heap space */ + LongInt bbSysHeapFract; /* fraction of RAM for system heap */ +} BootBlkHdr; + +typedef struct { + UInteger xdrStABN; /* first allocation block */ + UInteger xdrNumABlks; /* number of allocation blocks */ +} ExtDescriptor; + +typedef ExtDescriptor ExtDataRec[3]; + +typedef struct { + SignedByte xkrKeyLen; /* key length */ + SignedByte xkrFkType; /* fork type (0x00/0xff == data/resource */ + ULongInt xkrFNum; /* file number */ + UInteger xkrFABN; /* starting file allocation block */ +} ExtKeyRec; + +typedef struct { + SignedByte ckrKeyLen; /* key length */ + SignedByte ckrResrv1; /* reserved */ + ULongInt ckrParID; /* parent directory ID */ + Str31 ckrCName; /* catalog node name */ +} CatKeyRec; + +typedef struct { + Integer v; /* vertical coordinate */ + Integer h; /* horizontal coordinate */ +} Point; + +typedef struct { + Integer top; /* top edge of rectangle */ + Integer left; /* left edge */ + Integer bottom; /* bottom edge */ + Integer right; /* right edge */ +} Rect; + +typedef struct { + Rect frRect; /* folder's rectangle */ + Integer frFlags; /* flags */ + Point frLocation; /* folder's location */ + Integer frView; /* folder's view */ +} DInfo; + +typedef struct { + Point frScroll; /* scroll position */ + LongInt frOpenChain; /* directory ID chain of open folders */ + Integer frUnused; /* reserved */ + Integer frComment; /* comment ID */ + LongInt frPutAway; /* directory ID */ +} DXInfo; + +typedef struct { + OSType fdType; /* file type */ + OSType fdCreator; /* file's creator */ + Integer fdFlags; /* flags */ + Point fdLocation; /* file's location */ + Integer fdFldr; /* file's window */ +} FInfo; + +typedef struct { + Integer fdIconID; /* icon ID */ + Integer fdUnused[4]; /* reserved */ + Integer fdComment; /* comment ID */ + LongInt fdPutAway; /* home directory ID */ +} FXInfo; + +typedef struct { + Integer drSigWord; /* volume signature (0x4244 for HFS) */ + LongInt drCrDate; /* date and time of volume creation */ + LongInt drLsMod; /* date and time of last modification */ + Integer drAtrb; /* volume attributes */ + UInteger drNmFls; /* number of files in root directory */ + UInteger drVBMSt; /* first block of volume bit map (always 3) */ + UInteger drAllocPtr; /* start of next allocation search */ + UInteger drNmAlBlks; /* number of allocation blocks in volume */ + ULongInt drAlBlkSiz; /* size (in bytes) of allocation blocks */ + ULongInt drClpSiz; /* default clump size */ + UInteger drAlBlSt; /* first allocation block in volume */ + LongInt drNxtCNID; /* next unused catalog node ID (dir/file ID) */ + UInteger drFreeBks; /* number of unused allocation blocks */ + char drVN[28]; /* volume name (1-27 chars) */ + LongInt drVolBkUp; /* date and time of last backup */ + Integer drVSeqNum; /* volume backup sequence number */ + ULongInt drWrCnt; /* volume write count */ + ULongInt drXTClpSiz; /* clump size for extents overflow file */ + ULongInt drCTClpSiz; /* clump size for catalog file */ + UInteger drNmRtDirs; /* number of directories in root directory */ + ULongInt drFilCnt; /* number of files in volume */ + ULongInt drDirCnt; /* number of directories in volume */ + LongInt drFndrInfo[8]; /* information used by the Finder */ + UInteger drEmbedSigWord; /* type of embedded volume */ + ExtDescriptor drEmbedExtent; /* location of embedded volume */ + ULongInt drXTFlSize; /* size (in bytes) of extents overflow file */ + ExtDataRec drXTExtRec; /* first extent record for extents file */ + ULongInt drCTFlSize; /* size (in bytes) of catalog file */ + ExtDataRec drCTExtRec; /* first extent record for catalog file */ +} MDB; + +typedef enum { + cdrDirRec = 1, + cdrFilRec = 2, + cdrThdRec = 3, + cdrFThdRec = 4 +} CatDataType; + +typedef struct { + SignedByte cdrType; /* record type */ + SignedByte cdrResrv2; /* reserved */ + union { + struct { /* cdrDirRec */ + Integer dirFlags; /* directory flags */ + UInteger dirVal; /* directory valence */ + ULongInt dirDirID; /* directory ID */ + LongInt dirCrDat; /* date and time of creation */ + LongInt dirMdDat; /* date and time of last modification */ + LongInt dirBkDat; /* date and time of last backup */ + DInfo dirUsrInfo; /* Finder information */ + DXInfo dirFndrInfo; /* additional Finder information */ + LongInt dirResrv[4]; /* reserved */ + } dir; + struct { /* cdrFilRec */ + SignedByte + filFlags; /* file flags */ + SignedByte + filTyp; /* file type */ + FInfo filUsrWds; /* Finder information */ + ULongInt filFlNum; /* file ID */ + UInteger filStBlk; /* first alloc block of data fork */ + ULongInt filLgLen; /* logical EOF of data fork */ + ULongInt filPyLen; /* physical EOF of data fork */ + UInteger filRStBlk; /* first alloc block of resource fork */ + ULongInt filRLgLen; /* logical EOF of resource fork */ + ULongInt filRPyLen; /* physical EOF of resource fork */ + LongInt filCrDat; /* date and time of creation */ + LongInt filMdDat; /* date and time of last modification */ + LongInt filBkDat; /* date and time of last backup */ + FXInfo filFndrInfo; /* additional Finder information */ + UInteger filClpSize; /* file clump size */ + ExtDataRec + filExtRec; /* first data fork extent record */ + ExtDataRec + filRExtRec; /* first resource fork extent record */ + LongInt filResrv; /* reserved */ + } fil; + struct { /* cdrThdRec */ + LongInt thdResrv[2]; /* reserved */ + ULongInt thdParID; /* parent ID for this directory */ + Str31 thdCName; /* name of this directory */ + } dthd; + struct { /* cdrFThdRec */ + LongInt fthdResrv[2]; /* reserved */ + ULongInt fthdParID; /* parent ID for this file */ + Str31 fthdCName; /* name of this file */ + } fthd; + } u; +} CatDataRec; + +typedef struct { + ULongInt ndFLink; /* forward link */ + ULongInt ndBLink; /* backward link */ + SignedByte ndType; /* node type */ + SignedByte ndNHeight; /* node level */ + UInteger ndNRecs; /* number of records in node */ + Integer ndResv2; /* reserved */ +} NodeDescriptor; + +enum { + ndIndxNode = (SignedByte) 0x00, + ndHdrNode = (SignedByte) 0x01, + ndMapNode = (SignedByte) 0x02, + ndLeafNode = (SignedByte) 0xff +}; + +typedef struct { + UInteger bthDepth; /* current depth of tree */ + ULongInt bthRoot; /* number of root node */ + ULongInt bthNRecs; /* number of leaf records in tree */ + ULongInt bthFNode; /* number of first leaf node */ + ULongInt bthLNode; /* number of last leaf node */ + UInteger bthNodeSize; /* size of a node */ + UInteger bthKeyLen; /* maximum length of a key */ + ULongInt bthNNodes; /* total number of nodes in tree */ + ULongInt bthFree; /* number of free nodes */ + SignedByte bthResv[76]; /* reserved */ +} BTHdrRec; diff --git a/qemu/roms/openbios/fs/hfs/include/block.h b/qemu/roms/openbios/fs/hfs/include/block.h new file mode 100644 index 000000000..d7e764518 --- /dev/null +++ b/qemu/roms/openbios/fs/hfs/include/block.h @@ -0,0 +1,41 @@ +/* + * libhfs - library for reading and writing Macintosh HFS volumes + * Copyright (C) 1996-1998 Robert Leslie + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * $Id: block.h,v 1.10 1998/11/02 22:08:53 rob Exp $ + */ + +int b_init(hfsvol *); +int b_flush(hfsvol *); +int b_finish(hfsvol *); + +int b_readpb(hfsvol *, unsigned long, block *, unsigned int); +int b_writepb(hfsvol *, unsigned long, const block *, unsigned int); + +int b_readlb(hfsvol *, unsigned long, block *); +int b_writelb(hfsvol *, unsigned long, const block *); + +int b_readab(hfsvol *, unsigned int, unsigned int, block *); +int b_writeab(hfsvol *, unsigned int, unsigned int, const block *); + +unsigned long b_size(hfsvol *); + +# ifdef DEBUG +void b_showstats(const bcache *); +void b_dumpcache(const bcache *); +# endif diff --git a/qemu/roms/openbios/fs/hfs/include/btree.h b/qemu/roms/openbios/fs/hfs/include/btree.h new file mode 100644 index 000000000..36660f538 --- /dev/null +++ b/qemu/roms/openbios/fs/hfs/include/btree.h @@ -0,0 +1,34 @@ +/* + * libhfs - library for reading and writing Macintosh HFS volumes + * Copyright (C) 1996-1998 Robert Leslie + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * $Id: btree.h,v 1.8 1998/11/02 22:08:55 rob Exp $ + */ + +int bt_getnode(node *, btree *, unsigned long); +int bt_putnode(node *); + +int bt_readhdr(btree *); +int bt_writehdr(btree *); + +int bt_space(btree *, unsigned int); + +int bt_insert(btree *, const byte *, unsigned int); +int bt_delete(btree *, const byte *); + +int bt_search(btree *, const byte *, node *); diff --git a/qemu/roms/openbios/fs/hfs/include/data.h b/qemu/roms/openbios/fs/hfs/include/data.h new file mode 100644 index 000000000..f3e20008f --- /dev/null +++ b/qemu/roms/openbios/fs/hfs/include/data.h @@ -0,0 +1,57 @@ +/* + * libhfs - library for reading and writing Macintosh HFS volumes + * Copyright (C) 1996-1998 Robert Leslie + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * $Id: data.h,v 1.7 1998/11/02 22:08:58 rob Exp $ + */ + + signed char d_getsb(register const unsigned char *); +unsigned char d_getub(register const unsigned char *); + signed short d_getsw(register const unsigned char *); +unsigned short d_getuw(register const unsigned char *); + signed long d_getsl(register const unsigned char *); +unsigned long d_getul(register const unsigned char *); + +void d_putsb(register unsigned char *, register signed char); +void d_putub(register unsigned char *, register unsigned char); +void d_putsw(register unsigned char *, register signed short); +void d_putuw(register unsigned char *, register unsigned short); +void d_putsl(register unsigned char *, register signed long); +void d_putul(register unsigned char *, register unsigned long); + +void d_fetchsb(register const unsigned char **, register signed char *); +void d_fetchub(register const unsigned char **, register unsigned char *); +void d_fetchsw(register const unsigned char **, register signed short *); +void d_fetchuw(register const unsigned char **, register unsigned short *); +void d_fetchsl(register const unsigned char **, register signed long *); +void d_fetchul(register const unsigned char **, register unsigned long *); + +void d_storesb(register unsigned char **, register signed char); +void d_storeub(register unsigned char **, register unsigned char); +void d_storesw(register unsigned char **, register signed short); +void d_storeuw(register unsigned char **, register unsigned short); +void d_storesl(register unsigned char **, register signed long); +void d_storeul(register unsigned char **, register unsigned long); + +void d_fetchstr(const unsigned char **, char *, unsigned); +void d_storestr(unsigned char **, const char *, unsigned); + +int d_relstring(const char *, const char *); + +time_t d_ltime(unsigned long); +unsigned long d_mtime(time_t); diff --git a/qemu/roms/openbios/fs/hfs/include/file.h b/qemu/roms/openbios/fs/hfs/include/file.h new file mode 100644 index 000000000..dacdc4800 --- /dev/null +++ b/qemu/roms/openbios/fs/hfs/include/file.h @@ -0,0 +1,46 @@ +/* + * libhfs - library for reading and writing Macintosh HFS volumes + * Copyright (C) 1996-1998 Robert Leslie + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * $Id: file.h,v 1.6 1998/04/11 08:27:12 rob Exp $ + */ + +enum { + fkData = 0x00, + fkRsrc = 0xff +}; + +void f_init(hfsfile *, hfsvol *, long, const char *); +void f_selectfork(hfsfile *, int); +void f_getptrs(hfsfile *, ExtDataRec **, unsigned long **, unsigned long **); + +int f_doblock(hfsfile *, unsigned long, block *, + int (*)(hfsvol *, unsigned int, unsigned int, block *)); + +# define f_getblock(file, num, bp) \ + f_doblock((file), (num), (bp), b_readab) +# define f_putblock(file, num, bp) \ + f_doblock((file), (num), (bp), \ + (int (*)(hfsvol *, unsigned int, unsigned int, block *)) \ + b_writeab) + +int f_addextent(hfsfile *, ExtDescriptor *); +long f_alloc(hfsfile *); + +int f_trunc(hfsfile *); +int f_flush(hfsfile *); diff --git a/qemu/roms/openbios/fs/hfs/include/hfs.h b/qemu/roms/openbios/fs/hfs/include/hfs.h new file mode 100644 index 000000000..9996cc8dd --- /dev/null +++ b/qemu/roms/openbios/fs/hfs/include/hfs.h @@ -0,0 +1,180 @@ +/* + * libhfs - library for reading and writing Macintosh HFS volumes + * Copyright (C) 1996-1998 Robert Leslie + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * $Id: hfs.h,v 1.11 1998/11/02 22:09:01 rob Exp $ + */ + +# define HFS_BLOCKSZ 512 +# define HFS_BLOCKSZ_BITS 9 + +# define HFS_MAX_FLEN 31 +# define HFS_MAX_VLEN 27 + +typedef struct _hfsvol_ hfsvol; +typedef struct _hfsfile_ hfsfile; +typedef struct _hfsdir_ hfsdir; + +typedef struct { + char name[HFS_MAX_VLEN + 1]; /* name of volume (MacOS Standard Roman) */ + int flags; /* volume flags */ + + unsigned long totbytes; /* total bytes on volume */ + unsigned long freebytes; /* free bytes on volume */ + + unsigned long alblocksz; /* volume allocation block size */ + unsigned long clumpsz; /* default file clump size */ + + unsigned long numfiles; /* number of files in volume */ + unsigned long numdirs; /* number of directories in volume */ + + time_t crdate; /* volume creation date */ + time_t mddate; /* last volume modification date */ + time_t bkdate; /* last volume backup date */ + + unsigned long blessed; /* CNID of MacOS System Folder */ +} hfsvolent; + +typedef struct { + char name[HFS_MAX_FLEN + 1]; /* catalog name (MacOS Standard Roman) */ + int flags; /* bit flags */ + unsigned long cnid; /* catalog node id (CNID) */ + unsigned long parid; /* CNID of parent directory */ + + time_t crdate; /* date of creation */ + time_t mddate; /* date of last modification */ + time_t bkdate; /* date of last backup */ + + short fdflags; /* Macintosh Finder flags */ + + struct { + signed short v; /* Finder icon vertical coordinate */ + signed short h; /* horizontal coordinate */ + } fdlocation; + + union { + struct { + unsigned long dsize; /* size of data fork */ + unsigned long rsize; /* size of resource fork */ + + char type[5]; /* file type code (plus null) */ + char creator[5]; /* file creator code (plus null) */ + } file; + + struct { + unsigned short valence; /* number of items in directory */ + + struct { + signed short top; /* top edge of folder's rectangle */ + signed short left; /* left edge */ + signed short bottom; /* bottom edge */ + signed short right; /* right edge */ + } rect; + } dir; + } u; +} hfsdirent; + +# define HFS_ISDIR 0x0001 +# define HFS_ISLOCKED 0x0002 + +# define HFS_CNID_ROOTPAR 1 +# define HFS_CNID_ROOTDIR 2 +# define HFS_CNID_EXT 3 +# define HFS_CNID_CAT 4 +# define HFS_CNID_BADALLOC 5 + +# define HFS_FNDR_ISONDESK (1 << 0) +# define HFS_FNDR_COLOR 0x0e +# define HFS_FNDR_COLORRESERVED (1 << 4) +# define HFS_FNDR_REQUIRESSWITCHLAUNCH (1 << 5) +# define HFS_FNDR_ISSHARED (1 << 6) +# define HFS_FNDR_HASNOINITS (1 << 7) +# define HFS_FNDR_HASBEENINITED (1 << 8) +# define HFS_FNDR_RESERVED (1 << 9) +# define HFS_FNDR_HASCUSTOMICON (1 << 10) +# define HFS_FNDR_ISSTATIONERY (1 << 11) +# define HFS_FNDR_NAMELOCKED (1 << 12) +# define HFS_FNDR_HASBUNDLE (1 << 13) +# define HFS_FNDR_ISINVISIBLE (1 << 14) +# define HFS_FNDR_ISALIAS (1 << 15) + +extern const char *hfs_error; +extern const unsigned char hfs_charorder[]; + +# define HFS_MODE_RDONLY 0 +# define HFS_MODE_RDWR 1 +# define HFS_MODE_ANY 2 + +# define HFS_MODE_MASK 0x0003 + +# define HFS_OPT_NOCACHE 0x0100 +# define HFS_OPT_2048 0x0200 +# define HFS_OPT_ZERO 0x0400 + +# define HFS_SEEK_SET 0 +# define HFS_SEEK_CUR 1 +# define HFS_SEEK_END 2 + +hfsvol *hfs_mount( int os_fd, int); +int hfs_flush(hfsvol *); +void hfs_flushall(void); +int hfs_umount(hfsvol *); +void hfs_umountall(void); +hfsvol *hfs_getvol(const char *); +void hfs_setvol(hfsvol *); + +int hfs_vstat(hfsvol *, hfsvolent *); +int hfs_vsetattr(hfsvol *, hfsvolent *); + +int hfs_chdir(hfsvol *, const char *); +unsigned long hfs_getcwd(hfsvol *); +int hfs_setcwd(hfsvol *, unsigned long); +int hfs_dirinfo(hfsvol *, unsigned long *, char *); + +hfsdir *hfs_opendir(hfsvol *, const char *); +int hfs_readdir(hfsdir *, hfsdirent *); +int hfs_closedir(hfsdir *); + +hfsfile *hfs_create(hfsvol *, const char *, const char *, const char *); +hfsfile *hfs_open(hfsvol *, const char *); +int hfs_setfork(hfsfile *, int); +int hfs_getfork(hfsfile *); +unsigned long hfs_read(hfsfile *, void *, unsigned long); +unsigned long hfs_write(hfsfile *, const void *, unsigned long); +int hfs_truncate(hfsfile *, unsigned long); +unsigned long hfs_seek(hfsfile *, long, int); +int hfs_close(hfsfile *); + +int hfs_stat(hfsvol *, const char *, hfsdirent *); +int hfs_fstat(hfsfile *, hfsdirent *); +int hfs_setattr(hfsvol *, const char *, const hfsdirent *); +int hfs_fsetattr(hfsfile *, const hfsdirent *); + +int hfs_mkdir(hfsvol *, const char *); +int hfs_rmdir(hfsvol *, const char *); + +int hfs_delete(hfsvol *, const char *); +int hfs_rename(hfsvol *, const char *, const char *); + +int hfs_zero(const char *, unsigned int, unsigned long *); +int hfs_mkpart(const char *, unsigned long); +int hfs_nparts(const char *); + +int hfs_format(const char *, int, int, + const char *, unsigned int, const unsigned long []); +int hfs_probe(int fd, long long offset); diff --git a/qemu/roms/openbios/fs/hfs/include/libhfs.h b/qemu/roms/openbios/fs/hfs/include/libhfs.h new file mode 100644 index 000000000..f46f43832 --- /dev/null +++ b/qemu/roms/openbios/fs/hfs/include/libhfs.h @@ -0,0 +1,225 @@ +/* + * libhfs - library for reading and writing Macintosh HFS volumes + * Copyright (C) 1996-1998 Robert Leslie + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * $Id: libhfs.h,v 1.7 1998/11/02 22:09:02 rob Exp $ + */ + +# include "hfs.h" +# include "apple.h" + +# define ERROR(code, str) \ + do { hfs_error = (str), errno = (code); goto fail; } while (0) + +# ifdef DEBUG +# define ASSERT(cond) do { if (! (cond)) abort(); } while (0) +# else +# define ASSERT(cond) /* nothing */ +# endif + +# define SIZE(type, n) ((size_t) (sizeof(type) * (n))) +# define ALLOC(type, n) ((type *) malloc(SIZE(type, n))) +# define ALLOCX(type, n) ((n) ? ALLOC(type, n) : (type *) 0) +# define FREE(ptr) ((ptr) ? (void) free((void *) ptr) : (void) 0) + +# define REALLOC(ptr, type, n) \ + ((type *) ((ptr) ? realloc(ptr, SIZE(type, n)) : malloc(SIZE(type, n)))) +# define REALLOCX(ptr, type, n) \ + ((n) ? REALLOC(ptr, type, n) : (FREE(ptr), (type *) 0)) + +# define BMTST(bm, num) \ + (((const byte *) (bm))[(num) >> 3] & (0x80 >> ((num) & 0x07))) +# define BMSET(bm, num) \ + (((byte *) (bm))[(num) >> 3] |= (0x80 >> ((num) & 0x07))) +# define BMCLR(bm, num) \ + (((byte *) (bm))[(num) >> 3] &= ~(0x80 >> ((num) & 0x07))) + +# define STRINGIZE(x) #x +# define STR(x) STRINGIZE(x) + +typedef unsigned char byte; +typedef byte block[HFS_BLOCKSZ]; + +typedef struct _bucket_ { + int flags; /* bit flags */ + unsigned int count; /* number of times this block is requested */ + + unsigned long bnum; /* logical block number */ + block *data; /* pointer to block contents */ + + struct _bucket_ *cnext; /* next bucket in cache chain */ + struct _bucket_ *cprev; /* previous bucket in cache chain */ + + struct _bucket_ *hnext; /* next bucket in hash chain */ + struct _bucket_ **hprev; /* previous bucket's pointer to this bucket */ +} bucket; + +# define HFS_BUCKET_INUSE 0x01 +# define HFS_BUCKET_DIRTY 0x02 + +# define HFS_CACHESZ 128 +# define HFS_HASHSZ 32 +# define HFS_BLOCKBUFSZ 16 + +typedef struct { + struct _hfsvol_ *vol; /* volume to which cache belongs */ + bucket *tail; /* end of bucket chain */ + + unsigned int hits; /* number of cache hits */ + unsigned int misses; /* number of cache misses */ + + bucket chain[HFS_CACHESZ]; /* cache bucket chain */ + bucket *hash[HFS_HASHSZ]; /* hash table for bucket chain */ + + block pool[HFS_CACHESZ]; /* physical blocks in cache */ +} bcache; + +# define HFS_MAP1SZ 256 +# define HFS_MAPXSZ 492 + +# define HFS_NODEREC(nd, rnum) ((nd).data + (nd).roff[rnum]) +# define HFS_RECLEN(nd, rnum) ((nd).roff[(rnum) + 1] - (nd).roff[rnum]) + +# define HFS_RECKEYLEN(ptr) (*(const byte *) (ptr)) +# define HFS_RECKEYSKIP(ptr) ((size_t) ((1 + HFS_RECKEYLEN(ptr) + 1) & ~1)) +# define HFS_RECDATA(ptr) ((ptr) + HFS_RECKEYSKIP(ptr)) + +# define HFS_SETKEYLEN(ptr, x) (*(byte *) (ptr) = (x)) + +# define HFS_CATDATALEN sizeof(CatDataRec) +# define HFS_EXTDATALEN sizeof(ExtDataRec) +# define HFS_MAX_DATALEN (HFS_CATDATALEN > HFS_EXTDATALEN ? \ + HFS_CATDATALEN : HFS_EXTDATALEN) + +# define HFS_CATKEYLEN sizeof(CatKeyRec) +# define HFS_EXTKEYLEN sizeof(ExtKeyRec) +# define HFS_MAX_KEYLEN (HFS_CATKEYLEN > HFS_EXTKEYLEN ? \ + HFS_CATKEYLEN : HFS_EXTKEYLEN) + +# define HFS_MAX_CATRECLEN (HFS_CATKEYLEN + HFS_CATDATALEN) +# define HFS_MAX_EXTRECLEN (HFS_EXTKEYLEN + HFS_EXTDATALEN) +# define HFS_MAX_RECLEN (HFS_MAX_KEYLEN + HFS_MAX_DATALEN) + +# define HFS_SIGWORD 0x4244 +# define HFS_SIGWORD_MFS ((Integer) 0xd2d7) + +# define HFS_ATRB_BUSY (1 << 6) +# define HFS_ATRB_HLOCKED (1 << 7) +# define HFS_ATRB_UMOUNTED (1 << 8) +# define HFS_ATRB_BBSPARED (1 << 9) +# define HFS_ATRB_BVINCONSIS (1 << 11) +# define HFS_ATRB_COPYPROT (1 << 14) +# define HFS_ATRB_SLOCKED (1 << 15) + +struct _hfsfile_ { + struct _hfsvol_ *vol; /* pointer to volume descriptor */ + unsigned long parid; /* parent directory ID of this file */ + char name[HFS_MAX_FLEN + 1]; /* catalog name of this file */ + CatDataRec cat; /* catalog information */ + ExtDataRec ext; /* current extent record */ + unsigned int fabn; /* starting file allocation block number */ + int fork; /* current selected fork for I/O */ + unsigned long pos; /* current file seek pointer */ + int flags; /* bit flags */ + + struct _hfsfile_ *prev; + struct _hfsfile_ *next; +}; + +# define HFS_FILE_UPDATE_CATREC 0x01 + +# define HFS_MAX_NRECS 35 /* maximum based on minimum record size */ + +typedef struct _node_ { + struct _btree_ *bt; /* btree to which this node belongs */ + unsigned long nnum; /* node index */ + NodeDescriptor nd; /* node descriptor */ + int rnum; /* current record index */ + UInteger roff[HFS_MAX_NRECS + 1]; + /* record offsets */ + block data; /* raw contents of node */ +} node; + +struct _hfsdir_ { + struct _hfsvol_ *vol; /* associated volume */ + unsigned long dirid; /* directory ID of interest (or 0) */ + + node n; /* current B*-tree node */ + struct _hfsvol_ *vptr; /* current volume pointer */ + + struct _hfsdir_ *prev; + struct _hfsdir_ *next; +}; + +typedef void (*keyunpackfunc)(const byte *, void *); +typedef int (*keycomparefunc)(const void *, const void *); + +typedef struct _btree_ { + hfsfile f; /* subset file information */ + node hdrnd; /* header node */ + BTHdrRec hdr; /* header record */ + byte *map; /* usage bitmap */ + unsigned long mapsz; /* number of bytes in bitmap */ + int flags; /* bit flags */ + + keyunpackfunc keyunpack; /* key unpacking function */ + keycomparefunc keycompare; /* key comparison function */ +} btree; + +# define HFS_BT_UPDATE_HDR 0x01 + +struct _hfsvol_ { + int os_fd; /* OS-dependent private descriptor data */ + int flags; /* bit flags */ + + int pnum; /* ordinal HFS partition number */ + unsigned long vstart; /* logical block offset to start of volume */ + unsigned long vlen; /* number of logical blocks in volume */ + unsigned int lpa; /* number of logical blocks per allocation block */ + + bcache *cache; /* cache of recently used blocks */ + + MDB mdb; /* master directory block */ + block *vbm; /* volume bitmap */ + unsigned short vbmsz; /* number of blocks in bitmap */ + + btree ext; /* B*-tree control block for extents overflow file */ + btree cat; /* B*-tree control block for catalog file */ + + unsigned long cwd; /* directory id of current working directory */ + + int refs; /* number of external references to this volume */ + hfsfile *files; /* list of open files */ + hfsdir *dirs; /* list of open directories */ + + struct _hfsvol_ *prev; + struct _hfsvol_ *next; +}; + +# define HFS_VOL_OPEN 0x0001 +# define HFS_VOL_MOUNTED 0x0002 +# define HFS_VOL_READONLY 0x0004 +# define HFS_VOL_USINGCACHE 0x0008 + +# define HFS_VOL_UPDATE_MDB 0x0010 +# define HFS_VOL_UPDATE_ALTMDB 0x0020 +# define HFS_VOL_UPDATE_VBM 0x0040 + +# define HFS_VOL_OPT_MASK 0xff00 + +extern hfsvol *hfs_mounts; diff --git a/qemu/roms/openbios/fs/hfs/include/low.h b/qemu/roms/openbios/fs/hfs/include/low.h new file mode 100644 index 000000000..56d049a8e --- /dev/null +++ b/qemu/roms/openbios/fs/hfs/include/low.h @@ -0,0 +1,45 @@ +/* + * libhfs - library for reading and writing Macintosh HFS volumes + * Copyright (C) 1996-1998 Robert Leslie + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * $Id: low.h,v 1.6 1998/04/11 08:27:13 rob Exp $ + */ + +# define HFS_DDR_SIGWORD 0x4552 + +# define HFS_PM_SIGWORD 0x504d +# define HFS_PM_SIGWORD_OLD 0x5453 + +# define HFS_BB_SIGWORD 0x4c4b + +# define HFS_BOOTCODE1LEN (HFS_BLOCKSZ - 148) +# define HFS_BOOTCODE2LEN HFS_BLOCKSZ + +# define HFS_BOOTCODELEN (HFS_BOOTCODE1LEN + HFS_BOOTCODE2LEN) + +int l_getddr(hfsvol *, Block0 *); +int l_putddr(hfsvol *, const Block0 *); + +int l_getpmentry(hfsvol *, Partition *, unsigned long); +int l_putpmentry(hfsvol *, const Partition *, unsigned long); + +int l_getbb(hfsvol *, BootBlkHdr *, byte *); +int l_putbb(hfsvol *, const BootBlkHdr *, const byte *); + +int l_getmdb(hfsvol *, MDB *, int); +int l_putmdb(hfsvol *, const MDB *, int); diff --git a/qemu/roms/openbios/fs/hfs/include/medium.h b/qemu/roms/openbios/fs/hfs/include/medium.h new file mode 100644 index 000000000..29d97a4e7 --- /dev/null +++ b/qemu/roms/openbios/fs/hfs/include/medium.h @@ -0,0 +1,43 @@ +/* + * libhfs - library for reading and writing Macintosh HFS volumes + * Copyright (C) 1996-1998 Robert Leslie + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * $Id: medium.h,v 1.3 1998/04/11 08:27:13 rob Exp $ + */ + +/* + * Partition Types: + * + * "Apple_partition_map" partition map + * "Apple_Driver" device driver + * "Apple_Driver43" SCSI Manager 4.3 device driver + * "Apple_MFS" Macintosh 64K ROM filesystem + * "Apple_HFS" Macintosh hierarchical filesystem + * "Apple_Unix_SVR2" Unix filesystem + * "Apple_PRODOS" ProDOS filesystem + * "Apple_Free" unused + * "Apple_Scratch" empty + */ + +int m_zeroddr(hfsvol *); + +int m_zeropm(hfsvol *, unsigned int); +int m_findpmentry(hfsvol *, const char *, Partition *, unsigned long *); +int m_mkpart(hfsvol *, const char *, const char *, unsigned long); + +int m_zerobb(hfsvol *); diff --git a/qemu/roms/openbios/fs/hfs/include/node.h b/qemu/roms/openbios/fs/hfs/include/node.h new file mode 100644 index 000000000..d7367fd57 --- /dev/null +++ b/qemu/roms/openbios/fs/hfs/include/node.h @@ -0,0 +1,35 @@ +/* + * libhfs - library for reading and writing Macintosh HFS volumes + * Copyright (C) 1996-1998 Robert Leslie + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * $Id: node.h,v 1.7 1998/11/02 22:09:06 rob Exp $ + */ + +void n_init(node *, btree *, int, int); + +int n_new(node *); +int n_free(node *); + +int n_search(node *, const byte *); + +void n_index(const node *, byte *, unsigned int *); + +void n_insertx(node *, const byte *, unsigned int); +int n_insert(node *, byte *, unsigned int *); + +int n_delete(node *, byte *, int *); diff --git a/qemu/roms/openbios/fs/hfs/include/record.h b/qemu/roms/openbios/fs/hfs/include/record.h new file mode 100644 index 000000000..283e809fa --- /dev/null +++ b/qemu/roms/openbios/fs/hfs/include/record.h @@ -0,0 +1,48 @@ +/* + * libhfs - library for reading and writing Macintosh HFS volumes + * Copyright (C) 1996-1998 Robert Leslie + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * $Id: record.h,v 1.7 1998/11/02 22:09:08 rob Exp $ + */ + +void r_packcatkey(const CatKeyRec *, byte *, unsigned int *); +void r_unpackcatkey(const byte *, CatKeyRec *); + +void r_packextkey(const ExtKeyRec *, byte *, unsigned int *); +void r_unpackextkey(const byte *, ExtKeyRec *); + +int r_comparecatkeys(const CatKeyRec *, const CatKeyRec *); +int r_compareextkeys(const ExtKeyRec *, const ExtKeyRec *); + +void r_packcatdata(const CatDataRec *, byte *, unsigned int *); +void r_unpackcatdata(const byte *, CatDataRec *); + +void r_packextdata(const ExtDataRec *, byte *, unsigned int *); +void r_unpackextdata(const byte *, ExtDataRec *); + +void r_makecatkey(CatKeyRec *, unsigned long, const char *); +void r_makeextkey(ExtKeyRec *, int, unsigned long, unsigned int); + +void r_packcatrec(const CatKeyRec *, const CatDataRec *, + byte *, unsigned int *); +void r_packextrec(const ExtKeyRec *, const ExtDataRec *, + byte *, unsigned int *); + +void r_packdirent(CatDataRec *, const hfsdirent *); +void r_unpackdirent(unsigned long, const char *, + const CatDataRec *, hfsdirent *); diff --git a/qemu/roms/openbios/fs/hfs/include/volume.h b/qemu/roms/openbios/fs/hfs/include/volume.h new file mode 100644 index 000000000..562c2d194 --- /dev/null +++ b/qemu/roms/openbios/fs/hfs/include/volume.h @@ -0,0 +1,71 @@ +/* + * libhfs - library for reading and writing Macintosh HFS volumes + * Copyright (C) 1996-1998 Robert Leslie + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * $Id: volume.h,v 1.7 1998/11/02 22:09:12 rob Exp $ + */ + +#ifndef _H_VOLUME +#define _H_VOLUME + +void v_init(hfsvol *, int); + +int v_open(hfsvol *, int os_fd); +int v_flush(hfsvol *); +int v_close(hfsvol *); + +int v_same(hfsvol *, int os_fd); +int v_geometry(hfsvol *, int); + +int v_readmdb(hfsvol *); +int v_writemdb(hfsvol *); + +int v_readvbm(hfsvol *); +int v_writevbm(hfsvol *); + +int v_mount(hfsvol *); +int v_dirty(hfsvol *); + +int v_catsearch(hfsvol *, unsigned long, const char *, + CatDataRec *, char *, node *); +int v_extsearch(hfsfile *, unsigned int, ExtDataRec *, node *); + +int v_getthread(hfsvol *, unsigned long, CatDataRec *, node *, int); + +# define v_getdthread(vol, id, thread, np) \ + v_getthread(vol, id, thread, np, cdrThdRec) +# define v_getfthread(vol, id, thread, np) \ + v_getthread(vol, id, thread, np, cdrFThdRec) + +int v_putcatrec(const CatDataRec *, node *); +int v_putextrec(const ExtDataRec *, node *); + +int v_allocblocks(hfsvol *, ExtDescriptor *); +int v_freeblocks(hfsvol *, const ExtDescriptor *); + +int v_resolve(hfsvol **vol, const char *path, + CatDataRec *data, unsigned long *parid, char *fname, node *np); + +int v_adjvalence(hfsvol *, unsigned long, int, int); +int v_mkdir(hfsvol *, unsigned long, const char *); + +int v_scavenge(hfsvol *); + +int v_probe(int fd, long long offset); + +#endif /* _H_VOLUME */ diff --git a/qemu/roms/openbios/fs/hfs/low.c b/qemu/roms/openbios/fs/hfs/low.c new file mode 100644 index 000000000..e0f7cb0e3 --- /dev/null +++ b/qemu/roms/openbios/fs/hfs/low.c @@ -0,0 +1,157 @@ +/* + * libhfs - library for reading and writing Macintosh HFS volumes + * Copyright (C) 1996-1998, 2001 Robert Leslie + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * $Id: low.c,v 1.8 1998/11/02 22:09:03 rob Exp $ + */ + +#include "config.h" +#include "libhfs.h" +#include "low.h" +#include "data.h" +#include "block.h" +#include "file.h" + +/* + * NAME: low->getpmentry() + * DESCRIPTION: read a partition map entry + */ +int l_getpmentry(hfsvol *vol, Partition *map, unsigned long bnum) +{ + block b; + const byte *ptr = b; + int i; + + if (b_readpb(vol, bnum, &b, 1) == -1) + goto fail; + + d_fetchsw(&ptr, &map->pmSig); + d_fetchsw(&ptr, &map->pmSigPad); + d_fetchsl(&ptr, &map->pmMapBlkCnt); + d_fetchsl(&ptr, &map->pmPyPartStart); + d_fetchsl(&ptr, &map->pmPartBlkCnt); + + strncpy((char *) map->pmPartName, (const char *) ptr, 32); + map->pmPartName[32] = 0; + ptr += 32; + + strncpy((char *) map->pmParType, (const char *) ptr, 32); + map->pmParType[32] = 0; + ptr += 32; + + d_fetchsl(&ptr, &map->pmLgDataStart); + d_fetchsl(&ptr, &map->pmDataCnt); + d_fetchsl(&ptr, &map->pmPartStatus); + d_fetchsl(&ptr, &map->pmLgBootStart); + d_fetchsl(&ptr, &map->pmBootSize); + d_fetchsl(&ptr, &map->pmBootAddr); + d_fetchsl(&ptr, &map->pmBootAddr2); + d_fetchsl(&ptr, &map->pmBootEntry); + d_fetchsl(&ptr, &map->pmBootEntry2); + d_fetchsl(&ptr, &map->pmBootCksum); + + strncpy((char *) map->pmProcessor, (const char *) ptr, 16); + map->pmProcessor[16] = 0; + ptr += 16; + + for (i = 0; i < 188; ++i) + d_fetchsw(&ptr, &map->pmPad[i]); + + ASSERT(ptr - b == HFS_BLOCKSZ); + + return 0; + +fail: + return -1; +} + + +/* + * NAME: low->getmdb() + * DESCRIPTION: read a master directory block + */ +int l_getmdb(hfsvol *vol, MDB *mdb, int backup) +{ + block b; + const byte *ptr = b; + int i; + + if (b_readlb(vol, backup ? vol->vlen - 2 : 2, &b) == -1) + goto fail; + + d_fetchsw(&ptr, &mdb->drSigWord); + d_fetchsl(&ptr, &mdb->drCrDate); + d_fetchsl(&ptr, &mdb->drLsMod); + d_fetchsw(&ptr, &mdb->drAtrb); + d_fetchuw(&ptr, &mdb->drNmFls); + d_fetchuw(&ptr, &mdb->drVBMSt); + d_fetchuw(&ptr, &mdb->drAllocPtr); + d_fetchuw(&ptr, &mdb->drNmAlBlks); + d_fetchul(&ptr, &mdb->drAlBlkSiz); + d_fetchul(&ptr, &mdb->drClpSiz); + d_fetchuw(&ptr, &mdb->drAlBlSt); + d_fetchsl(&ptr, &mdb->drNxtCNID); + d_fetchuw(&ptr, &mdb->drFreeBks); + + d_fetchstr(&ptr, mdb->drVN, sizeof(mdb->drVN)); + + ASSERT(ptr - b == 64); + + d_fetchsl(&ptr, &mdb->drVolBkUp); + d_fetchsw(&ptr, &mdb->drVSeqNum); + d_fetchul(&ptr, &mdb->drWrCnt); + d_fetchul(&ptr, &mdb->drXTClpSiz); + d_fetchul(&ptr, &mdb->drCTClpSiz); + d_fetchuw(&ptr, &mdb->drNmRtDirs); + d_fetchul(&ptr, &mdb->drFilCnt); + d_fetchul(&ptr, &mdb->drDirCnt); + + for (i = 0; i < 8; ++i) + d_fetchsl(&ptr, &mdb->drFndrInfo[i]); + + ASSERT(ptr - b == 124); + + d_fetchuw(&ptr, &mdb->drEmbedSigWord); + d_fetchuw(&ptr, &mdb->drEmbedExtent.xdrStABN); + d_fetchuw(&ptr, &mdb->drEmbedExtent.xdrNumABlks); + + d_fetchul(&ptr, &mdb->drXTFlSize); + + for (i = 0; i < 3; ++i) + { + d_fetchuw(&ptr, &mdb->drXTExtRec[i].xdrStABN); + d_fetchuw(&ptr, &mdb->drXTExtRec[i].xdrNumABlks); + } + + ASSERT(ptr - b == 146); + + d_fetchul(&ptr, &mdb->drCTFlSize); + + for (i = 0; i < 3; ++i) + { + d_fetchuw(&ptr, &mdb->drCTExtRec[i].xdrStABN); + d_fetchuw(&ptr, &mdb->drCTExtRec[i].xdrNumABlks); + } + + ASSERT(ptr - b == 162); + + return 0; + +fail: + return -1; +} diff --git a/qemu/roms/openbios/fs/hfs/medium.c b/qemu/roms/openbios/fs/hfs/medium.c new file mode 100644 index 000000000..171ba80dc --- /dev/null +++ b/qemu/roms/openbios/fs/hfs/medium.c @@ -0,0 +1,84 @@ +/* + * libhfs - library for reading and writing Macintosh HFS volumes + * Copyright (C) 1996-1998 Robert Leslie + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * $Id: medium.c,v 1.4 1998/11/02 22:09:04 rob Exp $ + */ + +#include "config.h" +#include "libhfs.h" +#include "block.h" +#include "low.h" +#include "medium.h" + + +/* + * NAME: medium->findpmentry() + * DESCRIPTION: locate a partition map entry + */ +int m_findpmentry(hfsvol *vol, const char *type, + Partition *map, unsigned long *start) +{ + unsigned long bnum; + int found = 0; + + if (start && *start > 0) + { + bnum = *start; + + if (bnum++ >= (unsigned long) map->pmMapBlkCnt) + ERROR(EINVAL, "partition not found"); + } + else + bnum = 1; + + while (1) + { + if (l_getpmentry(vol, map, bnum) == -1) + { + found = -1; + goto fail; + } + + if (map->pmSig != HFS_PM_SIGWORD) + { + found = -1; + + if (map->pmSig == HFS_PM_SIGWORD_OLD) + ERROR(EINVAL, "old partition map format not supported"); + else + ERROR(EINVAL, "invalid partition map"); + } + + if (strcmp((char *) map->pmParType, type) == 0) + { + found = 1; + goto done; + } + + if (bnum++ >= (unsigned long) map->pmMapBlkCnt) + ERROR(EINVAL, "partition not found"); + } + +done: + if (start) + *start = bnum; + +fail: + return found; +} diff --git a/qemu/roms/openbios/fs/hfs/node.c b/qemu/roms/openbios/fs/hfs/node.c new file mode 100644 index 000000000..1670f038b --- /dev/null +++ b/qemu/roms/openbios/fs/hfs/node.c @@ -0,0 +1,60 @@ +/* + * libhfs - library for reading and writing Macintosh HFS volumes + * Copyright (C) 1996-1998 Robert Leslie + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * $Id: node.c,v 1.9 1998/11/02 22:09:05 rob Exp $ + */ + +#include "config.h" +#include "libhfs.h" +#include "node.h" +#include "data.h" +#include "btree.h" + +/* + * NAME: node->search() + * DESCRIPTION: locate a record in a node, or the record it should follow + */ +int n_search(node *np, const byte *pkey) +{ + const btree *bt = np->bt; + byte key1[HFS_MAX_KEYLEN], key2[HFS_MAX_KEYLEN]; + int i, comp = -1; + + bt->keyunpack(pkey, key2); + + for (i = np->nd.ndNRecs; i--; ) + { + const byte *rec; + + rec = HFS_NODEREC(*np, i); + + if (HFS_RECKEYLEN(rec) == 0) + continue; /* deleted record */ + + bt->keyunpack(rec, key1); + comp = bt->keycompare(key1, key2); + + if (comp <= 0) + break; + } + + np->rnum = i; + + return comp == 0; +} diff --git a/qemu/roms/openbios/fs/hfs/record.c b/qemu/roms/openbios/fs/hfs/record.c new file mode 100644 index 000000000..92a3adddf --- /dev/null +++ b/qemu/roms/openbios/fs/hfs/record.c @@ -0,0 +1,553 @@ +/* + * libhfs - library for reading and writing Macintosh HFS volumes + * Copyright (C) 1996-1998 Robert Leslie + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * $Id: record.c,v 1.9 1998/11/02 22:09:07 rob Exp $ + */ + +#include "config.h" +#include "libhfs.h" +#include "record.h" +#include "data.h" + +/* + * NAME: record->packcatkey() + * DESCRIPTION: pack a catalog record key + */ +void r_packcatkey(const CatKeyRec *key, byte *pkey, unsigned int *len) +{ + const byte *start = pkey; + + d_storesb(&pkey, key->ckrKeyLen); + d_storesb(&pkey, key->ckrResrv1); + d_storeul(&pkey, key->ckrParID); + + d_storestr(&pkey, key->ckrCName, sizeof(key->ckrCName)); + + if (len) + *len = HFS_RECKEYSKIP(start); +} + +/* + * NAME: record->unpackcatkey() + * DESCRIPTION: unpack a catalog record key + */ +void r_unpackcatkey(const byte *pkey, CatKeyRec *key) +{ + d_fetchsb(&pkey, &key->ckrKeyLen); + d_fetchsb(&pkey, &key->ckrResrv1); + d_fetchul(&pkey, &key->ckrParID); + + d_fetchstr(&pkey, key->ckrCName, sizeof(key->ckrCName)); +} + +/* + * NAME: record->packextkey() + * DESCRIPTION: pack an extents record key + */ +void r_packextkey(const ExtKeyRec *key, byte *pkey, unsigned int *len) +{ + const byte *start = pkey; + + d_storesb(&pkey, key->xkrKeyLen); + d_storesb(&pkey, key->xkrFkType); + d_storeul(&pkey, key->xkrFNum); + d_storeuw(&pkey, key->xkrFABN); + + if (len) + *len = HFS_RECKEYSKIP(start); +} + +/* + * NAME: record->unpackextkey() + * DESCRIPTION: unpack an extents record key + */ +void r_unpackextkey(const byte *pkey, ExtKeyRec *key) +{ + d_fetchsb(&pkey, &key->xkrKeyLen); + d_fetchsb(&pkey, &key->xkrFkType); + d_fetchul(&pkey, &key->xkrFNum); + d_fetchuw(&pkey, &key->xkrFABN); +} + +/* + * NAME: record->comparecatkeys() + * DESCRIPTION: compare two (packed) catalog record keys + */ +int r_comparecatkeys(const CatKeyRec *key1, const CatKeyRec *key2) +{ + int diff; + + diff = key1->ckrParID - key2->ckrParID; + if (diff) + return diff; + + return d_relstring(key1->ckrCName, key2->ckrCName); +} + +/* + * NAME: record->compareextkeys() + * DESCRIPTION: compare two (packed) extents record keys + */ +int r_compareextkeys(const ExtKeyRec *key1, const ExtKeyRec *key2) +{ + int diff; + + diff = key1->xkrFNum - key2->xkrFNum; + if (diff) + return diff; + + diff = (unsigned char) key1->xkrFkType - + (unsigned char) key2->xkrFkType; + if (diff) + return diff; + + return key1->xkrFABN - key2->xkrFABN; +} + +/* + * NAME: record->packcatdata() + * DESCRIPTION: pack catalog record data + */ +void r_packcatdata(const CatDataRec *data, byte *pdata, unsigned int *len) +{ + const byte *start = pdata; + int i; + + d_storesb(&pdata, data->cdrType); + d_storesb(&pdata, data->cdrResrv2); + + switch (data->cdrType) + { + case cdrDirRec: + d_storesw(&pdata, data->u.dir.dirFlags); + d_storeuw(&pdata, data->u.dir.dirVal); + d_storeul(&pdata, data->u.dir.dirDirID); + d_storesl(&pdata, data->u.dir.dirCrDat); + d_storesl(&pdata, data->u.dir.dirMdDat); + d_storesl(&pdata, data->u.dir.dirBkDat); + + d_storesw(&pdata, data->u.dir.dirUsrInfo.frRect.top); + d_storesw(&pdata, data->u.dir.dirUsrInfo.frRect.left); + d_storesw(&pdata, data->u.dir.dirUsrInfo.frRect.bottom); + d_storesw(&pdata, data->u.dir.dirUsrInfo.frRect.right); + d_storesw(&pdata, data->u.dir.dirUsrInfo.frFlags); + d_storesw(&pdata, data->u.dir.dirUsrInfo.frLocation.v); + d_storesw(&pdata, data->u.dir.dirUsrInfo.frLocation.h); + d_storesw(&pdata, data->u.dir.dirUsrInfo.frView); + + d_storesw(&pdata, data->u.dir.dirFndrInfo.frScroll.v); + d_storesw(&pdata, data->u.dir.dirFndrInfo.frScroll.h); + d_storesl(&pdata, data->u.dir.dirFndrInfo.frOpenChain); + d_storesw(&pdata, data->u.dir.dirFndrInfo.frUnused); + d_storesw(&pdata, data->u.dir.dirFndrInfo.frComment); + d_storesl(&pdata, data->u.dir.dirFndrInfo.frPutAway); + + for (i = 0; i < 4; ++i) + d_storesl(&pdata, data->u.dir.dirResrv[i]); + + break; + + case cdrFilRec: + d_storesb(&pdata, data->u.fil.filFlags); + d_storesb(&pdata, data->u.fil.filTyp); + + d_storesl(&pdata, data->u.fil.filUsrWds.fdType); + d_storesl(&pdata, data->u.fil.filUsrWds.fdCreator); + d_storesw(&pdata, data->u.fil.filUsrWds.fdFlags); + d_storesw(&pdata, data->u.fil.filUsrWds.fdLocation.v); + d_storesw(&pdata, data->u.fil.filUsrWds.fdLocation.h); + d_storesw(&pdata, data->u.fil.filUsrWds.fdFldr); + + d_storeul(&pdata, data->u.fil.filFlNum); + + d_storeuw(&pdata, data->u.fil.filStBlk); + d_storeul(&pdata, data->u.fil.filLgLen); + d_storeul(&pdata, data->u.fil.filPyLen); + + d_storeuw(&pdata, data->u.fil.filRStBlk); + d_storeul(&pdata, data->u.fil.filRLgLen); + d_storeul(&pdata, data->u.fil.filRPyLen); + + d_storesl(&pdata, data->u.fil.filCrDat); + d_storesl(&pdata, data->u.fil.filMdDat); + d_storesl(&pdata, data->u.fil.filBkDat); + + d_storesw(&pdata, data->u.fil.filFndrInfo.fdIconID); + for (i = 0; i < 4; ++i) + d_storesw(&pdata, data->u.fil.filFndrInfo.fdUnused[i]); + d_storesw(&pdata, data->u.fil.filFndrInfo.fdComment); + d_storesl(&pdata, data->u.fil.filFndrInfo.fdPutAway); + + d_storeuw(&pdata, data->u.fil.filClpSize); + + for (i = 0; i < 3; ++i) + { + d_storeuw(&pdata, data->u.fil.filExtRec[i].xdrStABN); + d_storeuw(&pdata, data->u.fil.filExtRec[i].xdrNumABlks); + } + + for (i = 0; i < 3; ++i) + { + d_storeuw(&pdata, data->u.fil.filRExtRec[i].xdrStABN); + d_storeuw(&pdata, data->u.fil.filRExtRec[i].xdrNumABlks); + } + + d_storesl(&pdata, data->u.fil.filResrv); + + break; + + case cdrThdRec: + for (i = 0; i < 2; ++i) + d_storesl(&pdata, data->u.dthd.thdResrv[i]); + + d_storeul(&pdata, data->u.dthd.thdParID); + + d_storestr(&pdata, data->u.dthd.thdCName, + sizeof(data->u.dthd.thdCName)); + + break; + + case cdrFThdRec: + for (i = 0; i < 2; ++i) + d_storesl(&pdata, data->u.fthd.fthdResrv[i]); + + d_storeul(&pdata, data->u.fthd.fthdParID); + + d_storestr(&pdata, data->u.fthd.fthdCName, + sizeof(data->u.fthd.fthdCName)); + + break; + + default: + ASSERT(0); + } + + if (len) + *len += pdata - start; +} + +/* + * NAME: record->unpackcatdata() + * DESCRIPTION: unpack catalog record data + */ +void r_unpackcatdata(const byte *pdata, CatDataRec *data) +{ + int i; + + d_fetchsb(&pdata, &data->cdrType); + d_fetchsb(&pdata, &data->cdrResrv2); + + switch (data->cdrType) + { + case cdrDirRec: + d_fetchsw(&pdata, &data->u.dir.dirFlags); + d_fetchuw(&pdata, &data->u.dir.dirVal); + d_fetchul(&pdata, &data->u.dir.dirDirID); + d_fetchsl(&pdata, &data->u.dir.dirCrDat); + d_fetchsl(&pdata, &data->u.dir.dirMdDat); + d_fetchsl(&pdata, &data->u.dir.dirBkDat); + + d_fetchsw(&pdata, &data->u.dir.dirUsrInfo.frRect.top); + d_fetchsw(&pdata, &data->u.dir.dirUsrInfo.frRect.left); + d_fetchsw(&pdata, &data->u.dir.dirUsrInfo.frRect.bottom); + d_fetchsw(&pdata, &data->u.dir.dirUsrInfo.frRect.right); + d_fetchsw(&pdata, &data->u.dir.dirUsrInfo.frFlags); + d_fetchsw(&pdata, &data->u.dir.dirUsrInfo.frLocation.v); + d_fetchsw(&pdata, &data->u.dir.dirUsrInfo.frLocation.h); + d_fetchsw(&pdata, &data->u.dir.dirUsrInfo.frView); + + d_fetchsw(&pdata, &data->u.dir.dirFndrInfo.frScroll.v); + d_fetchsw(&pdata, &data->u.dir.dirFndrInfo.frScroll.h); + d_fetchsl(&pdata, &data->u.dir.dirFndrInfo.frOpenChain); + d_fetchsw(&pdata, &data->u.dir.dirFndrInfo.frUnused); + d_fetchsw(&pdata, &data->u.dir.dirFndrInfo.frComment); + d_fetchsl(&pdata, &data->u.dir.dirFndrInfo.frPutAway); + + for (i = 0; i < 4; ++i) + d_fetchsl(&pdata, &data->u.dir.dirResrv[i]); + + break; + + case cdrFilRec: + d_fetchsb(&pdata, &data->u.fil.filFlags); + d_fetchsb(&pdata, &data->u.fil.filTyp); + + d_fetchsl(&pdata, &data->u.fil.filUsrWds.fdType); + d_fetchsl(&pdata, &data->u.fil.filUsrWds.fdCreator); + d_fetchsw(&pdata, &data->u.fil.filUsrWds.fdFlags); + d_fetchsw(&pdata, &data->u.fil.filUsrWds.fdLocation.v); + d_fetchsw(&pdata, &data->u.fil.filUsrWds.fdLocation.h); + d_fetchsw(&pdata, &data->u.fil.filUsrWds.fdFldr); + + d_fetchul(&pdata, &data->u.fil.filFlNum); + + d_fetchuw(&pdata, &data->u.fil.filStBlk); + d_fetchul(&pdata, &data->u.fil.filLgLen); + d_fetchul(&pdata, &data->u.fil.filPyLen); + + d_fetchuw(&pdata, &data->u.fil.filRStBlk); + d_fetchul(&pdata, &data->u.fil.filRLgLen); + d_fetchul(&pdata, &data->u.fil.filRPyLen); + + d_fetchsl(&pdata, &data->u.fil.filCrDat); + d_fetchsl(&pdata, &data->u.fil.filMdDat); + d_fetchsl(&pdata, &data->u.fil.filBkDat); + + d_fetchsw(&pdata, &data->u.fil.filFndrInfo.fdIconID); + for (i = 0; i < 4; ++i) + d_fetchsw(&pdata, &data->u.fil.filFndrInfo.fdUnused[i]); + d_fetchsw(&pdata, &data->u.fil.filFndrInfo.fdComment); + d_fetchsl(&pdata, &data->u.fil.filFndrInfo.fdPutAway); + + d_fetchuw(&pdata, &data->u.fil.filClpSize); + + for (i = 0; i < 3; ++i) + { + d_fetchuw(&pdata, &data->u.fil.filExtRec[i].xdrStABN); + d_fetchuw(&pdata, &data->u.fil.filExtRec[i].xdrNumABlks); + } + + for (i = 0; i < 3; ++i) + { + d_fetchuw(&pdata, &data->u.fil.filRExtRec[i].xdrStABN); + d_fetchuw(&pdata, &data->u.fil.filRExtRec[i].xdrNumABlks); + } + + d_fetchsl(&pdata, &data->u.fil.filResrv); + + break; + + case cdrThdRec: + for (i = 0; i < 2; ++i) + d_fetchsl(&pdata, &data->u.dthd.thdResrv[i]); + + d_fetchul(&pdata, &data->u.dthd.thdParID); + + d_fetchstr(&pdata, data->u.dthd.thdCName, + sizeof(data->u.dthd.thdCName)); + + break; + + case cdrFThdRec: + for (i = 0; i < 2; ++i) + d_fetchsl(&pdata, &data->u.fthd.fthdResrv[i]); + + d_fetchul(&pdata, &data->u.fthd.fthdParID); + + d_fetchstr(&pdata, data->u.fthd.fthdCName, + sizeof(data->u.fthd.fthdCName)); + + break; + + default: + ASSERT(0); + } +} + +/* + * NAME: record->packextdata() + * DESCRIPTION: pack extent record data + */ +void r_packextdata(const ExtDataRec *data, byte *pdata, unsigned int *len) +{ + const byte *start = pdata; + int i; + + for (i = 0; i < 3; ++i) + { + d_storeuw(&pdata, (*data)[i].xdrStABN); + d_storeuw(&pdata, (*data)[i].xdrNumABlks); + } + + if (len) + *len += pdata - start; +} + +/* + * NAME: record->unpackextdata() + * DESCRIPTION: unpack extent record data + */ +void r_unpackextdata(const byte *pdata, ExtDataRec *data) +{ + int i; + + for (i = 0; i < 3; ++i) + { + d_fetchuw(&pdata, &(*data)[i].xdrStABN); + d_fetchuw(&pdata, &(*data)[i].xdrNumABlks); + } +} + +/* + * NAME: record->makecatkey() + * DESCRIPTION: construct a catalog record key + */ +void r_makecatkey(CatKeyRec *key, unsigned long parid, const char *name) +{ + int len; + + len = strlen(name) + 1; + + key->ckrKeyLen = 0x05 + len + (len & 1); + key->ckrResrv1 = 0; + key->ckrParID = parid; + + strcpy(key->ckrCName, name); +} + +/* + * NAME: record->makeextkey() + * DESCRIPTION: construct an extents record key + */ +void r_makeextkey(ExtKeyRec *key, + int fork, unsigned long fnum, unsigned int fabn) +{ + key->xkrKeyLen = 0x07; + key->xkrFkType = fork; + key->xkrFNum = fnum; + key->xkrFABN = fabn; +} + +/* + * NAME: record->packcatrec() + * DESCRIPTION: create a packed catalog record + */ +void r_packcatrec(const CatKeyRec *key, const CatDataRec *data, + byte *precord, unsigned int *len) +{ + r_packcatkey(key, precord, len); + r_packcatdata(data, HFS_RECDATA(precord), len); +} + +/* + * NAME: record->packextrec() + * DESCRIPTION: create a packed extents record + */ +void r_packextrec(const ExtKeyRec *key, const ExtDataRec *data, + byte *precord, unsigned int *len) +{ + r_packextkey(key, precord, len); + r_packextdata(data, HFS_RECDATA(precord), len); +} + +/* + * NAME: record->packdirent() + * DESCRIPTION: make changes to a catalog record + */ +void r_packdirent(CatDataRec *data, const hfsdirent *ent) +{ + switch (data->cdrType) + { + case cdrDirRec: + data->u.dir.dirCrDat = d_mtime(ent->crdate); + data->u.dir.dirMdDat = d_mtime(ent->mddate); + data->u.dir.dirBkDat = d_mtime(ent->bkdate); + + data->u.dir.dirUsrInfo.frFlags = ent->fdflags; + data->u.dir.dirUsrInfo.frLocation.v = ent->fdlocation.v; + data->u.dir.dirUsrInfo.frLocation.h = ent->fdlocation.h; + + data->u.dir.dirUsrInfo.frRect.top = ent->u.dir.rect.top; + data->u.dir.dirUsrInfo.frRect.left = ent->u.dir.rect.left; + data->u.dir.dirUsrInfo.frRect.bottom = ent->u.dir.rect.bottom; + data->u.dir.dirUsrInfo.frRect.right = ent->u.dir.rect.right; + + break; + + case cdrFilRec: + if (ent->flags & HFS_ISLOCKED) + data->u.fil.filFlags |= (1 << 0); + else + data->u.fil.filFlags &= ~(1 << 0); + + data->u.fil.filCrDat = d_mtime(ent->crdate); + data->u.fil.filMdDat = d_mtime(ent->mddate); + data->u.fil.filBkDat = d_mtime(ent->bkdate); + + data->u.fil.filUsrWds.fdFlags = ent->fdflags; + data->u.fil.filUsrWds.fdLocation.v = ent->fdlocation.v; + data->u.fil.filUsrWds.fdLocation.h = ent->fdlocation.h; + + data->u.fil.filUsrWds.fdType = + d_getsl((const unsigned char *) ent->u.file.type); + data->u.fil.filUsrWds.fdCreator = + d_getsl((const unsigned char *) ent->u.file.creator); + + break; + } +} + +/* + * NAME: record->unpackdirent() + * DESCRIPTION: unpack catalog information into hfsdirent structure + */ +void r_unpackdirent(unsigned long parid, const char *name, + const CatDataRec *data, hfsdirent *ent) +{ + strcpy(ent->name, name); + ent->parid = parid; + + switch (data->cdrType) + { + case cdrDirRec: + ent->flags = HFS_ISDIR; + ent->cnid = data->u.dir.dirDirID; + + ent->crdate = d_ltime(data->u.dir.dirCrDat); + ent->mddate = d_ltime(data->u.dir.dirMdDat); + ent->bkdate = d_ltime(data->u.dir.dirBkDat); + + ent->fdflags = data->u.dir.dirUsrInfo.frFlags; + ent->fdlocation.v = data->u.dir.dirUsrInfo.frLocation.v; + ent->fdlocation.h = data->u.dir.dirUsrInfo.frLocation.h; + + ent->u.dir.valence = data->u.dir.dirVal; + + ent->u.dir.rect.top = data->u.dir.dirUsrInfo.frRect.top; + ent->u.dir.rect.left = data->u.dir.dirUsrInfo.frRect.left; + ent->u.dir.rect.bottom = data->u.dir.dirUsrInfo.frRect.bottom; + ent->u.dir.rect.right = data->u.dir.dirUsrInfo.frRect.right; + + break; + + case cdrFilRec: + ent->flags = (data->u.fil.filFlags & (1 << 0)) ? HFS_ISLOCKED : 0; + ent->cnid = data->u.fil.filFlNum; + + ent->crdate = d_ltime(data->u.fil.filCrDat); + ent->mddate = d_ltime(data->u.fil.filMdDat); + ent->bkdate = d_ltime(data->u.fil.filBkDat); + + ent->fdflags = data->u.fil.filUsrWds.fdFlags; + ent->fdlocation.v = data->u.fil.filUsrWds.fdLocation.v; + ent->fdlocation.h = data->u.fil.filUsrWds.fdLocation.h; + + ent->u.file.dsize = data->u.fil.filLgLen; + ent->u.file.rsize = data->u.fil.filRLgLen; + + d_putsl((unsigned char *) ent->u.file.type, + data->u.fil.filUsrWds.fdType); + d_putsl((unsigned char *) ent->u.file.creator, + data->u.fil.filUsrWds.fdCreator); + + ent->u.file.type[4] = ent->u.file.creator[4] = 0; + + break; + } +} diff --git a/qemu/roms/openbios/fs/hfs/volume.c b/qemu/roms/openbios/fs/hfs/volume.c new file mode 100644 index 000000000..4faf7e6c2 --- /dev/null +++ b/qemu/roms/openbios/fs/hfs/volume.c @@ -0,0 +1,612 @@ +/* + * libhfs - library for reading and writing Macintosh HFS volumes + * Copyright (C) 1996-1998 Robert Leslie + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * $Id: volume.c,v 1.12 1998/11/02 22:09:10 rob Exp $ + */ + +#include "config.h" +#include "libhfs.h" +#include "volume.h" +#include "data.h" +#include "block.h" +#include "low.h" +#include "medium.h" +#include "file.h" +#include "btree.h" +#include "record.h" +#include "os.h" + +#include "libc/byteorder.h" + +/* + * NAME: vol->init() + * DESCRIPTION: initialize volume structure + */ +void v_init(hfsvol *vol, int flags) +{ + btree *ext = &vol->ext; + btree *cat = &vol->cat; + + vol->os_fd = 0; + vol->flags = flags & HFS_VOL_OPT_MASK; + + vol->pnum = -1; + vol->vstart = 0; + vol->vlen = 0; + vol->lpa = 0; + + vol->cache = NULL; + + vol->vbm = NULL; + vol->vbmsz = 0; + + f_init(&ext->f, vol, HFS_CNID_EXT, "extents overflow"); + + ext->map = NULL; + ext->mapsz = 0; + ext->flags = 0; + + ext->keyunpack = (keyunpackfunc) r_unpackextkey; + ext->keycompare = (keycomparefunc) r_compareextkeys; + + f_init(&cat->f, vol, HFS_CNID_CAT, "catalog"); + + cat->map = NULL; + cat->mapsz = 0; + cat->flags = 0; + + cat->keyunpack = (keyunpackfunc) r_unpackcatkey; + cat->keycompare = (keycomparefunc) r_comparecatkeys; + + vol->cwd = HFS_CNID_ROOTDIR; + + vol->refs = 0; + vol->files = NULL; + vol->dirs = NULL; + + vol->prev = NULL; + vol->next = NULL; +} + +/* + * NAME: vol->open() + * DESCRIPTION: open volume source and lock against concurrent updates + */ +int v_open(hfsvol *vol, int os_fd ) +{ + if (vol->flags & HFS_VOL_OPEN) + ERROR(EINVAL, "volume already open"); + + vol->flags |= HFS_VOL_OPEN; + vol->os_fd = os_fd; + + /* initialize volume block cache (OK to fail) */ + + if (! (vol->flags & HFS_OPT_NOCACHE) && + b_init(vol) != -1) + vol->flags |= HFS_VOL_USINGCACHE; + + return 0; + +fail: + return -1; +} + +/* + * NAME: vol->close() + * DESCRIPTION: close access path to volume source + */ +int v_close(hfsvol *vol) +{ + int result = 0; + + if (! (vol->flags & HFS_VOL_OPEN)) + goto done; + + if ((vol->flags & HFS_VOL_USINGCACHE) && + b_finish(vol) == -1) + result = -1; + + vol->flags &= ~(HFS_VOL_OPEN | HFS_VOL_MOUNTED | HFS_VOL_USINGCACHE); + + /* free dynamically allocated structures */ + + FREE(vol->vbm); + + vol->vbm = NULL; + vol->vbmsz = 0; + + FREE(vol->ext.map); + FREE(vol->cat.map); + + vol->ext.map = NULL; + vol->cat.map = NULL; + +done: + return result; +} + +/* + * NAME: vol->same() + * DESCRIPTION: return 1 iff path is same as open volume + */ +int v_same(hfsvol *vol, int os_fd ) +{ + return vol->os_fd == os_fd; +} + +/* + * NAME: vol->geometry() + * DESCRIPTION: determine volume location and size (possibly in a partition) + */ +int v_geometry(hfsvol *vol, int pnum) +{ + Partition map; + unsigned long bnum = 0; + int found; + + vol->pnum = pnum; + + if (pnum == 0) + { + vol->vstart = 0; + vol->vlen = b_size(vol); + + if (vol->vlen == 0) + goto fail; + } + else + { + while (pnum--) + { + found = m_findpmentry(vol, "Apple_HFS", &map, &bnum); + if (found == -1 || ! found) + goto fail; + } + + vol->vstart = map.pmPyPartStart; + vol->vlen = map.pmPartBlkCnt; + + if (map.pmDataCnt) + { + if ((unsigned long) map.pmLgDataStart + + (unsigned long) map.pmDataCnt > vol->vlen) + ERROR(EINVAL, "partition data overflows partition"); + + vol->vstart += (unsigned long) map.pmLgDataStart; + vol->vlen = map.pmDataCnt; + } + + if (vol->vlen == 0) + ERROR(EINVAL, "volume partition is empty"); + } + + if (vol->vlen < 800 * (1024 >> HFS_BLOCKSZ_BITS)) + ERROR(EINVAL, "volume is smaller than 800K"); + + return 0; + +fail: + return -1; +} + +/* + * NAME: vol->readmdb() + * DESCRIPTION: load Master Directory Block into memory + */ +int v_readmdb(hfsvol *vol) +{ + if (l_getmdb(vol, &vol->mdb, 0) == -1) + goto fail; + + if (vol->mdb.drSigWord != HFS_SIGWORD) + { + if (vol->mdb.drSigWord == HFS_SIGWORD_MFS) + ERROR(EINVAL, "MFS volume format not supported"); + else + ERROR(EINVAL, "not a Macintosh HFS volume"); + } + + if (vol->mdb.drAlBlkSiz % HFS_BLOCKSZ != 0) + ERROR(EINVAL, "bad volume allocation block size"); + + vol->lpa = vol->mdb.drAlBlkSiz >> HFS_BLOCKSZ_BITS; + + /* extents pseudo-file structs */ + + vol->ext.f.cat.u.fil.filStBlk = vol->mdb.drXTExtRec[0].xdrStABN; + vol->ext.f.cat.u.fil.filLgLen = vol->mdb.drXTFlSize; + vol->ext.f.cat.u.fil.filPyLen = vol->mdb.drXTFlSize; + + vol->ext.f.cat.u.fil.filCrDat = vol->mdb.drCrDate; + vol->ext.f.cat.u.fil.filMdDat = vol->mdb.drLsMod; + + memcpy(&vol->ext.f.cat.u.fil.filExtRec, + &vol->mdb.drXTExtRec, sizeof(ExtDataRec)); + + f_selectfork(&vol->ext.f, fkData); + + /* catalog pseudo-file structs */ + + vol->cat.f.cat.u.fil.filStBlk = vol->mdb.drCTExtRec[0].xdrStABN; + vol->cat.f.cat.u.fil.filLgLen = vol->mdb.drCTFlSize; + vol->cat.f.cat.u.fil.filPyLen = vol->mdb.drCTFlSize; + + vol->cat.f.cat.u.fil.filCrDat = vol->mdb.drCrDate; + vol->cat.f.cat.u.fil.filMdDat = vol->mdb.drLsMod; + + memcpy(&vol->cat.f.cat.u.fil.filExtRec, + &vol->mdb.drCTExtRec, sizeof(ExtDataRec)); + + f_selectfork(&vol->cat.f, fkData); + + return 0; + +fail: + return -1; +} + +/* + * NAME: vol->readvbm() + * DESCRIPTION: read volume bitmap into memory + */ +int v_readvbm(hfsvol *vol) +{ + unsigned int vbmst = vol->mdb.drVBMSt; + unsigned int vbmsz = (vol->mdb.drNmAlBlks + 0x0fff) >> 12; + block *bp; + + ASSERT(vol->vbm == 0); + + if (vol->mdb.drAlBlSt - vbmst < vbmsz) + ERROR(EIO, "volume bitmap collides with volume data"); + + vol->vbm = ALLOC(block, vbmsz); + if (vol->vbm == NULL) + ERROR(ENOMEM, NULL); + + vol->vbmsz = vbmsz; + + for (bp = vol->vbm; vbmsz--; ++bp) + { + if (b_readlb(vol, vbmst++, bp) == -1) + goto fail; + } + + return 0; + +fail: + FREE(vol->vbm); + + vol->vbm = NULL; + vol->vbmsz = 0; + + return -1; +} + +/* + * NAME: vol->mount() + * DESCRIPTION: load volume information into memory + */ +int v_mount(hfsvol *vol) +{ + /* read the MDB, volume bitmap, and extents/catalog B*-tree headers */ + + if (v_readmdb(vol) == -1 || + v_readvbm(vol) == -1 || + bt_readhdr(&vol->ext) == -1 || + bt_readhdr(&vol->cat) == -1) + goto fail; + + if (vol->mdb.drAtrb & HFS_ATRB_SLOCKED) + vol->flags |= HFS_VOL_READONLY; + else if (vol->flags & HFS_VOL_READONLY) + vol->mdb.drAtrb |= HFS_ATRB_HLOCKED; + else + vol->mdb.drAtrb &= ~HFS_ATRB_HLOCKED; + + vol->flags |= HFS_VOL_MOUNTED; + + return 0; + +fail: + return -1; +} + +/* + * NAME: vol->catsearch() + * DESCRIPTION: search catalog tree + */ +int v_catsearch(hfsvol *vol, unsigned long parid, const char *name, + CatDataRec *data, char *cname, node *np) +{ + CatKeyRec key; + byte pkey[HFS_CATKEYLEN]; + const byte *ptr; + node n; + int found; + + if (np == NULL) + np = &n; + + r_makecatkey(&key, parid, name); + r_packcatkey(&key, pkey, NULL); + + found = bt_search(&vol->cat, pkey, np); + if (found <= 0) + return found; + + ptr = HFS_NODEREC(*np, np->rnum); + + if (cname) + { + r_unpackcatkey(ptr, &key); + strcpy(cname, key.ckrCName); + } + + if (data) + r_unpackcatdata(HFS_RECDATA(ptr), data); + + return 1; +} + +/* + * NAME: vol->extsearch() + * DESCRIPTION: search extents tree + */ +int v_extsearch(hfsfile *file, unsigned int fabn, + ExtDataRec *data, node *np) +{ + ExtKeyRec key; + ExtDataRec extsave; + unsigned int fabnsave; + byte pkey[HFS_EXTKEYLEN]; + const byte *ptr; + node n; + int found; + + if (np == NULL) + np = &n; + + r_makeextkey(&key, file->fork, file->cat.u.fil.filFlNum, fabn); + r_packextkey(&key, pkey, NULL); + + /* in case bt_search() clobbers these */ + + memcpy(&extsave, &file->ext, sizeof(ExtDataRec)); + fabnsave = file->fabn; + + found = bt_search(&file->vol->ext, pkey, np); + + memcpy(&file->ext, &extsave, sizeof(ExtDataRec)); + file->fabn = fabnsave; + + if (found <= 0) + return found; + + if (data) + { + ptr = HFS_NODEREC(*np, np->rnum); + r_unpackextdata(HFS_RECDATA(ptr), data); + } + + return 1; +} + +/* + * NAME: vol->getthread() + * DESCRIPTION: retrieve catalog thread information for a file or directory + */ +int v_getthread(hfsvol *vol, unsigned long id, + CatDataRec *thread, node *np, int type) +{ + CatDataRec rec; + int found; + + if (thread == NULL) + thread = &rec; + + found = v_catsearch(vol, id, "", thread, NULL, np); + if (found == 1 && thread->cdrType != type) + ERROR(EIO, "bad thread record"); + + return found; + +fail: + return -1; +} + + +/* + * NAME: vol->resolve() + * DESCRIPTION: translate a pathname; return catalog information + */ +int v_resolve(hfsvol **vol, const char *path, + CatDataRec *data, unsigned long *parid, char *fname, node *np) +{ + unsigned long dirid; + char name[HFS_MAX_FLEN + 1], *nptr; + int found = 0; + + if (*path == 0) + ERROR(ENOENT, "empty path"); + + if (parid) + *parid = 0; + + nptr = strchr(path, ':'); + + if (*path == ':' || nptr == NULL) + { + dirid = (*vol)->cwd; /* relative path */ + + if (*path == ':') + ++path; + + if (*path == 0) + { + found = v_getdthread(*vol, dirid, data, NULL); + if (found == -1) + goto fail; + + if (found) + { + if (parid) + *parid = data->u.dthd.thdParID; + + found = v_catsearch(*vol, data->u.dthd.thdParID, + data->u.dthd.thdCName, data, fname, np); + if (found == -1) + goto fail; + } + + goto done; + } + } + else + { + hfsvol *check; + + dirid = HFS_CNID_ROOTPAR; /* absolute path */ + + if (nptr - path > HFS_MAX_VLEN) + ERROR(ENAMETOOLONG, NULL); + + strncpy(name, path, nptr - path); + name[nptr - path] = 0; + + for (check = hfs_mounts; check; check = check->next) + { + if (d_relstring(check->mdb.drVN, name) == 0) + { + *vol = check; + break; + } + } + } + + while (1) + { + while (*path == ':') + { + ++path; + + found = v_getdthread(*vol, dirid, data, NULL); + if (found == -1) + goto fail; + else if (! found) + goto done; + + dirid = data->u.dthd.thdParID; + } + + if (*path == 0) + { + found = v_getdthread(*vol, dirid, data, NULL); + if (found == -1) + goto fail; + + if (found) + { + if (parid) + *parid = data->u.dthd.thdParID; + + found = v_catsearch(*vol, data->u.dthd.thdParID, + data->u.dthd.thdCName, data, fname, np); + if (found == -1) + goto fail; + } + + goto done; + } + + nptr = name; + while (nptr < name + sizeof(name) - 1 && *path && *path != ':') + *nptr++ = *path++; + + if (*path && *path != ':') + ERROR(ENAMETOOLONG, NULL); + + *nptr = 0; + if (*path == ':') + ++path; + + if (parid) + *parid = dirid; + + found = v_catsearch(*vol, dirid, name, data, fname, np); + if (found == -1) + goto fail; + + if (! found) + { + if (*path && parid) + *parid = 0; + + if (*path == 0 && fname) + strcpy(fname, name); + + goto done; + } + + switch (data->cdrType) + { + case cdrDirRec: + if (*path == 0) + goto done; + + dirid = data->u.dir.dirDirID; + break; + + case cdrFilRec: + if (*path == 0) + goto done; + + ERROR(ENOTDIR, "invalid pathname"); + + default: + ERROR(EIO, "unexpected catalog record"); + } + } + +done: + return found; + +fail: + return -1; +} + +/* Determine whether the volume is a HFS volume */ +int +v_probe(int fd, long long offset) +{ + MDB *mdb; + + mdb = (MDB*)malloc(2 * 512); + os_seek_offset( fd, 2 * 512 + offset ); + os_read(fd, mdb, 2, 9); + + if (__be16_to_cpu(mdb->drSigWord) != HFS_SIGWORD) { + free(mdb); + return 0; + } + + free(mdb); + return -1; +} diff --git a/qemu/roms/openbios/fs/hfs_mdb.h b/qemu/roms/openbios/fs/hfs_mdb.h new file mode 100644 index 000000000..652525d96 --- /dev/null +++ b/qemu/roms/openbios/fs/hfs_mdb.h @@ -0,0 +1,118 @@ +/* + * Creation Date: <2000/09/03 23:04:27 samuel> + * Time-stamp: <2000/09/04 01:23:55 samuel> + * + * <hfs_mdb.h> + * + * HFS Master Directory Block (MDB) + * + * 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 + * + */ + +#ifndef _H_HFS_MDB +#define _H_HFS_MDB + +#include "libc/byteorder.h" + +typedef unsigned char hfs_char_t; +typedef unsigned char hfs_ushort_t[2]; +typedef unsigned char hfs_uint_t[4]; + +static inline unsigned short hfs_get_ushort(hfs_ushort_t addr) +{ + return __be16_to_cpu(*((unsigned short *)(addr))); +} + +static inline unsigned int hfs_get_uint(hfs_uint_t addr) +{ + return __be32_to_cpu(*((unsigned int *)(addr))); +} + +/* + * The HFS Master Directory Block (MDB). + * + * Also known as the Volume Information Block (VIB), this structure is + * the HFS equivalent of a superblock. + * + * Reference: _Inside Macintosh: Files_ pages 2-59 through 2-62 + * + * modified for HFS Extended + */ + +typedef struct hfs_mdb { + hfs_ushort_t drSigWord; /* Signature word indicating fs type */ + hfs_uint_t drCrDate; /* fs creation date/time */ + hfs_uint_t drLsMod; /* fs modification date/time */ + hfs_ushort_t drAtrb; /* fs attributes */ + hfs_ushort_t drNmFls; /* number of files in root directory */ + hfs_ushort_t drVBMSt; /* location (in 512-byte blocks) + of the volume bitmap */ + hfs_ushort_t drAllocPtr; /* location (in allocation blocks) + to begin next allocation search */ + hfs_ushort_t drNmAlBlks; /* number of allocation blocks */ + hfs_uint_t drAlBlkSiz; /* bytes in an allocation block */ + hfs_uint_t drClpSiz; /* clumpsize, the number of bytes to + allocate when extending a file */ + hfs_ushort_t drAlBlSt; /* location (in 512-byte blocks) + of the first allocation block */ + hfs_uint_t drNxtCNID; /* CNID to assign to the next + file or directory created */ + hfs_ushort_t drFreeBks; /* number of free allocation blocks */ + hfs_char_t drVN[28]; /* the volume label */ + hfs_uint_t drVolBkUp; /* fs backup date/time */ + hfs_ushort_t drVSeqNum; /* backup sequence number */ + hfs_uint_t drWrCnt; /* fs write count */ + hfs_uint_t drXTClpSiz; /* clumpsize for the extents B-tree */ + hfs_uint_t drCTClpSiz; /* clumpsize for the catalog B-tree */ + hfs_ushort_t drNmRtDirs; /* number of directories in + the root directory */ + hfs_uint_t drFilCnt; /* number of files in the fs */ + hfs_uint_t drDirCnt; /* number of directories in the fs */ + hfs_char_t drFndrInfo[32]; /* data used by the Finder */ + hfs_ushort_t drEmbedSigWord; /* embedded volume signature */ + hfs_uint_t drEmbedExtent; /* starting block number (xdrStABN) + and number of allocation blocks + (xdrNumABlks) occupied by embedded + volume */ + hfs_uint_t drXTFlSize; /* bytes in the extents B-tree */ + hfs_char_t drXTExtRec[12]; /* extents B-tree's first 3 extents */ + hfs_uint_t drCTFlSize; /* bytes in the catalog B-tree */ + hfs_char_t drCTExtRec[12]; /* catalog B-tree's first 3 extents */ +} hfs_mdb_t; + +#define HFS_PLUS_SIGNATURE 0x482b /* 'H+' */ +#define HFS_SIGNATURE 0x4244 /* HFS / embedded HFS+ */ + + +typedef struct hfs_plus_mdb +{ + unsigned short signature; + unsigned short version; + unsigned int attributes; + unsigned int lastMountedVersion; + unsigned int reserved; + + unsigned int createDate; + unsigned int modifyDate; + unsigned int backupDate; + unsigned int checkedDate; + + unsigned int fileCount; + unsigned int folderCount; + + unsigned int blockSize; + unsigned int totalBlocks; + unsigned int freeBlocks; + + unsigned int nextAllocation; + unsigned int rsrcClumpSize; + unsigned int dataClumpSize; + + /* ... there are more fields here ... */ +} hfs_plus_mdb_t; + + +#endif /* _H_HFS_MDB */ diff --git a/qemu/roms/openbios/fs/hfsplus/build.xml b/qemu/roms/openbios/fs/hfsplus/build.xml new file mode 100644 index 000000000..5f4c28869 --- /dev/null +++ b/qemu/roms/openbios/fs/hfsplus/build.xml @@ -0,0 +1,11 @@ +<build> + <library name="fs" type="static" target="target"> + <object source="hfsp_blockiter.c" flags="-I$(SRCDIR)/fs/hfsplus/include -I$(SRCDIR)/fs/ -fno-strict-aliasing" condition="HFSP"/> + <object source="hfsp_btree.c" flags="-I$(SRCDIR)/fs/hfsplus/include -I$(SRCDIR)/fs/ -fno-strict-aliasing" condition="HFSP"/> + <object source="libhfsp.c" flags="-I$(SRCDIR)/fs/hfsplus/include -I$(SRCDIR)/fs/ -fno-strict-aliasing" condition="HFSP"/> + <object source="hfsp_record.c" flags="-I$(SRCDIR)/fs/hfsplus/include -I$(SRCDIR)/fs/ -fno-strict-aliasing" condition="HFSP"/> + <object source="hfsp_unicode.c" flags="-I$(SRCDIR)/fs/hfsplus/include -I$(SRCDIR)/fs/ -fno-strict-aliasing" condition="HFSP"/> + <object source="hfsp_volume.c" flags="-I$(SRCDIR)/fs/hfsplus/include -I$(SRCDIR)/fs/ -fno-strict-aliasing" condition="HFSP"/> + <object source="hfsp_fs.c" flags="-I$(SRCDIR)/fs/hfsplus/include -I$(SRCDIR)/fs/ -fno-strict-aliasing" condition="HFSP"/> + </library> +</build> diff --git a/qemu/roms/openbios/fs/hfsplus/hfsp_blockiter.c b/qemu/roms/openbios/fs/hfsplus/hfsp_blockiter.c new file mode 100644 index 000000000..e91009229 --- /dev/null +++ b/qemu/roms/openbios/fs/hfsplus/hfsp_blockiter.c @@ -0,0 +1,141 @@ +/* + * libhfs - library for reading and writing Macintosh HFS volumes + * + * The iterator shown here iterates over the blocks of a fork. + * + * Copyright (C) 2000 Klaus Halfmann <khalfmann@libra.de> + * Original work by 1996-1998 Robert Leslie <rob@mars.org> + * other work 2000 from Brad Boyer (flar@pants.nu) + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * $Id: blockiter.c,v 1.2 2000/10/17 05:58:46 hasi Exp $ + */ + +#include "config.h" +#include "libhfsp.h" +#include "blockiter.h" +#include "volume.h" +#include "record.h" +#include "btree.h" +#include "os.h" +#include "swab.h" +#include "hfstime.h" + +/* Initialize iterator for a given fork */ +void +blockiter_init(blockiter* b, volume* vol, hfsp_fork_raw* f, + UInt8 forktype, UInt32 fileId) +{ + b->vol = vol; + b->curr_block = 0; + b->block = 0; + b->max_block = f->total_blocks; + b->fileId = fileId; + b->index = 0; + b->file = f->extents; + b->e = f->extents; + b->forktype = forktype; + b->in_extent = 0; +} + +/* get next extent record when needed */ +static int +blockiter_next_extent(blockiter *b) +{ + btree* extents_tree = volume_get_extents_tree(b->vol); + int err; + + b->index = 0; + if (b->in_extent) // already using extents record ? + { + err = record_next_extent(&b->er); + // Hope there is no need to check this ... + // if (b->er.key.start_block != b->curr_block) + // HFSP_ERROR(ENOENT, + // "Extents record inconistent"); + } + else + { + err = record_init_file(&b->er, extents_tree, b->forktype, + b->fileId, b->curr_block); + b->in_extent = -1; // true + } + b->e = b->er.extent; + return err; +} + +/* find next block of the fork iterating over */ +int +blockiter_next(blockiter *b) +{ + b->curr_block ++; + b->block ++; + if (b->curr_block >= b->max_block) + return -1; // end of Blocks, but no error + // in current part of extent ? + if (b->block >= b->e->block_count) + { + b->index++; + b->block = 0; // reset relative position + b->e++; + if (b -> index >= 8) // need to fetch another extent + { + if (blockiter_next_extent(b)) + HFSP_ERROR(ENOENT, "Extends record not found."); + } + } + return 0; + + fail: + return -1; +} + +/* skip the indicated number of blocks */ +int +blockiter_skip(blockiter *b, UInt32 skip) +{ + while (skip > 0) + { + // Skip to skip or end of current extent + UInt32 diff = b->e->block_count - b->block; + if (skip < diff) + { + diff = skip; + skip = 0; + } + else + skip -= diff; + b->curr_block += diff; + b->block += diff; + if (b->curr_block >= b->max_block) + return -1; // end of Blocks, but no error + if (b->block >= b->e->block_count) + { + b->index++; + b->block = 0; // reset relative position + b->e++; + if (b -> index >= 8) // need to fetch another extent + { + if (blockiter_next_extent(b)) + HFSP_ERROR(ENOENT, "Extends record not found."); + } + } + } // we are here when skip was null, thats ok + return 0; + fail: + return -1; +} diff --git a/qemu/roms/openbios/fs/hfsplus/hfsp_btree.c b/qemu/roms/openbios/fs/hfsplus/hfsp_btree.c new file mode 100644 index 000000000..24eca924c --- /dev/null +++ b/qemu/roms/openbios/fs/hfsplus/hfsp_btree.c @@ -0,0 +1,372 @@ +/* + * libhfs - library for reading and writing Macintosh HFS volumes + * The fucntions are used to handle the various forms of btrees + * found on HFS+ volumes. + * + * The fucntions are used to handle the various forms of btrees + * found on HFS+ volumes. + * + * Copyright (C) 2000 Klaus Halfmann <khalfmann@libra.de> + * Original 1996-1998 Robert Leslie <rob@mars.org> + * Additional work by Brad Boyer (flar@pants.nu) + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * $Id: btree.c,v 1.14 2000/10/25 05:43:04 hasi Exp $ + */ + +#include "config.h" +#include "libhfsp.h" +#include "volume.h" +#include "btree.h" +#include "record.h" +#include "swab.h" + +/* Read the node from the given buffer and swap the bytes. + * + * return pointer after reading the structure + */ +static void* btree_readnode(btree_node_desc* node, void *p) +{ + node->next = bswabU32_inc(p); + node->prev = bswabU32_inc(p); + node->kind = bswabU8_inc(p); + node->height = bswabU8_inc(p); + node->num_rec = bswabU16_inc(p); + node->reserved = bswabU16_inc(p); + return p; +} + +/* read a btree header from the given buffer and swap the bytes. + * + * return pointer after reading the structure + */ +static void* btree_readhead(btree_head* head, void *p) +{ + UInt32 *q; + head->depth = bswabU16_inc(p); + head->root = bswabU32_inc(p); + head->leaf_count = bswabU32_inc(p); + head->leaf_head = bswabU32_inc(p); + head->leaf_tail = bswabU32_inc(p); + head->node_size = bswabU16_inc(p); + head->max_key_len = bswabU16_inc(p); + head->node_count = bswabU32_inc(p); + head->free_nodes = bswabU32_inc(p); + head->reserved1 = bswabU16_inc(p); + head->clump_size = bswabU32_inc(p); + head->btree_type = bswabU8_inc(p); + head->reserved2 = bswabU8_inc(p); + head->attributes = bswabU32_inc(p); + // skip reserved bytes + q=((UInt32*) p); + // ((UInt32*) p) += 16; + q+=16; + return q; +} + +/* Priority of the depth of the node compared to LRU value. + * Should be the average number of keys per node but these vary. */ +#define DEPTH_FACTOR 1000 + +/* Cache size is height of tree + this value + * Really big numbers wont help in case of ls -R + */ +#define EXTRA_CACHESIZE 3 + +/* Not in use by now ... */ +#define CACHE_DIRTY 0x0001 + +/* Intialize cache with default cache Size, + * must call node_cache_close to deallocate memory */ +static int node_cache_init(node_cache* cache, btree* tree, int size) +{ + int nodebufsize; + char * buf; + + cache->size = size; + cache->currindex = 0; + nodebufsize = tree->head.node_size + sizeof(node_buf); + buf = malloc(size *(sizeof(node_entry) + nodebufsize)); + if (!buf) + return -1; + cache -> nodebufsize = nodebufsize; + cache -> entries = (node_entry*) buf; + cache -> buffers = (char*) &cache->entries[size]; + bzero(cache->entries, size*sizeof(node_entry)); + return 0; +} + +/* Like cache->buffers[i], since size of node_buf is variable */ +static inline node_buf* node_buf_get(node_cache* cache, int i) +{ + return (node_buf*) (cache->buffers + (i * cache->nodebufsize)); +} + +/* flush the node at index */ +static void node_cache_flush_node(node_cache* cache, int index) +{ + // NYI + cache -> entries[index].index = 0; // invalidate entry +} + +static void node_cache_close(node_cache* cache) +{ + if (!cache->entries) // not (fully) intialized ? + return; + free(cache->entries); +} + +/* Load the cach node indentified by index with + * the node identified by node_index */ + +static node_buf* node_cache_load_buf + (btree* bt, node_cache* cache, int index, UInt16 node_index) +{ + node_buf *result = node_buf_get(cache ,index); + UInt32 blkpernode = bt->blkpernode; + UInt32 block = node_index * blkpernode; + void* p = volume_readfromfork(bt->vol, result->node, bt->fork, + block, blkpernode, HFSP_EXTENT_DATA, bt->cnid); + node_entry *e = &cache->entries[index]; + + if (!p) + return NULL; // evil ... + + result->index = node_index; + btree_readnode(&result->desc, p); + + e -> priority = result->desc.height * DEPTH_FACTOR; + e -> index = node_index; + return result; +} + +/* Read node at given index, using cache. + */ +node_buf* btree_node_by_index(btree* bt, UInt16 index) +{ + node_cache* cache = &bt->cache; + int oldindex, lruindex; + int currindex = cache->currindex; + UInt32 prio; + node_entry *e; + + // Shortcut acces to current node, will not change priorities + if (cache->entries[currindex].index == index) + return node_buf_get(cache ,currindex); + oldindex = currindex; + if (currindex == 0) + currindex = cache->size; + currindex--; + lruindex = oldindex; // entry to be flushed when needed + prio = 0; // current priority + while (currindex != oldindex) // round robin + { + e = &cache->entries[currindex]; + if (e->index == index) // got it + { + if (e->priority != 0) // already top, uuh + e->priority--; + cache->currindex = currindex; + return node_buf_get(cache ,currindex); + } + else + { + if (!e->index) + { + lruindex = currindex; + break; // empty entry, load it + } + if (e->priority != UINT_MAX) // already least, uuh + e->priority++; + } + if (prio < e->priority) + { + lruindex = currindex; + prio = e->priority; + } + if (currindex == 0) + currindex = cache->size; + currindex--; + } + e = &cache->entries[lruindex]; + cache->currindex = lruindex; + if (e->flags & CACHE_DIRTY) + node_cache_flush_node( cache, lruindex); + return node_cache_load_buf (bt, cache, lruindex, index); +} + +/** intialize the btree with the first entry in the fork */ +static int btree_init(btree* bt, volume* vol, hfsp_fork_raw* fork) +{ + void *p; + char buf[vol->blksize]; + UInt16 node_size; + btree_node_desc node; + + bt->vol = vol; + bt->fork = fork; + p = volume_readfromfork(vol, buf, fork, 0, 1, + HFSP_EXTENT_DATA, bt->cnid); + if (!p) + return -1; + p = btree_readnode(&node, p); + if (node.kind != HFSP_NODE_HEAD) + return -1; // should not happen ? + btree_readhead(&bt->head, p); + + node_size = bt->head.node_size; + bt->blkpernode = node_size / vol->blksize; + + if (bt->blkpernode == 0 || vol->blksize * + bt->blkpernode != node_size) + return -1; // should never happen ... + + node_cache_init(&bt->cache, bt, bt->head.depth + EXTRA_CACHESIZE); + + // Allocate buffer + // bt->buf = malloc(node_size); + // if (!bt->buf) + // return ENOMEM; + + return 0; +} + +/** Intialize catalog btree, so that btree_close can safely be called. */ +void btree_reset(btree* bt) +{ + bt->cache.entries = NULL; +} + +/** Intialize catalog btree */ +int btree_init_cat(btree* bt, volume* vol, hfsp_fork_raw* fork) +{ + int result = btree_init(bt,vol,fork); // super (...) + bt->cnid = HFSP_CAT_CNID; + bt->kcomp = record_key_compare; + bt->kread = record_readkey; + return result; +} + +/** Intialize catalog btree */ +int btree_init_extent(btree* bt, volume* vol, hfsp_fork_raw* fork) +{ + int result = btree_init(bt,vol,fork); // super (...) + bt->cnid = HFSP_EXT_CNID; + bt->kcomp = record_extent_key_compare; + bt->kread = record_extent_readkey; + return result; +} + +/** close the btree and free any resources */ +void btree_close(btree* bt) +{ + node_cache_close(&bt->cache); + // free(bt->buf); +} + +/* returns pointer to key given by index in current node. + * + * Assumes that current node is not NODE_HEAD ... + */ +void* btree_key_by_index(btree* bt, node_buf* buf, UInt16 index) +{ + UInt16 node_size = bt->head.node_size; + // The offsets are found at the end of the node ... + UInt16 off_pos = node_size - (index +1) * sizeof(btree_record_offset); + // position of offset at end of node + btree_record_offset* offset = + (btree_record_offset*) (buf->node + off_pos); + + // now we have the offset and can read the key ... +#ifdef CONFIG_LITTLE_ENDIAN + return buf->node + bswabU16(*offset); +#else + return buf->node + *offset; +#endif +} + + +#ifdef DEBUG + +/* print btree header node information */ +void btree_printhead(btree_head* head) +{ + UInt32 attr; + printf(" depth : %#X\n", head->depth); + printf(" root : %#lX\n", head->root); + printf(" leaf_count : %#lX\n", head->leaf_count); + printf(" leaf_head : %#lX\n", head->leaf_head); + printf(" leaf_tail : %#lX\n", head->leaf_tail); + printf(" node_size : %#X\n", head->node_size); + printf(" max_key_len : %#X\n", head->max_key_len); + printf(" node_count : %#lX\n", head->node_count); + printf(" free_nodes : %#lX\n", head->free_nodes); + printf(" reserved1 : %#X\n", head->reserved1); + printf(" clump_size : %#lX\n", head->clump_size); + printf(" btree_type : %#X\n", head->btree_type); + attr = head->attributes; + printf(" reserved2 : %#X\n", head->reserved2); + if (attr & HFSPLUS_BAD_CLOSE) + printf(" HFSPLUS_BAD_CLOSE *** "); + else + printf(" !HFSPLUS_BAD_CLOSE"); + if (attr & HFSPLUS_TREE_BIGKEYS) + printf(" HFSPLUS_TREE_BIGKEYS "); + else + printf(" !HFSPLUS_TREE_BIGKEYS"); + if (attr & HFSPLUS_TREE_VAR_NDXKEY_SIZE) + printf(" HFSPLUS_TREE_VAR_NDXKEY_SIZE"); + else + printf(" !HFSPLUS_TREE_VAR_NDXKEY_SIZE"); + if (attr & HFSPLUS_TREE_UNUSED) + printf(" HFSPLUS_TREE_UNUSED ***\n"); + printf("\n"); +} + +/* Dump all the node information to stdout */ +void btree_print(btree* bt) +{ + btree_node_desc* node; + + btree_printhead(&bt->head); + + node = &bt->node; + printf("next : %#lX\n", node->next); + printf("prev : %#lX\n", node->prev); + printf("height : %#X\n", node->height); + printf("num_rec : %#X\n", node->num_rec); + printf("reserved : %#X\n", node->reserved); + printf("height : %#X\n", node->height); switch(node->kind) + { + case HFSP_NODE_NDX : + printf("HFSP_NODE_NDX\n"); + break; + case HFSP_NODE_HEAD : + printf("HFSP_NODE_HEAD\n"); + break; + case HFSP_NODE_MAP : + printf("HFSP_NODE_MAP\n"); + break; + case HFSP_NODE_LEAF : + printf("HFSP_NODE_LEAF\n"); + break; + default: + printf("*** Unknown Node type ***\n"); + } +} + +#endif diff --git a/qemu/roms/openbios/fs/hfsplus/hfsp_fs.c b/qemu/roms/openbios/fs/hfsplus/hfsp_fs.c new file mode 100644 index 000000000..df234bb04 --- /dev/null +++ b/qemu/roms/openbios/fs/hfsplus/hfsp_fs.c @@ -0,0 +1,632 @@ +/* + * Creation Date: <2001/05/05 23:33:49 samuel> + * Time-stamp: <2004/01/12 10:25:39 samuel> + * + * /package/hfsplus-files + * + * HFS+ file system interface (and ROM lookup support) + * + * Copyright (C) 2001, 2002, 2003, 2004 Samuel Rydh (samuel@ibrium.se) + * Copyright (C) 2010 Mark Cave-Ayland (mark.cave-ayland@siriusit.co.uk) + * + * 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 + * + */ + +#include "config.h" +#include "libopenbios/bindings.h" +#include "fs/fs.h" +#include "libhfsp.h" +#include "volume.h" +#include "record.h" +#include "unicode.h" +#include "blockiter.h" +#include "libc/diskio.h" +#include "libc/vsprintf.h" + +#define MAC_OS_ROM_CREATOR 0x63687270 /* 'chrp' */ +#define MAC_OS_ROM_TYPE 0x74627869 /* 'tbxi' */ +#define MAC_OS_ROM_NAME "Mac OS ROM" + +#define FINDER_TYPE 0x464E4452 /* 'FNDR' */ +#define FINDER_CREATOR 0x4D414353 /* 'MACS' */ +#define SYSTEM_TYPE 0x7A737973 /* 'zsys' */ +#define SYSTEM_CREATOR 0x4D414353 /* 'MACS' */ + +#define VOLNAME_SIZE 64 + +extern void hfsp_init( void ); + +typedef struct { + record rec; + char *path; + off_t pos; +} hfsp_file_t; + +typedef struct { + volume *vol; + hfsp_file_t *hfspfile; +} hfsp_info_t; + +DECLARE_NODE( hfsp, 0, sizeof(hfsp_info_t), "+/packages/hfsplus-files" ); + + +/************************************************************************/ +/* Search implementation */ +/************************************************************************/ + +typedef int (*match_proc_t)( record *r, record *parent, const void *match_data, hfsp_file_t *pt ); + +static int +search_files( record *par, int recursive, match_proc_t proc, const void *match_data, hfsp_file_t *pt ) +{ + hfsp_file_t t; + record r; + int ret = 1; + + t.path = NULL; + + record_init_parent( &r, par ); + do{ + if( r.record.type == HFSP_FOLDER || r.record.type == HFSP_FILE ) + ret = (*proc)( &r, par, match_data, &t ); + + if( ret && r.record.type == HFSP_FOLDER && recursive ) + ret = search_files( &r, 1, proc, match_data, &t ); + + } while( ret && !record_next(&r) ); + + if( !ret && pt ) { + char name[256]; + const char *s2 = t.path ? t.path : ""; + + unicode_uni2asc( name, &r.key.name, sizeof(name)); + + pt->rec = t.rec; + pt->path = malloc( strlen(name) + strlen(s2) + 2 ); + strcpy( pt->path, name ); + if( strlen(s2) ) { + strcat( pt->path, "\\" ); + strcat( pt->path, s2 ); + } + } + + if( t.path ) + free( t.path ); + + return ret; +} + +static int +root_search_files( volume *vol, int recursive, match_proc_t proc, const void *match_data, hfsp_file_t *pt ) +{ + record r; + + record_init_root( &r, &vol->catalog ); + return search_files( &r, recursive, proc, match_data, pt ); +} + +static int +match_file( record *r, record *parent, const void *match_data, hfsp_file_t *pt ) +{ + const char *p = (const char*)match_data; + char name[256]; + int ret=1; + + if( r->record.type != HFSP_FILE ) + return 1; + + (void) unicode_uni2asc(name, &r->key.name, sizeof(name)); + if( !(ret=strcasecmp(p, name)) && pt ) + pt->rec = *r; + + return ret; +} + +static int +match_rom( record *r, record *par, const void *match_data, hfsp_file_t *pt ) +{ + hfsp_cat_file *file = &r->record.u.file; + FInfo *fi = &file->user_info; + int ret = 1; + char buf[256]; + + if( r->record.type == HFSP_FILE && fi->fdCreator == MAC_OS_ROM_CREATOR && fi->fdType == MAC_OS_ROM_TYPE ) { + ret = search_files( par, 0, match_file, "System", NULL ) + || search_files( par, 0, match_file, "Finder", NULL ); + + (void) unicode_uni2asc(buf, &r->key.name, sizeof(buf)); + if( !strcasecmp("BootX", buf) ) + return 1; + + if( !ret && pt ) + pt->rec = *r; + } + return ret; +} + +static int +match_path( record *r, record *par, const void *match_data, hfsp_file_t *pt ) +{ + char name[256], *s, *next, *org; + int ret=1; + + next = org = strdup( (char*)match_data ); + while( (s=strsep( &next, "\\/" )) && !strlen(s) ) + ; + if( !s ) { + free( org ); + return 1; + } + + if( *s == ':' && strlen(s) == 5 ) { + if( r->record.type == HFSP_FILE && !next ) { + /* match type */ + hfsp_cat_file *file = &r->record.u.file; + FInfo *fi = &file->user_info; + int i, type=0; + for( i=1; s[i] && i<=4; i++ ) + type = (type << 8) | s[i]; + /* printk("fi->fdType: %s / %s\n", s+1, b ); */ + if( fi->fdType == type ) { + if( pt ) + pt->rec = *r; + ret = 0; + } + } + } else { + (void) unicode_uni2asc(name, &r->key.name, sizeof(name)); + + if( !strcasecmp(s, name) ) { + if( r->record.type == HFSP_FILE && !next ) { + if( pt ) + pt->rec = *r; + ret = 0; + } else /* must be a directory */ + ret = search_files( r, 0, match_path, next, pt ); + } + } + free( org ); + return ret; +} + + +/************************************************************************/ +/* Standard package methods */ +/************************************************************************/ + +/* ( -- success? ) */ +static void +hfsp_files_open( hfsp_info_t *mi ) +{ + int fd; + char *path = my_args_copy(); + + if ( ! path ) + RET( 0 ); + + fd = open_ih( my_parent() ); + if ( fd == -1 ) { + free( path ); + RET( 0 ); + } + + mi->vol = malloc( sizeof(volume) ); + if (volume_open(mi->vol, fd)) { + free( path ); + close_io( fd ); + RET( 0 ); + } + + mi->hfspfile = malloc( sizeof(hfsp_file_t) ); + + /* Leading \\ means system folder. The finder info block has + * the following meaning. + * + * [0] Prefered boot directory ID + * [3] MacOS 9 boot directory ID + * [5] MacOS X boot directory ID + */ + if( !strncmp(path, "\\\\", 2) ) { + int *p = (int*)&(mi->vol)->vol.finder_info[0]; + int cnid = p[0]; + /* printk(" p[0] = %x, p[3] = %x, p[5] = %x\n", p[0], p[3], p[5] ); */ + if( p[0] == p[5] && p[3] ) + cnid = p[3]; + if( record_init_cnid(&(mi->hfspfile->rec), &(mi->vol)->catalog, cnid) ) + RET ( 0 ); + path += 2; + } else { + record_init_root( &(mi->hfspfile->rec), &(mi->vol)->catalog ); + } + + if( !search_files(&(mi->hfspfile->rec), 0, match_path, path, mi->hfspfile ) ) + RET ( -1 ); + + RET ( -1 ); +} + +/* ( -- ) */ +static void +hfsp_files_close( hfsp_info_t *mi ) +{ + volume_close(mi->vol); + + if( mi->hfspfile->path ) + free( mi->hfspfile->path ); + free( mi->hfspfile ); +} + +/* ( buf len -- actlen ) */ +static void +hfsp_files_read( hfsp_info_t *mi ) +{ + int count = POP(); + char *buf = (char *)cell2pointer(POP()); + + hfsp_file_t *t = mi->hfspfile; + volume *vol = t->rec.tree->vol; + UInt32 blksize = vol->blksize; + hfsp_cat_file *file = &t->rec.record.u.file; + blockiter iter; + char buf2[blksize]; + int act_count, curpos=0; + + blockiter_init( &iter, vol, &file->data_fork, HFSP_EXTENT_DATA, file->id ); + while( curpos + blksize < t->pos ) { + if( blockiter_next( &iter ) ) { + RET ( -1 ); + return; + } + curpos += blksize; + } + act_count = 0; + + while( act_count < count ){ + UInt32 block = blockiter_curr(&iter); + int max = blksize, add = 0, size; + + if( volume_readinbuf( vol, buf2, block ) ) + break; + + if( curpos < t->pos ){ + add += t->pos - curpos; + max -= t->pos - curpos; + } + size = (count-act_count > max)? max : count-act_count; + memcpy( (char *)buf + act_count, &buf2[add], size ); + + curpos += blksize; + act_count += size; + + if( blockiter_next( &iter ) ) + break; + } + + t->pos += act_count; + + RET ( act_count ); +} + +/* ( pos.d -- status ) */ +static void +hfsp_files_seek( hfsp_info_t *mi ) +{ + long long pos = DPOP(); + int offs = (int)pos; + int whence = SEEK_SET; + + hfsp_file_t *t = mi->hfspfile; + hfsp_cat_file *file = &t->rec.record.u.file; + int total = file->data_fork.total_size; + + if( offs == -1 ) { + offs = 0; + whence = SEEK_END; + } + + switch( whence ){ + case SEEK_END: + t->pos = total + offs; + break; + default: + case SEEK_SET: + t->pos = offs; + break; + } + + if( t->pos < 0 ) + t->pos = 0; + + if( t->pos > total ) + t->pos = total; + + RET ( 0 ); +} + +/* ( addr -- size ) */ +static void +hfsp_files_load( hfsp_info_t *mi ) +{ + char *buf = (char *)cell2pointer(POP()); + + hfsp_file_t *t = mi->hfspfile; + volume *vol = t->rec.tree->vol; + UInt32 blksize = vol->blksize; + hfsp_cat_file *file = &t->rec.record.u.file; + int total = file->data_fork.total_size; + blockiter iter; + char buf2[blksize]; + int act_count; + + blockiter_init( &iter, vol, &file->data_fork, HFSP_EXTENT_DATA, file->id ); + + act_count = 0; + + while( act_count < total ){ + UInt32 block = blockiter_curr(&iter); + int max = blksize, size; + + if( volume_readinbuf( vol, buf2, block ) ) + break; + + size = (total-act_count > max)? max : total-act_count; + memcpy( (char *)buf + act_count, &buf2, size ); + + act_count += size; + + if( blockiter_next( &iter ) ) + break; + } + + RET ( act_count ); +} + +/* ( -- cstr ) */ +static void +hfsp_files_get_fstype( hfsp_info_t *mi ) +{ + PUSH( pointer2cell(strdup("HFS+")) ); +} + +/* ( -- cstr ) */ +static void +hfsp_files_get_path( hfsp_info_t *mi ) +{ + char *buf; + hfsp_file_t *t = mi->hfspfile; + + if( !t->path ) + RET ( 0 ); + + buf = malloc(strlen(t->path) + 1); + strncpy( buf, t->path, strlen(t->path) ); + buf[strlen(t->path)] = 0; + + PUSH(pointer2cell(buf)); +} + +/* ( -- success? ) */ +static void +hfsp_files_open_nwrom( hfsp_info_t *mi ) +{ + /* Switch to an existing ROM image file on the fs! */ + if( !root_search_files(mi->vol, 1, match_rom, NULL, mi->hfspfile) ) + RET ( -1 ); + + RET ( 0 ); +} + +/* ( -- cstr|0 ) */ +static void +hfsp_files_volume_name( hfsp_info_t *mi ) +{ + int fd; + char *volname = malloc(VOLNAME_SIZE); + + fd = open_ih(my_self()); + if (fd >= 0) { + get_hfs_vol_name(fd, volname, VOLNAME_SIZE); + close_io(fd); + } else { + volname[0] = '\0'; + } + + PUSH(pointer2cell(volname)); +} + +static const int days_month[12] = + { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; +static const int days_month_leap[12] = + { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + +static inline int is_leap(int year) +{ + return ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0); +} + +static void +print_date(uint32_t sec) +{ + unsigned int second, minute, hour, month, day, year; + int current; + const int *days; + + second = sec % 60; + sec /= 60; + + minute = sec % 60; + sec /= 60; + + hour = sec % 24; + sec /= 24; + + year = sec * 100 / 36525; + sec -= year * 36525 / 100; + year += 1904; + + days = is_leap(year) ? days_month_leap : days_month; + + current = 0; + month = 0; + while (month < 12) { + if (sec <= current + days[month]) { + break; + } + current += days[month]; + month++; + } + month++; + + day = sec - current + 1; + + forth_printf("%d-%02d-%02d %02d:%02d:%02d ", + year, month, day, hour, minute, second); +} + +/* static method, ( pathstr len ihandle -- ) */ +static void +hfsp_files_dir( hfsp_info_t *dummy ) +{ + ihandle_t ih = POP_ih(); + char *path = pop_fstr_copy(); + int fd, found; + volume *vol; + record rec, r, folrec; + char name[256], *curfol, *tmppath; + + fd = open_ih(ih); + if ( fd == -1 ) { + free( path ); + RET( 0 ); + } + + vol = malloc( sizeof(volume) ); + if (volume_open(vol, fd)) { + free( path ); + close_io( fd ); + RET( 0 ); + } + + /* First move to the specified folder */ + tmppath = strdup(path); + record_init_root( &rec, &vol->catalog ); + record_init_parent( &r, &rec ); + + /* Remove initial \ or / */ + curfol = strsep(&tmppath, "\\//"); + curfol = strsep(&tmppath, "\\//"); + forth_printf("\n"); + + while (curfol && strlen(curfol)) { + found = 0; + do { + if (r.record.type == HFSP_FOLDER) { + unicode_uni2asc(name, &r.key.name, sizeof(name)); + + if (!strcmp(name, curfol)) { + folrec = r; + found = -1; + } + } + } while ( !record_next(&r) ); + + if (!found) { + forth_printf("Unable to locate path %s on filesystem\n", path); + goto done; + } else { + record_init_parent( &r, &folrec ); + } + + curfol = strsep(&tmppath, "\\//"); + } + + /* Output the directory contents */ + found = 0; + do { + unicode_uni2asc(name, &r.key.name, sizeof(name)); + + if (r.record.type == HFSP_FILE) { + /* Grab the file entry */ + hfsp_cat_file *file = &r.record.u.file; + forth_printf("% 10lld ", file->data_fork.total_size); + print_date(file->create_date); + forth_printf(" %s\n", name); + found = -1; + } + + if (r.record.type == HFSP_FOLDER) { + /* Grab the directory entry */ + hfsp_cat_folder *folder = &r.record.u.folder; + forth_printf(" 0 "); + print_date(folder->create_date); + forth_printf(" %s\\\n", name); + found = -1; + } + + } while ( !record_next(&r) ); + + if (!found) { + forth_printf(" (Empty folder)\n"); + } + +done: + volume_close(vol); + free(vol); + free(path); + if (tmppath) + free(tmppath); +} + +/* static method, ( pos.d ih -- flag? ) */ +static void +hfsp_files_probe( hfsp_info_t *dummy ) +{ + ihandle_t ih = POP_ih(); + long long offs = DPOP(); + int fd, ret = 0; + + fd = open_ih(ih); + if (fd >= 0) { + if (volume_probe(fd, offs)) { + ret = -1; + } + close_io(fd); + } else { + ret = -1; + } + + RET (ret); +} + +static void +hfsp_initializer( hfsp_info_t *dummy ) +{ + fword("register-fs-package"); +} + +NODE_METHODS( hfsp ) = { + { "probe", hfsp_files_probe }, + { "open", hfsp_files_open }, + { "close", hfsp_files_close }, + { "read", hfsp_files_read }, + { "seek", hfsp_files_seek }, + { "load", hfsp_files_load }, + { "dir", hfsp_files_dir }, + + /* special */ + { "open-nwrom", hfsp_files_open_nwrom }, + { "get-path", hfsp_files_get_path }, + { "get-fstype", hfsp_files_get_fstype }, + { "volume-name", hfsp_files_volume_name }, + + { NULL, hfsp_initializer }, +}; + +void +hfsp_init( void ) +{ + REGISTER_NODE( hfsp ); +} diff --git a/qemu/roms/openbios/fs/hfsplus/hfsp_record.c b/qemu/roms/openbios/fs/hfsplus/hfsp_record.c new file mode 100644 index 000000000..d4e7af1bf --- /dev/null +++ b/qemu/roms/openbios/fs/hfsplus/hfsp_record.c @@ -0,0 +1,759 @@ +/* + * libhfsp - library for reading and writing Macintosh HFS+ volumes. + * + * a record contains a key and a folder or file and is part + * of a btree. + * + * Copyright (C) 2000 Klaus Halfmann <khalfmann@libra.de> + * Original 1996-1998 Robert Leslie <rob@mars.org> + * Additional work by Brad Boyer (flar@pants.nu) + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * $Id: record.c,v 1.24 2000/10/17 05:58:46 hasi Exp $ + */ + +#include "config.h" +#include "libhfsp.h" +#include "hfstime.h" +#include "record.h" +#include "volume.h" +#include "btree.h" +#include "unicode.h" +#include "swab.h" + +/* read a hfsp_cat_key from memory */ +void* record_readkey(void* p, void* buf) +{ + hfsp_cat_key* key = (hfsp_cat_key*) buf; + const void* check; + UInt16 key_length, len,i; + UInt16* cp; + + key->key_length = key_length = bswabU16_inc(p); + check = p; + key->parent_cnid = bswabU32_inc(p); + key->name.strlen = len = bswabU16_inc(p); + cp = key->name.name; + for (i=0; i < len; i++, cp++) + *cp = bswabU16_inc(p); + /* check if keylenght was correct */ + if (key_length != ((char*) p) - ((char*) check)) + HFSP_ERROR(EINVAL, "Invalid key length in record_readkey"); + return p; + fail: + return NULL; +} + +/* read a hfsp_extent_key from memory */ +void* record_extent_readkey(void* p, void* buf) +{ + hfsp_extent_key* key = (hfsp_extent_key*) buf; + UInt16 key_length; + + key->key_length = key_length = bswabU16_inc(p); + key->fork_type = bswabU8_inc(p); + key->filler = bswabU8_inc(p); + if (key_length != 10) + HFSP_ERROR(-1, "Invalid key length in record_extent_readkey"); + key->file_id = bswabU32_inc(p); + key->start_block = bswabU32_inc(p); + return p; + fail: + return NULL; +} + + +/* read posix permission from memory */ +static inline void* record_readperm(void *p, hfsp_perm* perm) +{ + perm->owner= bswabU32_inc(p); + perm->group= bswabU32_inc(p); + perm->mode = bswabU32_inc(p); + perm->dev = bswabU32_inc(p); + return p; +} + +/* read directory info */ +static inline void* record_readDInfo(void *p, DInfo* info) +{ + info->frRect.top = bswabU16_inc(p); + info->frRect.left = bswabU16_inc(p); + info->frRect.bottom = bswabU16_inc(p); + info->frRect.right = bswabU16_inc(p); + info->frFlags = bswabU16_inc(p); + info->frLocation.v = bswabU16_inc(p); + info->frLocation.h = bswabU16_inc(p); + info->frView = bswabU16_inc(p); + return p; +} + +/* read extra Directory info */ +static inline void* record_readDXInfo(void *p, DXInfo* xinfo) +{ + xinfo->frScroll.v = bswabU16_inc(p); + xinfo->frScroll.h = bswabU16_inc(p); + xinfo->frOpenChain = bswabU32_inc(p); + xinfo->frUnused = bswabU16_inc(p); + xinfo->frComment = bswabU16_inc(p); + xinfo->frPutAway = bswabU32_inc(p); + return p; +} + +/* read a hfsp_cat_folder from memory */ +static void* record_readfolder(void *p, hfsp_cat_folder* folder) +{ + folder->flags = bswabU16_inc(p); + folder->valence = bswabU32_inc(p); + folder->id = bswabU32_inc(p); + folder->create_date = bswabU32_inc(p); + folder->content_mod_date = bswabU32_inc(p); + folder->attribute_mod_date = bswabU32_inc(p); + folder->access_date = bswabU32_inc(p); + folder->backup_date = bswabU32_inc(p); + p = record_readperm (p, &folder->permissions); + p = record_readDInfo (p, &folder->user_info); + p = record_readDXInfo (p, &folder->finder_info); + folder->text_encoding = bswabU32_inc(p); + folder->reserved = bswabU32_inc(p); + return p; +} + +/* read file info */ +static inline void* record_readFInfo(void *p, FInfo* info) +{ + info->fdType = bswabU32_inc(p); + info->fdCreator = bswabU32_inc(p); + info->fdFlags = bswabU16_inc(p); + info->fdLocation.v = bswabU16_inc(p); + info->fdLocation.h = bswabU16_inc(p); + info->fdFldr = bswabU16_inc(p); + return p; +} + +/* read extra File info */ +static inline void* record_readFXInfo(void *p, FXInfo* xinfo) +{ + SInt16 *q; + xinfo->fdIconID = bswabU16_inc(p); + q=(SInt16*) p; + q+=4; // skip unused + p=(void *)q; + xinfo->fdComment = bswabU16_inc(p); + xinfo->fdPutAway = bswabU32_inc(p); + return p; +} + +/* read a hfsp_cat_file from memory */ +static void* record_readfile(void *p, hfsp_cat_file* file) +{ + file->flags = bswabU16_inc(p); + file->reserved1 = bswabU32_inc(p); + file->id = bswabU32_inc(p); + file->create_date = bswabU32_inc(p); + file->content_mod_date = bswabU32_inc(p); + file->attribute_mod_date = bswabU32_inc(p); + file->access_date = bswabU32_inc(p); + file->backup_date = bswabU32_inc(p); + p = record_readperm (p, &file->permissions); + p = record_readFInfo (p, &file->user_info); + p = record_readFXInfo (p, &file->finder_info); + file->text_encoding = bswabU32_inc(p); + file->reserved2 = bswabU32_inc(p); + p = volume_readfork (p, &file->data_fork); + return volume_readfork (p, &file->res_fork); +} + +/* read a hfsp_cat_thread from memory */ +static void* record_readthread(void *p, hfsp_cat_thread* entry) +{ + int i; + UInt16 len; + UInt16* cp; + + entry-> reserved = bswabU16_inc(p); + entry-> parentID = bswabU32_inc(p); + entry->nodeName.strlen = len= bswabU16_inc(p); + cp = entry->nodeName.name; + if (len > 255) + HFSP_ERROR(-1, "Invalid key length in record thread"); + for (i=0; i < len; i++, cp++) + *cp = bswabU16_inc(p); + return p; + fail: + return NULL; +} + +/* read a hfsp_cat_entry from memory */ +static void* record_readentry(void *p, hfsp_cat_entry* entry) +{ + UInt16 type = bswabU16_inc(p); + entry->type = type; + switch (type) + { + case HFSP_FOLDER: + return record_readfolder(p, &entry->u.folder); + case HFSP_FILE: + return record_readfile (p, &entry->u.file); + case HFSP_FOLDER_THREAD: + case HFSP_FILE_THREAD: + return record_readthread(p, &entry->u.thread); + default: + HFSP_ERROR(-1, "Unexpected record type in record_readentry"); + } ; + fail: + return NULL; +} + + +/* Most of the functions here will not change the node in the btree, + But this must be changed in the future ... */ + + +/* intialize the record with the given index entry in the btree. */ +static int record_init(record* r, btree* bt, node_buf* buf, UInt16 index) +{ + void *p; + r-> tree = bt; + p = btree_key_by_index(bt,buf,index); + if (!p) + return -1; + p = record_readkey (p, &r->key); + if (!p) + return -1; + p = record_readentry(p, &r->record); + if (!p) + return -1; + r->node_index = buf->index; + r-> keyind = index; + + return 0; +} + +/* intialize the record with the given index entry in the btree. */ +static int record_init_extent(extent_record* r, btree* bt, node_buf* buf, UInt16 index) +{ + void *p; + r-> tree = bt; + p = btree_key_by_index(bt, buf,index); + if (!p) + return -1; + p = record_extent_readkey(p, &r->key); + if (!p) + return -1; + p = volume_readextent(p, r->extent); + if (!p) + return -1; + r->node_index = buf->index; + r-> keyind = index; + + return 0; +} + +/* intialize the record to the first record of the tree + * which is (per design) the root node. + */ +int record_init_root(record* r, btree* tree) +{ + // Position to first leaf node ... + UInt32 leaf_head = tree->head.leaf_head; + node_buf* buf = btree_node_by_index(tree, leaf_head); + if (!buf) + return -1; + return record_init(r, tree, buf, 0); +} + +/* Compare two cat_keys ... */ +int record_key_compare(void* k1, void* k2) +{ + hfsp_cat_key* key1 = (hfsp_cat_key*) k1; + hfsp_cat_key* key2 = (hfsp_cat_key*) k2; + int diff = key2->parent_cnid - key1->parent_cnid; + if (!diff) // same parent + diff = fast_unicode_compare(&key1->name, &key2->name); + return diff; +} + +/* Compare two extent_keys ... */ +int record_extent_key_compare(void* k1, void* k2) +{ + hfsp_extent_key* key1 = (hfsp_extent_key*) k1; + hfsp_extent_key* key2 = (hfsp_extent_key*) k2; + int diff = key2->fork_type - key1->fork_type; + if (!diff) // same type + { + diff = key2->file_id - key1->file_id; + if (!diff) // same file + diff = key2->start_block - key1->start_block; + } + return diff; +} + +/* Position node in btree so that key might be inside */ +static node_buf* record_find_node(btree* tree, void *key) +{ + int start, end, mid, comp; // components of a binary search + void *p = NULL; + char curr_key[tree->head.max_key_len]; + // The current key under examination + hfsp_key_read readkey = tree->kread; + hfsp_key_compare key_compare = tree->kcomp; + UInt32 index; + node_buf* node = btree_node_by_index(tree, tree->head.root); + if (!node) + HFSP_ERROR(-1, "record_find_node: Cant position to root node"); + while (node->desc.kind == HFSP_NODE_NDX) + { + mid = start = 0; + end = node->desc.num_rec; + comp = -1; + while (start < end) + { + mid = (start + end) >> 1; + p = btree_key_by_index(tree, node, mid); + if (!p) + HFSP_ERROR(-1, "record_find_node: unexpected error"); + p = readkey (p, curr_key); + if (!p) + HFSP_ERROR(-1, "record_find_node: unexpected error"); + comp = key_compare(curr_key, key); + if (comp > 0) + start = mid + 1; + else if (comp < 0) + end = mid; + else + break; + } + if (!p) // Empty tree, fascinating ... + HFSP_ERROR(-1, "record_find_node: unexpected empty node"); + if (comp < 0) // mmh interesting key is before this key ... + { + if (mid == 0) + return NULL; // nothing before this key .. + p = btree_key_by_index(tree, node, mid-1); + if (!p) + HFSP_ERROR(-1, "record_find_node: unexpected error"); + p = readkey (p, curr_key); + if (!p) + HFSP_ERROR(-1, "record_find_node: unexpected error"); + } + + index = bswabU32_inc(p); + node = btree_node_by_index(tree, index); + } + return node; // go on and use the found node + fail: + return NULL; +} + +/* search for the given key in the btree. + * + * returns pointer to memory just after key or NULL + * In any case *keyind recives the index where the + * key was found (or could be inserted.) + */ +static void * +record_find_key(btree* tree, void* key, int* keyind, UInt16* node_index) +{ + node_buf* buf = record_find_node(tree, key); + if (buf) + { + int comp = -1; + int start = 0; // components of a binary search + int end = buf->desc.num_rec; + int mid = -1; + void *p = NULL; + char curr_key[tree->head.max_key_len]; + hfsp_key_read readkey = tree->kread; + hfsp_key_compare key_compare = tree->kcomp; + while (start < end) + { + mid = (start + end) >> 1; + p = btree_key_by_index(tree, buf, mid); + if (!p) + HFSP_ERROR(-1, "record_init_key: unexpected error"); + p = readkey (p, curr_key); + if (!p) + HFSP_ERROR(-1, "record_init_cat_key: unexpected error"); + comp = key_compare(curr_key, key); + if (comp > 0) + start = mid + 1; + else if (comp < 0) + end = mid; + else + break; + } + if (!p) // Empty tree, fascinating ... + HFSP_ERROR(ENOENT, "record_init_key: unexpected empty node"); + *keyind = mid; + *node_index = buf->index; + if (!comp) // found something ... + return p; + } + HFSP_ERROR(ENOENT, NULL); + fail: + return NULL; +} + +/* intialize the record by searching for the given key in the btree. + * + * r is umodified on error. + */ +static int +record_init_key(record* r, btree* tree, hfsp_cat_key* key) +{ + int keyind; + UInt16 node_index; + void *p = record_find_key(tree, key, &keyind, &node_index); + + if (p) + { + r -> tree = tree; + r -> node_index= node_index; + r -> keyind = keyind; + r -> key = *key; // Better use a record_key_copy ... + p = record_readentry(p, &r->record); + if (!p) + HFSP_ERROR(-1, "record_init_key: unexpected error"); + return 0; + } + fail: + return -1; +} + +/* intialize the extent_record to the extent identified by the + * (first) blockindex. + * + * forktype: either HFSP_EXTEND_DATA or HFSP_EXTEND_RSRC + */ +int record_init_file(extent_record* r, btree* tree, + UInt8 forktype, UInt32 fileId, UInt32 blockindex) +{ + int keyind; + UInt16 node_index; + hfsp_extent_key key = { 10, forktype, 0, fileId, blockindex }; + void *p = record_find_key(tree, &key, &keyind, &node_index); + + if (p) + { + r -> tree = tree; + r -> node_index= node_index; + r -> keyind = keyind; + r -> key = key; // Better use a record_key_copy ... + p = volume_readextent(p, r->extent); + if (!p) + HFSP_ERROR(-1, "record_init_file: unexpected error"); + return 0; + } + fail: + return -1; +} + +/* intialize the record to the folder identified by cnid + */ +int record_init_cnid(record* r, btree* tree, UInt32 cnid) +{ + hfsp_cat_key thread_key; // the thread is the first record + + thread_key.key_length = 6; // null name (like '.' in unix ) + thread_key.parent_cnid = cnid; + thread_key.name.strlen = 0; + + return record_init_key(r, tree, &thread_key); +} + +/* intialize the record to the first record of the parent. + */ +int record_init_parent(record* r, record* parent) +{ + if (parent->record.type == HFSP_FOLDER) + return record_init_cnid(r, parent->tree, parent->record.u.folder.id); + else if(parent->record.type == HFSP_FOLDER_THREAD) + { + if (r != parent) + *r = *parent; // The folder thread is in fact the first entry, like '.' + return 0; + } + HFSP_ERROR(EINVAL, + "record_init_parent: parent is neither folder nor folder thread."); + + fail: + return EINVAL; +} + + +/* find correct node record for given node and *pindex. + * + * index of record in this (or next) node + * */ +static node_buf* prepare_next(btree* tree, UInt16 node_index, UInt16* pindex) +{ + node_buf* buf = btree_node_by_index(tree, node_index); + btree_node_desc* desc = &buf->desc; + UInt32 numrec = desc->num_rec; + if (*pindex >= numrec) // move on to next node + { + UInt16 next = desc->next; + *pindex = 0; + if (!next /* is there a next node ? */ + || !( buf = btree_node_by_index(tree, next))) + return NULL; + } + return buf; +} +/* move record foreward to next entry. + * + * In case of an error the value of *r is undefined ! + */ +int record_next(record* r) +{ + btree* tree = r->tree; + UInt16 index = r->keyind +1; + UInt32 parent; + node_buf* buf = prepare_next(tree, r->node_index, &index); + + if (!buf) + return ENOENT; // No (more) such file or directory + + parent = r->key.parent_cnid; + + if (record_init(r, tree, buf, index)) + return -1; + + if (r->key.parent_cnid != parent || // end of current directory + index != r->keyind) // internal error ? + return ENOENT; // No (more) such file or directory + + return 0; +} + +/* move record foreward to next extent record. + * + * In case of an error the value of *r is undefined ! + */ +int record_next_extent(extent_record* r) +{ + btree* tree = r->tree; + UInt16 index = r->keyind +1; + UInt32 file_id; + UInt8 fork_type; + node_buf* buf = prepare_next(tree, r->node_index, &index); + + if (!buf) + return ENOENT; // No (more) such file or directory + + file_id = r->key.file_id; + fork_type = r->key.fork_type; + + if (record_init_extent(r, tree, buf, index)) + return -1; + + if (r->key.file_id != file_id || // end of current file + r->key.fork_type != fork_type || // end of current fork + index != r->keyind) // internal error ? + return ENOENT; // No (more) such file or directory + + return 0; +} + +/* intialize the record by searching for the given string in the given folder. + * + * parent and r may be the same. + */ +int record_init_string_parent(record* r, record* parent, char* name) +{ + hfsp_cat_key key; + + if (parent->record.type == HFSP_FOLDER) + key.parent_cnid = parent->record.u.folder.id; + else if(parent->record.type == HFSP_FOLDER_THREAD) + key.parent_cnid = parent->key.parent_cnid; + else + HFSP_ERROR(-1, "record_init_string_parent: parent is not a folder."); + + key.key_length = 6 + unicode_asc2uni(&key.name,name); // 6 for minumum size + return record_init_key(r, parent->tree, &key); + + fail: + return -1; +} + +/* move record up in folder hierarchy (if possible) */ +int record_up(record* r) +{ + if (r->record.type == HFSP_FOLDER) + { + // locate folder thread + if (record_init_cnid(r, r->tree, r->record.u.folder.id)) + return -1; + } + else if(r->record.type == HFSP_FOLDER_THREAD) + { + // do nothing were are already where we want to be + } + else + HFSP_ERROR(-1, "record_up: record is neither folder nor folder thread."); + + if(r->record.type != HFSP_FOLDER_THREAD) + HFSP_ERROR(-1, "record_up: unable to locate parent"); + return record_init_cnid(r, r->tree, r->record.u.thread.parentID); + + fail: + return -1; +} + +#ifdef DEBUG + +/* print Quickdraw Point */ +static void record_print_Point(Point* p) +{ + printf("[ v=%d, h=%d ]", p->v, p->h); +} + +/* print Quickdraw Rect */ +static void record_print_Rect(Rect* r) +{ + printf("[ top=%d, left=%d, bottom=%d, right=%d ]", + r->top, r->left, r->bottom, r->right); +} + +/* print the key of a record */ +static void record_print_key(hfsp_cat_key* key) +{ + char buf[255]; // mh this _might_ overflow + unicode_uni2asc(buf, &key->name, 255); + printf("parent cnid : %ld\n", key->parent_cnid); + printf("name : %s\n", buf); +} + +/* print permissions */ +static void record_print_perm(hfsp_perm* perm) +{ + printf("owner :\t%ld\n", perm->owner); + printf("group :\t%ld\n", perm->group); + printf("perm :\t0x%lX\n",perm->mode); + printf("dev :\t%ld\n", perm->dev); +} + +/* print Directory info */ +static void record_print_DInfo(DInfo* dinfo) +{ + printf( "frRect :\t"); record_print_Rect(&dinfo->frRect); + printf("\nfrFlags :\t0X%X\n", dinfo->frFlags); + printf( "frLocation :\t"); record_print_Point(&dinfo->frLocation); + printf("\nfrView :\t0X%X\n", dinfo->frView); +} + +/* print extended Directory info */ +static void record_print_DXInfo(DXInfo* xinfo) +{ + printf( "frScroll :\t"); record_print_Point(&xinfo->frScroll); + printf("\nfrOpenChain :\t%ld\n", xinfo->frOpenChain); + printf( "frUnused :\t%d\n", xinfo->frUnused); + printf( "frComment :\t%d\n", xinfo->frComment); + printf( "frPutAway :\t%ld\n", xinfo->frPutAway); +} + +static void record_print_folder(hfsp_cat_folder* folder) +{ + printf("flags :\t0x%X\n", folder->flags); + printf("valence :\t0x%lX\n", folder->valence); + printf("id :\t%ld\n", folder->id); + record_print_perm (&folder->permissions); + record_print_DInfo (&folder->user_info); + record_print_DXInfo (&folder->finder_info); + printf("text_encoding :\t0x%lX\n", folder->text_encoding); + printf("reserved :\t0x%lX\n", folder->reserved); +} + +/* print File info */ +static void record_print_FInfo(FInfo* finfo) +{ + printf( "fdType :\t%4.4s\n", (char*) &finfo->fdType); + printf( "fdCreator :\t%4.4s\n", (char*) &finfo->fdCreator); + printf( "fdFlags :\t0X%X\n", finfo->fdFlags); + printf( "fdLocation :\t"); record_print_Point(&finfo->fdLocation); + printf("\nfdFldr :\t%d\n", finfo->fdFldr); +} + +/* print extended File info */ +static void record_print_FXInfo(FXInfo* xinfo) +{ + printf( "fdIconID :\t%d\n", xinfo->fdIconID); + // xinfo -> fdUnused; + printf( "fdComment :\t%d\n", xinfo->fdComment); + printf( "fdPutAway :\t%ld\n", xinfo->fdPutAway); +} + +/* print folder entry */ + +/* print file entry */ +static void record_print_file(hfsp_cat_file* file) +{ + printf("flags :\t0x%X\n", file->flags); + printf("reserved1 :\t0x%lX\n", file->reserved1); + printf("id :\t%ld\n", file->id); + record_print_perm (&file->permissions); + record_print_FInfo (&file->user_info); + record_print_FXInfo (&file->finder_info); + printf("text_encoding :\t0x%lX\n", file->text_encoding); + printf("reserved :\t0x%lX\n", file->reserved2); + printf("Datafork:\n"); + volume_print_fork (&file->data_fork); + printf("Rsrcfork:\n"); + volume_print_fork (&file->res_fork); +} + +/* print info for a file or folder thread */ +static void record_print_thread(hfsp_cat_thread* entry) +{ + char buf[255]; // mh this _might_ overflow + unicode_uni2asc(buf, &entry->nodeName, 255); + printf("parent cnid :\t%ld\n", entry->parentID); + printf("name :\t%s\n" , buf); +} + +/* print the information for a record */ +static void record_print_entry(hfsp_cat_entry* entry) +{ + switch (entry->type) + { + case HFSP_FOLDER: + printf("=== Folder ===\n"); + return record_print_folder(&entry->u.folder); + case HFSP_FILE: + printf("=== File ===\n"); + return record_print_file (&entry->u.file); + case HFSP_FOLDER_THREAD: + printf("=== Folder Thread ===\n"); + return record_print_thread(&entry->u.thread); + case HFSP_FILE_THREAD: + printf("=== File Thread ==\n"); + return record_print_thread(&entry->u.thread); + default: + printf("=== Unknown Record Type ===\n"); + } ; +} + + /* Dump all the record information to stdout */ +void record_print(record* r) +{ + printf ("keyind : %u\n", r->keyind); + record_print_key (&r->key); + record_print_entry(&r->record); +} + +#endif diff --git a/qemu/roms/openbios/fs/hfsplus/hfsp_unicode.c b/qemu/roms/openbios/fs/hfsplus/hfsp_unicode.c new file mode 100644 index 000000000..7a34affa1 --- /dev/null +++ b/qemu/roms/openbios/fs/hfsplus/hfsp_unicode.c @@ -0,0 +1,511 @@ +/* + * linux/fs/hfsplus/unicode.c + * + * Copyright (C) 1999-2000 Brad Boyer (flar@pants.nu) + * This file may be distributed under the terms of the GNU Public License. + * + * The routines found here convert hfs-unicode string into ascii Strings + * and vice versa. And the correct comparison between Strings. + */ + + +#include "config.h" +#include "libhfsp.h" +#include "unicode.h" + +/* ISO-8859-1 -> unicode */ +static int +asc2uni( unsigned char *ustr, const char *astr, int maxlen ) +{ + int len; + + if( maxlen <= 0 ) + return 0; + + for( len=0; *astr && len < maxlen-1 ; astr++, len++ ) { + *ustr++ = 0; + *ustr++ = *astr; + } + ustr[0] = ustr[1] = 0; + return len; +} + +/* unicode -> ISO-8859-1 */ +static int +uni2asc( char *astr, const unsigned char *ustr, int ustrlen, int maxlen ) +{ + int len; + + if( maxlen <= 0 ) + return 0; + + for( len=0; ustrlen-- > 0 && len < maxlen-1 ; ustr += 2 ) { + /* might be unrepresentable (or too complicated for us) */ + if( ustr[0] || !ustr[1] ) + continue; + if( ustr[1] < 0x20 || ustr[1] >= 0x7f ) + *astr++ = '?'; + else + *astr++ = ustr[1]; + len++; + } + *astr = 0; + return len; +} + +int +unicode_asc2uni( hfsp_unistr255 *ustr, const char* astr ) +{ + return ustr->strlen = asc2uni( (u8*)ustr->name, astr, 255 ); +} + +int +unicode_uni2asc(char *astr, const hfsp_unistr255 *ustr, int maxlen) +{ + return uni2asc( astr, (u8*)ustr->name, ustr->strlen, maxlen ); +} + +/* The following code is almost as published by Apple, only + small modifications where made to match some linux styles ... + +fastUnicodeCompare - Compare two Unicode strings; produce a relative ordering +*/ + +static const UInt16 gLowerCaseTable[]; + +SInt32 fast_unicode_compare ( const hfsp_unistr255 *ustr1, + const hfsp_unistr255 *ustr2) +{ + register UInt16 c1,c2; + register SInt32 diff; + register UInt16 temp; + register UInt16 length1 = ustr1->strlen; + register UInt16 length2 = ustr2->strlen; + register const UInt16* lowerCaseTable = gLowerCaseTable; + register const UInt16* str1 = ustr1->name; + register const UInt16* str2 = ustr2->name; + + while (1) { + // Set default values for c1, c2 in case there are no more valid chars + c1 = c2 = 0; + // Find next non-ignorable char from str1, or zero if no more + while (length1 && c1 == 0) { + c1 = *(str1++); + --length1; + if ((temp = lowerCaseTable[c1>>8]) != 0) // is there a subtable + // for this upper byte? + c1 = lowerCaseTable[temp + (c1 & 0x00FF)]; // yes, so fold the char + } + // Find next non-ignorable char from str2, or zero if no more + while (length2 && c2 == 0) { + c2 = *(str2++); + --length2; + if ((temp = lowerCaseTable[c2>>8]) != 0) // is there a subtable + // for this upper byte? + c2 = lowerCaseTable[temp + (c2 & 0x00FF)]; // yes, so fold the char + } + diff = c2-c1; + if (diff) // found a difference, so stop looping + break; + if (c1 == 0) // did we reach the end of both strings at the same time? + return 0; // yes, so strings are equal + } + return diff; +} + + +/* The lower case table consists of a 256-entry high-byte table followed by + some number of 256-entry subtables. The high-byte table contains either an + offset to the subtable for characters with that high byte or zero, which + means that there are no case mappings or ignored characters in that block. + Ignored characters are mapped to zero. + */ + +static const UInt16 gLowerCaseTable[] = { + + // High-byte indices ( == 0 iff no case mapping and no ignorables ) + + + /* 0 */ 0x0100, 0x0200, 0x0000, 0x0300, 0x0400, 0x0500, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 1 */ 0x0600, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 2 */ 0x0700, 0x0800, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 3 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 4 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 5 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 6 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 7 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 8 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 9 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* A */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* B */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* C */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* D */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* E */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* F */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0900, 0x0A00, + + // Table 1 (for high byte 0x00) + + /* 0 */ 0xFFFF, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, + 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, + /* 1 */ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, + 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F, + /* 2 */ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, + 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F, + /* 3 */ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, + 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F, + /* 4 */ 0x0040, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, + 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, + /* 5 */ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, + 0x0078, 0x0079, 0x007A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F, + /* 6 */ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, + 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, + /* 7 */ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, + 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F, + /* 8 */ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, + 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F, + /* 9 */ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, + 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, 0x009F, + /* A */ 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, + 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, + /* B */ 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, + 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, + /* C */ 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00E6, 0x00C7, + 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, + /* D */ 0x00F0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, + 0x00F8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00FE, 0x00DF, + /* E */ 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, + 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, + /* F */ 0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, + 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF, + + // Table 2 (for high byte 0x01) + + /* 0 */ 0x0100, 0x0101, 0x0102, 0x0103, 0x0104, 0x0105, 0x0106, 0x0107, + 0x0108, 0x0109, 0x010A, 0x010B, 0x010C, 0x010D, 0x010E, 0x010F, + /* 1 */ 0x0111, 0x0111, 0x0112, 0x0113, 0x0114, 0x0115, 0x0116, 0x0117, + 0x0118, 0x0119, 0x011A, 0x011B, 0x011C, 0x011D, 0x011E, 0x011F, + /* 2 */ 0x0120, 0x0121, 0x0122, 0x0123, 0x0124, 0x0125, 0x0127, 0x0127, + 0x0128, 0x0129, 0x012A, 0x012B, 0x012C, 0x012D, 0x012E, 0x012F, + /* 3 */ 0x0130, 0x0131, 0x0133, 0x0133, 0x0134, 0x0135, 0x0136, 0x0137, + 0x0138, 0x0139, 0x013A, 0x013B, 0x013C, 0x013D, 0x013E, 0x0140, + /* 4 */ 0x0140, 0x0142, 0x0142, 0x0143, 0x0144, 0x0145, 0x0146, 0x0147, + 0x0148, 0x0149, 0x014B, 0x014B, 0x014C, 0x014D, 0x014E, 0x014F, + /* 5 */ 0x0150, 0x0151, 0x0153, 0x0153, 0x0154, 0x0155, 0x0156, 0x0157, + 0x0158, 0x0159, 0x015A, 0x015B, 0x015C, 0x015D, 0x015E, 0x015F, + /* 6 */ 0x0160, 0x0161, 0x0162, 0x0163, 0x0164, 0x0165, 0x0167, 0x0167, + 0x0168, 0x0169, 0x016A, 0x016B, 0x016C, 0x016D, 0x016E, 0x016F, + /* 7 */ 0x0170, 0x0171, 0x0172, 0x0173, 0x0174, 0x0175, 0x0176, 0x0177, + 0x0178, 0x0179, 0x017A, 0x017B, 0x017C, 0x017D, 0x017E, 0x017F, + /* 8 */ 0x0180, 0x0253, 0x0183, 0x0183, 0x0185, 0x0185, 0x0254, 0x0188, + 0x0188, 0x0256, 0x0257, 0x018C, 0x018C, 0x018D, 0x01DD, 0x0259, + /* 9 */ 0x025B, 0x0192, 0x0192, 0x0260, 0x0263, 0x0195, 0x0269, 0x0268, + 0x0199, 0x0199, 0x019A, 0x019B, 0x026F, 0x0272, 0x019E, 0x0275, + /* A */ 0x01A0, 0x01A1, 0x01A3, 0x01A3, 0x01A5, 0x01A5, 0x01A6, 0x01A8, + 0x01A8, 0x0283, 0x01AA, 0x01AB, 0x01AD, 0x01AD, 0x0288, 0x01AF, + /* B */ 0x01B0, 0x028A, 0x028B, 0x01B4, 0x01B4, 0x01B6, 0x01B6, 0x0292, + 0x01B9, 0x01B9, 0x01BA, 0x01BB, 0x01BD, 0x01BD, 0x01BE, 0x01BF, + /* C */ 0x01C0, 0x01C1, 0x01C2, 0x01C3, 0x01C6, 0x01C6, 0x01C6, 0x01C9, + 0x01C9, 0x01C9, 0x01CC, 0x01CC, 0x01CC, 0x01CD, 0x01CE, 0x01CF, + /* D */ 0x01D0, 0x01D1, 0x01D2, 0x01D3, 0x01D4, 0x01D5, 0x01D6, 0x01D7, + 0x01D8, 0x01D9, 0x01DA, 0x01DB, 0x01DC, 0x01DD, 0x01DE, 0x01DF, + /* E */ 0x01E0, 0x01E1, 0x01E2, 0x01E3, 0x01E5, 0x01E5, 0x01E6, 0x01E7, + 0x01E8, 0x01E9, 0x01EA, 0x01EB, 0x01EC, 0x01ED, 0x01EE, 0x01EF, + /* F */ 0x01F0, 0x01F3, 0x01F3, 0x01F3, 0x01F4, 0x01F5, 0x01F6, 0x01F7, + 0x01F8, 0x01F9, 0x01FA, 0x01FB, 0x01FC, 0x01FD, 0x01FE, 0x01FF, + + // Table 3 (for high byte 0x03) + + /* 0 */ 0x0300, 0x0301, 0x0302, 0x0303, 0x0304, 0x0305, 0x0306, 0x0307, + 0x0308, 0x0309, 0x030A, 0x030B, 0x030C, 0x030D, 0x030E, 0x030F, + /* 1 */ 0x0310, 0x0311, 0x0312, 0x0313, 0x0314, 0x0315, 0x0316, 0x0317, + 0x0318, 0x0319, 0x031A, 0x031B, 0x031C, 0x031D, 0x031E, 0x031F, + /* 2 */ 0x0320, 0x0321, 0x0322, 0x0323, 0x0324, 0x0325, 0x0326, 0x0327, + 0x0328, 0x0329, 0x032A, 0x032B, 0x032C, 0x032D, 0x032E, 0x032F, + /* 3 */ 0x0330, 0x0331, 0x0332, 0x0333, 0x0334, 0x0335, 0x0336, 0x0337, + 0x0338, 0x0339, 0x033A, 0x033B, 0x033C, 0x033D, 0x033E, 0x033F, + /* 4 */ 0x0340, 0x0341, 0x0342, 0x0343, 0x0344, 0x0345, 0x0346, 0x0347, + 0x0348, 0x0349, 0x034A, 0x034B, 0x034C, 0x034D, 0x034E, 0x034F, + /* 5 */ 0x0350, 0x0351, 0x0352, 0x0353, 0x0354, 0x0355, 0x0356, 0x0357, + 0x0358, 0x0359, 0x035A, 0x035B, 0x035C, 0x035D, 0x035E, 0x035F, + /* 6 */ 0x0360, 0x0361, 0x0362, 0x0363, 0x0364, 0x0365, 0x0366, 0x0367, + 0x0368, 0x0369, 0x036A, 0x036B, 0x036C, 0x036D, 0x036E, 0x036F, + /* 7 */ 0x0370, 0x0371, 0x0372, 0x0373, 0x0374, 0x0375, 0x0376, 0x0377, + 0x0378, 0x0379, 0x037A, 0x037B, 0x037C, 0x037D, 0x037E, 0x037F, + /* 8 */ 0x0380, 0x0381, 0x0382, 0x0383, 0x0384, 0x0385, 0x0386, 0x0387, + 0x0388, 0x0389, 0x038A, 0x038B, 0x038C, 0x038D, 0x038E, 0x038F, + /* 9 */ 0x0390, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, + 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, + /* A */ 0x03C0, 0x03C1, 0x03A2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7, + 0x03C8, 0x03C9, 0x03AA, 0x03AB, 0x03AC, 0x03AD, 0x03AE, 0x03AF, + /* B */ 0x03B0, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, + 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, + /* C */ 0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7, + 0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03CC, 0x03CD, 0x03CE, 0x03CF, + /* D */ 0x03D0, 0x03D1, 0x03D2, 0x03D3, 0x03D4, 0x03D5, 0x03D6, 0x03D7, + 0x03D8, 0x03D9, 0x03DA, 0x03DB, 0x03DC, 0x03DD, 0x03DE, 0x03DF, + /* E */ 0x03E0, 0x03E1, 0x03E3, 0x03E3, 0x03E5, 0x03E5, 0x03E7, 0x03E7, + 0x03E9, 0x03E9, 0x03EB, 0x03EB, 0x03ED, 0x03ED, 0x03EF, 0x03EF, + /* F */ 0x03F0, 0x03F1, 0x03F2, 0x03F3, 0x03F4, 0x03F5, 0x03F6, 0x03F7, + 0x03F8, 0x03F9, 0x03FA, 0x03FB, 0x03FC, 0x03FD, 0x03FE, 0x03FF, + + // Table 4 (for high byte 0x04) + + /* 0 */ 0x0400, 0x0401, 0x0452, 0x0403, 0x0454, 0x0455, 0x0456, 0x0407, + 0x0458, 0x0459, 0x045A, 0x045B, 0x040C, 0x040D, 0x040E, 0x045F, + /* 1 */ 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, + 0x0438, 0x0419, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F, + /* 2 */ 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, + 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F, + /* 3 */ 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, + 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F, + /* 4 */ 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, + 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F, + /* 5 */ 0x0450, 0x0451, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456, 0x0457, + 0x0458, 0x0459, 0x045A, 0x045B, 0x045C, 0x045D, 0x045E, 0x045F, + /* 6 */ 0x0461, 0x0461, 0x0463, 0x0463, 0x0465, 0x0465, 0x0467, 0x0467, + 0x0469, 0x0469, 0x046B, 0x046B, 0x046D, 0x046D, 0x046F, 0x046F, + /* 7 */ 0x0471, 0x0471, 0x0473, 0x0473, 0x0475, 0x0475, 0x0476, 0x0477, + 0x0479, 0x0479, 0x047B, 0x047B, 0x047D, 0x047D, 0x047F, 0x047F, + /* 8 */ 0x0481, 0x0481, 0x0482, 0x0483, 0x0484, 0x0485, 0x0486, 0x0487, + 0x0488, 0x0489, 0x048A, 0x048B, 0x048C, 0x048D, 0x048E, 0x048F, + /* 9 */ 0x0491, 0x0491, 0x0493, 0x0493, 0x0495, 0x0495, 0x0497, 0x0497, + 0x0499, 0x0499, 0x049B, 0x049B, 0x049D, 0x049D, 0x049F, 0x049F, + /* A */ 0x04A1, 0x04A1, 0x04A3, 0x04A3, 0x04A5, 0x04A5, 0x04A7, 0x04A7, + 0x04A9, 0x04A9, 0x04AB, 0x04AB, 0x04AD, 0x04AD, 0x04AF, 0x04AF, + /* B */ 0x04B1, 0x04B1, 0x04B3, 0x04B3, 0x04B5, 0x04B5, 0x04B7, 0x04B7, + 0x04B9, 0x04B9, 0x04BB, 0x04BB, 0x04BD, 0x04BD, 0x04BF, 0x04BF, + /* C */ 0x04C0, 0x04C1, 0x04C2, 0x04C4, 0x04C4, 0x04C5, 0x04C6, 0x04C8, + 0x04C8, 0x04C9, 0x04CA, 0x04CC, 0x04CC, 0x04CD, 0x04CE, 0x04CF, + /* D */ 0x04D0, 0x04D1, 0x04D2, 0x04D3, 0x04D4, 0x04D5, 0x04D6, 0x04D7, + 0x04D8, 0x04D9, 0x04DA, 0x04DB, 0x04DC, 0x04DD, 0x04DE, 0x04DF, + /* E */ 0x04E0, 0x04E1, 0x04E2, 0x04E3, 0x04E4, 0x04E5, 0x04E6, 0x04E7, + 0x04E8, 0x04E9, 0x04EA, 0x04EB, 0x04EC, 0x04ED, 0x04EE, 0x04EF, + /* F */ 0x04F0, 0x04F1, 0x04F2, 0x04F3, 0x04F4, 0x04F5, 0x04F6, 0x04F7, + 0x04F8, 0x04F9, 0x04FA, 0x04FB, 0x04FC, 0x04FD, 0x04FE, 0x04FF, + + // Table 5 (for high byte 0x05) + + /* 0 */ 0x0500, 0x0501, 0x0502, 0x0503, 0x0504, 0x0505, 0x0506, 0x0507, + 0x0508, 0x0509, 0x050A, 0x050B, 0x050C, 0x050D, 0x050E, 0x050F, + /* 1 */ 0x0510, 0x0511, 0x0512, 0x0513, 0x0514, 0x0515, 0x0516, 0x0517, + 0x0518, 0x0519, 0x051A, 0x051B, 0x051C, 0x051D, 0x051E, 0x051F, + /* 2 */ 0x0520, 0x0521, 0x0522, 0x0523, 0x0524, 0x0525, 0x0526, 0x0527, + 0x0528, 0x0529, 0x052A, 0x052B, 0x052C, 0x052D, 0x052E, 0x052F, + /* 3 */ 0x0530, 0x0561, 0x0562, 0x0563, 0x0564, 0x0565, 0x0566, 0x0567, + 0x0568, 0x0569, 0x056A, 0x056B, 0x056C, 0x056D, 0x056E, 0x056F, + /* 4 */ 0x0570, 0x0571, 0x0572, 0x0573, 0x0574, 0x0575, 0x0576, 0x0577, + 0x0578, 0x0579, 0x057A, 0x057B, 0x057C, 0x057D, 0x057E, 0x057F, + /* 5 */ 0x0580, 0x0581, 0x0582, 0x0583, 0x0584, 0x0585, 0x0586, 0x0557, + 0x0558, 0x0559, 0x055A, 0x055B, 0x055C, 0x055D, 0x055E, 0x055F, + /* 6 */ 0x0560, 0x0561, 0x0562, 0x0563, 0x0564, 0x0565, 0x0566, 0x0567, + 0x0568, 0x0569, 0x056A, 0x056B, 0x056C, 0x056D, 0x056E, 0x056F, + /* 7 */ 0x0570, 0x0571, 0x0572, 0x0573, 0x0574, 0x0575, 0x0576, 0x0577, + 0x0578, 0x0579, 0x057A, 0x057B, 0x057C, 0x057D, 0x057E, 0x057F, + /* 8 */ 0x0580, 0x0581, 0x0582, 0x0583, 0x0584, 0x0585, 0x0586, 0x0587, + 0x0588, 0x0589, 0x058A, 0x058B, 0x058C, 0x058D, 0x058E, 0x058F, + /* 9 */ 0x0590, 0x0591, 0x0592, 0x0593, 0x0594, 0x0595, 0x0596, 0x0597, + 0x0598, 0x0599, 0x059A, 0x059B, 0x059C, 0x059D, 0x059E, 0x059F, + /* A */ 0x05A0, 0x05A1, 0x05A2, 0x05A3, 0x05A4, 0x05A5, 0x05A6, 0x05A7, + 0x05A8, 0x05A9, 0x05AA, 0x05AB, 0x05AC, 0x05AD, 0x05AE, 0x05AF, + /* B */ 0x05B0, 0x05B1, 0x05B2, 0x05B3, 0x05B4, 0x05B5, 0x05B6, 0x05B7, + 0x05B8, 0x05B9, 0x05BA, 0x05BB, 0x05BC, 0x05BD, 0x05BE, 0x05BF, + /* C */ 0x05C0, 0x05C1, 0x05C2, 0x05C3, 0x05C4, 0x05C5, 0x05C6, 0x05C7, + 0x05C8, 0x05C9, 0x05CA, 0x05CB, 0x05CC, 0x05CD, 0x05CE, 0x05CF, + /* D */ 0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, + 0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF, + /* E */ 0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7, + 0x05E8, 0x05E9, 0x05EA, 0x05EB, 0x05EC, 0x05ED, 0x05EE, 0x05EF, + /* F */ 0x05F0, 0x05F1, 0x05F2, 0x05F3, 0x05F4, 0x05F5, 0x05F6, 0x05F7, + 0x05F8, 0x05F9, 0x05FA, 0x05FB, 0x05FC, 0x05FD, 0x05FE, 0x05FF, + + // Table 6 (for high byte 0x10) + + /* 0 */ 0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, 0x1006, 0x1007, + 0x1008, 0x1009, 0x100A, 0x100B, 0x100C, 0x100D, 0x100E, 0x100F, + /* 1 */ 0x1010, 0x1011, 0x1012, 0x1013, 0x1014, 0x1015, 0x1016, 0x1017, + 0x1018, 0x1019, 0x101A, 0x101B, 0x101C, 0x101D, 0x101E, 0x101F, + /* 2 */ 0x1020, 0x1021, 0x1022, 0x1023, 0x1024, 0x1025, 0x1026, 0x1027, + 0x1028, 0x1029, 0x102A, 0x102B, 0x102C, 0x102D, 0x102E, 0x102F, + /* 3 */ 0x1030, 0x1031, 0x1032, 0x1033, 0x1034, 0x1035, 0x1036, 0x1037, + 0x1038, 0x1039, 0x103A, 0x103B, 0x103C, 0x103D, 0x103E, 0x103F, + /* 4 */ 0x1040, 0x1041, 0x1042, 0x1043, 0x1044, 0x1045, 0x1046, 0x1047, + 0x1048, 0x1049, 0x104A, 0x104B, 0x104C, 0x104D, 0x104E, 0x104F, + /* 5 */ 0x1050, 0x1051, 0x1052, 0x1053, 0x1054, 0x1055, 0x1056, 0x1057, + 0x1058, 0x1059, 0x105A, 0x105B, 0x105C, 0x105D, 0x105E, 0x105F, + /* 6 */ 0x1060, 0x1061, 0x1062, 0x1063, 0x1064, 0x1065, 0x1066, 0x1067, + 0x1068, 0x1069, 0x106A, 0x106B, 0x106C, 0x106D, 0x106E, 0x106F, + /* 7 */ 0x1070, 0x1071, 0x1072, 0x1073, 0x1074, 0x1075, 0x1076, 0x1077, + 0x1078, 0x1079, 0x107A, 0x107B, 0x107C, 0x107D, 0x107E, 0x107F, + /* 8 */ 0x1080, 0x1081, 0x1082, 0x1083, 0x1084, 0x1085, 0x1086, 0x1087, + 0x1088, 0x1089, 0x108A, 0x108B, 0x108C, 0x108D, 0x108E, 0x108F, + /* 9 */ 0x1090, 0x1091, 0x1092, 0x1093, 0x1094, 0x1095, 0x1096, 0x1097, + 0x1098, 0x1099, 0x109A, 0x109B, 0x109C, 0x109D, 0x109E, 0x109F, + /* A */ 0x10D0, 0x10D1, 0x10D2, 0x10D3, 0x10D4, 0x10D5, 0x10D6, 0x10D7, + 0x10D8, 0x10D9, 0x10DA, 0x10DB, 0x10DC, 0x10DD, 0x10DE, 0x10DF, + /* B */ 0x10E0, 0x10E1, 0x10E2, 0x10E3, 0x10E4, 0x10E5, 0x10E6, 0x10E7, + 0x10E8, 0x10E9, 0x10EA, 0x10EB, 0x10EC, 0x10ED, 0x10EE, 0x10EF, + /* C */ 0x10F0, 0x10F1, 0x10F2, 0x10F3, 0x10F4, 0x10F5, 0x10C6, 0x10C7, + 0x10C8, 0x10C9, 0x10CA, 0x10CB, 0x10CC, 0x10CD, 0x10CE, 0x10CF, + /* D */ 0x10D0, 0x10D1, 0x10D2, 0x10D3, 0x10D4, 0x10D5, 0x10D6, 0x10D7, + 0x10D8, 0x10D9, 0x10DA, 0x10DB, 0x10DC, 0x10DD, 0x10DE, 0x10DF, + /* E */ 0x10E0, 0x10E1, 0x10E2, 0x10E3, 0x10E4, 0x10E5, 0x10E6, 0x10E7, + 0x10E8, 0x10E9, 0x10EA, 0x10EB, 0x10EC, 0x10ED, 0x10EE, 0x10EF, + /* F */ 0x10F0, 0x10F1, 0x10F2, 0x10F3, 0x10F4, 0x10F5, 0x10F6, 0x10F7, + 0x10F8, 0x10F9, 0x10FA, 0x10FB, 0x10FC, 0x10FD, 0x10FE, 0x10FF, + + // Table 7 (for high byte 0x20) + + /* 0 */ 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007, + 0x2008, 0x2009, 0x200A, 0x200B, 0x0000, 0x0000, 0x0000, 0x0000, + /* 1 */ 0x2010, 0x2011, 0x2012, 0x2013, 0x2014, 0x2015, 0x2016, 0x2017, + 0x2018, 0x2019, 0x201A, 0x201B, 0x201C, 0x201D, 0x201E, 0x201F, + /* 2 */ 0x2020, 0x2021, 0x2022, 0x2023, 0x2024, 0x2025, 0x2026, 0x2027, + 0x2028, 0x2029, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x202F, + /* 3 */ 0x2030, 0x2031, 0x2032, 0x2033, 0x2034, 0x2035, 0x2036, 0x2037, + 0x2038, 0x2039, 0x203A, 0x203B, 0x203C, 0x203D, 0x203E, 0x203F, + /* 4 */ 0x2040, 0x2041, 0x2042, 0x2043, 0x2044, 0x2045, 0x2046, 0x2047, + 0x2048, 0x2049, 0x204A, 0x204B, 0x204C, 0x204D, 0x204E, 0x204F, + /* 5 */ 0x2050, 0x2051, 0x2052, 0x2053, 0x2054, 0x2055, 0x2056, 0x2057, + 0x2058, 0x2059, 0x205A, 0x205B, 0x205C, 0x205D, 0x205E, 0x205F, + /* 6 */ 0x2060, 0x2061, 0x2062, 0x2063, 0x2064, 0x2065, 0x2066, 0x2067, + 0x2068, 0x2069, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + /* 7 */ 0x2070, 0x2071, 0x2072, 0x2073, 0x2074, 0x2075, 0x2076, 0x2077, + 0x2078, 0x2079, 0x207A, 0x207B, 0x207C, 0x207D, 0x207E, 0x207F, + /* 8 */ 0x2080, 0x2081, 0x2082, 0x2083, 0x2084, 0x2085, 0x2086, 0x2087, + 0x2088, 0x2089, 0x208A, 0x208B, 0x208C, 0x208D, 0x208E, 0x208F, + /* 9 */ 0x2090, 0x2091, 0x2092, 0x2093, 0x2094, 0x2095, 0x2096, 0x2097, + 0x2098, 0x2099, 0x209A, 0x209B, 0x209C, 0x209D, 0x209E, 0x209F, + /* A */ 0x20A0, 0x20A1, 0x20A2, 0x20A3, 0x20A4, 0x20A5, 0x20A6, 0x20A7, + 0x20A8, 0x20A9, 0x20AA, 0x20AB, 0x20AC, 0x20AD, 0x20AE, 0x20AF, + /* B */ 0x20B0, 0x20B1, 0x20B2, 0x20B3, 0x20B4, 0x20B5, 0x20B6, 0x20B7, + 0x20B8, 0x20B9, 0x20BA, 0x20BB, 0x20BC, 0x20BD, 0x20BE, 0x20BF, + /* C */ 0x20C0, 0x20C1, 0x20C2, 0x20C3, 0x20C4, 0x20C5, 0x20C6, 0x20C7, + 0x20C8, 0x20C9, 0x20CA, 0x20CB, 0x20CC, 0x20CD, 0x20CE, 0x20CF, + /* D */ 0x20D0, 0x20D1, 0x20D2, 0x20D3, 0x20D4, 0x20D5, 0x20D6, 0x20D7, + 0x20D8, 0x20D9, 0x20DA, 0x20DB, 0x20DC, 0x20DD, 0x20DE, 0x20DF, + /* E */ 0x20E0, 0x20E1, 0x20E2, 0x20E3, 0x20E4, 0x20E5, 0x20E6, 0x20E7, + 0x20E8, 0x20E9, 0x20EA, 0x20EB, 0x20EC, 0x20ED, 0x20EE, 0x20EF, + /* F */ 0x20F0, 0x20F1, 0x20F2, 0x20F3, 0x20F4, 0x20F5, 0x20F6, 0x20F7, + 0x20F8, 0x20F9, 0x20FA, 0x20FB, 0x20FC, 0x20FD, 0x20FE, 0x20FF, + + // Table 8 (for high byte 0x21) + + /* 0 */ 0x2100, 0x2101, 0x2102, 0x2103, 0x2104, 0x2105, 0x2106, 0x2107, + 0x2108, 0x2109, 0x210A, 0x210B, 0x210C, 0x210D, 0x210E, 0x210F, + /* 1 */ 0x2110, 0x2111, 0x2112, 0x2113, 0x2114, 0x2115, 0x2116, 0x2117, + 0x2118, 0x2119, 0x211A, 0x211B, 0x211C, 0x211D, 0x211E, 0x211F, + /* 2 */ 0x2120, 0x2121, 0x2122, 0x2123, 0x2124, 0x2125, 0x2126, 0x2127, + 0x2128, 0x2129, 0x212A, 0x212B, 0x212C, 0x212D, 0x212E, 0x212F, + /* 3 */ 0x2130, 0x2131, 0x2132, 0x2133, 0x2134, 0x2135, 0x2136, 0x2137, + 0x2138, 0x2139, 0x213A, 0x213B, 0x213C, 0x213D, 0x213E, 0x213F, + /* 4 */ 0x2140, 0x2141, 0x2142, 0x2143, 0x2144, 0x2145, 0x2146, 0x2147, + 0x2148, 0x2149, 0x214A, 0x214B, 0x214C, 0x214D, 0x214E, 0x214F, + /* 5 */ 0x2150, 0x2151, 0x2152, 0x2153, 0x2154, 0x2155, 0x2156, 0x2157, + 0x2158, 0x2159, 0x215A, 0x215B, 0x215C, 0x215D, 0x215E, 0x215F, + /* 6 */ 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, 0x2177, + 0x2178, 0x2179, 0x217A, 0x217B, 0x217C, 0x217D, 0x217E, 0x217F, + /* 7 */ 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, 0x2177, + 0x2178, 0x2179, 0x217A, 0x217B, 0x217C, 0x217D, 0x217E, 0x217F, + /* 8 */ 0x2180, 0x2181, 0x2182, 0x2183, 0x2184, 0x2185, 0x2186, 0x2187, + 0x2188, 0x2189, 0x218A, 0x218B, 0x218C, 0x218D, 0x218E, 0x218F, + /* 9 */ 0x2190, 0x2191, 0x2192, 0x2193, 0x2194, 0x2195, 0x2196, 0x2197, + 0x2198, 0x2199, 0x219A, 0x219B, 0x219C, 0x219D, 0x219E, 0x219F, + /* A */ 0x21A0, 0x21A1, 0x21A2, 0x21A3, 0x21A4, 0x21A5, 0x21A6, 0x21A7, + 0x21A8, 0x21A9, 0x21AA, 0x21AB, 0x21AC, 0x21AD, 0x21AE, 0x21AF, + /* B */ 0x21B0, 0x21B1, 0x21B2, 0x21B3, 0x21B4, 0x21B5, 0x21B6, 0x21B7, + 0x21B8, 0x21B9, 0x21BA, 0x21BB, 0x21BC, 0x21BD, 0x21BE, 0x21BF, + /* C */ 0x21C0, 0x21C1, 0x21C2, 0x21C3, 0x21C4, 0x21C5, 0x21C6, 0x21C7, + 0x21C8, 0x21C9, 0x21CA, 0x21CB, 0x21CC, 0x21CD, 0x21CE, 0x21CF, + /* D */ 0x21D0, 0x21D1, 0x21D2, 0x21D3, 0x21D4, 0x21D5, 0x21D6, 0x21D7, + 0x21D8, 0x21D9, 0x21DA, 0x21DB, 0x21DC, 0x21DD, 0x21DE, 0x21DF, + /* E */ 0x21E0, 0x21E1, 0x21E2, 0x21E3, 0x21E4, 0x21E5, 0x21E6, 0x21E7, + 0x21E8, 0x21E9, 0x21EA, 0x21EB, 0x21EC, 0x21ED, 0x21EE, 0x21EF, + /* F */ 0x21F0, 0x21F1, 0x21F2, 0x21F3, 0x21F4, 0x21F5, 0x21F6, 0x21F7, + 0x21F8, 0x21F9, 0x21FA, 0x21FB, 0x21FC, 0x21FD, 0x21FE, 0x21FF, + + // Table 9 (for high byte 0xFE) + + /* 0 */ 0xFE00, 0xFE01, 0xFE02, 0xFE03, 0xFE04, 0xFE05, 0xFE06, 0xFE07, + 0xFE08, 0xFE09, 0xFE0A, 0xFE0B, 0xFE0C, 0xFE0D, 0xFE0E, 0xFE0F, + /* 1 */ 0xFE10, 0xFE11, 0xFE12, 0xFE13, 0xFE14, 0xFE15, 0xFE16, 0xFE17, + 0xFE18, 0xFE19, 0xFE1A, 0xFE1B, 0xFE1C, 0xFE1D, 0xFE1E, 0xFE1F, + /* 2 */ 0xFE20, 0xFE21, 0xFE22, 0xFE23, 0xFE24, 0xFE25, 0xFE26, 0xFE27, + 0xFE28, 0xFE29, 0xFE2A, 0xFE2B, 0xFE2C, 0xFE2D, 0xFE2E, 0xFE2F, + /* 3 */ 0xFE30, 0xFE31, 0xFE32, 0xFE33, 0xFE34, 0xFE35, 0xFE36, 0xFE37, + 0xFE38, 0xFE39, 0xFE3A, 0xFE3B, 0xFE3C, 0xFE3D, 0xFE3E, 0xFE3F, + /* 4 */ 0xFE40, 0xFE41, 0xFE42, 0xFE43, 0xFE44, 0xFE45, 0xFE46, 0xFE47, + 0xFE48, 0xFE49, 0xFE4A, 0xFE4B, 0xFE4C, 0xFE4D, 0xFE4E, 0xFE4F, + /* 5 */ 0xFE50, 0xFE51, 0xFE52, 0xFE53, 0xFE54, 0xFE55, 0xFE56, 0xFE57, + 0xFE58, 0xFE59, 0xFE5A, 0xFE5B, 0xFE5C, 0xFE5D, 0xFE5E, 0xFE5F, + /* 6 */ 0xFE60, 0xFE61, 0xFE62, 0xFE63, 0xFE64, 0xFE65, 0xFE66, 0xFE67, + 0xFE68, 0xFE69, 0xFE6A, 0xFE6B, 0xFE6C, 0xFE6D, 0xFE6E, 0xFE6F, + /* 7 */ 0xFE70, 0xFE71, 0xFE72, 0xFE73, 0xFE74, 0xFE75, 0xFE76, 0xFE77, + 0xFE78, 0xFE79, 0xFE7A, 0xFE7B, 0xFE7C, 0xFE7D, 0xFE7E, 0xFE7F, + /* 8 */ 0xFE80, 0xFE81, 0xFE82, 0xFE83, 0xFE84, 0xFE85, 0xFE86, 0xFE87, + 0xFE88, 0xFE89, 0xFE8A, 0xFE8B, 0xFE8C, 0xFE8D, 0xFE8E, 0xFE8F, + /* 9 */ 0xFE90, 0xFE91, 0xFE92, 0xFE93, 0xFE94, 0xFE95, 0xFE96, 0xFE97, + 0xFE98, 0xFE99, 0xFE9A, 0xFE9B, 0xFE9C, 0xFE9D, 0xFE9E, 0xFE9F, + /* A */ 0xFEA0, 0xFEA1, 0xFEA2, 0xFEA3, 0xFEA4, 0xFEA5, 0xFEA6, 0xFEA7, + 0xFEA8, 0xFEA9, 0xFEAA, 0xFEAB, 0xFEAC, 0xFEAD, 0xFEAE, 0xFEAF, + /* B */ 0xFEB0, 0xFEB1, 0xFEB2, 0xFEB3, 0xFEB4, 0xFEB5, 0xFEB6, 0xFEB7, + 0xFEB8, 0xFEB9, 0xFEBA, 0xFEBB, 0xFEBC, 0xFEBD, 0xFEBE, 0xFEBF, + /* C */ 0xFEC0, 0xFEC1, 0xFEC2, 0xFEC3, 0xFEC4, 0xFEC5, 0xFEC6, 0xFEC7, + 0xFEC8, 0xFEC9, 0xFECA, 0xFECB, 0xFECC, 0xFECD, 0xFECE, 0xFECF, + /* D */ 0xFED0, 0xFED1, 0xFED2, 0xFED3, 0xFED4, 0xFED5, 0xFED6, 0xFED7, + 0xFED8, 0xFED9, 0xFEDA, 0xFEDB, 0xFEDC, 0xFEDD, 0xFEDE, 0xFEDF, + /* E */ 0xFEE0, 0xFEE1, 0xFEE2, 0xFEE3, 0xFEE4, 0xFEE5, 0xFEE6, 0xFEE7, + 0xFEE8, 0xFEE9, 0xFEEA, 0xFEEB, 0xFEEC, 0xFEED, 0xFEEE, 0xFEEF, + /* F */ 0xFEF0, 0xFEF1, 0xFEF2, 0xFEF3, 0xFEF4, 0xFEF5, 0xFEF6, 0xFEF7, + 0xFEF8, 0xFEF9, 0xFEFA, 0xFEFB, 0xFEFC, 0xFEFD, 0xFEFE, 0x0000, + + // Table 10 (for high byte 0xFF) + + /* 0 */ 0xFF00, 0xFF01, 0xFF02, 0xFF03, 0xFF04, 0xFF05, 0xFF06, 0xFF07, + 0xFF08, 0xFF09, 0xFF0A, 0xFF0B, 0xFF0C, 0xFF0D, 0xFF0E, 0xFF0F, + /* 1 */ 0xFF10, 0xFF11, 0xFF12, 0xFF13, 0xFF14, 0xFF15, 0xFF16, 0xFF17, + 0xFF18, 0xFF19, 0xFF1A, 0xFF1B, 0xFF1C, 0xFF1D, 0xFF1E, 0xFF1F, + /* 2 */ 0xFF20, 0xFF41, 0xFF42, 0xFF43, 0xFF44, 0xFF45, 0xFF46, 0xFF47, + 0xFF48, 0xFF49, 0xFF4A, 0xFF4B, 0xFF4C, 0xFF4D, 0xFF4E, 0xFF4F, + /* 3 */ 0xFF50, 0xFF51, 0xFF52, 0xFF53, 0xFF54, 0xFF55, 0xFF56, 0xFF57, + 0xFF58, 0xFF59, 0xFF5A, 0xFF3B, 0xFF3C, 0xFF3D, 0xFF3E, 0xFF3F, + /* 4 */ 0xFF40, 0xFF41, 0xFF42, 0xFF43, 0xFF44, 0xFF45, 0xFF46, 0xFF47, + 0xFF48, 0xFF49, 0xFF4A, 0xFF4B, 0xFF4C, 0xFF4D, 0xFF4E, 0xFF4F, + /* 5 */ 0xFF50, 0xFF51, 0xFF52, 0xFF53, 0xFF54, 0xFF55, 0xFF56, 0xFF57, + 0xFF58, 0xFF59, 0xFF5A, 0xFF5B, 0xFF5C, 0xFF5D, 0xFF5E, 0xFF5F, + /* 6 */ 0xFF60, 0xFF61, 0xFF62, 0xFF63, 0xFF64, 0xFF65, 0xFF66, 0xFF67, + 0xFF68, 0xFF69, 0xFF6A, 0xFF6B, 0xFF6C, 0xFF6D, 0xFF6E, 0xFF6F, + /* 7 */ 0xFF70, 0xFF71, 0xFF72, 0xFF73, 0xFF74, 0xFF75, 0xFF76, 0xFF77, + 0xFF78, 0xFF79, 0xFF7A, 0xFF7B, 0xFF7C, 0xFF7D, 0xFF7E, 0xFF7F, + /* 8 */ 0xFF80, 0xFF81, 0xFF82, 0xFF83, 0xFF84, 0xFF85, 0xFF86, 0xFF87, + 0xFF88, 0xFF89, 0xFF8A, 0xFF8B, 0xFF8C, 0xFF8D, 0xFF8E, 0xFF8F, + /* 9 */ 0xFF90, 0xFF91, 0xFF92, 0xFF93, 0xFF94, 0xFF95, 0xFF96, 0xFF97, + 0xFF98, 0xFF99, 0xFF9A, 0xFF9B, 0xFF9C, 0xFF9D, 0xFF9E, 0xFF9F, + /* A */ 0xFFA0, 0xFFA1, 0xFFA2, 0xFFA3, 0xFFA4, 0xFFA5, 0xFFA6, 0xFFA7, + 0xFFA8, 0xFFA9, 0xFFAA, 0xFFAB, 0xFFAC, 0xFFAD, 0xFFAE, 0xFFAF, + /* B */ 0xFFB0, 0xFFB1, 0xFFB2, 0xFFB3, 0xFFB4, 0xFFB5, 0xFFB6, 0xFFB7, + 0xFFB8, 0xFFB9, 0xFFBA, 0xFFBB, 0xFFBC, 0xFFBD, 0xFFBE, 0xFFBF, + /* C */ 0xFFC0, 0xFFC1, 0xFFC2, 0xFFC3, 0xFFC4, 0xFFC5, 0xFFC6, 0xFFC7, + 0xFFC8, 0xFFC9, 0xFFCA, 0xFFCB, 0xFFCC, 0xFFCD, 0xFFCE, 0xFFCF, + /* D */ 0xFFD0, 0xFFD1, 0xFFD2, 0xFFD3, 0xFFD4, 0xFFD5, 0xFFD6, 0xFFD7, + 0xFFD8, 0xFFD9, 0xFFDA, 0xFFDB, 0xFFDC, 0xFFDD, 0xFFDE, 0xFFDF, + /* E */ 0xFFE0, 0xFFE1, 0xFFE2, 0xFFE3, 0xFFE4, 0xFFE5, 0xFFE6, 0xFFE7, + 0xFFE8, 0xFFE9, 0xFFEA, 0xFFEB, 0xFFEC, 0xFFED, 0xFFEE, 0xFFEF, + /* F */ 0xFFF0, 0xFFF1, 0xFFF2, 0xFFF3, 0xFFF4, 0xFFF5, 0xFFF6, 0xFFF7, + 0xFFF8, 0xFFF9, 0xFFFA, 0xFFFB, 0xFFFC, 0xFFFD, 0xFFFE, 0xFFFF, +}; diff --git a/qemu/roms/openbios/fs/hfsplus/hfsp_volume.c b/qemu/roms/openbios/fs/hfsplus/hfsp_volume.c new file mode 100644 index 000000000..2d624e23e --- /dev/null +++ b/qemu/roms/openbios/fs/hfsplus/hfsp_volume.c @@ -0,0 +1,323 @@ +/* + * libhfs - library for reading and writing Macintosh HFS volumes + * + * Code to acces the basic volume information of a HFS+ volume. + * + * Copyright (C) 2000 Klaus Halfmann <khalfmann@libra.de> + * Original work by 1996-1998 Robert Leslie <rob@mars.org> + * other work 2000 from Brad Boyer (flar@pants.nu) + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * $Id: volume.c,v 1.21 2000/10/25 05:43:04 hasi Exp $ + */ + +#include "config.h" +#include "libhfsp.h" +#include "volume.h" +#include "record.h" +#include "btree.h" +#include "blockiter.h" +#include "os.h" +#include "swab.h" +#include "hfstime.h" + + +/* Fill a given buffer with the given block in volume. + */ +int +volume_readinbuf(volume * vol,void* buf, long block) +{ + UInt16 blksize_bits; + ASSERT( block < vol->maxblocks); + + blksize_bits = vol->blksize_bits; + block += vol->startblock; + if( os_seek(vol->os_fd, block, blksize_bits) == block) + if( 1 == os_read(vol->os_fd, buf, 1, blksize_bits)) + return 0; + return -1; +} + +/* read multiple blocks into given memory. + * + * returns given pinter or NULL on failure. + */ +void* +volume_readfromfork(volume* vol, void* buf, + hfsp_fork_raw* f, UInt32 block, + UInt32 count, UInt8 forktype, UInt32 fileId) +{ + blockiter iter; + char *cbuf = buf; + + blockiter_init(&iter, vol, f, forktype, fileId); + if( blockiter_skip(&iter, block)) + return NULL; + + while( count > 0) { + --count; + if( volume_readinbuf(vol, cbuf, blockiter_curr(&iter))) + return NULL; + cbuf += vol->blksize; + if( count > 0 && blockiter_next(&iter)) + return NULL; + } + return buf; +} + + +/* Read a raw hfsp_extent_rec from memory. + * + * return pointer right after the structure. + */ +void* +volume_readextent(void *p, hfsp_extent_rec er) +{ + int i; + hfsp_extent *e; + + for( i=0; i < 8; i++) { + e = &er[i]; + e->start_block = bswabU32_inc(p); + e->block_count = bswabU32_inc(p); + } + return p; +} + +/* Read a raw hfsp_fork from memory. + * + * return pointer right after the structure. + */ +void* +volume_readfork(void *p, hfsp_fork_raw* f) +{ + f->total_size = bswabU64_inc(p); + f->clump_size = bswabU32_inc(p); + f->total_blocks = bswabU32_inc(p); + + return volume_readextent(p, f->extents); +} + +/* Read the volume from the given buffer and swap the bytes. + * + * ToDo: add more consitency checks. + */ +static int +volume_readbuf(hfsp_vh* vh, char * p) +{ + if( (vh->signature = bswabU16_inc(p)) != HFSP_VOLHEAD_SIG) + HFSP_ERROR(-1, "This is not a HFS+ volume"); + + vh->version = bswabU16_inc(p); + vh->attributes = bswabU32_inc(p); + vh->last_mount_vers = bswabU32_inc(p); + vh->reserved = bswabU32_inc(p); + vh->create_date = bswabU32_inc(p); + vh->modify_date = bswabU32_inc(p); + vh->backup_date = bswabU32_inc(p); + vh->checked_date = bswabU32_inc(p); + vh->file_count = bswabU32_inc(p); + vh->folder_count = bswabU32_inc(p); + vh->blocksize = bswabU32_inc(p); + vh->total_blocks = bswabU32_inc(p); + vh->free_blocks = bswabU32_inc(p); + vh->next_alloc = bswabU32_inc(p); + vh->rsrc_clump_sz = bswabU32_inc(p); + vh->data_clump_sz = bswabU32_inc(p); + vh->next_cnid = bswabU32_inc(p); + vh->write_count = bswabU32_inc(p); + vh->encodings_bmp = bswabU64_inc(p); + memcpy(vh->finder_info, p, 32); + p += 32; // So finderinfo must be swapped later, *** + p = volume_readfork(p, &vh->alloc_file ); + p = volume_readfork(p, &vh->ext_file ); + p = volume_readfork(p, &vh->cat_file ); + p = volume_readfork(p, &vh->attr_file ); + volume_readfork(p, &vh->start_file ); + return 0; + fail: + return -1; +} + +/* Read the volume from the given block */ +static int +volume_read(volume * vol, hfsp_vh* vh, UInt32 block) +{ + char buf[vol->blksize]; + + if( volume_readinbuf(vol, buf, block)) + return -1; + return volume_readbuf(vh, buf); +} + +/* Find out wether the volume is wrapped and unwrap it eventually */ +static int +volume_read_wrapper(volume * vol, hfsp_vh* vh) +{ + UInt16 signature; + char buf[vol->blksize]; + char *p = buf; + int ret; + UInt64 vol_size; + + if( volume_readinbuf(vol, buf, 2) ) // Wrapper or volume header starts here + return -1; + + signature = bswabU16_inc(p); + if( signature == HFS_VOLHEAD_SIG) { /* Wrapper */ + UInt32 drAlBlkSiz; /* size (in bytes) of allocation blocks */ + UInt32 sect_per_block; /* how may block build an hfs sector */ + UInt16 drAlBlSt; /* first allocation block in volume */ + UInt16 embeds, embedl; /* Start/lenght of embedded area in blocks */ + + p += 0x12; /* skip unneded HFS vol fields */ + drAlBlkSiz = bswabU32_inc(p); /* offset 0x14 */ + p += 0x4; /* skip unneded HFS vol fields */ + drAlBlSt = bswabU16_inc(p); /* offset 0x1C */ + + p += 0x5E; /* skip unneded HFS vol fields */ + signature = bswabU16_inc(p); /* offset 0x7C, drEmbedSigWord */ + if( signature != HFSP_VOLHEAD_SIG) + HFSP_ERROR(-1, "This looks like a normal HFS volume"); + embeds = bswabU16_inc(p); + embedl = bswabU16_inc(p); + sect_per_block = (drAlBlkSiz / HFSP_BLOCKSZ); + // end is absolute (not relative to HFS+ start) + vol->maxblocks = embedl * sect_per_block; + vol->startblock = drAlBlSt + embeds * sect_per_block; + /* Now we can try to read the embedded HFS+ volume header */ + return volume_read(vol,vh,2); + } + else if( signature == HFSP_VOLHEAD_SIG) { /* Native HFS+ volume */ + p = buf; // Restore to begin of block + ret = volume_readbuf(vh, p); + if( !ret ) { + /* When reading the initial partition we must use 512 byte blocks */ + vol_size = (uint64_t)vh->blocksize * vh->total_blocks; + vol->maxblocks = vol_size / HFSP_BLOCKSZ; + } + + return ret; + } else + HFSP_ERROR(-1, "Neither Wrapper nor native HFS+ volume header found"); +fail: + return -1; +} + + +/* Open the device, read and verify the volume header + (and its backup) */ +int +volume_open( volume* vol, int os_fd ) +{ + hfsp_vh backup; /* backup volume found at second to last block */ + long sect_per_block; + int shift; + + vol->blksize_bits = HFSP_BLOCKSZ_BITS; + vol->blksize = HFSP_BLOCKSZ; + vol->startblock = 0; + vol->maxblocks = 3; + /* this should be enough until we find the volume descriptor */ + vol->extents = NULL; /* Thanks to Jeremias Sauceda */ + + btree_reset(&vol->catalog); + vol->os_fd = os_fd; + + // vol->maxblocks = os_seek(vol->os_fd, -1, HFSP_BLOCKSZ_BITS); + // This wont work for /dev/... but we do not really need it + + if( volume_read_wrapper(vol, &vol->vol)) + return -1; + if( volume_read(vol, &backup, vol->maxblocks - 2)) + return -1; + + /* Now switch blksize from HFSP_BLOCKSZ (512) to value given in header + and adjust depend values accordingly, after that a block always + means a HFS+ allocation size */ + + /* Usually 4096 / 512 == 8 */ + sect_per_block = vol->vol.blocksize / HFSP_BLOCKSZ; + shift = 0; + if( sect_per_block > 1) { + shift = 1; + while( sect_per_block > 2) { + sect_per_block >>=1; + shift++; + } /* shift = 3 */ + } + vol -> blksize_bits += shift; + vol -> blksize = 1 << vol->blksize_bits; + vol -> startblock >>= shift; + vol -> maxblocks = vol->vol.total_blocks; /* cant calculate via shift ? */ + + if( btree_init_cat(&vol->catalog, vol, &vol->vol.cat_file)) + return -1; + + return 0; +} + +/* Write back all data eventually cached and close the device */ +int +volume_close(volume* vol) +{ + btree_close(&vol->catalog); + if( vol->extents) { + btree_close(vol->extents); + FREE(vol->extents); + } + return 0; +} + +/* internal fucntion used to create the extents btree, + is called by inline function when needed */ +void +volume_create_extents_tree(volume* vol) +{ + btree* result = (btree*) ALLOC(btree*, sizeof(btree)); + if( !result) + HFSP_ERROR(ENOMEM, "No memory for extents btree"); + if( !btree_init_extent(result, vol, &vol->vol.ext_file)) { + vol->extents = result; + return; + } + fail: + vol->extents = NULL; +} + +/* Determine whether the volume is a HFS-plus volume */ +int +volume_probe(int fd, long long offset) +{ + UInt16 *vol; + int ret = 0; + + vol = (UInt16 *)malloc(2 * 1 << HFSP_BLOCKSZ_BITS); + os_seek_offset( fd, 2 * (1 << HFSP_BLOCKSZ_BITS) + offset ); + os_read(fd, vol, 2, HFSP_BLOCKSZ_BITS); + + if (__be16_to_cpu(vol[0]) == HFS_VOLHEAD_SIG && + __be16_to_cpu(vol[0x3e]) == HFSP_VOLHEAD_SIG) { + ret = -1; + } else if (__be16_to_cpu(vol[0]) == HFSP_VOLHEAD_SIG) { + ret = -1; + } + + free(vol); + return ret; +} + diff --git a/qemu/roms/openbios/fs/hfsplus/include/apple.h b/qemu/roms/openbios/fs/hfsplus/include/apple.h new file mode 100644 index 000000000..7ba836db6 --- /dev/null +++ b/qemu/roms/openbios/fs/hfsplus/include/apple.h @@ -0,0 +1,111 @@ +/* + * libhfsp - library for reading and writing Macintosh HFS+ volumes + * + * This file contains defintions that are special for Apple. + * The names match the defintions found in Apple Header files. + * + * Copyright (C) 2000 Klaus Halfmann <khalfmann@libra.de> + * Original code 1996-1998 by Robert Leslie <rob@mars.rog> + * other work 2000 from Brad Boyer (flar@pants.nu) + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * $Id: apple.h,v 1.2 2000/09/08 14:55:08 hasi Exp $ + */ + +typedef signed char Char; +typedef unsigned char UChar; +typedef signed char SInt8; +typedef unsigned char UInt8; +typedef signed short SInt16; +typedef unsigned short UInt16; +typedef signed long SInt32; +typedef unsigned long UInt32; +typedef unsigned long OSType; +typedef unsigned long long UInt64; + +/* A point, normally used by Quickdraw, + * but found in Finderinformation, too + */ +typedef struct { + SInt16 v; /* vertical coordinate */ + SInt16 h; /* horizontal coordinate */ +} Point; + +/* A rectancle, normally used by Quickdraw, + * but found in Finderinformation, too. + */ +typedef struct { + SInt16 top; /* top edge of rectangle */ + SInt16 left; /* left edge */ + SInt16 bottom; /* bottom edge */ + SInt16 right; /* right edge */ +} Rect; + +/* Information about the location and size of a folder + * used by the Finder. + */ +typedef struct { + Rect frRect; /* folder's rectangle */ + SInt16 frFlags; /* flags */ + Point frLocation; /* folder's location */ + SInt16 frView; /* folder's view */ +} DInfo; + +/* Extended folder information used by the Finder ... + */ +typedef struct { + Point frScroll; /* scroll position */ + SInt32 frOpenChain; /* directory ID chain of open folders */ + SInt16 frUnused; /* reserved */ + SInt16 frComment; /* comment ID */ + SInt32 frPutAway; /* directory ID */ +} DXInfo; + +/* Finder information for a File + */ +typedef struct { + OSType fdType; /* file type */ + OSType fdCreator; /* file's creator */ + SInt16 fdFlags; /* flags */ + Point fdLocation; /* file's location */ + SInt16 fdFldr; /* file's window */ +} FInfo; + +/* Extendend Finder Information for a file + */ +typedef struct { + SInt16 fdIconID; /* icon ID */ + SInt16 fdUnused[4]; /* reserved */ + SInt16 fdComment; /* comment ID */ + SInt32 fdPutAway; /* home directory ID */ +} FXInfo; + +/* Flagvalues for FInfo and DInfo */ +# define HFS_FNDR_ISONDESK (1 << 0) +# define HFS_FNDR_COLOR 0x0e +# define HFS_FNDR_COLORRESERVED (1 << 4) +# define HFS_FNDR_REQUIRESSWITCHLAUNCH (1 << 5) +# define HFS_FNDR_ISSHARED (1 << 6) +# define HFS_FNDR_HASNOINITS (1 << 7) +# define HFS_FNDR_HASBEENINITED (1 << 8) +# define HFS_FNDR_RESERVED (1 << 9) +# define HFS_FNDR_HASCUSTOMICON (1 << 10) +# define HFS_FNDR_ISSTATIONERY (1 << 11) +# define HFS_FNDR_NAMELOCKED (1 << 12) +# define HFS_FNDR_HASBUNDLE (1 << 13) +# define HFS_FNDR_ISINVISIBLE (1 << 14) +# define HFS_FNDR_ISALIAS (1 << 15) diff --git a/qemu/roms/openbios/fs/hfsplus/include/blockiter.h b/qemu/roms/openbios/fs/hfsplus/include/blockiter.h new file mode 100644 index 000000000..da3e480fd --- /dev/null +++ b/qemu/roms/openbios/fs/hfsplus/include/blockiter.h @@ -0,0 +1,59 @@ +/* + * libhfs - library for reading and writing Macintosh HFS volumes + * + * The iterator shown here iterates over the blocks of a fork. + * + * Copyright (C) 2000 Klaus Halfmann <khalfmann@libra.de> + * Original work by 1996-1998 Robert Leslie <rob@mars.org> + * other work 2000 from Brad Boyer (flar@pants.nu) + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * $Id: blockiter.h,v 1.1 2000/10/10 11:14:05 hasi Exp $ + */ + +/* Structure of the blockiterator */ +typedef struct +{ + volume* vol; // volume we iterate over + UInt32 curr_block; // current, absolute block + UInt32 block; // relative block in current extent + UInt32 max_block; // Maximum allowed block + UInt32 fileId; // id of file we iterate over + int index; // 0 .. 7 in current extent + hfsp_extent* file; // original extent record from file + hfsp_extent* e; // current extentent under examination + UInt8 forktype; // type of fork we iterate over + UInt8 in_extent; // boolean 0 - in file extent + // 1 - in extents file + extent_record er; // record to iterate in extents file. +} blockiter; + +/* Initialize iterator for a given fork */ +extern void blockiter_init(blockiter* b, volume* vol, hfsp_fork_raw* f, + UInt8 forktype, UInt32 fileId); + +/* find next block of the fork iterating over */ +extern int blockiter_next(blockiter *b); + +/* skip the indicated number of blocks */ +extern int blockiter_skip(blockiter *b, UInt32 skip); + +/* return current block */ +static inline UInt32 blockiter_curr(blockiter *b) +{ + return b->e->start_block + b->block; +} diff --git a/qemu/roms/openbios/fs/hfsplus/include/btree.h b/qemu/roms/openbios/fs/hfsplus/include/btree.h new file mode 100644 index 000000000..46ac8501f --- /dev/null +++ b/qemu/roms/openbios/fs/hfsplus/include/btree.h @@ -0,0 +1,50 @@ +/* + * libhfs - library for reading and writing Macintosh HFS volumes. + * + * The fucntions are used to handle the various forms of btrees + * found on HFS+ volumes. + * + * Copyright (C) 2000 Klaus Halfmann <khalfmann@libra.de> + * Original 1996-1998 Robert Leslie <rob@mars.org> + * Additional work by Brad Boyer (flar@pants.nu) + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * $Id: btree.h,v 1.10 2000/10/25 05:43:04 hasi Exp $ + */ + +/** Intialize catalog btree, so that btree_close can safely be called. */ +extern void btree_reset(btree* bt); + +/** Intialize catalog btree */ +extern int btree_init_cat(btree* bt, volume* vol, hfsp_fork_raw* fork); + +/** Intialize extents btree */ +extern int btree_init_extent(btree* bt, volume* vol, hfsp_fork_raw* fork); + +/** close the btree and free any resources */ +extern void btree_close(btree* bt); + +/* Read node at given index */ +extern node_buf* btree_node_by_index(btree* bt, UInt16 index); + +/* returns pointer to key given by index in current node */ +extern void* btree_key_by_index(btree* bt, node_buf* buf, UInt16 index); + +#ifdef DEBUG + /* Dump all the btree information to stdout */ + extern void btree_print(btree* bt); +#endif diff --git a/qemu/roms/openbios/fs/hfsplus/include/hfs.h b/qemu/roms/openbios/fs/hfsplus/include/hfs.h new file mode 100644 index 000000000..5b0cbb490 --- /dev/null +++ b/qemu/roms/openbios/fs/hfsplus/include/hfs.h @@ -0,0 +1,32 @@ +/* + * libhfsp - library for reading and writing Macintosh HFS+ volumes + * + * This file includes definitions for access to old HFS structures. + * + * Copyright (C) 2000 Klaus Halfmann <khalfmann@libra.de> + * Original code 1996-1998 by Robert Leslie <rob@mars.rog> + * other work 2000 from Brad Boyer (flar@pants.nu) + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * $Id: hfs.h,v 1.1.1.1 2000/07/25 10:33:40 kkaempf Exp $ + */ + + +#define HFS_BLOCKSZ 512 + /* A sector for Apple is always 512 bytes */ +#define HFS_BLOCKSZ_BITS 9 /* 1<<9 == 512 */ +#define HFS_VOLHEAD_SIG 0x4244 /* 'BD' */ diff --git a/qemu/roms/openbios/fs/hfsplus/include/hfsp.h b/qemu/roms/openbios/fs/hfsplus/include/hfsp.h new file mode 100644 index 000000000..e916473c6 --- /dev/null +++ b/qemu/roms/openbios/fs/hfsplus/include/hfsp.h @@ -0,0 +1,305 @@ +/* + * libhfsp - library for reading and writing Macintosh HFS+ volumes + * + * This file includes definitions for the structures found on + * HFS+ Volumes. The structures are further wrapped by struct + * found in libhfsp.h. fucntions on those enhanced structures + * are found in files mentioned in comments below. + * + * Copyright (C) 2000 Klaus Halfmann <khalfmann@libra.de> + * Original code 1996-1998 by Robert Leslie <rob@mars.rog> + * other work 2000 from Brad Boyer (flar@pants.nu) + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * $Id: hfsp.h,v 1.17 2000/10/20 06:16:52 hasi Exp $ + */ + +#define HFSP_BLOCKSZ 512 /* A sector for Apple is always 512 bytes */ +#define HFSP_BLOCKSZ_BITS 9 /* 1<<9 == 512 */ +#define HFSP_VOLHEAD_SIG 0x482B /* 'H+' */ + +/* HFS+ includes POSIX permissions , although marked as reserved they will be + * used as such. Is ignored by MacOS 8-9 but probably not by MacOS X. + */ +typedef struct { + UInt32 owner; + UInt32 group; + UInt32 mode; + UInt32 dev; +} hfsp_perm; + +/* A single contiguous area (fragment) of a file */ +typedef struct { + UInt32 start_block; + UInt32 block_count; +} hfsp_extent; + +/* A file may contain up to 8 normale extents, all other + are found in some extra extent area */ +typedef hfsp_extent hfsp_extent_rec[8]; + +/* Information for a "Fork" in a file + * Forks are the "usual" DATA and RSRC forks or special files + * (e.g. the Volume Bitmap) + */ +typedef struct { + UInt64 total_size; // logical size + UInt32 clump_size; // number of bytes to preallocate + UInt32 total_blocks; + hfsp_extent_rec extents; // initial (8) extents +} hfsp_fork_raw; + +/* HFS+ Volume Header + * Always found at block 2 of the disk, a copy is stored + * at the second to last block of the disk. + */ +typedef struct hfsp_vh { + UInt16 signature; // must be HFSPLUS_VOLHEAD_SIG 'H+' + UInt16 version; // currently 4, ignored + UInt32 attributes; // See bit constants below + UInt32 last_mount_vers; + // Use a registered creator code here (what do we use ?) + // Mac OS uses '8.10' well + UInt32 reserved; + + UInt32 create_date; // local time ! + UInt32 modify_date; // GMT (?) + UInt32 backup_date; // GMT (?) + UInt32 checked_date; // GMT (?) fsck ? + + UInt32 file_count; + // not including special files but including DATA and RSRC forks + UInt32 folder_count; // excluding the root folder + + UInt32 blocksize; + // must be multiple of HFSPLUS_SECTOR_SIZE, + // should be a multiple of 4k for harddisk + UInt32 total_blocks; + UInt32 free_blocks; + // The total number of unused allocation blocks on the disk. + + UInt32 next_alloc; + // hint wher to search for next allocation blocks + UInt32 rsrc_clump_sz; + // default clump size for rsrc forks + UInt32 data_clump_sz; + // default clump size for data forks + UInt32 next_cnid; + // next unused catalog id + UInt32 write_count; + // increment on every mount (and write ?) + UInt64 encodings_bmp; + // for every encoding used on the disk a bit is set + // ignored but eventually must be cared for + Char finder_info[32]; + hfsp_fork_raw alloc_file; + // stores bitmap of use/free blocks + hfsp_fork_raw ext_file; + // stores oferflow extents + hfsp_fork_raw cat_file; + // This contains the root directory + hfsp_fork_raw attr_file; + hfsp_fork_raw start_file; + // a special startup file may be described here (used by ?) +} hfsp_vh; + +/* HFS+ volume attributes */ +/* 0-6 reserved, may be used in memory only */ +#define HFSPLUS_VOL_RESERVED1 0x000000FF +#define HFSPLUS_VOL_HARDLOCK 0x00000080 // Used in Memory by finder only +#define HFSPLUS_VOL_UNMNT 0x00000100 + // clear this bit when mounting, set as last step of unmounting + // This is checked by (slower) ROM code +#define HFSPLUS_VOL_SPARE_BLK 0x00000200 +#define HFSPLUS_VOL_NOCACHE 0x00000400 + // in case of RAM or ROM disk (try a HFS+ Ramdisk :) +#define HFSPLUS_VOL_INCNSTNT 0x00000800 + // Reverse meaning as of HFSPLUS_VOL_UNMNT + // This is checked by (faster) Mac OS code +/* 12-14 reserved */ +#define HFSPLUS_VOL_RESERVED2 0x00007000 +#define HFSPLUS_VOL_SOFTLOCK 0x00008000 +#define HFSPLUS_VOL_RESERVED3 0xFFFF0000 + +/* HFS+ Btree node descriptor */ +typedef struct { + UInt32 next; /* pointer to next node of this kind, or 0 */ + UInt32 prev; /* pointer to previous node of this kind, or 0 */ + UInt8 kind; /* see below */ + UInt8 height; /* root node starts with 0 */ + UInt16 num_rec; /* number of records in this node */ + UInt16 reserved; /* fill up to 4 byte alignment */ +} btree_node_desc; + +/* HFS+ Btree Node types */ +#define HFSP_NODE_NDX 0x00 +#define HFSP_NODE_HEAD 0x01 +#define HFSP_NODE_MAP 0x02 +#define HFSP_NODE_LEAF 0xFF + +#define HFSP_CATALOG_MIN_NODE_SIZE 0x1000 +#define HFSP_ATTRMIN_DOE_SIZE 0x1000 + +/* The record offsets are found at the end of the fork + * containing the Btree */ + +typedef UInt16 btree_record_offset; + +typedef struct { + UInt16 depth; + // equal to height of btree_node_desc + UInt32 root; + // root node of the hierarchy + UInt32 leaf_count; + UInt32 leaf_head; + UInt32 leaf_tail; + UInt16 node_size; + // node size of _all_ nodes in this fork + UInt16 max_key_len; + UInt32 node_count; + // count of all (free and used) nodes in tree + UInt32 free_nodes; + UInt16 reserved1; + UInt32 clump_size; + // ignored my MacOS used by ? + UInt8 btree_type; + // always 0 for HFS+ + UInt8 reserved2; + UInt32 attributes; + // see below + UInt32 reserved3[16]; +} btree_head; + +/* BTree attributes */ +#define HFSPLUS_BAD_CLOSE 0x01 + // Btree was not properly closed and should be checked + // not used for HFS+ but reserved +#define HFSPLUS_TREE_BIGKEYS 0x02 + // always set for HFS+ +#define HFSPLUS_TREE_VAR_NDXKEY_SIZE 0x04 + // use variable length index nodes, always set for catalog btree, + // always cleared for extents btree. + +#define HFSPLUS_TREE_UNUSED 0xFFFFFFF8 + +/* Some special File ID numbers */ +#define HFSP_POR_CNID 1 /* Parent Of the Root */ +#define HFSP_ROOT_CNID 2 /* ROOT directory */ +#define HFSP_EXT_CNID 3 /* EXTents B-tree */ +#define HFSP_CAT_CNID 4 /* CATalog B-tree */ +#define HFSP_BAD_CNID 5 /* BAD blocks file */ +#define HFSP_ALLOC_CNID 6 /* ALLOCation file */ +#define HFSP_START_CNID 7 /* STARTup file */ +#define HFSP_ATTR_CNID 8 /* ATTRibutes file */ +#define HFSP_EXCH_CNID 15 /* ExchangeFiles temp id */ +#define HFPS_MIN_CNID 15 /* Minimum expected value */ + +/* Unicode String */ +typedef struct { + UInt16 strlen; + UInt16 name[255]; // unicode charcters +} hfsp_unistr255; + +/* HFS+ catalog entry key */ +typedef struct { + UInt16 key_length; /* excluding length */ + UInt32 parent_cnid; + hfsp_unistr255 name; +} hfsp_cat_key; + +/* HFS+ exnteds entry key */ +typedef struct { + UInt16 key_length; /* excluding length */ + UInt8 fork_type; /* Seee below */ + UInt8 filler; + UInt32 file_id; + UInt32 start_block; +} hfsp_extent_key; + +#define HFSP_EXTENT_DATA 0x00 +#define HFSP_EXTENT_RSRC 0xFF + +/* The key is followed by a record, an index or some other data */ + +/* The types of these records are defined as follows */ + +#define HFSP_FOLDER 0x0001 // entry fo a Folder +#define HFSP_FILE 0x0002 // entry for a File +#define HFSP_FOLDER_THREAD 0x0003 + // Like '.' in unix, identifies the folder by its id, only +#define HFSP_FILE_THREAD 0x0004 + // Im unsure if this is used by HFS+, too + +/* HFS+ folder data (part of an hfsp_cat_entry) */ +typedef struct { + UInt16 flags; /* no flags defined yet */ + UInt32 valence; /* Numer of files and folders contained in folder */ + UInt32 id; + UInt32 create_date; // GMT + UInt32 content_mod_date; // GMT + UInt32 attribute_mod_date; // GMT + UInt32 access_date; // GMT + UInt32 backup_date; // GMT + hfsp_perm permissions; + DInfo user_info; + DXInfo finder_info; + UInt32 text_encoding; + // hint fo the finder what encoding to use, unused here + UInt32 reserved; +} hfsp_cat_folder; + +/* HFS+ file data (part of a cat_entry) */ +typedef struct { + UInt16 flags; /* See below */ + UInt32 reserved1; + UInt32 id; + UInt32 create_date; + UInt32 content_mod_date; + UInt32 attribute_mod_date; + UInt32 access_date; + UInt32 backup_date; + hfsp_perm permissions; + FInfo user_info; + FXInfo finder_info; + UInt32 text_encoding; + UInt32 reserved2; + + hfsp_fork_raw data_fork; + hfsp_fork_raw res_fork; +} hfsp_cat_file; + +/* File attribute bits */ +#define HFSP_FILE_LOCKED 0x0001 +#define HFSP_THREAD_EXISTS 0x0002 /* Always set in HFS+ */ + +/* HFS+ catalog thread (part of a cat_entry) */ +typedef struct { + UInt16 reserved; + UInt32 parentID; + hfsp_unistr255 nodeName; +} hfsp_cat_thread; + + +/* A data record in the catalog tree */ +typedef struct { + UInt16 type; + union { + hfsp_cat_folder folder; + hfsp_cat_file file; + hfsp_cat_thread thread; + } u; +} hfsp_cat_entry; diff --git a/qemu/roms/openbios/fs/hfsplus/include/hfstime.h b/qemu/roms/openbios/fs/hfsplus/include/hfstime.h new file mode 100644 index 000000000..bb6bd4a6e --- /dev/null +++ b/qemu/roms/openbios/fs/hfsplus/include/hfstime.h @@ -0,0 +1,34 @@ +/* + * libhfs - library for reading and writing Macintosh HFS volumes + * Copyright (C) 2000 Klaus Halfmann <khalfmann@libra.de>^ + * Original 1996-1998 Robert Leslie <rob@mars.org> + * other work 2000 from Brad Boyer (flar@pants.nu) + * + * The HFS+ dates are stored as UInt32 containing the number of seconds since + * midnight, January 1, 1904, GMT. This is slightly different from HFS, + * where the value represents local time. A notable exception is the + * creationdate !. Linux uses times in GMT starting at January 1, 1970 + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * $Id: hfstime.h,v 1.2 2000/10/19 13:33:38 hasi Exp $ + */ + + /* The number of seconds between 1.1.1904 and 1.1.1970 */ +#define HFSPTIMEDIFF 2082844800U + + /* return the given apple time as UNIX time */ +extern char* get_atime(UInt32 atime); diff --git a/qemu/roms/openbios/fs/hfsplus/include/libhfsp.h b/qemu/roms/openbios/fs/hfsplus/include/libhfsp.h new file mode 100644 index 000000000..912cfbd05 --- /dev/null +++ b/qemu/roms/openbios/fs/hfsplus/include/libhfsp.h @@ -0,0 +1,201 @@ +/* + * libhfs - library for reading and writing Macintosh HFS volumes + * Copyright (C) 2000 Klaus Halfmann (khalfmann@libra.de) + * Original work by 1996-1998 Robert Leslie (rob@mars.org) + * + * This file defines constants,structs etc needed for this library. + * Everything found here is usually not related to Apple defintions. + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * $Id: libhfsp.h,v 1.17 2000/10/20 06:16:52 hasi Exp $ + */ + +# include "apple.h" +# include "hfs.h" +# include "hfsp.h" + +/* Last error is eventually found here */ +extern const char *hfsp_error; + +# define HFSP_ERROR(code, str) \ + do { hfsp_error = (str), errno = (code); goto fail; } while (0) + +# ifdef DEBUG +# define ASSERT(cond) do { if (! (cond)) abort(); } while (0) +# else +# define ASSERT(cond) /* nothing */ +# endif + +# define SIZE(type, n) ((size_t) (sizeof(type) * (n))) +# define ALLOC(type, n) ((type *) malloc(SIZE(type, n))) +# define ALLOCX(type, n) ((n) ? ALLOC(type, n) : (type *) 0) +# define FREE(ptr) ((ptr) ? (void) free((void *) ptr) : (void) 0) + +# define REALLOC(ptr, type, n) \ + ((type *) ((ptr) ? realloc(ptr, SIZE(type, n)) : malloc(SIZE(type, n)))) +# define REALLOCX(ptr, type, n) \ + ((n) ? REALLOC(ptr, type, n) : (FREE(ptr), (type *) 0)) + +# define BMTST(bm, num) \ + (((const byte *) (bm))[(num) >> 3] & (0x80 >> ((num) & 0x07))) +# define BMSET(bm, num) \ + (((byte *) (bm))[(num) >> 3] |= (0x80 >> ((num) & 0x07))) +# define BMCLR(bm, num) \ + (((byte *) (bm))[(num) >> 3] &= ~(0x80 >> ((num) & 0x07))) + +# define STRINGIZE(x) #x +# define STR(x) STRINGIZE(x) + +/* used by internal routines to specify the open modes */ +# define HFSP_MODE_RDONLY 0 +# define HFSP_MODE_RDWR 1 +# define HFSP_MODE_ANY 2 + +/* Signatures registered with Apple to identify this driver */ + /* Identifies the userland implementation */ +# define HPLS_SIGNATURE 0x482B4C58 // 'H+LX' + /* Identifies the kernel module by Brad Boyer (flar@pants.nu) */ +# define HPLS_SIGRES1 0x482B4C78 // 'H+Lx' + /* not jet in use ... */ +# define HPLS_SIGRES2 0x482B6C78 // 'H+lx' + /* Signature used by Apple */ +# define HPAPPLE_SIGNATURE 0x382e3130 // '8.10' + +/* Version used for this implementation of HFS+. This is not related + * to the VERSION file found at the top-level of this package, + * but designates the version of the low level code */ +#define HPLS_VERSION 1 /* must fit in a short */ + + +/* Othe Signatures may follow for informational purpos */ + +/* prototype for key comparing functions. */ +typedef int (*hfsp_key_compare) (void* key1, void* key2); + +/* prototype for key reading (necessary for byte swapping) */ +typedef void* (*hfsp_key_read) (void* p, void* key); + +struct volume; /* foreward declaration for btree needed */ + +/* Structures for a node cache. The cache is an array + * with linear search. (So making it to big may make + * things slower). It is searched in a round robin + * fashion. + */ + +typedef struct +{ + UInt32 priority; + // as lower this number as higher the priority. + // decremetned on any sucessfull usage + // incremented else, intial value height*DEPTHFACTOR + UInt16 index; // of node in fork + // 0 means empty, since first node is node header + // contents of node in original byte order + UInt16 flags; // like DIRTY etc. +} node_entry; + +typedef struct +{ + UInt32 index; // duplicate of above + btree_node_desc desc; // header of node + char node[0]; // actual node_size + // contents of node in original byte order +} node_buf; + +typedef struct +{ + int size; // number of nodes in the cache + int currindex; // round robin index + int nodebufsize; // size of complete node_buf, including node + node_entry *entries; + char *buffers; // actually *node_buf +} node_cache; + +typedef struct +{ + struct volume* vol; /* pointer to volume this tree is part of */ + hfsp_fork_raw* fork; /* pointer to fork this tree is part of */ + UInt32 cnid; /* (pseudo) file id for the fork */ + hfsp_key_compare kcomp; + /* function used for key compare in _this_ btree */ + hfsp_key_read kread; + /* fucntion used to read a key int _this_ btree */ + btree_head head; + + UInt16 blkpernode; + /* Number of volume blocks per node (usually 1-4) */ + node_cache cache; + /* Warning all functions of btrees and records may modify + the following values ! */ + // UInt16 node_index; /* index of node in fork */ + // btree_node_desc node; /* current node under examination */ + // char* buf; /* buf with size of a node */ +} btree; + +/* Function on btrees are defined in btree.h */ + +/* A Wrapper around the raw hfs+ volume header for additional information + * needed by this library. + */ + +typedef struct volume +{ + int os_fd; /* OS dependend reference to device */ + UInt16 blksize_bits; /* blocksize of device = 1 << blksize_bits */ + UInt16 filler; + UInt32 blksize; /* always 1 << blksize_bits */ + UInt32 startblock; + /* Offset from physical to logical blocks, + eventually intodruced by HFS wrapper */ + UInt32 maxblocks; /* maximum number of blocks in device */ + // UInt32 currblock; /* value of current block, to cache blocks */ + hfsp_vh vol; /* raw volume data */ + // void* blockbuf; /* (single) buffer for fetching one block */ + /* Buffer has double size of blksize to allow cross block reading */ + + btree* extents; /* is NULL by default and intialized when needed */ + btree catalog; /* This is always neeeded */ +} volume; + +/* Functions on volumes are defined in volume.h */ + +typedef struct { // may not be used as found here + btree* tree; // tree where this record is contained in. + UInt16 node_index; /* index of record in btree */ + UInt16 keyind; /* index of current key in btree */ + hfsp_cat_key key; /* current key */ + UInt32 child; /* child node belonging to this key */ +} index_record; + +typedef struct { + btree* tree; // tree where this record is contained in. + UInt16 node_index; /* index of record in btree */ + UInt16 keyind; /* index of current key in btree */ + hfsp_extent_key key; /* current key */ + hfsp_extent_rec extent; /* The payload carried around */ +} extent_record; + +typedef struct { + btree* tree; // tree where this record is contained in. + UInt16 node_index; /* index of record in btree */ + UInt16 keyind; /* index of current key in btree */ + hfsp_cat_key key; /* current key */ + hfsp_cat_entry record; /* current record */ +} record; + +/* Functions on records are defined in record.h */ diff --git a/qemu/roms/openbios/fs/hfsplus/include/record.h b/qemu/roms/openbios/fs/hfsplus/include/record.h new file mode 100644 index 000000000..6454f552a --- /dev/null +++ b/qemu/roms/openbios/fs/hfsplus/include/record.h @@ -0,0 +1,80 @@ +/* + * libhfs - library for reading and writing Macintosh HFS volumes. + * + * a record contains a key and a folder or file and is part + * of a btree. + * + * Copyright (C) 2000 Klaus Halfmann <khalfmann@libra.de> + * Original 1996-1998 Robert Leslie <rob@mars.org> + * Additional work by Brad Boyer (flar@pants.nu) + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * $Id: record.h,v 1.10 2000/10/01 17:08:05 hasi Exp $ + */ + +/* Compare two cat_keys ... */ +extern int record_key_compare(void* k1, void* k2); + +/* Compare two extent_keys ... */ +extern int record_extent_key_compare(void* k1, void* k2); + +/* read a catalog key into a given buffer */ +extern void* record_readkey(void* p, void* buf); + +/* read an extent key into a given buffer */ +extern void* record_extent_readkey(void* p, void* buf); + +/* intialize the record to the first record of the tree + * which is (per design) the root node. + */ +extern int record_init_root(record* r, btree* tree); + +/* intialize the record to the folder given by cnid. + */ +extern int record_init_cnid(record* r, btree* tree, UInt32 cnid); + +/* intialize the record to the first record of the parent. + */ +extern int record_init_parent(record* r, record* parent); + +/* intialize the record by searching for the given string in the given folder. + * + * parent and r may be the same. + */ +extern int record_init_string_parent(record* r, record* parent, char* key); + +/* move record up in folder hierarchy (if possible) */ +extern int record_up(record* r); + +/* move record foreward to next entry. + * + * In case of an error the value of *r is undefined ! + */ +extern int record_next(record* r); + +/* intialize the extent_record to the extent identified by + * a given file */ +extern int record_init_file(extent_record* r, btree* tree, + UInt8 forktype, UInt32 fileId, UInt32 blockindex); + +/* move foreward to next entent record. */ +extern int record_next_extent(extent_record *r); + +#ifdef DEBUG + /* Dump all the record information to stdout */ + extern void record_print(record* r); +#endif diff --git a/qemu/roms/openbios/fs/hfsplus/include/swab.h b/qemu/roms/openbios/fs/hfsplus/include/swab.h new file mode 100644 index 000000000..c424008ee --- /dev/null +++ b/qemu/roms/openbios/fs/hfsplus/include/swab.h @@ -0,0 +1,64 @@ +/* + * libhfs - library for reading and writing Macintosh HFS volumes + * + * Copyright (C) 2000 Klaus Halfmann <klaus.halfmann@feri.de> + * Original work 1996-1998 Robert Leslie <rob@mars.org> + * + * This file defines some byte swapping function. I did not find this + * in any standard or linux way. + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * $Id: swab.h,v 1.1.1.1 2002/03/05 19:50:29 klaus Exp $ + */ + +#include "config.h" +#include "libc/byteorder.h" + + /* basic fuction: + value = swab_inc(ptr); + ptr is afterwards incremented by sizeof(value) + */ + +#ifndef CONFIG_BIG_ENDIAN + +#define bswabU16(val) __bswap16(val) + +#define bswabU16_inc(ptr) (__extension__ ({ UInt16 v=__bswap16(*((UInt16*) (ptr))); ptr+=sizeof(UInt16);v;})) +#define bswabU32_inc(ptr) (__extension__ ({ UInt32 v=__bswap32(*((UInt32*) (ptr))); ptr+=sizeof(UInt32);v;})) +#define bswabU64_inc(ptr) (__extension__ ({ UInt64 v=__bswap64(*((UInt64*) (ptr))); ptr+=sizeof(UInt64);v;})) + +#define bstoreU16_inc(ptr, val) do {(*((UInt16*) (ptr))) = __bswap16(val); ptr+=sizeof(UInt16);} while (0) +#define bstoreU32_inc(ptr, val) do {(*((UInt32*) (ptr))) = __bswap32(val); ptr+=sizeof(UInt32);} while (0) +#define bstoreU64_inc(ptr, val) do {(*((UInt64*) (ptr))) = __bswap64(val); ptr+=sizeof(UInt64);} while (0) + +#else // BYTE_ORDER == BIG_ENDIAN + +#define bswabU16(val) val + +#define bswabU16_inc(ptr) (__extension__ ({ UInt16 v=(*((UInt16*) (ptr))); ptr+=sizeof(UInt16);v;})) +#define bswabU32_inc(ptr) (__extension__ ({ UInt32 v=(*((UInt32*) (ptr))); ptr+=sizeof(UInt32);v;})) +#define bswabU64_inc(ptr) (__extension__ ({ UInt64 v=(*((UInt64*) (ptr))); ptr+=sizeof(UInt64);v;})) + +#define bstoreU16_inc(ptr, val) do {(*((UInt16*) (ptr))) = val; ptr+=sizeof(UInt16);} while (0) +#define bstoreU32_inc(ptr, val) do {(*((UInt32*) (ptr))) = val; ptr+=sizeof(UInt32);} while (0) +#define bstoreU64_inc(ptr, val) do {(*((UInt64*) (ptr))) = val; ptr+=sizeof(UInt64);} while (0) + +#endif + +/* for the sake of compleetness and readability */ +#define bswabU8_inc(ptr) (__extension__ ({ UInt8 v=(*((UInt8*) (ptr))); ptr+=sizeof(UInt8);v;})) +#define bstoreU8_inc(ptr,val) do {(*((UInt8*) (ptr))) = val; ptr+=sizeof(UInt8);} while (0) diff --git a/qemu/roms/openbios/fs/hfsplus/include/unicode.h b/qemu/roms/openbios/fs/hfsplus/include/unicode.h new file mode 100644 index 000000000..e7c86f78a --- /dev/null +++ b/qemu/roms/openbios/fs/hfsplus/include/unicode.h @@ -0,0 +1,28 @@ +/* + * linux/fs/hfsplus/unicode.c + * + * Copyright (C) 1999-2000 Brad Boyer (flar@pants.nu) + * This file may be distributed under the terms of the GNU Public License. + * + * The routines found here convert hfs-unicode string into ascii Strings + * and vice versa. And the correct comparison between Strings. + */ + +/* convert the asci string astr into a unicode string given by ustr. + * + * returns actual length of convertet string. + */ + +int unicode_asc2uni(hfsp_unistr255 *ustr, const char *astr); + +/* Convert an unicode string ustr to a ascii string astr of given maximum len + * + * returns actual length of convertet string. + */ + +int unicode_uni2asc(char *astr, const hfsp_unistr255 *ustr, int maxlen); + +/* similar to strcmp for unicode, pascal strings */ + +SInt32 fast_unicode_compare (const hfsp_unistr255 *ustr1, + const hfsp_unistr255 *ustr2); diff --git a/qemu/roms/openbios/fs/hfsplus/include/volume.h b/qemu/roms/openbios/fs/hfsplus/include/volume.h new file mode 100644 index 000000000..19be05500 --- /dev/null +++ b/qemu/roms/openbios/fs/hfsplus/include/volume.h @@ -0,0 +1,87 @@ +/* + * libhfs - library for reading and writing Macintosh HFS volumes + * Copyright (C) 2000 Klaus Halfmann <khalfmann@libra.de>^ + * Original 1996-1998 Robert Leslie <rob@mars.org> + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * $Id: volume.h,v 1.11 2000/10/17 05:58:46 hasi Exp $ + */ + +#ifndef _H_VOLUME +#define _H_VOLUME + +/* Open the device, read and verify the volume header + (and its backup) */ +extern int volume_open(volume* vol, int os_fd); + +/* Write back all data eventually cached and close the device. */ +extern int volume_close(volume* vol); + +/* read multiple blocks into given memory. + * + * returns given pointer or NULL on failure. + */ +extern void* volume_readfromfork(volume* vol, void* buf, + hfsp_fork_raw* f, UInt32 block, + UInt32 count, UInt8 forktype, UInt32 fileId); + +/* Fill a given buffer with the given block in volume. + */ +int volume_readinbuf(volume * vol,void* buf, long block); + +/* invalidat cache hold in volume, will be removed when + * caching strategy is clear to me. */ +/* +extern inline void volume_invalidate_cache(volume* vol) +{ + vol -> currblock = (UInt32) -1; +} +*/ + +/* Check in Allocation file if given block is allocated. */ +extern int volume_allocated(volume* v, UInt32 block); + +/* Read a raw hfsp_extent_rec from memory. */ +extern void* volume_readextent(void *p, hfsp_extent_rec er); + +/* Read fork information from raw memory */ +extern void* volume_readfork(void *p, hfsp_fork_raw* f); + +/* internal function used to create the extents btree, + is called by following inline fucntion when needed */ +extern void volume_create_extents_tree(volume* vol); + +/* accessor for entends btree, is created on demand */ +static inline btree* volume_get_extents_tree(volume* vol) { + if (!vol->extents) + volume_create_extents_tree(vol); + return vol->extents; +} + +/* Determine whether the volume is a HFS-plus volume */ +int volume_probe(int fd, long long offset); + +#ifdef DEBUG + /* Print raw fork information to stdout */ + void volume_print_fork(hfsp_fork_raw* f); + /* Dump all the volume information to stdout */ + void volume_print(hfsp_vh* vol); +#endif + + + +#endif /* _H_VOLUME */ diff --git a/qemu/roms/openbios/fs/hfsplus/libhfsp.c b/qemu/roms/openbios/fs/hfsplus/libhfsp.c new file mode 100644 index 000000000..af1cde6a9 --- /dev/null +++ b/qemu/roms/openbios/fs/hfsplus/libhfsp.c @@ -0,0 +1,29 @@ +/* + * libhfsp - library for reading and writing Macintosh HFS volumes + * Copyright (C) 1996-1998 Robert Leslie + * + * Thi file contains utitlity fucntions to manage the features of + * the hfs+ library. + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * $Id: libhfsp.c,v 1.1.1.1 2000/07/25 10:33:40 kkaempf Exp $ + */ + +#include "config.h" +#include "libhfsp.h" + +const char *hfsp_error = "no error"; /* static error string */ diff --git a/qemu/roms/openbios/fs/ioglue.c b/qemu/roms/openbios/fs/ioglue.c new file mode 100644 index 000000000..1d33d8fda --- /dev/null +++ b/qemu/roms/openbios/fs/ioglue.c @@ -0,0 +1,92 @@ +/* + * Creation Date: <2001/05/06 22:27:09 samuel> + * Time-stamp: <2003/12/12 02:24:56 samuel> + * + * <fs.c> + * + * I/O API used by the filesystem code + * + * Copyright (C) 2001, 2002, 2003 Samuel Rydh (samuel@ibrium.se) + * + * 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 + * + */ + +#include "config.h" +#include "libopenbios/bindings.h" +#include "fs/fs.h" +#include "libc/diskio.h" +#include "os.h" +#include "hfs_mdb.h" + +/************************************************************************/ +/* functionsions used by the various filesystems */ +/************************************************************************/ + +char * +get_hfs_vol_name( int fd, char *buf, int size ) +{ + char sect[512]; + hfs_mdb_t *mdb = (hfs_mdb_t*)§ + + seek_io( fd, 0x400 ); + read_io( fd, sect, sizeof(sect) ); + if( hfs_get_ushort(mdb->drSigWord) == HFS_SIGNATURE ) { + unsigned int n = mdb->drVN[0]; + if( n >= size ) + n = size - 1; + memcpy( buf, &mdb->drVN[1], n ); + buf[n] = 0; + } else if( hfs_get_ushort(mdb->drSigWord) == HFS_PLUS_SIGNATURE ) { + strncpy( buf, "Unembedded HFS+", size ); + } else { + strncpy( buf, "Error", size ); + } + return buf; +} + +unsigned long +os_read( int fd, void *buf, unsigned long len, int blksize_bits ) +{ + /* printk("os_read %d\n", (int)len); */ + + int cnt = read_io( fd, buf, len << blksize_bits ); + return (cnt > 0)? (cnt >> blksize_bits) : cnt; +} + +unsigned long +os_seek( int fd, unsigned long blknum, int blksize_bits ) +{ + /* printk("os_seek %d\n", blknum ); */ + long long offs = (long long)blknum << blksize_bits; + + /* offset == -1 means seek to EOF */ + if( (int)blknum == -1 ) + offs = -1; + + if( seek_io(fd, offs) ) { + /* printk("os_seek failure\n"); */ + return (unsigned long)-1; + } + + if( (int)blknum == -1 ) { + if( (offs=tell(fd)) < 0 ) + return -1; + blknum = offs >> blksize_bits; + } + return blknum; +} + +void +os_seek_offset( int fd, long long offset ) +{ + seek_io(fd, offset); +} + +int +os_same( int fd1, int fd2 ) +{ + return fd1 == fd2; +} diff --git a/qemu/roms/openbios/fs/iso9660/build.xml b/qemu/roms/openbios/fs/iso9660/build.xml new file mode 100644 index 000000000..00d390217 --- /dev/null +++ b/qemu/roms/openbios/fs/iso9660/build.xml @@ -0,0 +1,13 @@ +<build> + <library name="fs" type="static" target="target"> + <object source="iso9660_fs.c" condition="ISO9660"/> + <object source="iso9660_close.c" condition="ISO9660"/> + <object source="iso9660_closedir.c" condition="ISO9660"/> + <object source="iso9660_lseek.c" condition="ISO9660"/> + <object source="iso9660_mount.c" condition="ISO9660"/> + <object source="iso9660_open.c" condition="ISO9660"/> + <object source="iso9660_opendir.c" condition="ISO9660"/> + <object source="iso9660_read.c" condition="ISO9660"/> + <object source="iso9660_readdir.c" condition="ISO9660"/> + </library> +</build> diff --git a/qemu/roms/openbios/fs/iso9660/iso9660.h b/qemu/roms/openbios/fs/iso9660/iso9660.h new file mode 100644 index 000000000..ac6dcf091 --- /dev/null +++ b/qemu/roms/openbios/fs/iso9660/iso9660.h @@ -0,0 +1,58 @@ +/* + * + * (c) 2005-2009 Laurent Vivier <Laurent@vivier.eu> + * + * This file has been copied from EMILE, http://emile.sf.net + * + */ + +#ifndef __ISO9660_H__ +#define __ISO9660_H__ + +#include "iso9660_fs.h" + +typedef struct iso9660_VOLUME { + int ucs_level; + struct iso_primary_descriptor *descriptor; + int fd; +} iso9660_VOLUME; + +typedef struct iso9660_DIR { + iso9660_VOLUME *volume; + int extent; + int len; + int index; + unsigned char buffer[ISOFS_BLOCK_SIZE]; +} iso9660_DIR; + +typedef struct iso9660_FILE { + iso9660_VOLUME *volume; + char *path; + int base; /* first extent of the file */ + int size; /* size of the file */ + int offset; + int current; + unsigned char buffer[ISOFS_BLOCK_SIZE]; +} iso9660_FILE; + +static inline int isonum_721(char *p) +{ + return ((p[0] & 0xff) + | ((p[1] & 0xff) << 8)); +} + +static inline int isonum_723(char *p) +{ + return (isonum_721(p)); +} + +static inline int isonum_733(char *p) +{ + return ((p[0] & 0xff) | ((p[1] & 0xff) << 8) | + ((p[2] & 0xff) << 16) | ((p[3] & 0xff) << 24)); +} + +extern struct iso_directory_record *iso9660_get_root_node(iso9660_VOLUME* volume); +extern struct iso_directory_record* iso9660_get_node(iso9660_VOLUME *volume, struct iso_directory_record *dirnode, const char *path); + +#endif /* __ISO9660_H__ */ diff --git a/qemu/roms/openbios/fs/iso9660/iso9660_close.c b/qemu/roms/openbios/fs/iso9660/iso9660_close.c new file mode 100644 index 000000000..ce79c0fd4 --- /dev/null +++ b/qemu/roms/openbios/fs/iso9660/iso9660_close.c @@ -0,0 +1,15 @@ +/* + * + * (c) 2005-2009 Laurent Vivier <Laurent@vivier.eu> + * + * This file has been copied from EMILE bootloader, http://emile.sf.net + * + */ + +#include "libiso9660.h" + +void iso9660_close(iso9660_FILE *file) +{ + free(file->path); + free(file); +} diff --git a/qemu/roms/openbios/fs/iso9660/iso9660_closedir.c b/qemu/roms/openbios/fs/iso9660/iso9660_closedir.c new file mode 100644 index 000000000..706cc222f --- /dev/null +++ b/qemu/roms/openbios/fs/iso9660/iso9660_closedir.c @@ -0,0 +1,19 @@ +/* + * + * (c) 2005-2009 Laurent Vivier <Laurent@vivier.eu> + * + * This file has been copied from EMILE, http://emile.sf.net + * + */ + +#include "libiso9660.h" + +int iso9660_closedir(iso9660_DIR *dir) +{ + if (dir == NULL) + return -1; + + free(dir); + + return 0; +} diff --git a/qemu/roms/openbios/fs/iso9660/iso9660_fs.c b/qemu/roms/openbios/fs/iso9660/iso9660_fs.c new file mode 100644 index 000000000..d6f547be1 --- /dev/null +++ b/qemu/roms/openbios/fs/iso9660/iso9660_fs.c @@ -0,0 +1,263 @@ +/* + * /packages/iso9660-files filesystem handler + * + * (c) 2009 Laurent Vivier <Laurent@vivier.eu> + * (c) 2010 Mark Cave-Ayland <mark.cave-ayland@siriusit.co.uk> + */ + +#include "config.h" +#include "libopenbios/bindings.h" +#include "libiso9660.h" +#include "fs/fs.h" +#include "libc/vsprintf.h" +#include "libc/diskio.h" + +extern void iso9660_init( void ); + +typedef struct { + enum { FILE, DIR } type; + union { + iso9660_FILE *file; + iso9660_DIR * dir; + }; +} iso9660_COMMON; + +typedef struct { + iso9660_VOLUME *volume; + iso9660_COMMON *common; +} iso9660_info_t; + +DECLARE_NODE( iso9660, 0, sizeof(iso9660_info_t), "+/packages/iso9660-files" ); + +/* ( -- success? ) */ +static void +iso9660_files_open( iso9660_info_t *mi ) +{ + int fd; + char *path = my_args_copy(); + + if ( ! path ) + RET( 0 ); + + fd = open_ih( my_parent() ); + if ( fd == -1 ) { + free( path ); + RET( 0 ); + } + + mi->volume = iso9660_mount( fd ); + if ( mi->volume == NULL ) { + free( path ); + close_io( fd ); + RET( 0 ); + } + + mi->common->dir = iso9660_opendir( mi->volume, path ); + if ( mi->common->dir == NULL ) { + mi->common->file = iso9660_open( mi->volume, path ); + if (mi->common->file == NULL) { + iso9660_umount( mi->volume ); + close_io( fd ); + free( path ); + RET( 0 ); + } + mi->common->type = FILE; + free( path ); + RET( -1 ); + } + mi->common->type = DIR; + free( path ); + + RET( -1 ); +} + +/* ( -- ) */ +static void +iso9660_files_close( iso9660_info_t *mi ) +{ + int fd = mi->volume->fd; + + if (mi->common->type == FILE ) + iso9660_close( mi->common->file ); + else if ( mi->common->type == DIR ) + iso9660_closedir( mi->common->dir ); + iso9660_umount( mi->volume ); + close_io( fd ); +} + +/* ( buf len -- actlen ) */ +static void +iso9660_files_read( iso9660_info_t *mi ) +{ + int count = POP(); + char *buf = (char *)cell2pointer(POP()); + int ret; + + if ( mi->common->type != FILE ) + PUSH( 0 ); + + ret = iso9660_read( mi->common->file, buf, count ); + + PUSH( ret ); +} + +/* ( pos.d -- status ) */ +static void +iso9660_files_seek( iso9660_info_t *mi ) +{ + long long pos = DPOP(); + cell ret; + int offs = (int)pos; + int whence = SEEK_SET; + + if (mi->common->type != FILE) + PUSH( -1 ); + + if( offs == -1 ) { + offs = 0; + whence = SEEK_END; + } + + ret = iso9660_lseek(mi->common->file, offs, whence); + + PUSH( (ret < 0)? -1 : 0 ); +} + +/* ( -- filepos.d ) */ +static void +iso9660_files_offset( iso9660_info_t *mi ) +{ + if ( mi->common->type != FILE ) + DPUSH( -1 ); + + DPUSH( mi->common->file->offset ); +} + +/* ( addr -- size ) */ +static void +iso9660_files_load( iso9660_info_t *mi) +{ + char *buf = (char*)cell2pointer(POP()); + int ret, size; + + if ( mi->common->type != FILE ) + PUSH( 0 ); + + size = 0; + while(1) { + ret = iso9660_read( mi->common->file, buf, 512 ); + if (ret <= 0) + break; + buf += ret; + size += ret; + if (ret != 512) + break; + } + PUSH( size ); +} + +/* static method, ( pathstr len ihandle -- ) */ +static void +iso9660_files_dir( iso9660_info_t *dummy ) +{ + iso9660_VOLUME *volume; + iso9660_COMMON *common; + struct iso_directory_record *idr; + char name_buf[256]; + int fd; + + ihandle_t ih = POP(); + char *path = pop_fstr_copy(); + + fd = open_ih( ih ); + if ( fd == -1 ) { + free( path ); + return; + } + + volume = iso9660_mount( fd ); + if ( volume == NULL ) { + free ( path ); + close_io( fd ); + return; + } + + common = malloc(sizeof(iso9660_COMMON)); + common->dir = iso9660_opendir( volume, path ); + + forth_printf("\n"); + while ( (idr = iso9660_readdir(common->dir)) ) { + + forth_printf("% 10d ", isonum_733(idr->size)); + forth_printf("%d-%02d-%02d %02d:%02d:%02d ", + idr->date[0] + 1900, /* year */ + idr->date[1], /* month */ + idr->date[2], /* day */ + idr->date[3], idr->date[4], idr->date[5]); + iso9660_name(common->dir->volume, idr, name_buf); + if (idr->flags[0] & 2) + forth_printf("%s\\\n", name_buf); + else + forth_printf("%s\n", name_buf); + } + + iso9660_closedir( common->dir ); + iso9660_umount( volume ); + + close_io( fd ); + + free( common ); + free( path ); +} + +/* static method, ( pos.d ih -- flag? ) */ +static void +iso9660_files_probe( iso9660_info_t *dummy ) +{ + ihandle_t ih = POP_ih(); + long long offs = DPOP(); + int fd, ret = 0; + + fd = open_ih(ih); + if (fd >= 0) { + if (iso9660_probe(fd, offs)) { + ret = -1; + } + close_io(fd); + } else { + ret = -1; + } + + RET (ret); +} + +static void +iso9660_files_block_size( iso9660_info_t *dummy ) +{ + PUSH(2048); +} + +static void +iso9660_initializer( iso9660_info_t *dummy ) +{ + fword("register-fs-package"); +} + +NODE_METHODS( iso9660 ) = { + { "probe", iso9660_files_probe }, + { "open", iso9660_files_open }, + { "close", iso9660_files_close }, + { "read", iso9660_files_read }, + { "seek", iso9660_files_seek }, + { "offset", iso9660_files_offset }, + { "load", iso9660_files_load }, + { "dir", iso9660_files_dir }, + { "block-size", iso9660_files_block_size }, + { NULL, iso9660_initializer }, +}; + +void +iso9660_init( void ) +{ + REGISTER_NODE( iso9660 ); +} diff --git a/qemu/roms/openbios/fs/iso9660/iso9660_fs.h b/qemu/roms/openbios/fs/iso9660/iso9660_fs.h new file mode 100644 index 000000000..0de124da9 --- /dev/null +++ b/qemu/roms/openbios/fs/iso9660/iso9660_fs.h @@ -0,0 +1,161 @@ +#ifndef _ISO9660_FS_H +#define _ISO9660_FS_H + +/* this file has been copied from linux 2.6.26 */ + +/* + * The isofs filesystem constants/structures + */ + +/* This part borrowed from the bsd386 isofs */ +#define ISODCL(from, to) (to - from + 1) + +struct iso_volume_descriptor { + char type[ISODCL(1,1)]; /* 711 */ + char id[ISODCL(2,6)]; + char version[ISODCL(7,7)]; + char data[ISODCL(8,2048)]; +}; + +/* volume descriptor types */ +#define ISO_VD_PRIMARY 1 +#define ISO_VD_SUPPLEMENTARY 2 +#define ISO_VD_END 255 + +#define ISO_STANDARD_ID "CD001" + +struct iso_primary_descriptor { + char type [ISODCL ( 1, 1)]; /* 711 */ + char id [ISODCL ( 2, 6)]; + char version [ISODCL ( 7, 7)]; /* 711 */ + char unused1 [ISODCL ( 8, 8)]; + char system_id [ISODCL ( 9, 40)]; /* achars */ + char volume_id [ISODCL ( 41, 72)]; /* dchars */ + char unused2 [ISODCL ( 73, 80)]; + char volume_space_size [ISODCL ( 81, 88)]; /* 733 */ + char unused3 [ISODCL ( 89, 120)]; + char volume_set_size [ISODCL (121, 124)]; /* 723 */ + char volume_sequence_number [ISODCL (125, 128)]; /* 723 */ + char logical_block_size [ISODCL (129, 132)]; /* 723 */ + char path_table_size [ISODCL (133, 140)]; /* 733 */ + char type_l_path_table [ISODCL (141, 144)]; /* 731 */ + char opt_type_l_path_table [ISODCL (145, 148)]; /* 731 */ + char type_m_path_table [ISODCL (149, 152)]; /* 732 */ + char opt_type_m_path_table [ISODCL (153, 156)]; /* 732 */ + char root_directory_record [ISODCL (157, 190)]; /* 9.1 */ + char volume_set_id [ISODCL (191, 318)]; /* dchars */ + char publisher_id [ISODCL (319, 446)]; /* achars */ + char preparer_id [ISODCL (447, 574)]; /* achars */ + char application_id [ISODCL (575, 702)]; /* achars */ + char copyright_file_id [ISODCL (703, 739)]; /* 7.5 dchars */ + char abstract_file_id [ISODCL (740, 776)]; /* 7.5 dchars */ + char bibliographic_file_id [ISODCL (777, 813)]; /* 7.5 dchars */ + char creation_date [ISODCL (814, 830)]; /* 8.4.26.1 */ + char modification_date [ISODCL (831, 847)]; /* 8.4.26.1 */ + char expiration_date [ISODCL (848, 864)]; /* 8.4.26.1 */ + char effective_date [ISODCL (865, 881)]; /* 8.4.26.1 */ + char file_structure_version [ISODCL (882, 882)]; /* 711 */ + char unused4 [ISODCL (883, 883)]; + char application_data [ISODCL (884, 1395)]; + char unused5 [ISODCL (1396, 2048)]; +}; + +/* Almost the same as the primary descriptor but two fields are specified */ +struct iso_supplementary_descriptor { + char type [ISODCL ( 1, 1)]; /* 711 */ + char id [ISODCL ( 2, 6)]; + char version [ISODCL ( 7, 7)]; /* 711 */ + char flags [ISODCL ( 8, 8)]; /* 853 */ + char system_id [ISODCL ( 9, 40)]; /* achars */ + char volume_id [ISODCL ( 41, 72)]; /* dchars */ + char unused2 [ISODCL ( 73, 80)]; + char volume_space_size [ISODCL ( 81, 88)]; /* 733 */ + char escape [ISODCL ( 89, 120)]; /* 856 */ + char volume_set_size [ISODCL (121, 124)]; /* 723 */ + char volume_sequence_number [ISODCL (125, 128)]; /* 723 */ + char logical_block_size [ISODCL (129, 132)]; /* 723 */ + char path_table_size [ISODCL (133, 140)]; /* 733 */ + char type_l_path_table [ISODCL (141, 144)]; /* 731 */ + char opt_type_l_path_table [ISODCL (145, 148)]; /* 731 */ + char type_m_path_table [ISODCL (149, 152)]; /* 732 */ + char opt_type_m_path_table [ISODCL (153, 156)]; /* 732 */ + char root_directory_record [ISODCL (157, 190)]; /* 9.1 */ + char volume_set_id [ISODCL (191, 318)]; /* dchars */ + char publisher_id [ISODCL (319, 446)]; /* achars */ + char preparer_id [ISODCL (447, 574)]; /* achars */ + char application_id [ISODCL (575, 702)]; /* achars */ + char copyright_file_id [ISODCL (703, 739)]; /* 7.5 dchars */ + char abstract_file_id [ISODCL (740, 776)]; /* 7.5 dchars */ + char bibliographic_file_id [ISODCL (777, 813)]; /* 7.5 dchars */ + char creation_date [ISODCL (814, 830)]; /* 8.4.26.1 */ + char modification_date [ISODCL (831, 847)]; /* 8.4.26.1 */ + char expiration_date [ISODCL (848, 864)]; /* 8.4.26.1 */ + char effective_date [ISODCL (865, 881)]; /* 8.4.26.1 */ + char file_structure_version [ISODCL (882, 882)]; /* 711 */ + char unused4 [ISODCL (883, 883)]; + char application_data [ISODCL (884, 1395)]; + char unused5 [ISODCL (1396, 2048)]; +}; + + +#define HS_STANDARD_ID "CDROM" + +struct hs_volume_descriptor { + char foo [ISODCL ( 1, 8)]; /* 733 */ + char type [ISODCL ( 9, 9)]; /* 711 */ + char id [ISODCL ( 10, 14)]; + char version [ISODCL ( 15, 15)]; /* 711 */ + char data[ISODCL(16,2048)]; +}; + + +struct hs_primary_descriptor { + char foo [ISODCL ( 1, 8)]; /* 733 */ + char type [ISODCL ( 9, 9)]; /* 711 */ + char id [ISODCL ( 10, 14)]; + char version [ISODCL ( 15, 15)]; /* 711 */ + char unused1 [ISODCL ( 16, 16)]; /* 711 */ + char system_id [ISODCL ( 17, 48)]; /* achars */ + char volume_id [ISODCL ( 49, 80)]; /* dchars */ + char unused2 [ISODCL ( 81, 88)]; /* 733 */ + char volume_space_size [ISODCL ( 89, 96)]; /* 733 */ + char unused3 [ISODCL ( 97, 128)]; /* 733 */ + char volume_set_size [ISODCL (129, 132)]; /* 723 */ + char volume_sequence_number [ISODCL (133, 136)]; /* 723 */ + char logical_block_size [ISODCL (137, 140)]; /* 723 */ + char path_table_size [ISODCL (141, 148)]; /* 733 */ + char type_l_path_table [ISODCL (149, 152)]; /* 731 */ + char unused4 [ISODCL (153, 180)]; /* 733 */ + char root_directory_record [ISODCL (181, 214)]; /* 9.1 */ +}; + +/* We use this to help us look up the parent inode numbers. */ + +struct iso_path_table{ + unsigned char name_len[2]; /* 721 */ + char extent[4]; /* 731 */ + char parent[2]; /* 721 */ + char name[0]; +} __attribute__((packed)); + +/* high sierra is identical to iso, except that the date is only 6 bytes, and + there is an extra reserved byte after the flags */ + +struct iso_directory_record { + char length [ISODCL (1, 1)]; /* 711 */ + char ext_attr_length [ISODCL (2, 2)]; /* 711 */ + char extent [ISODCL (3, 10)]; /* 733 */ + char size [ISODCL (11, 18)]; /* 733 */ + char date [ISODCL (19, 25)]; /* 7 by 711 */ + char flags [ISODCL (26, 26)]; + char file_unit_size [ISODCL (27, 27)]; /* 711 */ + char interleave [ISODCL (28, 28)]; /* 711 */ + char volume_sequence_number [ISODCL (29, 32)]; /* 723 */ + unsigned char name_len [ISODCL (33, 33)]; /* 711 */ + char name [0]; +} __attribute__((packed)); + +#define ISOFS_BLOCK_BITS 11 +#define ISOFS_BLOCK_SIZE (1 << ISOFS_BLOCK_BITS) + +#endif /* _ISO9660_FS_H */ diff --git a/qemu/roms/openbios/fs/iso9660/iso9660_lseek.c b/qemu/roms/openbios/fs/iso9660/iso9660_lseek.c new file mode 100644 index 000000000..62987583c --- /dev/null +++ b/qemu/roms/openbios/fs/iso9660/iso9660_lseek.c @@ -0,0 +1,37 @@ +/* + * + * (c) 2005-2009 Laurent Vivier <Laurent@vivier.eu> + * + * This file has been copied from EMILE, http://emile.sf.net + * + */ + +#include "libiso9660.h" + +int iso9660_lseek(iso9660_FILE *_file, long offset, int whence) +{ + iso9660_FILE *file = (iso9660_FILE*)_file; + long new_offset; + + switch(whence) + { + case SEEK_SET: + new_offset = offset; + break; + case SEEK_CUR: + new_offset = file->offset + offset; + break; + case SEEK_END: + new_offset = file->size + offset; + break; + default: + return -1; + } + + if ( (new_offset < 0) || (new_offset > file->size) ) + return -1; + + file->offset = new_offset; + + return new_offset; +} diff --git a/qemu/roms/openbios/fs/iso9660/iso9660_mount.c b/qemu/roms/openbios/fs/iso9660/iso9660_mount.c new file mode 100644 index 000000000..a58170408 --- /dev/null +++ b/qemu/roms/openbios/fs/iso9660/iso9660_mount.c @@ -0,0 +1,210 @@ +/* + * + * (c) 2005-2009 Laurent Vivier <Laurent@vivier.eu> + * + * This file has been copied from EMILE, http://emile.sf.net + * + * some parts from mkisofs (c) J. Schilling + * + */ + +#include "libiso9660.h" +#include "libopenbios/bindings.h" +#include "libc/diskio.h" + +void iso9660_name(iso9660_VOLUME *volume, struct iso_directory_record *idr, char *buffer) +{ + int j; + unsigned char ul, uc; + + buffer[0] = 0; + if (idr->name_len[0] == 1 && idr->name[0] == 0) + strcpy(buffer, "."); + else if (idr->name_len[0] == 1 && idr->name[0] == 1) + strcpy(buffer, ".."); + else { + switch (volume->ucs_level) { + case 3: + case 2: + case 1: + /* + * Unicode name. + */ + + for (j = 0; j < (int)idr->name_len[0] / 2; j++) { + ul = idr->name[j*2+1]; + + /* + * unicode convertion + * up = unls->unls_uni2cs[uh]; + * + * if (up == NULL) + * uc = '\0'; + * else + * uc = up[ul]; + * + * we use only low byte + */ + + uc = ul; + + buffer[j] = uc ? uc : '_'; + } + buffer[idr->name_len[0]/2] = '\0'; + break; + case 0: + /* + * Normal non-Unicode name. + */ + strncpy(buffer, idr->name, idr->name_len[0]); + buffer[idr->name_len[0]] = 0; + break; + default: + /* + * Don't know how to do these yet. Maybe they are the same + * as one of the above. + */ + break; + } + } +} + +iso9660_VOLUME *iso9660_mount(int fd) +{ + iso9660_VOLUME* volume; + struct iso_primary_descriptor *jpd; + struct iso_primary_descriptor ipd; + int block; + int ucs_level = 0; + + /* read filesystem descriptor */ + + seek_io(fd, 16 * ISOFS_BLOCK_SIZE); + read_io(fd, &ipd, sizeof (ipd)); + + /* + * High sierra: + * + * DESC TYPE == 1 (VD_SFS) offset 8 len 1 + * STR ID == "CDROM" offset 9 len 5 + * STD_VER == 1 offset 14 len 1 + */ + + /* High Sierra format ? */ + + if ((((char *)&ipd)[8] == 1) && + (strncmp(&((char *)&ipd)[9], "CDROM", 5) == 0) && + (((char *)&ipd)[14] == 1)) { + printk("Incompatible format: High Sierra format\n"); + return NULL; + } + + /* + * ISO 9660: + * + * DESC TYPE == 1 (VD_PVD) offset 0 len 1 + * STR ID == "CD001" offset 1 len 5 + * STD_VER == 1 offset 6 len 1 + */ + + /* NOT ISO 9660 format ? */ + + if ((ipd.type[0] != ISO_VD_PRIMARY) || + (strncmp(ipd.id, ISO_STANDARD_ID, sizeof (ipd.id)) != 0) || + (ipd.version[0] != 1)) { + return NULL; + } + + /* UCS info */ + + block = 16; + + jpd = (struct iso_primary_descriptor *) + malloc(sizeof(struct iso_primary_descriptor)); + if (jpd == NULL) + return NULL; + + memcpy(jpd, &ipd, sizeof (ipd)); + while ((uint8_t)jpd->type[0] != ISO_VD_END) { + + /* + * If Joliet UCS escape sequence found, we may be wrong + */ + + if (jpd->unused3[0] == '%' && + jpd->unused3[1] == '/' && + (jpd->unused3[3] == '\0' || + jpd->unused3[3] == ' ') && + (jpd->unused3[2] == '@' || + jpd->unused3[2] == 'C' || + jpd->unused3[2] == 'E')) { + + if (jpd->version[0] != 1) + break; + } + + block++; + seek_io(fd, block * ISOFS_BLOCK_SIZE); + read_io(fd, jpd, sizeof (*jpd)); + } + + ucs_level = 0; + if (((unsigned char) jpd->type[0] == ISO_VD_END)) { + memcpy(jpd, &ipd, sizeof (ipd)); + } else { + switch (jpd->unused3[2]) { + case '@': + ucs_level = 1; + break; + case 'C': + ucs_level = 2; + break; + case 'E': + ucs_level = 3; + break; + } + + if (ucs_level && jpd->unused3[3] == ' ') + printk("Warning: Joliet escape sequence uses illegal space at offset 3\n"); + } + + volume = (iso9660_VOLUME*)malloc(sizeof(iso9660_VOLUME)); + if (volume == NULL) + return NULL; + + volume->descriptor = jpd; + volume->ucs_level = ucs_level; + volume->fd = fd; + + return volume; +} + +int iso9660_umount(iso9660_VOLUME* volume) +{ + if (volume == NULL) + return -1; + free(volume->descriptor); + free(volume); + return 0; +} + +int iso9660_probe(int fd, long long offset) +{ + struct iso_primary_descriptor ipd; + + seek_io(fd, 16 * ISOFS_BLOCK_SIZE + offset); + read_io(fd, &ipd, sizeof (ipd)); + + if ((ipd.type[0] != ISO_VD_PRIMARY) || + (strncmp(ipd.id, ISO_STANDARD_ID, sizeof (ipd.id)) != 0) || + (ipd.version[0] != 1)) { + return 0; + } + + return -1; +} + +struct iso_directory_record *iso9660_get_root_node(iso9660_VOLUME* volume) +{ + return (struct iso_directory_record *)volume->descriptor->root_directory_record; +} diff --git a/qemu/roms/openbios/fs/iso9660/iso9660_open.c b/qemu/roms/openbios/fs/iso9660/iso9660_open.c new file mode 100644 index 000000000..77c271f0f --- /dev/null +++ b/qemu/roms/openbios/fs/iso9660/iso9660_open.c @@ -0,0 +1,39 @@ +/* + * + * (c) 2005-2009 Laurent Vivier <Laurent@vivier.eu> + * + * This file has been copied from EMILE, http://emile.sf.net + * + */ + +#include "libiso9660.h" + +iso9660_FILE* iso9660_open(iso9660_VOLUME *volume, const char* pathname) +{ + struct iso_directory_record *root; + struct iso_directory_record *idr; + iso9660_FILE *file; + + root = iso9660_get_root_node(volume); + if (root == NULL) + return NULL; + + idr = iso9660_get_node(volume, root, pathname); + if (idr == NULL) + return NULL; + + file = (iso9660_FILE*)malloc(sizeof(iso9660_FILE)); + if (file == NULL) + return NULL; + + file->base = isonum_733((char *)idr->extent); + file->size = isonum_733((char *)idr->size); + file->offset = 0; + file->current = -1; + file->volume = volume; + file->path = strdup(pathname); + + free(idr); + + return file; +} diff --git a/qemu/roms/openbios/fs/iso9660/iso9660_opendir.c b/qemu/roms/openbios/fs/iso9660/iso9660_opendir.c new file mode 100644 index 000000000..49eab4b42 --- /dev/null +++ b/qemu/roms/openbios/fs/iso9660/iso9660_opendir.c @@ -0,0 +1,133 @@ +/* + * + * (c) 2005-2009 Laurent Vivier <Laurent@vivier.eu> + * + * This file has been copied from EMILE, http://emile.sf.net + * + */ + +#include "libiso9660.h" + +static inline int iso9660_is_directory(struct iso_directory_record * idr) +{ + return ((idr->flags[0] & 2) != 0); +} + +static iso9660_DIR* iso9660_opendir_node(iso9660_VOLUME *volume, struct iso_directory_record *node) +{ + iso9660_DIR *dir; + + dir = (iso9660_DIR*)malloc(sizeof(iso9660_DIR)); + if (dir == NULL) + return NULL; + + dir->extent = isonum_733((char *)node->extent); + dir->len = isonum_733((char *)node->size); + dir->index = sizeof (dir->buffer); + dir->volume = volume; + + return dir; +} + +static struct iso_directory_record* idr_new(struct iso_directory_record* idr) +{ + struct iso_directory_record* result; + int size = sizeof(*idr) + (int)idr->name_len[0]; + + result = (struct iso_directory_record*)malloc(size); + memcpy(result, idr, size); + + return result; +} + +static struct iso_directory_record * seek_name(iso9660_VOLUME *volume, + struct iso_directory_record *idr, + char *name) +{ + struct iso_directory_record *result; + char name_buf[256]; + iso9660_DIR *dir; + + dir = iso9660_opendir_node(volume, idr); + if (dir == NULL) + return NULL; + + while ((idr = iso9660_readdir(dir)) != NULL) + { + iso9660_name(volume, idr, name_buf); + if (strcasecmp(name, name_buf) == 0) + { + result = idr_new(idr); + iso9660_closedir(dir); + return result; + } + } + iso9660_closedir(dir); + return NULL; +} + +struct iso_directory_record* iso9660_get_node( + iso9660_VOLUME *volume, + struct iso_directory_record *dirnode, + const char *path) +{ + struct iso_directory_record* result; + struct iso_directory_record* current; + char name[256]; + int i; + + current = idr_new(dirnode); + while(1) + { + /* ignore head '\' */ + + while (*path && *path == '\\') + path++; + + if (*path == 0) + break; + + /* extract first path component */ + + i = 0; + while (*path && *path != '\\') + name[i++] = *path++; + name[i] = 0; + + /* seek first component in current directory */ + + result = seek_name(volume, current, name); + if (result == NULL) + return NULL; + + free(current); + current = result; + } + return current; +} + +iso9660_DIR* iso9660_opendir(iso9660_VOLUME *volume, const char *name) +{ + iso9660_DIR *dir; + struct iso_directory_record *node; + + node = iso9660_get_root_node((iso9660_VOLUME*)volume); + if (node == NULL) + return NULL; + + node = iso9660_get_node((iso9660_VOLUME*)volume, node, name); + if (node == NULL) + return NULL; + if (!iso9660_is_directory(node)) { + free(node); + return NULL; + } + + dir = iso9660_opendir_node((iso9660_VOLUME*)volume, node); + + free(node); + + dir->volume = (iso9660_VOLUME*)volume; + + return dir; +} diff --git a/qemu/roms/openbios/fs/iso9660/iso9660_read.c b/qemu/roms/openbios/fs/iso9660/iso9660_read.c new file mode 100644 index 000000000..22cc463f0 --- /dev/null +++ b/qemu/roms/openbios/fs/iso9660/iso9660_read.c @@ -0,0 +1,74 @@ +/* + * + * (c) 2005-2009 Laurent Vivier <Laurent@vivier.eu> + * + * This file has been copied from EMILE, http://emile.sf.net + * + */ + +#include "libiso9660.h" +#include "libopenbios/bindings.h" +#include "libc/diskio.h" + +size_t iso9660_read(iso9660_FILE *_file, char *buf, size_t count) +{ + iso9660_FILE *file = (iso9660_FILE*)_file; + size_t read = 0; + + if ( count > (file->size - file->offset) ) + count = file->size - file->offset; + + while (count > 0) + { + size_t part; + int offset_extent; + int offset_index; + + offset_extent = file->base + + (file->offset / ISOFS_BLOCK_SIZE); + offset_index = file->offset % ISOFS_BLOCK_SIZE; + + if (file->current != offset_extent) + { + if ( (offset_index == 0) && + (count >= ISOFS_BLOCK_SIZE) ) + { + /* direct i/o */ + + int extents_nb; + + extents_nb = count / ISOFS_BLOCK_SIZE; + + part = extents_nb * ISOFS_BLOCK_SIZE; + + seek_io(file->volume->fd, + offset_extent * ISOFS_BLOCK_SIZE); + read_io(file->volume->fd, buf + read, part); + + file->offset += part; + count -= part; + read += part; + + continue; + } + + file->current = offset_extent; + seek_io(file->volume->fd, + offset_extent * ISOFS_BLOCK_SIZE); + read_io(file->volume->fd, file->buffer, + ISOFS_BLOCK_SIZE); + } + + part = ISOFS_BLOCK_SIZE - offset_index; + if (count < part) + part = count; + + memcpy(buf + read, file->buffer + offset_index, part); + + file->offset += part; + count -= part; + read += part; + } + + return read; +} diff --git a/qemu/roms/openbios/fs/iso9660/iso9660_readdir.c b/qemu/roms/openbios/fs/iso9660/iso9660_readdir.c new file mode 100644 index 000000000..003ffb20f --- /dev/null +++ b/qemu/roms/openbios/fs/iso9660/iso9660_readdir.c @@ -0,0 +1,50 @@ +/* + * + * (c) 2005-2009 Laurent Vivier <Laurent@vivier.eu> + * + * This file has been copied from EMILE, http://emile.sf.net + * + */ + +#include "libiso9660.h" +#include "libopenbios/bindings.h" +#include "libc/diskio.h" + +#define offsetof(t,m) ((long)&(((t *)0)->m)) + +static void read_extent(iso9660_DIR *dir) +{ + seek_io(dir->volume->fd, dir->extent * ISOFS_BLOCK_SIZE); + read_io(dir->volume->fd, dir->buffer, ISOFS_BLOCK_SIZE); + + dir->len -= ISOFS_BLOCK_SIZE; + dir->extent ++; + dir->index = 0; +} + +struct iso_directory_record *iso9660_readdir(iso9660_DIR *dir) +{ + struct iso_directory_record *idr; + + if (dir->index > + ISOFS_BLOCK_SIZE - offsetof(struct iso_directory_record, name[0])) + { + if (dir->len <= 0) + return NULL; + + read_extent(dir); + } + + idr = (struct iso_directory_record *) &dir->buffer[dir->index]; + if (idr->length[0] == 0) { + if (dir->len <= 0) + return NULL; + + read_extent(dir); + idr = (struct iso_directory_record *) &dir->buffer[dir->index]; + } + + dir->index += dir->buffer[dir->index]; + + return idr; +} diff --git a/qemu/roms/openbios/fs/iso9660/libiso9660.h b/qemu/roms/openbios/fs/iso9660/libiso9660.h new file mode 100644 index 000000000..8a5b4801f --- /dev/null +++ b/qemu/roms/openbios/fs/iso9660/libiso9660.h @@ -0,0 +1,27 @@ +/* + * + * (c) 2005-2009 Laurent Vivier <Laurent@vivier.eu> + * + * This file has been copied from EMILE, http://emile.sf.net + * + */ + +#ifndef __LIBISO9660_H__ +#define __LIBISO9660_H__ + +#include "config.h" +#include "iso9660.h" + +extern iso9660_VOLUME* iso9660_mount(int fd); +extern int iso9660_umount(iso9660_VOLUME *volume); +extern int iso9660_probe(int fd, long long offs); +extern iso9660_DIR* iso9660_opendir(iso9660_VOLUME *, const char *name); +extern iso9660_FILE* iso9660_open(iso9660_VOLUME *, const char *pathname); +extern int iso9660_closedir(iso9660_DIR *dir); +extern struct iso_directory_record *iso9660_readdir(iso9660_DIR *dir); +extern size_t iso9660_read(iso9660_FILE *file, char *buf, size_t count); +extern void iso9660_close(iso9660_FILE *file); +extern int iso9660_lseek(iso9660_FILE *file, long offset, int whence); +extern void iso9660_name(iso9660_VOLUME *volume, struct iso_directory_record * idr, char *buffer); + +#endif /* __LIBISO9660_H__ */ diff --git a/qemu/roms/openbios/fs/os.h b/qemu/roms/openbios/fs/os.h new file mode 100644 index 000000000..b0375f7e2 --- /dev/null +++ b/qemu/roms/openbios/fs/os.h @@ -0,0 +1,57 @@ +/* + * libhfs - library for reading and writing Macintosh HFS volumes + * Copyright (C) 1996-1998, 2003 Robert Leslie + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * $Id: os.h,v 1.1.1.1 2000/07/25 10:33:40 kkaempf Exp $ + */ + +#ifndef _H_OS +#define _H_OS + +/* + * NAME: os->same() + * DESCRIPTION: return 1 iff path is same as the open descriptor + */ +int os_same( int fd1, int fd2 ); + +/* + * NAME: os->seek() + * DESCRIPTION: set a descriptor's seek pointer (offset in blocks) + */ +unsigned long os_seek( int fd, unsigned long offset, int blksize_bits); + +/* + * NAME: os->read() + * DESCRIPTION: read blocks from an open descriptor + */ +unsigned long os_read( int fd, void *buf, unsigned long len, int blksize_bits); + +/* + * NAME: os->write() + * DESCRIPTION: write blocks to an open descriptor + */ +unsigned long os_write( int fd, const void *buf, unsigned long len, int blksize_bits); + +/* + * NAME: os->seek_offset() + * DESCRIPTION: set a descriptor's seek pointer (offset in bytes) + */ +void os_seek_offset( int fd, long long offset ); + + +#endif /* _H_OS */ diff --git a/qemu/roms/openbios/include/arch/amd64/elf.h b/qemu/roms/openbios/include/arch/amd64/elf.h new file mode 100644 index 000000000..e391c62b6 --- /dev/null +++ b/qemu/roms/openbios/include/arch/amd64/elf.h @@ -0,0 +1,6 @@ +/* for now we're a 32bit architecture */ +#define ARCH_ELF_CLASS ELFCLASS32 +#define ARCH_ELF_DATA ELFDATA2LSB +#define ARCH_ELF_MACHINE_OK(x) ((x)==EM_386 || (x)==EM_486) +typedef Elf32_Ehdr Elf_ehdr; +typedef Elf32_Phdr Elf_phdr; diff --git a/qemu/roms/openbios/include/arch/amd64/io.h b/qemu/roms/openbios/include/arch/amd64/io.h new file mode 100644 index 000000000..9be1cb857 --- /dev/null +++ b/qemu/roms/openbios/include/arch/amd64/io.h @@ -0,0 +1,71 @@ +#ifndef _ASM_IO_H +#define _ASM_IO_H + +extern char _start, _end; +extern unsigned long virt_offset; + +#define phys_to_virt(phys) ((void *) ((unsigned long) (phys) - virt_offset)) +#define virt_to_phys(virt) ((unsigned long) (virt) + virt_offset) + +#ifndef BOOTSTRAP + +#define __SLOW_DOWN_IO "outb %%al,$0x80;" +static inline void slow_down_io(void) +{ + __asm__ __volatile__( + __SLOW_DOWN_IO +#ifdef REALLY_SLOW_IO + __SLOW_DOWN_IO __SLOW_DOWN_IO __SLOW_DOWN_IO +#endif + : : ); +} + +#define BUILDIO(bwl,bw,type) \ +static inline void out##bwl(unsigned type value, int port) { \ + __asm__ __volatile__("out" #bwl " %" #bw "0, %w1" : : "a"(value), "Nd"(port)); \ +} \ +static inline unsigned type in##bwl(int port) { \ + unsigned type value; \ + __asm__ __volatile__("in" #bwl " %w1, %" #bw "0" : "=a"(value) : "Nd"(port)); \ + return value; \ +} \ +static inline void out##bwl##_p(unsigned type value, int port) { \ + out##bwl(value, port); \ + slow_down_io(); \ +} \ +static inline unsigned type in##bwl##_p(int port) { \ + unsigned type value = in##bwl(port); \ + slow_down_io(); \ + return value; \ +} \ +static inline void outs##bwl(int port, const void *addr, unsigned long count) { \ + __asm__ __volatile__("rep; outs" #bwl : "+S"(addr), "+c"(count) : "d"(port)); \ +} \ +static inline void ins##bwl(int port, void *addr, unsigned long count) { \ + __asm__ __volatile__("rep; ins" #bwl : "+D"(addr), "+c"(count) : "d"(port)); \ +} + +BUILDIO(b,b,char) +BUILDIO(w,w,short) +BUILDIO(l,,int) + +#else /* BOOTSTRAP */ +#ifdef FCOMPILER +#define inb(reg) ((u8)0xff) +#define inw(reg) ((u16)0xffff) +#define inl(reg) ((u32)0xffffffff) +#define outb(reg, val) do{} while(0) +#define outw(reg, val) do{} while(0) +#define outl(reg, val) do{} while(0) +#else +extern u8 inb(u32 reg); +extern u16 inw(u32 reg); +extern u32 inl(u32 reg); +extern void insw(u32 reg, void *addr, unsigned long count); +extern void outb(u32 reg, u8 val); +extern void outw(u32 reg, u16 val); +extern void outl(u32 reg, u32 val); +extern void outsw(u32 reg, const void *addr, unsigned long count); +#endif +#endif +#endif diff --git a/qemu/roms/openbios/include/arch/amd64/pci.h b/qemu/roms/openbios/include/arch/amd64/pci.h new file mode 100644 index 000000000..3e88e150b --- /dev/null +++ b/qemu/roms/openbios/include/arch/amd64/pci.h @@ -0,0 +1,66 @@ +#ifndef AMD64_PCI_H +#define AMD64_PCI_H + +#include "asm/io.h" + +#if !(defined(PCI_CONFIG_1) || defined(PCI_CONFIG_2)) +#define PCI_CONFIG_1 1 /* default */ +#endif + +#ifdef PCI_CONFIG_1 + +/* PCI Configuration Mechanism #1 */ + +/* Have pci_addr in the same format as the values written to 0xcf8 + * so register accesses can be made easy. */ +#define PCI_ADDR(bus, dev, fn) \ + ((pci_addr) (0x80000000u \ + | (uint32_t) (bus) << 16 \ + | (uint32_t) (dev) << 11 \ + | (uint32_t) (fn) << 8)) + +#define PCI_BUS(pcidev) ((uint8_t) ((pcidev) >> 16)) +#define PCI_DEV(pcidev) ((uint8_t) ((pcidev) >> 11) & 0x1f) +#define PCI_FN(pcidev) ((uint8_t) ((pcidev) >> 8) & 7) + +static inline uint8_t pci_config_read8(pci_addr dev, uint8_t reg) +{ + outl(dev | (reg & ~3), 0xcf8); + return inb(0xcfc | (reg & 3)); +} + +static inline uint16_t pci_config_read16(pci_addr dev, uint8_t reg) +{ + outl(dev | (reg & ~3), 0xcf8); + return inw(0xcfc | (reg & 2)); +} + +static inline uint32_t pci_config_read32(pci_addr dev, uint8_t reg) +{ + outl(dev | reg, 0xcf8); + return inl(0xcfc | reg); +} + +static inline void pci_config_write8(pci_addr dev, uint8_t reg, uint8_t val) +{ + outl(dev | (reg & ~3), 0xcf8); + outb(val, 0xcfc | (reg & 3)); +} + +static inline void pci_config_write16(pci_addr dev, uint8_t reg, uint16_t val) +{ + outl(dev | (reg & ~3), 0xcf8); + outw(val, 0xcfc | (reg & 2)); +} + +static inline void pci_config_write32(pci_addr dev, uint8_t reg, uint32_t val) +{ + outl(dev | reg, 0xcf8); + outl(val, 0xcfc); +} + +#else /* !PCI_CONFIG_1 */ +#error PCI Configuration Mechanism is not specified or implemented +#endif + +#endif /* AMD64_PCI_H */ diff --git a/qemu/roms/openbios/include/arch/amd64/types.h b/qemu/roms/openbios/include/arch/amd64/types.h new file mode 100644 index 000000000..5b146cada --- /dev/null +++ b/qemu/roms/openbios/include/arch/amd64/types.h @@ -0,0 +1,67 @@ +/* tag: data types for forth engine + * + * This file is autogenerated by types.sh. Do not edit! + * + * Copyright (C) 2003 Patrick Mauritz, Stefan Reinauer + * + * See the file "COPYING" for further information about + * the copyright and warranty status of this work. + */ + +#ifndef __TYPES_H +#define __TYPES_H + +#include <inttypes.h> + +/* endianess */ +#include "autoconf.h" + +/* physical address */ + +typedef uint64_t phys_addr_t; + +#define FMT_plx "%016" PRIx64 + +/* cell based types */ + +typedef int64_t cell; +typedef uint64_t ucell; +typedef __int128_t dcell; +typedef __uint128_t ducell; + +#define FMT_cell "%" PRId64 +#define FMT_ucellx "%016" PRIx64 +#define FMT_ucell "%" PRIu64 + +typedef int64_t prom_arg_t; +typedef uint64_t prom_uarg_t; + +#define PRIdPROMARG PRId64 +#define PRIuPROMARG PRIu64 +#define PRIxPROMARG PRIx64 +#define FMT_prom_arg "%" PRIdPROMARG +#define FMT_prom_uarg "%" PRIuPROMARG +#define FMT_prom_uargx "%016" PRIxPROMARG + +#define FMT_elf "%#x" + +#define bitspercell (sizeof(cell)<<3) +#define bitsperdcell (sizeof(dcell)<<3) + +#define BITS 64 + +#define PAGE_SHIFT 12 + +/* size named types */ + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned int u32; +typedef unsigned long u64; + +typedef char s8; +typedef short s16; +typedef int s32; +typedef long s64; + +#endif diff --git a/qemu/roms/openbios/include/arch/common/a.out.h b/qemu/roms/openbios/include/arch/common/a.out.h new file mode 100644 index 000000000..350babd75 --- /dev/null +++ b/qemu/roms/openbios/include/arch/common/a.out.h @@ -0,0 +1,271 @@ +#ifndef __A_OUT_GNU_H__ +#define __A_OUT_GNU_H__ + +#define __GNU_EXEC_MACROS__ + +#ifndef __STRUCT_EXEC_OVERRIDE__ + +#include "asm/a.out.h" + +#endif /* __STRUCT_EXEC_OVERRIDE__ */ + +/* these go in the N_MACHTYPE field */ +enum machine_type { +#if defined (M_OLDSUN2) + M__OLDSUN2 = M_OLDSUN2, +#else + M_OLDSUN2 = 0, +#endif +#if defined (M_68010) + M__68010 = M_68010, +#else + M_68010 = 1, +#endif +#if defined (M_68020) + M__68020 = M_68020, +#else + M_68020 = 2, +#endif +#if defined (M_SPARC) + M__SPARC = M_SPARC, +#else + M_SPARC = 3, +#endif + /* skip a bunch so we don't run into any of sun's numbers */ + M_386 = 100, + M_MIPS1 = 151, /* MIPS R3000/R3000 binary */ + M_MIPS2 = 152 /* MIPS R6000/R4000 binary */ +}; + +#if !defined (N_MAGIC) +#define N_MAGIC(exec) ((exec).a_info & 0xffff) +#endif +#define N_MACHTYPE(exec) ((enum machine_type)(((exec).a_info >> 16) & 0xff)) +#define N_FLAGS(exec) (((exec).a_info >> 24) & 0xff) +#define N_SET_INFO(exec, magic, type, flags) \ + ((exec).a_info = ((magic) & 0xffff) \ + | (((int)(type) & 0xff) << 16) \ + | (((flags) & 0xff) << 24)) +#define N_SET_MAGIC(exec, magic) \ + ((exec).a_info = (((exec).a_info & 0xffff0000) | ((magic) & 0xffff))) + +#define N_SET_MACHTYPE(exec, machtype) \ + ((exec).a_info = \ + ((exec).a_info&0xff00ffff) | ((((int)(machtype))&0xff) << 16)) + +#define N_SET_FLAGS(exec, flags) \ + ((exec).a_info = \ + ((exec).a_info&0x00ffffff) | (((flags) & 0xff) << 24)) + +/* Code indicating object file or impure executable. */ +#define OMAGIC 0407 +/* Code indicating pure executable. */ +#define NMAGIC 0410 +/* Code indicating demand-paged executable. */ +#define ZMAGIC 0413 +/* This indicates a demand-paged executable with the header in the text. + The first page is unmapped to help trap NULL pointer references */ +#define QMAGIC 0314 + +/* Code indicating core file. */ +#define CMAGIC 0421 + +#if !defined (N_BADMAG) +#define N_BADMAG(x) (N_MAGIC(x) != OMAGIC \ + && N_MAGIC(x) != NMAGIC \ + && N_MAGIC(x) != ZMAGIC \ + && N_MAGIC(x) != QMAGIC) +#endif + +#define _N_HDROFF(x) (1024 - sizeof (struct exec)) + +#if !defined (N_TXTOFF) +#define N_TXTOFF(x) \ + (N_MAGIC(x) == ZMAGIC ? _N_HDROFF((x)) + sizeof (struct exec) : \ + (N_MAGIC(x) == QMAGIC ? 0 : sizeof (struct exec))) +#endif + +#if !defined (N_DATOFF) +#define N_DATOFF(x) (N_TXTOFF(x) + (x).a_text) +#endif + +#if !defined (N_TRELOFF) +#define N_TRELOFF(x) (N_DATOFF(x) + (x).a_data) +#endif + +#if !defined (N_DRELOFF) +#define N_DRELOFF(x) (N_TRELOFF(x) + N_TRSIZE(x)) +#endif + +#if !defined (N_SYMOFF) +#define N_SYMOFF(x) (N_DRELOFF(x) + N_DRSIZE(x)) +#endif + +#if !defined (N_STROFF) +#define N_STROFF(x) (N_SYMOFF(x) + N_SYMSIZE(x)) +#endif + +/* Address of text segment in memory after it is loaded. */ +#if !defined (N_TXTADDR) +#define N_TXTADDR(x) (N_MAGIC(x) == QMAGIC ? PAGE_SIZE : 0) +#endif + +/* Address of data segment in memory after it is loaded. + Note that it is up to you to define SEGMENT_SIZE + on machines not listed here. */ +#if defined(vax) || defined(hp300) || defined(pyr) +#define SEGMENT_SIZE page_size +#endif +#ifdef sony +#define SEGMENT_SIZE 0x2000 +#endif /* Sony. */ +#ifdef is68k +#define SEGMENT_SIZE 0x20000 +#endif +#if defined(m68k) && defined(PORTAR) +#define PAGE_SIZE 0x400 +#define SEGMENT_SIZE PAGE_SIZE +#endif + +#if !defined(SEGMENT_SIZE) +#ifdef linux +#if defined(__i386__) || defined(__mc68000__) +#define SEGMENT_SIZE 1024 +#elif defined(__sparc__) +#define SEGMENT_SIZE 0x2000 +#else +#if defined(PAGE_SIZE) +#define SEGMENT_SIZE PAGE_SIZE +#endif +#endif +#endif +#endif + +#define _N_SEGMENT_ROUND(x) (((x) + SEGMENT_SIZE - 1) & ~(SEGMENT_SIZE - 1)) + +#define _N_TXTENDADDR(x) (N_TXTADDR(x)+(x).a_text) + +#ifndef N_DATADDR +#define N_DATADDR(x) \ + (N_MAGIC(x)==OMAGIC? (_N_TXTENDADDR(x)) \ + : (_N_SEGMENT_ROUND (_N_TXTENDADDR(x)))) +#endif + +/* Address of bss segment in memory after it is loaded. */ +#if !defined (N_BSSADDR) +#define N_BSSADDR(x) (N_DATADDR(x) + (x).a_data) +#endif + +#if !defined (N_NLIST_DECLARED) +struct nlist { + union { + char *n_name; + struct nlist *n_next; + long n_strx; + } n_un; + unsigned char n_type; + char n_other; + short n_desc; + unsigned long n_value; +}; +#endif /* no N_NLIST_DECLARED. */ + +#if !defined (N_UNDF) +#define N_UNDF 0 +#endif +#if !defined (N_ABS) +#define N_ABS 2 +#endif +#if !defined (N_TEXT) +#define N_TEXT 4 +#endif +#if !defined (N_DATA) +#define N_DATA 6 +#endif +#if !defined (N_BSS) +#define N_BSS 8 +#endif +#if !defined (N_FN) +#define N_FN 15 +#endif + +#if !defined (N_EXT) +#define N_EXT 1 +#endif +#if !defined (N_TYPE) +#define N_TYPE 036 +#endif +#if !defined (N_STAB) +#define N_STAB 0340 +#endif + +/* The following type indicates the definition of a symbol as being + an indirect reference to another symbol. The other symbol + appears as an undefined reference, immediately following this symbol. + + Indirection is asymmetrical. The other symbol's value will be used + to satisfy requests for the indirect symbol, but not vice versa. + If the other symbol does not have a definition, libraries will + be searched to find a definition. */ +#define N_INDR 0xa + +/* The following symbols refer to set elements. + All the N_SET[ATDB] symbols with the same name form one set. + Space is allocated for the set in the text section, and each set + element's value is stored into one word of the space. + The first word of the space is the length of the set (number of elements). + + The address of the set is made into an N_SETV symbol + whose name is the same as the name of the set. + This symbol acts like a N_DATA global symbol + in that it can satisfy undefined external references. */ + +/* These appear as input to LD, in a .o file. */ +#define N_SETA 0x14 /* Absolute set element symbol */ +#define N_SETT 0x16 /* Text set element symbol */ +#define N_SETD 0x18 /* Data set element symbol */ +#define N_SETB 0x1A /* Bss set element symbol */ + +/* This is output from LD. */ +#define N_SETV 0x1C /* Pointer to set vector in data area. */ + +#if !defined (N_RELOCATION_INFO_DECLARED) +/* This structure describes a single relocation to be performed. + The text-relocation section of the file is a vector of these structures, + all of which apply to the text section. + Likewise, the data-relocation section applies to the data section. */ + +struct relocation_info +{ + /* Address (within segment) to be relocated. */ + int r_address; + /* The meaning of r_symbolnum depends on r_extern. */ + unsigned int r_symbolnum:24; + /* Nonzero means value is a pc-relative offset + and it should be relocated for changes in its own address + as well as for changes in the symbol or section specified. */ + unsigned int r_pcrel:1; + /* Length (as exponent of 2) of the field to be relocated. + Thus, a value of 2 indicates 1<<2 bytes. */ + unsigned int r_length:2; + /* 1 => relocate with value of symbol. + r_symbolnum is the index of the symbol + in file's the symbol table. + 0 => relocate with the address of a segment. + r_symbolnum is N_TEXT, N_DATA, N_BSS or N_ABS + (the N_EXT bit may be set also, but signifies nothing). */ + unsigned int r_extern:1; + /* Four bits that aren't used, but when writing an object file + it is desirable to clear them. */ +#ifdef NS32K + unsigned r_bsr:1; + unsigned r_disp:1; + unsigned r_pad:2; +#else + unsigned int r_pad:4; +#endif +}; +#endif /* no N_RELOCATION_INFO_DECLARED. */ + + +#endif /* __A_OUT_GNU_H__ */ diff --git a/qemu/roms/openbios/include/arch/common/elf.h b/qemu/roms/openbios/include/arch/common/elf.h new file mode 100644 index 000000000..f2cca558a --- /dev/null +++ b/qemu/roms/openbios/include/arch/common/elf.h @@ -0,0 +1,227 @@ +#ifndef ELF_H +#define ELF_H + +#define EI_NIDENT 16 /* Size of e_ident array. */ + +/* Values for e_type. */ +#define ET_NONE 0 /* No file type */ +#define ET_REL 1 /* Relocatable file */ +#define ET_EXEC 2 /* Executable file */ +#define ET_DYN 3 /* Shared object file */ +#define ET_CORE 4 /* Core file */ + +/* Values for e_machine (architecute). */ +#define EM_NONE 0 /* No machine */ +#define EM_M32 1 /* AT&T WE 32100 */ +#define EM_SPARC 2 /* SUN SPARC */ +#define EM_386 3 /* Intel 80386+ */ +#define EM_68K 4 /* Motorola m68k family */ +#define EM_88K 5 /* Motorola m88k family */ +#define EM_486 6 /* Perhaps disused */ +#define EM_860 7 /* Intel 80860 */ +#define EM_MIPS 8 /* MIPS R3000 big-endian */ +#define EM_S370 9 /* IBM System/370 */ +#define EM_MIPS_RS3_LE 10 /* MIPS R3000 little-endian */ + +#define EM_PARISC 15 /* HPPA */ +#define EM_VPP500 17 /* Fujitsu VPP500 */ +#define EM_SPARC32PLUS 18 /* Sun's "v8plus" */ +#define EM_960 19 /* Intel 80960 */ +#define EM_PPC 20 /* PowerPC */ +#define EM_PPC64 21 /* PowerPC 64-bit */ +#define EM_S390 22 /* IBM S390 */ + +#define EM_V800 36 /* NEC V800 series */ +#define EM_FR20 37 /* Fujitsu FR20 */ +#define EM_RH32 38 /* TRW RH-32 */ +#define EM_RCE 39 /* Motorola RCE */ +#define EM_ARM 40 /* ARM */ +#define EM_FAKE_ALPHA 41 /* Digital Alpha */ +#define EM_SH 42 /* Hitachi SH */ +#define EM_SPARCV9 43 /* SPARC v9 64-bit */ +#define EM_TRICORE 44 /* Siemens Tricore */ +#define EM_ARC 45 /* Argonaut RISC Core */ +#define EM_H8_300 46 /* Hitachi H8/300 */ +#define EM_H8_300H 47 /* Hitachi H8/300H */ +#define EM_H8S 48 /* Hitachi H8S */ +#define EM_H8_500 49 /* Hitachi H8/500 */ +#define EM_IA_64 50 /* Intel Merced */ +#define EM_MIPS_X 51 /* Stanford MIPS-X */ +#define EM_COLDFIRE 52 /* Motorola Coldfire */ +#define EM_68HC12 53 /* Motorola M68HC12 */ +#define EM_MMA 54 /* Fujitsu MMA Multimedia Accelerator*/ +#define EM_PCP 55 /* Siemens PCP */ +#define EM_NCPU 56 /* Sony nCPU embeeded RISC */ +#define EM_NDR1 57 /* Denso NDR1 microprocessor */ +#define EM_STARCORE 58 /* Motorola Start*Core processor */ +#define EM_ME16 59 /* Toyota ME16 processor */ +#define EM_ST100 60 /* STMicroelectronic ST100 processor */ +#define EM_TINYJ 61 /* Advanced Logic Corp. Tinyj emb.fam*/ +#define EM_X86_64 62 /* AMD x86-64 architecture */ +#define EM_PDSP 63 /* Sony DSP Processor */ + +#define EM_FX66 66 /* Siemens FX66 microcontroller */ +#define EM_ST9PLUS 67 /* STMicroelectronics ST9+ 8/16 mc */ +#define EM_ST7 68 /* STmicroelectronics ST7 8 bit mc */ +#define EM_68HC16 69 /* Motorola MC68HC16 microcontroller */ +#define EM_68HC11 70 /* Motorola MC68HC11 microcontroller */ +#define EM_68HC08 71 /* Motorola MC68HC08 microcontroller */ +#define EM_68HC05 72 /* Motorola MC68HC05 microcontroller */ +#define EM_SVX 73 /* Silicon Graphics SVx */ +#define EM_AT19 74 /* STMicroelectronics ST19 8 bit mc */ +#define EM_VAX 75 /* Digital VAX */ +#define EM_CRIS 76 /* Axis Communications 32-bit embedded processor */ +#define EM_JAVELIN 77 /* Infineon Technologies 32-bit embedded processor */ +#define EM_FIREPATH 78 /* Element 14 64-bit DSP Processor */ +#define EM_ZSP 79 /* LSI Logic 16-bit DSP Processor */ +#define EM_MMIX 80 /* Donald Knuth's educational 64-bit processor */ +#define EM_HUANY 81 /* Harvard University machine-independent object files */ +#define EM_PRISM 82 /* SiTera Prism */ +#define EM_AVR 83 /* Atmel AVR 8-bit microcontroller */ +#define EM_FR30 84 /* Fujitsu FR30 */ +#define EM_D10V 85 /* Mitsubishi D10V */ +#define EM_D30V 86 /* Mitsubishi D30V */ +#define EM_V850 87 /* NEC v850 */ +#define EM_M32R 88 /* Mitsubishi M32R */ +#define EM_MN10300 89 /* Matsushita MN10300 */ +#define EM_MN10200 90 /* Matsushita MN10200 */ +#define EM_PJ 91 /* picoJava */ +#define EM_OPENRISC 92 /* OpenRISC 32-bit embedded processor */ +#define EM_ARC_A5 93 /* ARC Cores Tangent-A5 */ +#define EM_XTENSA 94 /* Tensilica Xtensa Architecture */ +#define EM_NUM 95 + +/* Values for p_type. */ +#define PT_NULL 0 /* Unused entry. */ +#define PT_LOAD 1 /* Loadable segment. */ +#define PT_DYNAMIC 2 /* Dynamic linking information segment. */ +#define PT_INTERP 3 /* Pathname of interpreter. */ +#define PT_NOTE 4 /* Auxiliary information. */ +#define PT_SHLIB 5 /* Reserved (not used). */ +#define PT_PHDR 6 /* Location of program header itself. */ + +/* Values for p_flags. */ +#define PF_X 0x1 /* Executable. */ +#define PF_W 0x2 /* Writable. */ +#define PF_R 0x4 /* Readable. */ + + +#define ELF_PROGRAM_RETURNS_BIT 0x8000000 /* e_flags bit 31 */ + +#define EI_MAG0 0 +#define ELFMAG0 0x7f + +#define EI_MAG1 1 +#define ELFMAG1 'E' + +#define EI_MAG2 2 +#define ELFMAG2 'L' + +#define EI_MAG3 3 +#define ELFMAG3 'F' + +#define ELFMAG "\177ELF" + +#define EI_CLASS 4 /* File class byte index */ +#define ELFCLASSNONE 0 /* Invalid class */ +#define ELFCLASS32 1 /* 32-bit objects */ +#define ELFCLASS64 2 /* 64-bit objects */ + +#define EI_DATA 5 /* Data encodeing byte index */ +#define ELFDATANONE 0 /* Invalid data encoding */ +#define ELFDATA2LSB 1 /* 2's complement little endian */ +#define ELFDATA2MSB 2 /* 2's complement big endian */ + +#define EI_VERSION 6 /* File version byte index */ + /* Value must be EV_CURRENT */ + +#define EV_NONE 0 /* Invalid ELF Version */ +#define EV_CURRENT 1 /* Current version */ + +#define ELF32_PHDR_SIZE (8*4) /* Size of an elf program header */ + +#ifndef __ASSEMBLY__ +#include "asm/types.h" +/* + * ELF definitions common to all 32-bit architectures. + */ + +typedef uint32_t Elf32_Addr; +typedef uint16_t Elf32_Half; +typedef uint32_t Elf32_Off; +typedef int32_t Elf32_Sword; +typedef uint32_t Elf32_Word; +typedef uint32_t Elf32_Size; + +typedef uint64_t Elf64_Addr; +typedef uint16_t Elf64_Half; +typedef uint64_t Elf64_Off; +typedef int32_t Elf64_Sword; +typedef uint32_t Elf64_Word; +typedef uint64_t Elf64_Size; + +/* + * ELF header. + */ +typedef struct { + unsigned char e_ident[EI_NIDENT]; /* File identification. */ + Elf32_Half e_type; /* File type. */ + Elf32_Half e_machine; /* Machine architecture. */ + Elf32_Word e_version; /* ELF format version. */ + Elf32_Addr e_entry; /* Entry point. */ + Elf32_Off e_phoff; /* Program header file offset. */ + Elf32_Off e_shoff; /* Section header file offset. */ + Elf32_Word e_flags; /* Architecture-specific flags. */ + Elf32_Half e_ehsize; /* Size of ELF header in bytes. */ + Elf32_Half e_phentsize; /* Size of program header entry. */ + Elf32_Half e_phnum; /* Number of program header entries. */ + Elf32_Half e_shentsize; /* Size of section header entry. */ + Elf32_Half e_shnum; /* Number of section header entries. */ + Elf32_Half e_shstrndx; /* Section name strings section. */ +} Elf32_Ehdr; + +typedef struct { + unsigned char e_ident[EI_NIDENT]; /* File identification. */ + Elf64_Half e_type; /* File type. */ + Elf64_Half e_machine; /* Machine architecture. */ + Elf64_Word e_version; /* ELF format version. */ + Elf64_Addr e_entry; /* Entry point. */ + Elf64_Off e_phoff; /* Program header file offset. */ + Elf64_Off e_shoff; /* Section header file offset. */ + Elf64_Word e_flags; /* Architecture-specific flags. */ + Elf64_Half e_ehsize; /* Size of ELF header in bytes. */ + Elf64_Half e_phentsize; /* Size of program header entry. */ + Elf64_Half e_phnum; /* Number of program header entries. */ + Elf64_Half e_shentsize; /* Size of section header entry. */ + Elf64_Half e_shnum; /* Number of section header entries. */ + Elf64_Half e_shstrndx; /* Section name strings section. */ +} Elf64_Ehdr; + +/* + * Program header. + */ +typedef struct { + Elf32_Word p_type; /* Entry type. */ + Elf32_Off p_offset; /* File offset of contents. */ + Elf32_Addr p_vaddr; /* Virtual address (not used). */ + Elf32_Addr p_paddr; /* Physical address. */ + Elf32_Size p_filesz; /* Size of contents in file. */ + Elf32_Size p_memsz; /* Size of contents in memory. */ + Elf32_Word p_flags; /* Access permission flags. */ + Elf32_Size p_align; /* Alignment in memory and file. */ +} Elf32_Phdr; + +typedef struct { + Elf64_Word p_type; /* Entry type. */ + Elf64_Word p_flags; /* Access permission flags. */ + Elf64_Off p_offset; /* File offset of contents. */ + Elf64_Addr p_vaddr; /* Virtual address (not used). */ + Elf64_Addr p_paddr; /* Physical address. */ + Elf64_Size p_filesz; /* Size of contents in file. */ + Elf64_Size p_memsz; /* Size of contents in memory. */ + Elf64_Size p_align; /* Alignment in memory and file. */ +} Elf64_Phdr; + +#endif /* __ASSEMBLY__ */ + +#endif /* ELF_H */ diff --git a/qemu/roms/openbios/include/arch/common/elf_boot.h b/qemu/roms/openbios/include/arch/common/elf_boot.h new file mode 100644 index 000000000..18487f6b0 --- /dev/null +++ b/qemu/roms/openbios/include/arch/common/elf_boot.h @@ -0,0 +1,105 @@ +#ifndef ELF_BOOT_H +#define ELF_BOOT_H + + +/* This defines the structure of a table of parameters useful for ELF + * bootable images. These parameters are all passed and generated + * by the bootloader to the booted image. For simplicity and + * consistency the Elf Note format is reused. + * + * All of the information must be Position Independent Data. + * That is it must be safe to relocate the whole ELF boot parameter + * block without changing the meaning or correctnes of the data. + * Additionally it must be safe to permute the order of the ELF notes + * to any possible permutation without changing the meaning or correctness + * of the data. + * + */ + +#define ELF_BHDR_MAGIC 0x0E1FB007 + +#ifndef __ASSEMBLY__ +typedef uint16_t Elf_Half; +typedef uint32_t Elf_Word; + +/* + * Elf boot notes... + */ + +typedef struct Elf_Bhdr +{ + Elf_Word b_signature; /* "0x0E1FB007" */ + Elf_Word b_size; + Elf_Half b_checksum; + Elf_Half b_records; +} Elf_Bhdr; + +/* + * ELF Notes. + */ + +typedef struct Elf_Nhdr +{ + Elf_Word n_namesz; /* Length of the note's name. */ + Elf_Word n_descsz; /* Length of the note's descriptor. */ + Elf_Word n_type; /* Type of the note. */ +} Elf_Nhdr; + +#endif /* __ASSEMBLY__ */ + +/* Standardized Elf image notes for booting... The name for all of these is ELFBoot */ +#define ELF_NOTE_BOOT "ELFBoot" + +#define EIN_PROGRAM_NAME 0x00000001 +/* The program in this ELF file */ +#define EIN_PROGRAM_VERSION 0x00000002 +/* The version of the program in this ELF file */ +#define EIN_PROGRAM_CHECKSUM 0x00000003 +/* ip style checksum of the memory image. */ + + +/* Linux image notes for booting... The name for all of these is Linux */ + +#define LIN_COMMAND_LINE 0x00000001 +/* The command line to pass to the loaded kernel. */ +#define LIN_ROOT_DEV 0x00000002 +/* The root dev to pass to the loaded kernel. */ +#define LIN_RAMDISK_FLAGS 0x00000003 +/* Various old ramdisk flags */ +#define LIN_INITRD_START 0x00000004 +/* Start of the ramdisk in bytes */ +#define LIN_INITRD_SIZE 0x00000005 +/* Size of the ramdisk in bytes */ + +/* Notes that are passed to a loaded image */ +/* For the standard elf boot notes n_namesz must be zero */ +#define EBN_FIRMWARE_TYPE 0x00000001 +/* ASCIZ name of the platform firmware. */ +#define EBN_BOOTLOADER_NAME 0x00000002 +/* This specifies just the ASCIZ name of the bootloader */ +#define EBN_BOOTLOADER_VERSION 0x00000003 +/* This specifies the version of the bootloader as an ASCIZ string */ +#define EBN_COMMAND_LINE 0x00000004 +/* This specifies a command line that can be set by user interaction, + * and is provided as a free form ASCIZ string to the loaded image. + */ +#define EBN_NOP 0x00000005 +/* A note nop note has no meaning, useful for inserting explicit padding */ +#define EBN_LOADED_IMAGE 0x00000006 +/* An ASCIZ string naming the loaded image */ + + +/* Etherboot specific notes */ +#define EB_PARAM_NOTE "Etherboot" +#define EB_IA64_SYSTAB 0x00000001 +#define EB_IA64_MEMMAP 0x00000002 +#define EB_IA64_FPSWA 0x00000003 +#define EB_IA64_CONINFO 0x00000004 +#define EB_BOOTP_DATA 0x00000005 +#define EB_HEADER 0x00000006 +#define EB_IA64_IMAGE_HANDLE 0x00000007 +#define EB_I386_MEMMAP 0x00000008 + +extern const struct elf_image_note elf_image_notes; + +#endif /* ELF_BOOT_H */ diff --git a/qemu/roms/openbios/include/arch/common/fw_cfg.h b/qemu/roms/openbios/include/arch/common/fw_cfg.h new file mode 100644 index 000000000..df44c2e89 --- /dev/null +++ b/qemu/roms/openbios/include/arch/common/fw_cfg.h @@ -0,0 +1,90 @@ +#ifndef FW_CFG_H +#define FW_CFG_H + +#define FW_CFG_SIGNATURE 0x00 +#define FW_CFG_ID 0x01 +#define FW_CFG_UUID 0x02 +#define FW_CFG_RAM_SIZE 0x03 +#define FW_CFG_NOGRAPHIC 0x04 +#define FW_CFG_NB_CPUS 0x05 +#define FW_CFG_MACHINE_ID 0x06 +#define FW_CFG_KERNEL_ADDR 0x07 +#define FW_CFG_KERNEL_SIZE 0x08 +#define FW_CFG_KERNEL_CMDLINE 0x09 +#define FW_CFG_INITRD_ADDR 0x0a +#define FW_CFG_INITRD_SIZE 0x0b +#define FW_CFG_BOOT_DEVICE 0x0c +#define FW_CFG_NUMA 0x0d +#define FW_CFG_BOOT_MENU 0x0e +#define FW_CFG_MAX_CPUS 0x0f +#define FW_CFG_KERNEL_ENTRY 0x10 +#define FW_CFG_KERNEL_DATA 0x11 +#define FW_CFG_INITRD_DATA 0x12 +#define FW_CFG_CMDLINE_ADDR 0x13 +#define FW_CFG_CMDLINE_SIZE 0x14 +#define FW_CFG_CMDLINE_DATA 0x15 +#define FW_CFG_SETUP_ADDR 0x16 +#define FW_CFG_SETUP_SIZE 0x17 +#define FW_CFG_SETUP_DATA 0x18 +#define FW_CFG_FILE_DIR 0x19 + +#define FW_CFG_FILE_FIRST 0x20 +#define FW_CFG_FILE_SLOTS 0x10 +#define FW_CFG_MAX_ENTRY (FW_CFG_FILE_FIRST+FW_CFG_FILE_SLOTS) + +#define FW_CFG_WRITE_CHANNEL 0x4000 +#define FW_CFG_ARCH_LOCAL 0x8000 +#define FW_CFG_ENTRY_MASK ~(FW_CFG_WRITE_CHANNEL | FW_CFG_ARCH_LOCAL) + +#define FW_CFG_PPC_WIDTH (FW_CFG_ARCH_LOCAL + 0x00) +#define FW_CFG_PPC_HEIGHT (FW_CFG_ARCH_LOCAL + 0x01) +#define FW_CFG_PPC_DEPTH (FW_CFG_ARCH_LOCAL + 0x02) +#define FW_CFG_PPC_TBFREQ (FW_CFG_ARCH_LOCAL + 0x03) +#define FW_CFG_PPC_CLOCKFREQ (FW_CFG_ARCH_LOCAL + 0x04) +#define FW_CFG_PPC_IS_KVM (FW_CFG_ARCH_LOCAL + 0x05) +#define FW_CFG_PPC_KVM_HC (FW_CFG_ARCH_LOCAL + 0x06) +#define FW_CFG_PPC_KVM_PID (FW_CFG_ARCH_LOCAL + 0x07) +#define FW_CFG_PPC_NVRAM_ADDR (FW_CFG_ARCH_LOCAL + 0x08) +#define FW_CFG_PPC_BUSFREQ (FW_CFG_ARCH_LOCAL + 0x09) +#define FW_CFG_PPC_NVRAM_FLAT (FW_CFG_ARCH_LOCAL + 0x0a) + +#define FW_CFG_INVALID 0xffff + +#ifndef NO_QEMU_PROTOS +typedef struct FWCfgFile { + uint32_t size; /* file size */ + uint16_t select; /* write this to 0x510 to read it */ + uint16_t reserved; + char name[56]; +} FWCfgFile; + +typedef struct FWCfgFiles { + uint32_t count; + FWCfgFile f[]; +} FWCfgFiles; + +typedef void (*FWCfgCallback)(void *opaque, uint8_t *data); + +typedef struct _FWCfgState FWCfgState; +int fw_cfg_add_bytes(FWCfgState *s, uint16_t key, uint8_t *data, uint32_t len); +int fw_cfg_add_i16(FWCfgState *s, uint16_t key, uint16_t value); +int fw_cfg_add_i32(FWCfgState *s, uint16_t key, uint32_t value); +int fw_cfg_add_i64(FWCfgState *s, uint16_t key, uint64_t value); +int fw_cfg_add_callback(FWCfgState *s, uint16_t key, FWCfgCallback callback, + void *callback_opaque, uint8_t *data, size_t len); +int fw_cfg_add_file(FWCfgState *s, const char *dir, const char *filename, + uint8_t *data, uint32_t len); +FWCfgState *fw_cfg_init(uint32_t ctl_port, uint32_t data_port, + target_phys_addr_t crl_addr, target_phys_addr_t data_addr); + +#endif /* NO_QEMU_PROTOS */ + +#ifndef NO_OPENBIOS_PROTOS +void fw_cfg_read(uint16_t cmd, char *buf, unsigned int nbytes); +uint64_t fw_cfg_read_i64(uint16_t cmd); +uint32_t fw_cfg_read_i32(uint16_t cmd); +uint16_t fw_cfg_read_i16(uint16_t cmd); +void fw_cfg_init(void); +#endif /* NO_OPENBIOS_PROTOS */ + +#endif diff --git a/qemu/roms/openbios/include/arch/common/nvram.h b/qemu/roms/openbios/include/arch/common/nvram.h new file mode 100644 index 000000000..41b31ca78 --- /dev/null +++ b/qemu/roms/openbios/include/arch/common/nvram.h @@ -0,0 +1,24 @@ +/* + * Creation Date: <2003/12/20 01:04:25 samuel> + * Time-stamp: <2004/01/07 19:59:11 samuel> + * + * <nvram.h> + * + * arch NVRAM interface + * + * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#ifndef _H_NVRAM +#define _H_NVRAM + +extern int arch_nvram_size( void ); +extern void arch_nvram_get( char *buf ); +extern void arch_nvram_put( char *buf ); + +#endif /* _H_NVRAM */ diff --git a/qemu/roms/openbios/include/arch/common/xcoff.h b/qemu/roms/openbios/include/arch/common/xcoff.h new file mode 100644 index 000000000..99106fe81 --- /dev/null +++ b/qemu/roms/openbios/include/arch/common/xcoff.h @@ -0,0 +1,98 @@ +#ifndef XCOFF_H +#define XCOFF_H + +/* XCOFF executable loader */ + +typedef struct COFF_filehdr_t { + uint16_t f_magic; /* magic number */ + uint16_t f_nscns; /* number of sections */ + uint32_t f_timdat; /* time & date stamp */ + uint32_t f_symptr; /* file pointer to symtab */ + uint32_t f_nsyms; /* number of symtab entries */ + uint16_t f_opthdr; /* sizeof(optional hdr) */ + uint16_t f_flags; /* flags */ +} COFF_filehdr_t; + +/* IBM RS/6000 */ + +#define U802WRMAGIC 0x02DA /* writeable text segments **chh** */ +#define U802ROMAGIC 0x02DF /* readonly sharable text segments */ +#define U802TOCMAGIC 0x02E1 /* readonly text segments and TOC */ +#define U802TOMAGIC 0x01DF + +/* + * Bits for f_flags: + * + * F_RELFLG relocation info stripped from file + * F_EXEC file is executable (i.e. no unresolved external + * references) + * F_LNNO line numbers stripped from file + * F_LSYMS local symbols stripped from file + * F_MINMAL this is a minimal object file (".m") output of fextract + * F_UPDATE this is a fully bound update file, output of ogen + * F_SWABD this file has had its bytes swabbed (in names) + * F_AR16WR this file has the byte ordering of an AR16WR + * (e.g. 11/70) machine + * F_AR32WR this file has the byte ordering of an AR32WR machine + * (e.g. vax and iNTEL 386) + * F_AR32W this file has the byte ordering of an AR32W machine + * (e.g. 3b,maxi) + * F_PATCH file contains "patch" list in optional header + * F_NODF (minimal file only) no decision functions for + * replaced functions + */ + +#define COFF_F_RELFLG 0000001 +#define COFF_F_EXEC 0000002 +#define COFF_F_LNNO 0000004 +#define COFF_F_LSYMS 0000010 +#define COFF_F_MINMAL 0000020 +#define COFF_F_UPDATE 0000040 +#define COFF_F_SWABD 0000100 +#define COFF_F_AR16WR 0000200 +#define COFF_F_AR32WR 0000400 +#define COFF_F_AR32W 0001000 +#define COFF_F_PATCH 0002000 +#define COFF_F_NODF 0002000 + +typedef struct COFF_aouthdr_t { + uint16_t magic; /* type of file */ + uint16_t vstamp; /* version stamp */ + uint32_t tsize; /* text size in bytes, padded to FW bdry */ + uint32_t dsize; /* initialized data " " */ + uint32_t bsize; /* uninitialized data " " */ + uint32_t entry; /* entry pt. */ + uint32_t text_start; /* base of text used for this file */ + uint32_t data_start; /* base of data used for this file */ + uint32_t o_toc; /* address of TOC */ + uint16_t o_snentry; /* section number of entry point */ + uint16_t o_sntext; /* section number of .text section */ + uint16_t o_sndata; /* section number of .data section */ + uint16_t o_sntoc; /* section number of TOC */ + uint16_t o_snloader; /* section number of .loader section */ + uint16_t o_snbss; /* section number of .bss section */ + uint16_t o_algntext; /* .text alignment */ + uint16_t o_algndata; /* .data alignment */ + uint16_t o_modtype; /* module type (??) */ + uint16_t o_cputype; /* cpu type */ + uint32_t o_maxstack; /* max stack size (??) */ + uint32_t o_maxdata; /* max data size (??) */ + char o_resv2[12]; /* reserved */ +} COFF_aouthdr_t; + +#define AOUT_MAGIC 0x010b + +typedef struct COFF_scnhdr_t { + char s_name[8]; /* section name */ + uint32_t s_paddr; /* physical address, aliased s_nlib */ + uint32_t s_vaddr; /* virtual address */ + uint32_t s_size; /* section size */ + uint32_t s_scnptr; /* file ptr to raw data for section */ + uint32_t s_relptr; /* file ptr to relocation */ + uint32_t s_lnnoptr; /* file ptr to line numbers */ + uint16_t s_nreloc; /* number of relocation entries */ + uint16_t s_nlnno; /* number of line number entries */ + uint32_t s_flags; /* flags */ +} COFF_scnhdr_t; + +#endif /* XCOFF_H */ diff --git a/qemu/roms/openbios/include/arch/ia64/elf.h b/qemu/roms/openbios/include/arch/ia64/elf.h new file mode 100644 index 000000000..782ddc727 --- /dev/null +++ b/qemu/roms/openbios/include/arch/ia64/elf.h @@ -0,0 +1,5 @@ +#define ARCH_ELF_CLASS ELFCLASS64 +#define ARCH_ELF_DATA ELFDATA2LSB +#define ARCH_ELF_MACHINE_OK(x) ((x)==EM_IA64) +typedef Elf64_Ehdr Elf_ehdr; +typedef Elf64_Phdr Elf_phdr; diff --git a/qemu/roms/openbios/include/arch/ia64/io.h b/qemu/roms/openbios/include/arch/ia64/io.h new file mode 100644 index 000000000..8f06dcdaf --- /dev/null +++ b/qemu/roms/openbios/include/arch/ia64/io.h @@ -0,0 +1,59 @@ +#ifndef _ASM_IO_H +#define _ASM_IO_H + +extern unsigned long virt_offset; + +#define phys_to_virt(phys) ((void *) ((unsigned long) (phys) - virt_offset)) +#define virt_to_phys(virt) ((unsigned long) (virt) + virt_offset) + +#define __SLOW_DOWN_IO "outb %%al,$0x80;" +static inline void slow_down_io(void) +{ + __asm__ __volatile__( + __SLOW_DOWN_IO +#ifdef REALLY_SLOW_IO + __SLOW_DOWN_IO __SLOW_DOWN_IO __SLOW_DOWN_IO +#endif + : : ); +} + +#define BUILDIO(bwl,bw,type) \ +static inline void out##bwl(unsigned type value, int port) { \ + __asm__ __volatile__("out" #bwl " %" #bw "0, %w1" : : "a"(value), "Nd"(port)); \ +} \ +static inline unsigned type in##bwl(int port) { \ + unsigned type value; \ + __asm__ __volatile__("in" #bwl " %w1, %" #bw "0" : "=a"(value) : "Nd"(port)); \ + return value; \ +} \ +static inline void out##bwl##_p(unsigned type value, int port) { \ + out##bwl(value, port); \ + slow_down_io(); \ +} \ +static inline unsigned type in##bwl##_p(int port) { \ + unsigned type value = in##bwl(port); \ + slow_down_io(); \ + return value; \ +} \ +static inline void outs##bwl(int port, const void *addr, unsigned long count) { \ + __asm__ __volatile__("rep; outs" #bwl : "+S"(addr), "+c"(count) : "d"(port)); \ +} \ +static inline void ins##bwl(int port, void *addr, unsigned long count) { \ + __asm__ __volatile__("rep; ins" #bwl : "+D"(addr), "+c"(count) : "d"(port)); \ +} + +#ifndef BOOTSTRAP +BUILDIO(b,b,char) +BUILDIO(w,w,short) +BUILDIO(l,,int) +#else +extern u8 inb( u32 reg ); +extern u16 inw( u32 reg ); +extern u32 inl( u32 reg ); +extern void insw( u32 reg, void *addr, unsigned long count ); +extern void outb( u32 reg, u8 val ); +extern void outw( u32 reg, u16 val ); +extern void outl( u32 reg, u32 val ); +extern void outsw( u32 reg, const void *addr, unsigned long count); +#endif +#endif diff --git a/qemu/roms/openbios/include/arch/ia64/types.h b/qemu/roms/openbios/include/arch/ia64/types.h new file mode 100644 index 000000000..cb09cda5b --- /dev/null +++ b/qemu/roms/openbios/include/arch/ia64/types.h @@ -0,0 +1,60 @@ +/* tag: data types for forth engine + * + * This file is autogenerated by types.sh. Do not edit! + * + * Copyright (C) 2003 Patrick Mauritz, Stefan Reinauer + * + * See the file "COPYING" for further information about + * the copyright and warranty status of this work. + */ + +#ifndef __TYPES_H +#define __TYPES_H + +#include <inttypes.h> + +/* endianess */ + +#include <endian.h> + +/* physical address */ + +typedef uint64_t phys_addr_t; + +#define FMT_plx "%016" PRIx64 + +/* cell based types */ + +typedef int64_t cell; +typedef uint64_t ucell; +typedef __int128_t dcell; +typedef __uint128_t ducell; + +typedef int64_t prom_arg_t; +typedef uint64_t prom_uarg_t; + +#define PRIdPROMARG PRId64 +#define PRIuPROMARG PRIu64 +#define PRIxPROMARG PRIx64 +#define FMT_prom_arg "%" PRIdPROMARG +#define FMT_prom_uarg "%" PRIuPROMARG +#define FMT_prom_uargx "%016" PRIxPROMARG + +#define bitspercell (sizeof(cell)<<3) +#define bitsperdcell (sizeof(dcell)<<3) + +#define BITS 64 + +/* size named types */ + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned int u32; +typedef unsigned long u64; + +typedef char s8; +typedef short s16; +typedef int s32; +typedef long s64; + +#endif diff --git a/qemu/roms/openbios/include/arch/ppc/asmdefs.h b/qemu/roms/openbios/include/arch/ppc/asmdefs.h new file mode 100644 index 000000000..3b3cad434 --- /dev/null +++ b/qemu/roms/openbios/include/arch/ppc/asmdefs.h @@ -0,0 +1,151 @@ +/* -*- asm -*- + * + * Creation Date: <2001/02/03 19:38:07 samuel> + * Time-stamp: <2003/07/08 18:55:50 samuel> + * + * <asmdefs.h> + * + * Common assembly definitions + * + * Copyright (C) 2001, 2002, 2003 Samuel Rydh (samuel@ibrium.se) + * + * 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 + * + */ + +#ifndef _H_ASMDEFS +#define _H_ASMDEFS + +/************************************************************************/ +/* High/low halfword compatibility macros */ +/************************************************************************/ + +#ifndef __darwin__ +#define ha16( v ) (v)##@ha +#define hi16( v ) (v)##@h +#define lo16( v ) (v)##@l +#endif +#define HA(v) ha16(v) +#define HI(v) hi16(v) +#define LO(v) lo16(v) + +/* from Linux: include/asm-powerpc/ppc_asm.h */ +/* + * Copyright (C) 1995-1999 Gary Thomas, Paul Mackerras, Cort Dougan. + */ + +/* General Purpose Registers (GPRs) */ + +#define r0 0 +#define r1 1 +#define r2 2 +#define r3 3 +#define r4 4 +#define r5 5 +#define r6 6 +#define r7 7 +#define r8 8 +#define r9 9 +#define r10 10 +#define r11 11 +#define r12 12 +#define r13 13 +#define r14 14 +#define r15 15 +#define r16 16 +#define r17 17 +#define r18 18 +#define r19 19 +#define r20 20 +#define r21 21 +#define r22 22 +#define r23 23 +#define r24 24 +#define r25 25 +#define r26 26 +#define r27 27 +#define r28 28 +#define r29 29 +#define r30 30 +#define r31 31 + +/************************************************************************/ +/* MISC */ +/************************************************************************/ + +#ifdef __powerpc64__ + +#define LOAD_REG_IMMEDIATE(D, x) \ + lis (D), (x)@highest ; \ + ori (D), (D), (x)@higher ; \ + sldi (D), (D), 32 ; \ + oris (D), (D), (x)@h ; \ + ori (D), (D), (x)@l + +#define LOAD_REG_FUNC(D, x) \ + LOAD_REG_IMMEDIATE((D), (x)) ; \ + ld (D), 0(D) + +#else + +#define LOAD_REG_IMMEDIATE(D, x) \ + lis (D), HA(x) ; \ + addi (D), (D), LO(x) + +#define LOAD_REG_FUNC(D, x) \ + LOAD_REG_IMMEDIATE((D), (x)) + +#endif + +#ifdef __powerpc64__ +#define PPC_LL ld +#define PPC_STL std +#define PPC_STLU stdu +#define RFI rfid +#define MTMSRD(r) mtmsrd r +#define DATA_LONG(x) .quad x +#define BRANCH_LABEL(name) . ## name +#define PPC_LR_STKOFF 16 +#else +#define PPC_LL lwz +#define PPC_STL stw +#define PPC_STLU stwu +#define RFI rfi +#define MTMSRD(r) mtmsr r +#define DATA_LONG(x) .long x +#define BRANCH_LABEL(name) name +#define PPC_LR_STKOFF 4 +#endif + +#ifndef __darwin__ +#define GLOBL( name ) .globl name ; name +#define EXTERN( name ) name +#else +/* an underscore is needed on Darwin */ +#define GLOBL( name ) .globl _##name ; name: ; _##name +#define EXTERN( name ) _##name +#endif + +#if defined(__powerpc64__) && !defined(__darwin__) +#define _GLOBAL(name) \ + .align 2 ; \ + .section ".opd", "aw" ; \ + .globl name ; \ + .globl .##name ; \ + name: \ + .quad .##name ; \ + .quad .TOC.@tocbase ; \ + .quad 0 ; \ + .previous ; \ + .type .##name, @function ; \ + .##name +#else +#define _GLOBAL(name) \ + GLOBL(name) +#endif + +#define BIT(n) (1<<(31-(n))) + +#endif /* _H_ASMDEFS */ diff --git a/qemu/roms/openbios/include/arch/ppc/elf.h b/qemu/roms/openbios/include/arch/ppc/elf.h new file mode 100644 index 000000000..fd2a3f9eb --- /dev/null +++ b/qemu/roms/openbios/include/arch/ppc/elf.h @@ -0,0 +1,5 @@ +#define ARCH_ELF_CLASS ELFCLASS32 +#define ARCH_ELF_DATA ELFDATA2MSB +#define ARCH_ELF_MACHINE_OK(x) ((x)==EM_PPC) +typedef Elf32_Ehdr Elf_ehdr; +typedef Elf32_Phdr Elf_phdr; diff --git a/qemu/roms/openbios/include/arch/ppc/io.h b/qemu/roms/openbios/include/arch/ppc/io.h new file mode 100644 index 000000000..3449c5bf0 --- /dev/null +++ b/qemu/roms/openbios/include/arch/ppc/io.h @@ -0,0 +1,208 @@ +#ifndef _ASM_IO_H +#define _ASM_IO_H + +#include "asm/types.h" + +#define NO_QEMU_PROTOS +#include "arch/common/fw_cfg.h" + +extern char _start, _end; +extern unsigned long virt_offset; + +#define phys_to_virt(phys) ((void *) ((unsigned long) (phys) - virt_offset)) +#define virt_to_phys(virt) ((unsigned long) (virt) + virt_offset) + +#ifndef BOOTSTRAP + +extern unsigned long isa_io_base; + +/* + * 8, 16 and 32 bit, big and little endian I/O operations, with barrier. + */ +static inline uint8_t in_8(volatile uint8_t *addr) +{ + uint8_t ret; + + __asm__ __volatile__("lbz%U1%X1 %0,%1; eieio":"=r"(ret):"m"(*addr)); + return ret; +} + +static inline void out_8(volatile uint8_t *addr, uint8_t val) +{ + __asm__ __volatile__("stb%U0%X0 %1,%0; eieio":"=m"(*addr):"r"(val)); +} + +static inline uint16_t in_le16(volatile uint16_t *addr) +{ + uint16_t ret; + + __asm__ __volatile__("lhbrx %0,0,%1; eieio":"=r"(ret): + "r"(addr), "m"(*addr)); + return ret; +} + +static inline uint16_t in_be16(volatile uint16_t *addr) +{ + uint16_t ret; + + __asm__ __volatile__("lhz%U1%X1 %0,%1; eieio":"=r"(ret):"m"(*addr)); + return ret; +} + +static inline void out_le16(volatile uint16_t *addr, uint16_t val) +{ + __asm__ __volatile__("sthbrx %1,0,%2; eieio":"=m"(*addr):"r"(val), + "r"(addr)); +} + +static inline void out_be16(volatile uint16_t *addr, uint16_t val) +{ + __asm__ __volatile__("sth%U0%X0 %1,%0; eieio":"=m"(*addr):"r"(val)); +} + +static inline uint32_t in_le32(volatile uint32_t *addr) +{ + uint32_t ret; + + __asm__ __volatile__("lwbrx %0,0,%1; eieio":"=r"(ret): + "r"(addr), "m"(*addr)); + return ret; +} + +static inline uint32_t in_be32(volatile uint32_t *addr) +{ + uint32_t ret; + + __asm__ __volatile__("lwz%U1%X1 %0,%1; eieio":"=r"(ret):"m"(*addr)); + return ret; +} + +static inline void out_le32(volatile uint32_t *addr, uint32_t val) +{ + __asm__ __volatile__("stwbrx %1,0,%2; eieio":"=m"(*addr):"r"(val), + "r"(addr)); +} + +static inline void out_be32(volatile unsigned *addr, uint32_t val) +{ + __asm__ __volatile__("stw%U0%X0 %1,%0; eieio":"=m"(*addr):"r"(val)); +} + +static inline void _insw_ns(volatile uint16_t * port, void *buf, int ns) +{ + uint16_t *b = (uint16_t *) buf; + + while (ns > 0) { + *b++ = in_le16(port); + ns--; + } +} + +static inline void _outsw_ns(volatile uint16_t * port, const void *buf, + int ns) +{ + uint16_t *b = (uint16_t *) buf; + + while (ns > 0) { + out_le16(port, *b++); + ns--; + } +} + +static inline void _insw(volatile uint16_t * port, void *buf, int ns) +{ + uint16_t *b = (uint16_t *) buf; + + while (ns > 0) { + *b++ = in_be16(port); + ns--; + } +} + +static inline void _outsw(volatile uint16_t * port, const void *buf, + int ns) +{ + uint16_t *b = (uint16_t *) buf; + + while (ns > 0) { + out_be16(port, *b++); + ns--; + } +} + + +/* + * The insw/outsw/insl/outsl functions don't do byte-swapping. + * They are only used in practice for transferring buffers which + * are arrays of bytes, and byte-swapping is not appropriate in + * that case. - paulus + */ + +static inline void insw(uint16_t port, void *buf, int ns) +{ + _insw((uint16_t *)(port + isa_io_base), buf, ns); +} + +static inline void outsw(uint16_t port, void *buf, int ns) +{ + _outsw((uint16_t *)(port + isa_io_base), buf, ns); +} + + +static inline uint8_t inb(uint16_t port) +{ + return in_8((uint8_t *)(port + isa_io_base)); +} + +static inline void outb(uint8_t val, uint16_t port) +{ + out_8((uint8_t *)(port + isa_io_base), val); +} + +static inline uint16_t inw(uint16_t port) +{ + return in_le16((uint16_t *)(port + isa_io_base)); +} + +static inline void outw(uint16_t val, uint16_t port) +{ + out_le16((uint16_t *)(port + isa_io_base), val); +} + +static inline uint32_t inl(uint16_t port) +{ + return in_le32((uint32_t *)(port + isa_io_base)); +} + +static inline void outl(uint32_t val, uint16_t port) +{ + out_le32((uint32_t *)(port + isa_io_base), val); +} + +#else /* BOOTSTRAP */ +#ifdef FCOMPILER +#define inb(reg) ((u8)0xff) +#define inw(reg) ((u16)0xffff) +#define inl(reg) ((u32)0xffffffff) +#define outb(reg, val) do{} while(0) +#define outw(reg, val) do{} while(0) +#define outl(reg, val) do{} while(0) +#else +extern u8 inb(u32 reg); +extern u16 inw(u32 reg); +extern u32 inl(u32 reg); +extern void insw(u32 reg, void *addr, unsigned long count); +extern void outb(u32 reg, u8 val); +extern void outw(u32 reg, u16 val); +extern void outl(u32 reg, u32 val); +extern void outsw(u32 reg, const void *addr, unsigned long count); +#endif +#endif + +#if defined(CONFIG_QEMU) +#define FW_CFG_ARCH_WIDTH (FW_CFG_ARCH_LOCAL + 0x00) +#define FW_CFG_ARCH_HEIGHT (FW_CFG_ARCH_LOCAL + 0x01) +#define FW_CFG_ARCH_DEPTH (FW_CFG_ARCH_LOCAL + 0x02) +#endif + +#endif /* _ASM_IO_H */ diff --git a/qemu/roms/openbios/include/arch/ppc/pci.h b/qemu/roms/openbios/include/arch/ppc/pci.h new file mode 100644 index 000000000..d96bd7ee4 --- /dev/null +++ b/qemu/roms/openbios/include/arch/ppc/pci.h @@ -0,0 +1,69 @@ +#ifndef PPC_PCI_H +#define PPC_PCI_H + +#include "asm/io.h" + +#if !(defined(PCI_CONFIG_1) || defined(PCI_CONFIG_2)) +#define PCI_CONFIG_1 1 /* default */ +#endif + +#ifdef PCI_CONFIG_1 + +/* PCI Configuration Mechanism #1 */ + +#define PCI_ADDR(bus, dev, fn) \ + ((pci_addr) (0x80000000u \ + | (uint32_t) (bus) << 16 \ + | (uint32_t) (dev) << 11 \ + | (uint32_t) (fn) << 8)) + +#define PCI_BUS(pcidev) ((uint8_t) ((pcidev) >> 16)) +#define PCI_DEV(pcidev) ((uint8_t) ((pcidev) >> 11) & 0x1f) +#define PCI_FN(pcidev) ((uint8_t) ((pcidev) >> 8) & 7) + +static inline uint8_t pci_config_read8(pci_addr dev, uint8_t reg) +{ + uint8_t res; + out_le32((unsigned *)arch->cfg_addr, dev | (reg & ~3)); + res = in_8((unsigned char*)(arch->cfg_data + (reg & 3))); + return res; +} + +static inline uint16_t pci_config_read16(pci_addr dev, uint8_t reg) +{ + uint16_t res; + out_le32((unsigned *)arch->cfg_addr, dev | (reg & ~3)); + res = in_le16((unsigned short*)(arch->cfg_data + (reg & 2))); + return res; +} + +static inline uint32_t pci_config_read32(pci_addr dev, uint8_t reg) +{ + uint32_t res; + out_le32((unsigned *)arch->cfg_addr, dev | reg); + res = in_le32((unsigned *)(arch->cfg_data)); + return res; +} + +static inline void pci_config_write8(pci_addr dev, uint8_t reg, uint8_t val) +{ + out_le32((unsigned *)arch->cfg_addr, dev | (reg & ~3)); + out_8((unsigned char*)(arch->cfg_data + (reg & 3)), val); +} + +static inline void pci_config_write16(pci_addr dev, uint8_t reg, uint16_t val) +{ + out_le32((unsigned *)arch->cfg_addr, dev | (reg & ~3)); + out_le16((unsigned short *)(arch->cfg_data + (reg & 2)), val); +} + +static inline void pci_config_write32(pci_addr dev, uint8_t reg, uint32_t val) +{ + out_le32((unsigned *)arch->cfg_addr, dev | reg); + out_le32((unsigned *)(arch->cfg_data), val); +} +#else /* !PCI_CONFIG_1 */ +#error PCI Configuration Mechanism is not specified or implemented +#endif + +#endif /* PPC_PCI_H */ diff --git a/qemu/roms/openbios/include/arch/ppc/processor.h b/qemu/roms/openbios/include/arch/ppc/processor.h new file mode 100644 index 000000000..bb03bb164 --- /dev/null +++ b/qemu/roms/openbios/include/arch/ppc/processor.h @@ -0,0 +1,467 @@ +/* + * Creation Date: <2000/10/29 01:43:29 samuel> + * Time-stamp: <2003/07/27 22:37:49 samuel> + * + * <processor.h> + * + * Extract from <asm/processor.h> + * + * + * 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 + * + */ + +#ifndef _H_PROCESSOR +#define _H_PROCESSOR + + +#define PTE0_VSID(s) (((s)>>7) & 0xffffff) +#define PTE0_V BIT(0) +#define PTE0_H BIT(25) +#define PTE0_API 0x3f + +#define PTE1_R BIT(23) +#define PTE1_C BIT(24) +#define PTE1_W BIT(25) +#define PTE1_I BIT(26) +#define PTE1_M BIT(27) +#define PTE1_G BIT(28) +#define PTE1_WIMG (PTE1_W | PTE1_I | PTE1_M | PTE1_G) +#define PTE1_PP 0x3 +#define PTE1_RPN (~0xfffUL) + +#define VSID_Ks BIT(1) +#define VSID_Kp BIT(2) +#define VSID_N BIT(3) + + + +#ifndef MSR_VEC + +#define MSR_SF (1 << 63) /* Sixty-Four Bit Mode */ + +#define MSR_VEC (1<<25) /* 6: Enable AltiVec */ +#define MSR_POW (1<<18) /* 13: Enable Power Management */ +#define MSR_TGPR (1<<17) /* 14: TLB Update registers in use */ +#define MSR_ILE (1<<16) /* 15: Interrupt Little Endian */ +#define MSR_EE (1<<15) /* 16: External Interrupt Enable */ +#define MSR_PR (1<<14) /* 17: Privilege Level */ +#define MSR_FP (1<<13) /* 18: Floating Point enable */ +#define MSR_ME (1<<12) /* 19: Machine Check Enable */ +#define MSR_FE0 (1<<11) /* 20: Floating Exception mode 0 */ +#define MSR_SE (1<<10) /* 21: Single Step */ +#define MSR_BE (1<<9) /* 22: Branch Trace */ +#define MSR_FE1 (1<<8) /* 23: Floating Exception mode 1 */ +#define MSR_IP (1<<6) /* 25: Exception prefix 0x000/0xFFF */ +#define MSR_IR (1<<5) /* 26: Instruction Relocate */ +#define MSR_DR (1<<4) /* 27: Data Relocate */ +#define MSR_PE (1<<2) /* 29: Performance Monitor Flag */ +#define MSR_RI (1<<1) /* 30: Recoverable Exception */ +#define MSR_LE (1<<0) /* 31: Little Endian */ + +#endif /* MSR_VEC */ + +#ifndef S_SPRG0 + +#define NUM_SPRS 1024 +//#define S_XER 1 +#define S_RTCU_R 4 /* 601 RTC Upper/Lower (Reading) */ +#define S_RTCL_R 5 +//#define S_LR 8 +//#define S_CTR 9 +#define S_DSISR 18 /* Source Instruction Service Register */ +#define S_DAR 19 /* Data Address Register */ +#define S_RTCU_W 20 /* 601 RTC Upper/Lower (Writing) */ +#define S_RTCL_W 21 +#define S_DEC 22 /* Decrementer Register */ +#define S_SDR1 25 /* Table Search Description Register */ +#define S_SRR0 26 /* Save and Restore Register 0 */ +#define S_SRR1 27 /* Save and Restore Register 1 */ +#define S_VRSAVE 256 /* (AltiVec) Vector Register Save Register */ +#define S_TBRL 268 /* Time base Upper/Lower (Reading) */ +#define S_TBRU 269 +#define S_SPRG0 272 /* SPR General 0-3 */ +#define S_SPRG1 273 +#define S_SPRG2 274 +#define S_SPRG3 275 +#define S_SPRG4 276 /* SPR General 4-7 (7445/7455) */ +#define S_SPRG5 277 +#define S_SPRG6 278 +#define S_SPRG7 279 +#define S_EAR 282 /* External Access Register */ +#define S_TBWL 284 /* Time base Upper/Lower (Writing) */ +#define S_TBWU 285 +#define S_PVR 287 /* Processor Version Register */ +#define S_HIOR 311 /* Hardware Interrupt Offset Register */ +#define S_IBAT0U 528 +#define S_IBAT0L 529 +#define S_IBAT1U 530 +#define S_IBAT1L 531 +#define S_IBAT2U 532 +#define S_IBAT2L 533 +#define S_IBAT3U 534 +#define S_IBAT3L 535 +#define S_DBAT0U 536 +#define S_DBAT0L 537 +#define S_DBAT1U 538 +#define S_DBAT1L 539 +#define S_DBAT2U 540 +#define S_DBAT2L 541 +#define S_DBAT3U 542 +#define S_DBAT3L 543 +#define S_UMMCR2 928 +#define S_UPMC5 929 /* User Performance Monitor Counter Register */ +#define S_UPMC6 930 +#define S_UBAMR 935 +#define S_UMMCR0 936 /* User Monitor Mode Control Register */ +#define S_UPMC1 937 +#define S_UPMC2 938 +#define S_USIAR 939 /* User Sampled Instruction Address Register */ +#define S_UMMCR1 940 +#define S_UPMC3 941 +#define S_UPMC4 942 /* User Performance Monitor Counter Register 4 */ +#define S_USDAR 943 /* User Sampled Data Address Register */ +#define S_MMCR2 944 /* Monitor Mode Control Register */ +#define S_PMC5 945 +#define S_PMC6 946 +#define S_BAMR 951 /* Breakpoint Address Mask Register (74xx) */ +#define S_MMCR0 952 /* Monitor Mode Control Register 0 */ +#define S_PMC1 953 /* Performance Counter Register */ +#define S_PMC2 954 +#define S_SIAR 955 /* Sampled Instruction Address Register */ +#define S_MMCR1 956 +#define S_PMC3 957 +#define S_PMC4 958 +#define S_SDAR 959 /* Sampled Data Address Register */ +#define S_DMISS 976 /* 603 */ +#define S_DCMP 977 /* 603 */ +#define S_HASH1 978 /* 603 */ +#define S_HASH2 979 /* 603 */ +#define S_IMISS 980 /* 603 */ +#define S_TLBMISS 980 /* 7445/7455 */ +#define S_ICMP 981 /* 603 */ +#define S_PTEHI 981 /* 7445/7455 */ +#define S_RPA 982 /* 603 */ +#define S_PTELO 982 /* 7445/7455 */ +#define S_L3PM 983 /* L3 Private Memory Address Control Register */ +#define S_L3ITCR0 984 /* ??? */ +#define S_L3OHCR 1000 /* ??? */ +#define S_L3ITCR1 1001 /* ??? */ +#define S_L3ITCR2 1002 /* ??? */ +#define S_L3ITCR3 1003 /* ??? */ +#define S_HID0 1008 /* Hardware Implementation Registers */ +#define S_HID1 1009 +#define S_HID2 1010 +#define S_IABR S_HID2 /* HID2 - Instruction Address Breakpoint Register */ +#define S_ICTRL 1011 /* HID3 - Instruction Cache & Interrupt control reg */ +#define S_HID4 1012 /* HID4 - Instruction Address Compare 1 (?) */ +#define S_HID5 1013 +#define S_DABR S_HID5 /* HID5 - Data Address Breakpoint */ +#define S_MSSCR0 1014 /* HID6 - Memory Subsystem Control Register 0 */ +#define S_MSSCR1 1015 /* HID7 - Memory Subsystem Control Register 1 */ +#define S_LDSTCR 1016 /* HID8 - Load/Store Control Register */ +#define S_L2CR 1017 /* HID9 - Level 2 Cache Control Regsiter */ +#define S_L3CR 1018 /* HID10 - Level 3 Cache Control Regsiter (7450) */ +#define S_HID11 1019 +#define S_ICTC S_HID11 /* HID11 - Instruction Cache Throttling Control Reg */ +#define S_ICCR S_HID11 /* Instruction Cache Cacheability Reigster */ +#define S_THRM1 1020 /* HID12 - Thermal Management Register 1 */ +#define S_THRM2 1021 /* HID13 - Thermal Management Register 2 */ +#define S_THRM3 1022 /* HID14 - Thermal Management Register 3 */ +#define S_HID15 1023 +#define S_PIR S_HID15 /* HID15 - Processor Identification Register */ + +#endif /* S_SPRG0 */ + +/* the kernel might define these too... */ +#if !defined(__KERNEL__) || defined(__ASSEMBLY__) + +/* Floating Point Status and Control Register (FPSCR) Fields */ +#define FPSCR_FX 0x80000000 /* FPU exception summary */ +#define FPSCR_FEX 0x40000000 /* FPU enabled exception summary */ +#define FPSCR_VX 0x20000000 /* Invalid operation summary */ +#define FPSCR_OX 0x10000000 /* Overflow exception summary */ +#define FPSCR_UX 0x08000000 /* Underflow exception summary */ +#define FPSCR_ZX 0x04000000 /* Zero-devide exception summary */ +#define FPSCR_XX 0x02000000 /* Inexact exception summary */ +#define FPSCR_VXSNAN 0x01000000 /* Invalid op for SNaN */ +#define FPSCR_VXISI 0x00800000 /* Invalid op for Inv - Inv */ +#define FPSCR_VXIDI 0x00400000 /* Invalid op for Inv / Inv */ +#define FPSCR_VXZDZ 0x00200000 /* Invalid op for Zero / Zero */ +#define FPSCR_VXIMZ 0x00100000 /* Invalid op for Inv * Zero */ +#define FPSCR_VXVC 0x00080000 /* Invalid op for Compare */ +#define FPSCR_FR 0x00040000 /* Fraction rounded */ +#define FPSCR_FI 0x00020000 /* Fraction inexact */ +#define FPSCR_FPRF 0x0001f000 /* FPU Result Flags */ +#define FPSCR_FPCC 0x0000f000 /* FPU Condition Codes */ +#define FPSCR_VXSOFT 0x00000400 /* Invalid op for software request */ +#define FPSCR_VXSQRT 0x00000200 /* Invalid op for square root */ +#define FPSCR_VXCVI 0x00000100 /* Invalid op for integer convert */ +#define FPSCR_VE 0x00000080 /* Invalid op exception enable */ +#define FPSCR_OE 0x00000040 /* IEEE overflow exception enable */ +#define FPSCR_UE 0x00000020 /* IEEE underflow exception enable */ +#define FPSCR_ZE 0x00000010 /* IEEE zero divide exception enable */ +#define FPSCR_XE 0x00000008 /* FP inexact exception enable */ +#define FPSCR_NI 0x00000004 /* FPU non IEEE-Mode */ +#define FPSCR_RN 0x00000003 /* FPU rounding control */ + +/* SPR_HID0 */ +#define HID0_EMCP (1<<31) /* Enable Machine Check pin */ +#define HID0_EBA (1<<29) /* Enable Bus Address Parity */ +#define HID0_EBD (1<<28) /* Enable Bus Data Parity */ +#define HID0_SBCLK (1<<27) +#define HID0_EICE (1<<26) +#define HID0_ECLK (1<<25) +#define HID0_PAR (1<<24) +#define HID0_DOZE (1<<23) +#define HID0_NAP (1<<22) +#define HID0_SLEEP (1<<21) +#define HID0_DPM (1<<20) +#define HID0_NHR (1<<16) /* Not Hard Reset */ +#define HID0_ICE (1<<15) /* Instruction Cache Enable */ +#define HID0_DCE (1<<14) /* Data Cache Enable */ +#define HID0_ILOCK (1<<13) /* Instruction Cache Lock */ +#define HID0_DLOCK (1<<12) /* Data Cache Lock */ +#define HID0_ICFI (1<<11) /* Instr. Cache Flash Invalidate */ +#define HID0_DCFI (1<<10) /* Data Cache Flash Invalidate */ +#define HID0_SPD (1<<9) /* Speculative disable */ +#define HID0_SGE (1<<7) /* Store Gathering Enable */ +#define HID0_SIED (1<<7) /* Serial Instr. Execution [Disable] */ +#define HID0_BTIC (1<<5) /* Branch Target Instruction Cache Enable */ +#define HID0_ABE (1<<3) /* Address Broadcast Enable */ +#define HID0_BHT (1<<2) /* Branch History Table Enable */ +#define HID0_BTCD (1<<1) /* Branch target cache disable */ + +#define L2CR_L2E BIT(0) /* L2 enable */ +#define L2CR_L2PE BIT(1) /* L2 data parity generation and checking */ +#define L2CR_L2SIZ_512K BIT(2) +#define L2CR_L2SIZ_256K BIT(3) +#define L2CR_L2SIZ_1MB (BIT(2)|BIT(3)) +#define L2CR_L2CLK_1 BIT(6) /* L2 clock ration */ +#define L2CR_L2CLK_15 (BIT(6)*2) +#define L2CR_L2CLK_2 (BIT(6)*4) +#define L2CR_L2CLK_25 (BIT(6)*5) +#define L2CR_L2CLK_3 (BIT(6)*6) +#define L2CR_L2RAM_FT 0 /* flow-through (reg-buf) synchronous SRAM */ +#define L2CR_L2RAM_PB BIT(7) /* Piplined (reg-reg) synchronous burst SRAM */ +#define L2CR_L2RAM_PLW (BIT(7)|BIT(8)) /* Piplined (reg-reg) synchronous late-write */ +#define L2CR_L2DO BIT(9) /* L2 data-only */ +#define L2CR_L2I BIT(10) /* L2 global invalidate */ +#define L2CR_L2CTL BIT(11) /* L2 RAM control (ZZ enable, low-power mode) */ +#define L2CR_L2WT BIT(12) /* L2 write-through */ +#define L2CR_L2TS BIT(13) /* L2 test support */ +#define L2CR_L2OH_05 0 /* L2 output hold 0.5 nS */ +#define L2CR_L2OH_10 BIT(15) /* L2 output hold 1.0 nS */ +#define L2CR_L2SL BIT(16) /* L2 DLL slow (use if bus freq < 150 MHz) */ +#define L2CR_L2DF BIT(17) /* L2 differential clock */ +#define L2CR_L2BYP BIT(18) /* L2 DLL bypass */ +#define L2CR_L2IP BIT(31) /* L2 global invalidate in progress */ + +/* SPR_THRM1 */ +#define THRM1_TIN (1 << 31) +#define THRM1_TIV (1 << 30) +#define THRM1_THRES(x) ((x&0x7f)<<23) +#define THRM3_SITV(x) ((x&0x3fff)<<1) +#define THRM1_TID (1<<2) +#define THRM1_TIE (1<<1) +#define THRM1_V (1<<0) + +/* SPR_THRM3 */ +#define THRM3_E (1<<0) + +/* Processor Version Numbers */ + +#define PVR_VER(pvr) (((pvr) >> 16) & 0xFFFF) /* Version field */ +#define PVR_REV(pvr) (((pvr) >> 0) & 0xFFFF) /* Revison field */ + +#define PVR_403GA 0x00200000 +#define PVR_403GB 0x00200100 +#define PVR_403GC 0x00200200 +#define PVR_403GCX 0x00201400 +#define PVR_405GP 0x40110000 +#define PVR_601 0x00010000 +#define PVR_602 0x00050000 +#define PVR_603 0x00030000 +#define PVR_603e 0x00060000 +#define PVR_603ev 0x00070000 +#define PVR_603r 0x00071000 +#define PVR_604 0x00040000 +#define PVR_604e 0x00090000 +#define PVR_604r 0x000A0000 +#define PVR_620 0x00140000 +#define PVR_740 0x00080000 +#define PVR_750 PVR_740 +#define PVR_740P 0x10080000 +#define PVR_750P PVR_740P +#define PVR_821 0x00500000 +#define PVR_823 PVR_821 +#define PVR_850 PVR_821 +#define PVR_860 PVR_821 +#define PVR_7400 0x000C0000 +#define PVR_8240 0x00810100 +#define PVR_8260 PVR_8240 + +/* Vector VSCR register */ +#define VSCR_NJ 0x10000 +#define VSCR_SAT 0x1 + +#endif /* __KERNEL__ */ + + +#ifdef __ASSEMBLY__ + +#define CTR S_CTR /* Counter Register */ +#define DAR S_DAR /* Data Address Register */ +#define DABR S_DABR /* Data Address Breakpoint Register */ +#define DBAT0L S_DBAT0L /* Data BAT 0 Lower Register */ +#define DBAT0U S_DBAT0U /* Data BAT 0 Upper Register */ +#define DBAT1L S_DBAT1L /* Data BAT 1 Lower Register */ +#define DBAT1U S_DBAT1U /* Data BAT 1 Upper Register */ +#define DBAT2L S_DBAT2L /* Data BAT 2 Lower Register */ +#define DBAT2U S_DBAT2U /* Data BAT 2 Upper Register */ +#define DBAT3L S_DBAT3L /* Data BAT 3 Lower Register */ +#define DBAT3U S_DBAT3U /* Data BAT 3 Upper Register */ +#define DCMP S_DCMP /* Data TLB Compare Register */ +#define DEC S_DEC /* Decrement Register */ +#define DMISS S_DMISS /* Data TLB Miss Register */ +#define DSISR S_DSISR /* Data Storage Interrupt Status Register */ +#define EAR S_EAR /* External Address Register */ +#define HASH1 S_HASH1 /* Primary Hash Address Register */ +#define HASH2 S_HASH2 /* Secondary Hash Address Register */ +#define HID0 S_HID0 /* Hardware Implementation Register 0 */ +#define HID1 S_HID1 /* Hardware Implementation Register 1 */ +#define IABR S_IABR /* Instruction Address Breakpoint Register */ +#define IBAT0L S_IBAT0L /* Instruction BAT 0 Lower Register */ +#define IBAT0U S_IBAT0U /* Instruction BAT 0 Upper Register */ +#define IBAT1L S_IBAT1L /* Instruction BAT 1 Lower Register */ +#define IBAT1U S_IBAT1U /* Instruction BAT 1 Upper Register */ +#define IBAT2L S_IBAT2L /* Instruction BAT 2 Lower Register */ +#define IBAT2U S_IBAT2U /* Instruction BAT 2 Upper Register */ +#define IBAT3L S_IBAT3L /* Instruction BAT 3 Lower Register */ +#define IBAT3U S_IBAT3U /* Instruction BAT 3 Upper Register */ +#define ICMP S_ICMP /* Instruction TLB Compare Register */ +#define IMISS S_IMISS /* Instruction TLB Miss Register */ +#define IMMR S_IMMR /* PPC 860/821 Internal Memory Map Register */ +#define L2CR S_L2CR /* PPC 750 L2 control register */ +#define PVR S_PVR /* Processor Version */ +#define RPA S_RPA /* Required Physical Address Register */ +#define SDR1 S_SDR1 /* MMU hash base register */ +#define SPR0 S_SPRG0 /* Supervisor Private Registers */ +#define SPR1 S_SPRG1 +#define SPR2 S_SPRG2 +#define SPR3 S_SPRG3 +#define SPRG0 S_SPRG0 +#define SPRG1 S_SPRG1 +#define SPRG2 S_SPRG2 +#define SPRG3 S_SPRG3 +#define SRR0 S_SRR0 /* Save and Restore Register 0 */ +#define SRR1 S_SRR1 /* Save and Restore Register 1 */ +#define TBRL S_STBRL /* Time Base Read Lower Register */ +#define TBRU S_TBRU /* Time Base Read Upper Register */ +#define TBWL S_TBWL /* Time Base Write Lower Register */ +#define TBWU S_TBWU /* Time Base Write Upper Register */ +#define ICTC S_ICTC +#define THRM1 S_THRM1 /* Thermal Management Register 1 */ +#define THRM2 S_THRM2 /* Thermal Management Register 2 */ +#define THRM3 S_THRM3 /* Thermal Management Register 3 */ +#define SIAR S_SIAR +#define SDAR S_SDAR +#define XER 1 + +#define SR0 0 /* Segment registers */ +#define SR1 1 +#define SR2 2 +#define SR3 3 +#define SR4 4 +#define SR5 5 +#define SR6 6 +#define SR7 7 +#define SR8 8 +#define SR9 9 +#define SR10 10 +#define SR11 11 +#define SR12 12 +#define SR13 13 +#define SR14 14 +#define SR15 15 + +#endif /* __ASSEMBLY__ */ + +/* opcode macros */ + +#define OPCODE_PRIM(n) ( ((unsigned long)(n)) >> 26 ) +#define OPCODE_EXT(n) ( (((unsigned long)(n)) >> 1) & 0x3ff ) +#define OPCODE(op,op_ext) ( ((op)<<10) + op_ext ) + +#define B1(n) ( (((unsigned long)(n)) >> 21) & 0x1f ) +#define B2(n) ( (((unsigned long)(n)) >> 16) & 0x1f ) +#define B3(n) ( (((unsigned long)(n)) >> 11) & 0x1f ) + +#define BD(n) ((unsigned long)((n) & 0x7fff) + (((n) & 0x8000) ? (unsigned long)0xffff8000 : 0)) + +#define SPRNUM_FLIP( v ) ( (((v)>>5) & 0x1f) | (((v)<<5) & 0x3e0) ) + +/* C helpers */ + +#ifndef __ASSEMBLER__ + +#define __stringify_1(x) #x +#define __stringify(x) __stringify_1(x) +#define mtspr(rn, v) asm volatile("mtspr " __stringify(rn) ",%0" : : "r" (v)) + +static inline unsigned long mfmsr(void) +{ + unsigned long msr; + asm volatile("mfmsr %0" : "=r" (msr)); + return msr; +} + +static inline void mtmsr(unsigned long msr) +{ +#ifdef __powerpc64__ + asm volatile("mtmsrd %0" :: "r" (msr)); +#else + asm volatile("mtmsr %0" :: "r" (msr)); +#endif +} + +#ifdef __powerpc64__ +#define SDR1_HTABORG_MASK 0x3FFFFFFFFFFC0000UL +#else +#define SDR1_HTABORG_MASK 0xffff0000 +#endif + +static inline unsigned long mfsdr1(void) +{ + unsigned long sdr1; + asm volatile("mfsdr1 %0" : "=r" (sdr1)); + return sdr1; +} + +static inline void mtsdr1(unsigned long sdr1) +{ + asm volatile("mtsdr1 %0" :: "r" (sdr1)); +} + +static inline unsigned int mfpvr(void) +{ + unsigned int pvr; + asm volatile("mfspr %0, 0x11f" : "=r" (pvr) ); + return pvr; +} + +static inline void slbia(void) +{ + asm volatile("slbia" ::: "memory"); +} + +static inline void slbmte(unsigned long rs, unsigned long rb) +{ + asm volatile("slbmte %0,%1 ; isync" :: "r" (rs), "r" (rb) : "memory"); +} + +#endif /* !__ASSEMBLER__ */ + +#endif /* _H_PROCESSOR */ diff --git a/qemu/roms/openbios/include/arch/ppc/types.h b/qemu/roms/openbios/include/arch/ppc/types.h new file mode 100644 index 000000000..69b3db405 --- /dev/null +++ b/qemu/roms/openbios/include/arch/ppc/types.h @@ -0,0 +1,104 @@ +/* tag: data types for forth engine + * + * Copyright (C) 2003-2005 Patrick Mauritz, Stefan Reinauer + * + * See the file "COPYING" for further information about + * the copyright and warranty status of this work. + */ + +#ifndef __TYPES_H +#define __TYPES_H + +#include "mconfig.h" + +#ifdef BOOTSTRAP +#include <inttypes.h> +#else +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned int uint32_t; +typedef unsigned long long uint64_t; +typedef unsigned long uintptr_t; + +typedef signed char int8_t; +typedef short int16_t; +typedef int int32_t; +typedef long long int64_t; +typedef long intptr_t; + +#define PRId32 "d" +#define PRIu32 "u" +#define PRIx32 "x" +#define PRIX32 "X" +#define PRId64 "lld" +#define PRIu64 "llu" +#define PRIx64 "llx" +#define PRIX64 "llX" +#endif + +/* endianess */ +#include "autoconf.h" + +/* physical address */ +#if defined(__powerpc64__) +typedef uint64_t phys_addr_t; +#define FMT_plx "%016" PRIx64 +#else +typedef uint32_t phys_addr_t; +#define FMT_plx "%08" PRIx32 +#endif + +/* cell based types */ + +typedef int32_t cell; +typedef uint32_t ucell; +typedef int64_t dcell; +typedef uint64_t ducell; + +#define FMT_cell "%" PRId32 +#define FMT_ucell "%" PRIu32 +#define FMT_ucellx "%08" PRIx32 +#define FMT_ucellX "%08" PRIX32 + +typedef int32_t prom_arg_t; +typedef uint32_t prom_uarg_t; + +#define PRIdPROMARG PRId32 +#define PRIuPROMARG PRIu32 +#define PRIxPROMARG PRIx32 +#define FMT_prom_arg "%" PRIdPROMARG +#define FMT_prom_uarg "%" PRIuPROMARG +#define FMT_prom_uargx "%08" PRIxPROMARG + +#define FMT_elf "%#x" +#define FMT_sizet "%lx" +#define FMT_aout_ehdr "%lx" + +#define bitspercell (sizeof(cell)<<3) +#define bitsperdcell (sizeof(dcell)<<3) + +#define BITS 32 + +#define PAGE_SHIFT 12 + +/* size named types */ + +typedef unsigned char u8; +typedef unsigned char __u8; +typedef unsigned short u16; +typedef unsigned short __u16; +typedef unsigned int u32; +typedef unsigned int __u32; +typedef unsigned long long u64; +typedef unsigned long long __u64; + +typedef signed char s8; +typedef signed char __s8; +typedef short s16; +typedef short __s16; +typedef int s32; +typedef int __s32; +typedef long long s64; +typedef long long __s64; + +#endif diff --git a/qemu/roms/openbios/include/arch/sparc32/a.out.h b/qemu/roms/openbios/include/arch/sparc32/a.out.h new file mode 100644 index 000000000..e4e83eb01 --- /dev/null +++ b/qemu/roms/openbios/include/arch/sparc32/a.out.h @@ -0,0 +1,98 @@ +/* $Id: a.out.h,v 1.13 2000/01/09 10:46:53 anton Exp $ */ +#ifndef __SPARC_A_OUT_H__ +#define __SPARC_A_OUT_H__ + +#define SPARC_PGSIZE 0x2000 /* Thanks to the sun4 architecture... */ +#define SEGMENT_SIZE SPARC_PGSIZE /* whee... */ + +struct exec { + unsigned char a_dynamic:1; /* A __DYNAMIC is in this image */ + unsigned char a_toolversion:7; + unsigned char a_machtype; + unsigned short a_info; + unsigned long a_text; /* length of text, in bytes */ + unsigned long a_data; /* length of data, in bytes */ + unsigned long a_bss; /* length of bss, in bytes */ + unsigned long a_syms; /* length of symbol table, in bytes */ + unsigned long a_entry; /* where program begins */ + unsigned long a_trsize; + unsigned long a_drsize; +}; + +/* Where in the file does the text information begin? */ +#define N_TXTOFF(x) (N_MAGIC(x) == ZMAGIC ? 0 : sizeof (struct exec)) + +/* Where do the Symbols start? */ +#define N_SYMOFF(x) (N_TXTOFF(x) + (x).a_text + \ + (x).a_data + (x).a_trsize + \ + (x).a_drsize) + +/* Where does text segment go in memory after being loaded? */ +#define N_TXTADDR(x) (((N_MAGIC(x) == ZMAGIC) && \ + ((x).a_entry < SPARC_PGSIZE)) ? \ + 0 : SPARC_PGSIZE) + +/* And same for the data segment.. */ +#define N_DATADDR(x) (N_MAGIC(x)==OMAGIC ? \ + (N_TXTADDR(x) + (x).a_text) \ + : (_N_SEGMENT_ROUND (_N_TXTENDADDR(x)))) + +#define N_TRSIZE(a) ((a).a_trsize) +#define N_DRSIZE(a) ((a).a_drsize) +#define N_SYMSIZE(a) ((a).a_syms) + +/* + * Sparc relocation types + */ +enum reloc_type +{ + RELOC_8, + RELOC_16, + RELOC_32, /* simplest relocs */ + RELOC_DISP8, + RELOC_DISP16, + RELOC_DISP32, /* Disp's (pc-rel) */ + RELOC_WDISP30, + RELOC_WDISP22, /* SR word disp's */ + RELOC_HI22, + RELOC_22, /* SR 22-bit relocs */ + RELOC_13, + RELOC_LO10, /* SR 13&10-bit relocs */ + RELOC_SFA_BASE, + RELOC_SFA_OFF13, /* SR S.F.A. relocs */ + RELOC_BASE10, + RELOC_BASE13, + RELOC_BASE22, /* base_relative pic */ + RELOC_PC10, + RELOC_PC22, /* special pc-rel pic */ + RELOC_JMP_TBL, /* jmp_tbl_rel in pic */ + RELOC_SEGOFF16, /* ShLib offset-in-seg */ + RELOC_GLOB_DAT, + RELOC_JMP_SLOT, + RELOC_RELATIVE /* rtld relocs */ +}; + +/* + * Format of a relocation datum. + */ +struct relocation_info /* used when header.a_machtype == M_SPARC */ +{ + unsigned long r_address; /* relocation addr */ + unsigned int r_index:24; /* segment index or symbol index */ + unsigned int r_extern:1; /* if F, r_index==SEG#; if T, SYM idx */ + int r_pad:2; /* <unused> */ + enum reloc_type r_type:5; /* type of relocation to perform */ + long r_addend; /* addend for relocation value */ +}; + +#define N_RELOCATION_INFO_DECLARED 1 + +#ifdef __KERNEL__ + +#include <asm/page.h> + +#define STACK_TOP (PAGE_OFFSET - PAGE_SIZE) + +#endif /* __KERNEL__ */ + +#endif /* __SPARC_A_OUT_H__ */ diff --git a/qemu/roms/openbios/include/arch/sparc32/asi.h b/qemu/roms/openbios/include/arch/sparc32/asi.h new file mode 100644 index 000000000..af3d69c13 --- /dev/null +++ b/qemu/roms/openbios/include/arch/sparc32/asi.h @@ -0,0 +1,111 @@ +/* $Id: asi.h,v 1.1 2002/07/12 17:06:36 zaitcev Exp $ */ +#ifndef _SPARC_ASI_H +#define _SPARC_ASI_H + +/* asi.h: Address Space Identifier values for the sparc. + * + * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + * + * Pioneer work for sun4m: Paul Hatchman (paul@sfe.com.au) + * Joint edition for sun4c+sun4m: Pete A. Zaitcev <zaitcev@ipmce.su> + */ + +/* The first batch are for the sun4c. */ + +#define ASI_NULL1 0x00 +#define ASI_NULL2 0x01 + +/* sun4c and sun4 control registers and mmu/vac ops */ +#define ASI_CONTROL 0x02 +#define ASI_SEGMAP 0x03 +#define ASI_PTE 0x04 +#define ASI_HWFLUSHSEG 0x05 +#define ASI_HWFLUSHPAGE 0x06 +#define ASI_REGMAP 0x06 +#define ASI_HWFLUSHCONTEXT 0x07 + +#define ASI_USERTXT 0x08 +#define ASI_KERNELTXT 0x09 +#define ASI_USERDATA 0x0a +#define ASI_KERNELDATA 0x0b + +/* VAC Cache flushing on sun4c and sun4 */ +#define ASI_FLUSHSEG 0x0c +#define ASI_FLUSHPG 0x0d +#define ASI_FLUSHCTX 0x0e + +/* SPARCstation-5: only 6 bits are decoded. */ +/* wo = Write Only, rw = Read Write; */ +/* ss = Single Size, as = All Sizes; */ +#define ASI_M_RES00 0x00 /* Don't touch... */ +#define ASI_M_UNA01 0x01 /* Same here... */ +#define ASI_M_MXCC 0x02 /* Access to TI VIKING MXCC registers */ +#define ASI_M_FLUSH_PROBE 0x03 /* Reference MMU Flush/Probe; rw, ss */ +#define ASI_M_MMUREGS 0x04 /* MMU Registers; rw, ss */ +#define ASI_M_TLBDIAG 0x05 /* MMU TLB only Diagnostics */ +#define ASI_M_DIAGS 0x06 /* Reference MMU Diagnostics */ +#define ASI_M_IODIAG 0x07 /* MMU I/O TLB only Diagnostics */ +#define ASI_M_USERTXT 0x08 /* Same as ASI_USERTXT; rw, as */ +#define ASI_M_KERNELTXT 0x09 /* Same as ASI_KERNELTXT; rw, as */ +#define ASI_M_USERDATA 0x0A /* Same as ASI_USERDATA; rw, as */ +#define ASI_M_KERNELDATA 0x0B /* Same as ASI_KERNELDATA; rw, as */ +#define ASI_M_TXTC_TAG 0x0C /* Instruction Cache Tag; rw, ss */ +#define ASI_M_TXTC_DATA 0x0D /* Instruction Cache Data; rw, ss */ +#define ASI_M_DATAC_TAG 0x0E /* Data Cache Tag; rw, ss */ +#define ASI_M_DATAC_DATA 0x0F /* Data Cache Data; rw, ss */ + +/* The following cache flushing ASIs work only with the 'sta' + * instruction. Results are unpredictable for 'swap' and 'ldstuba', + * so don't do it. + */ + +/* These ASI flushes affect external caches too. */ +#define ASI_M_FLUSH_PAGE 0x10 /* Flush I&D Cache Line (page); wo, ss */ +#define ASI_M_FLUSH_SEG 0x11 /* Flush I&D Cache Line (seg); wo, ss */ +#define ASI_M_FLUSH_REGION 0x12 /* Flush I&D Cache Line (region); wo, ss */ +#define ASI_M_FLUSH_CTX 0x13 /* Flush I&D Cache Line (context); wo, ss */ +#define ASI_M_FLUSH_USER 0x14 /* Flush I&D Cache Line (user); wo, ss */ + +/* Block-copy operations are available only on certain V8 cpus. */ +#define ASI_M_BCOPY 0x17 /* Block copy */ + +/* These affect only the ICACHE and are Ross HyperSparc and TurboSparc specific. */ +#define ASI_M_IFLUSH_PAGE 0x18 /* Flush I Cache Line (page); wo, ss */ +#define ASI_M_IFLUSH_SEG 0x19 /* Flush I Cache Line (seg); wo, ss */ +#define ASI_M_IFLUSH_REGION 0x1A /* Flush I Cache Line (region); wo, ss */ +#define ASI_M_IFLUSH_CTX 0x1B /* Flush I Cache Line (context); wo, ss */ +#define ASI_M_IFLUSH_USER 0x1C /* Flush I Cache Line (user); wo, ss */ + +/* Block-fill operations are available on certain V8 cpus */ +#define ASI_M_BFILL 0x1F + +/* This allows direct access to main memory, actually 0x20 to 0x2f are + * the available ASI's for physical ram pass-through, but I don't have + * any idea what the other ones do.... + */ + +#define ASI_M_BYPASS 0x20 /* Reference MMU bypass; rw, as */ +#define ASI_M_FBMEM 0x29 /* Graphics card frame buffer access */ +#define ASI_M_VMEUS 0x2A /* VME user 16-bit access */ +#define ASI_M_VMEPS 0x2B /* VME priv 16-bit access */ +#define ASI_M_VMEUT 0x2C /* VME user 32-bit access */ +#define ASI_M_VMEPT 0x2D /* VME priv 32-bit access */ +#define ASI_M_SBUS 0x2E /* Direct SBus access */ +#define ASI_M_CTL 0x2F /* Control Space (ECC and MXCC are here) */ + + +/* This is ROSS HyperSparc only. */ +#define ASI_M_FLUSH_IWHOLE 0x31 /* Flush entire ICACHE; wo, ss */ + +/* Tsunami/Viking/TurboSparc i/d cache flash clear. */ +#define ASI_M_IC_FLCLEAR 0x36 +#define ASI_M_DC_FLCLEAR 0x37 + +#define ASI_M_DCDR 0x39 /* Data Cache Diagnostics Register rw, ss */ + +#define ASI_M_VIKING_TMP1 0x40 /* Emulation temporary 1 on Viking */ +#define ASI_M_VIKING_TMP2 0x41 /* Emulation temporary 2 on Viking */ + +#define ASI_M_ACTION 0x4c /* Breakpoint Action Register (GNU/Viking) */ + +#endif /* _SPARC_ASI_H */ diff --git a/qemu/roms/openbios/include/arch/sparc32/crs.h b/qemu/roms/openbios/include/arch/sparc32/crs.h new file mode 100644 index 000000000..7b4559372 --- /dev/null +++ b/qemu/roms/openbios/include/arch/sparc32/crs.h @@ -0,0 +1,14 @@ +/* + * Parts of asm-sparc/contregs.h + * + * contregs.h: Addresses of registers in the ASI_CONTROL alternate address + * space. These are for the mmu's context register, etc. + * + * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + */ +/* s=Swift, h=Ross_HyperSPARC, v=TI_Viking, t=Tsunami, r=Ross_Cypress */ +#define AC_M_PCR 0x0000 /* shv Processor Control Reg */ +#define AC_M_CTPR 0x0100 /* shv Context Table Pointer Reg */ +#define AC_M_CXR 0x0200 /* shv Context Register */ +#define AC_M_SFSR 0x0300 /* shv Synchronous Fault Status Reg */ +#define AC_M_SFAR 0x0400 /* shv Synchronous Fault Address Reg */ diff --git a/qemu/roms/openbios/include/arch/sparc32/dma.h b/qemu/roms/openbios/include/arch/sparc32/dma.h new file mode 100644 index 000000000..e1310557b --- /dev/null +++ b/qemu/roms/openbios/include/arch/sparc32/dma.h @@ -0,0 +1,213 @@ +/* + * Local copy of include/asm-sparc/dma.h + * + * Copyright 1995 (C) David S. Miller (davem@caip.rutgers.edu) + */ + +#ifndef _ASM_SPARC_DMA_H +#define _ASM_SPARC_DMA_H + +/* #include <linux/kernel.h> */ +/* #include <linux/types.h> */ +typedef unsigned int __u32; + +/* These are irrelevant for Sparc DMA, but we leave it in so that + * things can compile. + */ +#define MAX_DMA_CHANNELS 8 +#define MAX_DMA_ADDRESS (~0UL) +#define DMA_MODE_READ 1 +#define DMA_MODE_WRITE 2 + +/* Useful constants */ +#define SIZE_16MB (16*1024*1024) +#define SIZE_64K (64*1024) + +/* Structure to describe the current status of DMA registers on the Sparc */ +struct sparc_dma_registers { + __volatile__ __u32 cond_reg; /* DMA condition register */ + __volatile__ __u32 st_addr; /* Start address of this transfer */ + __volatile__ __u32 cnt; /* How many bytes to transfer */ + __volatile__ __u32 dma_test; /* DMA test register */ +}; + +/* DVMA chip revisions */ +enum dvma_rev { + dvmarev0, + dvmaesc1, + dvmarev1, + dvmarev2, + dvmarev3, + dvmarevplus, + dvmahme +}; + +#define DMA_HASCOUNT(rev) ((rev)==dvmaesc1) + +#if 0 +/* Linux DMA information structure, filled during probe. */ +struct Linux_SBus_DMA { + struct Linux_SBus_DMA *next; + struct linux_sbus_device *SBus_dev; + struct sparc_dma_registers *regs; + + /* Status, misc info */ + int node; /* Prom node for this DMA device */ + int running; /* Are we doing DMA now? */ + int allocated; /* Are we "owned" by anyone yet? */ + + /* Transfer information. */ + unsigned long addr; /* Start address of current transfer */ + int nbytes; /* Size of current transfer */ + int realbytes; /* For splitting up large transfers, etc. */ + + /* DMA revision */ + enum dvma_rev revision; +}; + +extern struct Linux_SBus_DMA *dma_chain; +#endif + +/* Broken hardware... */ +/* Have to sort this out. Does rev0 work fine on sun4[cmd] without isbroken? + * Or is rev0 present only on sun4 boxes? -jj */ +#define DMA_ISBROKEN(dma) ((dma)->revision == dvmarev0 || (dma)->revision == dvmarev1) +#define DMA_ISESC1(dma) ((dma)->revision == dvmaesc1) + +/* Fields in the cond_reg register */ +/* First, the version identification bits */ +#define DMA_DEVICE_ID 0xf0000000 /* Device identification bits */ +#define DMA_VERS0 0x00000000 /* Sunray DMA version */ +#define DMA_ESCV1 0x40000000 /* DMA ESC Version 1 */ +#define DMA_VERS1 0x80000000 /* DMA rev 1 */ +#define DMA_VERS2 0xa0000000 /* DMA rev 2 */ +#define DMA_VERHME 0xb0000000 /* DMA hme gate array */ +#define DMA_VERSPLUS 0x90000000 /* DMA rev 1 PLUS */ + +#define DMA_HNDL_INTR 0x00000001 /* An IRQ needs to be handled */ +#define DMA_HNDL_ERROR 0x00000002 /* We need to take an error */ +#define DMA_FIFO_ISDRAIN 0x0000000c /* The DMA FIFO is draining */ +#define DMA_INT_ENAB 0x00000010 /* Turn on interrupts */ +#define DMA_FIFO_INV 0x00000020 /* Invalidate the FIFO */ +#define DMA_ACC_SZ_ERR 0x00000040 /* The access size was bad */ +#define DMA_FIFO_STDRAIN 0x00000040 /* DMA_VERS1 Drain the FIFO */ +#define DMA_RST_SCSI 0x00000080 /* Reset the SCSI controller */ +#define DMA_RST_ENET DMA_RST_SCSI /* Reset the ENET controller */ +#define DMA_ST_WRITE 0x00000100 /* write from device to memory */ +#define DMA_ENABLE 0x00000200 /* Fire up DMA, handle requests */ +#define DMA_PEND_READ 0x00000400 /* DMA_VERS1/0/PLUS Pending Read */ +#define DMA_ESC_BURST 0x00000800 /* 1=16byte 0=32byte */ +#define DMA_READ_AHEAD 0x00001800 /* DMA read ahead partial longword */ +#define DMA_DSBL_RD_DRN 0x00001000 /* No EC drain on slave reads */ +#define DMA_BCNT_ENAB 0x00002000 /* If on, use the byte counter */ +#define DMA_TERM_CNTR 0x00004000 /* Terminal counter */ +#define DMA_SCSI_SBUS64 0x00008000 /* HME: Enable 64-bit SBUS mode. */ +#define DMA_CSR_DISAB 0x00010000 /* No FIFO drains during csr */ +#define DMA_SCSI_DISAB 0x00020000 /* No FIFO drains during reg */ +#define DMA_DSBL_WR_INV 0x00020000 /* No EC inval. on slave writes */ +#define DMA_ADD_ENABLE 0x00040000 /* Special ESC DVMA optimization */ +#define DMA_E_BURST8 0x00040000 /* ENET: SBUS r/w burst size */ +#define DMA_BRST_SZ 0x000c0000 /* SCSI: SBUS r/w burst size */ +#define DMA_BRST64 0x00080000 /* SCSI: 64byte bursts (HME on UltraSparc only) */ +#define DMA_BRST32 0x00040000 /* SCSI: 32byte bursts */ +#define DMA_BRST16 0x00000000 /* SCSI: 16byte bursts */ +#define DMA_BRST0 0x00080000 /* SCSI: no bursts (non-HME gate arrays) */ +#define DMA_ADDR_DISAB 0x00100000 /* No FIFO drains during addr */ +#define DMA_2CLKS 0x00200000 /* Each transfer = 2 clock ticks */ +#define DMA_3CLKS 0x00400000 /* Each transfer = 3 clock ticks */ +#define DMA_EN_ENETAUI DMA_3CLKS /* Put lance into AUI-cable mode */ +#define DMA_CNTR_DISAB 0x00800000 /* No IRQ when DMA_TERM_CNTR set */ +#define DMA_AUTO_NADDR 0x01000000 /* Use "auto nxt addr" feature */ +#define DMA_SCSI_ON 0x02000000 /* Enable SCSI dma */ +#define DMA_PARITY_OFF 0x02000000 /* HME: disable parity checking */ +#define DMA_LOADED_ADDR 0x04000000 /* Address has been loaded */ +#define DMA_LOADED_NADDR 0x08000000 /* Next address has been loaded */ +#define DMA_RESET_FAS366 0x08000000 /* HME: Assert RESET to FAS366 */ + +/* Values describing the burst-size property from the PROM */ +#define DMA_BURST1 0x01 +#define DMA_BURST2 0x02 +#define DMA_BURST4 0x04 +#define DMA_BURST8 0x08 +#define DMA_BURST16 0x10 +#define DMA_BURST32 0x20 +#define DMA_BURST64 0x40 +#define DMA_BURSTBITS 0x7f + +/* Determine highest possible final transfer address given a base */ +#define DMA_MAXEND(addr) (0x01000000UL-(((unsigned long)(addr))&0x00ffffffUL)) + +/* Yes, I hack a lot of elisp in my spare time... */ +#define DMA_ERROR_P(regs) ((((regs)->cond_reg) & DMA_HNDL_ERROR)) +#define DMA_IRQ_P(regs) ((((regs)->cond_reg) & (DMA_HNDL_INTR | DMA_HNDL_ERROR))) +#define DMA_WRITE_P(regs) ((((regs)->cond_reg) & DMA_ST_WRITE)) +#define DMA_OFF(regs) ((((regs)->cond_reg) &= (~DMA_ENABLE))) +#define DMA_INTSOFF(regs) ((((regs)->cond_reg) &= (~DMA_INT_ENAB))) +#define DMA_INTSON(regs) ((((regs)->cond_reg) |= (DMA_INT_ENAB))) +#define DMA_PUNTFIFO(regs) ((((regs)->cond_reg) |= DMA_FIFO_INV)) +#define DMA_SETSTART(regs, addr) ((((regs)->st_addr) = (char *) addr)) +#define DMA_BEGINDMA_W(regs) \ + ((((regs)->cond_reg |= (DMA_ST_WRITE|DMA_ENABLE|DMA_INT_ENAB)))) +#define DMA_BEGINDMA_R(regs) \ + ((((regs)->cond_reg |= ((DMA_ENABLE|DMA_INT_ENAB)&(~DMA_ST_WRITE))))) + +#if 0 + +/* For certain DMA chips, we need to disable ints upon irq entry + * and turn them back on when we are done. So in any ESP interrupt + * handler you *must* call DMA_IRQ_ENTRY upon entry and DMA_IRQ_EXIT + * when leaving the handler. You have been warned... + */ +#define DMA_IRQ_ENTRY(dma, dregs) do { \ + if(DMA_ISBROKEN(dma)) DMA_INTSOFF(dregs); \ + } while (0) + +#define DMA_IRQ_EXIT(dma, dregs) do { \ + if(DMA_ISBROKEN(dma)) DMA_INTSON(dregs); \ + } while(0) + + +/* Pause until counter runs out or BIT isn't set in the DMA condition + * register. + */ +extern __inline__ void sparc_dma_pause(struct sparc_dma_registers *regs, + unsigned long bit) +{ + int ctr = 50000; /* Let's find some bugs ;) */ + + /* Busy wait until the bit is not set any more */ + while((regs->cond_reg&bit) && (ctr>0)) { + ctr--; + __delay(5); + } + + /* Check for bogus outcome. */ + if(!ctr) + panic("DMA timeout"); +} + +/* Reset the friggin' thing... */ +#define DMA_RESET(dma) do { \ + struct sparc_dma_registers *regs = dma->regs; \ + /* Let the current FIFO drain itself */ \ + sparc_dma_pause(regs, (DMA_FIFO_ISDRAIN)); \ + /* Reset the logic */ \ + regs->cond_reg |= (DMA_RST_SCSI); /* assert */ \ + __delay(400); /* let the bits set ;) */ \ + regs->cond_reg &= ~(DMA_RST_SCSI); /* de-assert */ \ + sparc_dma_enable_interrupts(regs); /* Re-enable interrupts */ \ + /* Enable FAST transfers if available */ \ + if(dma->revision>dvmarev1) regs->cond_reg |= DMA_3CLKS; \ + dma->running = 0; \ +} while(0) + +#define for_each_dvma(dma) \ + for((dma) = dma_chain; (dma); (dma) = (dma)->next) + +extern int get_dma_list(char *); +extern int request_dma(unsigned int, __const__ char *); +extern void free_dma(unsigned int); + +#endif + +#endif /* !(_ASM_SPARC_DMA_H) */ diff --git a/qemu/roms/openbios/include/arch/sparc32/elf.h b/qemu/roms/openbios/include/arch/sparc32/elf.h new file mode 100644 index 000000000..8d429d7aa --- /dev/null +++ b/qemu/roms/openbios/include/arch/sparc32/elf.h @@ -0,0 +1,5 @@ +#define ARCH_ELF_CLASS ELFCLASS32 +#define ARCH_ELF_DATA ELFDATA2MSB +#define ARCH_ELF_MACHINE_OK(x) ((x)==EM_SPARC || (x)==EM_SPARC32PLUS) +typedef Elf32_Ehdr Elf_ehdr; +typedef Elf32_Phdr Elf_phdr; diff --git a/qemu/roms/openbios/include/arch/sparc32/io.h b/qemu/roms/openbios/include/arch/sparc32/io.h new file mode 100644 index 000000000..011770ad1 --- /dev/null +++ b/qemu/roms/openbios/include/arch/sparc32/io.h @@ -0,0 +1,201 @@ +#ifndef _ASM_IO_H +#define _ASM_IO_H + +#include "asm/types.h" + +extern unsigned int va_shift; // Set in entry.S + +// Defined in ldscript +extern char _start, _data, _stack, _estack, _end, _vmem, _evmem, _iomem; + +// XXX check use and merge +#define phys_to_virt(phys) ((void *) ((unsigned long) (phys))) +#define virt_to_phys(virt) ((unsigned long) (virt)) + +#ifndef BOOTSTRAP + +#ifndef _IO_BASE +#define _IO_BASE 0 +#endif + +/* + * The insw/outsw/insl/outsl macros don't do byte-swapping. + * They are only used in practice for transferring buffers which + * are arrays of bytes, and byte-swapping is not appropriate in + * that case. - paulus + */ +#define insw(port, buf, ns) _insw_ns((uint16_t *)((port)+_IO_BASE), (buf), (ns)) +#define outsw(port, buf, ns) _outsw_ns((uint16_t *)((port)+_IO_BASE), (buf), (ns)) + +#define inb(port) in_8((uint8_t *)((port)+_IO_BASE)) +#define outb(val, port) out_8((uint8_t *)((port)+_IO_BASE), (val)) +#define inw(port) in_le16((uint16_t *)((port)+_IO_BASE)) +#define outw(val, port) out_le16((uint16_t *)((port)+_IO_BASE), (val)) +#define inl(port) in_le32((uint32_t *)((port)+_IO_BASE)) +#define outl(val, port) out_le32((uint32_t *)((port)+_IO_BASE), (val)) + +/* + * 8, 16 and 32 bit, big and little endian I/O operations, with barrier. + */ +static inline int in_8(volatile unsigned char *addr) +{ + int ret; + + __asm__ __volatile__("ldub [%1], %0\n\t" + "stbar\n\t" + :"=r"(ret):"r"(addr):"memory"); + + return ret; +} + +static inline void out_8(volatile unsigned char *addr, int val) +{ + __asm__ __volatile__("stb %0, [%1]\n\t" + "stbar\n\t" + : : "r"(val), "r"(addr):"memory"); +} + +static inline int in_le16(volatile unsigned short *addr) +{ + int ret; + + // XXX + __asm__ __volatile__("lduh [%1], %0\n\t" + "stbar\n\t" + :"=r"(ret):"r"(addr):"memory"); + + return ret; +} + +static inline int in_be16(volatile unsigned short *addr) +{ + int ret; + + __asm__ __volatile__("lduh [%1], %0\n\t" + "stbar\n\t" + :"=r"(ret):"r"(addr):"memory"); + + return ret; +} + +static inline void out_le16(volatile unsigned short *addr, int val) +{ + // XXX + __asm__ __volatile__("sth %0, [%1]\n\t" + "stbar\n\t" + : : "r"(val), "r"(addr):"memory"); +} + +static inline void out_be16(volatile unsigned short *addr, int val) +{ + __asm__ __volatile__("sth %0, [%1]\n\t" + "stbar\n\t" + : : "r"(val), "r"(addr):"memory"); +} + +static inline unsigned in_le32(volatile unsigned *addr) +{ + unsigned ret; + + // XXX + __asm__ __volatile__("ld [%1], %0\n\t" + "stbar\n\t" + :"=r"(ret):"r"(addr):"memory"); + + return ret; +} + +static inline unsigned in_be32(volatile unsigned *addr) +{ + unsigned ret; + + __asm__ __volatile__("ld [%1], %0\n\t" + "stbar\n\t" + :"=r"(ret):"r"(addr):"memory"); + + return ret; +} + +static inline void out_le32(volatile unsigned *addr, int val) +{ + // XXX + __asm__ __volatile__("st %0, [%1]\n\t" + "stbar\n\t" + : : "r"(val), "r"(addr):"memory"); +} + +static inline void out_be32(volatile unsigned *addr, int val) +{ + __asm__ __volatile__("st %0, [%1]\n\t" + "stbar\n\t" + : : "r"(val), "r"(addr):"memory"); +} + +static inline void _insw_ns(volatile uint16_t * port, void *buf, int ns) +{ + uint16_t *b = (uint16_t *) buf; + + while (ns > 0) { + *b++ = in_le16(port); + ns--; + } +} + +static inline void _outsw_ns(volatile uint16_t * port, const void *buf, + int ns) +{ + uint16_t *b = (uint16_t *) buf; + + while (ns > 0) { + out_le16(port, *b++); + ns--; + } +} + +static inline void _insw(volatile uint16_t * port, void *buf, int ns) +{ + uint16_t *b = (uint16_t *) buf; + + while (ns > 0) { + *b++ = in_be16(port); + ns--; + } +} + +static inline void _outsw(volatile uint16_t * port, const void *buf, + int ns) +{ + uint16_t *b = (uint16_t *) buf; + + while (ns > 0) { + out_be16(port, *b++); + ns--; + } +} +#else /* BOOTSTRAP */ +#ifdef FCOMPILER +#define inb(reg) ((u8)0xff) +#define inw(reg) ((u16)0xffff) +#define inl(reg) ((u32)0xffffffff) +#define outb(reg, val) do{} while(0) +#define outw(reg, val) do{} while(0) +#define outl(reg, val) do{} while(0) +#else +extern u8 inb(u32 reg); +extern u16 inw(u32 reg); +extern u32 inl(u32 reg); +extern void insw(u32 reg, void *addr, unsigned long count); +extern void outb(u32 reg, u8 val); +extern void outw(u32 reg, u16 val); +extern void outl(u32 reg, u32 val); +extern void outsw(u32 reg, const void *addr, unsigned long count); +#endif +#endif + +#if defined(CONFIG_QEMU) +#define FW_CFG_ARCH_DEPTH (FW_CFG_ARCH_LOCAL + 0x00) +#define FW_CFG_ARCH_WIDTH (FW_CFG_ARCH_LOCAL + 0x01) +#define FW_CFG_ARCH_HEIGHT (FW_CFG_ARCH_LOCAL + 0x02) +#endif + +#endif /* _ASM_IO_H */ diff --git a/qemu/roms/openbios/include/arch/sparc32/ofmem_sparc32.h b/qemu/roms/openbios/include/arch/sparc32/ofmem_sparc32.h new file mode 100644 index 000000000..efc21b498 --- /dev/null +++ b/qemu/roms/openbios/include/arch/sparc32/ofmem_sparc32.h @@ -0,0 +1,31 @@ +/* + * <ofmem_sparc32.h> + * + * OF Memory manager + * + * Copyright (C) 1999, 2002 Samuel Rydh (samuel@ibrium.se) + * + * 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 + * + */ + +#ifndef _H_OFMEM_SPARC32 +#define _H_OFMEM_SPARC32 + +#include "libopenbios/ofmem.h" + +#define OF_CODE_START 0xffd00000 +#define OFMEM_VIRT_TOP 0xfe000000 + +struct mem; +extern struct mem cdvmem; + +extern unsigned long *l1; +extern unsigned long find_pte(unsigned long va, int alloc); + +void mem_init(struct mem *t, char *begin, char *limit); +void *mem_alloc(struct mem *t, int size, int align); + +#endif /* _H_OFMEM_SPARC32 */
\ No newline at end of file diff --git a/qemu/roms/openbios/include/arch/sparc32/types.h b/qemu/roms/openbios/include/arch/sparc32/types.h new file mode 100644 index 000000000..3f37d4e03 --- /dev/null +++ b/qemu/roms/openbios/include/arch/sparc32/types.h @@ -0,0 +1,93 @@ +/* tag: data types for forth engine + * + * Copyright (C) 2003-2005 Patrick Mauritz, Stefan Reinauer + * + * See the file "COPYING" for further information about + * the copyright and warranty status of this work. + */ + +#ifndef __TYPES_H +#define __TYPES_H + +#include "mconfig.h" + +#ifdef BOOTSTRAP +#include <inttypes.h> +#else +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned int uint32_t; +typedef unsigned long long uint64_t; +typedef unsigned long uintptr_t; + +typedef signed char int8_t; +typedef short int16_t; +typedef int int32_t; +typedef long long int64_t; +typedef long intptr_t; + +#define PRId32 "d" +#define PRIu32 "u" +#define PRIx32 "x" +#define PRIX32 "X" +#define PRId64 "lld" +#define PRIu64 "llu" +#define PRIx64 "llx" +#define PRIX64 "llX" +#endif + +/* endianess */ +#include "autoconf.h" + +/* physical address: 36 bits */ + +typedef uint64_t phys_addr_t; + +#define FMT_plx "%09" PRIx64 + +/* cell based types */ + +typedef int32_t cell; +typedef uint32_t ucell; +typedef long long dcell; +typedef unsigned long long ducell; + +#define FMT_cell "%" PRId32 +#define FMT_ucell "%" PRIu32 +#define FMT_ucellx "%08" PRIx32 +#define FMT_ucellX "%08" PRIX32 + +typedef int32_t prom_arg_t; +typedef uint32_t prom_uarg_t; + +#define PRIdPROMARG PRId32 +#define PRIuPROMARG PRIu32 +#define PRIxPROMARG PRIx32 +#define FMT_prom_arg "%" PRIdPROMARG +#define FMT_prom_uarg "%" PRIuPROMARG +#define FMT_prom_uargx "%08" PRIxPROMARG + +#define FMT_elf "%#x" +#define FMT_sizet "%lx" +#define FMT_aout_ehdr "%lx" + +#define bitspercell (sizeof(cell)<<3) +#define bitsperdcell (sizeof(dcell)<<3) + +#define BITS 32 + +#define PAGE_SHIFT 12 + +/* size named types */ + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned int u32; +typedef unsigned long long u64; + +typedef signed char s8; +typedef short s16; +typedef int s32; +typedef long long s64; + +#endif diff --git a/qemu/roms/openbios/include/arch/sparc64/a.out.h b/qemu/roms/openbios/include/arch/sparc64/a.out.h new file mode 100644 index 000000000..35cb5c9e0 --- /dev/null +++ b/qemu/roms/openbios/include/arch/sparc64/a.out.h @@ -0,0 +1,108 @@ +/* $Id: a.out.h,v 1.8 2002/02/09 19:49:31 davem Exp $ */ +#ifndef __SPARC64_A_OUT_H__ +#define __SPARC64_A_OUT_H__ + +#define SPARC_PGSIZE 0x2000 /* Thanks to the sun4 architecture... */ +#define SEGMENT_SIZE SPARC_PGSIZE /* whee... */ + +#ifndef __ASSEMBLY__ + +struct exec { + unsigned char a_dynamic:1; /* A __DYNAMIC is in this image */ + unsigned char a_toolversion:7; + unsigned char a_machtype; + unsigned short a_info; + unsigned int a_text; /* length of text, in bytes */ + unsigned int a_data; /* length of data, in bytes */ + unsigned int a_bss; /* length of bss, in bytes */ + unsigned int a_syms; /* length of symbol table, in bytes */ + unsigned int a_entry; /* where program begins */ + unsigned int a_trsize; + unsigned int a_drsize; +}; + +#endif /* !__ASSEMBLY__ */ + +/* Where in the file does the text information begin? */ +#define N_TXTOFF(x) (N_MAGIC(x) == ZMAGIC ? 0 : sizeof (struct exec)) + +/* Where do the Symbols start? */ +#define N_SYMOFF(x) (N_TXTOFF(x) + (x).a_text + \ + (x).a_data + (x).a_trsize + \ + (x).a_drsize) + +/* Where does text segment go in memory after being loaded? */ +#define N_TXTADDR(x) (unsigned long)(((N_MAGIC(x) == ZMAGIC) && \ + ((x).a_entry < SPARC_PGSIZE)) ? \ + 0 : SPARC_PGSIZE) + +/* And same for the data segment.. */ +#define N_DATADDR(x) (N_MAGIC(x)==OMAGIC ? \ + (N_TXTADDR(x) + (x).a_text) \ + : (unsigned long)(_N_SEGMENT_ROUND (_N_TXTENDADDR(x)))) + +#define N_TRSIZE(a) ((a).a_trsize) +#define N_DRSIZE(a) ((a).a_drsize) +#define N_SYMSIZE(a) ((a).a_syms) + +#ifndef __ASSEMBLY__ + +/* + * Sparc relocation types + */ +enum reloc_type +{ + RELOC_8, + RELOC_16, + RELOC_32, /* simplest relocs */ + RELOC_DISP8, + RELOC_DISP16, + RELOC_DISP32, /* Disp's (pc-rel) */ + RELOC_WDISP30, + RELOC_WDISP22, /* SR word disp's */ + RELOC_HI22, + RELOC_22, /* SR 22-bit relocs */ + RELOC_13, + RELOC_LO10, /* SR 13&10-bit relocs */ + RELOC_SFA_BASE, + RELOC_SFA_OFF13, /* SR S.F.A. relocs */ + RELOC_BASE10, + RELOC_BASE13, + RELOC_BASE22, /* base_relative pic */ + RELOC_PC10, + RELOC_PC22, /* special pc-rel pic */ + RELOC_JMP_TBL, /* jmp_tbl_rel in pic */ + RELOC_SEGOFF16, /* ShLib offset-in-seg */ + RELOC_GLOB_DAT, + RELOC_JMP_SLOT, + RELOC_RELATIVE /* rtld relocs */ +}; + +/* + * Format of a relocation datum. + */ +struct relocation_info /* used when header.a_machtype == M_SPARC */ +{ + unsigned int r_address; /* relocation addr */ + unsigned int r_index:24; /* segment index or symbol index */ + unsigned int r_extern:1; /* if F, r_index==SEG#; if T, SYM idx */ + int r_pad:2; /* <unused> */ + enum reloc_type r_type:5; /* type of relocation to perform */ + int r_addend; /* addend for relocation value */ +}; + +#define N_RELOCATION_INFO_DECLARED 1 + +#ifdef __KERNEL__ + +#define STACK_TOP32 ((1UL << 32UL) - PAGE_SIZE) +#define STACK_TOP64 (0x0000080000000000UL - (1UL << 32UL)) + +#define STACK_TOP (test_thread_flag(TIF_32BIT) ? \ + STACK_TOP32 : STACK_TOP64) + +#endif + +#endif /* !(__ASSEMBLY__) */ + +#endif /* !(__SPARC64_A_OUT_H__) */ diff --git a/qemu/roms/openbios/include/arch/sparc64/asi.h b/qemu/roms/openbios/include/arch/sparc64/asi.h new file mode 100644 index 000000000..534855660 --- /dev/null +++ b/qemu/roms/openbios/include/arch/sparc64/asi.h @@ -0,0 +1,145 @@ +/* $Id: asi.h,v 1.5 2001/03/29 11:47:47 davem Exp $ */ +#ifndef _SPARC64_ASI_H +#define _SPARC64_ASI_H + +/* asi.h: Address Space Identifier values for the V9. + * + * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) + */ + +/* V9 Architecture mandary ASIs. */ +#define ASI_N 0x04 /* Nucleus */ +#define ASI_NL 0x0c /* Nucleus, little endian */ +#define ASI_AIUP 0x10 /* Primary, user */ +#define ASI_AIUS 0x11 /* Secondary, user */ +#define ASI_AIUPL 0x18 /* Primary, user, little endian */ +#define ASI_AIUSL 0x19 /* Secondary, user, little endian */ +#define ASI_P 0x80 /* Primary, implicit */ +#define ASI_S 0x81 /* Secondary, implicit */ +#define ASI_PNF 0x82 /* Primary, no fault */ +#define ASI_SNF 0x83 /* Secondary, no fault */ +#define ASI_PL 0x88 /* Primary, implicit, l-endian */ +#define ASI_SL 0x89 /* Secondary, implicit, l-endian */ +#define ASI_PNFL 0x8a /* Primary, no fault, l-endian */ +#define ASI_SNFL 0x8b /* Secondary, no fault, l-endian */ + +/* SpitFire and later extended ASIs. The "(III)" marker designates + * UltraSparc-III and later specific ASIs. The "(CMT)" marker designates + * Chip Multi Threading specific ASIs. + */ +#define ASI_PHYS_USE_EC 0x14 /* PADDR, E-cachable */ +#define ASI_PHYS_BYPASS_EC_E 0x15 /* PADDR, E-bit */ +#define ASI_PHYS_USE_EC_L 0x1c /* PADDR, E-cachable, little endian*/ +#define ASI_PHYS_BYPASS_EC_E_L 0x1d /* PADDR, E-bit, little endian */ +#define ASI_NUCLEUS_QUAD_LDD 0x24 /* Cachable, qword load */ +#define ASI_NUCLEUS_QUAD_LDD_L 0x2c /* Cachable, qword load, l-endian */ +#define ASI_PCACHE_DATA_STATUS 0x30 /* (III) PCache data stat RAM diag */ +#define ASI_PCACHE_DATA 0x31 /* (III) PCache data RAM diag */ +#define ASI_PCACHE_TAG 0x32 /* (III) PCache tag RAM diag */ +#define ASI_PCACHE_SNOOP_TAG 0x33 /* (III) PCache snoop tag RAM diag */ +#define ASI_QUAD_LDD_PHYS 0x34 /* (III+) PADDR, qword load */ +#define ASI_WCACHE_VALID_BITS 0x38 /* (III) WCache Valid Bits diag */ +#define ASI_WCACHE_DATA 0x39 /* (III) WCache data RAM diag */ +#define ASI_WCACHE_TAG 0x3a /* (III) WCache tag RAM diag */ +#define ASI_WCACHE_SNOOP_TAG 0x3b /* (III) WCache snoop tag RAM diag */ +#define ASI_QUAD_LDD_PHYS_L 0x3c /* (III+) PADDR, qw-load, l-endian */ +#define ASI_SRAM_FAST_INIT 0x40 /* (III+) Fast SRAM init */ +#define ASI_CORE_AVAILABLE 0x41 /* (CMT) LP Available */ +#define ASI_CORE_ENABLE_STAT 0x41 /* (CMT) LP Enable Status */ +#define ASI_CORE_ENABLE 0x41 /* (CMT) LP Enable RW */ +#define ASI_XIR_STEERING 0x41 /* (CMT) XIR Steering RW */ +#define ASI_CORE_RUNNING_RW 0x41 /* (CMT) LP Running RW */ +#define ASI_CORE_RUNNING_W1S 0x41 /* (CMT) LP Running Write-One Set */ +#define ASI_CORE_RUNNING_W1C 0x41 /* (CMT) LP Running Write-One Clr */ +#define ASI_CORE_RUNNING_STAT 0x41 /* (CMT) LP Running Status */ +#define ASI_CMT_ERROR_STEERING 0x41 /* (CMT) Error Steering RW */ +#define ASI_DCACHE_INVALIDATE 0x42 /* (III) DCache Invalidate diag */ +#define ASI_DCACHE_UTAG 0x43 /* (III) DCache uTag diag */ +#define ASI_DCACHE_SNOOP_TAG 0x44 /* (III) DCache snoop tag RAM diag */ +#define ASI_LSU_CONTROL 0x45 /* Load-store control unit */ +#define ASI_DCU_CONTROL_REG 0x45 /* (III) DCache Unit Control reg */ +#define ASI_DCACHE_DATA 0x46 /* DCache data-ram diag access */ +#define ASI_DCACHE_TAG 0x47 /* Dcache tag/valid ram diag access*/ +#define ASI_INTR_DISPATCH_STAT 0x48 /* IRQ vector dispatch status */ +#define ASI_INTR_RECEIVE 0x49 /* IRQ vector receive status */ +#define ASI_UPA_CONFIG 0x4a /* UPA config space */ +#define ASI_JBUS_CONFIG 0x4a /* (IIIi) JBUS Config Register */ +#define ASI_SAFARI_CONFIG 0x4a /* (III) Safari Config Register */ +#define ASI_SAFARI_ADDRESS 0x4a /* (III) Safari Address Register */ +#define ASI_ESTATE_ERROR_EN 0x4b /* E-cache error enable space */ +#define ASI_AFSR 0x4c /* Async fault status register */ +#define ASI_AFAR 0x4d /* Async fault address register */ +#define ASI_EC_TAG_DATA 0x4e /* E-cache tag/valid ram diag acc */ +#define ASI_IMMU 0x50 /* Insn-MMU main register space */ +#define ASI_IMMU_TSB_8KB_PTR 0x51 /* Insn-MMU 8KB TSB pointer reg */ +#define ASI_IMMU_TSB_64KB_PTR 0x52 /* Insn-MMU 64KB TSB pointer reg */ +#define ASI_ITLB_DATA_IN 0x54 /* Insn-MMU TLB data in reg */ +#define ASI_ITLB_DATA_ACCESS 0x55 /* Insn-MMU TLB data access reg */ +#define ASI_ITLB_TAG_READ 0x56 /* Insn-MMU TLB tag read reg */ +#define ASI_IMMU_DEMAP 0x57 /* Insn-MMU TLB demap */ +#define ASI_DMMU 0x58 /* Data-MMU main register space */ +#define ASI_DMMU_TSB_8KB_PTR 0x59 /* Data-MMU 8KB TSB pointer reg */ +#define ASI_DMMU_TSB_64KB_PTR 0x5a /* Data-MMU 16KB TSB pointer reg */ +#define ASI_DMMU_TSB_DIRECT_PTR 0x5b /* Data-MMU TSB direct pointer reg */ +#define ASI_DTLB_DATA_IN 0x5c /* Data-MMU TLB data in reg */ +#define ASI_DTLB_DATA_ACCESS 0x5d /* Data-MMU TLB data access reg */ +#define ASI_DTLB_TAG_READ 0x5e /* Data-MMU TLB tag read reg */ +#define ASI_DMMU_DEMAP 0x5f /* Data-MMU TLB demap */ +#define ASI_IIU_INST_TRAP 0x60 /* (III) Instruction Breakpoint */ +#define ASI_INTR_ID 0x63 /* (CMT) Interrupt ID register */ +#define ASI_CORE_ID 0x63 /* (CMT) LP ID register */ +#define ASI_CESR_ID 0x63 /* (CMT) CESR ID register */ +#define ASI_IC_INSTR 0x66 /* Insn cache instrucion ram diag */ +#define ASI_IC_TAG 0x67 /* Insn cache tag/valid ram diag */ +#define ASI_IC_STAG 0x68 /* (III) Insn cache snoop tag ram */ +#define ASI_IC_PRE_DECODE 0x6e /* Insn cache pre-decode ram diag */ +#define ASI_IC_NEXT_FIELD 0x6f /* Insn cache next-field ram diag */ +#define ASI_BRPRED_ARRAY 0x6f /* (III) Branch Prediction RAM diag*/ +#define ASI_BLK_AIUP 0x70 /* Primary, user, block load/store */ +#define ASI_BLK_AIUS 0x71 /* Secondary, user, block ld/st */ +#define ASI_MCU_CTRL_REG 0x72 /* (III) Memory controller regs */ +#define ASI_EC_DATA 0x74 /* (III) E-cache data staging reg */ +#define ASI_EC_CTRL 0x75 /* (III) E-cache control reg */ +#define ASI_EC_W 0x76 /* E-cache diag write access */ +#define ASI_UDB_ERROR_W 0x77 /* External UDB error regs W */ +#define ASI_UDB_CONTROL_W 0x77 /* External UDB control regs W */ +#define ASI_INTR_W 0x77 /* IRQ vector dispatch write */ +#define ASI_INTR_DATAN_W 0x77 /* (III) Out irq vector data reg N */ +#define ASI_INTR_DISPATCH_W 0x77 /* (III) Interrupt vector dispatch */ +#define ASI_BLK_AIUPL 0x78 /* Primary, user, little, blk ld/st*/ +#define ASI_BLK_AIUSL 0x79 /* Secondary, user, little, blk ld/st*/ +#define ASI_EC_R 0x7e /* E-cache diag read access */ +#define ASI_UDBH_ERROR_R 0x7f /* External UDB error regs rd hi */ +#define ASI_UDBL_ERROR_R 0x7f /* External UDB error regs rd low */ +#define ASI_UDBH_CONTROL_R 0x7f /* External UDB control regs rd hi */ +#define ASI_UDBL_CONTROL_R 0x7f /* External UDB control regs rd low*/ +#define ASI_INTR_R 0x7f /* IRQ vector dispatch read */ +#define ASI_INTR_DATAN_R 0x7f /* (III) In irq vector data reg N */ +#define ASI_PST8_P 0xc0 /* Primary, 8 8-bit, partial */ +#define ASI_PST8_S 0xc1 /* Secondary, 8 8-bit, partial */ +#define ASI_PST16_P 0xc2 /* Primary, 4 16-bit, partial */ +#define ASI_PST16_S 0xc3 /* Secondary, 4 16-bit, partial */ +#define ASI_PST32_P 0xc4 /* Primary, 2 32-bit, partial */ +#define ASI_PST32_S 0xc5 /* Secondary, 2 32-bit, partial */ +#define ASI_PST8_PL 0xc8 /* Primary, 8 8-bit, partial, L */ +#define ASI_PST8_SL 0xc9 /* Secondary, 8 8-bit, partial, L */ +#define ASI_PST16_PL 0xca /* Primary, 4 16-bit, partial, L */ +#define ASI_PST16_SL 0xcb /* Secondary, 4 16-bit, partial, L */ +#define ASI_PST32_PL 0xcc /* Primary, 2 32-bit, partial, L */ +#define ASI_PST32_SL 0xcd /* Secondary, 2 32-bit, partial, L */ +#define ASI_FL8_P 0xd0 /* Primary, 1 8-bit, fpu ld/st */ +#define ASI_FL8_S 0xd1 /* Secondary, 1 8-bit, fpu ld/st */ +#define ASI_FL16_P 0xd2 /* Primary, 1 16-bit, fpu ld/st */ +#define ASI_FL16_S 0xd3 /* Secondary, 1 16-bit, fpu ld/st */ +#define ASI_FL8_PL 0xd8 /* Primary, 1 8-bit, fpu ld/st, L */ +#define ASI_FL8_SL 0xd9 /* Secondary, 1 8-bit, fpu ld/st, L*/ +#define ASI_FL16_PL 0xda /* Primary, 1 16-bit, fpu ld/st, L */ +#define ASI_FL16_SL 0xdb /* Secondary, 1 16-bit, fpu ld/st,L*/ +#define ASI_BLK_COMMIT_P 0xe0 /* Primary, blk store commit */ +#define ASI_BLK_COMMIT_S 0xe1 /* Secondary, blk store commit */ +#define ASI_BLK_P 0xf0 /* Primary, blk ld/st */ +#define ASI_BLK_S 0xf1 /* Secondary, blk ld/st */ +#define ASI_BLK_PL 0xf8 /* Primary, blk ld/st, little */ +#define ASI_BLK_SL 0xf9 /* Secondary, blk ld/st, little */ + +#endif /* _SPARC64_ASI_H */ diff --git a/qemu/roms/openbios/include/arch/sparc64/elf.h b/qemu/roms/openbios/include/arch/sparc64/elf.h new file mode 100644 index 000000000..8acad1a47 --- /dev/null +++ b/qemu/roms/openbios/include/arch/sparc64/elf.h @@ -0,0 +1,5 @@ +#define ARCH_ELF_CLASS ELFCLASS64 +#define ARCH_ELF_DATA ELFDATA2MSB +#define ARCH_ELF_MACHINE_OK(x) ((x)==EM_SPARCV9) +typedef Elf64_Ehdr Elf_ehdr; +typedef Elf64_Phdr Elf_phdr; diff --git a/qemu/roms/openbios/include/arch/sparc64/io.h b/qemu/roms/openbios/include/arch/sparc64/io.h new file mode 100644 index 000000000..2e4dfa37f --- /dev/null +++ b/qemu/roms/openbios/include/arch/sparc64/io.h @@ -0,0 +1,209 @@ +#ifndef _ASM_IO_H +#define _ASM_IO_H + +#include "asm/types.h" +#include "asi.h" + +#define NO_QEMU_PROTOS +#include "arch/common/fw_cfg.h" + +extern unsigned long va_shift; // Set in entry.S +// Defined in ldscript +extern char _start, _data, _stack, _estack, _end, _iomem; + +// XXX check use and merge +#define phys_to_virt(phys) ((void *) ((unsigned long) (phys))) +#define virt_to_phys(virt) ((unsigned long) (virt)) + +#ifndef BOOTSTRAP + +extern unsigned long isa_io_base; + +/* + * The insw/outsw/insl/outsl macros don't do byte-swapping. + * They are only used in practice for transferring buffers which + * are arrays of bytes, and byte-swapping is not appropriate in + * that case. - paulus + */ +#define insw(port, buf, ns) _insw_ns((uint16_t *)((port)+isa_io_base), (buf), (ns)) +#define outsw(port, buf, ns) _outsw_ns((uint16_t *)((port)+isa_io_base), (buf), (ns)) + +#define inb(port) in_8((uint8_t *)((port)+isa_io_base)) +#define outb(val, port) out_8((uint8_t *)((port)+isa_io_base), (val)) +#define inw(port) in_be16((uint16_t *)((port)+isa_io_base)) +#define outw(val, port) out_be16((uint16_t *)((port)+isa_io_base), (val)) +#define inl(port) in_be32((uint32_t *)((port)+isa_io_base)) +#define outl(val, port) out_be32((uint32_t *)((port)+isa_io_base), (val)) + +/* + * 8, 16 and 32 bit, big and little endian I/O operations, with barrier. + * On Sparc64, BE versions must swap bytes using LE access ASI. + */ +static inline int in_8(volatile unsigned char *addr) +{ + int ret; + + __asm__ __volatile__("lduba [%1] %2, %0\n\t" + : "=r"(ret) + : "r"(addr), "i" (ASI_PHYS_BYPASS_EC_E) + : "memory"); + + return ret; +} + +static inline void out_8(volatile unsigned char *addr, int val) +{ + __asm__ __volatile__("stba %0, [%1] %2\n\t" + : + : "r"(val), "r"(addr), "i" (ASI_PHYS_BYPASS_EC_E) + : "memory"); +} + +static inline int in_le16(volatile unsigned short *addr) +{ + int ret; + + __asm__ __volatile__("lduha [%1] %2, %0\n\t" + : "=r"(ret) + : "r"(addr), "i" (ASI_PHYS_BYPASS_EC_E) + : "memory"); + + return ret; +} + +static inline int in_be16(volatile unsigned short *addr) +{ + int ret; + + __asm__ __volatile__("lduha [%1] %2, %0\n\t" + : "=r"(ret) + : "r"(addr), "i" (ASI_PHYS_BYPASS_EC_E_L) + : "memory"); + + return ret; +} + +static inline void out_le16(volatile unsigned short *addr, int val) +{ + + __asm__ __volatile__("stha %0, [%1] %2\n\t" + : + : "r"(val), "r"(addr), "i" (ASI_PHYS_BYPASS_EC_E) + : "memory"); +} + +static inline void out_be16(volatile unsigned short *addr, int val) +{ + __asm__ __volatile__("stha %0, [%1] %2\n\t" + : + : "r"(val), "r"(addr), "i" (ASI_PHYS_BYPASS_EC_E_L) + : "memory"); +} + +static inline unsigned in_le32(volatile unsigned *addr) +{ + unsigned ret; + + __asm__ __volatile__("lduwa [%1] %2, %0\n\t" + : "=r"(ret) + : "r"(addr), "i" (ASI_PHYS_BYPASS_EC_E) + : "memory"); + + return ret; +} + +static inline unsigned in_be32(volatile unsigned *addr) +{ + unsigned ret; + + __asm__ __volatile__("lduwa [%1] %2, %0\n\t" + : "=r"(ret) + : "r"(addr), "i" (ASI_PHYS_BYPASS_EC_E_L) + : "memory"); + return ret; +} + +static inline void out_le32(volatile unsigned *addr, int val) +{ + __asm__ __volatile__("stwa %0, [%1] %2\n\t" + : + : "r"(val), "r"(addr), "i" (ASI_PHYS_BYPASS_EC_E) + : "memory"); +} + +static inline void out_be32(volatile unsigned *addr, int val) +{ + __asm__ __volatile__("stwa %0, [%1] %2\n\t" + : + : "r"(val), "r"(addr), "i" (ASI_PHYS_BYPASS_EC_E_L) + : "memory"); +} + +static inline void _insw_ns(volatile uint16_t * port, void *buf, int ns) +{ + uint16_t *b = (uint16_t *) buf; + + while (ns > 0) { + *b++ = in_le16(port); + ns--; + } +} + +static inline void _outsw_ns(volatile uint16_t * port, const void *buf, + int ns) +{ + uint16_t *b = (uint16_t *) buf; + + while (ns > 0) { + out_le16(port, *b++); + ns--; + } +} + +static inline void _insw(volatile uint16_t * port, void *buf, int ns) +{ + uint16_t *b = (uint16_t *) buf; + + while (ns > 0) { + *b++ = in_be16(port); + ns--; + } +} + +static inline void _outsw(volatile uint16_t * port, const void *buf, + int ns) +{ + uint16_t *b = (uint16_t *) buf; + + while (ns > 0) { + out_be16(port, *b++); + ns--; + } +} +#else /* BOOTSTRAP */ +#ifdef FCOMPILER +#define inb(reg) ((u8)0xff) +#define inw(reg) ((u16)0xffff) +#define inl(reg) ((u32)0xffffffff) +#define outb(reg, val) do{} while(0) +#define outw(reg, val) do{} while(0) +#define outl(reg, val) do{} while(0) +#else +extern u8 inb(u32 reg); +extern u16 inw(u32 reg); +extern u32 inl(u32 reg); +extern void insw(u32 reg, void *addr, unsigned long count); +extern void outb(u32 reg, u8 val); +extern void outw(u32 reg, u16 val); +extern void outl(u32 reg, u32 val); +extern void outsw(u32 reg, const void *addr, unsigned long count); +#endif +#endif + +#if defined(CONFIG_QEMU) +#define FW_CFG_ARCH_WIDTH (FW_CFG_ARCH_LOCAL + 0x00) +#define FW_CFG_ARCH_HEIGHT (FW_CFG_ARCH_LOCAL + 0x01) +#define FW_CFG_ARCH_DEPTH (FW_CFG_ARCH_LOCAL + 0x02) +#endif + +#endif /* _ASM_IO_H */ diff --git a/qemu/roms/openbios/include/arch/sparc64/ofmem_sparc64.h b/qemu/roms/openbios/include/arch/sparc64/ofmem_sparc64.h new file mode 100644 index 000000000..7ff24ae3d --- /dev/null +++ b/qemu/roms/openbios/include/arch/sparc64/ofmem_sparc64.h @@ -0,0 +1,50 @@ +/* + * <ofmem_sparc64.h> + * + * OF Memory manager + * + * Copyright (C) 1999, 2002 Samuel Rydh (samuel@ibrium.se) + * + * 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 + * + */ + +#ifndef _H_OFMEM_SPARC64 +#define _H_OFMEM_SPARC64 + +#include "libopenbios/ofmem.h" + +#define PAGE_SIZE_4M (4 * 1024 * 1024) +#define PAGE_SIZE_512K (512 * 1024) +#define PAGE_SIZE_64K (64 * 1024) +#define PAGE_SIZE_8K (8 * 1024) +#define PAGE_MASK_4M (4 * 1024 * 1024 - 1) +#define PAGE_MASK_512K (512 * 1024 - 1) +#define PAGE_MASK_64K (64 * 1024 - 1) +#define PAGE_MASK_8K (8 * 1024 - 1) + +extern ucell *va2ttedata; +extern unsigned long find_tte(unsigned long va); + +void itlb_load2(unsigned long vaddr, unsigned long tte_data); +void itlb_load3(unsigned long vaddr, unsigned long tte_data, unsigned long tte_index); +unsigned long itlb_faultva(void); +void itlb_demap(unsigned long vaddr); +void dtlb_load2(unsigned long vaddr, unsigned long tte_data); +void dtlb_load3(unsigned long vaddr, unsigned long tte_data, unsigned long tte_index); +unsigned long dtlb_faultva(void); +void dtlb_demap(unsigned long vaddr); + +typedef int (*translation_entry_cb)(ucell phys, ucell virt, ucell size, ucell mode); + +extern void ofmem_walk_boot_map(translation_entry_cb cb); + +extern translation_t **g_ofmem_translations; + +extern void dtlb_miss_handler(void); +extern void itlb_miss_handler(void); +extern void bug(void); + +#endif /* _H_OFMEM_SPARC64 */ diff --git a/qemu/roms/openbios/include/arch/sparc64/pci.h b/qemu/roms/openbios/include/arch/sparc64/pci.h new file mode 100644 index 000000000..c7509afe5 --- /dev/null +++ b/qemu/roms/openbios/include/arch/sparc64/pci.h @@ -0,0 +1,67 @@ +#ifndef SPARC64_PCI_H +#define SPARC64_PCI_H + +#include "asm/io.h" + +#if !(defined(PCI_CONFIG_1) || defined(PCI_CONFIG_2)) +#define PCI_CONFIG_1 1 /* default */ +#endif + +#ifdef PCI_CONFIG_1 + +/* PCI Configuration Mechanism #1 */ + +#define PCI_ADDR(bus, dev, fn) \ + (((pci_addr) (uint32_t) (bus) << 16 \ + | (uint32_t) (dev) << 11 \ + | (uint32_t) (fn) << 8)) + +#define PCI_BUS(pcidev) ((uint8_t) ((pcidev) >> 16) & 0xff) +#define PCI_DEV(pcidev) ((uint8_t) ((pcidev) >> 11) & 0x1f) +#define PCI_FN(pcidev) ((uint8_t) ((pcidev) >> 8) & 7) + +#define PCI_CONFIG(dev) (arch->cfg_addr \ + + (unsigned long)PCI_ADDR(PCI_BUS(dev), \ + PCI_DEV(dev), \ + PCI_FN(dev))) + +static inline uint8_t pci_config_read8(pci_addr dev, uint8_t reg) +{ + uint8_t res; + res = in_8((unsigned char*)(PCI_CONFIG(dev) + reg)); + return res; +} + +static inline uint16_t pci_config_read16(pci_addr dev, uint8_t reg) +{ + uint16_t res; + res = in_be16((uint16_t *)(PCI_CONFIG(dev) + reg)); + return res; +} + +static inline uint32_t pci_config_read32(pci_addr dev, uint8_t reg) +{ + uint32_t res; + res = in_be32((uint32_t *)(PCI_CONFIG(dev) + reg)); + return res; +} + +static inline void pci_config_write8(pci_addr dev, uint8_t reg, uint8_t val) +{ + out_8((unsigned char*)(PCI_CONFIG(dev) + reg), val); +} + +static inline void pci_config_write16(pci_addr dev, uint8_t reg, uint16_t val) +{ + out_be16((uint16_t *)(PCI_CONFIG(dev) + reg), val); +} + +static inline void pci_config_write32(pci_addr dev, uint8_t reg, uint32_t val) +{ + out_be32((uint32_t *)(PCI_CONFIG(dev) + reg), val); +} +#else /* !PCI_CONFIG_1 */ +#error PCI Configuration Mechanism is not specified or implemented +#endif + +#endif /* SPARC64_PCI_H */ diff --git a/qemu/roms/openbios/include/arch/sparc64/types.h b/qemu/roms/openbios/include/arch/sparc64/types.h new file mode 100644 index 000000000..a26fccb2c --- /dev/null +++ b/qemu/roms/openbios/include/arch/sparc64/types.h @@ -0,0 +1,102 @@ +/* tag: data types for forth engine + * + * Copyright (C) 2003-2005 Patrick Mauritz, Stefan Reinauer + * + * See the file "COPYING" for further information about + * the copyright and warranty status of this work. + */ + +#ifndef __TYPES_H +#define __TYPES_H + +#include "mconfig.h" + +#ifdef BOOTSTRAP +#include <inttypes.h> +#else +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned int uint32_t; +typedef unsigned long long uint64_t; +typedef unsigned long uintptr_t; + +typedef signed char int8_t; +typedef short int16_t; +typedef int int32_t; +typedef long long int64_t; +typedef long intptr_t; + +#define PRId32 "d" +#define PRIu32 "u" +#define PRIx32 "x" +#define PRIX32 "X" +#define PRId64 "lld" +#define PRIu64 "llu" +#define PRIx64 "llx" +#define PRIX64 "llX" +#endif + +/* endianess */ +#include "autoconf.h" + +/* physical address */ +typedef uint64_t phys_addr_t; + +#define FMT_plx "%016" PRIx64 + +/* cell based types */ +typedef int64_t cell; +typedef uint64_t ucell; + +#define FMT_cell "%" PRId64 +#define FMT_ucell "%" PRIu64 +#define FMT_ucellx "%016" PRIx64 +#define FMT_ucellX "%016" PRIX64 + +typedef int64_t prom_arg_t; +typedef uint64_t prom_uarg_t; + +#define PRIdPROMARG PRId64 +#define PRIuPROMARG PRIu64 +#define PRIxPROMARG PRIx64 +#define FMT_prom_arg "%" PRIdPROMARG +#define FMT_prom_uarg "%" PRIuPROMARG +#define FMT_prom_uargx "%016" PRIxPROMARG + +#define FMT_elf "%#llx" +#define FMT_sizet "%lx" +#define FMT_aout_ehdr "%x" + +#ifdef NEED_FAKE_INT128_T +typedef struct { + uint64_t hi; + uint64_t lo; +} blob_128_t; + +typedef blob_128_t dcell; +typedef blob_128_t ducell; +#else +typedef __int128_t dcell; +typedef __uint128_t ducell; +#endif + +#define bitspercell (sizeof(cell)<<3) +#define bitsperdcell (sizeof(dcell)<<3) + +#define BITS 64 + +#define PAGE_SHIFT 13 + +/* size named types */ + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned int u32; +typedef unsigned long long u64; + +typedef signed char s8; +typedef short s16; +typedef int s32; +typedef long long s64; + +#endif diff --git a/qemu/roms/openbios/include/arch/unix/plugin_pci.h b/qemu/roms/openbios/include/arch/unix/plugin_pci.h new file mode 100644 index 000000000..513db6337 --- /dev/null +++ b/qemu/roms/openbios/include/arch/unix/plugin_pci.h @@ -0,0 +1,25 @@ +/* tag: openbios pci plugin headers + * + * Copyright (C) 2003 Stefan Reinauer + * + * See the file "COPYING" for further information about + * the copyright and warranty status of this work. + */ + +#ifndef __PLUGINS_PCI_H +#define __PLUGINS_PCI_H + +typedef struct pci_dev pci_dev_t; + +struct pci_dev { + unsigned bus; + unsigned dev; + unsigned fn; + + u8 *config; + pci_dev_t *next; +}; + +int pci_register_device(unsigned bus, unsigned dev, unsigned fn, u8 *config); + +#endif diff --git a/qemu/roms/openbios/include/arch/unix/plugins.h b/qemu/roms/openbios/include/arch/unix/plugins.h new file mode 100644 index 000000000..305b3da9b --- /dev/null +++ b/qemu/roms/openbios/include/arch/unix/plugins.h @@ -0,0 +1,31 @@ + +#ifndef __PLUGINS_H +#define __PLUGINS_H + +#include "asm/types.h" + +struct io_ops { + u8 (*inb)(u32 reg); + u16 (*inw)(u32 reg); + u32 (*inl)(u32 reg); + void (*outb)(u32 reg, u8 val); + void (*outw)(u32 reg, u16 val); + void (*outl)(u32 reg, u32 val); +}; +typedef struct io_ops io_ops_t; + +extern unsigned char *plugindir; + +#define PLUGIN_DEPENDENCIES(x...) const char *plugin_deps[]={ x, NULL }; +#define PLUGIN_AUTHOR(author) const char *plugin_author=author; +#define PLUGIN_LICENSE(license) const char *plugin_license=license; +#define PLUGIN_DESCRIPTION(desc) const char *plugin_description=desc; + +int register_iorange(const char *name, io_ops_t *ops, + unsigned int rstart, unsigned int rend); +io_ops_t *find_iorange(u32 reg); + +int load_plugin(const char *plugin_name); +int is_loaded(const char *plugin_name); + +#endif diff --git a/qemu/roms/openbios/include/arch/x86/elf.h b/qemu/roms/openbios/include/arch/x86/elf.h new file mode 100644 index 000000000..86c672508 --- /dev/null +++ b/qemu/roms/openbios/include/arch/x86/elf.h @@ -0,0 +1,5 @@ +#define ARCH_ELF_CLASS ELFCLASS32 +#define ARCH_ELF_DATA ELFDATA2LSB +#define ARCH_ELF_MACHINE_OK(x) ((x)==EM_386 || (x)==EM_486) +typedef Elf32_Ehdr Elf_ehdr; +typedef Elf32_Phdr Elf_phdr; diff --git a/qemu/roms/openbios/include/arch/x86/io.h b/qemu/roms/openbios/include/arch/x86/io.h new file mode 100644 index 000000000..76fa4f23a --- /dev/null +++ b/qemu/roms/openbios/include/arch/x86/io.h @@ -0,0 +1,74 @@ +#ifndef _ASM_IO_H +#define _ASM_IO_H + +#include "asm/types.h" + +extern char _start, _end; +extern unsigned long virt_offset; + +#define phys_to_virt(phys) ((void *) ((unsigned long) (phys) - virt_offset)) +#define virt_to_phys(virt) ((unsigned long) (virt) + virt_offset) + +#ifndef BOOTSTRAP +#define __SLOW_DOWN_IO "outb %%al,$0x80;" +static inline void slow_down_io(void) +{ + __asm__ __volatile__( + __SLOW_DOWN_IO +#ifdef REALLY_SLOW_IO + __SLOW_DOWN_IO __SLOW_DOWN_IO __SLOW_DOWN_IO +#endif + : : ); +} + +#define BUILDIO(bwl,bw,type) \ +static inline void out##bwl(unsigned type value, int port) { \ + __asm__ __volatile__("out" #bwl " %" #bw "0, %w1" : : "a"(value), "Nd"(port)); \ +} \ +static inline unsigned type in##bwl(int port) { \ + unsigned type value; \ + __asm__ __volatile__("in" #bwl " %w1, %" #bw "0" : "=a"(value) : "Nd"(port)); \ + return value; \ +} \ +static inline void out##bwl##_p(unsigned type value, int port) { \ + out##bwl(value, port); \ + slow_down_io(); \ +} \ +static inline unsigned type in##bwl##_p(int port) { \ + unsigned type value = in##bwl(port); \ + slow_down_io(); \ + return value; \ +} \ +static inline void outs##bwl(int port, const void *addr, unsigned long count) { \ + __asm__ __volatile__("rep; outs" #bwl : "+S"(addr), "+c"(count) : "d"(port)); \ +} \ +static inline void ins##bwl(int port, void *addr, unsigned long count) { \ + __asm__ __volatile__("rep; ins" #bwl : "+D"(addr), "+c"(count) : "d"(port)); \ +} + +#ifndef BOOTSTRAP +BUILDIO(b,b,char) +BUILDIO(w,w,short) +BUILDIO(l,,int) +#endif + +#else /* BOOTSTRAP */ +#ifdef FCOMPILER +#define inb(reg) ((u8)0xff) +#define inw(reg) ((u16)0xffff) +#define inl(reg) ((u32)0xffffffff) +#define outb(reg, val) do{} while(0) +#define outw(reg, val) do{} while(0) +#define outl(reg, val) do{} while(0) +#else +extern u8 inb(u32 reg); +extern u16 inw(u32 reg); +extern u32 inl(u32 reg); +extern void insw(u32 reg, void *addr, unsigned long count); +extern void outb(u32 reg, u8 val); +extern void outw(u32 reg, u16 val); +extern void outl(u32 reg, u32 val); +extern void outsw(u32 reg, const void *addr, unsigned long count); +#endif +#endif +#endif diff --git a/qemu/roms/openbios/include/arch/x86/pci.h b/qemu/roms/openbios/include/arch/x86/pci.h new file mode 100644 index 000000000..49247d97c --- /dev/null +++ b/qemu/roms/openbios/include/arch/x86/pci.h @@ -0,0 +1,66 @@ +#ifndef i386_PCI_H +#define i386_PCI_H + +#include "asm/io.h" + +#if !(defined(PCI_CONFIG_1) || defined(PCI_CONFIG_2)) +#define PCI_CONFIG_1 1 /* default */ +#endif + +#ifdef PCI_CONFIG_1 + +/* PCI Configuration Mechanism #1 */ + +/* Have pci_addr in the same format as the values written to 0xcf8 + * so register accesses can be made easy. */ +#define PCI_ADDR(bus, dev, fn) \ + ((pci_addr) (0x80000000u \ + | (uint32_t) (bus) << 16 \ + | (uint32_t) (dev) << 11 \ + | (uint32_t) (fn) << 8)) + +#define PCI_BUS(pcidev) ((uint8_t) ((pcidev) >> 16)) +#define PCI_DEV(pcidev) ((uint8_t) ((pcidev) >> 11) & 0x1f) +#define PCI_FN(pcidev) ((uint8_t) ((pcidev) >> 8) & 7) + +static inline uint8_t pci_config_read8(pci_addr dev, uint8_t reg) +{ + outl(dev | (reg & ~3), 0xcf8); + return inb(0xcfc | (reg & 3)); +} + +static inline uint16_t pci_config_read16(pci_addr dev, uint8_t reg) +{ + outl(dev | (reg & ~3), 0xcf8); + return inw(0xcfc | (reg & 2)); +} + +static inline uint32_t pci_config_read32(pci_addr dev, uint8_t reg) +{ + outl(dev | reg, 0xcf8); + return inl(0xcfc | reg); +} + +static inline void pci_config_write8(pci_addr dev, uint8_t reg, uint8_t val) +{ + outl(dev | (reg & ~3), 0xcf8); + outb(val, 0xcfc | (reg & 3)); +} + +static inline void pci_config_write16(pci_addr dev, uint8_t reg, uint16_t val) +{ + outl(dev | (reg & ~3), 0xcf8); + outw(val, 0xcfc | (reg & 2)); +} + +static inline void pci_config_write32(pci_addr dev, uint8_t reg, uint32_t val) +{ + outl(dev | reg, 0xcf8); + outl(val, 0xcfc); +} + +#else /* !PCI_CONFIG_1 */ +#error PCI Configuration Mechanism is not specified or implemented +#endif + +#endif /* i386_PCI_H */ diff --git a/qemu/roms/openbios/include/arch/x86/types.h b/qemu/roms/openbios/include/arch/x86/types.h new file mode 100644 index 000000000..d7261f2a9 --- /dev/null +++ b/qemu/roms/openbios/include/arch/x86/types.h @@ -0,0 +1,69 @@ +/* tag: data types for forth engine + * + * This file is autogenerated by types.sh. Do not edit! + * + * Copyright (C) 2003-2005 Stefan Reinauer, Patrick Mauritz + * + * See the file "COPYING" for further information about + * the copyright and warranty status of this work. + */ + +#ifndef __TYPES_H +#define __TYPES_H + +#include <inttypes.h> + +/* endianess */ + +#include "autoconf.h" + +/* physical address: XXX theoretically 36 bits for PAE */ + +typedef uint32_t phys_addr_t; + +#define FMT_plx "%08" PRIx32 + +/* cell based types */ + +typedef int32_t cell; +typedef uint32_t ucell; +typedef int64_t dcell; +typedef uint64_t ducell; + +#define FMT_cell "%" PRId32 +#define FMT_ucell "%" PRIu32 +#define FMT_ucellx "%08" PRIx32 +#define FMT_ucellX "%08" PRIX32 + +typedef int32_t prom_arg_t; +typedef uint32_t prom_uarg_t; + +#define PRIdPROMARG PRId32 +#define PRIuPROMARG PRIu32 +#define PRIxPROMARG PRIx32 +#define FMT_prom_arg "%" PRIdPROMARG +#define FMT_prom_uarg "%" PRIuPROMARG +#define FMT_prom_uargx "%08" PRIxPROMARG + +#define FMT_elf "%#x" + +#define bitspercell (sizeof(cell)<<3) +#define bitsperdcell (sizeof(dcell)<<3) + +#define BITS 32 + +#define PAGE_SHIFT 12 + +/* size named types */ + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned int u32; +typedef unsigned long long u64; + +typedef char s8; +typedef short s16; +typedef int s32; +typedef long long s64; + +#endif diff --git a/qemu/roms/openbios/include/config.h b/qemu/roms/openbios/include/config.h new file mode 100644 index 000000000..d5a1e200a --- /dev/null +++ b/qemu/roms/openbios/include/config.h @@ -0,0 +1,68 @@ +/* + * Creation Date: <2003/12/20 00:07:16 samuel> + * Time-stamp: <2004/01/19 17:40:26 stepan> + * + * <config.h> + * + * + * + * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#ifndef _H_CONFIG +#define _H_CONFIG + +#include "autoconf.h" +#include "mconfig.h" +#include "asm/types.h" + +#define PROGRAM_NAME "OpenBIOS" + +#ifndef BOOTSTRAP + +#ifndef NULL +#define NULL ((void*)0) +#endif + +typedef unsigned int size_t; +typedef unsigned int usize_t; +typedef signed int ssize_t; +typedef signed int off_t; + +typedef unsigned int time_t; + +#define UINT_MAX ((unsigned int)-1) + +#define ENOMEM 1 +#define EIO 2 +#define EINVAL 3 +#define ENOENT 4 +#define ENOTDIR 5 +#define EISDIR 6 +#define ENAMETOOLONG 7 + +#define SEEK_CUR 1 +#define SEEK_SET 2 +#define SEEK_END 3 + +#endif /* BOOTSTRAP */ + +#include "sysinclude.h" + +#ifndef MIN +#define MIN(x,y) (((x) < (y)) ? (x) : (y)) +#define MAX(x,y) (((x) > (y)) ? (x) : (y)) +#endif + +/* errno is a macro on some systems, which might cause nasty problems. + * We try to cope with this here. + */ +#undef errno +#define errno errno_int + +#endif /* _H_CONFIG */ diff --git a/qemu/roms/openbios/include/drivers/drivers.h b/qemu/roms/openbios/include/drivers/drivers.h new file mode 100644 index 000000000..3b83b12d1 --- /dev/null +++ b/qemu/roms/openbios/include/drivers/drivers.h @@ -0,0 +1,132 @@ +/* + * OpenBIOS driver prototypes + * + * (C) 2004 Stefan Reinauer <stepan@openbios.org> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ +#ifndef OPENBIOS_DRIVERS_H +#define OPENBIOS_DRIVERS_H + +#include "config.h" + +#ifdef CONFIG_DRIVER_PCI +/* drivers/pci.c */ +int ob_pci_init(void); +#endif + +#if defined(CONFIG_DRIVER_PCI) || defined(CONFIG_DRIVER_ESCC) +#ifdef CONFIG_PPC +extern int is_apple(void); +extern int is_oldworld(void); +extern int is_newworld(void); +#else +static inline int is_apple(void) +{ + return 0; +} +static inline int is_oldworld(void) +{ + return 0; +} +static inline int is_newworld(void) +{ + return 0; +} +#endif +#define AAPL(_cmd) do { if (is_apple()) _cmd; } while(0) +#define OLDWORLD(_cmd) do { if (is_oldworld()) _cmd; } while(0) +#define NEWWORLD(_cmd) do { if (is_newworld()) _cmd; } while(0) +#endif +#ifdef CONFIG_DRIVER_SBUS +/* drivers/sbus.c */ +int ob_sbus_init(uint64_t base, int machine_id); + +/* arch/sparc32/console.c */ +void kbd_init(uint64_t base); +#endif +#ifdef CONFIG_DRIVER_IDE +/* drivers/ide.c */ +int ob_ide_init(const char *path, uint32_t io_port0, uint32_t ctl_port0, + uint32_t io_port1, uint32_t ctl_port1); +int macio_ide_init(const char *path, uint32_t addr, int nb_channels); +#endif +#ifdef CONFIG_DRIVER_ESP +/* drivers/esp.c */ +int ob_esp_init(unsigned int slot, uint64_t base, unsigned long espoffset, + unsigned long dmaoffset); +#endif +#ifdef CONFIG_DRIVER_OBIO +/* drivers/obio.c */ +int ob_obio_init(uint64_t slavio_base, unsigned long fd_offset, + unsigned long counter_offset, unsigned long intr_offset, + int intr_ncpu, unsigned long aux1_offset, unsigned long aux2_offset, + unsigned long mem_size); +int start_cpu(unsigned int pc, unsigned int context_ptr, unsigned int context, + int cpu); +void ob_eccmemctl_init(uint64_t base); +void ss5_init(uint64_t base); + +/* drivers/iommu.c */ +void ob_init_iommu(uint64_t base); +void *dvma_alloc(int size, unsigned int *pphys); + +/* drivers/sbus.c */ +extern uint16_t graphic_depth; + +/* drivers/obio.c */ +extern volatile unsigned char *power_reg; +extern volatile unsigned int *reset_reg; +extern volatile struct sun4m_timer_regs *counter_regs; + +void ob_new_obio_device(const char *name, const char *type); +unsigned long ob_reg(uint64_t base, uint64_t offset, unsigned long size, int map); +void ob_intr(int intr); + +/* arch/sparc32/boot.c */ +extern uint32_t kernel_image; +extern uint32_t kernel_size; +extern uint32_t qemu_cmdline; +extern uint32_t cmdline_size; +extern char boot_device; +#endif +#ifdef CONFIG_DRIVER_FLOPPY +int ob_floppy_init(const char *path, const char *dev_name, + unsigned long io_base, unsigned long mmio_base); +#endif +#ifdef CONFIG_DRIVER_PC_KBD +void ob_pc_kbd_init(const char *path, const char *dev_name, uint64_t base, + uint64_t offset, int intr); +int pc_kbd_dataready(void); +unsigned char pc_kbd_readdata(void); +#endif +#ifdef CONFIG_DRIVER_PC_SERIAL +void ob_pc_serial_init(const char *path, const char *dev_name, uint64_t base, + uint64_t offset, int intr); +int uart_init(int port, unsigned long speed); +int uart_charav(int port); +char uart_getchar(int port); +void uart_putchar(int c); +#endif +#ifdef CONFIG_DRIVER_ESCC +int escc_uart_init(phys_addr_t port, unsigned long speed); +int escc_uart_charav(uintptr_t port); +char escc_uart_getchar(uintptr_t port); +void escc_uart_putchar(int c); +void serial_cls(void); +#ifdef CONFIG_DRIVER_ESCC_SUN +int keyboard_dataready(void); +unsigned char keyboard_readdata(void); +#endif +#endif +int macio_get_nvram_size(void); +void macio_nvram_put(char *buf); +void macio_nvram_get(char *buf); + +/* drivers/timer.c */ +void setup_timers(void); + +#endif /* OPENBIOS_DRIVERS_H */ diff --git a/qemu/roms/openbios/include/drivers/pci.h b/qemu/roms/openbios/include/drivers/pci.h new file mode 100644 index 000000000..2eb5685d3 --- /dev/null +++ b/qemu/roms/openbios/include/drivers/pci.h @@ -0,0 +1,217 @@ +#ifndef _H_PCI +#define _H_PCI + +typedef uint32_t pci_addr; + +typedef struct pci_arch_t pci_arch_t; + +struct pci_arch_t { + const char * name; + uint16_t vendor_id; + uint16_t device_id; + unsigned long cfg_addr; + unsigned long cfg_data; + unsigned long cfg_base; + unsigned long cfg_len; + unsigned long host_pci_base; /* offset of PCI memory space within host memory space */ + unsigned long pci_mem_base; /* in PCI memory space */ + unsigned long mem_len; + unsigned long io_base; + unsigned long io_len; + unsigned long rbase; + unsigned long rlen; + uint8_t irqs[4]; +}; + +extern const pci_arch_t *arch; + +/* Device tree offsets */ + +#define PCI_INT_MAP_PCI0 0 +#define PCI_INT_MAP_PCI1 1 +#define PCI_INT_MAP_PCI2 2 +#define PCI_INT_MAP_PCI_INT 3 +#define PCI_INT_MAP_PIC_HANDLE 4 +#define PCI_INT_MAP_PIC_INT 5 +#define PCI_INT_MAP_PIC_POL 6 + +/* Device classes and subclasses */ + +#define PCI_BASE_CLASS_STORAGE 0x01 +#define PCI_SUBCLASS_STORAGE_SCSI 0x00 +#define PCI_SUBCLASS_STORAGE_IDE 0x01 +#define PCI_SUBCLASS_STORAGE_FLOPPY 0x02 +#define PCI_SUBCLASS_STORAGE_IPI 0x03 +#define PCI_SUBCLASS_STORAGE_RAID 0x04 +#define PCI_SUBCLASS_STORAGE_ATA 0x05 +#define PCI_SUBCLASS_STORAGE_SAS 0x07 +#define PCI_SUBCLASS_STORAGE_OTHER 0x80 + +#define PCI_BASE_CLASS_NETWORK 0x02 +#define PCI_SUBCLASS_NETWORK_ETHERNET 0x00 +#define PCI_SUBCLASS_NETWORK_TOKEN_RING 0x01 +#define PCI_SUBCLASS_NETWORK_FDDI 0x02 +#define PCI_SUBCLASS_NETWORK_ATM 0x03 +#define PCI_SUBCLASS_NETWORK_ISDN 0x04 +#define PCI_SUBCLASS_NETWORK_WORDFIP 0x05 +#define PCI_SUBCLASS_NETWORK_PICMG214 0x06 +#define PCI_SUBCLASS_NETWORK_OTHER 0x80 + +#define PCI_BASE_CLASS_DISPLAY 0x03 +#define PCI_SUBCLASS_DISPLAY_VGA 0x00 +#define PCI_SUBCLASS_DISPLAY_XGA 0x01 +#define PCI_SUBCLASS_DISPLAY_3D 0x02 +#define PCI_SUBCLASS_DISPLAY_OTHER 0x80 + +#define PCI_BASE_CLASS_MULTIMEDIA 0x04 +#define PCI_SUBCLASS_MULTIMEDIA_VIDEO 0x00 +#define PCI_SUBCLASS_MULTIMEDIA_AUDIO 0x01 +#define PCI_SUBCLASS_MULTIMEDIA_PHONE 0x02 +#define PCI_SUBCLASS_MULTIMEDIA_OTHER 0x80 + +#define PCI_BASE_CLASS_MEMORY 0x05 +#define PCI_SUBCLASS_MEMORY_RAM 0x00 +#define PCI_SUBCLASS_MEMORY_FLASH 0x01 + +#define PCI_BASE_CLASS_BRIDGE 0x06 +#define PCI_SUBCLASS_BRIDGE_HOST 0x00 +#define PCI_SUBCLASS_BRIDGE_ISA 0x01 +#define PCI_SUBCLASS_BRIDGE_EISA 0x02 +#define PCI_SUBCLASS_BRIDGE_MC 0x03 +#define PCI_SUBCLASS_BRIDGE_PCI 0x04 +#define PCI_SUBCLASS_BRIDGE_PCMCIA 0x05 +#define PCI_SUBCLASS_BRIDGE_NUBUS 0x06 +#define PCI_SUBCLASS_BRIDGE_CARDBUS 0x07 +#define PCI_SUBCLASS_BRIDGE_RACEWAY 0x08 +#define PCI_SUBCLASS_BRIDGE_PCI_SEMITP 0x09 +#define PCI_SUBCLASS_BRIDGE_IB_PCI 0x0a +#define PCI_SUBCLASS_BRIDGE_OTHER 0x80 + +#define PCI_BASE_CLASS_COMMUNICATION 0x07 +#define PCI_SUBCLASS_COMMUNICATION_SERIAL 0x00 +#define PCI_SUBCLASS_COMMUNICATION_PARALLEL 0x01 +#define PCI_SUBCLASS_COMMUNICATION_MULTISERIAL 0x02 +#define PCI_SUBCLASS_COMMUNICATION_MODEM 0x03 +#define PCI_SUBCLASS_COMMUNICATION_GPIB 0x04 +#define PCI_SUBCLASS_COMMUNICATION_SC 0x05 +#define PCI_SUBCLASS_COMMUNICATION_OTHER 0x80 + +#define PCI_BASE_CLASS_SYSTEM 0x08 +#define PCI_SUBCLASS_SYSTEM_PIC 0x00 +#define PCI_SUBCLASS_SYSTEM_DMA 0x01 +#define PCI_SUBCLASS_SYSTEM_TIMER 0x02 +#define PCI_SUBCLASS_SYSTEM_RTC 0x03 +#define PCI_SUBCLASS_SYSTEM_PCI_HOTPLUG 0x04 +#define PCI_SUBCLASS_SYSTEM_OTHER 0x80 + +#define PCI_BASE_CLASS_INPUT 0x09 +#define PCI_SUBCLASS_INPUT_KEYBOARD 0x00 +#define PCI_SUBCLASS_INPUT_PEN 0x01 +#define PCI_SUBCLASS_INPUT_MOUSE 0x02 +#define PCI_SUBCLASS_INPUT_SCANNER 0x03 +#define PCI_SUBCLASS_INPUT_GAMEPORT 0x04 +#define PCI_SUBCLASS_INPUT_OTHER 0x80 + +#define PCI_BASE_CLASS_DOCKING 0x0a +#define PCI_SUBCLASS_DOCKING_GENERIC 0x00 +#define PCI_SUBCLASS_DOCKING_OTHER 0x80 + +#define PCI_BASE_CLASS_PROCESSOR 0x0b +#define PCI_SUBCLASS_PROCESSOR_386 0x00 +#define PCI_SUBCLASS_PROCESSOR_486 0x01 +#define PCI_SUBCLASS_PROCESSOR_PENTIUM 0x02 +#define PCI_SUBCLASS_PROCESSOR_ALPHA 0x10 +#define PCI_SUBCLASS_PROCESSOR_POWERPC 0x20 +#define PCI_SUBCLASS_PROCESSOR_MIPS 0x30 +#define PCI_SUBCLASS_PROCESSOR_CO 0x40 + +#define PCI_BASE_CLASS_SERIAL 0x0c +#define PCI_SUBCLASS_SERIAL_FIREWIRE 0x00 +#define PCI_SUBCLASS_SERIAL_ACCESS 0x01 +#define PCI_SUBCLASS_SERIAL_SSA 0x02 +#define PCI_SUBCLASS_SERIAL_USB 0x03 +#define PCI_SUBCLASS_SERIAL_FIBER 0x04 +#define PCI_SUBCLASS_SERIAL_SMBUS 0x05 +#define PCI_SUBCLASS_SERIAL_IB 0x06 +#define PCI_SUBCLASS_SERIAL_IPMI 0x07 +#define PCI_SUBCLASS_SERIAL_SERCOS 0x08 +#define PCI_SUBCLASS_SERIAL_CANBUS 0x09 + +#define PCI_BASE_CLASS_WIRELESS 0x0d +#define PCI_SUBCLASS_WIRELESS_IRDA 0x00 +#define PCI_SUBCLASS_WIRELESS_CIR 0x01 +#define PCI_SUBCLASS_WIRELESS_RF_CONTROLLER 0x10 +#define PCI_SUBCLASS_WIRELESS_BLUETOOTH 0x11 +#define PCI_SUBCLASS_WIRELESS_BROADBAND 0x12 +#define PCI_SUBCLASS_WIRELESS_OTHER 0x80 + +#define PCI_BASE_CLASS_SATELLITE 0x0f +#define PCI_SUBCLASS_SATELLITE_TV 0x00 +#define PCI_SUBCLASS_SATELLITE_AUDIO 0x01 +#define PCI_SUBCLASS_SATELLITE_VOICE 0x03 +#define PCI_SUBCLASS_SATELLITE_DATA 0x04 + +#define PCI_BASE_CLASS_CRYPT 0x10 +#define PCI_SUBCLASS_CRYPT_NETWORK 0x00 +#define PCI_SUBCLASS_CRYPT_ENTERTAINMENT 0x01 +#define PCI_SUBCLASS_CRYPT_OTHER 0x80 + +#define PCI_BASE_CLASS_SIGNAL_PROCESSING 0x11 +#define PCI_SUBCLASS_SP_DPIO 0x00 +#define PCI_SUBCLASS_SP_PERF 0x01 +#define PCI_SUBCLASS_SP_SYNCH 0x10 +#define PCI_SUBCLASS_SP_MANAGEMENT 0x20 +#define PCI_SUBCLASS_SP_OTHER 0x80 + +#define PCI_CLASS_OTHERS 0xff + +/* Vendors and devices. */ + +#define PCI_VENDOR_ID_ATI 0x1002 +#define PCI_DEVICE_ID_ATI_RAGE128_PF 0x5046 + +#define PCI_VENDOR_ID_DEC 0x1011 +#define PCI_DEVICE_ID_DEC_21154 0x0026 + +#define PCI_VENDOR_ID_IBM 0x1014 +#define PCI_DEVICE_ID_IBM_OPENPIC 0x0002 +#define PCI_DEVICE_ID_IBM_OPENPIC2 0xffff + +#define PCI_VENDOR_ID_MOTOROLA 0x1057 +#define PCI_DEVICE_ID_MOTOROLA_MPC106 0x0002 +#define PCI_DEVICE_ID_MOTOROLA_RAVEN 0x4801 + +#define PCI_VENDOR_ID_APPLE 0x106b +#define PCI_DEVICE_ID_APPLE_343S1201 0x0010 +#define PCI_DEVICE_ID_APPLE_343S1211 0x0017 +#define PCI_DEVICE_ID_APPLE_UNI_N_I_PCI 0x001e +#define PCI_DEVICE_ID_APPLE_UNI_N_PCI 0x001f +#define PCI_DEVICE_ID_APPLE_UNI_N_AGP 0x0020 +#define PCI_DEVICE_ID_APPLE_UNI_N_KEYL 0x0022 +#define PCI_DEVICE_ID_APPLE_KEYL_USB 0x003f +#define PCI_DEVICE_ID_APPLE_U3_AGP 0x004b + +#define PCI_VENDOR_ID_SUN 0x108e +#define PCI_DEVICE_ID_SUN_EBUS 0x1000 +#define PCI_DEVICE_ID_SUN_SIMBA 0x5000 +#define PCI_DEVICE_ID_SUN_PBM 0x8000 +#define PCI_DEVICE_ID_SUN_SABRE 0xa000 + +#define PCI_VENDOR_ID_CMD 0x1095 +#define PCI_DEVICE_ID_CMD_646 0x0646 + +#define PCI_VENDOR_ID_REALTEK 0x10ec +#define PCI_DEVICE_ID_REALTEK_RTL8029 0x8029 + +#define PCI_VENDOR_ID_QEMU 0x1234 +#define PCI_DEVICE_ID_QEMU_VGA 0x1111 + +#define PCI_VENDOR_ID_REDHAT_QUMRANET 0x1af4 +#define PCI_DEVICE_ID_VIRTIO_NET 0x1000 +#define PCI_DEVICE_ID_VIRTIO_BLOCK 0x1001 + +#define PCI_VENDOR_ID_INTEL 0x8086 +#define PCI_DEVICE_ID_INTEL_82378 0x0484 +#define PCI_DEVICE_ID_INTEL_82441 0x1237 + +#endif /* _H_PCI */ diff --git a/qemu/roms/openbios/include/drivers/usb.h b/qemu/roms/openbios/include/drivers/usb.h new file mode 100644 index 000000000..143ed27bc --- /dev/null +++ b/qemu/roms/openbios/include/drivers/usb.h @@ -0,0 +1,8 @@ +#ifndef USB_H +#define USB_H + +int ob_usb_ohci_init(const char *path, uint32_t addr); +void ob_usb_hid_add_keyboard(const char *path); +int usb_exit(void); + +#endif /* USB_H */ diff --git a/qemu/roms/openbios/include/drivers/vga.h b/qemu/roms/openbios/include/drivers/vga.h new file mode 100644 index 000000000..a4951f870 --- /dev/null +++ b/qemu/roms/openbios/include/drivers/vga.h @@ -0,0 +1,20 @@ +#ifndef VIDEO_VGA_H +#define VIDEO_VGA_H + +/* drivers/vga_load_regs.c */ +void vga_load_regs(void); + +/* drivers/vga_set_mode.c */ +void vga_set_gmode (void); +void vga_set_amode (void); +void vga_font_load(unsigned char *vidmem, const unsigned char *font, int height, int num_chars); + +/* drivers/vga_vbe.c */ +void vga_set_color(int i, unsigned int r, unsigned int g, unsigned int b); +void vga_vbe_set_mode(int width, int height, int depth); +void vga_vbe_init(const char *path, unsigned long fb, uint32_t fb_size, + unsigned long rom, uint32_t rom_size); + +extern volatile uint32_t *dac; + +#endif /* VIDEO_VGA_H */ diff --git a/qemu/roms/openbios/include/fs/fs.h b/qemu/roms/openbios/include/fs/fs.h new file mode 100644 index 000000000..0a22fa278 --- /dev/null +++ b/qemu/roms/openbios/include/fs/fs.h @@ -0,0 +1,100 @@ +/* + * Creation Date: <2001/05/06 17:12:45 samuel> + * Time-stamp: <2003/10/22 11:43:45 samuel> + * + * <fs_loader.h> + * + * Generic file system access + * + * Copyright (C) 2001, 2002, 2003 Samuel Rydh (samuel@ibrium.se) + * + * 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 + * + */ + +#ifndef _H_FS +#define _H_FS + + +typedef struct fs_ops fs_ops_t; +typedef struct opaque_struct file_desc_t; + +#define fs_open_path( fs, path ) (fs)->open_path( fs, path ) +#define fs_search_rom( fs ) (fs)->search_rom( fs ) +#define fs_search_file( fs, name ) (fs)->search_file( fs, name ) +#define fs_vol_name( fs, buf, size ) (fs)->vol_name( fs, buf, size ) + +struct fs_ops { + void *fs_data; + int fd; /* owner block device */ + int type; + + void (*close_fs)( fs_ops_t *fs ); + file_desc_t *(*open_path)( fs_ops_t *fs, const char *path ); + file_desc_t *(*search_rom)( fs_ops_t *fs ); + file_desc_t *(*search_file)( fs_ops_t *fs, const char *name ); + char *(*vol_name)( fs_ops_t *fs, char *buf, int size ); + + /* file ops */ + void (*close)( file_desc_t *file ); + int (*read)( file_desc_t *file, void *buf, size_t count ); + int (*lseek)( file_desc_t *file, off_t offset, int whence ); + char *(*get_path)( file_desc_t *file, char *buf, int len ); + void (*dir)( file_desc_t *file ); + + const char *(*get_fstype)( fs_ops_t *fs ); +}; + +extern fs_ops_t *fs_open( int fs_type, int fd ); +extern void fs_close( fs_ops_t *fs ); +const char *fs_get_name( fs_ops_t *fs ); + +#ifdef CONFIG_HFSP +extern int fs_hfsp_open( int fd, fs_ops_t *fs ); +extern int fs_hfsp_probe( int fd, long long offs ); +#else +static inline int fs_hfsp_open( int fd, fs_ops_t *fs ) { return -1; } +static inline int fs_hfsp_probe( int fd, long long offs ) { return -1; } +#endif + +#ifdef CONFIG_HFS +extern int fs_hfs_open( int fd, fs_ops_t *fs ); +extern int fs_hfs_probe( int fd, long long offs ); +#else +static inline int fs_hfs_open( int fd, fs_ops_t *fs ) { return -1; } +static inline int fs_hfs_probe( int fd, long long offs ) { return -1; } +#endif + +#ifdef CONFIG_ISO9660 +extern int fs_iso9660_open( int fd, fs_ops_t *fs ); +extern int fs_iso9660_probe( int fd, long long offs ); +#else +static inline int fs_iso9660_open( int fd, fs_ops_t *fs ) { return -1; } +static inline int fs_iso9660_probe( int fd, long long offs ) { return -1; } +#endif + +#ifdef CONFIG_EXT2 +extern int fs_ext2_open( int fd, fs_ops_t *fs ); +extern int fs_ext2_probe( int fd, long long offs ); +#else +static inline int fs_ext2_open( int fd, fs_ops_t *fs ) { return -1; } +static inline int fs_ext2_probe( int fd, long long offs ) { return -1; } +#endif + +#ifdef CONFIG_GRUBFS +extern int fs_grubfs_open( int fd, fs_ops_t *fs ); +extern int fs_grubfs_probe( int fd, long long offs ); +#else +static inline int fs_grubfs_open( int fd, fs_ops_t *fs ) { return -1; } +static inline int fs_grubfs_probe( int fd, long long offs ) { return -1; } +#endif + + + +/* misc */ +extern char *get_hfs_vol_name( int fd, char *buf, int size ); + + +#endif /* _H_FS */ diff --git a/qemu/roms/openbios/include/kernel/kernel.h b/qemu/roms/openbios/include/kernel/kernel.h new file mode 100644 index 000000000..c887e24b9 --- /dev/null +++ b/qemu/roms/openbios/include/kernel/kernel.h @@ -0,0 +1,58 @@ +/* + * Creation Date: <2003/12/19 00:20:11 samuel> + * Time-stamp: <2004/01/07 19:19:14 samuel> + * + * <kernel.h> + * + * + * + * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se) + * Stefan Reinauer (stepan@openbios.org) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#ifndef _H_KERNEL +#define _H_KERNEL + +#include "kernel/stack.h" +#include "asm/io.h" + +/* Interrupt status */ +#define FORTH_INTSTAT_CLR 0x0 +#define FORTH_INTSTAT_STOP 0x1 +#define FORTH_INTSTAT_DBG 0x2 + +extern volatile int interruptforth; +extern int enterforth( xt_t xt ); +extern void panic(const char *error) __attribute__ ((noreturn)); + +extern xt_t findword(const char *s1); +extern void modules_init( void ); +extern void init_trampoline(ucell *t); +extern void forth_init(void); + +/* arch kernel hooks */ +extern void exception(cell no); + +#ifdef FCOMPILER +extern void include_file( const char *str ); +extern void encode_file( const char *str ); +extern int get_inputbyte( void ); +extern void put_outputbyte( int c ); +#endif + +#ifndef BOOTSTRAP +#undef putchar +#undef getchar + +extern int putchar( int ch ); +extern int getchar( void ); +#endif + +extern int availchar( void ); + +#endif /* _H_KERNEL */ diff --git a/qemu/roms/openbios/include/kernel/stack.h b/qemu/roms/openbios/include/kernel/stack.h new file mode 100644 index 000000000..5edfc5cf3 --- /dev/null +++ b/qemu/roms/openbios/include/kernel/stack.h @@ -0,0 +1,117 @@ +/* stack.h + * tag: stack and stack access functions + * + * Copyright (C) 2003 Patrick Mauritz, Stefan Reinauer + * + * See the file "COPYING" for further information about + * the copyright and warranty status of this work. + */ + +#ifndef __STACK_H +#define __STACK_H + +#define dstacksize 512 +extern int dstackcnt; +extern cell dstack[dstacksize]; + +#define rstacksize 512 +extern int rstackcnt; +extern cell rstack[rstacksize]; + +extern int dbgrstackcnt; + +//typedef struct opaque_xt *xt_t; +//typedef struct opaque_ihandle *ihandle_t; +//typedef struct opaque_phandle *phandle_t; + +typedef ucell xt_t; +typedef ucell ihandle_t; +typedef ucell phandle_t; + + + +#ifdef NATIVE_BITWIDTH_EQUALS_HOST_BITWIDTH + +static inline ucell pointer2cell(const void* x) +{ + return (ucell)(uintptr_t)x; +} + +static inline void* cell2pointer(ucell x) +{ + return (void*)(uintptr_t)x; +} + +#endif + +static inline void PUSH(ucell value) { + dstack[++dstackcnt] = (value); +} +static inline void PUSH_xt( xt_t xt ) { PUSH( (ucell)xt ); } +static inline void PUSH_ih( ihandle_t ih ) { PUSH( (ucell)ih ); } +static inline void PUSH_ph( phandle_t ph ) { PUSH( (ucell)ph ); } + +static inline ucell POP(void) { + return (ucell) dstack[dstackcnt--]; +} +static inline xt_t POP_xt( void ) { return (xt_t)POP(); } +static inline ihandle_t POP_ih( void ) { return (ihandle_t)POP(); } +static inline phandle_t POP_ph( void ) { return (phandle_t)POP(); } + +static inline void DROP(void) { + dstackcnt--; +} + +static inline void DDROP(void) { + dstackcnt -= 2; +} + +static inline void DPUSH(ducell value) { +#ifdef NEED_FAKE_INT128_T + dstack[++dstackcnt] = (cell) value.lo; + dstack[++dstackcnt] = (cell) value.hi; +#else + dstack[++dstackcnt] = (cell) value; + dstack[++dstackcnt] = (cell) (value >> bitspercell); +#endif +} + +static inline ducell DPOP(void) { +#ifdef NEED_FAKE_INT128_T + ducell du; + du.hi = (ucell) dstack[dstackcnt--]; + du.lo = (ucell) dstack[dstackcnt--]; + return du; +#else + ducell du; + du = ((ducell)(ucell) dstack[dstackcnt--]) << bitspercell; + du |= (ucell) dstack[dstackcnt--]; + return du; +#endif +} + +static inline ucell GETTOS(void) { + return dstack[dstackcnt]; +} + +#define GETITEM(number) (dstack[dstackcnt - number]) +static inline void PUSHR(ucell value) { + rstack[++rstackcnt] = (value); +} + +static inline ucell POPR(void) { + return (ucell) rstack[rstackcnt--]; +} +static inline ucell GETTORS(void) { + return rstack[rstackcnt]; +} + + +#if defined(DEBUG_DSTACK) || defined(FCOMPILER) +void printdstack(void); +#endif +#if defined(DEBUG_RSTACK) || defined(FCOMPILER) +void printrstack(void); +#endif + +#endif diff --git a/qemu/roms/openbios/include/libc/byteorder.h b/qemu/roms/openbios/include/libc/byteorder.h new file mode 100644 index 000000000..4ac9562f4 --- /dev/null +++ b/qemu/roms/openbios/include/libc/byteorder.h @@ -0,0 +1,61 @@ +/* tag: byteorder prototypes + * + * Copyright (C) 2004 Stefan Reinauer + * + * see the file "COPYING" for further information about + * the copyright and warranty status of this work. + */ +#ifndef __BYTEORDER_H +#define __BYTEORDER_H + +#define __bswap32(x) \ + ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \ + (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24)) + +#define __bswap16(x) ((((x) & 0xff00) >> 8) | (((x) & 0x00ff) << 8)) + +#define __bswap64(x) ( (__bswap32( (x) >> 32)) | \ + (__bswap32((x) & 0xffffffff) << 32) ) + +#ifdef CONFIG_LITTLE_ENDIAN +#define __cpu_to_le64(x) ((u64) (x)) +#define __le64_to_cpu(x) ((u64) (x)) +#define __cpu_to_le32(x) ((u32) (x)) +#define __le32_to_cpu(x) ((u32) (x)) +#define __cpu_to_le16(x) ((u16) (x)) +#define __le16_to_cpu(x) ((u16) (x)) +#define __cpu_to_be64(x) (__bswap64((u64) (x))) +#define __be64_to_cpu(x) (__bswap64((u64) (x))) +#define __cpu_to_be32(x) (__bswap32((u32) (x))) +#define __be32_to_cpu(x) (__bswap32((u32) (x))) +#define __cpu_to_be16(x) (__bswap16((u16) (x))) +#define __be16_to_cpu(x) (__bswap16((u16) (x))) +#endif +#ifdef CONFIG_BIG_ENDIAN +#define __cpu_to_le64(x) (__bswap64((u64) (x))) +#define __le64_to_cpu(x) (__bswap64((u64) (x))) +#define __cpu_to_le32(x) (__bswap32((u32) (x))) +#define __le32_to_cpu(x) (__bswap32((u32) (x))) +#define __cpu_to_le16(x) (__bswap16((u16) (x))) +#define __le16_to_cpu(x) (__bswap16((u16) (x))) +#define __cpu_to_be64(x) ((u64) (x)) +#define __be64_to_cpu(x) ((u64) (x)) +#define __cpu_to_be32(x) ((u32) (x)) +#define __be32_to_cpu(x) ((u32) (x)) +#define __cpu_to_be16(x) ((u16) (x)) +#define __be16_to_cpu(x) ((u16) (x)) +#endif + +#if BITS==32 +#define __becell_to_cpu(x) (__be32_to_cpu(x)) +#define __lecell_to_cpu(x) (__le32_to_cpu(x)) +#define __cpu_to_becell(x) (__cpu_to_be32(x)) +#define __cpu_to_lecell(x) (__cpu_to_le32(x)) +#else +#define __becell_to_cpu(x) (__be64_to_cpu(x)) +#define __lecell_to_cpu(x) (__le64_to_cpu(x)) +#define __cpu_to_becell(x) (__cpu_to_be64(x)) +#define __cpu_to_lecell(x) (__cpu_to_le64(x)) +#endif + +#endif diff --git a/qemu/roms/openbios/include/libc/diskio.h b/qemu/roms/openbios/include/libc/diskio.h new file mode 100644 index 000000000..3a5abb658 --- /dev/null +++ b/qemu/roms/openbios/include/libc/diskio.h @@ -0,0 +1,33 @@ +/* + * Creation Date: <2003/12/20 00:57:01 samuel> + * Time-stamp: <2004/01/07 19:32:29 samuel> + * + * <diskio.h> + * + * + * + * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#ifndef _H_DISKIO +#define _H_DISKIO + +extern int open_ih( ihandle_t ih ); +extern int open_io( const char *spec ); +extern int close_io( int fd ); +extern int read_io( int fd, void *buf, size_t cnt ); +extern int seek_io( int fd, long long offs ); +extern long long tell( int fd ); +extern int reopen( int fd, const char *filename ); +extern int reopen_nwrom( int fd ); +extern ihandle_t get_ih_from_fd( int fd ); +const char *get_file_path( int fd ); +const char *get_fstype( int fd ); +const char *get_volume_name( int fd ); + +#endif /* _H_DISKIO */ diff --git a/qemu/roms/openbios/include/libc/stdlib.h b/qemu/roms/openbios/include/libc/stdlib.h new file mode 100644 index 000000000..ef08838d6 --- /dev/null +++ b/qemu/roms/openbios/include/libc/stdlib.h @@ -0,0 +1,26 @@ +/* + * Creation Date: <2003/12/19 18:52:20 samuel> + * Time-stamp: <2003/12/19 18:52:21 samuel> + * + * <stdlib.h> + * + * + * Copyright (C) 2003 Samuel Rydh (samuel@ibrium.se) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#ifndef _H_STDLIB +#define _H_STDLIB + +extern void *malloc( int size ); +extern void free( void *ptr ); +extern void *realloc( void *ptr, size_t size ); + +/* should perhaps go somewhere else... */ +extern void qsort( void *base, size_t nmemb, size_t size, int (*compar)(const void*, const void*)); + +#endif /* _H_STDLIB */ diff --git a/qemu/roms/openbios/include/libc/string.h b/qemu/roms/openbios/include/libc/string.h new file mode 100644 index 000000000..0e72f8d73 --- /dev/null +++ b/qemu/roms/openbios/include/libc/string.h @@ -0,0 +1,105 @@ +/* + * Creation Date: <2002/10/12 20:41:57 samuel> + * Time-stamp: <2003/10/25 12:51:22 samuel> + * + * <string.h> + * + * string library functions + * + * Copyright (C) 2002, 2003 Samuel Rydh (samuel@ibrium.se) + * + * 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 + * + */ + +#ifndef _H_STRING +#define _H_STRING + +#include "config.h" + +#define bzero(s,n) memset( s, 0, n ) +#define atol(nptr) strtol(nptr, NULL, 10 ) + +extern long strtol( const char *nptr, char **endptr, int base ); +extern long long int strtoll( const char *nptr, char **endptr, int base ); + + +extern int strnicmp(const char *s1, const char *s2, size_t len); +extern char *strcpy(char * dest,const char *src); +extern char *strncpy(char * dest,const char *src,size_t count); +extern char *strcat(char * dest, const char * src); +extern char *strncat(char *dest, const char *src, size_t count); +extern int strcmp(const char * cs,const char * ct); +extern int strncmp(const char * cs,const char * ct,size_t count); +extern char *strchr(const char * s, int c); +extern char *strrchr(const char * s, int c); +extern size_t strlen(const char * s); +extern size_t strnlen(const char * s, size_t count); +extern char *strpbrk(const char * cs,const char * ct); +extern char *strsep(char **s, const char *ct); +extern void *memset(void * s,int c,size_t count); +extern void *memcpy(void * dest,const void *src,size_t count); +extern void *memmove(void * dest,const void *src,size_t count); +extern int memcmp(const void * cs,const void * ct,size_t count); + +extern char *strdup( const char *str ); +extern int strcasecmp( const char *cs, const char *ct ); +extern int strncasecmp( const char *cs, const char *ct, size_t count ); + +extern char *strncpy_nopad( char *dest, const char *src, size_t n ); + +#define _U 0x01 /* upper */ +#define _L 0x02 /* lower */ +#define _D 0x04 /* digit */ +#define _C 0x08 /* cntrl */ +#define _P 0x10 /* punct */ +#define _S 0x20 /* white space (space/lf/tab) */ +#define _X 0x40 /* hex digit */ +#define _SP 0x80 /* hard space (0x20) */ + +extern const unsigned char _ctype[]; + +#define __ismask(x) (_ctype[(int)(unsigned char)(x)]) + +#define isalnum(c) ((__ismask(c)&(_U|_L|_D)) != 0) +#define isalpha(c) ((__ismask(c)&(_U|_L)) != 0) +#define iscntrl(c) ((__ismask(c)&(_C)) != 0) +#define isdigit(c) ((__ismask(c)&(_D)) != 0) +#define isgraph(c) ((__ismask(c)&(_P|_U|_L|_D)) != 0) +#define islower(c) ((__ismask(c)&(_L)) != 0) +#define isprint(c) ((__ismask(c)&(_P|_U|_L|_D|_SP)) != 0) +#define ispunct(c) ((__ismask(c)&(_P)) != 0) +#define isspace(c) ((__ismask(c)&(_S)) != 0) +#define isupper(c) ((__ismask(c)&(_U)) != 0) +#define isxdigit(c) ((__ismask(c)&(_D|_X)) != 0) + +#define isascii(c) (((unsigned char)(c))<=0x7f) +#define toascii(c) (((unsigned char)(c))&0x7f) + + +static inline unsigned char __tolower(unsigned char c) { + if (isupper(c)) + c -= 'A'-'a'; + return c; +} + +static inline unsigned char __toupper(unsigned char c) { + if (islower(c)) + c -= 'a'-'A'; + return c; +} + +#define tolower(c) __tolower(c) +#define toupper(c) __toupper(c) + +extern int errno_int; + +// Propolice support +extern long __guard[8]; + +void __stack_smash_handler(const char *func, int damaged); +void __stack_chk_fail(void); + +#endif /* _H_STRING */ diff --git a/qemu/roms/openbios/include/libc/vsprintf.h b/qemu/roms/openbios/include/libc/vsprintf.h new file mode 100644 index 000000000..4852274fc --- /dev/null +++ b/qemu/roms/openbios/include/libc/vsprintf.h @@ -0,0 +1,35 @@ +/* + * Creation Date: <2003/12/20 01:51:22 samuel> + * Time-stamp: <2004/01/07 19:02:17 samuel> + * + * <vsprintf.h> + * + * + * + * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#ifndef _H_VSPRINTF +#define _H_VSPRINTF + +#include <stdarg.h> +#include "config.h" + +int vsprintf(char *buf, const char *fmt, va_list args) + __attribute__((__format__(__printf__, 2, 0))); +int sprintf(char * buf, const char *fmt, ...) + __attribute__((__format__(__printf__, 2, 3))); +int vsnprintf(char *buf, size_t size, const char *fmt, va_list args) + __attribute__((__format__(__printf__, 3, 0))); +int snprintf(char * buf, size_t size, const char *fmt, ...) + __attribute__((__format__(__printf__, 3, 4))); + +int forth_printf(const char *fmt, ...) + __attribute__((__format__(__printf__, 1, 2))); + +#endif /* _H_VSPRINTF */ diff --git a/qemu/roms/openbios/include/libopenbios/aout_load.h b/qemu/roms/openbios/include/libopenbios/aout_load.h new file mode 100644 index 000000000..b462e1c86 --- /dev/null +++ b/qemu/roms/openbios/include/libopenbios/aout_load.h @@ -0,0 +1,27 @@ +/* + * Creation Date: <2010/03/22 18:00:00 mcayland> + * Time-stamp: <2010/03/22 18:00:00 mcayland> + * + * <aout_load.h> + * + * a.out loader + * + * Copyright (C) 2010 Mark Cave-Ayland (mark.cave-ayland@siriusit.co.uk) + * + * 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 + * + */ + +#ifndef _H_AOUTLOAD +#define _H_AOUTLOAD + +#include "arch/common/a.out.h" +#include "libopenbios/sys_info.h" + +extern int is_aout(struct exec *ehdr); +extern int aout_load(struct sys_info *info, ihandle_t dev); +extern void aout_init_program(void); + +#endif /* _H_AOUTLOAD */ diff --git a/qemu/roms/openbios/include/libopenbios/bindings.h b/qemu/roms/openbios/include/libopenbios/bindings.h new file mode 100644 index 000000000..de9c77520 --- /dev/null +++ b/qemu/roms/openbios/include/libopenbios/bindings.h @@ -0,0 +1,156 @@ +/* + * Creation Date: <2003/12/19 23:09:56 samuel> + * Time-stamp: <2004/01/07 19:36:42 samuel> + * + * <bindings.h> + * + * Forth bindings + * + * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#ifndef _H_BINDINGS +#define _H_BINDINGS + +#include "kernel/stack.h" +#include "kernel/kernel.h" + +#define PUSH3(a,b,c) do { PUSH((a)); PUSH((b)); PUSH((c)); } while(0) +#define PUSH2(a,b) do { PUSH((a)); PUSH((b)); } while(0) +#define RET( v ) do { PUSH(v); return; } while(0) + +/* initialization */ +extern int initialize_forth( void ); + +/* panic */ +extern int forth_segv_handler( char *segv_addr ); + +/* active package */ +extern phandle_t find_dev( const char *path ); +extern phandle_t get_cur_dev( void ); +extern phandle_t activate_device( const char *str ); +extern void device_end( void ); +extern void activate_dev( phandle_t ph ); + + +/* ihandle related */ +extern phandle_t ih_to_phandle( ihandle_t ih ); +extern ihandle_t my_parent( void ); +extern ihandle_t my_self( void ); +extern char *my_args_copy( void ); + +extern xt_t find_package_method( const char *meth, phandle_t ph ); +extern xt_t find_ih_method( const char *method, ihandle_t ih ); +extern xt_t find_parent_method( const char *method ); +extern void call_package( xt_t xt, ihandle_t ihandle ); +extern void call_parent( xt_t xt ); +extern void call_parent_method( const char *method ); + +/* package */ +extern ihandle_t open_package( const char *argstr, phandle_t ph ); +extern ihandle_t open_dev( const char *spec ); +extern void close_package( ihandle_t ih ); +extern void close_dev( ihandle_t ih ); + +/* property access */ +extern void set_property( phandle_t ph, const char *name, + const char *buf, int len ); +extern void set_int_property( phandle_t ph, const char *name, + u32 val ); +extern u32 get_int_property( phandle_t ph, const char *name, + int *retlen ); +extern char *get_property( phandle_t ph, const char *name, + int *retlen ); + +/* device tree iteration */ +extern phandle_t dt_iter_begin( void ); +extern phandle_t dt_iterate( phandle_t last_tree ); +extern phandle_t dt_iterate_type( phandle_t last_tree, + const char *type ); +static inline phandle_t dt_find_type( const char *type ) { + return dt_iterate_type( 0, type ); +} + +/* forth bindings */ +extern cell feval( const char *str ); +extern void bind_xtfunc( const char *name, xt_t xt, + ucell arg, void (*func)(void) ); +extern void bind_func( const char *name, void (*func)(void) ); +extern xt_t bind_noname_func( void (*func)(void) ); +extern void push_str( const char *str ); +extern char *pop_fstr_copy( void ); + +extern int _fword( const char *word, xt_t *cache_xt ); +extern cell _eword( const char *word, xt_t *cache_xt, int nargs ); +extern int _selfword( const char *method, xt_t *cache_xt ); +extern int _parword( const char *method, xt_t *cache_xt ); + +#define fword(w) ({ static xt_t cache_xt = 0; _fword(w, &cache_xt); }) +#define eword(w, nargs) ({ static xt_t cache_xt = 0; _eword(w, &cache_xt, nargs); }) +#define selfword(w) ({ static xt_t cache_xt = 0; _selfword(w, &cache_xt); }) +#define parword(w) ({ static xt_t cache_xt = 0; _parword(w, &cache_xt); }) + +extern void throw( int error ); + + +/* node bindings */ +extern void make_openable( int only_parents ); + + +typedef struct { + const char *name; + void *func; +} method_t; + +#define REGISTER_NAMED_NODE( name, path ) do { \ + bind_new_node( name##_flags_, name##_size_, \ + path, name##_m, sizeof(name##_m)/sizeof(method_t)); \ + } while(0) + +#define REGISTER_NAMED_NODE_PHANDLE( name, path, phandle ) do { \ + phandle = \ + bind_new_node( name##_flags_, name##_size_, \ + path, name##_m, sizeof(name##_m)/sizeof(method_t)); \ + } while(0) + +#define REGISTER_NODE_METHODS( name, path ) do { \ + const char *paths[1]; \ + \ + paths[0] = path; \ + bind_node( name##_flags_, name##_size_, \ + paths, 1, name##_m, sizeof(name##_m)/sizeof(method_t)); \ + } while(0) + +#define DECLARE_UNNAMED_NODE( name, flags, size ) \ +static const int name##_flags_ = flags; \ +static const int name##_size_ = size; + +#define DECLARE_NODE( name, flags, size, paths... ) \ +static const char * const name##_p[] = { paths }; \ +DECLARE_UNNAMED_NODE(name, flags, size) + +#define NODE_METHODS( name ) \ +static const method_t name##_m[] + +#define REGISTER_NODE( name ) do { \ + bind_node( name##_flags_, name##_size_, \ + name##_p, sizeof(name##_p)/sizeof(char*), \ + name##_m, sizeof(name##_m)/sizeof(method_t) ); \ + } while(0) + +extern void bind_node( int flags, int size, const char * const *paths, int npaths, + const method_t *methods, int nmethods ); + +extern phandle_t bind_new_node( int flags, int size, const char *name, + const method_t *methods, int nmethods ); + +#define INSTALL_OPEN 1 /* install trivial open and close methods */ + + + +#endif /* _H_BINDINGS */ diff --git a/qemu/roms/openbios/include/libopenbios/bootcode_load.h b/qemu/roms/openbios/include/libopenbios/bootcode_load.h new file mode 100644 index 000000000..147783ae0 --- /dev/null +++ b/qemu/roms/openbios/include/libopenbios/bootcode_load.h @@ -0,0 +1,22 @@ +/* + * Creation Date: <2010/03/22 18:00:00 mcayland> + * Time-stamp: <2010/03/22 18:00:00 mcayland> + * + * <bootcode_load.h> + * + * Raw bootcode (%BOOT) loader + * + * Copyright (C) 2013 Mark Cave-Ayland (mark.cave-ayland@ilande.co.uk) + * + * 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 + * + */ + +#ifndef _H_BOOTCODELOAD +#define _H_BOOTCODELOAD + +extern int bootcode_load(ihandle_t dev); + +#endif /* _H__H_BOOTCODELOAD */ diff --git a/qemu/roms/openbios/include/libopenbios/bootinfo_load.h b/qemu/roms/openbios/include/libopenbios/bootinfo_load.h new file mode 100644 index 000000000..1905a5e99 --- /dev/null +++ b/qemu/roms/openbios/include/libopenbios/bootinfo_load.h @@ -0,0 +1,26 @@ +/* + * Creation Date: <2010/03/22 18:00:00 mcayland> + * Time-stamp: <2010/03/22 18:00:00 mcayland> + * + * <bootinfo_load.h> + * + * CHRP boot info loader + * + * Copyright (C) 2010 Mark Cave-Ayland (mark.cave-ayland@siriusit.co.uk) + * + * 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 + * + */ + +#ifndef _H_BOOTINFOLOAD +#define _H_BOOTINFOLOAD + +#include "libopenbios/sys_info.h" + +extern int is_bootinfo(char *bootinfo); +extern int bootinfo_load(struct sys_info *info, const char *filename); +extern void bootinfo_init_program(void); + +#endif /* _H_BOOTINFOLOAD */ diff --git a/qemu/roms/openbios/include/libopenbios/console.h b/qemu/roms/openbios/include/libopenbios/console.h new file mode 100644 index 000000000..899dab831 --- /dev/null +++ b/qemu/roms/openbios/include/libopenbios/console.h @@ -0,0 +1,25 @@ +/* + * <console.h> + * + * Shared console routines + * + * Copyright (C) 2013 Mark Cave-Ayland (mark.cave-ayland@ilande.co.uk) + * + * 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 + * + */ + +#ifndef _H_CONSOLE +#define _H_CONSOLE + +struct _console_ops { + int (*putchar)(int c); + int (*availchar)(void); + int (*getchar)(void); +}; + +void init_console(struct _console_ops ops); + +#endif /* _H_CONSOLE */ diff --git a/qemu/roms/openbios/include/libopenbios/elf_load.h b/qemu/roms/openbios/include/libopenbios/elf_load.h new file mode 100644 index 000000000..d3876241f --- /dev/null +++ b/qemu/roms/openbios/include/libopenbios/elf_load.h @@ -0,0 +1,31 @@ +/* + * Creation Date: <2001/05/05 16:44:17 samuel> + * Time-stamp: <2003/10/22 23:18:42 samuel> + * + * <elfload.h> + * + * Elf loader + * + * Copyright (C) 2001, 2003 Samuel Rydh (samuel@ibrium.se) + * + * 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 + * + */ + +#ifndef _H_ELFLOAD +#define _H_ELFLOAD + +#include "arch/common/elf.h" +#include "asm/elf.h" +#include "libopenbios/sys_info.h" + +extern int elf_load(struct sys_info *info, ihandle_t dev, const char *cmdline, void **boot_notes); +extern void elf_init_program(void); +extern int is_elf(Elf_ehdr *ehdr); +extern int find_elf(Elf_ehdr *ehdr); + +extern Elf_phdr * elf_readhdrs(int offset, Elf_ehdr *ehdr); + +#endif /* _H_ELFLOAD */ diff --git a/qemu/roms/openbios/include/libopenbios/fcode_load.h b/qemu/roms/openbios/include/libopenbios/fcode_load.h new file mode 100644 index 000000000..a84ac982b --- /dev/null +++ b/qemu/roms/openbios/include/libopenbios/fcode_load.h @@ -0,0 +1,24 @@ +/* + * Creation Date: <2010/03/22 18:00:00 mcayland> + * Time-stamp: <2010/03/22 18:00:00 mcayland> + * + * <fcode_load.h> + * + * Fcode loader + * + * Copyright (C) 2010 Mark Cave-Ayland (mark.cave-ayland@siriusit.co.uk) + * + * 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 + * + */ + +#ifndef _H_FCODELOAD +#define _H_FCODELOAD + +extern int is_fcode(unsigned char *fcode); +extern int fcode_load(ihandle_t dev); +extern void fcode_init_program(void); + +#endif /* _H_FCODELOAD */ diff --git a/qemu/roms/openbios/include/libopenbios/fontdata.h b/qemu/roms/openbios/include/libopenbios/fontdata.h new file mode 100644 index 000000000..1f8f0de32 --- /dev/null +++ b/qemu/roms/openbios/include/libopenbios/fontdata.h @@ -0,0 +1,28 @@ +/* Font definitions */ + +#ifndef OPENBIOS_FONTDATA_H +#define OPENBIOS_FONTDATA_H + +#define FONTDATAMAX_8X8 2048 +#define FONT_WIDTH_8X8 8 +#define FONT_HEIGHT_8X8 8 + +extern const unsigned char fontdata_8x8[FONTDATAMAX_8X8]; + +#define FONTDATAMAX_8X16 4096 +#define FONT_WIDTH_8X16 8 +#define FONT_HEIGHT_8X16 16 + +extern const unsigned char fontdata_8x16[FONTDATAMAX_8X16]; + +#if defined(CONFIG_FONT_8X8) +#define fontdata fontdata_8x8 +#define FONT_HEIGHT FONT_HEIGHT_8X8 +#define FONT_WIDTH FONT_WIDTH_8X8 +#elif defined(CONFIG_FONT_8X16) +#define fontdata fontdata_8x16 +#define FONT_HEIGHT FONT_HEIGHT_8X16 +#define FONT_WIDTH FONT_WIDTH_8X16 +#endif + +#endif /* OPENBIOS_FONTDATA_H */ diff --git a/qemu/roms/openbios/include/libopenbios/forth_load.h b/qemu/roms/openbios/include/libopenbios/forth_load.h new file mode 100644 index 000000000..a39d414c7 --- /dev/null +++ b/qemu/roms/openbios/include/libopenbios/forth_load.h @@ -0,0 +1,24 @@ +/* + * Creation Date: <2010/03/22 18:00:00 mcayland> + * Time-stamp: <2010/03/22 18:00:00 mcayland> + * + * <forth_load.h> + * + * Forth loader + * + * Copyright (C) 2010 Mark Cave-Ayland (mark.cave-ayland@siriusit.co.uk) + * + * 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 + * + */ + +#ifndef _H_FORTHLOAD +#define _H_FORTHLOAD + +extern int is_forth(char *forth); +extern int forth_load(ihandle_t dev); +extern void forth_init_program(void); + +#endif /* _H_FORTHLOAD */ diff --git a/qemu/roms/openbios/include/libopenbios/initprogram.h b/qemu/roms/openbios/include/libopenbios/initprogram.h new file mode 100644 index 000000000..1684f5d9b --- /dev/null +++ b/qemu/roms/openbios/include/libopenbios/initprogram.h @@ -0,0 +1,22 @@ +/* + * Creation Date: <2010/04/02 13:00:00 mcayland> + * Time-stamp: <2010/04/02 13:00:00 mcayland> + * + * <initprogram.h> + * + * C implementation of (init-program) word + * + * Copyright (C) 2010 Mark Cave-Ayland (mark.cave-ayland@siriusit.co.uk) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#ifndef _H_INITPROGRAM +#define _H_INITPROGRAM + +extern void init_program(void); + +#endif /* _H_INITPROGRAM */ diff --git a/qemu/roms/openbios/include/libopenbios/ipchecksum.h b/qemu/roms/openbios/include/libopenbios/ipchecksum.h new file mode 100644 index 000000000..24cc1d744 --- /dev/null +++ b/qemu/roms/openbios/include/libopenbios/ipchecksum.h @@ -0,0 +1,7 @@ +#ifndef IPCHECKSUM_H +#define IPCHECKSUM_H + +unsigned short ipchksum(const void *data, unsigned long length); +unsigned short add_ipchksums(unsigned long offset, unsigned short sum, unsigned short new); + +#endif /* IPCHECKSUM_H */ diff --git a/qemu/roms/openbios/include/libopenbios/load.h b/qemu/roms/openbios/include/libopenbios/load.h new file mode 100644 index 000000000..2a4d97f3e --- /dev/null +++ b/qemu/roms/openbios/include/libopenbios/load.h @@ -0,0 +1,22 @@ +/* + * Creation Date: <2010/06/25 20:00:00 mcayland> + * Time-stamp: <2010/06/25 20:00:00 mcayland> + * + * <load.h> + * + * C implementation of load + * + * Copyright (C) 2010 Mark Cave-Ayland (mark.cave-ayland@siriusit.co.uk) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#ifndef _H_LOAD +#define _H_LOAD + +extern void load(ihandle_t dev); + +#endif /* _H_LOAD */ diff --git a/qemu/roms/openbios/include/libopenbios/of.h b/qemu/roms/openbios/include/libopenbios/of.h new file mode 100644 index 000000000..64cf6d080 --- /dev/null +++ b/qemu/roms/openbios/include/libopenbios/of.h @@ -0,0 +1,22 @@ +/* + * Creation Date: <2004/01/07 19:19:18 samuel> + * Time-stamp: <2004/01/07 19:19:48 samuel> + * + * <of.h> + * + * OpenFirmware related defines + * + * Copyright (C) 2004 Samuel Rydh (samuel@ibrium.se) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#ifndef _H_OF +#define _H_OF + +extern int of_client_interface( int *params ); + +#endif /* _H_OF */ diff --git a/qemu/roms/openbios/include/libopenbios/ofmem.h b/qemu/roms/openbios/include/libopenbios/ofmem.h new file mode 100644 index 000000000..0b19db1ca --- /dev/null +++ b/qemu/roms/openbios/include/libopenbios/ofmem.h @@ -0,0 +1,145 @@ +/* + * Creation Date: <1999/11/16 00:47:06 samuel> + * Time-stamp: <2003/10/18 13:28:14 samuel> + * + * <ofmem.h> + * + * + * + * Copyright (C) 1999, 2002 Samuel Rydh (samuel@ibrium.se) + * + * 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 + * + */ + +#ifndef _H_OFMEM +#define _H_OFMEM + +#include "kernel/stack.h" + +typedef struct alloc_desc { + struct alloc_desc *next; + ucell size; /* size (including) this struct */ +} alloc_desc_t; + +typedef struct mem_range { + struct mem_range *next; + phys_addr_t start; /* sizeof(phys) >= sizeof(virt), e.g SPARC32 */ + ucell size; +} range_t; + +typedef struct trans { + struct trans *next; + ucell virt; /* chain is sorted by virt */ + ucell size; + phys_addr_t phys; + ucell mode; +} translation_t; + +/* ofmem private data */ +typedef struct { + ucell ramsize; + char *next_malloc; + alloc_desc_t *mfree; /* list of free malloc blocks */ + + range_t *phys_range; + range_t *virt_range; + range_t *io_range; + + translation_t *trans; /* this is really a translation_t */ +} ofmem_t; + +/* structure for retained data */ +typedef struct { + ucell magic; + ucell numentries; + range_t retain_phys_range[8]; /* physical memory that should survive a warm reset */ +} retain_t; + +/* TODO: temporary migration interface */ +extern ofmem_t* ofmem_arch_get_private(void); +extern void* ofmem_arch_get_malloc_base(void); +extern ucell ofmem_arch_get_heap_top(void); +extern ucell ofmem_arch_get_virt_top(void); +extern ucell ofmem_arch_get_iomem_base(void); +extern ucell ofmem_arch_get_iomem_top(void); +extern retain_t* ofmem_arch_get_retained(void); +extern int ofmem_arch_get_physaddr_cellsize(void); +extern int ofmem_arch_encode_physaddr(ucell *p, phys_addr_t value); +extern int ofmem_arch_get_available_entry_size(phandle_t ph); +extern void ofmem_arch_create_available_entry(phandle_t ph, ucell *availentry, phys_addr_t start, ucell size); +extern int ofmem_arch_get_translation_entry_size(void); +extern void ofmem_arch_create_translation_entry(ucell *transentry, translation_t *t); +extern ucell ofmem_arch_default_translation_mode( phys_addr_t phys ); +extern ucell ofmem_arch_io_translation_mode( phys_addr_t phys ); +extern void ofmem_arch_map_pages(phys_addr_t phys, ucell virt, ucell size, + ucell mode); +extern void ofmem_arch_unmap_pages(ucell virt, ucell size); +/* sparc64 uses this method */ +extern int ofmem_map_page_range( phys_addr_t phys, ucell virt, ucell size, + ucell mode ); + +/* Private functions for mapping between physical/virtual addresses */ +extern phys_addr_t va2pa(unsigned long va); +extern unsigned long pa2va(phys_addr_t pa); + +/* malloc interface */ +extern int ofmem_posix_memalign( void **memptr, size_t alignment, size_t size ); +extern void* ofmem_malloc( size_t size ); +extern void ofmem_free( void *ptr ); +extern void* ofmem_realloc( void *ptr, size_t size ); + +/* ofmem_common.c */ + +extern void ofmem_cleanup( void ); +extern void ofmem_init( void ); + +/* + * register /memory and /virtual-memory handles + * ofmem module will update "available" and "translations" properties + * using these handles + * + * to disable updating /memory properties pass zero memory handle + */ +extern void ofmem_register( phandle_t ph_memory, phandle_t ph_mmu ); + +extern ucell ofmem_claim( ucell addr, ucell size, ucell align ); +extern phys_addr_t ofmem_claim_phys( phys_addr_t mphys, ucell size, ucell align ); +extern ucell ofmem_claim_virt( ucell mvirt, ucell size, ucell align ); +extern ucell ofmem_claim_io( ucell virt, ucell size, ucell align ); + +extern phys_addr_t ofmem_retain( phys_addr_t phys, ucell size, ucell align ); + +extern int ofmem_map( phys_addr_t phys, ucell virt, ucell size, ucell mode ); +extern int ofmem_unmap( ucell virt, ucell size ); +extern ucell ofmem_map_io( phys_addr_t phys, ucell size ); + +extern void ofmem_release( ucell virt, ucell size ); +extern void ofmem_release_phys( phys_addr_t phys, ucell size ); +extern void ofmem_release_virt( ucell virt, ucell size ); +extern void ofmem_release_io( ucell virt, ucell size ); +extern phys_addr_t ofmem_translate( ucell virt, ucell *ret_mode ); + +/* memory and virtual-memory nodes */ +extern phandle_t s_phandle_memory; +extern phandle_t s_phandle_mmu; + +#define PAGE_SIZE (1 << PAGE_SHIFT) +#define PAGE_MASK (~(PAGE_SIZE - 1)) +#define PAGE_ALIGN(addr) (((addr) + PAGE_SIZE - 1) & PAGE_MASK) + +#if defined(CONFIG_DEBUG_OFMEM) + #define DEBUG_OFMEM 1 +#else + #define DEBUG_OFMEM 0 +#endif + +#define OFMEM_TRACE(fmt, ...) do { \ + if (DEBUG_OFMEM) { \ + printk("OFMEM: " fmt, ## __VA_ARGS__); \ + } \ +} while (0); + +#endif /* _H_OFMEM */ diff --git a/qemu/roms/openbios/include/libopenbios/openbios.h b/qemu/roms/openbios/include/libopenbios/openbios.h new file mode 100644 index 000000000..394ed4484 --- /dev/null +++ b/qemu/roms/openbios/include/libopenbios/openbios.h @@ -0,0 +1,22 @@ +/* + * Creation Date: <2010/04/02 12:00:00 mcayland> + * Time-stamp: <2010/04/02 12:00:00 mcayland> + * + * <openbios.h> + * + * General OpenBIOS initialization + * + * Copyright (C) 2010 Mark Cave-Ayland (mark.cave-ayland@siriusit.co.uk) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#ifndef _H_LIBOPENBIOS +#define _H_LIBOPENBIOS + +extern void openbios_init( void ); + +#endif /* _H_LIBOPENBIOS */ diff --git a/qemu/roms/openbios/include/libopenbios/sys_info.h b/qemu/roms/openbios/include/libopenbios/sys_info.h new file mode 100644 index 000000000..a8b3cce37 --- /dev/null +++ b/qemu/roms/openbios/include/libopenbios/sys_info.h @@ -0,0 +1,38 @@ +#ifndef SYS_INFO_H +#define SYS_INFO_H + +/* Information collected from firmware/bootloader */ + +struct sys_info { + /* Values passed by bootloader */ + unsigned long boot_type; + unsigned long boot_data; + unsigned long boot_arg; + + const char *firmware; /* "PCBIOS", "LinuxBIOS", etc. */ + const char *command_line; /* command line given to us */ + + /* memory map */ + int n_memranges; + struct memrange { + unsigned long long base; + unsigned long long size; + } *memrange; + unsigned long *dict_start; + unsigned long *dict_end; + cell dict_limit; + ucell *dict_last; +}; + +extern void *elf_boot_notes; +extern struct sys_info sys_info; + +void collect_elfboot_info(struct sys_info *info); +void collect_linuxbios_info(struct sys_info *info); + +/* Our name and version. I want to see single instance of these in the image */ +extern const char *program_name, *program_version; + +#define LOADER_NOT_SUPPORT 0xbadf11e + +#endif /* SYS_INFO_H */ diff --git a/qemu/roms/openbios/include/libopenbios/video.h b/qemu/roms/openbios/include/libopenbios/video.h new file mode 100644 index 000000000..44d74564f --- /dev/null +++ b/qemu/roms/openbios/include/libopenbios/video.h @@ -0,0 +1,36 @@ + +#ifdef CONFIG_VGA_WIDTH +#define VGA_DEFAULT_WIDTH CONFIG_VGA_WIDTH +#else +#define VGA_DEFAULT_WIDTH 800 +#endif + +#ifdef CONFIG_VGA_HEIGHT +#define VGA_DEFAULT_HEIGHT CONFIG_VGA_HEIGHT +#else +#define VGA_DEFAULT_HEIGHT 600 +#endif + +#ifdef CONFIG_VGA_DEPTH +#define VGA_DEFAULT_DEPTH CONFIG_VGA_DEPTH +#else +#define VGA_DEFAULT_DEPTH 8 +#endif + +#define VGA_DEFAULT_LINEBYTES (VGA_DEFAULT_WIDTH*((VGA_DEFAULT_DEPTH+7)/8)) + +void setup_video(void); +unsigned long video_get_color(int col_ind); +void video_mask_blit(void); +void video_invert_rect(void); +void video_fill_rect(void); + +extern struct video_info { + volatile ihandle_t *ih; + volatile ucell *mvirt; + volatile ucell *rb, *w, *h, *depth; + + volatile ucell *pal; /* 256 elements */ +} video; + +#define VIDEO_DICT_VALUE(x) (*(ucell *)(x)) diff --git a/qemu/roms/openbios/include/libopenbios/xcoff_load.h b/qemu/roms/openbios/include/libopenbios/xcoff_load.h new file mode 100644 index 000000000..2ec693d60 --- /dev/null +++ b/qemu/roms/openbios/include/libopenbios/xcoff_load.h @@ -0,0 +1,27 @@ +/* + * Creation Date: <2010/03/22 18:00:00 mcayland> + * Time-stamp: <2010/03/22 18:00:00 mcayland> + * + * <xcoff_load.h> + * + * XCOFF loader + * + * Copyright (C) 2010 Mark Cave-Ayland (mark.cave-ayland@siriusit.co.uk) + * + * 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 + * + */ + +#ifndef _H_XCOFFLOAD +#define _H_XCOFFLOAD + +#include "arch/common/xcoff.h" +#include "libopenbios/sys_info.h" + +extern int is_xcoff(COFF_filehdr_t *fhdr); +extern int xcoff_load(struct sys_info *info, const char *filename); +extern void xcoff_init_program(void); + +#endif /* _H_XCOFFLOAD */ diff --git a/qemu/roms/openbios/include/mconfig.h b/qemu/roms/openbios/include/mconfig.h new file mode 100644 index 000000000..0a4decfb9 --- /dev/null +++ b/qemu/roms/openbios/include/mconfig.h @@ -0,0 +1,70 @@ +/* + * We got rid of configure for now, and I hope it stays like this. + * This file may have to be changed/reworked completely + * + * + */ + +/* mconfig.h. Generated by configure. */ +/* mconfig.h.in. Generated from configure.in by autoheader. */ + +/* Define to 1 if you have the <endian.h> header file. */ +#define HAVE_ENDIAN_H 1 + +/* Define to 1 if you have the <inttypes.h> header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the <machine/endian.h> header file. */ +/* #undef HAVE_MACHINE_ENDIAN_H */ + +/* Define to 1 if you have the <memory.h> header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the <stdint.h> header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the <stdlib.h> header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the <strings.h> header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the <string.h> header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the <sys/stat.h> header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the <sys/types.h> header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the <unistd.h> header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "" + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a + `char[]'. */ +#define YYTEXT_POINTER 1 + +/* Number of bits in a file offset, on hosts where this is settable. */ +/* #undef _FILE_OFFSET_BITS */ + +/* Define for large files, on AIX-style hosts. */ +/* #undef _LARGE_FILES */ diff --git a/qemu/roms/openbios/include/packages/nvram.h b/qemu/roms/openbios/include/packages/nvram.h new file mode 100644 index 000000000..ba1b38b9e --- /dev/null +++ b/qemu/roms/openbios/include/packages/nvram.h @@ -0,0 +1,24 @@ +/* + * Creation Date: <2003/12/20 01:04:25 samuel> + * Time-stamp: <2004/01/07 19:59:11 samuel> + * + * <nvram.h> + * + * arch NVRAM interface + * + * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#ifndef _H_NVRAM_PACKAGE +#define _H_NVRAM_PACKAGE + +extern void nvconf_init( void ); +extern void nvram_init( const char *path ); +extern void update_nvram( void ); + +#endif /* _H_NVRAM_PACKAGE */ diff --git a/qemu/roms/openbios/include/packages/video.h b/qemu/roms/openbios/include/packages/video.h new file mode 100644 index 000000000..2b7f41248 --- /dev/null +++ b/qemu/roms/openbios/include/packages/video.h @@ -0,0 +1,7 @@ +#ifndef VIDEO_SUBR_H +#define VIDEO_SUBR_H + +/* packages/video.c */ +void molvideo_init(void); + +#endif /* VIDEO_SUBR_H */ diff --git a/qemu/roms/openbios/include/sysinclude.h b/qemu/roms/openbios/include/sysinclude.h new file mode 100644 index 000000000..a8b828b4f --- /dev/null +++ b/qemu/roms/openbios/include/sysinclude.h @@ -0,0 +1,20 @@ +#ifndef __SYSINCLUDE_H +#define __SYSINCLUDE_H + +#ifdef BOOTSTRAP +#include "asm/types.h" +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#else /* BOOTSTRAP */ +#include "libc/stdlib.h" +#include "libc/string.h" +#endif /* BOOTSTRAP */ + +extern int printk( const char *fmt, ... ) \ + __attribute__ ((format (printf, 1, 2))); +#ifdef BOOTSTRAP +#define printk printf +#endif + +#endif /* __SYSINCLUDE_H */ diff --git a/qemu/roms/openbios/kernel/Kconfig b/qemu/roms/openbios/kernel/Kconfig new file mode 100644 index 000000000..32831f737 --- /dev/null +++ b/qemu/roms/openbios/kernel/Kconfig @@ -0,0 +1,88 @@ +menu "Kernel Debugging" + +config DEBUG + bool "Kernel Debugging" + default y + help + Kernel Debugging + +config DEBUG_BOOT + bool "Boot messages" + depends on DEBUG + default y + help + early boot code (multiboot parsing etc) + +config DEBUG_DSTACK + bool "dstack messages" + depends on DEBUG + default n + help + stack debugging. warning: heavy output! + +config DEBUG_RSTACK + bool "rstack messages" + depends on DEBUG + default n + help + stack debugging. warning: heavy output! + +config DEBUG_DICTIONARY + bool "Dictionary loading/dumping" + depends on DEBUG + default n + help + print few additional information on dictionary loading/dumping + +config DEBUG_INTERNAL + bool "Prime Words" + depends on DEBUG + default n + help + print additional information for some prime words, like branches + +config DEBUG_INTERPRETER + bool "Interpreter" + depends on DEBUG + default n + help + additional information about the unix.c builtin C interpreter + and some other places where it actually does not belong. + +config DEBUG_CONSOLE + bool "Console" + default y + help + use builtin C console code for user interaction. There is no + real alternative to this until someone writes a display/kbd or + serial driver in forth. + +config DEBUG_CONSOLE_SERIAL + bool "Serial Console" + depends on DEBUG_CONSOLE + default y + help + use serial console. + +config SERIAL_PORT + int "Serial Port" + depends on DEBUG_CONSOLE_SERIAL + default "1" + help + 0 for none, 1 for ttyS0, 2 for ttyS1 + +config SERIAL_SPEED + int "Serial line speed" + depends on DEBUG_CONSOLE_SERIAL + default "115200" + help + supported speeds are: 115200, 57600, 38400, 19200, 9600 + +config DEBUG_CONSOLE_VGA + bool "VGA Console" + depends on DEBUG_CONSOLE + default y + help + use vga textmode and keyboard console + +endmenu diff --git a/qemu/roms/openbios/kernel/README b/qemu/roms/openbios/kernel/README new file mode 100644 index 000000000..c84879b83 --- /dev/null +++ b/qemu/roms/openbios/kernel/README @@ -0,0 +1,93 @@ + +Welcome to the OpenBIOS forth core "begin again". + +Find more information about OpenBIOS at http://www.openbios.org/ + +This program was written by Patrick Mauritz and Stefan Reinauer in 2003 +For license details on this piece of software, check Documentation/COPYING. + +How OpenBIOS works +------------------ + + The OpenBIOS forth core is split into a forth kernel written in C + and a forth dictionary which operated on by the kernel. + + When building the forth core, you get different versions of + the forth kernel: + + * a "hosted" unix binary. This binary can be used on a unix system + + - to execute a forth dictionary from a file. This can be used for + testing openbios code in a development environment on a unix host. + + - to create a dictionary file. Such a dictionary file sets up + all of the forth language. Primitives are indexed to save relocations. + + The default is to create a forth dictionary forth.dict from + forth/start.fs. This file includes all of the basic forth language + constructs from forth/bootstrap.fs and starts the interpreter. + + To achieve this, the hosted unix version contains a basic set of + forth words coded in C that allow creating a full dictionary. + + * a varying number of target specific binaries. On x86 you can start + openbios for example from GRUB or LinuxBIOS. They are all based on + the same forth engine consisting of a dictionary scheduler, primitive + words needed to build the forth environment, 2 stacks and a simple + set of console functions. These binaries can not be started directly + in the unix host environment. + +Requirements +------------ + * gcc + * grub or any other multiboot loader to run the standalone + binary "openbios.multiboot" + +Building & Usage +---------------- + + * make + + this builds "openbios.multiboot", the standalone image and "unix", + the hosted image. Additionally it creates a forth dictionary + file from forth/start.fs. All generated files are written to + the absolute directory held by the variable BUILDDIR, which defaults + to obj-[platform]. Some compile time parameters can be tweaked in + include/config.h + + * use "unix" to create a forth dictionary on your own: + $ ./unix -Iforth start.fs + creates the file forth.dict from forth source forth/start.fs. + + * use "unix" to run a created dictionary: + $ ./unix forth.dict + This is useful for testing + + * booting openbios + You can boot openbios i.e. in grub. Add the following lines to + your menu.lst: + + title openbios + kernel (hd0,2)/boot/openbios.multiboot + module (hd0,2)/boot/openfirmware.dict + + Note: change (hd0,2) to the partition you copied openbios and + forth.dict to. + + To boot OpenBIOS from LinuxBIOS/etherboot, you can either use + "openbios" or "openbios.full": + + - openbios is the pure kernel that loads the dictionary from a + hardcoded address in flash memory (0xfffe0000) + + - openbios.full also includes the dictionary directly so that it + can be easily used from etherboot or the LinuxBIOS builtin ELF + loader without taking care of the dictionary + + +Comments are welcome. + + OpenBIOS team + +------------------------------------------------------------------------ +tag: README for openbios forth core diff --git a/qemu/roms/openbios/kernel/bootstrap.c b/qemu/roms/openbios/kernel/bootstrap.c new file mode 100644 index 000000000..520d7b48c --- /dev/null +++ b/qemu/roms/openbios/kernel/bootstrap.c @@ -0,0 +1,1322 @@ +/* tag: forth bootstrap environment + * + * Copyright (C) 2003-2006 Stefan Reinauer, Patrick Mauritz + * + * See the file "COPYING" for further information about + * the copyright and warranty status of this work. + */ + +#include "sysinclude.h" +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <signal.h> +#include <fcntl.h> +#include <unistd.h> +#include <termios.h> +#include <sys/stat.h> + +#ifdef __GLIBC__ +#define _GNU_SOURCE +#include <getopt.h> +#endif + +#include "config.h" +#include "kernel/stack.h" +#include "sysinclude.h" +#include "kernel/kernel.h" +#include "dict.h" +#include "cross.h" +#include "openbios-version.h" + +#define MAX_PATH_LEN 256 + +#define MEMORY_SIZE (1024*1024) /* 1M ram for hosted system */ +#define DICTIONARY_SIZE (256*1024) /* 256k for the dictionary */ +#define TRAMPOLINE_SIZE (4*sizeof(cell)) /* 4 cells for the trampoline */ + +/* state variables */ +static ucell *latest, *state, *base; +static ucell *memory; +ucell *trampoline; + +/* local variables */ +static int errors = 0; +static int segfault = 0; +static int verbose = 0; + +#define MAX_SRC_FILES 128 + +static FILE *srcfiles[MAX_SRC_FILES]; +static char *srcfilenames[MAX_SRC_FILES]; +static int srclines[MAX_SRC_FILES]; +static unsigned int cursrc = 0; + +static char *srcbasedict; + +/* console variables */ +static FILE *console; + +#ifdef NATIVE_BITWIDTH_SMALLER_THAN_HOST_BITWIDTH +unsigned long base_address; +#endif + +/* include path handling */ +typedef struct include_path include; +struct include_path { + const char *path; + include *next; +}; + +static include includes = { ".", NULL }; +static FILE *depfile; + +static ucell * relocation_address=NULL; +static int relocation_length=0; + +/* the word names are used to generate the prim words in the + * dictionary. This is done by the C written interpreter. + */ +static const char *wordnames[] = { + "(semis)", "", "(lit)", "", "", "", "", "(do)", "(?do)", "(loop)", + "(+loop)", "", "", "", "dup", "2dup", "?dup", "over", "2over", "pick", "drop", + "2drop", "nip", "roll", "rot", "-rot", "swap", "2swap", ">r", "r>", + "r@", "depth", "depth!", "rdepth", "rdepth!", "+", "-", "*", "u*", + "mu/mod", "abs", "negate", "max", "min", "lshift", "rshift", ">>a", + "and", "or", "xor", "invert", "d+", "d-", "m*", "um*", "@", "c@", + "w@", "l@", "!", "+!", "c!", "w!", "l!", "=", ">", "<", "u>", "u<", + "sp@", "move", "fill", "(emit)", "(key?)", "(key)", "execute", + "here", "here!", "dobranch", "do?branch", "unaligned-w@", + "unaligned-w!", "unaligned-l@", "unaligned-l!", "ioc@", "iow@", + "iol@", "ioc!", "iow!", "iol!", "i", "j", "call", "sys-debug", + "$include", "$encode-file", "(debug", "(debug-off)" +}; + +/* + * dictionary related functions. + */ + +/* + * Compare two dictionaries constructed at different addresses. When + * the cells don't match, a need for relocation is detected and the + * corresponding bit in reloc_table bitmap is set. + */ +static void relocation_table(unsigned char * dict_one, unsigned char *dict_two, int length) +{ + ucell *d1=(ucell *)dict_one, *d2=(ucell *)dict_two; + ucell *reloc_table; + int pos, bit; + int l=(length+(sizeof(cell)-1))/sizeof(ucell), i; + + /* prepare relocation table */ + relocation_length=(length+BITS-1)/BITS; + reloc_table = malloc(relocation_length*sizeof(cell)); + memset(reloc_table,0,relocation_length*sizeof(cell)); + + for (i=0; i<l; i++) { + + pos=i/BITS; + bit=i&~(-BITS); + + if(d1[i]==d2[i]) { + reloc_table[pos] &= target_ucell(~((ucell)1ULL << bit)); + + // This check might bring false positives in data. + //if(d1[i] >= pointer2cell(dict_one) && + // d1[i] <= pointer2cell(dict_one+length)) + // printk("\nWARNING: inconsistent relocation (%x:%x)!\n", d1[i], d2[i]); + } else { + /* This is a pointer, it needs relocation, d2==dict */ + reloc_table[pos] |= target_ucell((ucell)1ULL << bit); + d2[i] = target_ucell(target_ucell(d2[i]) - pointer2cell(d2)); + } + } + +#ifdef CONFIG_DEBUG_DICTIONARY + printk("dict1 %lx dict2 %lx dict %lx\n",dict_one, dict_two, dict); + for (i=0; i< relocation_length ; i++) + printk("reloc %d %lx\n",i+1, reloc_table[i]); +#endif + relocation_address=reloc_table; +} + +static void write_dictionary(const char *filename) +{ + FILE *f; + unsigned char *write_data, *walk_data; + int write_len; + dictionary_header_t *header; + u32 checksum=0; + + /* + * get memory for dictionary + */ + + write_len = sizeof(dictionary_header_t)+dicthead+relocation_length*sizeof(cell); + write_data = malloc(write_len); + if(!write_data) { + printk("panic: can't allocate memory for output dictionary (%d" + " bytes\n", write_len); + exit(1); + } + memset(write_data, 0, write_len); + + /* + * prepare dictionary header + */ + + header = (dictionary_header_t *)write_data; + *header = (dictionary_header_t){ + .signature = DICTID, + .version = 2, + .cellsize = sizeof(ucell), +#ifdef CONFIG_BIG_ENDIAN + .endianess = -1, +#else + .endianess = 0, +#endif + .checksum = 0, + .compression = 0, + .relocation = -1, + .length = target_ulong((uint32_t)dicthead), + .last = target_ucell((ucell)((unsigned long)last + - (unsigned long)dict)), + }; + + /* + * prepare dictionary data + */ + + walk_data=write_data+sizeof(dictionary_header_t); + memcpy (walk_data, dict, dicthead); + + /* + * prepare relocation data. + * relocation_address is zero when writing a dictionary core. + */ + + if (relocation_address) { +#ifdef CONFIG_DEBUG_DICTIONARY + printk("writing %d reloc cells \n",relocation_length); +#endif + walk_data += dicthead; + memcpy(walk_data, relocation_address, + relocation_length*sizeof(cell)); + /* free relocation information */ + free(relocation_address); + relocation_address=NULL; + } else { + header->relocation=0; + } + + /* + * Calculate Checksum + */ + + walk_data=write_data; + while (walk_data<write_data+write_len) { + checksum+=read_long(walk_data); + walk_data+=sizeof(u32); + } + checksum=(u32)-checksum; + + header->checksum=target_long(checksum); + + if (verbose) { + dump_header(header); + } + + f = fopen(filename, "w"); + if (!f) { + printk("panic: can't write to dictionary '%s'.\n", filename); + exit(1); + } + + fwrite(write_data, write_len, 1, f); + + free(write_data); + fclose(f); + +#ifdef CONFIG_DEBUG_DICTIONARY + printk("wrote dictionary to file %s.\n", filename); +#endif +} + +/* + * Write dictionary as a list of ucell hex values to filename. Array + * header and end lines are not generated. + * + * Cells with relocations are output using the expression + * DICTIONARY_BASE + value. + * + * Define some helpful constants. + */ +static void write_dictionary_hex(const char *filename) +{ + FILE *f; + ucell *walk; + + f = fopen(filename, "w"); + if (!f) { + printk("panic: can't write to dictionary '%s'.\n", filename); + exit(1); + } + + for (walk = (ucell *)dict; walk < (ucell *)(dict + dicthead); walk++) { + int pos, bit, l; + ucell val; + + l = (walk - (ucell *)dict); + pos = l / BITS; + bit = l & ~(-BITS); + + val = read_ucell(walk); + if (relocation_address[pos] & target_ucell((ucell)1ULL << bit)) { + fprintf(f, "DICTIONARY_BASE + 0x%" FMT_CELL_x + ",\n", val); + } else { + fprintf(f, "0x%" FMT_CELL_x",\n", val); + } + } + + fprintf(f, "#define FORTH_DICTIONARY_LAST 0x%" FMT_CELL_x"\n", + (ucell)((unsigned long)last - (unsigned long)dict)); + fprintf(f, "#define FORTH_DICTIONARY_END 0x%" FMT_CELL_x"\n", + (ucell)dicthead); + fclose(f); + +#ifdef CONFIG_DEBUG_DICTIONARY + printk("wrote dictionary to file %s.\n", filename); +#endif +} + +static ucell read_dictionary(char *fil) +{ + int ilen; + ucell ret; + char *mem; + FILE *f; + struct stat finfo; + + if (stat(fil, &finfo)) + return 0; + + ilen = finfo.st_size; + + if ((mem = malloc(ilen)) == NULL) { + printk("panic: not enough memory.\n"); + exit(1); + } + + f = fopen(fil, "r"); + if (!f) { + printk("panic: can't open dictionary.\n"); + exit(1); + } + + if (fread(mem, ilen, 1, f) != 1) { + printk("panic: can't read dictionary.\n"); + fclose(f); + exit(1); + } + fclose(f); + + ret = load_dictionary(mem, ilen); + + free(mem); + return ret; +} + + +/* + * C Parser related functions + */ + +/* + * skipws skips all whitespaces (space, tab, newline) from the input file + */ + +static void skipws(FILE * f) +{ + int c; + while (!feof(f)) { + c = getc(f); + + if (c == ' ' || c == '\t') + continue; + + if (c == '\n') { + srclines[cursrc - 1]++; + continue; + } + + ungetc(c, f); + break; + } +} + +/* + * parse gets the next word from the input stream, delimited by + * delim. If delim is 0, any word delimiter will end the stream + * word delimiters are space, tab and newline. The resulting word + * will be put zero delimited to the char array line. + */ + +static int parse(FILE * f, char *line, char delim) +{ + int cnt = 0, c = 0; + + while (!feof(f)) { + c = getc(f); + + if (delim && c == delim) + break; + + if ((!delim) && (c == ' ' || c == '\t' || c == '\n')) + break; + + line[cnt++] = c; + } + + /* Update current line number */ + if (c == '\n') { + srclines[cursrc - 1]++; + } + + line[cnt] = 0; + + return cnt; +} + +/* + * parse_word is a small helper that skips whitespaces before a word. + * it's behaviour is similar to the forth version parse-word. + */ + +static void parse_word(FILE * f, char *line) +{ + skipws(f); + parse(f, line, 0); +} + + +static void writestring(const char *str) +{ + unsigned int i; + for (i = 0; i < strlen(str); i++) { + dict[dicthead + i] = str[i]; + } + dicthead += i + 1; + dict[dicthead - 1] = (char) strlen(str) + 128; +} + +#define writebyte(value) {write_byte(dict+dicthead,value); dicthead++;} +#define writecell(value) {write_cell(dict+dicthead, value); dicthead+=sizeof(cell);} + +/* + * reveal a word, ie. make it visible. + */ + +static void reveal(void) +{ + *last = *latest; +} + +/* + * dictionary padding + */ + +static void paddict(ucell align) +{ + while (dicthead % align != 0) + writebyte(0); +} + +/* + * generic forth word creator function. + */ + +static void fcreate(const char *word, ucell cfaval) +{ + if (strlen(word) == 0) { + printk("WARNING: tried to create unnamed word.\n"); + return; + } + + writestring(word); + /* get us at least 1 byte for flags */ + writebyte(0); + paddict(sizeof(cell)); + /* set flags high bit. */ + dict[dicthead - 1] = 128; + /* lfa and cfa */ + writecell(read_ucell(latest)); + *latest = target_ucell(pointer2cell(dict) + dicthead - sizeof(cell)); + writecell(cfaval); +} + + +static ucell *buildvariable(const char *name, cell defval) +{ + fcreate(name, DOVAR); /* see dict.h for DOVAR and other CFA ids */ + writecell(defval); + return (ucell *) (dict + dicthead - sizeof(cell)); +} + +static void buildconstant(const char *name, cell defval) +{ + fcreate(name, DOCON); /* see dict.h for DOCON and other CFA ids */ + writecell(defval); +} + +static void builddefer(const char *name) +{ + fcreate(name, DODFR); /* see dict.h for DODFR and other CFA ids */ + writecell((ucell)0); + writecell((ucell)findword("(semis)")); +} + +/* + * Include file handling + */ + +static void add_includepath(char *path) +{ + include *incl = &includes; + include *newpath; + + while (incl->next) + incl = incl->next; + + newpath = malloc(sizeof(include)); + if (!newpath) { + printk("panic: not enough memory for include path.\n"); + exit(1); + } + + incl->next = newpath; + newpath->path = path; + newpath->next = NULL; +} + + +static FILE *fopen_include(const char *fil) +{ + char fullpath[MAX_PATH_LEN]; + FILE *ret; + include *incl = &includes; + + while (incl) { + snprintf(fullpath, sizeof(fullpath), "%s/%s", incl->path, fil); + + ret = fopen(fullpath, "r"); + if (ret != NULL) { + +#ifdef CONFIG_DEBUG_INTERPRETER + printk("Including '%s'\n", fil); +#endif + srcfilenames[cursrc] = strdup(fil); + srclines[cursrc] = 1; + srcfiles[cursrc++] = ret; + + if (depfile) { + fprintf(depfile, " %s", fullpath); + } + + return ret; + } + + incl = incl->next; + } + return NULL; +} + + +/* + * Forth exception handler + */ + +void exception(cell no) +{ + printk("%s:%d: ", srcfilenames[cursrc - 1], srclines[cursrc - 1]); + + /* See also forth/bootstrap/interpreter.fs */ + switch (no) { + case -1: + case -2: + printk("Aborted.\n"); + break; + case -3: + printk("Stack Overflow.\n"); + break; + case -4: + printk("Stack Underflow.\n"); + break; + case -5: + printk("Return Stack Overflow.\n"); + break; + case -6: + printk("Return Stack Underflow.\n"); + break; + case -19: + printk("undefined word.\n"); + break; + case -21: + printk("out of memory.\n"); + break; + case -33: + printk("undefined method.\n"); + break; + case -34: + printk("no such device.\n"); + break; + default: + printk("error %" FMT_CELL_d " occured.\n", no); + } + exit(1); +} + + +/* + * This is the C version of the forth interpreter + */ + +static int interpret_source(char *fil) +{ + FILE *f; + char tib[160]; + cell num; + char *test; + + const ucell SEMIS = (ucell)findword("(semis)"); + const ucell LIT = (ucell)findword("(lit)"); + const ucell DOBRANCH = (ucell)findword("dobranch"); + + if ((f = fopen_include(fil)) == NULL) { + printk("error while loading source file '%s'\n", fil); + errors++; + exit(1); + } + + /* FIXME: We should read this file at + * once. No need to get it char by char + */ + + while (!feof(f)) { + xt_t res; + parse_word(f, tib); + + /* if there is actually no word, we continue right away */ + if (strlen(tib) == 0) { + continue; + } + + /* Checking for builtin words that are needed to + * bootstrap the forth base dictionary. + */ + + if (!strcmp(tib, "(")) { + parse(f, tib, ')'); + continue; + } + + if (!strcmp(tib, "\\")) { + parse(f, tib, '\n'); + continue; + } + + if (!strcmp(tib, ":")) { + parse_word(f, tib); + +#ifdef CONFIG_DEBUG_INTERPRETER + printk("create colon word %s\n\n", tib); +#endif + fcreate(tib, DOCOL); /* see dict.h for DOCOL and other CFA ids */ + *state = (ucell) (-1); + continue; + } + + if (!strcmp(tib, ";")) { +#ifdef CONFIG_DEBUG_INTERPRETER + printk("finish colon definition\n\n"); +#endif + writecell((cell)SEMIS); + *state = (ucell) 0; + reveal(); + continue; + } + + if (!strcasecmp(tib, "variable")) { + parse_word(f, tib); +#ifdef CONFIG_DEBUG_INTERPRETER + printk("defining variable %s\n\n", tib); +#endif + buildvariable(tib, 0); + reveal(); + continue; + } + + if (!strcasecmp(tib, "constant")) { + parse_word(f, tib); +#ifdef CONFIG_DEBUG_INTERPRETER + printk("defining constant %s\n\n", tib); +#endif + buildconstant(tib, POP()); + reveal(); + continue; + } + + if (!strcasecmp(tib, "value")) { + parse_word(f, tib); +#ifdef CONFIG_DEBUG_INTERPRETER + printk("defining value %s\n\n", tib); +#endif + buildconstant(tib, POP()); + reveal(); + continue; + } + + if (!strcasecmp(tib, "defer")) { + parse_word(f, tib); +#ifdef CONFIG_DEBUG_INTERPRETER + printk("defining defer word %s\n\n", tib); +#endif + builddefer(tib); + reveal(); + continue; + } + + if (!strcasecmp(tib, "include")) { + parse_word(f, tib); +#ifdef CONFIG_DEBUG_INTERPRETER + printk("including file %s\n\n", tib); +#endif + interpret_source(tib); + continue; + } + + if (!strcmp(tib, "[']")) { + xt_t xt; + parse_word(f, tib); + xt = findword(tib); + if (*state == 0) { +#ifdef CONFIG_DEBUG_INTERPRETER + printk + ("writing address of %s to stack\n\n", + tib); +#endif + PUSH_xt(xt); + } else { +#ifdef CONFIG_DEBUG_INTERPRETER + printk("writing lit, addr(%s) to dict\n\n", + tib); +#endif + writecell(LIT); /* lit */ + writecell((cell)xt); + } + continue; + /* we have no error detection here */ + } + + if (!strcasecmp(tib, "s\"")) { + int cnt; + cell loco; + + cnt = parse(f, tib, '"'); +#ifdef CONFIG_DEBUG_INTERPRETER + printk("compiling string %s\n", tib); +#endif + loco = dicthead + (6 * sizeof(cell)); + writecell(LIT); + writecell(pointer2cell(dict) + loco); + writecell(LIT); + writecell((ucell)cnt); + writecell(DOBRANCH); + loco = cnt + sizeof(cell) - 1; + loco &= ~(sizeof(cell) - 1); + writecell(loco); + memcpy(dict + dicthead, tib, cnt); + dicthead += cnt; + paddict(sizeof(cell)); + continue; + } + + /* look if tib is in dictionary. */ + /* should the dictionary be searched before the builtins ? */ + res = findword(tib); + if (res) { + u8 flags = read_byte((u8*)cell2pointer(res) - + sizeof(cell) - 1); +#ifdef CONFIG_DEBUG_INTERPRETER + printk("%s is 0x%" FMT_CELL_x "\n", tib, (ucell) res); +#endif + if (!(*state) || (flags & 3)) { +#ifdef CONFIG_DEBUG_INTERPRETER + printk("executing %s, %" FMT_CELL_d + " (flags: %s %s)\n", + tib, res, + (flags & 1) ? "immediate" : "", + (flags & 2) ? "compile-only" : ""); +#endif + PC = (ucell)res; + enterforth(res); + } else { +#ifdef CONFIG_DEBUG_INTERPRETER + printk("writing %s to dict\n\n", tib); +#endif + writecell((cell)res); + } + continue; + } + + /* if not look if it's a number */ + if (tib[0] == '-') + num = strtoll(tib, &test, read_ucell(base)); + else + num = strtoull(tib, &test, read_ucell(base)); + + + if (*test != 0) { + /* what is it?? */ + printk("%s:%d: %s is not defined.\n\n", srcfilenames[cursrc - 1], srclines[cursrc - 1], tib); + errors++; +#ifdef CONFIG_DEBUG_INTERPRETER + continue; +#else + return -1; +#endif + } + + if (*state == 0) { +#ifdef CONFIG_DEBUG_INTERPRETER + printk("pushed %" FMT_CELL_x " to stack\n\n", num); +#endif + PUSH(num); + } else { +#ifdef CONFIG_DEBUG_INTERPRETER + printk("writing lit, %" FMT_CELL_x " to dict\n\n", num); +#endif + writecell(LIT); /* lit */ + writecell(num); + } + } + + fclose(f); + cursrc--; + + return 0; +} + +static int build_dictionary(void) +{ + ucell lfa = 0; + unsigned int i; + + /* we need a temporary place for latest outside the dictionary */ + latest = &lfa; + + /* starting a new dictionary: clear dicthead */ + dicthead = 0; + +#ifdef CONFIG_DEBUG_DICTIONARY + printk("building dictionary, %d primitives.\nbuilt words:", + sizeof(wordnames) / sizeof(void *)); +#endif + + for (i = 0; i < sizeof(wordnames) / sizeof(void *); i++) { + if (strlen(wordnames[i]) != 0) { + fcreate((char *) wordnames[i], i); +#ifdef CONFIG_DEBUG_DICTIONARY + printk(" %s", wordnames[i]); +#endif + } + } +#ifdef CONFIG_DEBUG_DICTIONARY + printk(".\n"); +#endif + + /* get last/latest and state */ + state = buildvariable("state", 0); + last = buildvariable("forth-last", 0); + latest = buildvariable("latest", 0); + + *latest = target_ucell(pointer2cell(latest)-2*sizeof(cell)); + + base=buildvariable("base", 10); + + buildconstant("/c", sizeof(u8)); + buildconstant("/w", sizeof(u16)); + buildconstant("/l", sizeof(u32)); + buildconstant("/n", sizeof(ucell)); + buildconstant("/x", sizeof(u64)); + + reveal(); + if (verbose) { + printk("Dictionary initialization finished.\n"); + } + return 0; +} + +/* + * functions used by primitives + */ + +int availchar(void) +{ + int tmp; + if( cursrc < 1 ) { + interruptforth |= FORTH_INTSTAT_STOP; + /* return -1 in order to exit the loop in key() */ + return -1; + } + + tmp = getc( srcfiles[cursrc-1] ); + if (tmp != EOF) { + ungetc(tmp, srcfiles[cursrc-1]); + return -1; + } + + fclose(srcfiles[--cursrc]); + + return availchar(); +} + +int get_inputbyte( void ) +{ + int tmp; + + if( cursrc < 1 ) { + interruptforth |= FORTH_INTSTAT_STOP; + return 0; + } + + tmp = getc( srcfiles[cursrc-1] ); + + /* Update current line number */ + if (tmp == '\n') { + srclines[cursrc - 1]++; + } + + if (tmp != EOF) { + return tmp; + } + + fclose(srcfiles[--cursrc]); + + return get_inputbyte(); +} + +void put_outputbyte( int c ) +{ + if (console) + fputc(c, console); +} + +/* + * segmentation fault handler. linux specific? + */ + +static void +segv_handler(int signo __attribute__ ((unused)), + siginfo_t * si, void *context __attribute__ ((unused))) +{ + static int count = 0; + ucell addr = 0xdeadbeef; + + if (count) { + printk("Died while dumping forth dictionary core.\n"); + goto out; + } + + count++; + + if (PC >= pointer2cell(dict) && PC <= pointer2cell(dict) + dicthead) + addr = read_cell(cell2pointer(PC)); + + printk("panic: segmentation violation at %p\n", (char *)si->si_addr); + printk("dict=%p here=%p(dict+0x%" FMT_CELL_x ") pc=0x%" FMT_CELL_x "(dict+0x%" FMT_CELL_x ")\n", + dict, dict + dicthead, dicthead, PC, PC - pointer2cell(dict)); + printk("dstackcnt=%d rstackcnt=%d instruction=%" FMT_CELL_x "\n", + dstackcnt, rstackcnt, addr); + + printdstack(); + printrstack(); + + printk("Writing dictionary core file\n"); + write_dictionary("forth.dict.core"); + + out: + exit(1); +} + +/* + * allocate memory and prepare engine for memory management. + */ + +static void init_memory(void) +{ + memset(memory, 0, MEMORY_SIZE); + + /* we push start and end of memory to the stack + * so that it can be used by the forth word QUIT + * to initialize the memory allocator. + * Add a cell to the start address so we don't end + * up with a start address of zero during bootstrap + */ + + PUSH(pointer2cell(memory)+sizeof(cell)); + PUSH(pointer2cell(memory) + MEMORY_SIZE-1); +} + + +void +include_file( const char *name ) +{ + FILE *file; + + if( cursrc >= sizeof(srcfiles)/sizeof(srcfiles[0]) ) { + printk("\npanic: Maximum include depth reached!\n"); + exit(1); + } + + file = fopen_include( name ); + if( !file ) { + printk("\npanic: Failed opening file '%s'\n", name ); + exit(1); + } +} + + +void +encode_file( const char *name ) +{ + FILE *file = fopen_include(name); + int size; + + if( !file ) { + printk("\npanic: Can't open '%s'\n", name ); + exit(1); + } + fseek( file, 0, SEEK_END ); + size = ftell( file ); + fseek( file, 0, SEEK_SET ); + + if (verbose) { + printk("\nEncoding %s [%d bytes]\n", name, size ); + } + fread( dict + dicthead, size, 1, file ); + PUSH( pointer2cell(dict + dicthead) ); + PUSH( size ); + dicthead += size; + paddict(sizeof(cell)); +} + + +static void run_dictionary(char *basedict, char *confile) +{ + if(!basedict) + return; + + read_dictionary(basedict); + PC = (ucell)findword("initialize"); + + if (!PC) { + if (verbose) { + printk("Unable to find initialize word in dictionary %s; ignoring\n", basedict); + } + return; + } + + if(!srcfiles[0]) { + cursrc = 1; + srcfiles[cursrc-1] = stdin; + } + + dstackcnt=0; + rstackcnt=0; + + init_memory(); + if (verbose) + printk("Jumping to dictionary %s...\n", basedict); + + /* If a console file has been specified, open it */ + if (confile) + console = fopen(confile, "w"); + + srcbasedict = basedict; + + enterforth((xt_t)PC); + + /* Close the console file */ + if (console) + fclose(console); +} + +static void new_dictionary(const char *source) +{ + build_dictionary(); + + interpret_source((char *)source); + + if (verbose || errors > 0) { + printk("interpretion finished. %d errors occured.\n", + errors); + } +} + +/* + * main loop + */ + +#define BANNER "OpenBIOS bootstrap kernel. (C) 2003-2006 Patrick Mauritz, Stefan Reinauer\n"\ + "This software comes with absolutely no warranty. "\ + "All rights reserved.\n\n" + +#ifdef __GLIBC__ +#define USAGE "Usage: %s [options] [dictionary file|source file]\n\n" \ + " -h|--help show this help\n" \ + " -V|--version print version and exit\n" \ + " -v|--verbose print debugging information\n" \ + " -I|--include dir add dir to include path\n" \ + " -d|--source-dictionary bootstrap.dict\n" \ + " use this dictionary as base\n" \ + " -D|--target-dictionary output.dict\n" \ + " write to output.dict\n" \ + " -c|--console output.log\n" \ + " write kernel console output to log file\n" \ + " -s|--segfault install segfault handler\n" \ + " -M|--dependency-dump file\n" \ + " dump dependencies in Makefile format\n\n" \ + " -x|--hexdump output format is C language hex dump\n" +#else +#define USAGE "Usage: %s [options] [dictionary file|source file]\n\n" \ + " -h show this help\n" \ + " -V print version and exit\n" \ + " -v print debugging information\n" \ + " -I add dir to include path\n" \ + " -d bootstrap.dict\n" \ + " use this dictionary as base\n" \ + " -D output.dict\n" \ + " write to output.dict\n" \ + " -c output.log\n" \ + " write kernel console output to log file\n" \ + " -s install segfault handler\n\n" \ + " -M file dump dependencies in Makefile format\n\n" \ + " -x output format is C language hex dump\n" +#endif + +int main(int argc, char *argv[]) +{ + struct sigaction sa; + + unsigned char *ressources=NULL; /* All memory used by us */ + const char *dictname = NULL; + char *basedict = NULL; + char *consolefile = NULL; + char *depfilename = NULL; + + unsigned char *bootstrapdict[2]; + int c, cnt, hexdump = 0; + + const char *optstring = "VvhsI:d:D:c:M:x?"; + + while (1) { +#ifdef __GLIBC__ + int option_index = 0; + static struct option long_options[] = { + {"version", 0, NULL, 'V'}, + {"verbose", 0, NULL, 'v'}, + {"help", 0, NULL, 'h'}, + {"segfault", 0, NULL, 's'}, + {"include", 1, NULL, 'I'}, + {"source-dictionary", 1, NULL, 'd'}, + {"target-dictionary", 1, NULL, 'D'}, + {"console", 1, NULL, 'c'}, + {"dependency-dump", 1, NULL, 'M'}, + {"hexdump", 0, NULL, 'x'}, + }; + + /* + * option handling + */ + + c = getopt_long(argc, argv, optstring, long_options, + &option_index); +#else + c = getopt(argc, argv, optstring); +#endif + if (c == -1) + break; + + switch (c) { + case 'V': + printk("Version " OPENBIOS_VERSION_STR "\n"); + return 0; + case 'h': + case '?': + printk("Version " OPENBIOS_VERSION_STR "\n" USAGE, + argv[0]); + return 0; + case 'v': + verbose = 1; + break; + case 's': + segfault = 1; + break; + case 'I': +#ifdef CONFIG_DEBUG_INTERPRETER + printk("adding '%s' to include path\n", optarg); +#endif + add_includepath(optarg); + break; + case 'd': + if (!basedict) { + basedict = optarg; + } + break; + case 'D': + if(!dictname) { + dictname = optarg; + } + break; + case 'c': + if (!consolefile) { + consolefile = optarg; + } + break; + case 'M': + if (!depfilename) { + depfilename = optarg; + } + break; + case 'x': + hexdump = 1; + break; + default: + return 1; + } + } + + if (!dictname) { + dictname = "bootstrap.dict"; + } + if (verbose) { + printk(BANNER); + printk("Using source dictionary '%s'\n", basedict); + printk("Dumping final dictionary to '%s'\n", dictname); + printk("Dumping dependencies to '%s'\n", depfilename); + } + + if (argc < optind) { + printk(USAGE, argv[0]); + return 1; + } + + if (depfilename) { + depfile = fopen(depfilename, "w"); + if (!depfile) { + printk("panic: can't write to dependency file '%s'.\n", + depfilename); + exit(1); + } + fprintf(depfile, "%s:", dictname); + } + + /* + * Get all required resources + */ + + + ressources = malloc(MEMORY_SIZE + (2 * DICTIONARY_SIZE) + TRAMPOLINE_SIZE); + if (!ressources) { + printk("panic: not enough memory on host system.\n"); + return 1; + } + +#ifdef NATIVE_BITWIDTH_SMALLER_THAN_HOST_BITWIDTH + base_address=(unsigned long)ressources; +#endif + + memory = (ucell *)ressources; + + bootstrapdict[0] = ressources + MEMORY_SIZE; + bootstrapdict[1] = ressources + MEMORY_SIZE + DICTIONARY_SIZE; + trampoline = (ucell *)(ressources + MEMORY_SIZE + DICTIONARY_SIZE + DICTIONARY_SIZE); + +#ifdef CONFIG_DEBUG_INTERPRETER + printf("memory: %p\n",memory); + printf("dict1: %p\n",bootstrapdict[0]); + printf("dict2: %p\n",bootstrapdict[1]); + printf("trampoline: %p\n",trampoline); + printf("size=%d, trampoline_size=%d\n",MEMORY_SIZE + (2 * + DICTIONARY_SIZE) + TRAMPOLINE_SIZE, + TRAMPOLINE_SIZE); +#endif + + if (trampoline == NULL) { + /* We're using side effects which is to some extent nasty */ + printf("WARNING: no trampoline!\n"); + } else { + init_trampoline(trampoline); + } + + if (!segfault) { + if (verbose) + printk("Installing SIGSEGV handler..."); + + sa.sa_sigaction = segv_handler; + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_SIGINFO | SA_NODEFER; + sigaction(SIGSEGV, &sa, NULL); + + if (verbose) + printk("done.\n"); + } + + /* + * Now do the real work + */ + + for (cnt=0; cnt<2; cnt++) { + if (verbose) { + printk("Compiling dictionary %d/%d\n", cnt+1, 2); + } + dict=bootstrapdict[cnt]; + if(!basedict) { + new_dictionary(argv[optind]); + } else { + for (c=argc-1; c>=optind; c--) + include_file(argv[c]); + + run_dictionary(basedict, consolefile); + } + if (depfile) { + fprintf(depfile, "\n"); + fclose(depfile); + depfile = NULL; + } + if(errors) + break; + } + +#ifndef CONFIG_DEBUG_INTERPRETER + if (errors) + printk("dictionary not dumped to file.\n"); + else +#endif + { + relocation_table( bootstrapdict[0], bootstrapdict[1], dicthead); + if (hexdump) { + write_dictionary_hex(dictname); + } else { + write_dictionary(dictname); + } + } + + free(ressources); + + if (errors) + return 1; + else + return 0; +} diff --git a/qemu/roms/openbios/kernel/build.xml b/qemu/roms/openbios/kernel/build.xml new file mode 100644 index 000000000..1090cd62e --- /dev/null +++ b/qemu/roms/openbios/kernel/build.xml @@ -0,0 +1,16 @@ +<build> + + <executable name="forthstrap" target="host"> + <object source="dict.c"/> + <object source="bootstrap.c"/> + <object source="forth.c"/> + <object source="stack.c"/> + </executable> + + <library name="bootstrap" type="static" target="target"> + <object source="dict.c"/> + <object source="forth.c"/> + <object source="stack.c"/> + </library> + +</build> diff --git a/qemu/roms/openbios/kernel/cross.h b/qemu/roms/openbios/kernel/cross.h new file mode 100644 index 000000000..9dd656f8e --- /dev/null +++ b/qemu/roms/openbios/kernel/cross.h @@ -0,0 +1,124 @@ +/* memory access abstraction layer for forth kernel + * + * Copyright (C) 2005 Stefan Reinauer + * + * See the file "COPYING" for further information about + * the copyright and warranty status of this work. + */ + +#ifndef __CROSS_H +#define __CROSS_H 1 + +/* The forthstrap compiler has to abstract the underlying dictionary + * type: big/little endian, 32/64bit. All other binaries shall use + * unchanged memory access for performance. + */ + +/* byte swapping */ + +#ifndef SWAP_ENDIANNESS + +/* trivial case - we don't have to change anything */ +#define read_ucell(addr) (*(ucell *)(addr)) +#define read_cell(addr) (*(cell *)(addr)) +#define read_long(addr) (*(u32 *)(addr)) +#define read_word(addr) (*(u16 *)(addr)) +#define read_byte(addr) (*(u8 *)(addr)) + +#define write_ucell(addr, value) {*(ucell *)(addr)=(value);} +#define write_cell(addr, value) {*(cell *)(addr)=(value);} +#define write_long(addr, value) {*(u32 *)(addr)=(value);} +#define write_word(addr, value) {*(u16 *)(addr)=(value);} +#define write_byte(addr, value) {*(u8 *)(addr)=(value);} + +#define target_ucell(x) (x) +#define target_cell(x) (x) +#define target_long(x) (x) +#define target_ulong(x) (x) + +#else /* SWAP_ENDIANNESS */ + +#define target_word(value) ( (((value)>>8)&0xff) | (((value)&0xff)<<8) ) +#define target_long(value) ( (((value)&0xff000000)>>24)|(((value)&0x00ff0000)>>8)|(((value)&0xff00)<<8)|(((value)&0xff)<<24) ) +#define target_ulong(value) (target_long(value)) + +#if BITS==32 +#define target_ucell(value) ((ucell)target_long(value)) +#define target_cell(value) ((cell)target_long(value)) +#elif BITS==64 +#define target_ucell(value) \ + ((((ucell)target_long((value) & 0xffffffff)) << 32) | \ + ((ucell)target_long((value) >> 32))) +#define target_cell(value) \ + ((((cell)target_long((value) & 0xffffffff)) << 32) | \ + ((cell)target_long((value) >> 32))) +#else +#error "Endianness not supported. Please report." +#endif + +#define read_ucell(addr) target_ucell(*(ucell *)(addr)) +#define read_cell(addr) target_cell(*(cell *)(addr)) +#define read_long(addr) target_long(*(u32 *)(addr)) +#define read_word(addr) target_word(*(u16 *)(addr)) +#define read_byte(addr) (*(u8 *)(addr)) + +#define write_ucell(addr, value) {*(ucell *)(addr)=target_ucell(value);} +#define write_cell(addr, value) {*(cell *)(addr)=target_cell(value);} +#define write_long(addr, value) {*(u32 *)(addr)=target_long(value);} +#define write_word(addr, value) {*(u16 *)(addr)=target_word(value);} +#define write_byte(addr, value) {*(u8 *)(addr)=(value);} +#endif + +#ifdef CONFIG_LITTLE_ENDIAN +#define unaligned_read_word(addr) \ + (read_byte(addr)|(read_byte((u8 *)addr+1)<<8)) + +#define unaligned_read_long(addr) \ + (unaligned_read_word(addr)|(unaligned_read_word((u8 *)addr+2)<<16)) + +#define unaligned_write_word(addr, value) \ + write_byte(addr, (value & 0xff)); write_byte((u8 *)(addr+1), (value>>8)) + +#define unaligned_write_long(addr, value) \ + unaligned_write_word(addr, (value & 0xffff)); \ + unaligned_write_word((addr + 2), (value >> 16)) + +#endif + +#ifdef CONFIG_BIG_ENDIAN +#define unaligned_read_word(addr) \ + ((read_byte(addr)<<8)|read_byte((u8 *)addr+1)) + +#define unaligned_read_long(addr) \ + ((unaligned_read_word(addr)<<16)|unaligned_read_word((u8 *)addr+2)) + +#define unaligned_write_word(addr, value) \ + write_byte(addr, (value >> 8)); write_byte((u8 *)(addr+1), (value & 0xff)) + +#define unaligned_write_long(addr, value) \ + unaligned_write_word(addr, (value >> 16)); \ + unaligned_write_word((addr + 2), (value & 0xffff)) +#endif + +/* bit width handling */ + +#if BITS==32 +#define FMT_CELL_x PRIx32 +#define FMT_CELL_d PRId32 +#else +#define FMT_CELL_x PRIx64 +#define FMT_CELL_d PRId64 +#endif + +#ifdef NATIVE_BITWIDTH_SMALLER_THAN_HOST_BITWIDTH +extern unsigned long base_address; +#define pointer2cell(x) ((ucell)(((unsigned long)(x))-base_address)) +#define cell2pointer(x) ((u8 *)(((unsigned long)(x))+base_address)) +#endif + +#ifdef NATIVE_BITWIDTH_LARGER_THAN_HOST_BITWIDTH +#define pointer2cell(x) ((ucell)(unsigned long)(x)) +#define cell2pointer(x) ((u8 *)((unsigned long)(x)&0xFFFFFFFFUL)) +#endif + +#endif diff --git a/qemu/roms/openbios/kernel/dict.c b/qemu/roms/openbios/kernel/dict.c new file mode 100644 index 000000000..0986cb14f --- /dev/null +++ b/qemu/roms/openbios/kernel/dict.c @@ -0,0 +1,320 @@ +/* + * tag: dict management + * + * Copyright (C) 2003-2005 Stefan Reinauer, Patrick Mauritz + * + * See the file "COPYING" for further information about + * the copyright and warranty status of this work. + */ + +#include "config.h" +#include "kernel/kernel.h" +#include "dict.h" +#ifdef BOOTSTRAP +#include <string.h> +#else +#include "libc/string.h" +#endif +#include "cross.h" + + +unsigned char *dict = NULL; +ucell *last; +cell dicthead = 0; +cell dictlimit = 0; + +/* lfa2nfa + * converts a link field address to a name field address, + * i.e find pointer to a given words name + */ + +ucell lfa2nfa(ucell ilfa) +{ + /* get offset from dictionary start */ + ilfa = ilfa - (ucell)pointer2cell(dict); + ilfa--; /* skip status */ + while (dict[--ilfa] == 0); /* skip all pad bytes */ + ilfa -= (dict[ilfa] - 128); + return ilfa + (ucell)pointer2cell(dict); +} + +/* lfa2cfa + * converts a link field address to a code field address. + * in this forth implementation this is just a fixed offset + */ + +static xt_t lfa2cfa(ucell ilfa) +{ + return (xt_t)(ilfa + sizeof(cell)); +} + + +/* fstrlen - returns length of a forth string. */ + +ucell fstrlen(ucell fstr) +{ + fstr -= pointer2cell(dict)+1; + //fstr -= pointer2cell(dict); FIXME + while (dict[++fstr] < 128) + ; + return dict[fstr] - 128; +} + +/* to_lower - convert a character to lowecase */ + +static int to_lower(int c) +{ + return ((c >= 'A') && (c <= 'Z')) ? (c - 'A' + 'a') : c; +} + +/* fstrcmp - compare null terminated string with forth string. */ + +static int fstrcmp(const char *s1, ucell fstr) +{ + char *s2 = (char*)cell2pointer(fstr); + while (*s1) { + if ( to_lower(*(s1++)) != to_lower(*(s2++)) ) + return -1; + } + return 0; +} + +/* fstrncpy - copy a forth string to a destination (with NULL termination) */ + +void fstrncpy(char *dest, ucell src, unsigned int maxlen) +{ + int len = fstrlen(src); + + if (fstrlen(src) >= maxlen) len = maxlen - 1; + memcpy(dest, cell2pointer(src), len); + *(dest + len) = '\0'; +} + + +/* findword + * looks up a given word in the dictionary. This function + * is used by the c based interpreter and to find the "initialize" + * word. + */ + +xt_t findword(const char *s1) +{ + ucell tmplfa, len; + + if (!last) + return 0; + + tmplfa = read_ucell(last); + + len = strlen(s1); + + while (tmplfa) { + ucell nfa = lfa2nfa(tmplfa); + + if (len == fstrlen(nfa) && !fstrcmp(s1, nfa)) { + return lfa2cfa(tmplfa); + } + + tmplfa = read_ucell(cell2pointer(tmplfa)); + } + + return 0; +} + + +/* findsemis_wordlist + * Given a DOCOL xt and a wordlist, find the address of the semis + * word at the end of the word definition. We do this by finding + * the word before this in the dictionary, then counting back one + * from the NFA. + */ + +static ucell findsemis_wordlist(ucell xt, ucell wordlist) +{ + ucell tmplfa, nextlfa, nextcfa; + + if (!wordlist) + return 0; + + tmplfa = read_ucell(cell2pointer(wordlist)); + nextcfa = lfa2cfa(tmplfa); + + /* Catch the special case where the lfa of the word we + * want is the last word in the dictionary; in that case + * the end of the word is given by "here" - 1 */ + if (nextcfa == xt) + return pointer2cell(dict) + dicthead - sizeof(cell); + + while (tmplfa) { + + /* Peek ahead and see if the next CFA in the list is the + * one we are searching for */ + nextlfa = read_ucell(cell2pointer(tmplfa)); + nextcfa = lfa2cfa(nextlfa); + + /* If so, count back 1 cell from the current NFA */ + if (nextcfa == xt) + return lfa2nfa(tmplfa) - sizeof(cell); + + tmplfa = nextlfa; + } + + return 0; +} + + +/* findsemis + * Given a DOCOL xt, find the address of the semis word at the end + * of the word definition by searching all vocabularies */ + +ucell findsemis(ucell xt) +{ + ucell usesvocab = findword("vocabularies?") + sizeof(cell); + unsigned int i; + + if (read_ucell(cell2pointer(usesvocab))) { + /* Vocabularies are in use, so search each one in turn */ + ucell numvocabs = findword("#order") + sizeof(cell); + + for (i = 0; i < read_ucell(cell2pointer(numvocabs)); i++) { + ucell vocabs = findword("vocabularies") + 2 * sizeof(cell); + ucell semis = findsemis_wordlist(xt, read_cell(cell2pointer(vocabs + (i * sizeof(cell))))); + + /* If we get a non-zero result, we found the xt in this vocab */ + if (semis) + return semis; + } + } else { + /* Vocabularies not in use */ + return findsemis_wordlist(xt, read_ucell(last)); + } + + return 0; +} + + +/* findxtfromcell_wordlist + * Given a cell and a wordlist, determine the CFA of the word containing + * the cell or 0 if we are unable to return a suitable CFA + */ + +ucell findxtfromcell_wordlist(ucell incell, ucell wordlist) +{ + ucell tmplfa; + + if (!wordlist) + return 0; + + tmplfa = read_ucell(cell2pointer(wordlist)); + while (tmplfa) { + if (tmplfa < incell) + return lfa2cfa(tmplfa); + + tmplfa = read_ucell(cell2pointer(tmplfa)); + } + + return 0; +} + + +/* findxtfromcell + * Given a cell, determine the CFA of the word containing + * the cell by searching all vocabularies + */ + +ucell findxtfromcell(ucell incell) +{ + ucell usesvocab = findword("vocabularies?") + sizeof(cell); + unsigned int i; + + if (read_ucell(cell2pointer(usesvocab))) { + /* Vocabularies are in use, so search each one in turn */ + ucell numvocabs = findword("#order") + sizeof(cell); + + for (i = 0; i < read_ucell(cell2pointer(numvocabs)); i++) { + ucell vocabs = findword("vocabularies") + 2 * sizeof(cell); + ucell semis = findxtfromcell_wordlist(incell, read_cell(cell2pointer(vocabs + (i * sizeof(cell))))); + + /* If we get a non-zero result, we found the xt in this vocab */ + if (semis) + return semis; + } + } else { + /* Vocabularies not in use */ + return findxtfromcell_wordlist(incell, read_ucell(last)); + } + + return 0; +} + +void dump_header(dictionary_header_t *header) +{ + printk("OpenBIOS dictionary:\n"); + printk(" version: %d\n", header->version); + printk(" cellsize: %d\n", header->cellsize); + printk(" endianess: %s\n", header->endianess?"big":"little"); + printk(" compression: %s\n", header->compression?"yes":"no"); + printk(" relocation: %s\n", header->relocation?"yes":"no"); + printk(" checksum: %08x\n", target_long(header->checksum)); + printk(" length: %08x\n", target_long(header->length)); + printk(" last: %0" FMT_CELL_x "\n", target_cell(header->last)); +} + +ucell load_dictionary(const char *data, ucell len) +{ + u32 checksum=0; + const char *checksum_walk; + ucell *walk, *reloc_table; + dictionary_header_t *header=(dictionary_header_t *)data; + + /* assertions */ + if (len <= (sizeof(dictionary_header_t)) || strncmp(DICTID, data, 8)) + return 0; +#ifdef CONFIG_DEBUG_DICTIONARY + dump_header(header); +#endif + + checksum_walk=data; + while (checksum_walk<data+len) { + checksum+=read_long(checksum_walk); + checksum_walk+=sizeof(u32); + } + + if(checksum) { + printk("Checksum invalid (%08x)!\n", checksum); + return 0; + } + + data += sizeof(dictionary_header_t); + + dicthead = target_long(header->length); + + memcpy(dict, data, dicthead); + reloc_table=(ucell *)(data+dicthead); + +#ifdef CONFIG_DEBUG_DICTIONARY + printk("\nmoving dictionary (%x bytes) to %x\n", + (ucell)dicthead, (ucell)dict); + printk("\ndynamic relocation..."); +#endif + + for (walk = (ucell *) dict; walk < (ucell *) (dict + dicthead); + walk++) { + int pos, bit, l; + l=(walk-(ucell *)dict); + pos=l/BITS; + bit=l&~(-BITS); + if (reloc_table[pos] & target_ucell((ucell)1ULL << bit)) { + // printk("%lx, pos %x, bit %d\n",*walk, pos, bit); + write_ucell(walk, read_ucell(walk)+pointer2cell(dict)); + } + } + +#ifdef CONFIG_DEBUG_DICTIONARY + printk(" done.\n"); +#endif + + last = (ucell *)(dict + target_ucell(header->last)); + + return -1; +} diff --git a/qemu/roms/openbios/kernel/forth.c b/qemu/roms/openbios/kernel/forth.c new file mode 100644 index 000000000..61dd70d31 --- /dev/null +++ b/qemu/roms/openbios/kernel/forth.c @@ -0,0 +1,1966 @@ +/* tag: C implementation of all forth primitives, + * internal words, inner interpreter and such + * + * Copyright (C) 2003 Patrick Mauritz, Stefan Reinauer + * + * See the file "COPYING" for further information about + * the copyright and warranty status of this work. + */ + +#include "config.h" +#include "sysinclude.h" +#include "kernel/stack.h" +#include "kernel/kernel.h" +#include "dict.h" + +/* + * cross platform abstraction + */ + +#include "cross.h" + +#ifndef FCOMPILER +#include "libc/vsprintf.h" +#else +#include <stdarg.h> +#endif + +/* + * execution works as follows: + * - PC is pushed on return stack + * - PC is set to new CFA + * - address pointed by CFA is executed by CPU + */ + +typedef void forth_word(void); + +static forth_word * const words[]; +ucell PC; +volatile int interruptforth = 0; + +#define DEBUG_MODE_NONE 0 +#define DEBUG_MODE_STEP 1 +#define DEBUG_MODE_TRACE 2 +#define DEBUG_MODE_STEPUP 3 + +#define DEBUG_BANNER "\nStepper keys: <space>/<enter> Up Down Trace Rstack Forth\n" + +/* Empty linked list of debug xts */ +struct debug_xt { + ucell xt_docol; + ucell xt_semis; + int mode; + struct debug_xt *next; +}; + +static struct debug_xt debug_xt_eol = { (ucell)0, (ucell)0, 0, NULL}; +static struct debug_xt *debug_xt_list = &debug_xt_eol; + +/* Static buffer for xt name */ +char xtname[MAXNFALEN]; + +#ifndef FCOMPILER +/* instead of pointing to an explicit 0 variable we + * point behind the pointer. + */ +static ucell t[] = { 0, 0, 0, 0 }; +static ucell *trampoline = t; + +/* + * Code Field Address (CFA) definitions (DOCOL and the like) + */ + +void forth_init(void) +{ + init_trampoline(trampoline); +} +#endif + +#ifndef CONFIG_DEBUG_INTERPRETER +#define dbg_interp_printk( a... ) do { } while(0) +#else +#define dbg_interp_printk( a... ) printk( a ) +#endif + +#ifndef CONFIG_DEBUG_INTERNAL +#define dbg_internal_printk( a... ) do { } while(0) +#else +#define dbg_internal_printk( a... ) printk( a ) +#endif + + +void init_trampoline(ucell *tramp) +{ + tramp[0] = DOCOL; + tramp[1] = 0; + tramp[2] = target_ucell(pointer2cell(tramp) + 3 * sizeof(ucell)); + tramp[3] = 0; +} + +static inline void processxt(ucell xt) +{ + void (*tokenp) (void); + + dbg_interp_printk("processxt: pc=%x, xt=%x\n", PC, xt); + tokenp = words[xt]; + tokenp(); +} + +static void docol(void) +{ /* DOCOL */ + PUSHR(PC); + PC = read_ucell(cell2pointer(PC)); + + dbg_interp_printk("docol: %s\n", cell2pointer( lfa2nfa(PC - sizeof(cell)) )); +} + +static void semis(void) +{ + PC = POPR(); +} + +static inline void next(void) +{ + PC += sizeof(ucell); + + dbg_interp_printk("next: PC is now %x\n", PC); + processxt(read_ucell(cell2pointer(read_ucell(cell2pointer(PC))))); +} + +static inline void next_dbg(void); + +int enterforth(xt_t xt) +{ + ucell *_cfa = (ucell*)cell2pointer(xt); + cell tmp; + + if (read_ucell(_cfa) != DOCOL) { + trampoline[1] = target_ucell(xt); + _cfa = trampoline; + } + + if (rstackcnt < 0) { + rstackcnt = 0; + } + + tmp = rstackcnt; + interruptforth = FORTH_INTSTAT_CLR; + + PUSHR(PC); + PC = pointer2cell(_cfa); + + while (rstackcnt > tmp && !(interruptforth & FORTH_INTSTAT_STOP)) { + if (debug_xt_list->next == NULL) { + while (rstackcnt > tmp && !interruptforth) { + dbg_interp_printk("enterforth: NEXT\n"); + next(); + } + } else { + while (rstackcnt > tmp && !interruptforth) { + dbg_interp_printk("enterforth: NEXT_DBG\n"); + next_dbg(); + } + } + + /* Always clear the debug mode change flag */ + interruptforth = interruptforth & (~FORTH_INTSTAT_DBG); + } + +#if 0 + /* return true if we took an exception. The caller should normally + * handle exceptions by returning immediately since the throw + * is supposed to abort the execution of this C-code too. + */ + + if (rstackcnt != tmp) { + printk("EXCEPTION DETECTED!\n"); + } +#endif + return rstackcnt != tmp; +} + +/* called inline thus a slightly different behaviour */ +static void lit(void) +{ /* LIT */ + PC += sizeof(cell); + PUSH(read_ucell(cell2pointer(PC))); + dbg_interp_printk("lit: %x\n", read_ucell(cell2pointer(PC))); +} + +static void docon(void) +{ /* DOCON */ + ucell tmp = read_ucell(cell2pointer(read_ucell(cell2pointer(PC)) + sizeof(ucell))); + PUSH(tmp); + dbg_interp_printk("docon: PC=%x, value=%x\n", PC, tmp); +} + +static void dovar(void) +{ /* DOVAR */ + ucell tmp = read_ucell(cell2pointer(PC)) + sizeof(ucell); + PUSH(tmp); /* returns address to variable */ + dbg_interp_printk("dovar: PC: %x, %x\n", PC, tmp); +} + +static void dobranch(void) +{ /* unconditional branch */ + PC += sizeof(cell); + PC += read_cell(cell2pointer(PC)); +} + +static void docbranch(void) +{ /* conditional branch */ + PC += sizeof(cell); + if (POP()) { + dbg_internal_printk(" ?branch: end loop\n"); + } else { + dbg_internal_printk(" ?branch: follow branch\n"); + PC += read_cell(cell2pointer(PC)); + } +} + + +static void execute(void) +{ /* EXECUTE */ + ucell address = POP(); + dbg_interp_printk("execute: %x\n", address); + + PUSHR(PC); + trampoline[1] = target_ucell(address); + PC = pointer2cell(trampoline); +} + +/* + * call ( ... function-ptr -- ??? ) + */ +static void call(void) +{ +#ifdef FCOMPILER + printk("Sorry. Usage of Forth2C binding is forbidden during bootstrap.\n"); + exit(1); +#else + void (*funcptr) (void); + funcptr=(void *)cell2pointer(POP()); + dbg_interp_printk("call: %x", funcptr); + funcptr(); +#endif +} + +/* + * sys-debug ( errno -- ) + */ + +static void sysdebug(void) +{ +#ifdef FCOMPILER + cell errorno=POP(); + exception(errorno); +#else + (void) POP(); +#endif +} + +static void dodoes(void) +{ /* DODOES */ + ucell data = read_ucell(cell2pointer(PC)) + (2 * sizeof(ucell)); + ucell word = read_ucell(cell2pointer(read_ucell(cell2pointer(PC)) + sizeof(ucell))); + + dbg_interp_printk("DODOES data=%x word=%x\n", data, word); + + PUSH(data); + PUSH(word); + + execute(); +} + +static void dodefer(void) +{ + docol(); +} + +static void dodo(void) +{ + cell startval, endval; + startval = POP(); + endval = POP(); + + PUSHR(endval); + PUSHR(startval); +} + +static void doisdo(void) +{ + cell startval, endval, offset; + + startval = POP(); + endval = POP(); + + PC += sizeof(cell); + + if (startval == endval) { + offset = read_cell(cell2pointer(PC)); + PC += offset; + } else { + PUSHR(endval); + PUSHR(startval); + } +} + +static void doloop(void) +{ + cell offset, startval, endval; + + startval = POPR() + 1; + endval = POPR(); + + PC += sizeof(cell); + + if (startval < endval) { + offset = read_cell(cell2pointer(PC)); + PC += offset; + PUSHR(endval); + PUSHR(startval); + } + +} + +static void doplusloop(void) +{ + ucell high, low; + cell increment, startval, endval, offset; + + increment = POP(); + + startval = POPR(); + endval = POPR(); + + low = (ucell) startval; + startval += increment; + + PC += sizeof(cell); + + if (increment >= 0) { + high = (ucell) startval; + } else { + high = low; + low = (ucell) startval; + } + + if (endval - (low + 1) >= high - low) { + offset = read_cell(cell2pointer(PC)); + PC += offset; + + PUSHR(endval); + PUSHR(startval); + } +} + +/* + * instance handling CFAs + */ +#ifndef FCOMPILER +static ucell get_myself(void) +{ + static ucell *myselfptr = NULL; + if (myselfptr == NULL) { + myselfptr = (ucell*)cell2pointer(findword("my-self")) + 1; + } + ucell *myself = (ucell*)cell2pointer(*myselfptr); + return (myself != NULL) ? *myself : 0; +} + +static void doivar(void) +{ + ucell r, *p = (ucell *)(*(ucell *) cell2pointer(PC) + sizeof(ucell)); + ucell ibase = get_myself(); + + dbg_interp_printk("ivar, offset: %d size: %d (ibase %d)\n", p[0], p[1], ibase ); + + r = ibase ? ibase + p[0] : pointer2cell(&p[2]); + PUSH( r ); +} + +static void doival(void) +{ + ucell r, *p = (ucell *)(*(ucell *) cell2pointer(PC) + sizeof(ucell)); + ucell ibase = get_myself(); + + dbg_interp_printk("ivar, offset: %d size: %d\n", p[0], p[1] ); + + r = ibase ? ibase + p[0] : pointer2cell(&p[2]); + PUSH( *(ucell *)cell2pointer(r) ); +} + +static void doidefer(void) +{ + ucell *p = (ucell *)(*(ucell *) cell2pointer(PC) + sizeof(ucell)); + ucell ibase = get_myself(); + + dbg_interp_printk("doidefer, offset: %d size: %d\n", p[0], p[1] ); + + PUSHR(PC); + PC = ibase ? ibase + p[0] : pointer2cell(&p[2]); + PC -= sizeof(ucell); +} +#else +static void noinstances(void) +{ + printk("Opening devices is not supported during bootstrap. Sorry.\n"); + exit(1); +} +#define doivar noinstances +#define doival noinstances +#define doidefer noinstances +#endif + +/* + * $include / $encode-file + */ +#ifdef FCOMPILER +static void +string_relay(void (*func)(const char *)) +{ + int len = POP(); + char *name, *p = (char*)cell2pointer(POP()); + name = malloc(len + 1); + memcpy(name, p, len); + name[len] = 0; + (*func)(name); + free(name); +} +#else +#define string_relay(dummy) do { DROP(); DROP(); } while(0) +#endif + +static void +do_include(void) +{ + string_relay(&include_file); +} + +static void +do_encode_file( void ) +{ + string_relay(&encode_file); +} + +/* + * Debug support functions + */ + +static +int printf_console(const char *fmt, ...) +{ + cell tmp; + + char buf[512]; + va_list args; + int i; + + va_start(args, fmt); + i = vsnprintf(buf, sizeof(buf), fmt, args); + va_end(args); + + /* Push to the Forth interpreter for console output */ + tmp = rstackcnt; + + PUSH(pointer2cell(buf)); + PUSH((int)strlen(buf)); + trampoline[1] = findword("type"); + + PUSHR(PC); + PC = pointer2cell(trampoline); + + while (rstackcnt > tmp) { + dbg_interp_printk("printf_console: NEXT\n"); + next(); + } + + return i; +} + +static +int getchar_console(void) +{ + cell tmp; + + /* Push to the Forth interpreter for console output */ + tmp = rstackcnt; + + trampoline[1] = findword("key"); + + PUSHR(PC); + PC = pointer2cell(trampoline); + + while (rstackcnt > tmp) { + dbg_interp_printk("getchar_console: NEXT\n"); + next(); + } + + return POP(); +} + +static void +display_dbg_dstack(void) +{ + /* Display dstack contents between parentheses */ + int i; + + if (dstackcnt == 0) { + printf_console(" ( Empty ) "); + return; + } else { + printf_console(" ( "); + for (i = 1; i <= dstackcnt; i++) { + if (i != 1) { + printf_console(" "); + } + printf_console("%" FMT_CELL_x, dstack[i]); + } + printf_console(" ) "); + } +} + +static void +display_dbg_rstack(void) +{ + /* Display rstack contents between parentheses */ + int i; + + if (rstackcnt == 0) { + printf_console(" ( Empty ) "); + return; + } else { + printf_console("\nR: ( "); + for (i = 1; i <= rstackcnt; i++) { + if (i != 1) { + printf_console(" "); + } + printf_console("%" FMT_CELL_x, rstack[i]); + } + printf_console(" ) \n"); + } +} + +static int +add_debug_xt(ucell xt) +{ + struct debug_xt *debug_xt_item; + + /* If the xt CFA isn't DOCOL then issue a warning and do nothing */ + if (read_ucell(cell2pointer(xt)) != DOCOL) { + printf_console("\nprimitive words cannot be debugged\n"); + return 0; + } + + /* If this xt is already in the list, do nothing but indicate success */ + for (debug_xt_item = debug_xt_list; debug_xt_item->next != NULL; + debug_xt_item = debug_xt_item->next) + if (debug_xt_item->xt_docol == xt) { + return 1; + } + + /* We already have the CFA (PC) indicating the starting cell of + the word, however we also need the ending cell too (we cannot + rely on the rstack as it can be arbitrarily changed by a forth + word). Hence the use of findsemis() */ + + /* Otherwise add to the head of the linked list */ + debug_xt_item = malloc(sizeof(struct debug_xt)); + debug_xt_item->xt_docol = xt; + debug_xt_item->xt_semis = findsemis(xt); + debug_xt_item->mode = DEBUG_MODE_NONE; + debug_xt_item->next = debug_xt_list; + debug_xt_list = debug_xt_item; + + /* Indicate debug mode change */ + interruptforth |= FORTH_INTSTAT_DBG; + + /* Success */ + return 1; +} + +static void +del_debug_xt(ucell xt) +{ + struct debug_xt *debug_xt_item, *tmp_xt_item; + + /* Handle the case where the xt is at the head of the list */ + if (debug_xt_list->xt_docol == xt) { + tmp_xt_item = debug_xt_list; + debug_xt_list = debug_xt_list->next; + free(tmp_xt_item); + + return; + } + + /* Otherwise find this xt in the linked list and remove it */ + for (debug_xt_item = debug_xt_list; debug_xt_item->next != NULL; + debug_xt_item = debug_xt_item->next) { + if (debug_xt_item->next->xt_docol == xt) { + tmp_xt_item = debug_xt_item->next; + debug_xt_item->next = debug_xt_item->next->next; + free(tmp_xt_item); + } + } + + /* If the list is now empty, indicate debug mode change */ + if (debug_xt_list->next == NULL) { + interruptforth |= FORTH_INTSTAT_DBG; + } +} + +static void +do_source_dbg(struct debug_xt *debug_xt_item) +{ + /* Forth source debugger implementation */ + char k, done = 0; + + /* Display current dstack */ + display_dbg_dstack(); + printf_console("\n"); + + fstrncpy(xtname, lfa2nfa(read_ucell(cell2pointer(PC)) - sizeof(cell)), MAXNFALEN); + printf_console("%p: %s ", cell2pointer(PC), xtname); + + /* If in trace mode, we just carry on */ + if (debug_xt_item->mode == DEBUG_MODE_TRACE) { + return; + } + + /* Otherwise in step mode, prompt for a keypress */ + k = getchar_console(); + + /* Only proceed if done is true */ + while (!done) { + switch (k) { + + case ' ': + case '\n': + /* Perform a single step */ + done = 1; + break; + + case 'u': + case 'U': + /* Up - unmark current word for debug, mark its caller for + * debugging and finish executing current word */ + + /* Since this word could alter the rstack during its execution, + * we only know the caller when (semis) is called for this xt. + * Hence we mark the xt as a special DEBUG_MODE_STEPUP which + * means we run as normal, but schedule the xt for deletion + * at its corresponding (semis) word when we know the rstack + * will be set to its final parent value */ + debug_xt_item->mode = DEBUG_MODE_STEPUP; + done = 1; + break; + + case 'd': + case 'D': + /* Down - mark current word for debug and step into it */ + done = add_debug_xt(read_ucell(cell2pointer(PC))); + if (!done) { + k = getchar_console(); + } + break; + + case 't': + case 'T': + /* Trace mode */ + debug_xt_item->mode = DEBUG_MODE_TRACE; + done = 1; + break; + + case 'r': + case 'R': + /* Display rstack */ + display_dbg_rstack(); + done = 0; + k = getchar_console(); + break; + + case 'f': + case 'F': + /* Start subordinate Forth interpreter */ + PUSHR(PC - sizeof(cell)); + PC = findword("outer-interpreter") + sizeof(ucell); + + /* Save rstack position for when we return */ + dbgrstackcnt = rstackcnt; + done = 1; + break; + + default: + /* Display debug banner */ + printf_console(DEBUG_BANNER); + k = getchar_console(); + } + } +} + +static void docol_dbg(void) +{ /* DOCOL */ + struct debug_xt *debug_xt_item; + + PUSHR(PC); + PC = read_ucell(cell2pointer(PC)); + + /* If current xt is in our debug xt list, display word name */ + debug_xt_item = debug_xt_list; + while (debug_xt_item->next) { + if (debug_xt_item->xt_docol == PC) { + fstrncpy(xtname, lfa2nfa(PC - sizeof(cell)), MAXNFALEN); + printf_console("\n: %s ", xtname); + + /* Step mode is the default */ + debug_xt_item->mode = DEBUG_MODE_STEP; + } + + debug_xt_item = debug_xt_item->next; + } + + dbg_interp_printk("docol_dbg: %s\n", cell2pointer(lfa2nfa(PC - sizeof(cell)))); +} + +static void semis_dbg(void) +{ + struct debug_xt *debug_xt_item, *debug_xt_up = NULL; + + /* If current semis is in our debug xt list, disable debug mode */ + debug_xt_item = debug_xt_list; + while (debug_xt_item->next) { + if (debug_xt_item->xt_semis == PC) { + if (debug_xt_item->mode != DEBUG_MODE_STEPUP) { + /* Handle the normal case */ + fstrncpy(xtname, lfa2nfa(debug_xt_item->xt_docol - sizeof(cell)), MAXNFALEN); + printf_console("\n[ Finished %s ] ", xtname); + + /* Reset to step mode in case we were in trace mode */ + debug_xt_item->mode = DEBUG_MODE_STEP; + } else { + /* This word requires execution of the debugger "Up" + * semantics. However we can't do this here since we + * are iterating through the debug list, and we need + * to change it. So we do it afterwards. + */ + debug_xt_up = debug_xt_item; + } + } + + debug_xt_item = debug_xt_item->next; + } + + /* Execute debugger "Up" semantics if required */ + if (debug_xt_up) { + /* Only add the parent word if it is not within the trampoline */ + if (rstack[rstackcnt] != (cell)pointer2cell(&trampoline[1])) { + del_debug_xt(debug_xt_up->xt_docol); + add_debug_xt(findxtfromcell(rstack[rstackcnt])); + + fstrncpy(xtname, lfa2nfa(findxtfromcell(rstack[rstackcnt]) - sizeof(cell)), MAXNFALEN); + printf_console("\n[ Up to %s ] ", xtname); + } else { + fstrncpy(xtname, lfa2nfa(findxtfromcell(debug_xt_up->xt_docol) - sizeof(cell)), MAXNFALEN); + printf_console("\n[ Finished %s (Unable to go up, hit trampoline) ] ", xtname); + + del_debug_xt(debug_xt_up->xt_docol); + } + + debug_xt_up = NULL; + } + + PC = POPR(); +} + +static inline void next_dbg(void) +{ + struct debug_xt *debug_xt_item; + void (*tokenp) (void); + + PC += sizeof(ucell); + + /* If the PC lies within a debug range, run the source debugger */ + debug_xt_item = debug_xt_list; + while (debug_xt_item->next) { + if (PC >= debug_xt_item->xt_docol && PC <= debug_xt_item->xt_semis && + debug_xt_item->mode != DEBUG_MODE_STEPUP) { + do_source_dbg(debug_xt_item); + } + + debug_xt_item = debug_xt_item->next; + } + + dbg_interp_printk("next_dbg: PC is now %x\n", PC); + + /* Intercept DOCOL and SEMIS and redirect to debug versions */ + if (read_ucell(cell2pointer(read_ucell(cell2pointer(PC)))) == DOCOL) { + tokenp = docol_dbg; + tokenp(); + } else if (read_ucell(cell2pointer(read_ucell(cell2pointer(PC)))) == DOSEMIS) { + tokenp = semis_dbg; + tokenp(); + } else { + /* Otherwise process as normal */ + processxt(read_ucell(cell2pointer(read_ucell(cell2pointer(PC))))); + } +} + +static void +do_debug_xt(void) +{ + ucell xt = POP(); + + /* Add to the debug list */ + if (add_debug_xt(xt)) { + /* Display debug banner */ + printf_console(DEBUG_BANNER); + + /* Indicate change to debug mode */ + interruptforth |= FORTH_INTSTAT_DBG; + } +} + +static void +do_debug_off(void) +{ + /* Empty the debug xt linked list */ + while (debug_xt_list->next != NULL) { + del_debug_xt(debug_xt_list->xt_docol); + } +} + +/* + * Forth primitives needed to set up + * all the words described in IEEE1275-1994. + */ + +/* + * dup ( x -- x x ) + */ + +static void fdup(void) +{ + const cell tmp = GETTOS(); + PUSH(tmp); +} + + +/* + * 2dup ( x1 x2 -- x1 x2 x1 x2 ) + */ + +static void twodup(void) +{ + cell tmp = GETITEM(1); + PUSH(tmp); + tmp = GETITEM(1); + PUSH(tmp); +} + + +/* + * ?dup ( x -- 0 | x x ) + */ + +static void isdup(void) +{ + const cell tmp = GETTOS(); + if (tmp) + PUSH(tmp); +} + + +/* + * over ( x y -- x y x ) + */ + +static void over(void) +{ + const cell tmp = GETITEM(1); + PUSH(tmp); +} + + +/* + * 2over ( x1 x2 x3 x4 -- x1 x2 x3 x4 x1 x2 ) + */ + +static void twoover(void) +{ + const cell tmp = GETITEM(3); + const cell tmp2 = GETITEM(2); + PUSH(tmp); + PUSH(tmp2); +} + +/* + * pick ( xu ... x1 x0 u -- xu ... x1 x0 xu ) + */ + +static void pick(void) +{ + const cell u = POP(); + if (dstackcnt >= u) { + ucell tmp = dstack[dstackcnt - u]; + PUSH(tmp); + } else { + /* underrun */ + } +} + + +/* + * drop ( x -- ) + */ + +static void drop(void) +{ + POP(); +} + +/* + * 2drop ( x1 x2 -- ) + */ + +static void twodrop(void) +{ + POP(); + POP(); +} + + +/* + * nip ( x1 x2 -- x2 ) + */ + +static void nip(void) +{ + const cell tmp = POP(); + POP(); + PUSH(tmp); +} + + +/* + * roll ( xu ... x1 x0 u -- xu-1... x1 x0 xu ) + */ + +static void roll(void) +{ + const cell u = POP(); + if (dstackcnt >= u) { + int i; + const cell xu = dstack[dstackcnt - u]; + for (i = dstackcnt - u; i < dstackcnt; i++) { + dstack[i] = dstack[i + 1]; + } + dstack[dstackcnt] = xu; + } else { + /* Stack underrun */ + } +} + + +/* + * rot ( x1 x2 x3 -- x2 x3 x1 ) + */ + +static void rot(void) +{ + const cell tmp = POP(); + const cell tmp2 = POP(); + const cell tmp3 = POP(); + PUSH(tmp2); + PUSH(tmp); + PUSH(tmp3); +} + + +/* + * -rot ( x1 x2 x3 -- x3 x1 x2 ) + */ + +static void minusrot(void) +{ + const cell tmp = POP(); + const cell tmp2 = POP(); + const cell tmp3 = POP(); + PUSH(tmp); + PUSH(tmp3); + PUSH(tmp2); +} + + +/* + * swap ( x1 x2 -- x2 x1 ) + */ + +static void swap(void) +{ + const cell tmp = POP(); + const cell tmp2 = POP(); + PUSH(tmp); + PUSH(tmp2); +} + + +/* + * 2swap ( x1 x2 x3 x4 -- x3 x4 x1 x2 ) + */ + +static void twoswap(void) +{ + const cell tmp = POP(); + const cell tmp2 = POP(); + const cell tmp3 = POP(); + const cell tmp4 = POP(); + PUSH(tmp2); + PUSH(tmp); + PUSH(tmp4); + PUSH(tmp3); +} + + +/* + * >r ( x -- ) (R: -- x ) + */ + +static void tor(void) +{ + ucell tmp = POP(); +#ifdef CONFIG_DEBUG_RSTACK + printk(" >R: %x\n", tmp); +#endif + PUSHR(tmp); +} + + +/* + * r> ( -- x ) (R: x -- ) + */ + +static void rto(void) +{ + ucell tmp = POPR(); +#ifdef CONFIG_DEBUG_RSTACK + printk(" R>: %x\n", tmp); +#endif + PUSH(tmp); +} + + +/* + * r@ ( -- x ) (R: x -- x ) + */ + +static void rfetch(void) +{ + PUSH(GETTORS()); +} + + +/* + * depth ( -- u ) + */ + +static void depth(void) +{ + const cell tmp = dstackcnt; + PUSH(tmp); +} + + +/* + * depth! ( ... u -- x1 x2 .. xu ) + */ + +static void depthwrite(void) +{ + ucell tmp = POP(); + dstackcnt = tmp; +} + + +/* + * rdepth ( -- u ) + */ + +static void rdepth(void) +{ + const cell tmp = rstackcnt; + PUSH(tmp); +} + + +/* + * rdepth! ( u -- ) ( R: ... -- x1 x2 .. xu ) + */ + +static void rdepthwrite(void) +{ + ucell tmp = POP(); + rstackcnt = tmp; +} + + +/* + * + ( nu1 nu2 -- sum ) + */ + +static void plus(void) +{ + cell tmp = POP() + POP(); + PUSH(tmp); +} + + +/* + * - ( nu1 nu2 -- diff ) + */ + +static void minus(void) +{ + const cell nu2 = POP(); + const cell nu1 = POP(); + PUSH(nu1 - nu2); +} + + +/* + * * ( nu1 nu2 -- prod ) + */ + +static void mult(void) +{ + const cell nu2 = POP(); + const cell nu1 = POP(); + PUSH(nu1 * nu2); +} + + +/* + * u* ( u1 u2 -- prod ) + */ + +static void umult(void) +{ + const ucell tmp = (ucell) POP() * (ucell) POP(); + PUSH(tmp); +} + + +/* + * mu/mod ( n1 n2 -- rem quot.l quot.h ) + */ + +static void mudivmod(void) +{ + const ucell b = POP(); + const ducell a = DPOP(); +#ifdef NEED_FAKE_INT128_T + if (a.hi != 0) { + fprintf(stderr, "mudivmod called (0x%016llx %016llx / 0x%016llx)\n", + a.hi, a.lo, b); + exit(-1); + } else { + ducell c; + + PUSH(a.lo % b); + c.hi = 0; + c.lo = a.lo / b; + DPUSH(c); + } +#else + PUSH(a % b); + DPUSH(a / b); +#endif +} + + +/* + * abs ( n -- u ) + */ + +static void forthabs(void) +{ + const cell tmp = GETTOS(); + if (tmp < 0) { + POP(); + PUSH(-tmp); + } +} + + +/* + * negate ( n1 -- n2 ) + */ + +static void negate(void) +{ + const cell tmp = POP(); + PUSH(-tmp); +} + + +/* + * max ( n1 n2 -- n1|n2 ) + */ + +static void max(void) +{ + const cell tmp = POP(); + const cell tmp2 = POP(); + PUSH((tmp > tmp2) ? tmp : tmp2); +} + + +/* + * min ( n1 n2 -- n1|n2 ) + */ + +static void min(void) +{ + const cell tmp = POP(); + const cell tmp2 = POP(); + PUSH((tmp < tmp2) ? tmp : tmp2); +} + + +/* + * lshift ( x1 u -- x2 ) + */ + +static void lshift(void) +{ + const ucell u = POP(); + const ucell x1 = POP(); + PUSH(x1 << u); +} + + +/* + * rshift ( x1 u -- x2 ) + */ + +static void rshift(void) +{ + const ucell u = POP(); + const ucell x1 = POP(); + PUSH(x1 >> u); +} + + +/* + * >>a ( x1 u -- x2 ) ?? + */ + +static void rshifta(void) +{ + const cell u = POP(); + const cell x1 = POP(); + PUSH(x1 >> u); +} + + +/* + * and ( x1 x2 -- x3 ) + */ + +static void and(void) +{ + const cell x1 = POP(); + const cell x2 = POP(); + PUSH(x1 & x2); +} + + +/* + * or ( x1 x2 -- x3 ) + */ + +static void or(void) +{ + const cell x1 = POP(); + const cell x2 = POP(); + PUSH(x1 | x2); +} + + +/* + * xor ( x1 x2 -- x3 ) + */ + +static void xor(void) +{ + const cell x1 = POP(); + const cell x2 = POP(); + PUSH(x1 ^ x2); +} + + +/* + * invert ( x1 -- x2 ) + */ + +static void invert(void) +{ + const cell x1 = POP(); + PUSH(x1 ^ -1); +} + + +/* + * d+ ( d1 d2 -- d.sum ) + */ + +static void dplus(void) +{ + const dcell d2 = DPOP(); + const dcell d1 = DPOP(); +#ifdef NEED_FAKE_INT128_T + ducell c; + + if (d1.hi != 0 || d2.hi != 0) { + fprintf(stderr, "dplus called (0x%016llx %016llx + 0x%016llx %016llx)\n", + d1.hi, d1.lo, d2.hi, d2.lo); + exit(-1); + } + c.hi = 0; + c.lo = d1.lo + d2.lo; + DPUSH(c); +#else + DPUSH(d1 + d2); +#endif +} + + +/* + * d- ( d1 d2 -- d.diff ) + */ + +static void dminus(void) +{ + const dcell d2 = DPOP(); + const dcell d1 = DPOP(); +#ifdef NEED_FAKE_INT128_T + ducell c; + + if (d1.hi != 0 || d2.hi != 0) { + fprintf(stderr, "dminus called (0x%016llx %016llx + 0x%016llx %016llx)\n", + d1.hi, d1.lo, d2.hi, d2.lo); + exit(-1); + } + c.hi = 0; + c.lo = d1.lo - d2.lo; + DPUSH(c); +#else + DPUSH(d1 - d2); +#endif +} + + +/* + * m* ( ?? -- ) + */ + +static void mmult(void) +{ + const cell u2 = POP(); + const cell u1 = POP(); +#ifdef NEED_FAKE_INT128_T + ducell c; + + if (0) { // XXX How to detect overflow? + fprintf(stderr, "mmult called (%016llx * 0x%016llx)\n", u1, u2); + exit(-1); + } + c.hi = 0; + c.lo = u1 * u2; + DPUSH(c); +#else + DPUSH((dcell) u1 * u2); +#endif +} + + +/* + * um* ( u1 u2 -- d.prod ) + */ + +static void ummult(void) +{ + const ucell u2 = POP(); + const ucell u1 = POP(); +#ifdef NEED_FAKE_INT128_T + ducell c; + + if (0) { // XXX How to detect overflow? + fprintf(stderr, "ummult called (%016llx * 0x%016llx)\n", u1, u2); + exit(-1); + } + c.hi = 0; + c.lo = u1 * u2; + DPUSH(c); +#else + DPUSH((ducell) u1 * u2); +#endif +} + + +/* + * @ ( a-addr -- x ) + */ + +static void fetch(void) +{ + const ucell *aaddr = (ucell *)cell2pointer(POP()); + PUSH(read_ucell(aaddr)); +} + + +/* + * c@ ( addr -- byte ) + */ + +static void cfetch(void) +{ + const u8 *aaddr = (u8 *)cell2pointer(POP()); + PUSH(read_byte(aaddr)); +} + + +/* + * w@ ( waddr -- w ) + */ + +static void wfetch(void) +{ + const u16 *aaddr = (u16 *)cell2pointer(POP()); + PUSH(read_word(aaddr)); +} + + +/* + * l@ ( qaddr -- quad ) + */ + +static void lfetch(void) +{ + const u32 *aaddr = (u32 *)cell2pointer(POP()); + PUSH(read_long(aaddr)); +} + + +/* + * ! ( x a-addr -- ) + */ + +static void store(void) +{ + const ucell *aaddr = (ucell *)cell2pointer(POP()); + const ucell x = POP(); +#ifdef CONFIG_DEBUG_INTERNAL + printk("!: %lx : %lx -> %lx\n", aaddr, read_ucell(aaddr), x); +#endif + write_ucell(aaddr,x); +} + + +/* + * +! ( nu a-addr -- ) + */ + +static void plusstore(void) +{ + const ucell *aaddr = (ucell *)cell2pointer(POP()); + const cell nu = POP(); + write_cell(aaddr,read_cell(aaddr)+nu); +} + + +/* + * c! ( byte addr -- ) + */ + +static void cstore(void) +{ + const u8 *aaddr = (u8 *)cell2pointer(POP()); + const ucell byte = POP(); +#ifdef CONFIG_DEBUG_INTERNAL + printk("c!: %x = %x\n", aaddr, byte); +#endif + write_byte(aaddr, byte); +} + + +/* + * w! ( w waddr -- ) + */ + +static void wstore(void) +{ + const u16 *aaddr = (u16 *)cell2pointer(POP()); + const u16 word = POP(); + write_word(aaddr, word); +} + + +/* + * l! ( quad qaddr -- ) + */ + +static void lstore(void) +{ + const u32 *aaddr = (u32 *)cell2pointer(POP()); + const u32 longval = POP(); + write_long(aaddr, longval); +} + + +/* + * = ( x1 x2 -- equal? ) + */ + +static void equals(void) +{ + cell tmp = (POP() == POP()); + PUSH(-tmp); +} + + +/* + * > ( n1 n2 -- greater? ) + */ + +static void greater(void) +{ + cell tmp = ((cell) POP() < (cell) POP()); + PUSH(-tmp); +} + + +/* + * < ( n1 n2 -- less? ) + */ + +static void less(void) +{ + cell tmp = ((cell) POP() > (cell) POP()); + PUSH(-tmp); +} + + +/* + * u> ( u1 u2 -- unsigned-greater? ) + */ + +static void ugreater(void) +{ + cell tmp = ((ucell) POP() < (ucell) POP()); + PUSH(-tmp); +} + + +/* + * u< ( u1 u2 -- unsigned-less? ) + */ + +static void uless(void) +{ + cell tmp = ((ucell) POP() > (ucell) POP()); + PUSH(-tmp); +} + + +/* + * sp@ ( -- stack-pointer ) + */ + +static void spfetch(void) +{ + // FIXME this can only work if the stack pointer + // is within range. + ucell tmp = pointer2cell(&(dstack[dstackcnt])); + PUSH(tmp); +} + + +/* + * move ( src-addr dest-addr len -- ) + */ + +static void fmove(void) +{ + ucell count = POP(); + void *dest = (void *)cell2pointer(POP()); + const void *src = (const void *)cell2pointer(POP()); + memmove(dest, src, count); +} + + +/* + * fill ( addr len byte -- ) + */ + +static void ffill(void) +{ + ucell value = POP(); + ucell count = POP(); + void *src = (void *)cell2pointer(POP()); + memset(src, value, count); +} + + +/* + * unaligned-w@ ( addr -- w ) + */ + +static void unalignedwordread(void) +{ + const unsigned char *addr = (const unsigned char *) cell2pointer(POP()); + PUSH(unaligned_read_word(addr)); +} + + +/* + * unaligned-w! ( w addr -- ) + */ + +static void unalignedwordwrite(void) +{ + const unsigned char *addr = (const unsigned char *) cell2pointer(POP()); + u16 w = POP(); + unaligned_write_word(addr, w); +} + + +/* + * unaligned-l@ ( addr -- quad ) + */ + +static void unalignedlongread(void) +{ + const unsigned char *addr = (const unsigned char *) cell2pointer(POP()); + PUSH(unaligned_read_long(addr)); +} + + +/* + * unaligned-l! ( quad addr -- ) + */ + +static void unalignedlongwrite(void) +{ + unsigned char *addr = (unsigned char *) cell2pointer(POP()); + u32 l = POP(); + unaligned_write_long(addr, l); +} + +/* + * here ( -- dictionary-pointer ) + */ + +static void here(void) +{ + PUSH(pointer2cell(dict) + dicthead); +#ifdef CONFIG_DEBUG_INTERNAL + printk("here: %x\n", pointer2cell(dict) + dicthead); +#endif +} + +/* + * here! ( new-dict-pointer -- ) + */ + +static void herewrite(void) +{ + ucell tmp = POP(); /* converted pointer */ + dicthead = tmp - pointer2cell(dict); +#ifdef CONFIG_DEBUG_INTERNAL + printk("here!: new value: %x\n", tmp); +#endif + + if (dictlimit && dicthead >= dictlimit) { + printk("Dictionary space overflow:" + " dicthead=" FMT_ucellx + " dictlimit=" FMT_ucellx + "\n", + dicthead, dictlimit); + } +} + + +/* + * emit ( char -- ) + */ + +static void emit(void) +{ + cell tmp = POP(); +#ifndef FCOMPILER + putchar(tmp); +#else + put_outputbyte(tmp); +#endif +} + + +/* + * key? ( -- pressed? ) + */ + +static void iskey(void) +{ + PUSH((cell) availchar()); +} + + +/* + * key ( -- char ) + */ + +static void key(void) +{ + while (!availchar()); +#ifdef FCOMPILER + PUSH(get_inputbyte()); +#else + PUSH(getchar()); +#endif +} + + +/* + * ioc@ ( reg -- val ) + */ + +static void iocfetch(void) +{ +#ifndef FCOMPILER + cell reg = POP(); + PUSH(inb(reg)); +#else + (void)POP(); + PUSH(0); +#endif +} + + +/* + * iow@ ( reg -- val ) + */ + +static void iowfetch(void) +{ +#ifndef FCOMPILER + cell reg = POP(); + PUSH(inw(reg)); +#else + (void)POP(); + PUSH(0); +#endif +} + +/* + * iol@ ( reg -- val ) + */ + +static void iolfetch(void) +{ +#ifndef FCOMPILER + cell reg = POP(); + PUSH(inl(reg)); +#else + (void)POP(); + PUSH(0); +#endif +} + + +/* + * ioc! ( val reg -- ) + */ + +static void iocstore(void) +{ +#ifndef FCOMPILER + cell reg = POP(); + cell val = POP(); + + outb(val, reg); +#else + (void)POP(); + (void)POP(); +#endif +} + + +/* + * iow! ( val reg -- ) + */ + +static void iowstore(void) +{ +#ifndef FCOMPILER + cell reg = POP(); + cell val = POP(); + + outw(val, reg); +#else + (void)POP(); + (void)POP(); +#endif +} + + +/* + * iol! ( val reg -- ) + */ + +static void iolstore(void) +{ +#ifndef FCOMPILER + ucell reg = POP(); + ucell val = POP(); + + outl(val, reg); +#else + (void)POP(); + (void)POP(); +#endif +} + +/* + * i ( -- i ) + */ + +static void loop_i(void) +{ + PUSH(rstack[rstackcnt]); +} + +/* + * j ( -- i ) + */ + +static void loop_j(void) +{ + PUSH(rstack[rstackcnt - 2]); +} + +/* words[] is a function array of all native code functions used by + * the dictionary, i.e. CFAs and primitives. + * Any change here needs a matching change in the primitive word's + * name list that is kept for bootstrapping in kernel/bootstrap.c + * + * NOTE: THIS LIST SHALL NOT CHANGE (EXCEPT MANDATORY ADDITIONS AT + * THE END). ANY OTHER CHANGE WILL BREAK COMPATIBILITY TO OLDER + * BINARY DICTIONARIES. + */ +static forth_word * const words[] = { + /* + * CFAs and special words + */ + semis, + docol, + lit, + docon, + dovar, + dodefer, + dodoes, + dodo, + doisdo, + doloop, + doplusloop, + doival, + doivar, + doidefer, + + /* + * primitives + */ + fdup, /* dup */ + twodup, /* 2dup */ + isdup, /* ?dup */ + over, /* over */ + twoover, /* 2over */ + pick, /* pick */ + drop, /* drop */ + twodrop, /* 2drop */ + nip, /* nip */ + roll, /* roll */ + rot, /* rot */ + minusrot, /* -rot */ + swap, /* swap */ + twoswap, /* 2swap */ + tor, /* >r */ + rto, /* r> */ + rfetch, /* r@ */ + depth, /* depth */ + depthwrite, /* depth! */ + rdepth, /* rdepth */ + rdepthwrite, /* rdepth! */ + plus, /* + */ + minus, /* - */ + mult, /* * */ + umult, /* u* */ + mudivmod, /* mu/mod */ + forthabs, /* abs */ + negate, /* negate */ + max, /* max */ + min, /* min */ + lshift, /* lshift */ + rshift, /* rshift */ + rshifta, /* >>a */ + and, /* and */ + or, /* or */ + xor, /* xor */ + invert, /* invert */ + dplus, /* d+ */ + dminus, /* d- */ + mmult, /* m* */ + ummult, /* um* */ + fetch, /* @ */ + cfetch, /* c@ */ + wfetch, /* w@ */ + lfetch, /* l@ */ + store, /* ! */ + plusstore, /* +! */ + cstore, /* c! */ + wstore, /* w! */ + lstore, /* l! */ + equals, /* = */ + greater, /* > */ + less, /* < */ + ugreater, /* u> */ + uless, /* u< */ + spfetch, /* sp@ */ + fmove, /* move */ + ffill, /* fill */ + emit, /* emit */ + iskey, /* key? */ + key, /* key */ + execute, /* execute */ + here, /* here */ + herewrite, /* here! */ + dobranch, /* dobranch */ + docbranch, /* do?branch */ + unalignedwordread, /* unaligned-w@ */ + unalignedwordwrite, /* unaligned-w! */ + unalignedlongread, /* unaligned-l@ */ + unalignedlongwrite, /* unaligned-l! */ + iocfetch, /* ioc@ */ + iowfetch, /* iow@ */ + iolfetch, /* iol@ */ + iocstore, /* ioc! */ + iowstore, /* iow! */ + iolstore, /* iol! */ + loop_i, /* i */ + loop_j, /* j */ + call, /* call */ + sysdebug, /* sys-debug */ + do_include, /* $include */ + do_encode_file, /* $encode-file */ + do_debug_xt, /* (debug */ + do_debug_off, /* (debug-off) */ +}; diff --git a/qemu/roms/openbios/kernel/include/dict.h b/qemu/roms/openbios/kernel/include/dict.h new file mode 100644 index 000000000..749fd6fba --- /dev/null +++ b/qemu/roms/openbios/kernel/include/dict.h @@ -0,0 +1,59 @@ +/* tag: dict management headers + * + * Copyright (C) 2003 Patrick Mauritz, Stefan Reinauer + * + * See the file "COPYING" for further information about + * the copyright and warranty status of this work. + */ + +#ifndef __DICT_H +#define __DICT_H + +#define DICTID "OpenBIOS" + +#define DOSEMIS 0 +#define DOCOL 1 +#define DOLIT 2 +#define DOCON 3 +#define DOVAR 4 +#define DODFR 5 +#define DODOES 6 + +#define MAXNFALEN 128 + +/* The header is 28/32 bytes on 32/64bit platforms */ + +typedef struct dictionary_header { + char signature[8]; + u8 version; + u8 cellsize; + u8 endianess; + u8 compression; + u8 relocation; + u8 reserved[3]; + u32 checksum; + u32 length; + ucell last; +} __attribute__((packed)) dictionary_header_t; + +ucell lfa2nfa(ucell ilfa); +ucell load_dictionary(const char *data, ucell len); +void dump_header(dictionary_header_t *header); +ucell fstrlen(ucell fstr); +void fstrncpy(char *dest, ucell src, unsigned int maxlen); +ucell findsemis(ucell xt); +ucell findxtfromcell_wordlist(ucell incell, ucell wordlist); +ucell findxtfromcell(ucell incell); + +/* program counter */ +extern ucell PC; + +extern unsigned char *dict; +extern cell dicthead; +extern cell dictlimit; +extern ucell *last; +#ifdef FCOMPILER +extern ucell *trampoline; +#endif + +#endif diff --git a/qemu/roms/openbios/kernel/stack.c b/qemu/roms/openbios/kernel/stack.c new file mode 100644 index 000000000..f6715d1c3 --- /dev/null +++ b/qemu/roms/openbios/kernel/stack.c @@ -0,0 +1,46 @@ +/* tag: defines the stacks, program counter and ways to access those + * + * Copyright (C) 2003 Patrick Mauritz, Stefan Reinauer + * + * See the file "COPYING" for further information about + * the copyright and warranty status of this work. + */ + + +#include "config.h" +#include "kernel/stack.h" +#include "cross.h" + +#define dstacksize 512 +int dstackcnt = 0; +cell dstack[dstacksize]; + +#define rstacksize 512 +int rstackcnt = 0; +cell rstack[rstacksize]; + +/* Rstack value saved before entering forth interpreter in debugger */ +int dbgrstackcnt = 0; + +#if defined(CONFIG_DEBUG_DSTACK) || defined(FCOMPILER) +void printdstack(void) +{ + int i; + printk("dstack:"); + for (i = 0; i <= dstackcnt; i++) { + printk(" 0x%" FMT_CELL_x , dstack[i]); + } + printk("\n"); +} +#endif +#if defined(CONFIG_DEBUG_RSTACK) || defined(FCOMPILER) +void printrstack(void) +{ + int i; + printk("rstack:"); + for (i = 0; i <= rstackcnt; i++) { + printk(" 0x%" FMT_CELL_x , rstack[i]); + } + printk("\n"); +} +#endif diff --git a/qemu/roms/openbios/libc/build.xml b/qemu/roms/openbios/libc/build.xml new file mode 100644 index 000000000..cb2b560db --- /dev/null +++ b/qemu/roms/openbios/libc/build.xml @@ -0,0 +1,12 @@ +<build> + + <library name="libc" type="static" target="target"> + <object source="ctype.c"/> + <object source="diskio.c"/> + <object source="extra.c"/> + <object source="misc.c"/> + <object source="string.c"/> + <object source="vsprintf.c"/> + </library> + +</build> diff --git a/qemu/roms/openbios/libc/ctype.c b/qemu/roms/openbios/libc/ctype.c new file mode 100644 index 000000000..c433f6c62 --- /dev/null +++ b/qemu/roms/openbios/libc/ctype.c @@ -0,0 +1,34 @@ +/* + * linux/lib/ctype.c + * + * Copyright (C) 1991, 1992 Linus Torvalds + */ + +#include "config.h" +#include "libc/string.h" + +const unsigned char _ctype[] = { +_C,_C,_C,_C,_C,_C,_C,_C, /* 0-7 */ +_C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C, /* 8-15 */ +_C,_C,_C,_C,_C,_C,_C,_C, /* 16-23 */ +_C,_C,_C,_C,_C,_C,_C,_C, /* 24-31 */ +_S|_SP,_P,_P,_P,_P,_P,_P,_P, /* 32-39 */ +_P,_P,_P,_P,_P,_P,_P,_P, /* 40-47 */ +_D,_D,_D,_D,_D,_D,_D,_D, /* 48-55 */ +_D,_D,_P,_P,_P,_P,_P,_P, /* 56-63 */ +_P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U, /* 64-71 */ +_U,_U,_U,_U,_U,_U,_U,_U, /* 72-79 */ +_U,_U,_U,_U,_U,_U,_U,_U, /* 80-87 */ +_U,_U,_U,_P,_P,_P,_P,_P, /* 88-95 */ +_P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L, /* 96-103 */ +_L,_L,_L,_L,_L,_L,_L,_L, /* 104-111 */ +_L,_L,_L,_L,_L,_L,_L,_L, /* 112-119 */ +_L,_L,_L,_P,_P,_P,_P,_C, /* 120-127 */ +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 128-143 */ +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 144-159 */ +_S|_SP,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 160-175 */ +_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 176-191 */ +_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U, /* 192-207 */ +_U,_U,_U,_U,_U,_U,_U,_P,_U,_U,_U,_U,_U,_U,_U,_L, /* 208-223 */ +_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L, /* 224-239 */ +_L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L}; /* 240-255 */ diff --git a/qemu/roms/openbios/libc/diskio.c b/qemu/roms/openbios/libc/diskio.c new file mode 100644 index 000000000..23f38ebb2 --- /dev/null +++ b/qemu/roms/openbios/libc/diskio.c @@ -0,0 +1,248 @@ +/* + * Creation Date: <2003/12/07 19:36:00 samuel> + * Time-stamp: <2004/01/07 19:28:43 samuel> + * + * <diskio.c> + * + * I/O wrappers + * + * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#include "config.h" +#include "libopenbios/bindings.h" +#include "libc/diskio.h" + +//#define CONFIG_DEBUG_DISKIO +#ifdef CONFIG_DEBUG_DISKIO +#define DPRINTF(fmt, args...) \ + do { printk(fmt , ##args); } while (0) +#else +#define DPRINTF(fmt, args...) +#endif + +typedef struct { + ihandle_t ih; + int do_close; + xt_t read_xt; + xt_t seek_xt; + + xt_t reopen_xt; + xt_t tell_xt; + xt_t get_path_xt; + xt_t get_fstype_xt; + xt_t open_nwrom_xt; + xt_t volume_name_xt; +} priv_fd_t; + +#define MAX_FD 32 +static priv_fd_t *file_descriptors[MAX_FD]; + +static int +lookup_xt( ihandle_t ih, const char *method, xt_t *xt ) +{ + if( *xt ) + return 0; + *xt = find_ih_method( method, ih ); + return (*xt) ? 0:1; +} + +int +open_ih( ihandle_t ih ) +{ + xt_t read_xt=0, seek_xt=0; + priv_fd_t *fdp; + int fd; + + if( !ih || lookup_xt(ih, "read", &read_xt) ) + return -1; + if( lookup_xt(ih, "seek", &seek_xt) ) + return -1; + + for (fd=0; fd<MAX_FD; fd++) + if(file_descriptors[fd]==NULL) + break; + if(fd==MAX_FD) + return -1; + + fdp = malloc( sizeof(*fdp) ); + /* Better clear the fd, as it + * contains valuable information + */ + memset(fdp, 0, sizeof(*fdp)); + fdp->ih = ih; + fdp->read_xt = read_xt; + fdp->seek_xt = seek_xt; + fdp->do_close = 0; + + file_descriptors[fd]=fdp; + DPRINTF("%s(0x%lx) = %d\n", __func__, (unsigned long)ih, fd); + return fd; +} + +int +open_io( const char *spec ) +{ + int fd; + ihandle_t ih = open_dev( spec ); + priv_fd_t *fdp; + + DPRINTF("%s(%s)\n", __func__, spec); + if( !ih ) + return -1; + + if( (fd=open_ih(ih)) == -1 ) { + close_dev( ih ); + return -1; + } + + fdp = file_descriptors[fd]; + fdp->do_close = 1; + + return fd; +} + +int +reopen( int fd, const char *filename ) +{ + priv_fd_t *fdp = file_descriptors[fd]; + int ret; + + if( lookup_xt(fdp->ih, "reopen", &fdp->reopen_xt) ) + return -1; + + push_str( filename ); + call_package( fdp->reopen_xt, fdp->ih ); + ret = (POP() == (ucell)-1)? 0 : -1; + + DPRINTF("%s(%d, %s) = %d\n", __func__, fd, filename, ret); + return ret; +} + +int +reopen_nwrom( int fd ) +{ + priv_fd_t *fdp = file_descriptors[fd]; + + DPRINTF("%s(%d)\n", __func__, fd); + if( lookup_xt(fdp->ih, "open-nwrom", &fdp->open_nwrom_xt) ) + return -1; + call_package( fdp->open_nwrom_xt, fdp->ih ); + return (POP() == (ucell)-1)? 0 : -1; +} + +ihandle_t +get_ih_from_fd( int fd ) +{ + priv_fd_t *fdp = file_descriptors[fd]; + return fdp->ih; +} + +const char * +get_file_path( int fd ) +{ + priv_fd_t *fdp = file_descriptors[fd]; + if( lookup_xt(fdp->ih, "get-path", &fdp->get_path_xt) ) + return NULL; + call_package( fdp->get_path_xt, fdp->ih ); + return (char*)cell2pointer(POP()); +} + +const char * +get_volume_name( int fd ) +{ + priv_fd_t *fdp = file_descriptors[fd]; + if( lookup_xt(fdp->ih, "volume-name", &fdp->volume_name_xt) ) + return NULL; + call_package( fdp->volume_name_xt, fdp->ih ); + return (char*)cell2pointer(POP()); +} + +const char * +get_fstype( int fd ) +{ + priv_fd_t *fdp = file_descriptors[fd]; + if( lookup_xt(fdp->ih, "get-fstype", &fdp->get_fstype_xt) ) + return NULL; + call_package( fdp->get_fstype_xt, fdp->ih ); + return (char*)cell2pointer(POP()); +} + +int +read_io( int fd, void *buf, size_t cnt ) +{ + priv_fd_t *fdp; + ucell ret; + + DPRINTF("%s(%d, %p, %u)\n", __func__, fd, buf, cnt); + if (fd != -1) { + fdp = file_descriptors[fd]; + + PUSH( pointer2cell(buf) ); + PUSH( cnt ); + call_package( fdp->read_xt, fdp->ih ); + ret = POP(); + + if( !ret && cnt ) + ret = -1; + } else { + ret = -1; + } + + return ret; +} + +int +seek_io( int fd, long long offs ) +{ + priv_fd_t *fdp; + + DPRINTF("%s(%d, %lld)\n", __func__, fd, offs); + if (fd != -1) { + fdp = file_descriptors[fd]; + + DPUSH( offs ); + call_package( fdp->seek_xt, fdp->ih ); + return ((((cell)POP()) >= 0)? 0 : -1); + } else { + return -1; + } +} + +long long +tell( int fd ) +{ + priv_fd_t *fdp = file_descriptors[fd]; + long long offs; + + if( lookup_xt(fdp->ih, "tell", &fdp->tell_xt) ) + return -1; + call_package( fdp->tell_xt, fdp->ih ); + offs = DPOP(); + DPRINTF("%s(%d) = %lld\n", __func__, fd, offs); + return offs; +} + +int +close_io( int fd ) +{ + priv_fd_t *fdp; + + DPRINTF("%s(%d)\n", __func__, fd); + if (fd != -1) { + fdp = file_descriptors[fd]; + + if( fdp->do_close ) + close_dev( fdp->ih ); + free( fdp ); + + file_descriptors[fd]=NULL; + } + + return 0; +} diff --git a/qemu/roms/openbios/libc/extra.c b/qemu/roms/openbios/libc/extra.c new file mode 100644 index 000000000..85731ade9 --- /dev/null +++ b/qemu/roms/openbios/libc/extra.c @@ -0,0 +1,49 @@ +/* + * Creation Date: <2003/10/18 13:52:32 samuel> + * Time-stamp: <2003/10/18 13:54:24 samuel> + * + * <extra.c> + * + * Libc extras + * + * Copyright (C) 2003 Samuel Rydh (samuel@ibrium.se) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#include "config.h" +#include "libc/string.h" +#include "libc/vsprintf.h" +#include "libopenbios/bindings.h" + +/* strncpy without 0-pad */ +char * +strncpy_nopad( char *dest, const char *src, size_t n ) +{ + int len = MIN( n, strlen(src)+1 ); + return memcpy( dest, src, len ); +} + +/* printf */ + +int forth_printf( const char *fmt, ... ) +{ + char buf[512]; + va_list args; + int i; + + va_start(args, fmt); + i = vsnprintf(buf, sizeof(buf), fmt, args); + va_end(args); + + PUSH(pointer2cell(buf)); + PUSH(i); + fword("type"); + + return i; +} + + diff --git a/qemu/roms/openbios/libc/misc.c b/qemu/roms/openbios/libc/misc.c new file mode 100644 index 000000000..e7cf4f408 --- /dev/null +++ b/qemu/roms/openbios/libc/misc.c @@ -0,0 +1,144 @@ +/* + * Creation Date: <2002/10/19 21:05:07 samuel> + * Time-stamp: <2002/10/22 22:29:18 samuel> + * + * <misc.c> + * + * Miscellaneous + * + * Copyright (C) 2002, 2003 Samuel Rydh (samuel@ibrium.se) + * + * 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 + * + */ + +#include "config.h" +#include "libc/string.h" + +int errno_int; + +void +qsort( void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void*) ) +{ + unsigned int worked, i, j; + + /* even more inefficient than the glibc variant :-) */ + do { + char *p = base; + worked = 0; + for( i=0; i<nmemb-1; i++, p+= size ) { + if( compar( p, p + size ) > 0 ) { + worked = 1; + for( j=0; j<size; j++ ) { + char ch = p[j]; + p[j] = p[j+size]; + p[j+size] = ch; + } + } + } + } while( worked ); +} + + +long int +strtol( const char *nptr, char **endptr, int base ) +{ + int sum, n, sign=1; + while( isspace(*nptr) ) + nptr++; + + if( *nptr == '-' || *nptr == '+' ) + sign = (*nptr++ == '-') ? -1 : 1; + + if( base == 16 || base == 0) { + if( !base ) + base = (nptr[0] == '0')? 8 : 10; + if( nptr[0] == '0' && nptr[1] == 'x' ) { + nptr += 2; + base = 16; + } + } + for( sum=0 ;; nptr++ ) { + char ch = *nptr; + if( !isalnum(ch) ) + break; + n = isdigit(ch) ? ch - '0' : toupper(ch) - 'A' + 10; + if( n >= base || n < 0 ) + break; + sum *= base; + sum += n; + } + if( endptr ) + *endptr = (char*)nptr; + + return sum * sign; +} + +long long int +strtoll( const char *nptr, char **endptr, int base ) +{ + long long int sum; + int n, sign=1; + while( isspace(*nptr) ) + nptr++; + + if( *nptr == '-' || *nptr == '+' ) + sign = (*nptr++ == '-') ? -1 : 1; + + if( base == 16 || base == 0) { + if( !base ) + base = (nptr[0] == '0')? 8 : 10; + if( nptr[0] == '0' && nptr[1] == 'x' ) { + nptr += 2; + base = 16; + } + } + for( sum=0 ;; nptr++ ) { + char ch = *nptr; + if( !isalnum(ch) ) + break; + n = isdigit(ch) ? ch - '0' : toupper(ch) - 'A' + 10; + if( n >= base || n < 0 ) + break; + sum *= base; + sum += n; + } + if( endptr ) + *endptr = (char*)nptr; + + return sum * sign; +} + +// Propolice support +long __guard[8] = { +#ifdef CONFIG_BIG_ENDIAN + (0 << 24) | (0 << 16) | ('\n' << 8) | 255, +#else + (255 << 24) | ('\n' << 16) | (0 << 8) | 0, +#endif + 0, 0, 0, 0, 0, 0, 0 +}; + +static void freeze(void) +{ + // Freeze + // XXX: Disable interrupts? + for(;;) + ; +} + +void __stack_smash_handler(const char *func, int damaged) +{ + printk("Propolice detected a stack smashing attack %x at function %s," + " freezing\n", damaged, func); + freeze(); +} + +void __stack_chk_fail(void) +{ + printk("Propolice detected a stack smashing attack, freezing\n"); + + freeze(); +} diff --git a/qemu/roms/openbios/libc/string.c b/qemu/roms/openbios/libc/string.c new file mode 100644 index 000000000..8f62bd7bb --- /dev/null +++ b/qemu/roms/openbios/libc/string.c @@ -0,0 +1,387 @@ +/* + * linux/lib/string.c + * + * Copyright (C) 1991, 1992 Linus Torvalds + */ + +/* + * stupid library routines.. The optimized versions should generally be found + * as inline code in <asm-xx/string.h> + * + * These are buggy as well.. + * + * * Fri Jun 25 1999, Ingo Oeser <ioe@informatik.tu-chemnitz.de> + * - Added strsep() which will replace strtok() soon (because strsep() is + * reentrant and should be faster). Use only strsep() in new code, please. + */ + +#include "config.h" +#include "libc/string.h" +#include "libc/stdlib.h" + +/** + * strnicmp - Case insensitive, length-limited string comparison + * @s1: One string + * @s2: The other string + * @len: the maximum number of characters to compare + */ +int strnicmp(const char *s1, const char *s2, size_t len) +{ + /* Yes, Virginia, it had better be unsigned */ + unsigned char c1, c2; + + c1 = 0; c2 = 0; + if (len) { + do { + c1 = *s1; c2 = *s2; + s1++; s2++; + if (!c1) + break; + if (!c2) + break; + if (c1 == c2) + continue; + c1 = tolower(c1); + c2 = tolower(c2); + if (c1 != c2) + break; + } while (--len); + } + return (int)c1 - (int)c2; +} + +/** + * strcpy - Copy a %NUL terminated string + * @dest: Where to copy the string to + * @src: Where to copy the string from + */ +char * strcpy(char * dest,const char *src) +{ + char *tmp = dest; + + while ((*dest++ = *src++) != '\0') + /* nothing */; + return tmp; +} + +/** + * strncpy - Copy a length-limited, %NUL-terminated string + * @dest: Where to copy the string to + * @src: Where to copy the string from + * @count: The maximum number of bytes to copy + * + * Note that unlike userspace strncpy, this does not %NUL-pad the buffer. + * However, the result is not %NUL-terminated if the source exceeds + * @count bytes. + */ +char * strncpy(char * dest,const char *src,size_t count) +{ + char *tmp = dest; + + while (count-- && (*dest++ = *src++) != '\0') + /* nothing */; + + return tmp; +} + +/** + * strcat - Append one %NUL-terminated string to another + * @dest: The string to be appended to + * @src: The string to append to it + */ +char * strcat(char * dest, const char * src) +{ + char *tmp = dest; + + while (*dest) + dest++; + while ((*dest++ = *src++) != '\0') + ; + + return tmp; +} + +/** + * strncat - Append a length-limited, %NUL-terminated string to another + * @dest: The string to be appended to + * @src: The string to append to it + * @count: The maximum numbers of bytes to copy + * + * Note that in contrast to strncpy, strncat ensures the result is + * terminated. + */ +char * strncat(char *dest, const char *src, size_t count) +{ + char *tmp = dest; + + if (count) { + while (*dest) + dest++; + while ((*dest++ = *src++)) { + if (--count == 0) { + *dest = '\0'; + break; + } + } + } + + return tmp; +} + +/** + * strcmp - Compare two strings + * @cs: One string + * @ct: Another string + */ +int strcmp(const char * cs,const char * ct) +{ + register signed char __res; + + while (1) { + if ((__res = *cs - *ct++) != 0 || !*cs++) + break; + } + + return __res; +} + +/** + * strncmp - Compare two length-limited strings + * @cs: One string + * @ct: Another string + * @count: The maximum number of bytes to compare + */ +int strncmp(const char * cs,const char * ct,size_t count) +{ + register signed char __res = 0; + + while (count) { + if ((__res = *cs - *ct++) != 0 || !*cs++) + break; + count--; + } + + return __res; +} + + +/** + * strchr - Find the first occurrence of a character in a string + * @s: The string to be searched + * @c: The character to search for + */ +char * strchr(const char * s, int c) +{ + for(; *s != (char) c; ++s) + if (*s == '\0') + return NULL; + return (char *) s; +} + +/** + * strrchr - Find the last occurrence of a character in a string + * @s: The string to be searched + * @c: The character to search for + */ +char * strrchr(const char * s, int c) +{ + const char *p = s + strlen(s); + do { + if (*p == (char)c) + return (char *)p; + } while (--p >= s); + return NULL; +} + +/** + * strlen - Find the length of a string + * @s: The string to be sized + */ +size_t strlen(const char * s) +{ + const char *sc; + + for (sc = s; *sc != '\0'; ++sc) + /* nothing */; + return sc - s; +} + +/** + * strnlen - Find the length of a length-limited string + * @s: The string to be sized + * @count: The maximum number of bytes to search + */ +size_t strnlen(const char * s, size_t count) +{ + const char *sc; + + for (sc = s; count-- && *sc != '\0'; ++sc) + /* nothing */; + return sc - s; +} + +/** + * strpbrk - Find the first occurrence of a set of characters + * @cs: The string to be searched + * @ct: The characters to search for + */ +char * strpbrk(const char * cs,const char * ct) +{ + const char *sc1,*sc2; + + for( sc1 = cs; *sc1 != '\0'; ++sc1) { + for( sc2 = ct; *sc2 != '\0'; ++sc2) { + if (*sc1 == *sc2) + return (char *) sc1; + } + } + return NULL; +} + +/** + * strsep - Split a string into tokens + * @s: The string to be searched + * @ct: The characters to search for + * + * strsep() updates @s to point after the token, ready for the next call. + * + * It returns empty tokens, too, behaving exactly like the libc function + * of that name. In fact, it was stolen from glibc2 and de-fancy-fied. + * Same semantics, slimmer shape. ;) + */ +char * strsep(char **s, const char *ct) +{ + char *sbegin = *s, *end; + + if (sbegin == NULL) + return NULL; + + end = strpbrk(sbegin, ct); + if (end) + *end++ = '\0'; + *s = end; + + return sbegin; +} + +/** + * memset - Fill a region of memory with the given value + * @s: Pointer to the start of the area. + * @c: The byte to fill the area with + * @count: The size of the area. + * + * Do not use memset() to access IO space, use memset_io() instead. + */ +void * memset(void * s,int c,size_t count) +{ + char *xs = (char *) s; + + while (count--) + *xs++ = c; + + return s; +} + +/** + * memcpy - Copy one area of memory to another + * @dest: Where to copy to + * @src: Where to copy from + * @count: The size of the area. + * + * You should not use this function to access IO space, use memcpy_toio() + * or memcpy_fromio() instead. + */ +void * memcpy(void * dest,const void *src,size_t count) +{ + char *tmp = (char *) dest, *s = (char *) src; + + while (count--) + *tmp++ = *s++; + + return dest; +} + +/** + * memmove - Copy one area of memory to another + * @dest: Where to copy to + * @src: Where to copy from + * @count: The size of the area. + * + * Unlike memcpy(), memmove() copes with overlapping areas. + */ +void * memmove(void * dest,const void *src,size_t count) +{ + char *tmp, *s; + + if (dest <= src) { + tmp = (char *) dest; + s = (char *) src; + while (count--) + *tmp++ = *s++; + } + else { + tmp = (char *) dest + count; + s = (char *) src + count; + while (count--) + *--tmp = *--s; + } + + return dest; +} + +/** + * memcmp - Compare two areas of memory + * @cs: One area of memory + * @ct: Another area of memory + * @count: The size of the area. + */ +int memcmp(const void * cs,const void * ct,size_t count) +{ + const unsigned char *su1, *su2; + int res = 0; + + for( su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--) + if ((res = *su1 - *su2) != 0) + break; + return res; +} + +char * +strdup( const char *str ) +{ + char *p; + if( !str ) + return NULL; + p = malloc( strlen(str) + 1 ); + strcpy( p, str ); + return p; +} + +int +strcasecmp( const char *cs, const char *ct ) +{ + register signed char __res; + + while (1) { + char ch1 = toupper(*cs), ch2 = toupper(*ct); + ct++; + if ((__res = ch1 - ch2) != 0 || !*cs++) + break; + } + return __res; +} + +int +strncasecmp( const char *cs, const char *ct, size_t count ) +{ + register signed char __res = 0; + + while (count--) { + char ch1 = toupper(*cs), ch2 = toupper(*ct); + ct++; + if ((__res = ch1 - ch2) != 0 || !*cs++) + break; + } + return __res; +} + diff --git a/qemu/roms/openbios/libc/vsprintf.c b/qemu/roms/openbios/libc/vsprintf.c new file mode 100644 index 000000000..29ec7b96e --- /dev/null +++ b/qemu/roms/openbios/libc/vsprintf.c @@ -0,0 +1,448 @@ +/* + * String functions for logger. + */ + +/* + * linux/lib/vsprintf.c + * + * Copyright (C) 1991, 1992 Linus Torvalds + */ + +/* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */ +/* + * Wirzenius wrote this portably, Torvalds fucked it up :-) + */ + +/* + * Fri Jul 13 2001 Crutcher Dunnavant <crutcher+kernel@datastacks.com> + * - changed to provide snprintf and vsnprintf functions + */ + +#include "config.h" +#include "libc/string.h" +#include "libc/vsprintf.h" + +static int skip_atoi(const char **s) +{ + int i=0; + + while (isdigit(**s)) + i = i*10 + *((*s)++) - '0'; + return i; +} + +#define ZEROPAD 1 /* pad with zero */ +#define SIGN 2 /* unsigned/signed long */ +#define PLUS 4 /* show plus */ +#define SPACE 8 /* space if plus */ +#define LEFT 16 /* left justified */ +#define SPECIAL 32 /* 0x */ +#define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */ + +#define do_div(n,base) ({ \ +int __res; \ +__res = ((unsigned long long) n) % (unsigned) base; \ +n = ((unsigned long long) n) / (unsigned) base; \ +__res; }) + +static int mstrlen( const char *str ); + +#ifndef PAGE_SIZE +#define PAGE_SIZE 4096 +#endif + +static char * number(char * buf, char * end, long long num, int base, int size, int precision, int type) +{ + char c,sign,tmp[66]; + const char *digits; + static const char small_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz"; + static const char large_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + int i; + + digits = (type & LARGE) ? large_digits : small_digits; + if (type & LEFT) + type &= ~ZEROPAD; + if (base < 2 || base > 36) + return NULL; + c = (type & ZEROPAD) ? '0' : ' '; + sign = 0; + if (type & SIGN) { + if (num < 0) { + sign = '-'; + num = -num; + size--; + } else if (type & PLUS) { + sign = '+'; + size--; + } else if (type & SPACE) { + sign = ' '; + size--; + } + } + if (type & SPECIAL) { + if (base == 16) + size -= 2; + else if (base == 8) + size--; + } + i = 0; + if (num == 0) + tmp[i++]='0'; + else while (num != 0) + tmp[i++] = digits[do_div(num,base)]; + if (i > precision) + precision = i; + size -= precision; + if (!(type&(ZEROPAD+LEFT))) { + while(size-->0) { + if (buf <= end) + *buf = ' '; + ++buf; + } + } + if (sign) { + if (buf <= end) + *buf = sign; + ++buf; + } + if (type & SPECIAL) { + if (base==8) { + if (buf <= end) + *buf = '0'; + ++buf; + } else if (base==16) { + if (buf <= end) + *buf = '0'; + ++buf; + if (buf <= end) + *buf = digits[33]; + ++buf; + } + } + if (!(type & LEFT)) { + while (size-- > 0) { + if (buf <= end) + *buf = c; + ++buf; + } + } + while (i < precision--) { + if (buf <= end) + *buf = '0'; + ++buf; + } + while (i-- > 0) { + if (buf <= end) + *buf = tmp[i]; + ++buf; + } + while (size-- > 0) { + if (buf <= end) + *buf = ' '; + ++buf; + } + return buf; +} + +/** +* vsnprintf - Format a string and place it in a buffer +* @buf: The buffer to place the result into +* @size: The size of the buffer, including the trailing null space +* @fmt: The format string to use +* @args: Arguments for the format string +* +* Call this function if you are already dealing with a va_list. +* You probably want snprintf instead. + */ +int vsnprintf(char *buf, size_t size, const char *fmt, va_list args) +{ + int len; + unsigned long long num; + int i, base; + char *str, *end, c; + const char *s; + + int flags; /* flags to number() */ + + int field_width; /* width of output field */ + int precision; /* min. # of digits for integers; max + number of chars for from string */ + int qualifier; /* 'h', 'l', or 'L' for integer fields */ + /* 'z' support added 23/7/1999 S.H. */ + /* 'z' changed to 'Z' --davidm 1/25/99 */ + + str = buf; + end = buf + size - 1; + + if (end < buf - 1) { + end = ((void *) -1); + size = end - buf + 1; + } + + for (; *fmt ; ++fmt) { + if (*fmt != '%') { + if (str <= end) + *str = *fmt; + ++str; + continue; + } + + /* process flags */ + flags = 0; + repeat: + ++fmt; /* this also skips first '%' */ + switch (*fmt) { + case '-': flags |= LEFT; goto repeat; + case '+': flags |= PLUS; goto repeat; + case ' ': flags |= SPACE; goto repeat; + case '#': flags |= SPECIAL; goto repeat; + case '0': flags |= ZEROPAD; goto repeat; + } + + /* get field width */ + field_width = -1; + if (isdigit(*fmt)) + field_width = skip_atoi(&fmt); + else if (*fmt == '*') { + ++fmt; + /* it's the next argument */ + field_width = va_arg(args, int); + if (field_width < 0) { + field_width = -field_width; + flags |= LEFT; + } + } + + /* get the precision */ + precision = -1; + if (*fmt == '.') { + ++fmt; + if (isdigit(*fmt)) + precision = skip_atoi(&fmt); + else if (*fmt == '*') { + ++fmt; + /* it's the next argument */ + precision = va_arg(args, int); + } + if (precision < 0) + precision = 0; + } + + /* get the conversion qualifier */ + qualifier = -1; + if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || + *fmt =='Z' || *fmt == 'z') { + qualifier = *fmt; + ++fmt; + if (qualifier == 'l' && *fmt == 'l') { + qualifier = 'L'; + ++fmt; + } + } + + /* default base */ + base = 10; + + switch (*fmt) { + case 'c': + if (!(flags & LEFT)) { + while (--field_width > 0) { + if (str <= end) + *str = ' '; + ++str; + } + } + c = (unsigned char) va_arg(args, int); + if (str <= end) + *str = c; + ++str; + while (--field_width > 0) { + if (str <= end) + *str = ' '; + ++str; + } + continue; + + case 's': + s = va_arg(args, char *); + if ((unsigned long)s < PAGE_SIZE) + s = "<NULL>"; + +#if 0 + len = strnlen(s, precision); +#else + len = mstrlen(s); + if( precision > len ) + len = precision; +#endif + if (!(flags & LEFT)) { + while (len < field_width--) { + if (str <= end) + *str = ' '; + ++str; + } + } + for (i = 0; i < len; ++i) { + if (str <= end) + *str = *s; + ++str; ++s; + } + while (len < field_width--) { + if (str <= end) + *str = ' '; + ++str; + } + continue; + + case 'p': + if (field_width == -1) { + field_width = 2*sizeof(void *); + flags |= ZEROPAD; + } + str = number(str, end, + (unsigned long) va_arg(args, void *), + 16, field_width, precision, flags); + continue; + + + case 'n': + /* FIXME: + * What does C99 say about the overflow case here? */ + if (qualifier == 'l') { + long * ip = va_arg(args, long *); + *ip = (str - buf); + } else if (qualifier == 'Z' || qualifier == 'z') { + size_t * ip = va_arg(args, size_t *); + *ip = (str - buf); + } else { + int * ip = va_arg(args, int *); + *ip = (str - buf); + } + continue; + + case '%': + if (str <= end) + *str = '%'; + ++str; + continue; + + /* integer number formats - set up the flags and "break" */ + case 'o': + base = 8; + break; + + case 'X': + flags |= LARGE; + case 'x': + base = 16; + break; + + case 'd': + case 'i': + flags |= SIGN; + case 'u': + break; + + default: + if (str <= end) + *str = '%'; + ++str; + if (*fmt) { + if (str <= end) + *str = *fmt; + ++str; + } else { + --fmt; + } + continue; + } + if (qualifier == 'L') + num = va_arg(args, long long); + else if (qualifier == 'l') { + num = va_arg(args, unsigned long); + if (flags & SIGN) + num = (signed long) num; + } else if (qualifier == 'Z' || qualifier == 'z') { + num = va_arg(args, size_t); + } else if (qualifier == 'h') { + num = (unsigned short) va_arg(args, int); + if (flags & SIGN) + num = (signed short) num; + } else { + num = va_arg(args, unsigned int); + if (flags & SIGN) + num = (signed int) num; + } + str = number(str, end, num, base, + field_width, precision, flags); + } + if (str <= end) + *str = '\0'; + else if (size > 0) + /* don't write out a null byte if the buf size is zero */ + *end = '\0'; + /* the trailing null byte doesn't count towards the total + * ++str; + */ + return str-buf; +} + +/** + * snprintf - Format a string and place it in a buffer + * @buf: The buffer to place the result into + * @size: The size of the buffer, including the trailing null space + * @fmt: The format string to use + * @...: Arguments for the format string + */ +int snprintf(char * buf, size_t size, const char *fmt, ...) +{ + va_list args; + int i; + + va_start(args, fmt); + i=vsnprintf(buf,size,fmt,args); + va_end(args); + return i; +} + +/** + * vsprintf - Format a string and place it in a buffer + * @buf: The buffer to place the result into + * @fmt: The format string to use + * @args: Arguments for the format string + * + * Call this function if you are already dealing with a va_list. + * You probably want sprintf instead. + */ +int vsprintf(char *buf, const char *fmt, va_list args) +{ + return vsnprintf(buf, (~0U)>>1, fmt, args); +} + + +/** + * sprintf - Format a string and place it in a buffer + * @buf: The buffer to place the result into + * @fmt: The format string to use + * @...: Arguments for the format string + */ +int sprintf(char * buf, const char *fmt, ...) +{ + va_list args; + int i; + + va_start(args, fmt); + i=vsprintf(buf,fmt,args); + va_end(args); + return i; +} + +static int mstrlen( const char *str ) +{ + int i=0; + if( str == NULL ) + return 0; + while( *str++ ) + i++; + return i; +} diff --git a/qemu/roms/openbios/libgcc/__divdi3.c b/qemu/roms/openbios/libgcc/__divdi3.c new file mode 100644 index 000000000..a6b29b9af --- /dev/null +++ b/qemu/roms/openbios/libgcc/__divdi3.c @@ -0,0 +1,26 @@ +/* + * arch/i386/libgcc/__divdi3.c + */ + +#include "libgcc.h" + +int64_t __divdi3(int64_t num, int64_t den) +{ + int minus = 0; + int64_t v; + + if ( num < 0 ) { + num = -num; + minus = 1; + } + if ( den < 0 ) { + den = -den; + minus ^= 1; + } + + v = __udivmoddi4(num, den, NULL); + if ( minus ) + v = -v; + + return v; +} diff --git a/qemu/roms/openbios/libgcc/__divti3.c b/qemu/roms/openbios/libgcc/__divti3.c new file mode 100644 index 000000000..501c14f67 --- /dev/null +++ b/qemu/roms/openbios/libgcc/__divti3.c @@ -0,0 +1,26 @@ +/* + * arch/i386/libgcc/__divti3.c + */ + +#include "libgcc.h" + +__int128_t __divti3(__int128_t num, __int128_t den) +{ + int minus = 0; + __int128_t v; + + if ( num < 0 ) { + num = -num; + minus = 1; + } + if ( den < 0 ) { + den = -den; + minus ^= 1; + } + + v = __udivmodti4(num, den, NULL); + if ( minus ) + v = -v; + + return v; +} diff --git a/qemu/roms/openbios/libgcc/__lshrdi3.c b/qemu/roms/openbios/libgcc/__lshrdi3.c new file mode 100644 index 000000000..4c1a38cd5 --- /dev/null +++ b/qemu/roms/openbios/libgcc/__lshrdi3.c @@ -0,0 +1,59 @@ +/* lshrdi3.c extracted from gcc-2.7.2/libgcc2.c which is: */ +/* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC 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 2, or (at your option) +any later version. + +GNU CC 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 GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 51 Franklin St, Fifth Floor, Boston, +MA 02110-1301, USA. */ + +#include "libgcc.h" + +#define BITS_PER_UNIT 8 + +struct DIstruct {SItype high, low;}; + +typedef union +{ + struct DIstruct s; + DItype ll; +} DIunion; + +DItype +__lshrdi3 (DItype u, word_type b) +{ + DIunion w; + word_type bm; + DIunion uu; + + if (b == 0) + return u; + + uu.ll = u; + + bm = (sizeof (SItype) * BITS_PER_UNIT) - b; + if (bm <= 0) + { + w.s.high = 0; + w.s.low = (USItype)uu.s.high >> -bm; + } + else + { + USItype carries = (USItype)uu.s.high << bm; + w.s.high = (USItype)uu.s.high >> b; + w.s.low = ((USItype)uu.s.low >> b) | carries; + } + + return w.ll; +} diff --git a/qemu/roms/openbios/libgcc/__negti2.c b/qemu/roms/openbios/libgcc/__negti2.c new file mode 100644 index 000000000..e97cd1228 --- /dev/null +++ b/qemu/roms/openbios/libgcc/__negti2.c @@ -0,0 +1,53 @@ +/* Extracted from gcc-3.4.1/gcc/config/mips/_tilibi.c */ +/* A few TImode functions needed for TFmode emulated arithmetic. + Copyright 2002, 2003 Free Software Foundation, Inc. + Contributed by Alexandre Oliva <aoliva@redhat.com> + +This file is part of GCC. + +GCC 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 2, or (at your option) +any later version. + +GCC 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 GCC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +#include "libgcc.h" + +#if defined(__sparc__) || defined(__ppc__) +#define LIBGCC2_WORDS_BIG_ENDIAN +#endif + +typedef union +{ + struct TIstruct { +#if defined(LIBGCC2_WORDS_BIG_ENDIAN) + DItype high, low; +#else + DItype low, high; +#endif + } s; + TItype ll; +} TIunion; + +TItype +__negti2 (TItype u) +{ + TIunion w; + TIunion uu; + + uu.ll = u; + + w.s.low = -uu.s.low; + w.s.high = -uu.s.high - ((UDItype) w.s.low > 0); + + return w.ll; +} diff --git a/qemu/roms/openbios/libgcc/__udivdi3.c b/qemu/roms/openbios/libgcc/__udivdi3.c new file mode 100644 index 000000000..2bfe91393 --- /dev/null +++ b/qemu/roms/openbios/libgcc/__udivdi3.c @@ -0,0 +1,10 @@ +/* + * arch/i386/libgcc/__divdi3.c + */ + +#include "libgcc.h" + +uint64_t __udivdi3(uint64_t num, uint64_t den) +{ + return __udivmoddi4(num, den, NULL); +} diff --git a/qemu/roms/openbios/libgcc/__udivmoddi4.c b/qemu/roms/openbios/libgcc/__udivmoddi4.c new file mode 100644 index 000000000..bed70e12b --- /dev/null +++ b/qemu/roms/openbios/libgcc/__udivmoddi4.c @@ -0,0 +1,31 @@ +#include "libgcc.h" + +uint64_t __udivmoddi4(uint64_t num, uint64_t den, uint64_t *rem_p) +{ + uint64_t quot = 0, qbit = 1; + + if ( den == 0 ) { + __divide_error(); + return 0; /* If trap returns... */ + } + + /* Left-justify denominator and count shift */ + while ( (int64_t)den >= 0 ) { + den <<= 1; + qbit <<= 1; + } + + while ( qbit ) { + if ( den <= num ) { + num -= den; + quot += qbit; + } + den >>= 1; + qbit >>= 1; + } + + if ( rem_p ) + *rem_p = num; + + return quot; +} diff --git a/qemu/roms/openbios/libgcc/__udivmodti4.c b/qemu/roms/openbios/libgcc/__udivmodti4.c new file mode 100644 index 000000000..e373c59e6 --- /dev/null +++ b/qemu/roms/openbios/libgcc/__udivmodti4.c @@ -0,0 +1,31 @@ +#include "libgcc.h" + +__uint128_t __udivmodti4(__uint128_t num, __uint128_t den, __uint128_t *rem_p) +{ + __uint128_t quot = 0, qbit = 1; + + if ( den == 0 ) { + __divide_error(); + return 0; /* If trap returns... */ + } + + /* Left-justify denominator and count shift */ + while ( (__int128_t)den >= 0 ) { + den <<= 1; + qbit <<= 1; + } + + while ( qbit ) { + if ( den <= num ) { + num -= den; + quot += qbit; + } + den >>= 1; + qbit >>= 1; + } + + if ( rem_p ) + *rem_p = num; + + return quot; +} diff --git a/qemu/roms/openbios/libgcc/__udivti3.c b/qemu/roms/openbios/libgcc/__udivti3.c new file mode 100644 index 000000000..6be015bb5 --- /dev/null +++ b/qemu/roms/openbios/libgcc/__udivti3.c @@ -0,0 +1,10 @@ +/* + * arch/i386/libgcc/__divdi3.c + */ + +#include "libgcc.h" + +__uint128_t __udivti3(__uint128_t num, __uint128_t den) +{ + return __udivmodti4(num, den, NULL); +} diff --git a/qemu/roms/openbios/libgcc/__umoddi3.c b/qemu/roms/openbios/libgcc/__umoddi3.c new file mode 100644 index 000000000..1c7b1cd72 --- /dev/null +++ b/qemu/roms/openbios/libgcc/__umoddi3.c @@ -0,0 +1,13 @@ +/* + * arch/i386/libgcc/__umoddi3.c + */ + +#include "libgcc.h" + +uint64_t __umoddi3(uint64_t num, uint64_t den) +{ + uint64_t v; + + (void) __udivmoddi4(num, den, &v); + return v; +} diff --git a/qemu/roms/openbios/libgcc/__umodti3.c b/qemu/roms/openbios/libgcc/__umodti3.c new file mode 100644 index 000000000..196c7bf7e --- /dev/null +++ b/qemu/roms/openbios/libgcc/__umodti3.c @@ -0,0 +1,13 @@ +/* + * arch/i386/libgcc/__umoddi3.c + */ + +#include "libgcc.h" + +__uint128_t __umodti3(__uint128_t num, __uint128_t den) +{ + __uint128_t v; + + (void) __udivmodti4(num, den, &v); + return v; +} diff --git a/qemu/roms/openbios/libgcc/ashldi3.c b/qemu/roms/openbios/libgcc/ashldi3.c new file mode 100644 index 000000000..6feb063e8 --- /dev/null +++ b/qemu/roms/openbios/libgcc/ashldi3.c @@ -0,0 +1,59 @@ +/* ashrdi3.c extracted from gcc-2.95.2/libgcc2.c which is: */ +/* Copyright (C) 1989, 92-98, 1999 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC 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 2, or (at your option) +any later version. + +GNU CC 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 GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 51 Franklin St, Fifth Floor, Boston, +MA 02110-1301, USA. */ + +#include "libgcc.h" + +#define BITS_PER_UNIT 8 + +struct DIstruct {SItype high, low;}; + +typedef union +{ + struct DIstruct s; + DItype ll; +} DIunion; + +DItype +__ashldi3 (DItype u, word_type b) +{ + DIunion w; + word_type bm; + DIunion uu; + + if (b == 0) + return u; + + uu.ll = u; + + bm = (sizeof (SItype) * BITS_PER_UNIT) - b; + if (bm <= 0) + { + w.s.low = 0; + w.s.high = (USItype)uu.s.low << -bm; + } + else + { + USItype carries = (USItype)uu.s.low >> bm; + w.s.low = (USItype)uu.s.low << b; + w.s.high = ((USItype)uu.s.high << b) | carries; + } + + return w.ll; +} diff --git a/qemu/roms/openbios/libgcc/ashrdi3.c b/qemu/roms/openbios/libgcc/ashrdi3.c new file mode 100644 index 000000000..8594d5eef --- /dev/null +++ b/qemu/roms/openbios/libgcc/ashrdi3.c @@ -0,0 +1,60 @@ +/* ashrdi3.c extracted from gcc-2.7.2/libgcc2.c which is: */ +/* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC 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 2, or (at your option) +any later version. + +GNU CC 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 GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 51 Franklin St, Fifth Floor, Boston, +MA 02110-1301, USA. */ + +#include "libgcc.h" + +#define BITS_PER_UNIT 8 + +struct DIstruct {SItype high, low;}; + +typedef union +{ + struct DIstruct s; + DItype ll; +} DIunion; + +DItype +__ashrdi3 (DItype u, word_type b) +{ + DIunion w; + word_type bm; + DIunion uu; + + if (b == 0) + return u; + + uu.ll = u; + + bm = (sizeof (SItype) * BITS_PER_UNIT) - b; + if (bm <= 0) + { + /* w.s.high = 1..1 or 0..0 */ + w.s.high = uu.s.high >> (sizeof (SItype) * BITS_PER_UNIT - 1); + w.s.low = uu.s.high >> -bm; + } + else + { + USItype carries = (USItype)uu.s.high << bm; + w.s.high = uu.s.high >> b; + w.s.low = ((USItype)uu.s.low >> b) | carries; + } + + return w.ll; +} diff --git a/qemu/roms/openbios/libgcc/build.xml b/qemu/roms/openbios/libgcc/build.xml new file mode 100644 index 000000000..1b7724c5e --- /dev/null +++ b/qemu/roms/openbios/libgcc/build.xml @@ -0,0 +1,24 @@ +<build> + + <library name="gcc" type="static" target="target"> + <object source="ashldi3.c"/> + <object source="ashrdi3.c"/> + <object source="__lshrdi3.c"/> + + <object source="__divdi3.c"/> + <object source="__udivdi3.c"/> + <object source="__udivmoddi4.c"/> + <object source="__umoddi3.c"/> + + <object source="crtsavres.S" condition="PPC"/> + + <!-- CONDITION="CONFIG_64BITS" --> + <object source="__divti3.c" condition="SPARC64"/> + <object source="__udivti3.c" condition="SPARC64"/> + <object source="__udivmodti4.c" condition="SPARC64"/> + <object source="__umodti3.c" condition="SPARC64"/> + <object source="multi3.c" condition="SPARC64"/> + <object source="__negti2.c" condition="SPARC64"/> + </library> + +</build> diff --git a/qemu/roms/openbios/libgcc/crtsavres.S b/qemu/roms/openbios/libgcc/crtsavres.S new file mode 100644 index 000000000..40bd7365d --- /dev/null +++ b/qemu/roms/openbios/libgcc/crtsavres.S @@ -0,0 +1,401 @@ +/* + * Special support for eabi and SVR4 + * + * Copyright (C) 1995, 1996, 1998, 2000, 2001 Free Software Foundation, Inc. + * Copyright 2008 Freescale Semiconductor, Inc. + * Written By Michael Meissner + * + * Based on gcc/config/rs6000/crtsavres.asm from gcc + * 64 bit additions from reading the PPC elf64abi document. + * + * This file 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 2, or (at your option) any + * later version. + * + * In addition to the permissions in the GNU General Public License, the + * Free Software Foundation gives you unlimited permission to link the + * compiled version of this file with other programs, and to distribute + * those programs without any restriction coming from the use of this + * file. (The General Public License restrictions do apply in other + * respects; for example, they cover modification of the file, and + * distribution when not linked into another program.) + * + * This file 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; see the file COPYING. If not, write to + * the Free Software Foundation, 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + * As a special exception, if you link this library with files + * compiled with GCC to produce an executable, this does not cause + * the resulting executable to be covered by the GNU General Public License. + * This exception does not however invalidate any other reasons why + * the executable file might be covered by the GNU General Public License. + */ + +/* taken from Linux arch/powerpc/lib/crtsavres.S */ + +/* arch/powerpc/include/asm/ppc_asm.h */ +#ifdef CONFIG_PPC64 + +#define XGLUE(a,b) a##b +#define GLUE(a,b) XGLUE(a,b) + +#define _GLOBAL(name) \ + .section ".text"; \ + .align 2 ; \ + .globl name; \ + .globl GLUE(.,name); \ + .section ".opd","aw"; \ +name: \ + .quad GLUE(.,name); \ + .quad .TOC.@tocbase; \ + .quad 0; \ + .previous; \ + .type GLUE(.,name),@function; \ +GLUE(.,name): + +#else /* 32-bit */ + +/* include/linux/stringify.h */ + +/* Indirect stringification. Doing two levels allows the parameter to be a + * macro itself. For example, compile with -DFOO=bar, __stringify(FOO) + * converts to "bar". + */ + +#define __stringify_1(x...) #x +#define __stringify(x...) __stringify_1(x) + +/* arch/powerpc/include/asm/ppc_asm.h continues */ + +#define _GLOBAL(n) \ + .text; \ + .stabs __stringify(n:F-1),N_FUN,0,0,n;\ + .globl n; \ +n: + +/* some stab codes */ +#define N_FUN 36 + +#endif + +/* arch/powerpc/lib/crtsavres.S continues */ + + .file "crtsavres.S" + .section ".text" + +#ifndef CONFIG_PPC64 + +/* Routines for saving integer registers, called by the compiler. */ +/* Called with r11 pointing to the stack header word of the caller of the */ +/* function, just beyond the end of the integer save area. */ + +_GLOBAL(_savegpr_14) +_GLOBAL(_save32gpr_14) + stw 14,-72(11) /* save gp registers */ +_GLOBAL(_savegpr_15) +_GLOBAL(_save32gpr_15) + stw 15,-68(11) +_GLOBAL(_savegpr_16) +_GLOBAL(_save32gpr_16) + stw 16,-64(11) +_GLOBAL(_savegpr_17) +_GLOBAL(_save32gpr_17) + stw 17,-60(11) +_GLOBAL(_savegpr_18) +_GLOBAL(_save32gpr_18) + stw 18,-56(11) +_GLOBAL(_savegpr_19) +_GLOBAL(_save32gpr_19) + stw 19,-52(11) +_GLOBAL(_savegpr_20) +_GLOBAL(_save32gpr_20) + stw 20,-48(11) +_GLOBAL(_savegpr_21) +_GLOBAL(_save32gpr_21) + stw 21,-44(11) +_GLOBAL(_savegpr_22) +_GLOBAL(_save32gpr_22) + stw 22,-40(11) +_GLOBAL(_savegpr_23) +_GLOBAL(_save32gpr_23) + stw 23,-36(11) +_GLOBAL(_savegpr_24) +_GLOBAL(_save32gpr_24) + stw 24,-32(11) +_GLOBAL(_savegpr_25) +_GLOBAL(_save32gpr_25) + stw 25,-28(11) +_GLOBAL(_savegpr_26) +_GLOBAL(_save32gpr_26) + stw 26,-24(11) +_GLOBAL(_savegpr_27) +_GLOBAL(_save32gpr_27) + stw 27,-20(11) +_GLOBAL(_savegpr_28) +_GLOBAL(_save32gpr_28) + stw 28,-16(11) +_GLOBAL(_savegpr_29) +_GLOBAL(_save32gpr_29) + stw 29,-12(11) +_GLOBAL(_savegpr_30) +_GLOBAL(_save32gpr_30) + stw 30,-8(11) +_GLOBAL(_savegpr_31) +_GLOBAL(_save32gpr_31) + stw 31,-4(11) + blr + +/* Routines for restoring integer registers, called by the compiler. */ +/* Called with r11 pointing to the stack header word of the caller of the */ +/* function, just beyond the end of the integer restore area. */ + +_GLOBAL(_restgpr_14) +_GLOBAL(_rest32gpr_14) + lwz 14,-72(11) /* restore gp registers */ +_GLOBAL(_restgpr_15) +_GLOBAL(_rest32gpr_15) + lwz 15,-68(11) +_GLOBAL(_restgpr_16) +_GLOBAL(_rest32gpr_16) + lwz 16,-64(11) +_GLOBAL(_restgpr_17) +_GLOBAL(_rest32gpr_17) + lwz 17,-60(11) +_GLOBAL(_restgpr_18) +_GLOBAL(_rest32gpr_18) + lwz 18,-56(11) +_GLOBAL(_restgpr_19) +_GLOBAL(_rest32gpr_19) + lwz 19,-52(11) +_GLOBAL(_restgpr_20) +_GLOBAL(_rest32gpr_20) + lwz 20,-48(11) +_GLOBAL(_restgpr_21) +_GLOBAL(_rest32gpr_21) + lwz 21,-44(11) +_GLOBAL(_restgpr_22) +_GLOBAL(_rest32gpr_22) + lwz 22,-40(11) +_GLOBAL(_restgpr_23) +_GLOBAL(_rest32gpr_23) + lwz 23,-36(11) +_GLOBAL(_restgpr_24) +_GLOBAL(_rest32gpr_24) + lwz 24,-32(11) +_GLOBAL(_restgpr_25) +_GLOBAL(_rest32gpr_25) + lwz 25,-28(11) +_GLOBAL(_restgpr_26) +_GLOBAL(_rest32gpr_26) + lwz 26,-24(11) +_GLOBAL(_restgpr_27) +_GLOBAL(_rest32gpr_27) + lwz 27,-20(11) +_GLOBAL(_restgpr_28) +_GLOBAL(_rest32gpr_28) + lwz 28,-16(11) +_GLOBAL(_restgpr_29) +_GLOBAL(_rest32gpr_29) + lwz 29,-12(11) +_GLOBAL(_restgpr_30) +_GLOBAL(_rest32gpr_30) + lwz 30,-8(11) +_GLOBAL(_restgpr_31) +_GLOBAL(_rest32gpr_31) + lwz 31,-4(11) + blr + +/* Routines for restoring integer registers, called by the compiler. */ +/* Called with r11 pointing to the stack header word of the caller of the */ +/* function, just beyond the end of the integer restore area. */ + +_GLOBAL(_restgpr_14_x) +_GLOBAL(_rest32gpr_14_x) + lwz 14,-72(11) /* restore gp registers */ +_GLOBAL(_restgpr_15_x) +_GLOBAL(_rest32gpr_15_x) + lwz 15,-68(11) +_GLOBAL(_restgpr_16_x) +_GLOBAL(_rest32gpr_16_x) + lwz 16,-64(11) +_GLOBAL(_restgpr_17_x) +_GLOBAL(_rest32gpr_17_x) + lwz 17,-60(11) +_GLOBAL(_restgpr_18_x) +_GLOBAL(_rest32gpr_18_x) + lwz 18,-56(11) +_GLOBAL(_restgpr_19_x) +_GLOBAL(_rest32gpr_19_x) + lwz 19,-52(11) +_GLOBAL(_restgpr_20_x) +_GLOBAL(_rest32gpr_20_x) + lwz 20,-48(11) +_GLOBAL(_restgpr_21_x) +_GLOBAL(_rest32gpr_21_x) + lwz 21,-44(11) +_GLOBAL(_restgpr_22_x) +_GLOBAL(_rest32gpr_22_x) + lwz 22,-40(11) +_GLOBAL(_restgpr_23_x) +_GLOBAL(_rest32gpr_23_x) + lwz 23,-36(11) +_GLOBAL(_restgpr_24_x) +_GLOBAL(_rest32gpr_24_x) + lwz 24,-32(11) +_GLOBAL(_restgpr_25_x) +_GLOBAL(_rest32gpr_25_x) + lwz 25,-28(11) +_GLOBAL(_restgpr_26_x) +_GLOBAL(_rest32gpr_26_x) + lwz 26,-24(11) +_GLOBAL(_restgpr_27_x) +_GLOBAL(_rest32gpr_27_x) + lwz 27,-20(11) +_GLOBAL(_restgpr_28_x) +_GLOBAL(_rest32gpr_28_x) + lwz 28,-16(11) +_GLOBAL(_restgpr_29_x) +_GLOBAL(_rest32gpr_29_x) + lwz 29,-12(11) +_GLOBAL(_restgpr_30_x) +_GLOBAL(_rest32gpr_30_x) + lwz 30,-8(11) +_GLOBAL(_restgpr_31_x) +_GLOBAL(_rest32gpr_31_x) + lwz 0,4(11) + lwz 31,-4(11) + mtlr 0 + mr 1,11 + blr + +#else /* CONFIG_PPC64 */ + +.globl _savegpr0_14 +_savegpr0_14: + std r14,-144(r1) +.globl _savegpr0_15 +_savegpr0_15: + std r15,-136(r1) +.globl _savegpr0_16 +_savegpr0_16: + std r16,-128(r1) +.globl _savegpr0_17 +_savegpr0_17: + std r17,-120(r1) +.globl _savegpr0_18 +_savegpr0_18: + std r18,-112(r1) +.globl _savegpr0_19 +_savegpr0_19: + std r19,-104(r1) +.globl _savegpr0_20 +_savegpr0_20: + std r20,-96(r1) +.globl _savegpr0_21 +_savegpr0_21: + std r21,-88(r1) +.globl _savegpr0_22 +_savegpr0_22: + std r22,-80(r1) +.globl _savegpr0_23 +_savegpr0_23: + std r23,-72(r1) +.globl _savegpr0_24 +_savegpr0_24: + std r24,-64(r1) +.globl _savegpr0_25 +_savegpr0_25: + std r25,-56(r1) +.globl _savegpr0_26 +_savegpr0_26: + std r26,-48(r1) +.globl _savegpr0_27 +_savegpr0_27: + std r27,-40(r1) +.globl _savegpr0_28 +_savegpr0_28: + std r28,-32(r1) +.globl _savegpr0_29 +_savegpr0_29: + std r29,-24(r1) +.globl _savegpr0_30 +_savegpr0_30: + std r30,-16(r1) +.globl _savegpr0_31 +_savegpr0_31: + std r31,-8(r1) + std r0,16(r1) + blr + +.globl _restgpr0_14 +_restgpr0_14: + ld r14,-144(r1) +.globl _restgpr0_15 +_restgpr0_15: + ld r15,-136(r1) +.globl _restgpr0_16 +_restgpr0_16: + ld r16,-128(r1) +.globl _restgpr0_17 +_restgpr0_17: + ld r17,-120(r1) +.globl _restgpr0_18 +_restgpr0_18: + ld r18,-112(r1) +.globl _restgpr0_19 +_restgpr0_19: + ld r19,-104(r1) +.globl _restgpr0_20 +_restgpr0_20: + ld r20,-96(r1) +.globl _restgpr0_21 +_restgpr0_21: + ld r21,-88(r1) +.globl _restgpr0_22 +_restgpr0_22: + ld r22,-80(r1) +.globl _restgpr0_23 +_restgpr0_23: + ld r23,-72(r1) +.globl _restgpr0_24 +_restgpr0_24: + ld r24,-64(r1) +.globl _restgpr0_25 +_restgpr0_25: + ld r25,-56(r1) +.globl _restgpr0_26 +_restgpr0_26: + ld r26,-48(r1) +.globl _restgpr0_27 +_restgpr0_27: + ld r27,-40(r1) +.globl _restgpr0_28 +_restgpr0_28: + ld r28,-32(r1) +.globl _restgpr0_29 +_restgpr0_29: + ld r0,16(r1) + ld r29,-24(r1) + mtlr r0 + ld r30,-16(r1) + ld r31,-8(r1) + blr + +.globl _restgpr0_30 +_restgpr0_30: + ld r30,-16(r1) +.globl _restgpr0_31 +_restgpr0_31: + ld r0,16(r1) + ld r31,-8(r1) + mtlr r0 + blr + +#endif /* CONFIG_PPC64 */ diff --git a/qemu/roms/openbios/libgcc/libgcc.h b/qemu/roms/openbios/libgcc/libgcc.h new file mode 100644 index 000000000..fc82397dc --- /dev/null +++ b/qemu/roms/openbios/libgcc/libgcc.h @@ -0,0 +1,45 @@ +#ifndef _LIBGCC_H +#define _LIBGCC_H + +#include "asm/types.h" + +#ifndef NULL +#define NULL ((void *)0) +#endif + +typedef int SItype __attribute__ ((mode (SI))); +typedef unsigned int USItype __attribute__ ((mode (SI))); +typedef int DItype __attribute__ ((mode (DI))); +typedef unsigned int UDItype __attribute__ ((mode (DI))); +typedef int word_type __attribute__ ((mode (__word__))); + +uint64_t __udivmoddi4(uint64_t num, uint64_t den, uint64_t *rem); + +int64_t __divdi3(int64_t num, int64_t den); +uint64_t __udivdi3(uint64_t num, uint64_t den); + +uint64_t __umoddi3(uint64_t num, uint64_t den); + +DItype __ashldi3 (DItype u, word_type b); +DItype __lshrdi3 (DItype u, word_type b); +DItype __ashrdi3 (DItype u, word_type b); + +// Must be implemented outside: +void __divide_error(void); + +#if defined(__arch64__) || defined(__LP64__) +typedef int TItype __attribute__ ((mode (TI))); + +__uint128_t __udivmodti4(__uint128_t num, __uint128_t den, __uint128_t *rem); + +__int128_t __divti3(__int128_t num, __int128_t den); +__uint128_t __udivti3(__uint128_t num, __uint128_t den); + +__uint128_t __umodti3(__uint128_t num, __uint128_t den); + +TItype __multi3 (TItype u, TItype v); +TItype __negti2 (TItype u); + +#endif + +#endif /* _LIBGCC_H */ diff --git a/qemu/roms/openbios/libgcc/multi3.c b/qemu/roms/openbios/libgcc/multi3.c new file mode 100644 index 000000000..e7186be2a --- /dev/null +++ b/qemu/roms/openbios/libgcc/multi3.c @@ -0,0 +1,83 @@ +/* muldi3.c extracted from gcc-2.7.2.3/libgcc2.c and + gcc-2.7.2.3/longlong.h which is: */ +/* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC 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 2, or (at your option) +any later version. + +GNU CC 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 GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 51 Franklin St, Fifth Floor, Boston, +MA 02110-1301, USA. */ + +#include "libgcc.h" + +#define BITS_PER_UNIT 8 +#define DI_TYPE_SIZE 64 + +#define __BITS4 (DI_TYPE_SIZE / 4) +#define __ll_B (1L << (DI_TYPE_SIZE / 2)) +#define __ll_lowpart(t) ((UDItype) (t) % __ll_B) +#define __ll_highpart(t) ((UDItype) (t) / __ll_B) + +#define umul_ppmm(w1, w0, u, v) \ + do { \ + UDItype __x0, __x1, __x2, __x3; \ + UDItype __ul, __vl, __uh, __vh; \ + \ + __ul = __ll_lowpart (u); \ + __uh = __ll_highpart (u); \ + __vl = __ll_lowpart (v); \ + __vh = __ll_highpart (v); \ + \ + __x0 = (UDItype) __ul * __vl; \ + __x1 = (UDItype) __ul * __vh; \ + __x2 = (UDItype) __uh * __vl; \ + __x3 = (UDItype) __uh * __vh; \ + \ + __x1 += __ll_highpart (__x0);/* this can't give carry */ \ + __x1 += __x2; /* but this indeed can */ \ + if (__x1 < __x2) /* did we get it? */ \ + __x3 += __ll_B; /* yes, add it in the proper pos. */ \ + \ + (w1) = __x3 + __ll_highpart (__x1); \ + (w0) = __ll_lowpart (__x1) * __ll_B + __ll_lowpart (__x0); \ + } while (0) + +#define __umulsidi3(u, v) \ + ({TIunion __w; \ + umul_ppmm (__w.s.high, __w.s.low, u, v); \ + __w.ll; }) + +struct TIstruct {DItype high, low;}; + +typedef union +{ + struct TIstruct s; + TItype ll; +} TIunion; + +TItype +__multi3 (TItype u, TItype v) +{ + TIunion w; + TIunion uu, vv; + + uu.ll = u, + vv.ll = v; + + w.ll = __umulsidi3 (uu.s.low, vv.s.low); + w.s.high += ((UDItype) uu.s.low * (UDItype) vv.s.high + + (UDItype) uu.s.high * (UDItype) vv.s.low); + + return w.ll; +} diff --git a/qemu/roms/openbios/libopenbios/Kconfig b/qemu/roms/openbios/libopenbios/Kconfig new file mode 100644 index 000000000..1b36f1925 --- /dev/null +++ b/qemu/roms/openbios/libopenbios/Kconfig @@ -0,0 +1,97 @@ + + +menu "Module Configuration" + + +config CMDLINE + bool "Command Line Editing" + default y + help + Improved openfirmware prompt + +config DEBLOCKER + bool "Deblocker" + default y + help + Deblocker implementation + +endmenu + +menu "Filesystem Configuration" + +config DISK_LABEL + bool "Disk-Label" + default y + help + Disk-label package implementation + +config PART_SUPPORT + depends on DISK_LABEL + bool "Partition support" + default y + help + Support for partition tables + +config MAC_PARTS + depends on PART_SUPPORT && BIG_ENDIAN + bool "Mac partition support" + default y + help + Support for Macintosh partition tables + +config PC_PARTS + depends on PART_SUPPORT + bool "PC style partition support" + default y + help + Support for PC style partition tables + +config FS + depends on DISK_LABEL + bool "Filesystem Support" + default y + help + Include filesystem support + +config HFS + depends on FS && BIG_ENDIAN + bool "HFS support" + default y + help + Include HFS support + +config HFSP + depends on FS && BIG_ENDIAN + bool "HFS+ support" + default y + help + Include HFS+ support + +config GRUBFS + depends on FS + bool "Additional Filesystems (from GRUB)" + default y + help + Grub provides a lot of filesystem drivers. + +source "fs/grubfs/Kconfig" + +config DEBUG_FS + depends on FS + bool "Debugging output for Filesystem code" + default y + help + Say Y here if you want to debug the filesystem layer + +endmenu + +menu "Miscellaneous" + +config LINUXBIOS + bool "Support reading LinuxBIOS table" + default y + help + If you want to boot OpenBIOS as a LinuxBIOS payload, + you should say Y here. + +endmenu diff --git a/qemu/roms/openbios/libopenbios/aout_load.c b/qemu/roms/openbios/libopenbios/aout_load.c new file mode 100644 index 000000000..e9d200251 --- /dev/null +++ b/qemu/roms/openbios/libopenbios/aout_load.c @@ -0,0 +1,176 @@ +/* a.out boot loader + * As we have seek, this implementation can be straightforward. + * 2003-07 by SONE Takeshi + */ + +#include "config.h" +#include "kernel/kernel.h" + +#ifdef CONFIG_SPARC64 +#define CONFIG_SPARC64_PAGE_SIZE_8KB +#endif + +/* NextStep bootloader on SPARC32 expects the a.out header directly + below load-base (0x4000) */ +#ifdef CONFIG_SPARC32 +#define AOUT_HEADER_COPY +#endif + +#include "libopenbios/sys_info.h" +#include "libopenbios/bindings.h" +#include "libopenbios/aout_load.h" +#include "libc/diskio.h" +#define printf printk +#define debug printk + +#define addr_fixup(addr) ((addr) & 0x00ffffff) + +static char *image_name, *image_version; +static int fd; + +static int +check_mem_ranges(struct sys_info *info, + unsigned long start, + unsigned long size) +{ + int j; + unsigned long end; + unsigned long prog_start, prog_end; + struct memrange *mem; + + prog_start = virt_to_phys(&_start); + prog_end = virt_to_phys(&_end); + + end = start + size; + + if (start < prog_start && end > prog_start) + goto conflict; + if (start < prog_end && end > prog_end) + goto conflict; + mem = info->memrange; + for (j = 0; j < info->n_memranges; j++) { + if (mem[j].base <= start && mem[j].base + mem[j].size >= end) + break; + } + if (j >= info->n_memranges) + goto badseg; + return 1; + + conflict: + printf("%s occupies [%#lx-%#lx]\n", program_name, prog_start, prog_end); + + badseg: + printf("A.out file [%#lx-%#lx] doesn't fit into memory\n", start, end - 1); + return 0; +} + +int +is_aout(struct exec *ehdr) +{ + return ((ehdr->a_info & 0xffff) == OMAGIC + || (ehdr->a_info & 0xffff) == NMAGIC + || (ehdr->a_info & 0xffff) == ZMAGIC + || (ehdr->a_info & 0xffff) == QMAGIC); +} + +int +aout_load(struct sys_info *info, ihandle_t dev) +{ + int retval = -1; + struct exec ehdr; + unsigned long start, size; + unsigned int offset; + + image_name = image_version = NULL; + + /* Mark the saved-program-state as invalid */ + feval("0 state-valid !"); + + fd = open_ih(dev); + if (fd == -1) { + goto out; + } + + for (offset = 0; offset < 16 * 512; offset += 512) { + seek_io(fd, offset); + if (read_io(fd, &ehdr, sizeof ehdr) != sizeof ehdr) { + debug("Can't read a.out header\n"); + retval = LOADER_NOT_SUPPORT; + goto out; + } + if (is_aout(&ehdr)) + break; + } + + if (!is_aout(&ehdr)) { + debug("Not a bootable a.out image\n"); + retval = LOADER_NOT_SUPPORT; + goto out; + } + + if (ehdr.a_text == 0x30800007) + ehdr.a_text=64*1024; + + if (N_MAGIC(ehdr) == NMAGIC) { + size = addr_fixup(N_DATADDR(ehdr)) + addr_fixup(ehdr.a_data); + } else { + size = addr_fixup(ehdr.a_text) + addr_fixup(ehdr.a_data); + } + + if (size < 7680) + size = 7680; + + fword("load-base"); + start = POP(); // N_TXTADDR(ehdr); + + if (!check_mem_ranges(info, start, size)) + goto out; + + printf("Loading a.out %s...\n", image_name ? image_name : "image"); + + seek_io(fd, offset + N_TXTOFF(ehdr)); + + if (N_MAGIC(ehdr) == NMAGIC) { + if ((size_t)read_io(fd, (void *)start, ehdr.a_text) != ehdr.a_text) { + printf("Can't read program text segment (size 0x" FMT_aout_ehdr ")\n", ehdr.a_text); + goto out; + } + if ((size_t)read_io(fd, (void *)(start + N_DATADDR(ehdr)), ehdr.a_data) != ehdr.a_data) { + printf("Can't read program data segment (size 0x" FMT_aout_ehdr ")\n", ehdr.a_data); + goto out; + } + } else { + if ((size_t)read_io(fd, (void *)start, size) != size) { + printf("Can't read program (size 0x" FMT_sizet ")\n", size); + goto out; + } + } + + debug("Loaded %lu bytes\n", size); + debug("entry point is %#lx\n", start); + +#ifdef AOUT_HEADER_COPY + // Copy the a.out header just before start + memcpy((char *)(start - 0x20), &ehdr, 0x20); +#endif + + // Initialise saved-program-state + PUSH(addr_fixup(start)); + feval("saved-program-state >sps.entry !"); + PUSH(size); + feval("saved-program-state >sps.file-size !"); + feval("aout saved-program-state >sps.file-type !"); + + feval("-1 state-valid !"); + +out: + close_io(fd); + return retval; +} + +void +aout_init_program(void) +{ + // Currently not implemented + feval("0 state-valid !"); +} diff --git a/qemu/roms/openbios/libopenbios/bindings.c b/qemu/roms/openbios/libopenbios/bindings.c new file mode 100644 index 000000000..5323421f5 --- /dev/null +++ b/qemu/roms/openbios/libopenbios/bindings.c @@ -0,0 +1,524 @@ +/* + * Creation Date: <2003/11/24 12:30:18 samuel> + * Time-stamp: <2004/01/07 19:37:38 samuel> + * + * <bindings.c> + * + * Forth bindings + * + * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#include "config.h" +#include "libopenbios/bindings.h" +#include "libc/string.h" +#include "libc/stdlib.h" +#include "libc/byteorder.h" + + +/************************************************************************/ +/* forth interface glue */ +/************************************************************************/ + +void +push_str( const char *str ) +{ + PUSH( pointer2cell(str) ); + PUSH( str ? strlen(str) : 0 ); +} + +/* WARNING: sloooow - AVOID */ +cell +feval( const char *str ) +{ + push_str( str ); + return eword("evaluate", 2); +} + +cell +_eword( const char *word, xt_t *cache_xt, int nargs ) +{ + static xt_t catch_xt = 0; + cell ret = -1; + + if( !catch_xt ) + catch_xt = findword("catch"); + if( !*cache_xt ) + *cache_xt = findword( (char*)word ); + + if( *cache_xt ) { + PUSH_xt( *cache_xt ); + enterforth( catch_xt ); + if( (ret=POP()) ) + dstackcnt -= nargs; + } + return ret; +} + +/* note: only the built-in dictionary is searched */ +int +_fword( const char *word, xt_t *cache_xt ) +{ + if( !*cache_xt ) + *cache_xt = findword( (char*)word ); + + if( *cache_xt ) { + enterforth( *cache_xt ); + return 0; + } + return -1; +} + +int +_selfword( const char *method, xt_t *cache_xt ) +{ + if( !*cache_xt ) + *cache_xt = find_ih_method( method, my_self() ); + if( *cache_xt ) { + enterforth( *cache_xt ); + return 0; + } + return -1; +} + +int +_parword( const char *method, xt_t *cache_xt ) +{ + if( !*cache_xt ) + *cache_xt = find_ih_method( method, my_parent() ); + if( *cache_xt ) { + enterforth( *cache_xt ); + return 0; + } + return -1; +} + +void +bind_func( const char *name, void (*func)(void) ) +{ + PUSH( pointer2cell(func) ); + push_str( name ); + fword("is-cfunc"); +} + +void +bind_xtfunc( const char *name, xt_t xt, ucell arg, void (*func)(void) ) +{ + PUSH_xt( xt ); + PUSH( arg ); + PUSH( pointer2cell(func) ); + push_str( name ); + fword("is-xt-cfunc"); +} + +xt_t +bind_noname_func( void (*func)(void) ) +{ + PUSH( pointer2cell(func) ); + fword("is-noname-cfunc"); + return POP_xt(); +} + +void +throw( int error ) +{ + PUSH( error ); + fword("throw"); +} + + +/************************************************************************/ +/* ihandle related */ +/************************************************************************/ + +phandle_t +ih_to_phandle( ihandle_t ih ) +{ + PUSH_ih( ih ); + fword("ihandle>phandle"); + return POP_ph(); +} + +ihandle_t +my_parent( void ) +{ + fword("my-parent"); + return POP_ih(); +} + +ihandle_t +my_self( void ) +{ + fword("my-self"); + return POP_ih(); +} + +xt_t +find_package_method( const char *method, phandle_t ph ) +{ + push_str( method ); + PUSH_ph( ph ); + fword("find-method"); + if( POP() ) + return POP_xt(); + return 0; +} + +xt_t +find_ih_method( const char *method, ihandle_t ih ) +{ + return find_package_method( method, ih_to_phandle(ih) ); +} + + +xt_t +find_parent_method( const char *method ) +{ + return find_ih_method( method, my_parent() ); +} + +void +call_package( xt_t xt, ihandle_t ihandle ) +{ + PUSH_xt( xt ); + PUSH_ih( ihandle ); + fword("call-package"); +} + +void +call_parent( xt_t xt ) +{ + PUSH_xt( xt ); + fword("call-parent"); +} + +void +call_parent_method( const char *method ) +{ + push_str( method ); + fword("$call-parent"); +} + + +/************************************************************************/ +/* open/close package/dev */ +/************************************************************************/ + +ihandle_t +open_dev( const char *spec ) +{ + push_str( spec ); + fword("open-dev"); + return POP_ih(); +} + +void +close_dev( ihandle_t ih ) +{ + PUSH_ih( ih ); + fword("close-dev"); +} + +ihandle_t +open_package( const char *argstr, phandle_t ph ) +{ + push_str( argstr ); + PUSH_ph( ph ); + fword("open-package"); + return POP_ih(); +} + +void +close_package( ihandle_t ih ) +{ + PUSH_ih( ih ); + fword("close-package"); +} + + +/************************************************************************/ +/* ihandle arguments */ +/************************************************************************/ + +char * +pop_fstr_copy( void ) +{ + int len = POP(); + char *str, *p = (char*)cell2pointer(POP()); + if( !len ) + return NULL; + str = malloc( len + 1 ); + if( !str ) + return NULL; + memcpy( str, p, len ); + str[len] = 0; + return str; +} + +char * +my_args_copy( void ) +{ + fword("my-args"); + return pop_fstr_copy(); +} + + +/************************************************************************/ +/* properties */ +/************************************************************************/ + +void +set_property( phandle_t ph, const char *name, const char *buf, int len ) +{ + if( !ph ) { + printk("set_property: NULL phandle\n"); + return; + } + PUSH(pointer2cell(buf)); + PUSH(len); + push_str( name ); + PUSH_ph(ph); + fword("set-property"); +} + +void +set_int_property( phandle_t ph, const char *name, u32 val ) +{ + u32 swapped=__cpu_to_be32(val); + set_property( ph, name, (char*)&swapped, sizeof(swapped) ); +} + +char * +get_property( phandle_t ph, const char *name, int *retlen ) +{ + int len; + + if( retlen ) + *retlen = -1; + + push_str( name ); + PUSH_ph( ph ); + fword("get-package-property"); + if( POP() ) + return NULL; + len = POP(); + if( retlen ) + *retlen = len; + return (char*)cell2pointer(POP()); +} + +u32 +get_int_property( phandle_t ph, const char *name, int *retlen ) +{ + u32 *p; + + if( !(p=(u32 *)get_property(ph, name, retlen)) ) + return 0; + return __be32_to_cpu(*p); +} + + +/************************************************************************/ +/* device selection / iteration */ +/************************************************************************/ + +void +activate_dev( phandle_t ph ) +{ + PUSH_ph( ph ); + fword("active-package!"); +} + +phandle_t +activate_device( const char *str ) +{ + phandle_t ph = find_dev( str ); + activate_dev( ph ); + return ph; +} + +void +device_end( void ) +{ + fword("device-end"); +} + +phandle_t +get_cur_dev( void ) +{ + fword("active-package"); + return POP_ph(); +} + +phandle_t +find_dev( const char *path ) +{ + phandle_t ret = 0; + push_str( path ); + fword("(find-dev)"); + if( POP() ) + return POP_ph(); + return ret; +} + +phandle_t +dt_iter_begin( void ) +{ + fword("iterate-tree-begin"); + return POP_ph(); +} + +phandle_t +dt_iterate( phandle_t last_tree ) +{ + if( !last_tree ) + return dt_iter_begin(); + + PUSH_ph( last_tree ); + fword("iterate-tree"); + return POP_ph(); +} + +phandle_t +dt_iterate_type( phandle_t last_tree, const char *type ) +{ + if( !last_tree ) + last_tree = dt_iter_begin(); + + /* root node is never matched but we don't care about that */ + while( (last_tree = dt_iterate(last_tree)) ) { + char *s = get_property( last_tree, "device_type", NULL ); + if( s && !strcmp(type, s) ) + break; + } + return last_tree; +} + + +/************************************************************************/ +/* node methods */ +/************************************************************************/ + +void +make_openable( int only_parents ) +{ + phandle_t ph, save_ph = get_cur_dev(); + PUSH_ph( save_ph ); + + for( ;; ) { + if( only_parents++ ) + fword("parent"); + if( !(ph=POP_ph()) ) + break; + activate_dev( ph ); + PUSH_ph( ph ); + fword("is-open"); + } + activate_dev( save_ph ); +} + +static void +call1_func( void ) +{ + void (*func)(cell v); + func = (void*)cell2pointer(POP()); + + (*func)( POP() ); +} + + +static void +add_methods( int flags, int size, const method_t *methods, int nmet ) +{ + xt_t xt=0; + int i; + + /* nodes might be matched multiple times */ + if( find_package_method(methods[0].name, get_cur_dev()) ) + return; + + if( size ) { + PUSH( size ); + fword("is-ibuf"); + xt = POP_xt(); + } + + for( i=0; i<nmet; i++ ) { + /* null-name methods specify static initializers */ + if( !methods[i].name ) { + typedef void (*initfunc)( void *p ); + char *buf = NULL; + if( xt ) { + enterforth( xt ); + buf = (char*)cell2pointer(POP()); + } + (*(initfunc)methods[i].func)( buf ); + continue; + } + if( !size ) + bind_func( methods[i].name, methods[i].func ); + else + bind_xtfunc( methods[i].name, xt, pointer2cell(methods[i].func), + &call1_func ); + } + + if( flags & INSTALL_OPEN ) + make_openable(0); +} + +void +bind_node( int flags, int size, const char * const *paths, int npaths, + const method_t *methods, int nmet ) +{ + phandle_t save_ph = get_cur_dev(); + int i; + + for( i=0; i<npaths; i++ ) { + const char *name = paths[i]; + + /* type matching? */ + if( *name == 'T' ) { + phandle_t ph = 0; + name++; + while( (ph=dt_iterate_type(ph, name)) ) { + activate_dev( ph ); + add_methods( flags, size, methods, nmet ); + } + continue; + } + + /* path patching */ + if( activate_device(name) ) + add_methods( flags, size, methods, nmet ); + else if( *name == '+' ) { + /* create node (and missing parents) */ + if( !activate_device(++name) ) { + push_str( name ); + fword("create-node"); + } + add_methods( flags, size, methods, nmet ); + } + } + activate_dev( save_ph ); +} + +phandle_t +bind_new_node( int flags, int size, const char *name, + const method_t *methods, int nmet ) +{ + phandle_t save_ph = get_cur_dev(); + phandle_t new_ph; + /* create node */ + push_str( name ); + fword("create-node"); + add_methods( flags, size, methods, nmet ); + new_ph = get_cur_dev(); + + activate_dev( save_ph ); + return new_ph; +} diff --git a/qemu/roms/openbios/libopenbios/bootcode_load.c b/qemu/roms/openbios/libopenbios/bootcode_load.c new file mode 100644 index 000000000..0fabf55c1 --- /dev/null +++ b/qemu/roms/openbios/libopenbios/bootcode_load.c @@ -0,0 +1,99 @@ +/* + * Raw bootcode loader (CHRP/Apple %BOOT) + * Written by Mark Cave-Ayland 2013 + */ + +#include "config.h" +#include "kernel/kernel.h" +#include "libopenbios/bindings.h" +#include "libopenbios/bootcode_load.h" +#include "libc/diskio.h" +#include "drivers/drivers.h" +#define printf printk +#define debug printk + + +int +bootcode_load(ihandle_t dev) +{ + int retval = -1, count = 0, fd; + unsigned long bootcode, loadbase, entry, size, offset; + ihandle_t bootcode_info; + + /* Mark the saved-program-state as invalid */ + feval("0 state-valid !"); + + fd = open_ih(dev); + if (fd == -1) { + goto out; + } + + /* If we don't have the get-bootcode-info word then we don't support + loading bootcode via %BOOT */ + bootcode_info = find_ih_method("get-bootcode-info", dev); + if (!bootcode_info) { + goto out; + } + + /* Default to loading at load-base */ + fword("load-base"); + loadbase = POP(); + entry = loadbase; + size = 0; + +#ifdef CONFIG_PPC + /* + * Apple OF does not honor load-base and instead uses pmBootLoad + * value from the boot partition descriptor. + * + * Tested with: + * a debian image with QUIK installed + * a debian image with iQUIK installed (https://github.com/andreiw/quik) + * an IQUIK boot floppy + * a NetBSD boot floppy (boots stage 2) + */ + if (is_apple()) { + PUSH(bootcode_info); + fword("execute"); + + loadbase = POP(); + entry = POP(); + size = POP(); + } +#endif + + bootcode = loadbase; + offset = 0; + + while(1) { + if (seek_io(fd, offset) == -1) + break; + count = read_io(fd, (void *)bootcode, 512); + offset += count; + bootcode += count; + } + + /* If we didn't read anything then exit */ + if (!count) { + goto out; + } + + /* Use proper file size if we got it from bootcode info */ + if (size == 0) { + size = offset; + } + + /* Initialise saved-program-state */ + PUSH(entry); + feval("saved-program-state >sps.entry !"); + PUSH(size); + feval("saved-program-state >sps.file-size !"); + feval("bootcode saved-program-state >sps.file-type !"); + + feval("-1 state-valid !"); + +out: + close_io(fd); + return retval; +} + diff --git a/qemu/roms/openbios/libopenbios/bootinfo_load.c b/qemu/roms/openbios/libopenbios/bootinfo_load.c new file mode 100644 index 000000000..fa9e36bd4 --- /dev/null +++ b/qemu/roms/openbios/libopenbios/bootinfo_load.c @@ -0,0 +1,263 @@ +/* + * + * <bootinfo_load.c> + * + * bootinfo file loader + * + * Copyright (C) 2009 Laurent Vivier (Laurent@vivier.eu) + * + * Original XML parser by Blue Swirl <blauwirbel@gmail.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#include "config.h" +#include "libopenbios/bindings.h" +#include "libopenbios/bootinfo_load.h" +#include "libopenbios/ofmem.h" +#include "libc/vsprintf.h" + +//#define DEBUG_BOOTINFO + +#ifdef DEBUG_BOOTINFO +#define DPRINTF(fmt, args...) \ + do { printk("%s: " fmt, __func__ , ##args); } while (0) +#else +#define DPRINTF(fmt, args...) \ + do { } while (0) +#endif + +static char * +get_device( const char *path ) +{ + int i; + static char buf[1024]; + + for (i = 0; i < sizeof(buf) && path[i] && path[i] != ':'; i++) + buf[i] = path[i]; + buf[i] = 0; + + return buf; +} + +static char * +get_partition( const char *path ) +{ + static char buf[2]; + + buf[0] = '\0'; + buf[1] = '\0'; + + while ( *path && *path != ':' ) + path++; + + if (!*path) + return buf; + path++; + + if (path[0] == ',' || !strchr(path, ',')) /* if there is not a ',' or no partition id then return */ + return buf; + + /* Must be a partition id */ + buf[0] = path[0]; + + return buf; +} + +static char * +get_filename( const char * path , char **dirname) +{ + static char buf[1024]; + char *filename; + + while ( *path && *path != ':' ) + path++; + + if (!*path) { + *dirname = NULL; + return NULL; + } + path++; + + while ( *path && isdigit(*path) ) + path++; + + if (*path == ',') + path++; + + strncpy(buf, path, sizeof(buf)); + buf[sizeof(buf) - 1] = 0; + + filename = strrchr(buf, '\\'); + if (filename) { + *dirname = buf; + (*filename++) = 0; + } else { + *dirname = NULL; + filename = buf; + } + + return filename; +} + +int +is_bootinfo(char *bootinfo) +{ + return (strncasecmp(bootinfo, "<chrp-boot", 10) ? 0 : -1); +} + +int +bootinfo_load(struct sys_info *info, const char *filename) +{ + // Currently not implemented + return LOADER_NOT_SUPPORT; +} + +/* + Parse SGML structure like: + <chrp-boot> + <description>Debian/GNU Linux Installation on IBM CHRP hardware</description> + <os-name>Debian/GNU Linux for PowerPC</os-name> + <boot-script>boot &device;:\install\yaboot</boot-script> + <icon size=64,64 color-space=3,3,2> + + CHRP system bindings are described at: + http://playground.sun.com/1275/bindings/chrp/chrp1_7a.ps +*/ + +void +bootinfo_init_program(void) +{ + char *base; + int proplen; + phandle_t chosen; + int tag, taglen, script, scriptlen, scriptvalid, entity, chrp; + char tagbuf[128], c; + char *device, *filename, *directory, *partition; + int current, size; + char *bootscript; + char *tmp; + char bootpath[1024]; + + /* Parse the boot script */ + + chosen = find_dev("/chosen"); + tmp = get_property(chosen, "bootpath", &proplen); + memcpy(bootpath, tmp, proplen); + bootpath[proplen] = 0; + + DPRINTF("bootpath %s\n", bootpath); + + device = get_device(bootpath); + partition = get_partition(bootpath); + filename = get_filename(bootpath, &directory); + + feval("load-base"); + base = (char*)cell2pointer(POP()); + + feval("load-size"); + size = POP(); + + bootscript = malloc(size); + if (bootscript == NULL) { + DPRINTF("Can't malloc %d bytes\n", size); + return; + } + + if (!is_bootinfo(base)) { + DPRINTF("Not a valid bootinfo memory image\n"); + free(bootscript); + return; + } + + chrp = 0; + tag = 0; + taglen = 0; + script = 0; + scriptvalid = 0; + scriptlen = 0; + entity = 0; + current = 0; + while (current < size) { + + c = base[current++]; + + if (c == '<') { + script = 0; + tag = 1; + taglen = 0; + } else if (c == '>') { + tag = 0; + tagbuf[taglen] = '\0'; + if (strncasecmp(tagbuf, "chrp-boot", 9) == 0) { + chrp = 1; + } else if (chrp == 1) { + if (strncasecmp(tagbuf, "boot-script", 11) == 0) { + script = 1; + scriptlen = 0; + } else if (strncasecmp(tagbuf, "/boot-script", 12) == 0) { + + script = 0; + bootscript[scriptlen] = '\0'; + + DPRINTF("got bootscript %s\n", + bootscript); + + scriptvalid = -1; + + break; + } else if (strncasecmp(tagbuf, "/chrp-boot", 10) == 0) + break; + } + } else if (tag && taglen < sizeof(tagbuf)) { + tagbuf[taglen++] = c; + } else if (script && c == '&') { + entity = 1; + taglen = 0; + } else if (entity && c ==';') { + entity = 0; + tagbuf[taglen] = '\0'; + if (strncasecmp(tagbuf, "lt", 2) == 0) { + bootscript[scriptlen++] = '<'; + } else if (strncasecmp(tagbuf, "gt", 2) == 0) { + bootscript[scriptlen++] = '>'; + } else if (strncasecmp(tagbuf, "device", 6) == 0) { + strcpy(bootscript + scriptlen, device); + scriptlen += strlen(device); + } else if (strncasecmp(tagbuf, "partition", 9) == 0) { + strcpy(bootscript + scriptlen, partition); + scriptlen += strlen(partition); + } else if (strncasecmp(tagbuf, "directory", 9) == 0) { + strcpy(bootscript + scriptlen, directory); + scriptlen += strlen(directory); + } else if (strncasecmp(tagbuf, "filename", 8) == 0) { + strcpy(bootscript + scriptlen, filename); + scriptlen += strlen(filename); + } else if (strncasecmp(tagbuf, "full-path", 9) == 0) { + strcpy(bootscript + scriptlen, bootpath); + scriptlen += strlen(bootpath); + } else { /* unknown, keep it */ + bootscript[scriptlen] = '&'; + strcpy(bootscript + scriptlen + 1, tagbuf); + scriptlen += taglen + 1; + bootscript[scriptlen] = ';'; + scriptlen++; + } + } else if (entity && taglen < sizeof(tagbuf)) { + tagbuf[taglen++] = c; + } else if (script && scriptlen < size) { + bootscript[scriptlen++] = c; + } + } + + /* If the payload is bootinfo then we execute it immediately */ + if (scriptvalid) { + DPRINTF("bootscript: %s\n", bootscript); + feval(bootscript); + } + else + DPRINTF("Unable to parse bootinfo bootscript\n"); +} diff --git a/qemu/roms/openbios/libopenbios/build.xml b/qemu/roms/openbios/libopenbios/build.xml new file mode 100644 index 000000000..feb8f6c7d --- /dev/null +++ b/qemu/roms/openbios/libopenbios/build.xml @@ -0,0 +1,31 @@ +<build> + + <library name="openbios" type="static" target="target"> + <object source="aout_load.c" condition="LOADER_AOUT"/> + <object source="bindings.c"/> + <object source="bootcode_load.c" condition="LOADER_BOOTCODE"/> + <object source="bootinfo_load.c" condition="LOADER_BOOTINFO"/> + <object source="client.c"/> + <object source="console.c"/> + <object source="elf_info.c" /> + <object source="elf_load.c" condition="LOADER_ELF"/> + <object source="font_8x8.c" condition="FONT_8X8"/> + <object source="font_8x16.c" condition="FONT_8X16"/> + <object source="fcode_load.c" condition="LOADER_FCODE"/> + <object source="forth_load.c" condition="LOADER_FORTH"/> + <object source="init.c"/> + <object source="initprogram.c"/> + <object source="ipchecksum.c"/> + <object source="load.c"/> + <object source="linuxbios_info.c" condition="LINUXBIOS"/> + <object source="ofmem_common.c" condition="OFMEM"/> + <object source="xcoff_load.c" condition="LOADER_XCOFF"/> + <object source="video_common.c"/> + </library> + + <dictionary name="openbios" target="forth"> + <object source="clib.fs"/> + <object source="helpers.fs"/> + </dictionary> + +</build> diff --git a/qemu/roms/openbios/libopenbios/clib.fs b/qemu/roms/openbios/libopenbios/clib.fs new file mode 100644 index 000000000..04dd0aa43 --- /dev/null +++ b/qemu/roms/openbios/libopenbios/clib.fs @@ -0,0 +1,36 @@ +\ tag: C helpers +\ +\ Misc C helpers +\ +\ Copyright (C) 2003, 2004 Samuel Rydh +\ +\ See the file "COPYING" for further information about +\ the copyright and warranty status of this work. +\ + +\ should perhaps be moved somewhere else +: set-property ( buf len propname propname-len phandle -- ) + >r 2swap encode-bytes 2swap r> encode-property +; + +\ install C function +: is-cfunc ( funcaddr word word-len -- ) + $create , does> @ call +; + +\ install a nameless C function +: is-noname-cfunc ( funcaddr -- xt ) + 0 0 is-cfunc last-xt +; + +\ is-xt-cfunc installs a function which does the following: +\ - xt is executes +\ - funcarg is pushed +\ - funcaddr is called + +: is-xt-cfunc ( xt|0 funcarg funcaddr word word-len -- ) + is-func-begin + rot ?dup if , then + swap ['] (lit) , , ['] (lit) , , ['] call , + is-func-end +; diff --git a/qemu/roms/openbios/libopenbios/client.c b/qemu/roms/openbios/libopenbios/client.c new file mode 100644 index 000000000..8b3d582b6 --- /dev/null +++ b/qemu/roms/openbios/libopenbios/client.c @@ -0,0 +1,367 @@ +/* + * Creation Date: <2003/11/25 14:29:08 samuel> + * Time-stamp: <2004/03/27 01:13:53 samuel> + * + * <client.c> + * + * OpenFirmware client interface + * + * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#include "config.h" +#include "libopenbios/bindings.h" +#include "libopenbios/of.h" + +/* Uncomment to enable debug printout of client interface calls */ +//#define DEBUG_CIF +//#define DUMP_IO + +/* OF client interface. r3 points to the argument array. On return, + * r3 should contain 0==true or -1==false. r4-r12,cr0,cr1 may + * be modified freely. + * + * -1 should only be returned if the control transfer to OF fails + * (it doesn't) or if the function is unimplemented. + */ + +#define PROM_MAX_ARGS 10 +typedef struct prom_args { + prom_uarg_t service; + prom_arg_t nargs; + prom_arg_t nret; + prom_uarg_t args[PROM_MAX_ARGS]; +} __attribute__((packed)) prom_args_t; + +static inline const char * +arg2pointer(prom_uarg_t value) +{ + return (char*)(uintptr_t)value; +} + +static inline const char * +get_service(prom_args_t *pb) +{ + return arg2pointer(pb->service); +} + +#ifdef DEBUG_CIF +static void memdump(const char *mem, unsigned long size) +{ + int i; + + if (size == (unsigned long) -1) + return; + + for (i = 0; i < size; i += 16) { + int j; + + printk("0x%08lx ", (unsigned long)mem + i); + + for (j = 0; j < 16 && i + j < size; j++) + printk(" %02x", *(unsigned char*)(mem + i + j)); + + for ( ; j < 16; j++) + printk(" __"); + + printk(" "); + + for (j = 0; j < 16 && i + j < size; j++) { + unsigned char c = *(mem + i + j); + if (isprint(c)) + printk("%c", c); + else + printk("."); + } + printk("\n"); + } +} + +static void dump_service(prom_args_t *pb) +{ + int i; + const char *service = get_service(pb); + if (strcmp(service, "test") == 0) { + printk("test(\"%s\") = ", arg2pointer(pb->args[0])); + } else if (strcmp(service, "peer") == 0) { + printk("peer(0x" FMT_prom_uargx ") = ", pb->args[0]); + } else if (strcmp(service, "child") == 0) { + printk("child(0x" FMT_prom_uargx ") = ", pb->args[0]); + } else if (strcmp(service, "parent") == 0) { + printk("parent(0x" FMT_prom_uargx ") = ", pb->args[0]); + } else if (strcmp(service, "instance-to-package") == 0) { + printk("instance-to-package(0x" FMT_prom_uargx ") = ", pb->args[0]); + } else if (strcmp(service, "getproplen") == 0) { + printk("getproplen(0x" FMT_prom_uargx ", \"%s\") = ", + pb->args[0], arg2pointer(pb->args[1])); + } else if (strcmp(service, "getprop") == 0) { + printk("getprop(0x" FMT_prom_uargx ", \"%s\", 0x" FMT_prom_uargx ", " FMT_prom_arg ") = ", + pb->args[0], arg2pointer(pb->args[1]), + pb->args[2], pb->args[3]); + } else if (strcmp(service, "nextprop") == 0) { + printk("nextprop(0x" FMT_prom_uargx ", \"%s\", 0x" FMT_prom_uargx ") = ", + pb->args[0], arg2pointer(pb->args[1]), pb->args[2]); + } else if (strcmp(service, "setprop") == 0) { + printk("setprop(0x" FMT_prom_uargx ", \"%s\", 0x" FMT_prom_uargx ", " FMT_prom_arg ")\n", + pb->args[0], arg2pointer(pb->args[1]), + pb->args[2], pb->args[3]); + memdump(arg2pointer(pb->args[2]), pb->args[3]); + printk(" = "); + } else if (strcmp(service, "canon") == 0) { + printk("canon(\"%s\", 0x" FMT_prom_uargx ", " FMT_prom_arg ")\n", + arg2pointer(pb->args[0]), pb->args[1], pb->args[2]); + } else if (strcmp(service, "finddevice") == 0) { + printk("finddevice(\"%s\") = ", arg2pointer(pb->args[0])); + } else if (strcmp(service, "instance-to-path") == 0) { + printk("instance-to-path(0x" FMT_prom_uargx ", 0x" FMT_prom_uargx ", " FMT_prom_arg ") = ", + pb->args[0], pb->args[1], pb->args[2]); + } else if (strcmp(service, "package-to-path") == 0) { + printk("package-to-path(0x" FMT_prom_uargx ", 0x" FMT_prom_uargx ", " FMT_prom_arg ") = ", + pb->args[0], pb->args[1], pb->args[2]); + } else if (strcmp(service, "open") == 0) { + printk("open(\"%s\") = ", arg2pointer(pb->args[0])); + } else if (strcmp(service, "close") == 0) { + printk("close(0x" FMT_prom_uargx ")\n", pb->args[0]); + } else if (strcmp(service, "read") == 0) { +#ifdef DUMP_IO + printk("read(0x" FMT_prom_uargx ", 0x" FMT_prom_uargx ", " FMT_prom_arg ") = ", + pb->args[0], pb->args[1], pb->args[2]); +#endif + } else if (strcmp(service, "write") == 0) { +#ifdef DUMP_IO + printk("write(0x" FMT_prom_uargx ", 0x" FMT_prom_uargx ", " FMT_prom_arg ")\n", + pb->args[0], pb->args[1], pb->args[2]); + memdump(arg2pointer(pb->args[1]), pb->args[2]); + printk(" = "); +#endif + } else if (strcmp(service, "seek") == 0) { +#ifdef DUMP_IO + printk("seek(0x" FMT_prom_uargx ", 0x" FMT_prom_uargx ", 0x" FMT_prom_uargx ") = ", + pb->args[0], pb->args[1], pb->args[2]); +#endif + } else if (strcmp(service, "claim") == 0) { + printk("claim(0x" FMT_prom_uargx ", " FMT_prom_arg ", " FMT_prom_arg ") = ", + pb->args[0], pb->args[1], pb->args[2]); + } else if (strcmp(service, "release") == 0) { + printk("release(0x" FMT_prom_uargx ", " FMT_prom_arg ")\n", + pb->args[0], pb->args[1]); + } else if (strcmp(service, "boot") == 0) { + printk("boot \"%s\"\n", arg2pointer(pb->args[0])); + } else if (strcmp(service, "enter") == 0) { + printk("enter()\n"); + } else if (strcmp(service, "exit") == 0) { + printk("exit()\n"); + } else if (strcmp(service, "test-method") == 0) { + printk("test-method(0x" FMT_prom_uargx ", \"%s\") = ", + pb->args[0], arg2pointer(pb->args[1])); + } else { + printk("of_client_interface: %s", service); + for( i = 0; i < pb->nargs; i++ ) + printk(" " FMT_prom_uargx, pb->args[i]); + printk("\n"); + } +} + +static void dump_return(prom_args_t *pb) +{ + int i; + const char *service = get_service(pb); + if (strcmp(service, "test") == 0) { + printk(FMT_prom_arg "\n", pb->args[pb->nargs]); + } else if (strcmp(service, "peer") == 0) { + printk("0x" FMT_prom_uargx "\n", pb->args[pb->nargs]); + } else if (strcmp(service, "child") == 0) { + printk("0x" FMT_prom_uargx "\n", pb->args[pb->nargs]); + } else if (strcmp(service, "parent") == 0) { + printk("0x" FMT_prom_uargx "\n", pb->args[pb->nargs]); + } else if (strcmp(service, "instance-to-package") == 0) { + printk("0x" FMT_prom_uargx "\n", pb->args[pb->nargs]); + } else if (strcmp(service, "getproplen") == 0) { + printk("0x" FMT_prom_uargx "\n", pb->args[pb->nargs]); + } else if (strcmp(service, "getprop") == 0) { + printk(FMT_prom_arg "\n", pb->args[pb->nargs]); + if ((prom_arg_t)pb->args[pb->nargs] != -1) + memdump(arg2pointer(pb->args[2]), MIN(pb->args[3], pb->args[pb->nargs])); + } else if (strcmp(service, "nextprop") == 0) { + printk(FMT_prom_arg "\n", pb->args[pb->nargs]); + memdump(arg2pointer(pb->args[2]), 32); + } else if (strcmp(service, "setprop") == 0) { + printk(FMT_prom_arg "\n", pb->args[pb->nargs]); + } else if (strcmp(service, "canon") == 0) { + printk(FMT_prom_arg "\n", pb->args[pb->nargs]); + memdump(arg2pointer(pb->args[1]), pb->args[pb->nargs]); + } else if (strcmp(service, "finddevice") == 0) { + printk("0x" FMT_prom_uargx "\n", pb->args[pb->nargs]); + } else if (strcmp(service, "instance-to-path") == 0) { + printk(FMT_prom_arg "\n", pb->args[pb->nargs]); + memdump(arg2pointer(pb->args[1]), pb->args[pb->nargs]); + } else if (strcmp(service, "package-to-path") == 0) { + printk(FMT_prom_arg "\n", pb->args[pb->nargs]); + memdump(arg2pointer(pb->args[1]), pb->args[pb->nargs]); + } else if (strcmp(service, "open") == 0) { + printk("0x" FMT_prom_uargx "\n", pb->args[pb->nargs]); + } else if (strcmp(service, "close") == 0) { + /* do nothing */ + } else if (strcmp(service, "read") == 0) { +#ifdef DUMP_IO + printk(FMT_prom_arg "\n", pb->args[pb->nargs]); + memdump(arg2pointer(pb->args[1]), pb->args[pb->nargs]); +#endif + } else if (strcmp(service, "write") == 0) { +#ifdef DUMP_IO + printk(FMT_prom_arg "\n", pb->args[pb->nargs]); +#endif + } else if (strcmp(service, "seek") == 0) { +#ifdef DUMP_IO + printk(FMT_prom_arg "\n", pb->args[pb->nargs]); +#endif + } else if (strcmp(service, "claim") == 0) { + printk("0x" FMT_prom_uargx "\n", pb->args[pb->nargs]); + } else if (strcmp(service, "release") == 0) { + /* do nothing */ + } else if (strcmp(service, "boot") == 0) { + /* do nothing */ + } else if (strcmp(service, "enter") == 0) { + /* do nothing */ + } else if (strcmp(service, "exit") == 0) { + /* do nothing */ + } else if (strcmp(service, "test-method") == 0) { + printk("0x" FMT_prom_uargx "\n", pb->args[pb->nargs]); + } else { + printk("of_client_interface return:"); + for (i = 0; i < pb->nret; i++) { + printk(" " FMT_prom_uargx, pb->args[pb->nargs + i]); + } + printk("\n"); + } +} +#endif + +/* call-method, interpret */ +static int +handle_calls(prom_args_t *pb) +{ + int i, j, dstacksave; + ucell val; + +#ifdef DEBUG_CIF + printk("%s %s ([" FMT_prom_arg "] -- [" FMT_prom_arg "])\n", + get_service(pb), arg2pointer(pb->args[0]), pb->nargs, pb->nret); +#endif + + dstacksave = dstackcnt; + for (i = pb->nargs - 1; i >= 0; i--) + PUSH(pb->args[i]); + + push_str(get_service(pb)); + fword("client-call-iface"); + + /* Ignore client-call-iface return */ + POP(); + + /* If the catch result is non-zero, restore stack and exit */ + val = POP(); + if (val) { + printk("%s %s failed with error " FMT_ucellx "\n", get_service(pb), arg2pointer(pb->args[0]), val); + dstackcnt = dstacksave; + return 0; + } + + /* Store catch result */ + pb->args[pb->nargs] = val; + + j = dstackcnt; + for (i = 1; i < pb->nret; i++, j--) { + if (dstackcnt > dstacksave) { + pb->args[pb->nargs + i] = POP(); + } + } + +#ifdef DEBUG_CIF + /* useful for debug but not necessarily an error */ + if (j != dstacksave) { + printk("%s '%s': possible argument error (" FMT_prom_arg "--" FMT_prom_arg ") got %d\n", + get_service(pb), arg2pointer(pb->args[0]), + pb->nargs - 2, pb->nret, j - dstacksave); + } + + printk("handle_calls return:"); + for (i = 0; i < pb->nret; i++) { + printk(" " FMT_prom_uargx, pb->args[pb->nargs + i]); + } + printk("\n"); +#endif + + dstackcnt = dstacksave; + return 0; +} + +int +of_client_interface(int *params) +{ + prom_args_t *pb = (prom_args_t*)params; + ucell val; + int i, j, dstacksave; + + if (pb->nargs < 0 || pb->nret < 0 || + pb->nargs + pb->nret > PROM_MAX_ARGS) + return -1; + +#ifdef DEBUG_CIF + dump_service(pb); +#endif + + /* call-method exceptions are special */ + if (!strcmp("call-method", get_service(pb)) || !strcmp("interpret", get_service(pb))) + return handle_calls(pb); + + dstacksave = dstackcnt; + for (i = pb->nargs - 1; i >= 0; i--) + PUSH(pb->args[i]); + + push_str(get_service(pb)); + fword("client-iface"); + + val = POP(); + if (val) { + if (val == -1) { + printk("Unimplemented service %s ([" FMT_prom_arg "] -- [" FMT_prom_arg "])\n", + get_service(pb), pb->nargs, pb->nret); + } else { +#ifdef DEBUG_CIF + printk("Error calling client interface: " FMT_ucellx "\n", val); +#endif + } + + dstackcnt = dstacksave; + return -1; + } + + j = dstackcnt; + for (i = 0; i < pb->nret; i++, j--) { + if (dstackcnt > dstacksave) { + pb->args[pb->nargs + i] = POP(); + } + } + +#ifdef DEBUG_CIF + if (j != dstacksave) { + printk("service %s: possible argument error (%d %d)\n", + get_service(pb), i, j - dstacksave); + + /* Some clients request less parameters than the CIF method + returns, e.g. getprop with OpenSolaris. Hence we drop any + stack parameters on exit after issuing a warning above */ + } + + dump_return(pb); +#endif + + dstackcnt = dstacksave; + return 0; +} diff --git a/qemu/roms/openbios/libopenbios/console.c b/qemu/roms/openbios/libopenbios/console.c new file mode 100644 index 000000000..7f3aad8ef --- /dev/null +++ b/qemu/roms/openbios/libopenbios/console.c @@ -0,0 +1,68 @@ +/* + * <console.c> + * + * Simple text console + * + * Copyright (C) 2005 Stefan Reinauer <stepan@openbios.org> + * Copyright (C) 2013 Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk> + * + * 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 + * + */ + +#include "config.h" +#include "libopenbios/bindings.h" +#include "libopenbios/console.h" +#include "drivers/drivers.h" + +/* ****************************************************************** + * common functions, implementing simple concurrent console + * ****************************************************************** */ + +/* Dummy routines for when console is unassigned */ + +static int dummy_putchar(int c) +{ + return c; +} + +static int dummy_availchar(void) +{ + return 0; +} + +static int dummy_getchar(void) +{ + return 0; +} + +struct _console_ops console_ops = { + .putchar = dummy_putchar, + .availchar = dummy_availchar, + .getchar = dummy_getchar +}; + +#ifdef CONFIG_DEBUG_CONSOLE + +void init_console(struct _console_ops ops) +{ + console_ops = ops; +} + +int putchar(int c) +{ + return (*console_ops.putchar)(c); +} + +int availchar(void) +{ + return (*console_ops.availchar)(); +} + +int getchar(void) +{ + return (*console_ops.getchar)(); +} +#endif // CONFIG_DEBUG_CONSOLE diff --git a/qemu/roms/openbios/libopenbios/elf_info.c b/qemu/roms/openbios/libopenbios/elf_info.c new file mode 100644 index 000000000..f7febef9d --- /dev/null +++ b/qemu/roms/openbios/libopenbios/elf_info.c @@ -0,0 +1,151 @@ +/* Support for ELF Boot Proposal as a boot image */ +#include "config.h" +#include "arch/common/elf_boot.h" +#include "libopenbios/sys_info.h" +#include "asm/io.h" +#include "libopenbios/ipchecksum.h" +#include "openbios-version.h" +#define printf printk +#define debug printk + +/* ELF image notes provide information to the loader who boots us */ + +/* This compiles and generates correct PT_NOTE segment for me. + * If it doesn't, use assembly version below. */ + +struct elf_image_note { + Elf_Nhdr hdr0; + char name0[sizeof(ELF_NOTE_BOOT)]; + char prog_name[sizeof(PROGRAM_NAME)]; + + Elf_Nhdr hdr1; + char name1[sizeof(ELF_NOTE_BOOT)]; + char version[sizeof(OPENBIOS_VERSION_STR)]; + + Elf_Nhdr hdr2; + char name2[sizeof(ELF_NOTE_BOOT)]; + unsigned short checksum; +}; + +const struct elf_image_note elf_image_notes + __attribute__ ((section (".note.ELFBoot"))) = +{ + .hdr0 = { + .n_namesz = sizeof(ELF_NOTE_BOOT), + .n_descsz = sizeof(PROGRAM_NAME), + .n_type = EIN_PROGRAM_NAME, + }, + .name0 = ELF_NOTE_BOOT, + .prog_name = PROGRAM_NAME, + + .hdr1 = { + .n_namesz = sizeof(ELF_NOTE_BOOT), + .n_descsz = sizeof(OPENBIOS_VERSION_STR), + .n_type = EIN_PROGRAM_VERSION, + }, + .name1 = ELF_NOTE_BOOT, + .version = OPENBIOS_VERSION_STR, + + .hdr2 = { + .n_namesz = sizeof(ELF_NOTE_BOOT), + .n_descsz = sizeof(unsigned short), + .n_type = EIN_PROGRAM_CHECKSUM, + }, + .name2 = ELF_NOTE_BOOT, + .checksum = 0, /* to be computed by external tool */ +}; + +/* This is refered by other files */ +const char *program_name = elf_image_notes.prog_name; +const char *program_version = elf_image_notes.version; + +#if 0 + + /* This tells the linker to make a PT_NOTE segment. + * If the section is named just ".note", it will be + * mixed up with useless .version notes generated by GCC. + */ + .section ".note.ELFBoot", "a" + + .align 4 + .int 2f - 1f + .int 4f - 3f + .int EIN_PROGRAM_NAME +1: .asciz "ELFBoot" +2: .align 4 +3: .asciz PROGRAM_NAME +4: + + .align 4 + .int 2f - 1f + .int 4f - 3f + .int EIN_PROGRAM_VERSION +1: .asciz "ELFBoot" +2: .align 4 +3: .asciz OPENBIOS_VERSION_STR +4: + + .align 4 + .int 2f - 1f + .int 4f - 3f + .int EIN_PROGRAM_CHECKSUM +1: .asciz "ELFBoot" +2: .align 4 +3: .short 0 +4: +#endif + +/* Collect information from the ELF bootloader + * Note that we have to copy them to our own memory, + * otherwise they might be overwritten afterward. */ +void collect_elfboot_info(struct sys_info *info) +{ + Elf_Bhdr *hdr = NULL; + char *addr, *end; + Elf_Nhdr *nhdr; + char *desc; + + if (info->boot_type == ELF_BHDR_MAGIC) + hdr = phys_to_virt(info->boot_data); + else + hdr = phys_to_virt(info->boot_arg); + + if (hdr->b_signature != ELF_BHDR_MAGIC) + return; + + if (ipchksum(hdr, hdr->b_size) != 0) { + printf("Broken ELF boot notes\n"); + return; + } + + addr = (char *) (hdr + 1); + end = addr + hdr->b_size; + while (addr < end) { + nhdr = (Elf_Nhdr *) addr; + addr += sizeof(Elf_Nhdr); + addr += (nhdr->n_namesz + 3) & ~3; + desc = addr; + addr += (nhdr->n_descsz + 3) & ~3; + + if (nhdr->n_namesz == 0) { + /* Standard notes */ + switch (nhdr->n_type) { + case EBN_FIRMWARE_TYPE: + info->firmware = strdup(desc); + break; + case EBN_BOOTLOADER_NAME: + debug("Bootloader: %s\n", desc); + break; + case EBN_BOOTLOADER_VERSION: + debug("Version: %s\n", desc); + break; + case EBN_COMMAND_LINE: + info->command_line = strdup(desc); + break; + case EBN_LOADED_IMAGE: + debug("Image name: %s\n", desc); + break; + } + } + } +} diff --git a/qemu/roms/openbios/libopenbios/elf_load.c b/qemu/roms/openbios/libopenbios/elf_load.c new file mode 100644 index 000000000..9c7850e11 --- /dev/null +++ b/qemu/roms/openbios/libopenbios/elf_load.c @@ -0,0 +1,537 @@ +/* ELF Boot loader + * As we have seek, this implementation can be straightforward. + * 2003-07 by SONE Takeshi + */ + +#include "config.h" +#include "kernel/kernel.h" +#include "libc/diskio.h" +#include "arch/common/elf_boot.h" +#include "libopenbios/elf_load.h" +#include "libopenbios/sys_info.h" +#include "libopenbios/ipchecksum.h" +#include "libopenbios/bindings.h" +#include "libopenbios/ofmem.h" +#define printf printk +#define debug printk + +#define DEBUG 0 + +#define MAX_HEADERS 0x20 +#define BS 0x100 /* smallest step used when looking for the ELF header */ + +#ifdef CONFIG_PPC +extern void flush_icache_range( char *start, char *stop ); +#endif + +/* FreeBSD and possibly others mask the high 8 bits */ +#define addr_fixup(addr) ((addr) & 0x00ffffff) + +static char *image_name, *image_version; +static int fd; + +/* Note: avoid name collision with platforms which have their own version of calloc() */ +static void *ob_calloc(size_t nmemb, size_t size) +{ + size_t alloc_size = nmemb * size; + void *mem; + + if (alloc_size < nmemb || alloc_size < size) { + printf("calloc overflow: %u, %u\n", nmemb, size); + return NULL; + } + + mem = malloc(alloc_size); + memset(mem, 0, alloc_size); + + return mem; +} + +static int check_mem_ranges(struct sys_info *info, + Elf_phdr *phdr, int phnum) +{ + int i, j; + unsigned long start, end; + unsigned long prog_start, prog_end; + struct memrange *mem; + + prog_start = virt_to_phys(&_start); + prog_end = virt_to_phys(&_end); + + for (i = 0; i < phnum; i++) { + if (phdr[i].p_type != PT_LOAD) + continue; + start = addr_fixup(phdr[i].p_paddr); + end = start + phdr[i].p_memsz; + if (start < prog_start && end > prog_start) + goto conflict; + if (start < prog_end && end > prog_end) + goto conflict; + mem=info->memrange; + for (j = 0; j < info->n_memranges; j++) { + if (mem[j].base <= start && mem[j].base + mem[j].size >= end) + break; + } + if (j >= info->n_memranges) + goto badseg; + } + return 1; + +conflict: + printf("%s occupies [%#lx-%#lx]\n", program_name, prog_start, prog_end); + +badseg: + printf("Segment %d [%#lx-%#lx] doesn't fit into memory\n", i, start, end-1); + return 0; +} + +static unsigned long process_image_notes(Elf_phdr *phdr, int phnum, + unsigned short *sum_ptr, + unsigned int offset) +{ + int i; + char *buf = NULL; + int retval = 0; + unsigned long addr, end; + Elf_Nhdr *nhdr; + const char *name; + void *desc; + + for (i = 0; i < phnum; i++) { + if (phdr[i].p_type != PT_NOTE) + continue; + buf = malloc(phdr[i].p_filesz); + seek_io(fd, offset + phdr[i].p_offset); + if ((size_t)read_io(fd, buf, phdr[i].p_filesz) != phdr[i].p_filesz) { + printf("Can't read note segment\n"); + goto out; + } + addr = (unsigned long) buf; + end = addr + phdr[i].p_filesz; + while (addr < end) { + nhdr = (Elf_Nhdr *) addr; + addr += sizeof(Elf_Nhdr); + name = (const char *) addr; + addr += (nhdr->n_namesz+3) & ~3; + desc = (void *) addr; + addr += (nhdr->n_descsz+3) & ~3; + + if (nhdr->n_namesz==sizeof(ELF_NOTE_BOOT) + && memcmp(name, ELF_NOTE_BOOT, sizeof(ELF_NOTE_BOOT))==0) { + if (nhdr->n_type == EIN_PROGRAM_NAME) { + image_name = ob_calloc(1, nhdr->n_descsz + 1); + memcpy(image_name, desc, nhdr->n_descsz); + } + if (nhdr->n_type == EIN_PROGRAM_VERSION) { + image_version = ob_calloc(1, nhdr->n_descsz + 1); + memcpy(image_version, desc, nhdr->n_descsz); + } + if (nhdr->n_type == EIN_PROGRAM_CHECKSUM) { + *sum_ptr = *(unsigned short *) desc; + debug("Image checksum: %#04x\n", *sum_ptr); + /* Where in the file */ + retval = phdr[i].p_offset + + (unsigned long) desc - (unsigned long) buf; + } + } + } + } +out: + close_io(fd); + if (buf) + free(buf); + return retval; +} + +static int load_segments(Elf_phdr *phdr, int phnum, + unsigned long checksum_offset, + unsigned int offset, unsigned long *bytes) +{ + //unsigned int start_time, time; + int i; + + *bytes = 0; + // start_time = currticks(); + for (i = 0; i < phnum; i++) { + if (phdr[i].p_type != PT_LOAD) + continue; + debug("segment %d addr:" FMT_elf " file:" FMT_elf " mem:" FMT_elf " ", + i, addr_fixup(phdr[i].p_paddr), phdr[i].p_filesz, phdr[i].p_memsz); + seek_io(fd, offset + phdr[i].p_offset); + debug("loading... "); + if ((size_t)read_io(fd, phys_to_virt(addr_fixup(phdr[i].p_paddr)), phdr[i].p_filesz) + != phdr[i].p_filesz) { + printf("Can't read program segment %d\n", i); + return 0; + } + bytes += phdr[i].p_filesz; + debug("clearing... "); + memset(phys_to_virt(addr_fixup(phdr[i].p_paddr) + phdr[i].p_filesz), 0, + phdr[i].p_memsz - phdr[i].p_filesz); + if (phdr[i].p_offset <= checksum_offset + && phdr[i].p_offset + phdr[i].p_filesz >= checksum_offset+2) { + debug("clearing checksum... "); + memset(phys_to_virt(addr_fixup(phdr[i].p_paddr) + checksum_offset + - phdr[i].p_offset), 0, 2); + } + debug("ok\n"); + + } + // time = currticks() - start_time; + //debug("Loaded %lu bytes in %ums (%luKB/s)\n", bytes, time, + // time? bytes/time : 0); + debug("Loaded %lu bytes \n", *bytes); + + return 1; +} + +static int verify_image(Elf_ehdr *ehdr, Elf_phdr *phdr, int phnum, + unsigned short image_sum) +{ + unsigned short sum, part_sum; + unsigned long offset; + int i; + + sum = 0; + offset = 0; + + part_sum = ipchksum(ehdr, sizeof *ehdr); + sum = add_ipchksums(offset, sum, part_sum); + offset += sizeof *ehdr; + + part_sum = ipchksum(phdr, phnum * sizeof(*phdr)); + sum = add_ipchksums(offset, sum, part_sum); + offset += phnum * sizeof(*phdr); + + for (i = 0; i < phnum; i++) { + if (phdr[i].p_type != PT_LOAD) + continue; + part_sum = ipchksum(phys_to_virt(addr_fixup(phdr[i].p_paddr)), phdr[i].p_memsz); + sum = add_ipchksums(offset, sum, part_sum); + offset += phdr[i].p_memsz; + } + + if (sum != image_sum) { + printf("Verify FAILED (image:%#04x vs computed:%#04x)\n", + image_sum, sum); + return 0; + } + return 1; +} + +static inline unsigned padded(unsigned s) +{ + return (s + 3) & ~3; +} + +static Elf_Bhdr *add_boot_note(Elf_Bhdr *bhdr, const char *name, + unsigned type, const char *desc, unsigned descsz) +{ + Elf_Nhdr nhdr; + unsigned ent_size, new_size, pad; + char *addr; + + if (!bhdr) + return NULL; + + nhdr.n_namesz = name? strlen(name)+1 : 0; + nhdr.n_descsz = descsz; + nhdr.n_type = type; + ent_size = sizeof(nhdr) + padded(nhdr.n_namesz) + padded(nhdr.n_descsz); + if (bhdr->b_size + ent_size > 0xffff) { + printf("Boot notes too big\n"); + free(bhdr); + return NULL; + } + if (bhdr->b_size + ent_size > bhdr->b_checksum) { + do { + new_size = bhdr->b_checksum * 2; + } while (new_size < bhdr->b_size + ent_size); + if (new_size > 0xffff) + new_size = 0xffff; + debug("expanding boot note size to %u\n", new_size); +#ifdef HAVE_REALLOC + bhdr = realloc(bhdr, new_size); + bhdr->b_checksum = new_size; +#else + printf("Boot notes too big\n"); + free(bhdr); + return NULL; +#endif + } + + addr = (char *) bhdr; + addr += bhdr->b_size; + memcpy(addr, &nhdr, sizeof(nhdr)); + addr += sizeof(nhdr); + + if (name && nhdr.n_namesz) { + memcpy(addr, name, nhdr.n_namesz); + addr += nhdr.n_namesz; + pad = padded(nhdr.n_namesz) - nhdr.n_namesz; + memset(addr, 0, pad); + addr += pad; + } + + memcpy(addr, desc, nhdr.n_descsz); + addr += nhdr.n_descsz; + pad = padded(nhdr.n_descsz) - nhdr.n_descsz; + memset(addr, 0, pad); + + bhdr->b_size += ent_size; + bhdr->b_records++; + return bhdr; +} + +static inline Elf_Bhdr *add_note_string(Elf_Bhdr *bhdr, const char *name, + unsigned type, const char *desc) +{ + return add_boot_note(bhdr, name, type, desc, strlen(desc) + 1); +} + +static Elf_Bhdr *build_boot_notes(struct sys_info *info, const char *cmdline) +{ + Elf_Bhdr *bhdr; + + bhdr = malloc(256); + bhdr->b_signature = ELF_BHDR_MAGIC; + bhdr->b_size = sizeof *bhdr; + bhdr->b_checksum = 256; /* XXX cache the current buffer size here */ + bhdr->b_records = 0; + + if (info->firmware) + bhdr = add_note_string(bhdr, NULL, EBN_FIRMWARE_TYPE, info->firmware); + bhdr = add_note_string(bhdr, NULL, EBN_BOOTLOADER_NAME, program_name); + bhdr = add_note_string(bhdr, NULL, EBN_BOOTLOADER_VERSION, program_version); + if (cmdline) + bhdr = add_note_string(bhdr, NULL, EBN_COMMAND_LINE, cmdline); + if (!bhdr) + return bhdr; + bhdr->b_checksum = 0; + bhdr->b_checksum = ipchksum(bhdr, bhdr->b_size); + return bhdr; +} + +int +is_elf(Elf_ehdr *ehdr) +{ + return (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_CLASS] == ARCH_ELF_CLASS + && ehdr->e_ident[EI_DATA] == ARCH_ELF_DATA + && ehdr->e_ident[EI_VERSION] == EV_CURRENT + && ehdr->e_type == ET_EXEC + && ARCH_ELF_MACHINE_OK(ehdr->e_machine) + && ehdr->e_version == EV_CURRENT + && ehdr->e_phentsize == sizeof(Elf_phdr)); +} + +int +find_elf(Elf_ehdr *ehdr) +{ + int offset; + + for (offset = 0; offset < MAX_HEADERS * BS; offset += BS) { + if ((size_t)read_io(fd, ehdr, sizeof ehdr) != sizeof ehdr) { + debug("Can't read ELF header\n"); + return 0; + } + + if (is_elf(ehdr)) { + debug("Found ELF header at offset %d\n", offset); + return offset; + } + + seek_io(fd, offset); + } + + debug("Not a bootable ELF image\n"); + return 0; +} + +Elf_phdr * +elf_readhdrs(int offset, Elf_ehdr *ehdr) +{ + unsigned long phdr_size; + Elf_phdr *phdr; + + phdr_size = ehdr->e_phnum * sizeof(Elf_phdr); + phdr = malloc(phdr_size); + seek_io(fd, offset + ehdr->e_phoff); + if ((size_t)read_io(fd, phdr, phdr_size) != phdr_size) { + printf("Can't read program header\n"); + return NULL; + } + + return phdr; +} + +int +elf_load(struct sys_info *info, ihandle_t dev, const char *cmdline, void **boot_notes) +{ + Elf_ehdr ehdr; + Elf_phdr *phdr = NULL; + unsigned long checksum_offset, file_size; + unsigned short checksum = 0; + int retval = -1; + unsigned int offset; + + image_name = image_version = NULL; + + /* Mark the saved-program-state as invalid */ + feval("0 state-valid !"); + + fd = open_ih(dev); + if (fd == -1) { + goto out; + } + + offset = find_elf(&ehdr); + if (!offset) { + retval = LOADER_NOT_SUPPORT; + goto out; + } + +#if DEBUG + printk("ELF header:\n"); + printk(" ehdr.e_type = %d\n", (int)ehdr.e_type); + printk(" ehdr.e_machine = %d\n", (int)ehdr.e_machine); + printk(" ehdr.e_version = %d\n", (int)ehdr.e_version); + printk(" ehdr.e_entry = 0x%08x\n", (int)ehdr.e_entry); + printk(" ehdr.e_phoff = 0x%08x\n", (int)ehdr.e_phoff); + printk(" ehdr.e_shoff = 0x%08x\n", (int)ehdr.e_shoff); + printk(" ehdr.e_flags = %d\n", (int)ehdr.e_flags); + printk(" ehdr.e_ehsize = 0x%08x\n", (int)ehdr.e_ehsize); + printk(" ehdr.e_phentsize = 0x%08x\n", (int)ehdr.e_phentsize); + printk(" ehdr.e_phnum = %d\n", (int)ehdr.e_phnum); +#endif + + if (ehdr.e_phnum > MAX_HEADERS) { + printk ("elfload: too many program headers (MAX_HEADERS)\n"); + retval = 0; + goto out; + } + + phdr = elf_readhdrs(offset, &ehdr); + if (!phdr) + goto out; + + if (!check_mem_ranges(info, phdr, ehdr.e_phnum)) + goto out; + + checksum_offset = process_image_notes(phdr, ehdr.e_phnum, &checksum, offset); + + printf("Loading %s", image_name ? image_name : "image"); + if (image_version) + printf(" version %s", image_version); + printf("...\n"); + + if (!load_segments(phdr, ehdr.e_phnum, checksum_offset, offset, &file_size)) + goto out; + + if (checksum_offset) { + if (!verify_image(&ehdr, phdr, ehdr.e_phnum, checksum)) + goto out; + } + + /* If we are attempting an ELF boot image, we pass a non-NULL pointer + into boot_notes and mark the image as elf-boot rather than standard + ELF */ + if (boot_notes) { + *boot_notes = (void *)virt_to_phys(build_boot_notes(info, cmdline)); + feval("elf-boot saved-program-state >sps.file-type !"); + } else { + feval("elf saved-program-state >sps.file-type !"); + } + + //debug("current time: %lu\n", currticks()); + + debug("entry point is " FMT_elf "\n", addr_fixup(ehdr.e_entry)); + + // Initialise saved-program-state + PUSH(addr_fixup(ehdr.e_entry)); + feval("saved-program-state >sps.entry !"); + PUSH(file_size); + feval("saved-program-state >sps.file-size !"); + + feval("-1 state-valid !"); + +out: + close_io(fd); + if (phdr) + free(phdr); + if (image_name) + free(image_name); + if (image_version) + free(image_version); + return retval; +} + +void +elf_init_program(void) +{ + char *base; + int i; + Elf_ehdr *ehdr; + Elf_phdr *phdr; + size_t size, total_size = 0; + char *addr; + uintptr_t tmp; + + /* TODO: manage ELF notes section */ + feval("0 state-valid !"); + feval("load-base"); + base = (char*)cell2pointer(POP()); + + ehdr = (Elf_ehdr *)base; + + if (!is_elf(ehdr)) { + debug("Not a valid ELF memory image\n"); + return; + } + + phdr = (Elf_phdr *)(base + ehdr->e_phoff); + + for (i = 0; i < ehdr->e_phnum; i++) { + +#if DEBUG + debug("filesz: %08lX memsz: %08lX p_offset: %08lX " + "p_vaddr %08lX\n", + (unsigned long)phdr[i].p_filesz, (unsigned long)phdr[i].p_memsz, + (unsigned long)phdr[i].p_offset, (unsigned long)phdr[i].p_vaddr ); +#endif + + size = MIN(phdr[i].p_filesz, phdr[i].p_memsz); + if (!size) + continue; +#if !defined(CONFIG_SPARC32) && !defined(CONFIG_X86) + if( ofmem_claim( phdr[i].p_vaddr, phdr[i].p_memsz, 0 ) == -1 ) { + printk("Ignoring failed claim for va %lx memsz %lx!\n", + (unsigned long)phdr[i].p_vaddr, + (unsigned long)phdr[i].p_memsz); + } +#endif + /* Workaround for archs where sizeof(int) != pointer size */ + tmp = phdr[i].p_vaddr; + addr = (char *)tmp; + + memcpy(addr, base + phdr[i].p_offset, size); + + total_size += size; + +#ifdef CONFIG_PPC + flush_icache_range( addr, addr + size ); +#endif + } + + // Initialise saved-program-state + PUSH(ehdr->e_entry); + feval("saved-program-state >sps.entry !"); + PUSH(total_size); + feval("saved-program-state >sps.file-size !"); + feval("elf saved-program-state >sps.file-type !"); + + feval("-1 state-valid !"); +} diff --git a/qemu/roms/openbios/libopenbios/fcode_load.c b/qemu/roms/openbios/libopenbios/fcode_load.c new file mode 100644 index 000000000..f4eb7bf3f --- /dev/null +++ b/qemu/roms/openbios/libopenbios/fcode_load.c @@ -0,0 +1,109 @@ +/* + * FCode boot loader + */ + +#include "config.h" +#include "kernel/kernel.h" +#include "libopenbios/bindings.h" +#include "libopenbios/fcode_load.h" +#include "libopenbios/sys_info.h" +#include "libc/diskio.h" +#define printf printk +#define debug printk + +static int fd; + +int +is_fcode(unsigned char *fcode) +{ + return (fcode[0] == 0xf0 // start0 + || fcode[0] == 0xf1 // start1 + || fcode[0] == 0xf2 // start2 + || fcode[0] == 0xf3 // start4 + || fcode[0] == 0xfd); // version1 +} + +int +fcode_load(ihandle_t dev) +{ + int retval = -1; + uint8_t fcode_header[8]; + unsigned long start, size; + unsigned int offset; + + /* Mark the saved-program-state as invalid */ + feval("0 state-valid !"); + + fd = open_ih(dev); + if (fd == -1) { + goto out; + } + + for (offset = 0; offset < 16 * 512; offset += 512) { + seek_io(fd, offset); + if (read_io(fd, &fcode_header, sizeof(fcode_header)) + != sizeof(fcode_header)) { + debug("Can't read FCode header from ihandle " FMT_ucellx "\n", dev); + retval = LOADER_NOT_SUPPORT; + goto out; + } + + if (is_fcode(fcode_header)) + goto found; + } + + debug("Not a bootable FCode image\n"); + retval = LOADER_NOT_SUPPORT; + goto out; + + found: + size = (fcode_header[4] << 24) | (fcode_header[5] << 16) | + (fcode_header[6] << 8) | fcode_header[7]; + + fword("load-base"); + start = POP(); + + printf("\nLoading FCode image...\n"); + + seek_io(fd, offset); + + if ((size_t)read_io(fd, (void *)start, size) != size) { + printf("Can't read file (size 0x%lx)\n", size); + goto out; + } + + debug("Loaded %lu bytes\n", size); + debug("entry point is %#lx\n", start); + + // Initialise saved-program-state + PUSH(start); + feval("saved-program-state >sps.entry !"); + PUSH(size); + feval("saved-program-state >sps.file-size !"); + feval("fcode saved-program-state >sps.file-type !"); + + feval("-1 state-valid !"); + +out: + close_io(fd); + return retval; +} + +void +fcode_init_program(void) +{ + /* If the payload is Fcode then we execute it immediately */ + ucell address; + + fword("load-base"); + address = POP(); + + if (!is_fcode((unsigned char *)address)) { + debug("Not a valid Fcode memory image\n"); + return; + } + + PUSH(address); + PUSH(1); + fword("byte-load"); +} diff --git a/qemu/roms/openbios/libopenbios/font_8x16.c b/qemu/roms/openbios/libopenbios/font_8x16.c new file mode 100644 index 000000000..26c4e449c --- /dev/null +++ b/qemu/roms/openbios/libopenbios/font_8x16.c @@ -0,0 +1,4622 @@ +/**********************************************/ +/* */ +/* Font file generated by cpi2fnt */ +/* * + * * + * originally from the Linux distribution * + * * + **********************************************/ + +#include "libopenbios/fontdata.h" + +const unsigned char fontdata_8x16[FONTDATAMAX_8X16] = { + + /* 0 0x00 '^@' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 1 0x01 '^A' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x81, /* 10000001 */ + 0xa5, /* 10100101 */ + 0x81, /* 10000001 */ + 0x81, /* 10000001 */ + 0xbd, /* 10111101 */ + 0x99, /* 10011001 */ + 0x81, /* 10000001 */ + 0x81, /* 10000001 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 2 0x02 '^B' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0xff, /* 11111111 */ + 0xdb, /* 11011011 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xc3, /* 11000011 */ + 0xe7, /* 11100111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 3 0x03 '^C' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x6c, /* 01101100 */ + 0xfe, /* 11111110 */ + 0xfe, /* 11111110 */ + 0xfe, /* 11111110 */ + 0xfe, /* 11111110 */ + 0x7c, /* 01111100 */ + 0x38, /* 00111000 */ + 0x10, /* 00010000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 4 0x04 '^D' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x10, /* 00010000 */ + 0x38, /* 00111000 */ + 0x7c, /* 01111100 */ + 0xfe, /* 11111110 */ + 0x7c, /* 01111100 */ + 0x38, /* 00111000 */ + 0x10, /* 00010000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 5 0x05 '^E' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x3c, /* 00111100 */ + 0xe7, /* 11100111 */ + 0xe7, /* 11100111 */ + 0xe7, /* 11100111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 6 0x06 '^F' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x7e, /* 01111110 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 7 0x07 '^G' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 8 0x08 '^H' */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xe7, /* 11100111 */ + 0xc3, /* 11000011 */ + 0xc3, /* 11000011 */ + 0xe7, /* 11100111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + + /* 9 0x09 '^I' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0x42, /* 01000010 */ + 0x42, /* 01000010 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 10 0x0a '^J' */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xc3, /* 11000011 */ + 0x99, /* 10011001 */ + 0xbd, /* 10111101 */ + 0xbd, /* 10111101 */ + 0x99, /* 10011001 */ + 0xc3, /* 11000011 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + + /* 11 0x0b '^K' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x1e, /* 00011110 */ + 0x0e, /* 00001110 */ + 0x1a, /* 00011010 */ + 0x32, /* 00110010 */ + 0x78, /* 01111000 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x78, /* 01111000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 12 0x0c '^L' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 13 0x0d '^M' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3f, /* 00111111 */ + 0x33, /* 00110011 */ + 0x3f, /* 00111111 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x70, /* 01110000 */ + 0xf0, /* 11110000 */ + 0xe0, /* 11100000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 14 0x0e '^N' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7f, /* 01111111 */ + 0x63, /* 01100011 */ + 0x7f, /* 01111111 */ + 0x63, /* 01100011 */ + 0x63, /* 01100011 */ + 0x63, /* 01100011 */ + 0x63, /* 01100011 */ + 0x67, /* 01100111 */ + 0xe7, /* 11100111 */ + 0xe6, /* 11100110 */ + 0xc0, /* 11000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 15 0x0f '^O' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xdb, /* 11011011 */ + 0x3c, /* 00111100 */ + 0xe7, /* 11100111 */ + 0x3c, /* 00111100 */ + 0xdb, /* 11011011 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 16 0x10 '^P' */ + 0x00, /* 00000000 */ + 0x80, /* 10000000 */ + 0xc0, /* 11000000 */ + 0xe0, /* 11100000 */ + 0xf0, /* 11110000 */ + 0xf8, /* 11111000 */ + 0xfe, /* 11111110 */ + 0xf8, /* 11111000 */ + 0xf0, /* 11110000 */ + 0xe0, /* 11100000 */ + 0xc0, /* 11000000 */ + 0x80, /* 10000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 17 0x11 '^Q' */ + 0x00, /* 00000000 */ + 0x02, /* 00000010 */ + 0x06, /* 00000110 */ + 0x0e, /* 00001110 */ + 0x1e, /* 00011110 */ + 0x3e, /* 00111110 */ + 0xfe, /* 11111110 */ + 0x3e, /* 00111110 */ + 0x1e, /* 00011110 */ + 0x0e, /* 00001110 */ + 0x06, /* 00000110 */ + 0x02, /* 00000010 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 18 0x12 '^R' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 19 0x13 '^S' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x00, /* 00000000 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 20 0x14 '^T' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7f, /* 01111111 */ + 0xdb, /* 11011011 */ + 0xdb, /* 11011011 */ + 0xdb, /* 11011011 */ + 0x7b, /* 01111011 */ + 0x1b, /* 00011011 */ + 0x1b, /* 00011011 */ + 0x1b, /* 00011011 */ + 0x1b, /* 00011011 */ + 0x1b, /* 00011011 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 21 0x15 '^U' */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0x60, /* 01100000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x0c, /* 00001100 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 22 0x16 '^V' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0xfe, /* 11111110 */ + 0xfe, /* 11111110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 23 0x17 '^W' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 24 0x18 '^X' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 25 0x19 '^Y' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 26 0x1a '^Z' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0xfe, /* 11111110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 27 0x1b '^[' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0xfe, /* 11111110 */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 28 0x1c '^\' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 29 0x1d '^]' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x28, /* 00101000 */ + 0x6c, /* 01101100 */ + 0xfe, /* 11111110 */ + 0x6c, /* 01101100 */ + 0x28, /* 00101000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 30 0x1e '^^' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x10, /* 00010000 */ + 0x38, /* 00111000 */ + 0x38, /* 00111000 */ + 0x7c, /* 01111100 */ + 0x7c, /* 01111100 */ + 0xfe, /* 11111110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 31 0x1f '^_' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0xfe, /* 11111110 */ + 0x7c, /* 01111100 */ + 0x7c, /* 01111100 */ + 0x38, /* 00111000 */ + 0x38, /* 00111000 */ + 0x10, /* 00010000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 32 0x20 ' ' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 33 0x21 '!' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x3c, /* 00111100 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 34 0x22 '"' */ + 0x00, /* 00000000 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x24, /* 00100100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 35 0x23 '#' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0xfe, /* 11111110 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0xfe, /* 11111110 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 36 0x24 '$' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc2, /* 11000010 */ + 0xc0, /* 11000000 */ + 0x7c, /* 01111100 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x86, /* 10000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 37 0x25 '%' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc2, /* 11000010 */ + 0xc6, /* 11000110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0xc6, /* 11000110 */ + 0x86, /* 10000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 38 0x26 '&' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x76, /* 01110110 */ + 0xdc, /* 11011100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 39 0x27 ''' */ + 0x00, /* 00000000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 40 0x28 '(' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 41 0x29 ')' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 42 0x2a '*' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0xff, /* 11111111 */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 43 0x2b '+' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 44 0x2c ',' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 45 0x2d '-' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 46 0x2e '.' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 47 0x2f '/' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x02, /* 00000010 */ + 0x06, /* 00000110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0xc0, /* 11000000 */ + 0x80, /* 10000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 48 0x30 '0' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xd6, /* 11010110 */ + 0xd6, /* 11010110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 49 0x31 '1' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x38, /* 00111000 */ + 0x78, /* 01111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 50 0x32 '2' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0x06, /* 00000110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0xc0, /* 11000000 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 51 0x33 '3' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x3c, /* 00111100 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 52 0x34 '4' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x0c, /* 00001100 */ + 0x1c, /* 00011100 */ + 0x3c, /* 00111100 */ + 0x6c, /* 01101100 */ + 0xcc, /* 11001100 */ + 0xfe, /* 11111110 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x1e, /* 00011110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 53 0x35 '5' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xfc, /* 11111100 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 54 0x36 '6' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x60, /* 01100000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xfc, /* 11111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 55 0x37 '7' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 56 0x38 '8' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 57 0x39 '9' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7e, /* 01111110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x0c, /* 00001100 */ + 0x78, /* 01111000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 58 0x3a ':' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 59 0x3b ';' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 60 0x3c '<' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x06, /* 00000110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x06, /* 00000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 61 0x3d '=' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 62 0x3e '>' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x06, /* 00000110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 63 0x3f '?' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 64 0x40 '@' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xde, /* 11011110 */ + 0xde, /* 11011110 */ + 0xde, /* 11011110 */ + 0xdc, /* 11011100 */ + 0xc0, /* 11000000 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 65 0x41 'A' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x10, /* 00010000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 66 0x42 'B' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfc, /* 11111100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x7c, /* 01111100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0xfc, /* 11111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 67 0x43 'C' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0xc2, /* 11000010 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc2, /* 11000010 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 68 0x44 'D' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xf8, /* 11111000 */ + 0x6c, /* 01101100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x6c, /* 01101100 */ + 0xf8, /* 11111000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 69 0x45 'E' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x66, /* 01100110 */ + 0x62, /* 01100010 */ + 0x68, /* 01101000 */ + 0x78, /* 01111000 */ + 0x68, /* 01101000 */ + 0x60, /* 01100000 */ + 0x62, /* 01100010 */ + 0x66, /* 01100110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 70 0x46 'F' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x66, /* 01100110 */ + 0x62, /* 01100010 */ + 0x68, /* 01101000 */ + 0x78, /* 01111000 */ + 0x68, /* 01101000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0xf0, /* 11110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 71 0x47 'G' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0xc2, /* 11000010 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xde, /* 11011110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x66, /* 01100110 */ + 0x3a, /* 00111010 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 72 0x48 'H' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 73 0x49 'I' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 74 0x4a 'J' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x1e, /* 00011110 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x78, /* 01111000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 75 0x4b 'K' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xe6, /* 11100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x6c, /* 01101100 */ + 0x78, /* 01111000 */ + 0x78, /* 01111000 */ + 0x6c, /* 01101100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0xe6, /* 11100110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 76 0x4c 'L' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xf0, /* 11110000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x62, /* 01100010 */ + 0x66, /* 01100110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 77 0x4d 'M' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xee, /* 11101110 */ + 0xfe, /* 11111110 */ + 0xfe, /* 11111110 */ + 0xd6, /* 11010110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 78 0x4e 'N' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xe6, /* 11100110 */ + 0xf6, /* 11110110 */ + 0xfe, /* 11111110 */ + 0xde, /* 11011110 */ + 0xce, /* 11001110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 79 0x4f 'O' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 80 0x50 'P' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfc, /* 11111100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x7c, /* 01111100 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0xf0, /* 11110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 81 0x51 'Q' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xd6, /* 11010110 */ + 0xde, /* 11011110 */ + 0x7c, /* 01111100 */ + 0x0c, /* 00001100 */ + 0x0e, /* 00001110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 82 0x52 'R' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfc, /* 11111100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x7c, /* 01111100 */ + 0x6c, /* 01101100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0xe6, /* 11100110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 83 0x53 'S' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x60, /* 01100000 */ + 0x38, /* 00111000 */ + 0x0c, /* 00001100 */ + 0x06, /* 00000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 84 0x54 'T' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x7e, /* 01111110 */ + 0x5a, /* 01011010 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 85 0x55 'U' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 86 0x56 'V' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x10, /* 00010000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 87 0x57 'W' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xd6, /* 11010110 */ + 0xd6, /* 11010110 */ + 0xd6, /* 11010110 */ + 0xfe, /* 11111110 */ + 0xee, /* 11101110 */ + 0x6c, /* 01101100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 88 0x58 'X' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x6c, /* 01101100 */ + 0x7c, /* 01111100 */ + 0x38, /* 00111000 */ + 0x38, /* 00111000 */ + 0x7c, /* 01111100 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 89 0x59 'Y' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 90 0x5a 'Z' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0x86, /* 10000110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0xc2, /* 11000010 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 91 0x5b '[' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00111100 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 92 0x5c '\' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x80, /* 10000000 */ + 0xc0, /* 11000000 */ + 0xe0, /* 11100000 */ + 0x70, /* 01110000 */ + 0x38, /* 00111000 */ + 0x1c, /* 00011100 */ + 0x0e, /* 00001110 */ + 0x06, /* 00000110 */ + 0x02, /* 00000010 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 93 0x5d ']' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00111100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 94 0x5e '^' */ + 0x10, /* 00010000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 95 0x5f '_' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 96 0x60 '`' */ + 0x00, /* 00000000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 97 0x61 'a' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x78, /* 01111000 */ + 0x0c, /* 00001100 */ + 0x7c, /* 01111100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 98 0x62 'b' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xe0, /* 11100000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x78, /* 01111000 */ + 0x6c, /* 01101100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 99 0x63 'c' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 100 0x64 'd' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x1c, /* 00011100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x3c, /* 00111100 */ + 0x6c, /* 01101100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 101 0x65 'e' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 102 0x66 'f' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x1c, /* 00011100 */ + 0x36, /* 00110110 */ + 0x32, /* 00110010 */ + 0x30, /* 00110000 */ + 0x78, /* 01111000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x78, /* 01111000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 103 0x67 'g' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x76, /* 01110110 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x7c, /* 01111100 */ + 0x0c, /* 00001100 */ + 0xcc, /* 11001100 */ + 0x78, /* 01111000 */ + 0x00, /* 00000000 */ + + /* 104 0x68 'h' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xe0, /* 11100000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x6c, /* 01101100 */ + 0x76, /* 01110110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0xe6, /* 11100110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 105 0x69 'i' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 106 0x6a 'j' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x00, /* 00000000 */ + 0x0e, /* 00001110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + + /* 107 0x6b 'k' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xe0, /* 11100000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x66, /* 01100110 */ + 0x6c, /* 01101100 */ + 0x78, /* 01111000 */ + 0x78, /* 01111000 */ + 0x6c, /* 01101100 */ + 0x66, /* 01100110 */ + 0xe6, /* 11100110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 108 0x6c 'l' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 109 0x6d 'm' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xec, /* 11101100 */ + 0xfe, /* 11111110 */ + 0xd6, /* 11010110 */ + 0xd6, /* 11010110 */ + 0xd6, /* 11010110 */ + 0xd6, /* 11010110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 110 0x6e 'n' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xdc, /* 11011100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 111 0x6f 'o' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 112 0x70 'p' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xdc, /* 11011100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x7c, /* 01111100 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0xf0, /* 11110000 */ + 0x00, /* 00000000 */ + + /* 113 0x71 'q' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x76, /* 01110110 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x7c, /* 01111100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x1e, /* 00011110 */ + 0x00, /* 00000000 */ + + /* 114 0x72 'r' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xdc, /* 11011100 */ + 0x76, /* 01110110 */ + 0x66, /* 01100110 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0xf0, /* 11110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 115 0x73 's' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0x60, /* 01100000 */ + 0x38, /* 00111000 */ + 0x0c, /* 00001100 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 116 0x74 't' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x10, /* 00010000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0xfc, /* 11111100 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x36, /* 00110110 */ + 0x1c, /* 00011100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 117 0x75 'u' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 118 0x76 'v' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 119 0x77 'w' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xd6, /* 11010110 */ + 0xd6, /* 11010110 */ + 0xd6, /* 11010110 */ + 0xfe, /* 11111110 */ + 0x6c, /* 01101100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 120 0x78 'x' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x38, /* 00111000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 121 0x79 'y' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7e, /* 01111110 */ + 0x06, /* 00000110 */ + 0x0c, /* 00001100 */ + 0xf8, /* 11111000 */ + 0x00, /* 00000000 */ + + /* 122 0x7a 'z' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0xcc, /* 11001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 123 0x7b '{' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x0e, /* 00001110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x70, /* 01110000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x0e, /* 00001110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 124 0x7c '|' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 125 0x7d '}' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x70, /* 01110000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x0e, /* 00001110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x70, /* 01110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 126 0x7e '~' */ + 0x00, /* 00000000 */ + 0x76, /* 01110110 */ + 0xdc, /* 11011100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 127 0x7f '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x10, /* 00010000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 128 0x80 '€' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0xc2, /* 11000010 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc2, /* 11000010 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x70, /* 01110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 129 0x81 '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xcc, /* 11001100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 130 0x82 '‚' */ + 0x00, /* 00000000 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 131 0x83 'ƒ' */ + 0x00, /* 00000000 */ + 0x10, /* 00010000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0x00, /* 00000000 */ + 0x78, /* 01111000 */ + 0x0c, /* 00001100 */ + 0x7c, /* 01111100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 132 0x84 '„' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xcc, /* 11001100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x78, /* 01111000 */ + 0x0c, /* 00001100 */ + 0x7c, /* 01111100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 133 0x85 '…' */ + 0x00, /* 00000000 */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x78, /* 01111000 */ + 0x0c, /* 00001100 */ + 0x7c, /* 01111100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 134 0x86 '†' */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x00, /* 00000000 */ + 0x78, /* 01111000 */ + 0x0c, /* 00001100 */ + 0x7c, /* 01111100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 135 0x87 '‡' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x18, /* 00011000 */ + 0x70, /* 01110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 136 0x88 'ˆ' */ + 0x00, /* 00000000 */ + 0x10, /* 00010000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 137 0x89 '‰' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 138 0x8a 'Š' */ + 0x00, /* 00000000 */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 139 0x8b '‹' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x66, /* 01100110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 140 0x8c 'Œ' */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 141 0x8d '' */ + 0x00, /* 00000000 */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 142 0x8e 'Ž' */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x10, /* 00010000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 143 0x8f '' */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x10, /* 00010000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 144 0x90 '' */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x66, /* 01100110 */ + 0x62, /* 01100010 */ + 0x68, /* 01101000 */ + 0x78, /* 01111000 */ + 0x68, /* 01101000 */ + 0x62, /* 01100010 */ + 0x66, /* 01100110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 145 0x91 '‘' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xec, /* 11101100 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x7e, /* 01111110 */ + 0xd8, /* 11011000 */ + 0xd8, /* 11011000 */ + 0x6e, /* 01101110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 146 0x92 '’' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3e, /* 00111110 */ + 0x6c, /* 01101100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xfe, /* 11111110 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xce, /* 11001110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 147 0x93 '“' */ + 0x00, /* 00000000 */ + 0x10, /* 00010000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 148 0x94 '”' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 149 0x95 '•' */ + 0x00, /* 00000000 */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 150 0x96 '–' */ + 0x00, /* 00000000 */ + 0x30, /* 00110000 */ + 0x78, /* 01111000 */ + 0xcc, /* 11001100 */ + 0x00, /* 00000000 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 151 0x97 '—' */ + 0x00, /* 00000000 */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 152 0x98 '˜' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7e, /* 01111110 */ + 0x06, /* 00000110 */ + 0x0c, /* 00001100 */ + 0x78, /* 01111000 */ + 0x00, /* 00000000 */ + + /* 153 0x99 '™' */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 154 0x9a 'š' */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 155 0x9b '›' */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 156 0x9c 'œ' */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0x64, /* 01100100 */ + 0x60, /* 01100000 */ + 0xf0, /* 11110000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0xe6, /* 11100110 */ + 0xfc, /* 11111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 157 0x9d '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 158 0x9e 'ž' */ + 0x00, /* 00000000 */ + 0xf8, /* 11111000 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xf8, /* 11111000 */ + 0xc4, /* 11000100 */ + 0xcc, /* 11001100 */ + 0xde, /* 11011110 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 159 0x9f 'Ÿ' */ + 0x00, /* 00000000 */ + 0x0e, /* 00001110 */ + 0x1b, /* 00011011 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xd8, /* 11011000 */ + 0x70, /* 01110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 160 0xa0 ' ' */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0x00, /* 00000000 */ + 0x78, /* 01111000 */ + 0x0c, /* 00001100 */ + 0x7c, /* 01111100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 161 0xa1 '¡' */ + 0x00, /* 00000000 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 162 0xa2 '¢' */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 163 0xa3 '£' */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0x00, /* 00000000 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 164 0xa4 '¤' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x76, /* 01110110 */ + 0xdc, /* 11011100 */ + 0x00, /* 00000000 */ + 0xdc, /* 11011100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 165 0xa5 '¥' */ + 0x76, /* 01110110 */ + 0xdc, /* 11011100 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xe6, /* 11100110 */ + 0xf6, /* 11110110 */ + 0xfe, /* 11111110 */ + 0xde, /* 11011110 */ + 0xce, /* 11001110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 166 0xa6 '¦' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00111100 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x3e, /* 00111110 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 167 0xa7 '§' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 168 0xa8 '¨' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x00, /* 00000000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0xc0, /* 11000000 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 169 0xa9 '©' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 170 0xaa 'ª' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 171 0xab '«' */ + 0x00, /* 00000000 */ + 0x60, /* 01100000 */ + 0xe0, /* 11100000 */ + 0x62, /* 01100010 */ + 0x66, /* 01100110 */ + 0x6c, /* 01101100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0xdc, /* 11011100 */ + 0x86, /* 10000110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x3e, /* 00111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 172 0xac '¬' */ + 0x00, /* 00000000 */ + 0x60, /* 01100000 */ + 0xe0, /* 11100000 */ + 0x62, /* 01100010 */ + 0x66, /* 01100110 */ + 0x6c, /* 01101100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x66, /* 01100110 */ + 0xce, /* 11001110 */ + 0x9a, /* 10011010 */ + 0x3f, /* 00111111 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 173 0xad '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x3c, /* 00111100 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 174 0xae '®' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x36, /* 00110110 */ + 0x6c, /* 01101100 */ + 0xd8, /* 11011000 */ + 0x6c, /* 01101100 */ + 0x36, /* 00110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 175 0xaf '¯' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xd8, /* 11011000 */ + 0x6c, /* 01101100 */ + 0x36, /* 00110110 */ + 0x6c, /* 01101100 */ + 0xd8, /* 11011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 176 0xb0 '°' */ + 0x11, /* 00010001 */ + 0x44, /* 01000100 */ + 0x11, /* 00010001 */ + 0x44, /* 01000100 */ + 0x11, /* 00010001 */ + 0x44, /* 01000100 */ + 0x11, /* 00010001 */ + 0x44, /* 01000100 */ + 0x11, /* 00010001 */ + 0x44, /* 01000100 */ + 0x11, /* 00010001 */ + 0x44, /* 01000100 */ + 0x11, /* 00010001 */ + 0x44, /* 01000100 */ + 0x11, /* 00010001 */ + 0x44, /* 01000100 */ + + /* 177 0xb1 '±' */ + 0x55, /* 01010101 */ + 0xaa, /* 10101010 */ + 0x55, /* 01010101 */ + 0xaa, /* 10101010 */ + 0x55, /* 01010101 */ + 0xaa, /* 10101010 */ + 0x55, /* 01010101 */ + 0xaa, /* 10101010 */ + 0x55, /* 01010101 */ + 0xaa, /* 10101010 */ + 0x55, /* 01010101 */ + 0xaa, /* 10101010 */ + 0x55, /* 01010101 */ + 0xaa, /* 10101010 */ + 0x55, /* 01010101 */ + 0xaa, /* 10101010 */ + + /* 178 0xb2 '²' */ + 0xdd, /* 11011101 */ + 0x77, /* 01110111 */ + 0xdd, /* 11011101 */ + 0x77, /* 01110111 */ + 0xdd, /* 11011101 */ + 0x77, /* 01110111 */ + 0xdd, /* 11011101 */ + 0x77, /* 01110111 */ + 0xdd, /* 11011101 */ + 0x77, /* 01110111 */ + 0xdd, /* 11011101 */ + 0x77, /* 01110111 */ + 0xdd, /* 11011101 */ + 0x77, /* 01110111 */ + 0xdd, /* 11011101 */ + 0x77, /* 01110111 */ + + /* 179 0xb3 '³' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 180 0xb4 '´' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xf8, /* 11111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 181 0xb5 'µ' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xf8, /* 11111000 */ + 0x18, /* 00011000 */ + 0xf8, /* 11111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 182 0xb6 '¶' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0xf6, /* 11110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 183 0xb7 '·' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 184 0xb8 '¸' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xf8, /* 11111000 */ + 0x18, /* 00011000 */ + 0xf8, /* 11111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 185 0xb9 '¹' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0xf6, /* 11110110 */ + 0x06, /* 00000110 */ + 0xf6, /* 11110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 186 0xba 'º' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 187 0xbb '»' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x06, /* 00000110 */ + 0xf6, /* 11110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 188 0xbc '¼' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0xf6, /* 11110110 */ + 0x06, /* 00000110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 189 0xbd '½' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 190 0xbe '¾' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xf8, /* 11111000 */ + 0x18, /* 00011000 */ + 0xf8, /* 11111000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 191 0xbf '¿' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xf8, /* 11111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 192 0xc0 'À' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x1f, /* 00011111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 193 0xc1 'Á' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 194 0xc2 'Â' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 195 0xc3 'Ã' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x1f, /* 00011111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 196 0xc4 'Ä' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 197 0xc5 'Å' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xff, /* 11111111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 198 0xc6 'Æ' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x1f, /* 00011111 */ + 0x18, /* 00011000 */ + 0x1f, /* 00011111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 199 0xc7 'Ç' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x37, /* 00110111 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 200 0xc8 'È' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x37, /* 00110111 */ + 0x30, /* 00110000 */ + 0x3f, /* 00111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 201 0xc9 'É' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3f, /* 00111111 */ + 0x30, /* 00110000 */ + 0x37, /* 00110111 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 202 0xca 'Ê' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0xf7, /* 11110111 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 203 0xcb 'Ë' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0xf7, /* 11110111 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 204 0xcc 'Ì' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x37, /* 00110111 */ + 0x30, /* 00110000 */ + 0x37, /* 00110111 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 205 0xcd 'Í' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 206 0xce 'Î' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0xf7, /* 11110111 */ + 0x00, /* 00000000 */ + 0xf7, /* 11110111 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 207 0xcf 'Ï' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 208 0xd0 'Ð' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 209 0xd1 'Ñ' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 210 0xd2 'Ò' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 211 0xd3 'Ó' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x3f, /* 00111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 212 0xd4 'Ô' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x1f, /* 00011111 */ + 0x18, /* 00011000 */ + 0x1f, /* 00011111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 213 0xd5 'Õ' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x1f, /* 00011111 */ + 0x18, /* 00011000 */ + 0x1f, /* 00011111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 214 0xd6 'Ö' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3f, /* 00111111 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 215 0xd7 '×' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0xff, /* 11111111 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 216 0xd8 'Ø' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xff, /* 11111111 */ + 0x18, /* 00011000 */ + 0xff, /* 11111111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 217 0xd9 'Ù' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xf8, /* 11111000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 218 0xda 'Ú' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x1f, /* 00011111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 219 0xdb 'Û' */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + + /* 220 0xdc 'Ü' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + + /* 221 0xdd 'Ý' */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + + /* 222 0xde 'Þ' */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + + /* 223 0xdf 'ß' */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 224 0xe0 'à' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x76, /* 01110110 */ + 0xdc, /* 11011100 */ + 0xd8, /* 11011000 */ + 0xd8, /* 11011000 */ + 0xd8, /* 11011000 */ + 0xdc, /* 11011100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 225 0xe1 'á' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x78, /* 01111000 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xd8, /* 11011000 */ + 0xcc, /* 11001100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xcc, /* 11001100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 226 0xe2 'â' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 227 0xe3 'ã' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 228 0xe4 'ä' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 229 0xe5 'å' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0xd8, /* 11011000 */ + 0xd8, /* 11011000 */ + 0xd8, /* 11011000 */ + 0xd8, /* 11011000 */ + 0xd8, /* 11011000 */ + 0x70, /* 01110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 230 0xe6 'æ' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x7c, /* 01111100 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0xc0, /* 11000000 */ + 0x00, /* 00000000 */ + + /* 231 0xe7 'ç' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x76, /* 01110110 */ + 0xdc, /* 11011100 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 232 0xe8 'è' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 233 0xe9 'é' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 234 0xea 'ê' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0xee, /* 11101110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 235 0xeb 'ë' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x1e, /* 00011110 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x3e, /* 00111110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 236 0xec 'ì' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0xdb, /* 11011011 */ + 0xdb, /* 11011011 */ + 0xdb, /* 11011011 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 237 0xed 'í' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x03, /* 00000011 */ + 0x06, /* 00000110 */ + 0x7e, /* 01111110 */ + 0xdb, /* 11011011 */ + 0xdb, /* 11011011 */ + 0xf3, /* 11110011 */ + 0x7e, /* 01111110 */ + 0x60, /* 01100000 */ + 0xc0, /* 11000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 238 0xee 'î' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x1c, /* 00011100 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x7c, /* 01111100 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x1c, /* 00011100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 239 0xef 'ï' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 240 0xf0 'ð' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 241 0xf1 'ñ' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 242 0xf2 'ò' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x06, /* 00000110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 243 0xf3 'ó' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 244 0xf4 'ô' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x0e, /* 00001110 */ + 0x1b, /* 00011011 */ + 0x1b, /* 00011011 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 245 0xf5 'õ' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xd8, /* 11011000 */ + 0xd8, /* 11011000 */ + 0xd8, /* 11011000 */ + 0x70, /* 01110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 246 0xf6 'ö' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 247 0xf7 '÷' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x76, /* 01110110 */ + 0xdc, /* 11011100 */ + 0x00, /* 00000000 */ + 0x76, /* 01110110 */ + 0xdc, /* 11011100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 248 0xf8 'ø' */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 249 0xf9 'ù' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 250 0xfa 'ú' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 251 0xfb 'û' */ + 0x00, /* 00000000 */ + 0x0f, /* 00001111 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0xec, /* 11101100 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x3c, /* 00111100 */ + 0x1c, /* 00011100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 252 0xfc 'ü' */ + 0x00, /* 00000000 */ + 0x6c, /* 01101100 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 253 0xfd 'ý' */ + 0x00, /* 00000000 */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x32, /* 00110010 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 254 0xfe 'þ' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x7e, /* 01111110 */ + 0x7e, /* 01111110 */ + 0x7e, /* 01111110 */ + 0x7e, /* 01111110 */ + 0x7e, /* 01111110 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 255 0xff 'ÿ' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + +}; diff --git a/qemu/roms/openbios/libopenbios/font_8x8.c b/qemu/roms/openbios/libopenbios/font_8x8.c new file mode 100644 index 000000000..861929ea4 --- /dev/null +++ b/qemu/roms/openbios/libopenbios/font_8x8.c @@ -0,0 +1,2571 @@ +/**********************************************/ +/* */ +/* Font file generated by cpi2fnt */ +/* */ +/**********************************************/ + +#include "libopenbios/fontdata.h" + +const unsigned char fontdata_8x8[FONTDATAMAX_8X8] = { + + /* 0 0x00 '^@' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 1 0x01 '^A' */ + 0xfe, /* 11111110 */ + 0xfe, /* 11111110 */ + 0xfe, /* 11111110 */ + 0xfe, /* 11111110 */ + 0xfe, /* 11111110 */ + 0xfe, /* 11111110 */ + 0xfe, /* 11111110 */ + 0xfe, /* 11111110 */ + + /* 2 0x02 '^B' */ + 0x6c, /* 01101100 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + + /* 3 0x03 '^C' */ + 0x6c, /* 01101100 */ + 0xfe, /* 11111110 */ + 0xfe, /* 11111110 */ + 0xfe, /* 11111110 */ + 0x7c, /* 01111100 */ + 0x38, /* 00111000 */ + 0x10, /* 00010000 */ + 0x00, /* 00000000 */ + + /* 4 0x04 '^D' */ + 0x10, /* 00010000 */ + 0x38, /* 00111000 */ + 0x7c, /* 01111100 */ + 0xfe, /* 11111110 */ + 0x7c, /* 01111100 */ + 0x38, /* 00111000 */ + 0x10, /* 00010000 */ + 0x00, /* 00000000 */ + + /* 5 0x05 '^E' */ + 0x38, /* 00111000 */ + 0x7c, /* 01111100 */ + 0x38, /* 00111000 */ + 0xfe, /* 11111110 */ + 0xfe, /* 11111110 */ + 0xd6, /* 11010110 */ + 0x10, /* 00010000 */ + 0x38, /* 00111000 */ + + /* 6 0x06 '^F' */ + 0x10, /* 00010000 */ + 0x38, /* 00111000 */ + 0x7c, /* 01111100 */ + 0xfe, /* 11111110 */ + 0xfe, /* 11111110 */ + 0x7c, /* 01111100 */ + 0x10, /* 00010000 */ + 0x38, /* 00111000 */ + + /* 7 0x07 '^G' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 8 0x08 '^H' */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xe7, /* 11100111 */ + 0xc3, /* 11000011 */ + 0xc3, /* 11000011 */ + 0xe7, /* 11100111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + + /* 9 0x09 '^I' */ + 0x00, /* 00000000 */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0x42, /* 01000010 */ + 0x42, /* 01000010 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + + /* 10 0x0a '^J' */ + 0xff, /* 11111111 */ + 0xc3, /* 11000011 */ + 0x99, /* 10011001 */ + 0xbd, /* 10111101 */ + 0xbd, /* 10111101 */ + 0x99, /* 10011001 */ + 0xc3, /* 11000011 */ + 0xff, /* 11111111 */ + + /* 11 0x0b '^K' */ + 0x0f, /* 00001111 */ + 0x07, /* 00000111 */ + 0x0f, /* 00001111 */ + 0x7d, /* 01111101 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x78, /* 01111000 */ + + /* 12 0x0c '^L' */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + + /* 13 0x0d '^M' */ + 0x3f, /* 00111111 */ + 0x33, /* 00110011 */ + 0x3f, /* 00111111 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x70, /* 01110000 */ + 0xf0, /* 11110000 */ + 0xe0, /* 11100000 */ + + /* 14 0x0e '^N' */ + 0x7f, /* 01111111 */ + 0x63, /* 01100011 */ + 0x7f, /* 01111111 */ + 0x63, /* 01100011 */ + 0x63, /* 01100011 */ + 0x67, /* 01100111 */ + 0xe6, /* 11100110 */ + 0xc0, /* 11000000 */ + + /* 15 0x0f '^O' */ + 0x18, /* 00011000 */ + 0xdb, /* 11011011 */ + 0x3c, /* 00111100 */ + 0xe7, /* 11100111 */ + 0xe7, /* 11100111 */ + 0x3c, /* 00111100 */ + 0xdb, /* 11011011 */ + 0x18, /* 00011000 */ + + /* 16 0x10 '^P' */ + 0x80, /* 10000000 */ + 0xe0, /* 11100000 */ + 0xf8, /* 11111000 */ + 0xfe, /* 11111110 */ + 0xf8, /* 11111000 */ + 0xe0, /* 11100000 */ + 0x80, /* 10000000 */ + 0x00, /* 00000000 */ + + /* 17 0x11 '^Q' */ + 0x02, /* 00000010 */ + 0x0e, /* 00001110 */ + 0x3e, /* 00111110 */ + 0xfe, /* 11111110 */ + 0x3e, /* 00111110 */ + 0x0e, /* 00001110 */ + 0x02, /* 00000010 */ + 0x00, /* 00000000 */ + + /* 18 0x12 '^R' */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + + /* 19 0x13 '^S' */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x00, /* 00000000 */ + 0x66, /* 01100110 */ + 0x00, /* 00000000 */ + + /* 20 0x14 '^T' */ + 0x7f, /* 01111111 */ + 0xdb, /* 11011011 */ + 0xdb, /* 11011011 */ + 0x7b, /* 01111011 */ + 0x1b, /* 00011011 */ + 0x1b, /* 00011011 */ + 0x1b, /* 00011011 */ + 0x00, /* 00000000 */ + + /* 21 0x15 '^U' */ + 0x3e, /* 00111110 */ + 0x61, /* 01100001 */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x86, /* 10000110 */ + 0x7c, /* 01111100 */ + + /* 22 0x16 '^V' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x7e, /* 01111110 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + + /* 23 0x17 '^W' */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0xff, /* 11111111 */ + + /* 24 0x18 '^X' */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + + /* 25 0x19 '^Y' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + + /* 26 0x1a '^Z' */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0xfe, /* 11111110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 27 0x1b '^[' */ + 0x00, /* 00000000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0xfe, /* 11111110 */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 28 0x1c '^\' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 29 0x1d '^]' */ + 0x00, /* 00000000 */ + 0x24, /* 00100100 */ + 0x66, /* 01100110 */ + 0xff, /* 11111111 */ + 0x66, /* 01100110 */ + 0x24, /* 00100100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 30 0x1e '^^' */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x7e, /* 01111110 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 31 0x1f '^_' */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0x7e, /* 01111110 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 32 0x20 ' ' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 33 0x21 '!' */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + + /* 34 0x22 '"' */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x24, /* 00100100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 35 0x23 '#' */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0xfe, /* 11111110 */ + 0x6c, /* 01101100 */ + 0xfe, /* 11111110 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x00, /* 00000000 */ + + /* 36 0x24 '$' */ + 0x18, /* 00011000 */ + 0x3e, /* 00111110 */ + 0x60, /* 01100000 */ + 0x3c, /* 00111100 */ + 0x06, /* 00000110 */ + 0x7c, /* 01111100 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + + /* 37 0x25 '%' */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xcc, /* 11001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x66, /* 01100110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + + /* 38 0x26 '&' */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x76, /* 01110110 */ + 0xdc, /* 11011100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + + /* 39 0x27 ''' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 40 0x28 '(' */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x00, /* 00000000 */ + + /* 41 0x29 ')' */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x00, /* 00000000 */ + + /* 42 0x2a '*' */ + 0x00, /* 00000000 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0xff, /* 11111111 */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 43 0x2b '+' */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 44 0x2c ',' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + + /* 45 0x2d '-' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 46 0x2e '.' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + + /* 47 0x2f '/' */ + 0x06, /* 00000110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0xc0, /* 11000000 */ + 0x80, /* 10000000 */ + 0x00, /* 00000000 */ + + /* 48 0x30 '0' */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xd6, /* 11010110 */ + 0xc6, /* 11000110 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x00, /* 00000000 */ + + /* 49 0x31 '1' */ + 0x18, /* 00011000 */ + 0x38, /* 00111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + + /* 50 0x32 '2' */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0x06, /* 00000110 */ + 0x1c, /* 00011100 */ + 0x30, /* 00110000 */ + 0x66, /* 01100110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + + /* 51 0x33 '3' */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0x06, /* 00000110 */ + 0x3c, /* 00111100 */ + 0x06, /* 00000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + + /* 52 0x34 '4' */ + 0x1c, /* 00011100 */ + 0x3c, /* 00111100 */ + 0x6c, /* 01101100 */ + 0xcc, /* 11001100 */ + 0xfe, /* 11111110 */ + 0x0c, /* 00001100 */ + 0x1e, /* 00011110 */ + 0x00, /* 00000000 */ + + /* 53 0x35 '5' */ + 0xfe, /* 11111110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xfc, /* 11111100 */ + 0x06, /* 00000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + + /* 54 0x36 '6' */ + 0x38, /* 00111000 */ + 0x60, /* 01100000 */ + 0xc0, /* 11000000 */ + 0xfc, /* 11111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + + /* 55 0x37 '7' */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x00, /* 00000000 */ + + /* 56 0x38 '8' */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + + /* 57 0x39 '9' */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7e, /* 01111110 */ + 0x06, /* 00000110 */ + 0x0c, /* 00001100 */ + 0x78, /* 01111000 */ + 0x00, /* 00000000 */ + + /* 58 0x3a ':' */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + + /* 59 0x3b ';' */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + + /* 60 0x3c '<' */ + 0x06, /* 00000110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x06, /* 00000110 */ + 0x00, /* 00000000 */ + + /* 61 0x3d '=' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 62 0x3e '>' */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0x00, /* 00000000 */ + + /* 63 0x3f '?' */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + + /* 64 0x40 '@' */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xde, /* 11011110 */ + 0xde, /* 11011110 */ + 0xde, /* 11011110 */ + 0xc0, /* 11000000 */ + 0x78, /* 01111000 */ + 0x00, /* 00000000 */ + + /* 65 0x41 'A' */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + + /* 66 0x42 'B' */ + 0xfc, /* 11111100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x7c, /* 01111100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0xfc, /* 11111100 */ + 0x00, /* 00000000 */ + + /* 67 0x43 'C' */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + + /* 68 0x44 'D' */ + 0xf8, /* 11111000 */ + 0x6c, /* 01101100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x6c, /* 01101100 */ + 0xf8, /* 11111000 */ + 0x00, /* 00000000 */ + + /* 69 0x45 'E' */ + 0xfe, /* 11111110 */ + 0x62, /* 01100010 */ + 0x68, /* 01101000 */ + 0x78, /* 01111000 */ + 0x68, /* 01101000 */ + 0x62, /* 01100010 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + + /* 70 0x46 'F' */ + 0xfe, /* 11111110 */ + 0x62, /* 01100010 */ + 0x68, /* 01101000 */ + 0x78, /* 01111000 */ + 0x68, /* 01101000 */ + 0x60, /* 01100000 */ + 0xf0, /* 11110000 */ + 0x00, /* 00000000 */ + + /* 71 0x47 'G' */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xce, /* 11001110 */ + 0x66, /* 01100110 */ + 0x3a, /* 00111010 */ + 0x00, /* 00000000 */ + + /* 72 0x48 'H' */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + + /* 73 0x49 'I' */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + + /* 74 0x4a 'J' */ + 0x1e, /* 00011110 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x78, /* 01111000 */ + 0x00, /* 00000000 */ + + /* 75 0x4b 'K' */ + 0xe6, /* 11100110 */ + 0x66, /* 01100110 */ + 0x6c, /* 01101100 */ + 0x78, /* 01111000 */ + 0x6c, /* 01101100 */ + 0x66, /* 01100110 */ + 0xe6, /* 11100110 */ + 0x00, /* 00000000 */ + + /* 76 0x4c 'L' */ + 0xf0, /* 11110000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x62, /* 01100010 */ + 0x66, /* 01100110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + + /* 77 0x4d 'M' */ + 0xc6, /* 11000110 */ + 0xee, /* 11101110 */ + 0xfe, /* 11111110 */ + 0xfe, /* 11111110 */ + 0xd6, /* 11010110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + + /* 78 0x4e 'N' */ + 0xc6, /* 11000110 */ + 0xe6, /* 11100110 */ + 0xf6, /* 11110110 */ + 0xde, /* 11011110 */ + 0xce, /* 11001110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + + /* 79 0x4f 'O' */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + + /* 80 0x50 'P' */ + 0xfc, /* 11111100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x7c, /* 01111100 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0xf0, /* 11110000 */ + 0x00, /* 00000000 */ + + /* 81 0x51 'Q' */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xce, /* 11001110 */ + 0x7c, /* 01111100 */ + 0x0e, /* 00001110 */ + + /* 82 0x52 'R' */ + 0xfc, /* 11111100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x7c, /* 01111100 */ + 0x6c, /* 01101100 */ + 0x66, /* 01100110 */ + 0xe6, /* 11100110 */ + 0x00, /* 00000000 */ + + /* 83 0x53 'S' */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + + /* 84 0x54 'T' */ + 0x7e, /* 01111110 */ + 0x7e, /* 01111110 */ + 0x5a, /* 01011010 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + + /* 85 0x55 'U' */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + + /* 86 0x56 'V' */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x00, /* 00000000 */ + + /* 87 0x57 'W' */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xd6, /* 11010110 */ + 0xd6, /* 11010110 */ + 0xfe, /* 11111110 */ + 0x6c, /* 01101100 */ + 0x00, /* 00000000 */ + + /* 88 0x58 'X' */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + + /* 89 0x59 'Y' */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + + /* 90 0x5a 'Z' */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0x8c, /* 10001100 */ + 0x18, /* 00011000 */ + 0x32, /* 00110010 */ + 0x66, /* 01100110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + + /* 91 0x5b '[' */ + 0x3c, /* 00111100 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + + /* 92 0x5c '\' */ + 0xc0, /* 11000000 */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x06, /* 00000110 */ + 0x02, /* 00000010 */ + 0x00, /* 00000000 */ + + /* 93 0x5d ']' */ + 0x3c, /* 00111100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + + /* 94 0x5e '^' */ + 0x10, /* 00010000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 95 0x5f '_' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + + /* 96 0x60 '`' */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 97 0x61 'a' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x78, /* 01111000 */ + 0x0c, /* 00001100 */ + 0x7c, /* 01111100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + + /* 98 0x62 'b' */ + 0xe0, /* 11100000 */ + 0x60, /* 01100000 */ + 0x7c, /* 01111100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0xdc, /* 11011100 */ + 0x00, /* 00000000 */ + + /* 99 0x63 'c' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc0, /* 11000000 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + + /* 100 0x64 'd' */ + 0x1c, /* 00011100 */ + 0x0c, /* 00001100 */ + 0x7c, /* 01111100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + + /* 101 0x65 'e' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc0, /* 11000000 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + + /* 102 0x66 'f' */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0x60, /* 01100000 */ + 0xf8, /* 11111000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0xf0, /* 11110000 */ + 0x00, /* 00000000 */ + + /* 103 0x67 'g' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x76, /* 01110110 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x7c, /* 01111100 */ + 0x0c, /* 00001100 */ + 0xf8, /* 11111000 */ + + /* 104 0x68 'h' */ + 0xe0, /* 11100000 */ + 0x60, /* 01100000 */ + 0x6c, /* 01101100 */ + 0x76, /* 01110110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0xe6, /* 11100110 */ + 0x00, /* 00000000 */ + + /* 105 0x69 'i' */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + + /* 106 0x6a 'j' */ + 0x06, /* 00000110 */ + 0x00, /* 00000000 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + + /* 107 0x6b 'k' */ + 0xe0, /* 11100000 */ + 0x60, /* 01100000 */ + 0x66, /* 01100110 */ + 0x6c, /* 01101100 */ + 0x78, /* 01111000 */ + 0x6c, /* 01101100 */ + 0xe6, /* 11100110 */ + 0x00, /* 00000000 */ + + /* 108 0x6c 'l' */ + 0x38, /* 00111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + + /* 109 0x6d 'm' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xec, /* 11101100 */ + 0xfe, /* 11111110 */ + 0xd6, /* 11010110 */ + 0xd6, /* 11010110 */ + 0xd6, /* 11010110 */ + 0x00, /* 00000000 */ + + /* 110 0x6e 'n' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xdc, /* 11011100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x00, /* 00000000 */ + + /* 111 0x6f 'o' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + + /* 112 0x70 'p' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xdc, /* 11011100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x7c, /* 01111100 */ + 0x60, /* 01100000 */ + 0xf0, /* 11110000 */ + + /* 113 0x71 'q' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x76, /* 01110110 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x7c, /* 01111100 */ + 0x0c, /* 00001100 */ + 0x1e, /* 00011110 */ + + /* 114 0x72 'r' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xdc, /* 11011100 */ + 0x76, /* 01110110 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0xf0, /* 11110000 */ + 0x00, /* 00000000 */ + + /* 115 0x73 's' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0xc0, /* 11000000 */ + 0x7c, /* 01111100 */ + 0x06, /* 00000110 */ + 0xfc, /* 11111100 */ + 0x00, /* 00000000 */ + + /* 116 0x74 't' */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0xfc, /* 11111100 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x36, /* 00110110 */ + 0x1c, /* 00011100 */ + 0x00, /* 00000000 */ + + /* 117 0x75 'u' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + + /* 118 0x76 'v' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x00, /* 00000000 */ + + /* 119 0x77 'w' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xd6, /* 11010110 */ + 0xd6, /* 11010110 */ + 0xfe, /* 11111110 */ + 0x6c, /* 01101100 */ + 0x00, /* 00000000 */ + + /* 120 0x78 'x' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + + /* 121 0x79 'y' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7e, /* 01111110 */ + 0x06, /* 00000110 */ + 0xfc, /* 11111100 */ + + /* 122 0x7a 'z' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x4c, /* 01001100 */ + 0x18, /* 00011000 */ + 0x32, /* 00110010 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + + /* 123 0x7b '{' */ + 0x0e, /* 00001110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x70, /* 01110000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x0e, /* 00001110 */ + 0x00, /* 00000000 */ + + /* 124 0x7c '|' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + + /* 125 0x7d '}' */ + 0x70, /* 01110000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x0e, /* 00001110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x70, /* 01110000 */ + 0x00, /* 00000000 */ + + /* 126 0x7e '~' */ + 0x76, /* 01110110 */ + 0xdc, /* 11011100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 127 0x7f '' */ + 0x00, /* 00000000 */ + 0x10, /* 00010000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + + /* 128 0x80 '€' */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x0c, /* 00001100 */ + 0x78, /* 01111000 */ + + /* 129 0x81 '' */ + 0xcc, /* 11001100 */ + 0x00, /* 00000000 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + + /* 130 0x82 '‚' */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc0, /* 11000000 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + + /* 131 0x83 'ƒ' */ + 0x7c, /* 01111100 */ + 0x82, /* 10000010 */ + 0x78, /* 01111000 */ + 0x0c, /* 00001100 */ + 0x7c, /* 01111100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + + /* 132 0x84 '„' */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x78, /* 01111000 */ + 0x0c, /* 00001100 */ + 0x7c, /* 01111100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + + /* 133 0x85 '…' */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x78, /* 01111000 */ + 0x0c, /* 00001100 */ + 0x7c, /* 01111100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + + /* 134 0x86 '†' */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x78, /* 01111000 */ + 0x0c, /* 00001100 */ + 0x7c, /* 01111100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + + /* 135 0x87 '‡' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0x7e, /* 01111110 */ + 0x0c, /* 00001100 */ + 0x38, /* 00111000 */ + + /* 136 0x88 'ˆ' */ + 0x7c, /* 01111100 */ + 0x82, /* 10000010 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc0, /* 11000000 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + + /* 137 0x89 '‰' */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc0, /* 11000000 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + + /* 138 0x8a 'Š' */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc0, /* 11000000 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + + /* 139 0x8b '‹' */ + 0x66, /* 01100110 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + + /* 140 0x8c 'Œ' */ + 0x7c, /* 01111100 */ + 0x82, /* 10000010 */ + 0x38, /* 00111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + + /* 141 0x8d '' */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + + /* 142 0x8e 'Ž' */ + 0xc6, /* 11000110 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + + /* 143 0x8f '' */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + + /* 144 0x90 '' */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0xfe, /* 11111110 */ + 0xc0, /* 11000000 */ + 0xf8, /* 11111000 */ + 0xc0, /* 11000000 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + + /* 145 0x91 '‘' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0xd8, /* 11011000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + + /* 146 0x92 '’' */ + 0x3e, /* 00111110 */ + 0x6c, /* 01101100 */ + 0xcc, /* 11001100 */ + 0xfe, /* 11111110 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xce, /* 11001110 */ + 0x00, /* 00000000 */ + + /* 147 0x93 '“' */ + 0x7c, /* 01111100 */ + 0x82, /* 10000010 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + + /* 148 0x94 '”' */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + + /* 149 0x95 '•' */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + + /* 150 0x96 '–' */ + 0x78, /* 01111000 */ + 0x84, /* 10000100 */ + 0x00, /* 00000000 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + + /* 151 0x97 '—' */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + + /* 152 0x98 '˜' */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7e, /* 01111110 */ + 0x06, /* 00000110 */ + 0xfc, /* 11111100 */ + + /* 153 0x99 '™' */ + 0xc6, /* 11000110 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x00, /* 00000000 */ + + /* 154 0x9a 'š' */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + + /* 155 0x9b '›' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 156 0x9c 'œ' */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0x64, /* 01100100 */ + 0xf0, /* 11110000 */ + 0x60, /* 01100000 */ + 0x66, /* 01100110 */ + 0xfc, /* 11111100 */ + 0x00, /* 00000000 */ + + /* 157 0x9d '' */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 158 0x9e 'ž' */ + 0xf8, /* 11111000 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xfa, /* 11111010 */ + 0xc6, /* 11000110 */ + 0xcf, /* 11001111 */ + 0xc6, /* 11000110 */ + 0xc7, /* 11000111 */ + + /* 159 0x9f 'Ÿ' */ + 0x0e, /* 00001110 */ + 0x1b, /* 00011011 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0xd8, /* 11011000 */ + 0x70, /* 01110000 */ + 0x00, /* 00000000 */ + + /* 160 0xa0 ' ' */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x78, /* 01111000 */ + 0x0c, /* 00001100 */ + 0x7c, /* 01111100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + + /* 161 0xa1 '¡' */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + + /* 162 0xa2 '¢' */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + + /* 163 0xa3 '£' */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + + /* 164 0xa4 '¤' */ + 0x76, /* 01110110 */ + 0xdc, /* 11011100 */ + 0x00, /* 00000000 */ + 0xdc, /* 11011100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x00, /* 00000000 */ + + /* 165 0xa5 '¥' */ + 0x76, /* 01110110 */ + 0xdc, /* 11011100 */ + 0x00, /* 00000000 */ + 0xe6, /* 11100110 */ + 0xf6, /* 11110110 */ + 0xde, /* 11011110 */ + 0xce, /* 11001110 */ + 0x00, /* 00000000 */ + + /* 166 0xa6 '¦' */ + 0x3c, /* 00111100 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x3e, /* 00111110 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 167 0xa7 '§' */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 168 0xa8 '¨' */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x63, /* 01100011 */ + 0x3e, /* 00111110 */ + 0x00, /* 00000000 */ + + /* 169 0xa9 '©' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 170 0xaa 'ª' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 171 0xab '«' */ + 0x63, /* 01100011 */ + 0xe6, /* 11100110 */ + 0x6c, /* 01101100 */ + 0x7e, /* 01111110 */ + 0x33, /* 00110011 */ + 0x66, /* 01100110 */ + 0xcc, /* 11001100 */ + 0x0f, /* 00001111 */ + + /* 172 0xac '¬' */ + 0x63, /* 01100011 */ + 0xe6, /* 11100110 */ + 0x6c, /* 01101100 */ + 0x7a, /* 01111010 */ + 0x36, /* 00110110 */ + 0x6a, /* 01101010 */ + 0xdf, /* 11011111 */ + 0x06, /* 00000110 */ + + /* 173 0xad '' */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + + /* 174 0xae '®' */ + 0x00, /* 00000000 */ + 0x33, /* 00110011 */ + 0x66, /* 01100110 */ + 0xcc, /* 11001100 */ + 0x66, /* 01100110 */ + 0x33, /* 00110011 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 175 0xaf '¯' */ + 0x00, /* 00000000 */ + 0xcc, /* 11001100 */ + 0x66, /* 01100110 */ + 0x33, /* 00110011 */ + 0x66, /* 01100110 */ + 0xcc, /* 11001100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 176 0xb0 '°' */ + 0x22, /* 00100010 */ + 0x88, /* 10001000 */ + 0x22, /* 00100010 */ + 0x88, /* 10001000 */ + 0x22, /* 00100010 */ + 0x88, /* 10001000 */ + 0x22, /* 00100010 */ + 0x88, /* 10001000 */ + + /* 177 0xb1 '±' */ + 0x55, /* 01010101 */ + 0xaa, /* 10101010 */ + 0x55, /* 01010101 */ + 0xaa, /* 10101010 */ + 0x55, /* 01010101 */ + 0xaa, /* 10101010 */ + 0x55, /* 01010101 */ + 0xaa, /* 10101010 */ + + /* 178 0xb2 '²' */ + 0x77, /* 01110111 */ + 0xdd, /* 11011101 */ + 0x77, /* 01110111 */ + 0xdd, /* 11011101 */ + 0x77, /* 01110111 */ + 0xdd, /* 11011101 */ + 0x77, /* 01110111 */ + 0xdd, /* 11011101 */ + + /* 179 0xb3 '³' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 180 0xb4 '´' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xf8, /* 11111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 181 0xb5 'µ' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xf8, /* 11111000 */ + 0x18, /* 00011000 */ + 0xf8, /* 11111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 182 0xb6 '¶' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0xf6, /* 11110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 183 0xb7 '·' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 184 0xb8 '¸' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xf8, /* 11111000 */ + 0x18, /* 00011000 */ + 0xf8, /* 11111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 185 0xb9 '¹' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0xf6, /* 11110110 */ + 0x06, /* 00000110 */ + 0xf6, /* 11110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 186 0xba 'º' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 187 0xbb '»' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x06, /* 00000110 */ + 0xf6, /* 11110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 188 0xbc '¼' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0xf6, /* 11110110 */ + 0x06, /* 00000110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 189 0xbd '½' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 190 0xbe '¾' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xf8, /* 11111000 */ + 0x18, /* 00011000 */ + 0xf8, /* 11111000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 191 0xbf '¿' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xf8, /* 11111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 192 0xc0 'À' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x1f, /* 00011111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 193 0xc1 'Á' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 194 0xc2 'Â' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 195 0xc3 'Ã' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x1f, /* 00011111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 196 0xc4 'Ä' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 197 0xc5 'Å' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xff, /* 11111111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 198 0xc6 'Æ' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x1f, /* 00011111 */ + 0x18, /* 00011000 */ + 0x1f, /* 00011111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 199 0xc7 'Ç' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x37, /* 00110111 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 200 0xc8 'È' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x37, /* 00110111 */ + 0x30, /* 00110000 */ + 0x3f, /* 00111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 201 0xc9 'É' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3f, /* 00111111 */ + 0x30, /* 00110000 */ + 0x37, /* 00110111 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 202 0xca 'Ê' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0xf7, /* 11110111 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 203 0xcb 'Ë' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0xf7, /* 11110111 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 204 0xcc 'Ì' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x37, /* 00110111 */ + 0x30, /* 00110000 */ + 0x37, /* 00110111 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 205 0xcd 'Í' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 206 0xce 'Î' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0xf7, /* 11110111 */ + 0x00, /* 00000000 */ + 0xf7, /* 11110111 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 207 0xcf 'Ï' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 208 0xd0 'Ð' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 209 0xd1 'Ñ' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 210 0xd2 'Ò' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 211 0xd3 'Ó' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x3f, /* 00111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 212 0xd4 'Ô' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x1f, /* 00011111 */ + 0x18, /* 00011000 */ + 0x1f, /* 00011111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 213 0xd5 'Õ' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x1f, /* 00011111 */ + 0x18, /* 00011000 */ + 0x1f, /* 00011111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 214 0xd6 'Ö' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3f, /* 00111111 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 215 0xd7 '×' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0xff, /* 11111111 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 216 0xd8 'Ø' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xff, /* 11111111 */ + 0x18, /* 00011000 */ + 0xff, /* 11111111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 217 0xd9 'Ù' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xf8, /* 11111000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 218 0xda 'Ú' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x1f, /* 00011111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 219 0xdb 'Û' */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + + /* 220 0xdc 'Ü' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + + /* 221 0xdd 'Ý' */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + + /* 222 0xde 'Þ' */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + + /* 223 0xdf 'ß' */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 224 0xe0 'à' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x76, /* 01110110 */ + 0xdc, /* 11011100 */ + 0xc8, /* 11001000 */ + 0xdc, /* 11011100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + + /* 225 0xe1 'á' */ + 0x78, /* 01111000 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xd8, /* 11011000 */ + 0xcc, /* 11001100 */ + 0xc6, /* 11000110 */ + 0xcc, /* 11001100 */ + 0x00, /* 00000000 */ + + /* 226 0xe2 'â' */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0x00, /* 00000000 */ + + /* 227 0xe3 'ã' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x00, /* 00000000 */ + + /* 228 0xe4 'ä' */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + + /* 229 0xe5 'å' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0xd8, /* 11011000 */ + 0xd8, /* 11011000 */ + 0xd8, /* 11011000 */ + 0x70, /* 01110000 */ + 0x00, /* 00000000 */ + + /* 230 0xe6 'æ' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x7c, /* 01111100 */ + 0xc0, /* 11000000 */ + + /* 231 0xe7 'ç' */ + 0x00, /* 00000000 */ + 0x76, /* 01110110 */ + 0xdc, /* 11011100 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + + /* 232 0xe8 'è' */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + + /* 233 0xe9 'é' */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x00, /* 00000000 */ + + /* 234 0xea 'ê' */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0xee, /* 11101110 */ + 0x00, /* 00000000 */ + + /* 235 0xeb 'ë' */ + 0x0e, /* 00001110 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x3e, /* 00111110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + + /* 236 0xec 'ì' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0xdb, /* 11011011 */ + 0xdb, /* 11011011 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 237 0xed 'í' */ + 0x06, /* 00000110 */ + 0x0c, /* 00001100 */ + 0x7e, /* 01111110 */ + 0xdb, /* 11011011 */ + 0xdb, /* 11011011 */ + 0x7e, /* 01111110 */ + 0x60, /* 01100000 */ + 0xc0, /* 11000000 */ + + /* 238 0xee 'î' */ + 0x1e, /* 00011110 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0x7e, /* 01111110 */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x1e, /* 00011110 */ + 0x00, /* 00000000 */ + + /* 239 0xef 'ï' */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + + /* 240 0xf0 'ð' */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 241 0xf1 'ñ' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + + /* 242 0xf2 'ò' */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + + /* 243 0xf3 'ó' */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + + /* 244 0xf4 'ô' */ + 0x0e, /* 00001110 */ + 0x1b, /* 00011011 */ + 0x1b, /* 00011011 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 245 0xf5 'õ' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xd8, /* 11011000 */ + 0xd8, /* 11011000 */ + 0x70, /* 01110000 */ + + /* 246 0xf6 'ö' */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 247 0xf7 '÷' */ + 0x00, /* 00000000 */ + 0x76, /* 01110110 */ + 0xdc, /* 11011100 */ + 0x00, /* 00000000 */ + 0x76, /* 01110110 */ + 0xdc, /* 11011100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 248 0xf8 'ø' */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 249 0xf9 'ù' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 250 0xfa 'ú' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 251 0xfb 'û' */ + 0x0f, /* 00001111 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0xec, /* 11101100 */ + 0x6c, /* 01101100 */ + 0x3c, /* 00111100 */ + 0x1c, /* 00011100 */ + + /* 252 0xfc 'ü' */ + 0x6c, /* 01101100 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 253 0xfd 'ý' */ + 0x78, /* 01111000 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 254 0xfe 'þ' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00111100 */ + 0x3c, /* 00111100 */ + 0x3c, /* 00111100 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 255 0xff 'ÿ' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + +}; diff --git a/qemu/roms/openbios/libopenbios/forth_load.c b/qemu/roms/openbios/libopenbios/forth_load.c new file mode 100644 index 000000000..c3a1929f2 --- /dev/null +++ b/qemu/roms/openbios/libopenbios/forth_load.c @@ -0,0 +1,88 @@ +/* tag: forth source loader + * + * Copyright (C) 2004 Stefan Reinauer + * + * See the file "COPYING" for further information about + * the copyright and warranty status of this work. + */ + +#include "config.h" +#include "kernel/kernel.h" +#include "libopenbios/bindings.h" +#include "libopenbios/sys_info.h" +#include "libc/diskio.h" +#include "libopenbios/forth_load.h" +#define printk printk +#define debug printk + +static int fd; +static char *forthtext=NULL; + +int is_forth(char *forth) +{ + return (forth[0] == '\\' && forth[1] == ' '); +} + +int forth_load(ihandle_t dev) +{ + char magic[2]; + unsigned long forthsize; + int retval = -1; + + /* Mark the saved-program-state as invalid */ + feval("0 state-valid !"); + + fd = open_ih(dev); + if (fd == -1) { + goto out; + } + + if (read_io(fd, magic, 2) != 2) { + debug("Can't read magic header\n"); + retval = LOADER_NOT_SUPPORT; + goto out; + } + + if (!is_forth(magic)) { + debug("No forth source image\n"); + retval = LOADER_NOT_SUPPORT; + goto out; + } + + /* Calculate the file size by seeking to the end of the file */ + seek_io(fd, -1); + forthsize = tell(fd); + forthtext = malloc(forthsize+1); + seek_io(fd, 0); + + printk("Loading forth source ..."); + if ((size_t)read_io(fd, forthtext, forthsize) != forthsize) { + printk("Can't read forth text\n"); + goto out; + } + forthtext[forthsize]=0; + printk("ok\n"); + + // Initialise saved-program-state + PUSH((ucell)forthtext); + feval("saved-program-state >sps.entry !"); + PUSH((ucell)forthsize); + feval("saved-program-state >sps.file-size !"); + feval("forth saved-program-state >sps.file-type !"); + + feval("-1 state-valid !"); + + retval=0; + +out: + //if (forthtext) + // free(forthtext); + return retval; +} + +void +forth_init_program(void) +{ + // Currently not implemented + feval("0 state-valid !"); +} diff --git a/qemu/roms/openbios/libopenbios/helpers.fs b/qemu/roms/openbios/libopenbios/helpers.fs new file mode 100644 index 000000000..8f5db9ffc --- /dev/null +++ b/qemu/roms/openbios/libopenbios/helpers.fs @@ -0,0 +1,35 @@ +\ tag: helper functions +\ +\ deblocker / filesystem support +\ +\ Copyright (C) 2003 Samuel Rydh +\ +\ See the file "COPYING" for further information about +\ the copyright and warranty status of this work. +\ + + +\ create device node and any missing parents. +\ The new node becomes the active package + +: create-node ( nodepath -- ) + recursive + ascii / right-split + 2dup find-dev if + active-package! + 2drop + else + ( nodename path ) + dup if + create-node + else + device-tree @ active-package! + 2drop + then + then + new-device + device-name + active-package + finish-device + active-package! +; diff --git a/qemu/roms/openbios/libopenbios/init.c b/qemu/roms/openbios/libopenbios/init.c new file mode 100644 index 000000000..10fb55cd6 --- /dev/null +++ b/qemu/roms/openbios/libopenbios/init.c @@ -0,0 +1,27 @@ +/* + * Creation Date: <2010/04/02 12:00:00 mcayland> + * Time-stamp: <2010/04/02 12:00:00 mcayland> + * + * <init.c> + * + * OpenBIOS intialization + * + * Copyright (C) 2010 Mark Cave-Ayland (mark.cave-ayland@siriusit.co.uk) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#include "config.h" +#include "libopenbios/openbios.h" +#include "libopenbios/bindings.h" +#include "libopenbios/initprogram.h" + +void +openbios_init( void ) +{ + // Bind the C implementation of (init-program) into Forth + bind_func("(init-program)", init_program); +} diff --git a/qemu/roms/openbios/libopenbios/initprogram.c b/qemu/roms/openbios/libopenbios/initprogram.c new file mode 100644 index 000000000..1fa33ba66 --- /dev/null +++ b/qemu/roms/openbios/libopenbios/initprogram.c @@ -0,0 +1,85 @@ +/* + * Creation Date: <2010/04/02 13:00:00 mcayland> + * Time-stamp: <2010/04/02 13:00:00 mcayland> + * + * <initprogram.c> + * + * C implementation of (init-program) word + * + * Copyright (C) 2010 Mark Cave-Ayland (mark.cave-ayland@siriusit.co.uk) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#include "config.h" +#include "kernel/kernel.h" +#include "libopenbios/bindings.h" +#include "libopenbios/initprogram.h" + +/* Because the a.out loader requires platform-specific headers */ +#ifdef CONFIG_LOADER_AOUT +#include "libopenbios/aout_load.h" +#endif + +#include "libopenbios/bootinfo_load.h" +#include "libopenbios/elf_load.h" +#include "libopenbios/fcode_load.h" +#include "libopenbios/forth_load.h" +#include "libopenbios/xcoff_load.h" + + +void init_program(void) +{ + /* Get the value of load-base and use it to determine the correct loader + to use */ + ucell addr; + + feval("load-base"); + addr = POP(); + +#ifdef CONFIG_LOADER_AOUT + if (is_aout((struct exec *)cell2pointer(addr))) { + aout_init_program(); + return; + } +#endif + +#ifdef CONFIG_LOADER_BOOTINFO + if (is_bootinfo((char *)cell2pointer(addr))) { + bootinfo_init_program(); + return; + } +#endif + +#ifdef CONFIG_LOADER_ELF + if (is_elf((Elf_ehdr *)cell2pointer(addr))) { + elf_init_program(); + return; + } +#endif + +#ifdef CONFIG_LOADER_FCODE + if (is_fcode((unsigned char *)cell2pointer(addr))) { + fcode_init_program(); + return; + } +#endif + +#ifdef CONFIG_LOADER_FORTH + if (is_forth((char *)cell2pointer(addr))) { + forth_init_program(); + return; + } +#endif + +#ifdef CONFIG_LOADER_XCOFF + if (is_xcoff((COFF_filehdr_t *)cell2pointer(addr))) { + xcoff_init_program(); + return; + } +#endif + +} diff --git a/qemu/roms/openbios/libopenbios/ipchecksum.c b/qemu/roms/openbios/libopenbios/ipchecksum.c new file mode 100644 index 000000000..83f39bcea --- /dev/null +++ b/qemu/roms/openbios/libopenbios/ipchecksum.c @@ -0,0 +1,55 @@ +/* Taken from Etherboot */ + +#include "libopenbios/ipchecksum.h" + +unsigned short ipchksum(const void *data, unsigned long length) +{ + unsigned long sum; + unsigned long i; + const unsigned char *ptr; + union { + unsigned char byte[2]; + unsigned short word; + } u; + + /* In the most straight forward way possible, + * compute an ip style checksum. + */ + sum = 0; + ptr = data; + for(i = 0; i < length; i++) { + unsigned long value; + value = ptr[i]; + if (i & 1) { + value <<= 8; + } + /* Add the new value */ + sum += value; + /* Wrap around the carry */ + if (sum > 0xFFFF) { + sum = (sum + (sum >> 16)) & 0xFFFF; + } + } + u.byte[0] = (unsigned char) sum; + u.byte[1] = (unsigned char) (sum >> 8); + return (unsigned short) ~u.word; +} + +unsigned short add_ipchksums(unsigned long offset, unsigned short sum, unsigned short new) +{ + unsigned long checksum; + sum = ~sum & 0xFFFF; + new = ~new & 0xFFFF; + if (offset & 1) { + /* byte swap the sum if it came from an odd offset + * since the computation is endian independant this + * works. + */ + new = (new << 8) | (new >> 8); + } + checksum = sum + new; + if (checksum > 0xFFFF) { + checksum -= 0xFFFF; + } + return (~checksum) & 0xFFFF; +} diff --git a/qemu/roms/openbios/libopenbios/linuxbios.h b/qemu/roms/openbios/libopenbios/linuxbios.h new file mode 100644 index 000000000..0f7cba96a --- /dev/null +++ b/qemu/roms/openbios/libopenbios/linuxbios.h @@ -0,0 +1,181 @@ +#ifndef LINUXBIOS_TABLES_H +#define LINUXBIOS_TABLES_H + +/* The linuxbios table information is for conveying information + * from the firmware to the loaded OS image. Primarily this + * is expected to be information that cannot be discovered by + * other means, such as quering the hardware directly. + * + * All of the information should be Position Independent Data. + * That is it should be safe to relocated any of the information + * without it's meaning/correctnes changing. For table that + * can reasonably be used on multiple architectures the data + * size should be fixed. This should ease the transition between + * 32 bit and 64 bit architectures etc. + * + * The completeness test for the information in this table is: + * - Can all of the hardware be detected? + * - Are the per motherboard constants available? + * - Is there enough to allow a kernel to run that was written before + * a particular motherboard is constructed? (Assuming the kernel + * has drivers for all of the hardware but it does not have + * assumptions on how the hardware is connected together). + * + * With this test it should be straight forward to determine if a + * table entry is required or not. This should remove much of the + * long term compatibility burden as table entries which are + * irrelevant or have been replaced by better alternatives may be + * dropped. Of course it is polite and expidite to include extra + * table entries and be backwards compatible, but it is not required. + */ + + +struct lb_header +{ + uint8_t signature[4]; /* LBIO */ + uint32_t header_bytes; + uint32_t header_checksum; + uint32_t table_bytes; + uint32_t table_checksum; + uint32_t table_entries; +}; + +/* Every entry in the boot enviroment list will correspond to a boot + * info record. Encoding both type and size. The type is obviously + * so you can tell what it is. The size allows you to skip that + * boot enviroment record if you don't know what it easy. This allows + * forward compatibility with records not yet defined. + */ +struct lb_record { + uint32_t tag; /* tag ID */ + uint32_t size; /* size of record (in bytes) */ +}; + +#define LB_TAG_UNUSED 0x0000 + +#define LB_TAG_MEMORY 0x0001 + +struct lb_memory_range { + uint64_t start; + uint64_t size; + uint32_t type; +#define LB_MEM_RAM 1 /* Memory anyone can use */ +#define LB_MEM_RESERVED 2 /* Don't use this memory region */ +#define LB_MEM_TABLE 16 /* Ram configuration tables are kept in */ + +}; + +struct lb_memory { + uint32_t tag; + uint32_t size; + struct lb_memory_range map[0]; +}; + +#define LB_TAG_HWRPB 0x0002 +struct lb_hwrpb { + uint32_t tag; + uint32_t size; + uint64_t hwrpb; +}; + +#define LB_TAG_MAINBOARD 0x0003 +struct lb_mainboard { + uint32_t tag; + uint32_t size; + uint8_t vendor_idx; + uint8_t part_number_idx; + uint8_t strings[0]; +}; + +#define LB_TAG_VERSION 0x0004 +#define LB_TAG_EXTRA_VERSION 0x0005 +#define LB_TAG_BUILD 0x0006 +#define LB_TAG_COMPILE_TIME 0x0007 +#define LB_TAG_COMPILE_BY 0x0008 +#define LB_TAG_COMPILE_HOST 0x0009 +#define LB_TAG_COMPILE_DOMAIN 0x000a +#define LB_TAG_COMPILER 0x000b +#define LB_TAG_LINKER 0x000c +#define LB_TAG_ASSEMBLER 0x000d +struct lb_string { + uint32_t tag; + uint32_t size; + uint8_t string[0]; +}; + +/* The following structures are for the cmos definitions table */ +#define LB_TAG_CMOS_OPTION_TABLE 200 +/* cmos header record */ +struct cmos_option_table { + uint32_t tag; /* CMOS definitions table type */ + uint32_t size; /* size of the entire table */ + uint32_t header_length; /* length of header */ +}; + +/* cmos entry record + This record is variable length. The name field may be + shorter than CMOS_MAX_NAME_LENGTH. The entry may start + anywhere in the byte, but can not span bytes unless it + starts at the beginning of the byte and the length is + fills complete bytes. +*/ +#define LB_TAG_OPTION 201 +struct cmos_entries { + uint32_t tag; /* entry type */ + uint32_t size; /* length of this record */ + uint32_t bit; /* starting bit from start of image */ + uint32_t length; /* length of field in bits */ + uint32_t config; /* e=enumeration, h=hex, r=reserved */ + uint32_t config_id; /* a number linking to an enumeration record */ +#define CMOS_MAX_NAME_LENGTH 32 + uint8_t name[CMOS_MAX_NAME_LENGTH]; /* name of entry in ascii, + variable length int aligned */ +}; + + +/* cmos enumerations record + This record is variable length. The text field may be + shorter than CMOS_MAX_TEXT_LENGTH. +*/ +#define LB_TAG_OPTION_ENUM 202 +struct cmos_enums { + uint32_t tag; /* enumeration type */ + uint32_t size; /* length of this record */ + uint32_t config_id; /* a number identifying the config id */ + uint32_t value; /* the value associated with the text */ +#define CMOS_MAX_TEXT_LENGTH 32 + uint8_t text[CMOS_MAX_TEXT_LENGTH]; /* enum description in ascii, + variable length int aligned */ +}; + +/* cmos defaults record + This record contains default settings for the cmos ram. +*/ +#define LB_TAG_OPTION_DEFAULTS 203 +struct cmos_defaults { + uint32_t tag; /* default type */ + uint32_t size; /* length of this record */ + uint32_t name_length; /* length of the following name field */ + uint8_t name[CMOS_MAX_NAME_LENGTH]; /* name identifying the default */ +#define CMOS_IMAGE_BUFFER_SIZE 128 + uint8_t default_set[CMOS_IMAGE_BUFFER_SIZE]; /* default settings */ +}; + +#define LB_TAG_OPTION_CHECKSUM 204 +struct cmos_checksum { + uint32_t tag; + uint32_t size; + /* In practice everything is byte aligned, but things are measured + * in bits to be consistent. + */ + uint32_t range_start; /* First bit that is checksummed (byte aligned) */ + uint32_t range_end; /* Last bit that is checksummed (byte aligned) */ + uint32_t location; /* First bit of the checksum (byte aligned) */ + uint32_t type; /* Checksum algorithm that is used */ +#define CHECKSUM_NONE 0 +#define CHECKSUM_PCBIOS 1 +}; + + + +#endif /* LINUXBIOS_TABLES_H */ diff --git a/qemu/roms/openbios/libopenbios/linuxbios_info.c b/qemu/roms/openbios/libopenbios/linuxbios_info.c new file mode 100644 index 000000000..bef996cf0 --- /dev/null +++ b/qemu/roms/openbios/libopenbios/linuxbios_info.c @@ -0,0 +1,130 @@ +/* Adapted from Etherboot 5.1.8 */ + +#include "config.h" +#include "sysinclude.h" +#include "asm/types.h" +#include "asm/io.h" +#include "linuxbios.h" +#include "libopenbios/ipchecksum.h" +#include "libopenbios/sys_info.h" + +#ifdef CONFIG_DEBUG_BOOT +#define debug printk +#else +#define debug(x...) +#endif + +#define for_each_lbrec(head, rec) \ + for(rec = (struct lb_record *)(((char *)head) + sizeof(*head)); \ + (((char *)rec) < (((char *)head) + sizeof(*head) + head->table_bytes)) && \ + (rec->size >= 1) && \ + ((((char *)rec) + rec->size) <= (((char *)head) + sizeof(*head) + head->table_bytes)); \ + rec = (struct lb_record *)(((char *)rec) + rec->size)) + +static void convert_memmap(struct lb_memory *lbmem, struct sys_info *info) +{ + int lbcount; + int i; + + lbcount = lbmem->size / sizeof(struct lb_memory_range); + info->memrange = malloc(lbcount * sizeof(struct memrange)); + info->n_memranges = 0; + for (i = 0; i < lbcount; i++) { + debug("%#016llx %#016llx %d\n", + (long long)lbmem->map[i].start, (long long)lbmem->map[i].size, + (int) lbmem->map[i].type); + if (lbmem->map[i].type != LB_MEM_RAM) + continue; + info->memrange[info->n_memranges].base = lbmem->map[i].start; + info->memrange[info->n_memranges].size = lbmem->map[i].size; + info->n_memranges++; + } +} + +static int read_lbtable(struct lb_header *head, struct sys_info *info) +{ + int retval = 0; + + /* Read linuxbios tables... */ + struct lb_record *rec; + + for_each_lbrec(head, rec) { + switch(rec->tag) { + case LB_TAG_MEMORY: + convert_memmap((struct lb_memory *) rec, info); + retval = 1; + break; + }; + } + return retval; +} + +static unsigned long count_lb_records(void *start, unsigned long length) +{ + struct lb_record *rec; + void *end; + unsigned long count; + count = 0; + end = ((char *)start) + length; + for(rec = start; ((void *)rec < end) && + ((signed long)rec->size <= + ((signed long)end - (signed long)rec)); + rec = (void *)(((char *)rec) + rec->size)) { + count++; + } + return count; +} + +static int find_lb_table(void *start, void *end, struct lb_header **result) +{ + unsigned char *ptr; + /* For now be stupid.... */ + for(ptr = start; (void *)ptr < end; ptr += 16) { + struct lb_header *head = (struct lb_header *)ptr; + if ( (head->signature[0] != 'L') || + (head->signature[1] != 'B') || + (head->signature[2] != 'I') || + (head->signature[3] != 'O')) { + continue; + } + if (head->header_bytes != sizeof(*head)) + continue; + debug("Found canidate at: %p\n", head); + if (ipchksum((uint16_t *)head, sizeof(*head)) != 0) + continue; + debug("header checksum o.k.\n"); + if (ipchksum((uint16_t *)(ptr + sizeof(*head)), head->table_bytes) != + head->table_checksum) { + continue; + } + debug("table checksum o.k.\n"); + if (count_lb_records(ptr + sizeof(*head), head->table_bytes) != + head->table_entries) { + continue; + } + debug("record count o.k.\n"); + *result = head; + return 1; + }; + return 0; +} + +void collect_linuxbios_info(struct sys_info *info) +{ + struct lb_header *lb_table; + int found; + debug("Searching for LinuxBIOS tables...\n"); + found = 0; + if (!found) { + found = find_lb_table(phys_to_virt(0x00000), phys_to_virt(0x01000), &lb_table); + } + if (!found) { + found = find_lb_table(phys_to_virt(0xf0000), phys_to_virt(0x100000), &lb_table); + } + if (!found) + return; + + debug("Found LinuxBIOS table at: %p\n", lb_table); + info->firmware = "LinuxBIOS"; + read_lbtable(lb_table, info); +} diff --git a/qemu/roms/openbios/libopenbios/load.c b/qemu/roms/openbios/libopenbios/load.c new file mode 100644 index 000000000..4bc12ea35 --- /dev/null +++ b/qemu/roms/openbios/libopenbios/load.c @@ -0,0 +1,122 @@ +/* + * Creation Date: <2010/06/25 20:00:00 mcayland> + * Time-stamp: <2010/06/25 20:00:00 mcayland> + * + * <load.c> + * + * C implementation of load + * + * Copyright (C) 2010 Mark Cave-Ayland (mark.cave-ayland@siriusit.co.uk) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#include "config.h" +#include "kernel/kernel.h" +#include "libopenbios/bindings.h" +#include "libopenbios/sys_info.h" +#include "libopenbios/load.h" + +#ifdef CONFIG_LOADER_ELF +#include "libopenbios/elf_load.h" +#endif + +#ifdef CONFIG_LOADER_AOUT +#include "libopenbios/aout_load.h" +#endif + +#ifdef CONFIG_LOADER_FCODE +#include "libopenbios/fcode_load.h" +#endif + +#ifdef CONFIG_LOADER_FORTH +#include "libopenbios/forth_load.h" +#endif + +#ifdef CONFIG_LOADER_BOOTCODE +#include "libopenbios/bootcode_load.h" +#endif + + +struct sys_info sys_info; +void *elf_boot_notes = NULL; + +/* ( addr -- size ) */ + +void load(ihandle_t dev) +{ + /* Invoke the loaders on the specified device */ + char *param; + ucell valid; + + /* TODO: Currently the internal loader APIs use load-base directly, so + drop the address */ + POP(); + +#ifdef CONFIG_LOADER_ELF + + /* Grab the boot arguments */ + push_str("bootargs"); + push_str("/chosen"); + fword("(find-dev)"); + POP(); + fword("get-package-property"); + POP(); + param = pop_fstr_copy(); + + elf_load(&sys_info, dev, param, &elf_boot_notes); + feval("state-valid @"); + valid = POP(); + if (valid) { + feval("saved-program-state >sps.file-size @"); + return; + } +#endif + +#ifdef CONFIG_LOADER_AOUT + aout_load(&sys_info, dev); + feval("state-valid @"); + valid = POP(); + if (valid) { + feval("saved-program-state >sps.file-size @"); + return; + } +#endif + +#ifdef CONFIG_LOADER_FCODE + fcode_load(dev); + feval("state-valid @"); + valid = POP(); + if (valid) { + feval("saved-program-state >sps.file-size @"); + return; + } +#endif + +#ifdef CONFIG_LOADER_FORTH + forth_load(dev); + feval("state-valid @"); + valid = POP(); + if (valid) { + feval("saved-program-state >sps.file-size @"); + return; + } +#endif + +#ifdef CONFIG_LOADER_BOOTCODE + /* Check for a "raw" %BOOT bootcode payload */ + bootcode_load(dev); + feval("state-valid @"); + valid = POP(); + if (valid) { + feval("saved-program-state >sps.file-size @"); + return; + } +#endif + + /* Didn't load anything, so return zero size */ + PUSH(0); +} diff --git a/qemu/roms/openbios/libopenbios/ofmem_common.c b/qemu/roms/openbios/libopenbios/ofmem_common.c new file mode 100644 index 000000000..052aa2f4d --- /dev/null +++ b/qemu/roms/openbios/libopenbios/ofmem_common.c @@ -0,0 +1,990 @@ +/* + * <ofmem_common.c> + * + * OF Memory manager + * + * Copyright (C) 1999-2004 Samuel Rydh (samuel@ibrium.se) + * Copyright (C) 2004 Stefan Reinauer + * + * 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 + * + */ + +#include "config.h" +#include "libopenbios/bindings.h" +#include "libopenbios/ofmem.h" + +/* Default size of memory allocated for each of the MMU properties (in bytes) */ +#define OFMEM_DEFAULT_PROP_SIZE 2048 + +/* + * define OFMEM_FILL_RANGE to claim any unclaimed virtual and + * physical memory in the range for ofmem_map + * + * TODO: remove this macro and wrapped code if not needed by implementations + */ +//#define OFMEM_FILL_RANGE + + +static inline size_t align_size(size_t x, size_t a) +{ + return (x + a - 1) & ~(a - 1); +} + +static inline phys_addr_t align_ptr(uintptr_t x, size_t a) +{ + return (x + a - 1) & ~(a - 1); +} + +static ucell get_ram_size( void ) +{ + ofmem_t *ofmem = ofmem_arch_get_private(); + return ofmem->ramsize; +} + +/************************************************************************/ +/* debug */ +/************************************************************************/ + +#if 0 +static void +print_range( range_t *r, const char *str ) +{ + printk("--- Range %s ---\n", str ); + for( ; r; r=r->next ) + printk("%p : " FMT_plx " - " FMT_plx "\n", r, r->start, r->start + r->size - 1); + printk("\n"); +} + +static void +print_phys_range(void) +{ + ofmem_t *ofmem = ofmem_arch_get_private(); + print_range( ofmem->phys_range, "phys" ); +} + +static void +print_virt_range(void) +{ + ofmem_t *ofmem = ofmem_arch_get_private(); + print_range( ofmem->virt_range, "virt" ); +} + +static void +print_trans( void ) +{ + ofmem_t *ofmem = ofmem_arch_get_private(); + translation_t *t = ofmem->trans; + + printk("--- Translations ---\n"); + for( ; t; t=t->next ) + printk("%p : " FMT_ucellx " -> " FMT_plx " [size " FMT_ucellx "]\n", t, t->virt, t->phys, t->size); + printk("\n"); +} +#endif + +/************************************************************************/ +/* OF private allocations */ +/************************************************************************/ + +int ofmem_posix_memalign( void **memptr, size_t alignment, size_t size ) +{ + ofmem_t *ofmem = ofmem_arch_get_private(); + alloc_desc_t *d, **pp; + void *ret; + ucell top; + phys_addr_t pa; + + if( !size ) + return ENOMEM; + + if( !ofmem->next_malloc ) + ofmem->next_malloc = (char*)ofmem_arch_get_malloc_base(); + + size = align_size(size + sizeof(alloc_desc_t), alignment); + + /* look in the freelist */ + for( pp=&ofmem->mfree; *pp && (**pp).size < size; pp = &(**pp).next ) { + } + + /* waste at most 4K by taking an entry from the freelist */ + if( *pp && (**pp).size > size + 0x1000 ) { + /* Alignment should be on physical not virtual address */ + pa = va2pa((uintptr_t)*pp + sizeof(alloc_desc_t)); + pa = align_ptr(pa, alignment); + ret = (void *)pa2va(pa); + + memset( ret, 0, (**pp).size - sizeof(alloc_desc_t) ); + *pp = (**pp).next; + + *memptr = ret; + return 0; + } + + top = ofmem_arch_get_heap_top(); + + /* Alignment should be on physical not virtual address */ + pa = va2pa((uintptr_t)ofmem->next_malloc + sizeof(alloc_desc_t)); + pa = align_ptr(pa, alignment); + ret = (void *)pa2va(pa); + + if( pointer2cell(ret) + size > top ) { + printk("out of malloc memory (%x)!\n", size ); + return ENOMEM; + } + + d = (alloc_desc_t*)((uintptr_t)ret - sizeof(alloc_desc_t)); + ofmem->next_malloc += size; + + d->next = NULL; + d->size = size; + + memset( ret, 0, size - sizeof(alloc_desc_t) ); + + *memptr = ret; + return 0; +} + +void* ofmem_malloc( size_t size ) +{ + void *memptr; + int res; + + res = ofmem_posix_memalign( &memptr, CONFIG_OFMEM_MALLOC_ALIGN, size ); + if (!res) { + /* Success */ + return memptr; + } else { + /* Failure */ + return NULL; + } +} + +void ofmem_free( void *ptr ) +{ + ofmem_t *ofmem = ofmem_arch_get_private(); + alloc_desc_t **pp, *d; + + /* it is legal to free NULL pointers (size zero allocations) */ + if( !ptr ) + return; + + d = (alloc_desc_t*)((char *)ptr - sizeof(alloc_desc_t)); + d->next = ofmem->mfree; + + /* insert in the (sorted) freelist */ + for( pp=&ofmem->mfree; *pp && (**pp).size < d->size ; pp = &(**pp).next ) { + } + + d->next = *pp; + *pp = d; +} + +void* ofmem_realloc( void *ptr, size_t size ) +{ + alloc_desc_t *d = (alloc_desc_t*)((char *)ptr - sizeof(alloc_desc_t)); + char *p; + + if( !ptr ) + return malloc( size ); + if( !size ) { + free( ptr ); + return NULL; + } + p = malloc( size ); + memcpy( p, ptr, MIN(d->size - sizeof(alloc_desc_t),size) ); + free( ptr ); + return p; +} + + +/************************************************************************/ +/* "translations" and "available" property tracking */ +/************************************************************************/ + +static int trans_prop_size = 0, phys_range_prop_size = 0, virt_range_prop_size = 0; +static int trans_prop_used = 0, phys_range_prop_used = 0, virt_range_prop_used = 0; +static ucell *trans_prop, *phys_range_prop, *virt_range_prop; + +static void +ofmem_set_property( phandle_t ph, const char *name, const char *buf, int len ) +{ + /* This is very similar to set_property() in libopenbios/bindings.c but allows + us to set the property pointer directly, rather than having to copy it + into the Forth dictonary every time we update the memory properties */ + if( !ph ) { + printk("ofmem_set_property: NULL phandle\n"); + return; + } + PUSH(pointer2cell(buf)); + PUSH(len); + push_str(name); + PUSH_ph(ph); + fword("encode-property"); +} + +phandle_t s_phandle_memory = 0; +phandle_t s_phandle_mmu = 0; + +static void ofmem_update_mmu_translations( void ) +{ + ofmem_t *ofmem = ofmem_arch_get_private(); + translation_t *t; + int ncells, prop_used, prop_size; + + if (s_phandle_mmu == 0) + return; + + for( t = ofmem->trans, ncells = 0; t ; t=t->next, ncells++ ) { + } + + /* Get the current number of bytes required for the MMU translation property */ + prop_used = ncells * sizeof(ucell) * ofmem_arch_get_translation_entry_size(); + + if (prop_used > trans_prop_size) { + + /* The property doesn't fit within the existing space, so keep doubling it + until it does */ + prop_size = trans_prop_size; + while (prop_size < prop_used) { + prop_size *= 2; + } + + /* Allocate the new memory and copy all of the existing information across */ + trans_prop = realloc(trans_prop, prop_size); + trans_prop_size = prop_size; + trans_prop_used = prop_used; + } + + if (trans_prop == NULL) { + /* out of memory! */ + printk("Unable to allocate memory for translations property!\n"); + return; + } + + /* Call architecture-specific routines to generate translation entries */ + for( t = ofmem->trans, ncells = 0 ; t ; t=t->next ) { + ofmem_arch_create_translation_entry(&trans_prop[ncells], t); + ncells += ofmem_arch_get_translation_entry_size(); + } + + ofmem_set_property(s_phandle_mmu, "translations", + (char*)trans_prop, ncells * sizeof(trans_prop[0])); + +} + + +static void ofmem_update_memory_available( phandle_t ph, range_t *range, + ucell **mem_prop, int *mem_prop_size, int *mem_prop_used, u64 top_address ) +{ + range_t *r; + int ncells, prop_used, prop_size; + phys_addr_t start; + ucell size, *prop; + + if (s_phandle_memory == 0) + return; + + /* count phys_range list entries */ + for( r = range, ncells = 0; r ; r=r->next, ncells++ ) { + } + + /* inverse of phys_range list could take 2 or more additional cells for the tail + For /memory, physical addresses may be wider than one ucell. */ + prop_used = (ncells + 1) * sizeof(ucell) * ofmem_arch_get_available_entry_size(ph) + 1; + + if (prop_used > *mem_prop_size) { + + /* The property doesn't fit within the existing space, so keep doubling it + until it does */ + prop_size = *mem_prop_size; + while (prop_size < prop_used) { + prop_size *= 2; + } + + /* Allocate the new memory and copy all of the existing information across */ + *mem_prop = realloc(*mem_prop, prop_size); + *mem_prop_size = prop_size; + *mem_prop_used = prop_used; + } + + if (*mem_prop == NULL) { + /* out of memory! */ + printk("Unable to allocate memory for memory range property!\n"); + return; + } + + start = 0; + ncells = 0; + prop = *mem_prop; + + for (r = range; r; r=r->next) { + if (r->start >= top_address) { + break; + } + + size = r->start - start; + if (size) { + ofmem_arch_create_available_entry(ph, &prop[ncells], start, size); + ncells += ofmem_arch_get_available_entry_size(ph); + } + start = r->start + r->size; + } + + /* tail */ + if ((start - 1) < top_address) { + ofmem_arch_create_available_entry(ph, &prop[ncells], start, top_address - start + 1); + ncells += ofmem_arch_get_available_entry_size(ph); + } + + ofmem_set_property(ph, "available", + (char*)prop, ncells * sizeof(prop[0])); +} + +static void ofmem_update_translations( void ) +{ + ofmem_t *ofmem = ofmem_arch_get_private(); + + ofmem_update_memory_available(s_phandle_memory, ofmem->phys_range, + &phys_range_prop, &phys_range_prop_size, &phys_range_prop_used, get_ram_size() - 1); + ofmem_update_memory_available(s_phandle_mmu, ofmem->virt_range, + &virt_range_prop, &virt_range_prop_size, &virt_range_prop_used, (ucell)-1); + ofmem_update_mmu_translations(); +} + + +/************************************************************************/ +/* client interface */ +/************************************************************************/ + +static int is_free( phys_addr_t ea, ucell size, range_t *r ) +{ + if( size == 0 ) + return 1; + for( ; r ; r=r->next ) { + if( r->start + r->size - 1 >= ea && r->start <= ea ) + return 0; + if( r->start >= ea && r->start <= ea + size - 1 ) + return 0; + } + return 1; +} + +static void add_entry_( phys_addr_t ea, ucell size, range_t **r ) +{ + range_t *nr; + + for( ; *r && (**r).start < ea; r=&(**r).next ) { + } + + nr = (range_t*)malloc( sizeof(range_t) ); + nr->next = *r; + nr->start = ea; + nr->size = size; + *r = nr; +} + +static int add_entry( phys_addr_t ea, ucell size, range_t **r ) +{ + if( !is_free( ea, size, *r ) ) { + OFMEM_TRACE("add_entry: range not free!\n"); + return -1; + } + add_entry_( ea, size, r ); + return 0; +} + +#if defined(OFMEM_FILL_RANGE) +static void join_ranges( range_t **rr ) +{ + range_t *n, *r = *rr; + while( r ) { + if( !(n=r->next) ) + break; + + if( r->start + r->size - 1 >= n->start -1 ) { + int s = n->size + (n->start - r->start - r->size); + if( s > 0 ) + r->size += s; + r->next = n->next; + free( n ); + continue; + } + r=r->next; + } +} + +static void fill_range( phys_addr_t ea, ucell size, range_t **rr ) +{ + add_entry_( ea, size, rr ); + join_ranges( rr ); +} +#endif + +static ucell find_area( ucell align, ucell size, range_t *r, + phys_addr_t min, phys_addr_t max, int reverse ) +{ + phys_addr_t base = min; + range_t *r2; + ucell old_align = align; + int i; + + if( (align < PAGE_SIZE) ) { + + /* Minimum alignment is page size */ + align = PAGE_SIZE; + + OFMEM_TRACE("warning: bad alignment " FMT_ucellx " rounded up to " FMT_ucellx "\n", old_align, align); + } + + if( (align & (align-1)) ) { + + /* As per IEEE1275 specification, round up to the nearest power of 2 */ + align--; + for (i = 1; i < sizeof(ucell) * 8; i<<=1) { + align |= align >> i; + } + align++; + + OFMEM_TRACE("warning: bad alignment " FMT_ucellx " rounded up to " FMT_ucellx "\n", old_align, align); + } + + base = reverse ? max - size : min; + r2 = reverse ? NULL : r; + + for( ;; ) { + if( !reverse ) { + base = (base + align - 1) & ~(align-1); + if( base < min ) + base = min; + if( base + size - 1 >= max -1 ) + break; + } else { + if( base > max - size ) + base = max - size; + base -= base & (align-1); + } + if( is_free( base, size, r ) ) + return base; + + if( !reverse ) { + if( !r2 ) + break; + base = r2->start + r2->size; + r2 = r2->next; + } else { + range_t *rp; + + for( rp=r; rp && rp->next != r2 ; rp=rp->next ) { + } + + r2 = rp; + if( !r2 ) + break; + base = r2->start - size; + } + } + return -1; +} + +static phys_addr_t ofmem_claim_phys_( phys_addr_t phys, ucell size, ucell align, + phys_addr_t min, phys_addr_t max, int reverse ) +{ + ofmem_t *ofmem = ofmem_arch_get_private(); + if( !align ) { + if( !is_free( phys, size, ofmem->phys_range ) ) { + OFMEM_TRACE("Non-free physical memory claimed!\n"); + return -1; + } + add_entry( phys, size, &ofmem->phys_range ); + ofmem_update_translations(); + return phys; + } + phys = find_area( align, size, ofmem->phys_range, min, max, reverse ); + if( phys == -1 ) { + printk("ofmem_claim_phys - out of space (failed request for " FMT_ucellx " bytes)\n", size); + return -1; + } + add_entry( phys, size, &ofmem->phys_range ); + + ofmem_update_translations(); + + return phys; +} + +/* if align != 0, phys is ignored. Returns -1 on error */ +phys_addr_t ofmem_claim_phys( phys_addr_t phys, ucell size, ucell align ) +{ + OFMEM_TRACE("ofmem_claim_phys phys=" FMT_plx " size=" FMT_ucellx + " align=" FMT_ucellx "\n", + phys, size, align); + + return ofmem_claim_phys_( phys, size, align, 0, get_ram_size(), 1 ); +} + +static ucell ofmem_claim_virt_( ucell virt, ucell size, ucell align, + ucell min, ucell max, int reverse ) +{ + ofmem_t *ofmem = ofmem_arch_get_private(); + if( !align ) { + if( !is_free( virt, size, ofmem->virt_range ) ) { + OFMEM_TRACE("Non-free virtual memory claimed!\n"); + return -1; + } + add_entry( virt, size, &ofmem->virt_range ); + ofmem_update_translations(); + return virt; + } + + virt = find_area( align, size, ofmem->virt_range, min, max, reverse ); + if( virt == -1 ) { + printk("ofmem_claim_virt - out of space (failed request for " FMT_ucellx " bytes)\n", size); + return -1; + } + add_entry( virt, size, &ofmem->virt_range ); + + ofmem_update_translations(); + + return virt; +} + +ucell ofmem_claim_virt( ucell virt, ucell size, ucell align ) +{ + OFMEM_TRACE("ofmem_claim_virt virt=" FMT_ucellx " size=" FMT_ucellx + " align=" FMT_ucellx "\n", + virt, size, align); + + /* printk("+ ofmem_claim virt %08lx %lx %ld\n", virt, size, align ); */ + return ofmem_claim_virt_( virt, size, align, + get_ram_size(), ofmem_arch_get_virt_top(), 1 ); +} + +static ucell ofmem_claim_io_( ucell virt, ucell size, ucell align, + ucell min, ucell max, int reverse ) +{ + ofmem_t *ofmem = ofmem_arch_get_private(); + if( !align ) { + if( !is_free( virt, size, ofmem->io_range ) ) { + OFMEM_TRACE("Non-free I/O memory claimed!\n"); + return -1; + } + add_entry( virt, size, &ofmem->io_range ); + return virt; + } + + virt = find_area( align, size, ofmem->io_range, min, max, reverse ); + if( virt == -1 ) { + printk("ofmem_claim_io - out of space (failed request for " FMT_ucellx " bytes)\n", size); + return -1; + } + add_entry( virt, size, &ofmem->io_range ); + return virt; +} + +ucell ofmem_claim_io( ucell virt, ucell size, ucell align ) +{ + /* Claim a section of memory from the I/O range */ + return ofmem_claim_io_( virt, size, align, + ofmem_arch_get_iomem_base(), ofmem_arch_get_iomem_top(), 0 ); +} + +/* if align != 0, phys is ignored. Returns -1 on error */ +phys_addr_t ofmem_retain( phys_addr_t phys, ucell size, ucell align ) +{ + retain_t *retained = ofmem_arch_get_retained(); + phys_addr_t retain_phys; + + OFMEM_TRACE("ofmem_retain phys=" FMT_plx " size=" FMT_ucellx + " align=" FMT_ucellx "\n", + phys, size, align); + + retain_phys = ofmem_claim_phys_( phys, size, align, 0, get_ram_size(), 1 /* reverse */ ); + + /* Add to the retain_phys_range list */ + retained->retain_phys_range[retained->numentries].next = NULL; + retained->retain_phys_range[retained->numentries].start = retain_phys; + retained->retain_phys_range[retained->numentries].size = size; + retained->numentries++; + + return retain_phys; +} + +/* allocate both physical and virtual space and add a translation */ +ucell ofmem_claim( ucell addr, ucell size, ucell align ) +{ + ofmem_t *ofmem = ofmem_arch_get_private(); + ucell virt; + phys_addr_t phys; + ucell offs = addr & (PAGE_SIZE - 1); + + OFMEM_TRACE("ofmem_claim " FMT_ucellx " " FMT_ucellx " " FMT_ucellx "\n", addr, size, align ); + virt = phys = 0; + if( !align ) { + if( is_free(addr, size, ofmem->virt_range) && + is_free(addr, size, ofmem->phys_range) ) { + ofmem_claim_phys_( addr, size, 0, 0, 0, 0 ); + ofmem_claim_virt_( addr, size, 0, 0, 0, 0 ); + virt = phys = addr; + } else { + OFMEM_TRACE("**** ofmem_claim failure ***!\n"); + return -1; + } + } else { + if( align < PAGE_SIZE ) + align = PAGE_SIZE; + phys = ofmem_claim_phys_( -1, size, align, 0, get_ram_size(), 1 /* reverse */ ); + virt = ofmem_claim_virt_( phys, size, 0, 0, 0, 0 ); + if( phys == -1 || virt == -1 ) { + OFMEM_TRACE("ofmem_claim failed\n"); + return -1; + } + /* printk("...phys = %08lX, virt = %08lX, size = %08lX\n", phys, virt, size ); */ + } + + /* align */ + if( phys & (PAGE_SIZE - 1) ) { + size += (phys & (PAGE_SIZE - 1)); + virt -= (phys & (PAGE_SIZE - 1)); + phys &= PAGE_MASK; + } + if( size & (PAGE_SIZE - 1) ) + size = (size + (PAGE_SIZE - 1)) & PAGE_MASK; + + /* printk("...free memory found... phys: %08lX, virt: %08lX, size %lX\n", phys, virt, size ); */ + ofmem_map( phys, virt, size, -1 ); + return virt + offs; +} + + +/************************************************************************/ +/* keep track of ea -> phys translations */ +/************************************************************************/ + +static void split_trans( ucell virt ) +{ + ofmem_t *ofmem = ofmem_arch_get_private(); + translation_t *t, *t2; + + for( t=ofmem->trans; t; t=t->next ) { + if( virt > t->virt && virt < t->virt + t->size-1 ) { + t2 = (translation_t*)malloc( sizeof(translation_t) ); + t2->virt = virt; + t2->size = t->size - (virt - t->virt); + t->size = virt - t->virt; + t2->phys = t->phys + t->size; + t2->mode = t->mode; + t2->next = t->next; + t->next = t2; + } + } +} + +int ofmem_map_page_range( phys_addr_t phys, ucell virt, ucell size, ucell mode ) +{ + ofmem_t *ofmem = ofmem_arch_get_private(); + translation_t *t, **tt; + + OFMEM_TRACE("ofmem_map_page_range " FMT_ucellx + " -> " FMT_plx " " FMT_ucellx " mode " FMT_ucellx "\n", + virt, phys, size, mode ); + + split_trans( virt ); + split_trans( virt + size ); + + /* detect remappings */ + for( t=ofmem->trans; t; ) { + if( virt == t->virt || (virt < t->virt && virt + size > t->virt )) { + if( t->phys + virt - t->virt != phys ) { + OFMEM_TRACE("mapping altered virt=" FMT_ucellx ")\n", t->virt ); + } else if( t->mode != mode ){ + OFMEM_TRACE("mapping mode altered virt=" FMT_ucellx + " old mode=" FMT_ucellx " new mode=" FMT_ucellx "\n", + t->virt, t->mode, mode); + } + + for( tt=&ofmem->trans; *tt != t ; tt=&(**tt).next ) { + } + + *tt = t->next; + + /* really unmap these pages */ + ofmem_arch_unmap_pages(t->virt, t->size); + + free((char*)t); + + t=ofmem->trans; + continue; + } + t=t->next; + } + + /* add mapping */ + for( tt=&ofmem->trans; *tt && (**tt).virt < virt ; tt=&(**tt).next ) { + } + + t = (translation_t*)malloc( sizeof(translation_t) ); + t->virt = virt; + t->phys = phys; + t->size = size; + t->mode = mode; + t->next = *tt; + *tt = t; + + ofmem_update_translations(); + + return 0; +} + +static int unmap_page_range( ucell virt, ucell size ) +{ + ofmem_t *ofmem = ofmem_arch_get_private(); + translation_t **plink; + + /* make sure there is exactly one matching translation entry */ + + split_trans( virt ); + split_trans( virt + size ); + + /* find and unlink entries in range */ + plink = &ofmem->trans; + + while (*plink && (*plink)->virt < virt+size) { + translation_t **plinkentry = plink; + translation_t *t = *plink; + + /* move ahead */ + plink = &t->next; + + if (t->virt >= virt && t->virt + t->size <= virt+size) { + + /* unlink entry */ + *plinkentry = t->next; + + OFMEM_TRACE("unmap_page_range found " + FMT_ucellx " -> " FMT_plx " " FMT_ucellx + " mode " FMT_ucellx "\n", + t->virt, t->phys, t->size, t->mode ); + + // really map these pages + ofmem_arch_unmap_pages(t->virt, t->size); + + free((char*)t); + } + } + + ofmem_update_translations(); + + return 0; +} + +int ofmem_map( phys_addr_t phys, ucell virt, ucell size, ucell mode ) +{ + /* printk("+ofmem_map: %08lX --> %08lX (size %08lX, mode 0x%02X)\n", + virt, phys, size, mode ); */ + + if( (phys & (PAGE_SIZE - 1)) || (virt & (PAGE_SIZE - 1)) || (size & (PAGE_SIZE - 1)) ) { + + OFMEM_TRACE("ofmem_map: Bad parameters (" + FMT_plx " " FMT_ucellx " " FMT_ucellx ")\n", + phys, virt, size ); + + phys &= PAGE_MASK; + virt &= PAGE_MASK; + size = (size + (PAGE_SIZE - 1)) & PAGE_MASK; + } + +#if defined(OFMEM_FILL_RANGE) + { + ofmem_t *ofmem = ofmem_arch_get_private(); + /* claim any unclaimed virtual memory in the range */ + fill_range( virt, size, &ofmem->virt_range ); + /* hmm... we better claim the physical range too */ + fill_range( phys, size, &ofmem->phys_range ); + } +#endif + + if (mode==-1) { + mode = ofmem_arch_default_translation_mode(phys); + } + + /* install translations */ + ofmem_map_page_range(phys, virt, size, mode); + + /* allow arch to map the pages */ + ofmem_arch_map_pages(phys, virt, size, mode); + + return 0; +} + +int ofmem_unmap( ucell virt, ucell size ) +{ + OFMEM_TRACE("ofmem_unmap " FMT_ucellx " " FMT_ucellx "\n", + virt, size ); + + if( (virt & (PAGE_SIZE - 1)) || (size & (PAGE_SIZE - 1)) ) { + /* printk("ofmem_unmap: Bad parameters (%08lX %08lX)\n", + virt, size ); */ + virt &= PAGE_MASK; + size = (size + (PAGE_SIZE - 1)) & PAGE_MASK; + } + + /* remove translations and unmap pages */ + unmap_page_range(virt, size); + + return 0; +} + +ucell ofmem_map_io( phys_addr_t phys, ucell size ) +{ + /* Claim virtual memory from the I/O range and map the page-aligned + physical address phys to it, returning the newly allocated + virtual address */ + ucell virt, mode; + phys_addr_t off; + int npages; + + off = phys & (PAGE_SIZE - 1); + npages = (off + size - 1) / PAGE_SIZE + 1; + phys &= ~(PAGE_SIZE - 1); + + virt = ofmem_claim_io(-1, npages * PAGE_SIZE, PAGE_SIZE); + + mode = ofmem_arch_io_translation_mode(off); + + ofmem_map_page_range(phys, virt, npages * PAGE_SIZE, mode); + ofmem_arch_map_pages(phys, virt, npages * PAGE_SIZE, mode); + + return (virt + off); +} + +/* virtual -> physical. */ +phys_addr_t ofmem_translate( ucell virt, ucell *mode ) +{ + ofmem_t *ofmem = ofmem_arch_get_private(); + translation_t *t; + + for( t=ofmem->trans; t && t->virt <= virt ; t=t->next ) { + ucell offs; + if( t->virt + t->size - 1 < virt ) + continue; + offs = virt - t->virt; + *mode = t->mode; + return t->phys + offs; + } + + /*printk("ofmem_translate: no translation defined (%08lx)\n", virt);*/ + /*print_trans();*/ + return -1; +} + +static void remove_range_( phys_addr_t ea, ucell size, range_t **r ) +{ + range_t **t, *u; + + /* If not an exact match then split the range */ + for (t = r; *t; t = &(**t).next) { + if (ea > (**t).start && ea < (**t).start + (**t).size - 1) { + u = (range_t*)malloc(sizeof(range_t)); + u->start = ea; + u->size = size; + u->next = (**t).next; + + OFMEM_TRACE("remove_range_ splitting range with addr=" FMT_plx + " size=" FMT_ucellx " -> addr=" FMT_plx " size=" FMT_ucellx ", " + "addr=" FMT_plx " size=" FMT_ucellx "\n", + (**t).start, (**t).size, (**t).start, (**t).size - size, + u->start, u->size); + + (**t).size = (**t).size - size; + (**t).next = u; + } + } + + for (t = r; *t; t = &(**t).next) { + if (ea >= (**t).start && ea + size <= (**t).start + (**t).size) { + OFMEM_TRACE("remove_range_ freeing range with addr=" FMT_plx + " size=" FMT_ucellx "\n", (**t).start, (**t).size); + u = *t; + *t = (**t).next; + free(u); + break; + } + } +} + +static int remove_range( phys_addr_t ea, ucell size, range_t **r ) +{ + if( is_free( ea, size, *r ) ) { + OFMEM_TRACE("remove_range: range isn't occupied\n"); + return -1; + } + remove_range_( ea, size, r ); + return 0; +} + +/* release memory allocated by ofmem_claim_phys */ +void ofmem_release_phys( phys_addr_t phys, ucell size ) +{ + OFMEM_TRACE("ofmem_release_phys addr=" FMT_plx " size=" FMT_ucellx "\n", + phys, size); + + ofmem_t *ofmem = ofmem_arch_get_private(); + remove_range(phys, size, &ofmem->phys_range); +} + +/* release memory allocated by ofmem_claim_virt */ +void ofmem_release_virt( ucell virt, ucell size ) +{ + OFMEM_TRACE("ofmem_release_virt addr=" FMT_ucellx " size=" FMT_ucellx "\n", + virt, size); + + ofmem_t *ofmem = ofmem_arch_get_private(); + remove_range(virt, size, &ofmem->virt_range); +} + +/* release memory allocated by ofmem_claim_io */ +void ofmem_release_io( ucell virt, ucell size ) +{ + OFMEM_TRACE("ofmem_release_io addr=" FMT_ucellx " size=" FMT_ucellx "\n", + virt, size); + + ofmem_t *ofmem = ofmem_arch_get_private(); + remove_range(virt, size, &ofmem->io_range); +} + +/* release memory allocated by ofmem_claim - 6.3.2.4 */ +void ofmem_release( ucell virt, ucell size ) +{ + OFMEM_TRACE("%s addr=" FMT_ucellx " size=" FMT_ucellx "\n", + __func__, virt, size); + + ucell mode; + phys_addr_t phys = ofmem_translate(virt, &mode); + if (phys == (phys_addr_t)-1) { + OFMEM_TRACE("%s: no mapping\n", __func__); + return; + } + ofmem_unmap(virt, size); + ofmem_release_virt(virt, size); + ofmem_release_phys(phys, size); +} + +/************************************************************************/ +/* init / cleanup */ +/************************************************************************/ + +void ofmem_register( phandle_t ph_memory, phandle_t ph_mmu ) +{ + s_phandle_memory = ph_memory; + s_phandle_mmu = ph_mmu; + + /* Initialise some default property sizes */ + trans_prop_size = phys_range_prop_size = virt_range_prop_size = OFMEM_DEFAULT_PROP_SIZE; + trans_prop = malloc(trans_prop_size); + phys_range_prop = malloc(phys_range_prop_size); + virt_range_prop = malloc(virt_range_prop_size); + + ofmem_update_translations(); +} diff --git a/qemu/roms/openbios/libopenbios/video_common.c b/qemu/roms/openbios/libopenbios/video_common.c new file mode 100644 index 000000000..9bbc18c3c --- /dev/null +++ b/qemu/roms/openbios/libopenbios/video_common.c @@ -0,0 +1,258 @@ +/* + * Creation Date: <2002/10/23 20:26:40 samuel> + * Time-stamp: <2004/01/07 19:39:15 samuel> + * + * <video_common.c> + * + * Shared video routines + * + * Copyright (C) 2002, 2003, 2004 Samuel Rydh (samuel@ibrium.se) + * + * 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 + * + */ + +#include "config.h" +#include "libc/vsprintf.h" +#include "libopenbios/bindings.h" +#include "libopenbios/fontdata.h" +#include "libopenbios/ofmem.h" +#include "libopenbios/video.h" +#include "packages/video.h" +#include "drivers/vga.h" +#define NO_QEMU_PROTOS +#include "arch/common/fw_cfg.h" + +struct video_info video; + +unsigned long +video_get_color( int col_ind ) +{ + unsigned long col; + if( !VIDEO_DICT_VALUE(video.ih) || col_ind < 0 || col_ind > 255 ) + return 0; + if( VIDEO_DICT_VALUE(video.depth) == 8 ) + return col_ind; + col = video.pal[col_ind]; + if( VIDEO_DICT_VALUE(video.depth) == 24 || VIDEO_DICT_VALUE(video.depth) == 32 ) + return col; + if( VIDEO_DICT_VALUE(video.depth) == 15 ) + return ((col>>9) & 0x7c00) | ((col>>6) & 0x03e0) | ((col>>3) & 0x1f); + return 0; +} + +/* ( fbaddr maskaddr width height fgcolor bgcolor -- ) */ + +void +video_mask_blit(void) +{ + ucell bgcolor = POP(); + ucell fgcolor = POP(); + ucell height = POP(); + ucell width = POP(); + unsigned char *mask = (unsigned char *)POP(); + unsigned char *fbaddr = (unsigned char *)POP(); + + ucell color; + unsigned char *dst, *rowdst; + int x, y, m, b, d, depthbytes; + + fgcolor = video_get_color(fgcolor); + bgcolor = video_get_color(bgcolor); + d = VIDEO_DICT_VALUE(video.depth); + depthbytes = (d + 1) >> 3; + + dst = fbaddr; + for( y = 0; y < height; y++) { + rowdst = dst; + for( x = 0; x < (width + 1) >> 3; x++ ) { + for (b = 0; b < 8; b++) { + m = (1 << (7 - b)); + + if (*mask & m) { + color = fgcolor; + } else { + color = bgcolor; + } + + if( d >= 24 ) + *((uint32_t*)dst) = color; + else if( d >= 15 ) + *((uint16_t*)dst) = color; + else + *dst = color; + + dst += depthbytes; + } + mask++; + } + dst = rowdst; + dst += VIDEO_DICT_VALUE(video.rb); + } +} + +/* ( x y w h fgcolor bgcolor -- ) */ + +void +video_invert_rect( void ) +{ + ucell bgcolor = POP(); + ucell fgcolor = POP(); + int h = POP(); + int w = POP(); + int y = POP(); + int x = POP(); + char *pp; + + bgcolor = video_get_color(bgcolor); + fgcolor = video_get_color(fgcolor); + + if (!VIDEO_DICT_VALUE(video.ih) || x < 0 || y < 0 || w <= 0 || h <= 0 || + x + w > VIDEO_DICT_VALUE(video.w) || y + h > VIDEO_DICT_VALUE(video.h)) + return; + + pp = (char*)VIDEO_DICT_VALUE(video.mvirt) + VIDEO_DICT_VALUE(video.rb) * y; + for( ; h--; pp += *(video.rb) ) { + int ww = w; + if( VIDEO_DICT_VALUE(video.depth) == 24 || VIDEO_DICT_VALUE(video.depth) == 32 ) { + uint32_t *p = (uint32_t*)pp + x; + while( ww-- ) { + if (*p == fgcolor) { + *p++ = bgcolor; + } else if (*p == bgcolor) { + *p++ = fgcolor; + } + } + } else if( VIDEO_DICT_VALUE(video.depth) == 16 || VIDEO_DICT_VALUE(video.depth) == 15 ) { + uint16_t *p = (uint16_t*)pp + x; + while( ww-- ) { + if (*p == (uint16_t)fgcolor) { + *p++ = bgcolor; + } else if (*p == (uint16_t)bgcolor) { + *p++ = fgcolor; + } + } + } else { + char *p = (char *)(pp + x); + + while( ww-- ) { + if (*p == (char)fgcolor) { + *p++ = bgcolor; + } else if (*p == (char)bgcolor) { + *p++ = fgcolor; + } + } + } + } +} + +/* ( color_ind x y width height -- ) (?) */ +void +video_fill_rect(void) +{ + int h = POP(); + int w = POP(); + int y = POP(); + int x = POP(); + int col_ind = POP(); + + char *pp; + unsigned long col = video_get_color(col_ind); + + if (!VIDEO_DICT_VALUE(video.ih) || x < 0 || y < 0 || w <= 0 || h <= 0 || + x + w > VIDEO_DICT_VALUE(video.w) || y + h > VIDEO_DICT_VALUE(video.h)) + return; + + pp = (char*)VIDEO_DICT_VALUE(video.mvirt) + VIDEO_DICT_VALUE(video.rb) * y; + for( ; h--; pp += VIDEO_DICT_VALUE(video.rb) ) { + int ww = w; + if( VIDEO_DICT_VALUE(video.depth) == 24 || VIDEO_DICT_VALUE(video.depth) == 32 ) { + uint32_t *p = (uint32_t*)pp + x; + while( ww-- ) + *p++ = col; + } else if( VIDEO_DICT_VALUE(video.depth) == 16 || VIDEO_DICT_VALUE(video.depth) == 15 ) { + uint16_t *p = (uint16_t*)pp + x; + while( ww-- ) + *p++ = col; + } else { + char *p = (char *)(pp + x); + + while( ww-- ) + *p++ = col; + } + } +} + +void setup_video() +{ + /* Make everything inside the video_info structure point to the + values in the Forth dictionary. Hence everything is always in + sync. */ + phandle_t options; + char buf[6]; + + feval("['] display-ih cell+"); + video.ih = cell2pointer(POP()); + + feval("['] frame-buffer-adr cell+"); + video.mvirt = cell2pointer(POP()); + feval("['] openbios-video-width cell+"); + video.w = cell2pointer(POP()); + feval("['] openbios-video-height cell+"); + video.h = cell2pointer(POP()); + feval("['] depth-bits cell+"); + video.depth = cell2pointer(POP()); + feval("['] line-bytes cell+"); + video.rb = cell2pointer(POP()); + feval("['] color-palette cell+"); + video.pal = cell2pointer(POP()); + + /* Set global variables ready for fb8-install */ + PUSH( pointer2cell(video_mask_blit) ); + fword("is-noname-cfunc"); + feval("to fb8-blitmask"); + PUSH( pointer2cell(video_fill_rect) ); + fword("is-noname-cfunc"); + feval("to fb8-fillrect"); + PUSH( pointer2cell(video_invert_rect) ); + fword("is-noname-cfunc"); + feval("to fb8-invertrect"); + + /* Static information */ + PUSH((ucell)fontdata); + feval("to (romfont)"); + PUSH(FONT_HEIGHT); + feval("to (romfont-height)"); + PUSH(FONT_WIDTH); + feval("to (romfont-width)"); + + /* Initialise the structure */ + VIDEO_DICT_VALUE(video.w) = VGA_DEFAULT_WIDTH; + VIDEO_DICT_VALUE(video.h) = VGA_DEFAULT_HEIGHT; + VIDEO_DICT_VALUE(video.depth) = VGA_DEFAULT_DEPTH; + VIDEO_DICT_VALUE(video.rb) = VGA_DEFAULT_LINEBYTES; + +#if defined(CONFIG_QEMU) && (defined(CONFIG_PPC) || defined(CONFIG_SPARC32) || defined(CONFIG_SPARC64)) + /* If running from QEMU, grab the parameters from the firmware interface */ + int w, h, d; + + w = fw_cfg_read_i16(FW_CFG_ARCH_WIDTH); + h = fw_cfg_read_i16(FW_CFG_ARCH_HEIGHT); + d = fw_cfg_read_i16(FW_CFG_ARCH_DEPTH); + if (w && h && d) { + VIDEO_DICT_VALUE(video.w) = w; + VIDEO_DICT_VALUE(video.h) = h; + VIDEO_DICT_VALUE(video.depth) = d; + VIDEO_DICT_VALUE(video.rb) = (w * ((d + 7) / 8)); + } +#endif + + /* Setup screen-#rows/screen-#columns */ + options = find_dev("/options"); + snprintf(buf, sizeof(buf), FMT_ucell, VIDEO_DICT_VALUE(video.w) / FONT_WIDTH); + set_property(options, "screen-#columns", buf, strlen(buf) + 1); + snprintf(buf, sizeof(buf), FMT_ucell, VIDEO_DICT_VALUE(video.h) / FONT_HEIGHT); + set_property(options, "screen-#rows", buf, strlen(buf) + 1); +} diff --git a/qemu/roms/openbios/libopenbios/xcoff_load.c b/qemu/roms/openbios/libopenbios/xcoff_load.c new file mode 100644 index 000000000..0dcb28ca4 --- /dev/null +++ b/qemu/roms/openbios/libopenbios/xcoff_load.c @@ -0,0 +1,147 @@ +/* + * + * <xcoff_load.c> + * + * XCOFF file loader + * + * Copyright (C) 2009 Laurent Vivier (Laurent@vivier.eu) + * + * from original XCOFF loader by Steven Noonan <steven@uplinklabs.net> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#include "config.h" +#include "libopenbios/bindings.h" +#include "libopenbios/xcoff_load.h" + +#include "arch/common/xcoff.h" + +#ifdef CONFIG_PPC +extern void flush_icache_range( char *start, char *stop ); +#endif + +//#define DEBUG_XCOFF + +#ifdef DEBUG_XCOFF +#define DPRINTF(fmt, args...) \ + do { printk("%s: " fmt, __func__ , ##args); } while (0) +#else +#define DPRINTF(fmt, args...) \ + do { } while (0) +#endif + +int +is_xcoff(COFF_filehdr_t *fhdr) +{ + return (fhdr->f_magic == U802WRMAGIC + || fhdr->f_magic == U802ROMAGIC + || fhdr->f_magic == U802TOCMAGIC + || fhdr->f_magic == U802TOMAGIC); +} + +int +xcoff_load(struct sys_info *info, const char *filename) +{ + // Currently not implemented + return LOADER_NOT_SUPPORT; +} + +void +xcoff_init_program(void) +{ + char *base; + COFF_filehdr_t *fhdr; + COFF_aouthdr_t *ahdr; + COFF_scnhdr_t *shdr; + uint32_t offset; + size_t total_size = 0; + int i; + + feval("0 state-valid !"); + + feval("load-base"); + base = (char*)cell2pointer(POP()); + + fhdr = (COFF_filehdr_t*)base; + + /* Is it an XCOFF file ? */ + if (!is_xcoff(fhdr)) { + DPRINTF("Not a XCOFF file %02x\n", fhdr->f_magic); + return; + } + + /* Is it executable ? */ + if (fhdr->f_magic != 0x01DF && + (fhdr->f_flags & COFF_F_EXEC) == 0) { + DPRINTF("Not an executable XCOFF file %02x\n", fhdr->f_flags); + return; + } + + /* Optional header is a.out ? */ + if (fhdr->f_opthdr != sizeof(COFF_aouthdr_t)) { + DPRINTF("AOUT optional error size mismatch in XCOFF file\n"); + return; + } + + ahdr = (COFF_aouthdr_t*)(base + sizeof(COFF_filehdr_t)); + + /* check a.out magic number */ + if (ahdr->magic != AOUT_MAGIC) { + DPRINTF("Invalid AOUT optional header\n"); + return; + } + + offset = sizeof(COFF_filehdr_t) + sizeof(COFF_aouthdr_t); + + DPRINTF("XCOFF file with %d sections\n", fhdr->f_nscns); + + for (i = 0; i < fhdr->f_nscns; i++) { + + DPRINTF("Read header at offset %0x\n", offset); + + shdr = (COFF_scnhdr_t*)(base + offset); + + DPRINTF("Initializing '%s' section from %0x %0x to %0x (%0x)\n", + shdr->s_name, offset, shdr->s_scnptr, + shdr->s_vaddr, shdr->s_size); + + if (strcmp(shdr->s_name, ".text") == 0) { + + memcpy((char*)(uintptr_t)shdr->s_vaddr, base + shdr->s_scnptr, + shdr->s_size); + total_size += shdr->s_size; +#ifdef CONFIG_PPC + flush_icache_range((char*)(uintptr_t)shdr->s_vaddr, + (char*)(uintptr_t)(shdr->s_vaddr + shdr->s_size)); +#endif + } else if (strcmp(shdr->s_name, ".data") == 0) { + + memcpy((char*)(uintptr_t)shdr->s_vaddr, base + shdr->s_scnptr, + shdr->s_size); + total_size += shdr->s_size; + + } else if (strcmp(shdr->s_name, ".bss") == 0) { + + memset((void *)(uintptr_t)shdr->s_vaddr, 0, shdr->s_size); + total_size += shdr->s_size; + } else { + DPRINTF(" Skip '%s' section\n", shdr->s_name); + } + offset += sizeof(COFF_scnhdr_t); + } + + DPRINTF("XCOFF entry point: %x\n", *(uint32_t*)ahdr->entry); + + // Initialise saved-program-state + PUSH(*(uint32_t*)(uintptr_t)ahdr->entry); + feval("saved-program-state >sps.entry !"); + PUSH(total_size); + feval("saved-program-state >sps.file-size !"); + feval("xcoff saved-program-state >sps.file-type !"); + + feval("-1 state-valid !"); +} diff --git a/qemu/roms/openbios/packages/bootinfo-loader.c b/qemu/roms/openbios/packages/bootinfo-loader.c new file mode 100644 index 000000000..1497227cb --- /dev/null +++ b/qemu/roms/openbios/packages/bootinfo-loader.c @@ -0,0 +1,29 @@ +/* + * + * <bootinfo-loader.c> + * + * bootinfo file loader + * + * Copyright (C) 2009 Laurent Vivier (Laurent@vivier.eu) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#include "config.h" +#include "libopenbios/bindings.h" +#include "libopenbios/bootinfo_load.h" +#include "packages.h" + +DECLARE_NODE(bootinfo_loader, INSTALL_OPEN, 0, "+/packages/bootinfo-loader" ); + +NODE_METHODS( bootinfo_loader ) = { + { "init-program", bootinfo_init_program }, +}; + +void bootinfo_loader_init( void ) +{ + REGISTER_NODE( bootinfo_loader ); +} diff --git a/qemu/roms/openbios/packages/build.xml b/qemu/roms/openbios/packages/build.xml new file mode 100644 index 000000000..bf49099c3 --- /dev/null +++ b/qemu/roms/openbios/packages/build.xml @@ -0,0 +1,23 @@ +<build> + + <library name="packages" type="static" target="target"> + <object source="bootinfo-loader.c" condition="LOADER_BOOTINFO"/> + <object source="cmdline.c" condition="CMDLINE"/> + <object source="deblocker.c" condition="DEBLOCKER"/> + <object source="disk-label.c" condition="DISK_LABEL"/> + <object source="elf-loader.c" condition="LOADER_ELF"/> + <object source="init.c"/> + <object source="mac-parts.c" condition="MAC_PARTS"/> + <object source="nvram.c"/> + <object source="pc-parts.c" condition="PC_PARTS"/> + <object source="sun-parts.c" condition="SUN_PARTS"/> + <object source="molvideo.c" condition="MOL"/> + <object source="xcoff-loader.c" condition="LOADER_XCOFF"/> + </library> + + <dictionary name="openbios" target="forth"> + <object source="cmdline.fs"/> + <object source="disk-label.fs"/> + </dictionary> + +</build> diff --git a/qemu/roms/openbios/packages/cmdline.c b/qemu/roms/openbios/packages/cmdline.c new file mode 100644 index 000000000..ea6bca3db --- /dev/null +++ b/qemu/roms/openbios/packages/cmdline.c @@ -0,0 +1,415 @@ +/* + * Creation Date: <2003/12/28 14:16:31 samuel> + * Time-stamp: <2004/01/07 10:37:40 samuel> + * + * <cmdline.c> + * + * OpenFirmwware User Interface + * + * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#include "config.h" +#include "libopenbios/bindings.h" +#include "packages.h" +#include "libc/vsprintf.h" + +typedef struct { + char *buf; /* size: ncol+1 */ + char *killbuf; /* size: ncol+1 */ + char *history; + int hsize; /* size of history buffer */ + int ncol; /* #columns */ +} cmdline_info_t; + +DECLARE_NODE( cmdline, INSTALL_OPEN, sizeof(cmdline_info_t), + "+/packages/cmdline" ); + +static void +emit( int ch ) +{ + PUSH( ch ); + fword("emit"); +} + +static int +emit_str( const char *str ) +{ + int n = 0; + while( *str ) { + n++; + emit( *str++ ); + } + return n; +} + +static void +move_cursor( int n ) +{ + if( n >= 0 ) { + while( n-- ) + emit( '\f' ); + } else { + while( n++ ) + emit( 8 ); + } +} + +static void +clear( int n ) +{ + int i; + for( i=0; i<n; i++ ) + emit(' '); + move_cursor( -n ); +} + +static void +clearline( int pos, int n ) +{ + move_cursor( -pos ); + clear( n ); +} + +static int +key( void ) +{ + fword("key"); + return POP(); +} + +/* ( -- flag ) */ +static void +cmdline_open( cmdline_info_t *ci ) +{ + ci->ncol = 80; + ci->buf = malloc( ci->ncol + 1 ); + ci->killbuf = malloc( ci->ncol + 1 ); + + ci->hsize = 40; + ci->history = malloc( ci->hsize ); + ci->history[0] = 0; + + RET( -1 ); +} + +/* ( -- ) */ +static void +cmdline_close( cmdline_info_t *ci ) +{ + free( ci->buf ); + free( ci->killbuf ); + free( ci->history ); +} + + +static char * +history_get( cmdline_info_t *ci, int n ) +{ + char *p = ci->history; + int len; + + while( n-- && p ) + if( (p=strchr(p,'\n')) ) + p++; + + ci->buf[0] = 0; + if( !p ) + return NULL; + + for( len=0; len <= ci->ncol && p[len] != '\n' && p[len] ; len++ ) + ; + memcpy( ci->buf, p, len ); + ci->buf[len] = 0; + return p; +} + +static int +history_remove( cmdline_info_t *ci, int line ) +{ + char *s, *p = history_get( ci, line ); + + if( !p || !(s=strchr(p, '\n')) ) + return 1; + s++; + memmove( p, s, strlen(s)+1 ); + return 0; +} + +static int /* ( -- ) */ +add_to_history( cmdline_info_t *ci, char *str ) +{ + int n, len; + + if( !ci->history ) + return 0; + len = strlen(str); + if( !len ) + return 0; + + /* make room for line in history */ + for( ;; ) { + char *p; + n = strlen(ci->history) + 1; + + if( n + len + 1 <= ci->hsize ) + break; + + if( !(p=strrchr(ci->history,'\n')) ) + return 0; + *p = 0; + if( !(p=strrchr(ci->history, '\n')) ) + p = ci->history-1; + p[1] = 0; + } + + memmove( ci->history + len + 1, ci->history, n ); + memcpy( ci->history, str, len ); + ci->history[ len ] = '\n'; + return 1; +} + +static void /* ( -- ) */ +cmdline_prompt( cmdline_info_t *ci ) +{ + int cur_added=0, histind=0, ch, i, pos=0, n=0, prompt=1; + char *buf; + int terminate = 0; + + buf = ci->buf; + selfword("prepare"); + + emit('\n'); +#ifdef NOLEAVE + for (;;) +#else + while (rstackcnt && !terminate) +#endif + { + int drop = 0; + terminate = 0; + + if( prompt ) { + fword("print-prompt"); + buf[0] = 0; + cur_added = prompt = histind = pos = n = 0; + } + + ch = key(); + switch( ch ) { + case 27: + switch( key() ) { + case 'f': + while( buf[pos] == ' ' ) + emit( buf[pos++] ); + while( buf[pos] && buf[pos] != ' ' ) + emit( buf[pos++] ); + break; + + case 'b': + while( pos && buf[pos-1] == ' ' ) { + move_cursor( -1 ); + pos--; + } + while( pos && buf[pos-1] != ' ' ) { + move_cursor( -1 ); + pos--; + } + break; + case '[': + switch( key() ) { + case 'A': + goto go_up; + case 'B': + goto go_down; + case 'C': + goto go_right; + case 'D': + goto go_left; + case '3': + key(); + goto delete; + } + break; + case 'O': + switch(key()) { + case 'F': + goto go_end; + case 'H': + goto go_home; + } + break; + } + break; + case '\n': + case '\r': + if( cur_added ) + history_remove( ci, 0 ); + add_to_history( ci, ci->buf ); + + emit_str( &buf[pos] ); + emit(' '); + PUSH( feval(buf) ); + fword("print-status"); + + /* Leave the interpreter if terminate? value set */ + fword("terminate?"); + if (POP()) + terminate = 1; + + prompt = 1; + break; + + case 3: /* ^c */ + emit_str("\n"); + prompt = 1; + if( cur_added ) + history_remove( ci, 0 ); + break; + + case 4: /* ^d */ +delete: + if( pos == n ) + break; + emit( buf[pos++] ); + /* fall through */ + + case 8: /* ^h */ + case 127: /* backspace */ + drop = 1; + if( !pos ) + break; + move_cursor( -1 ); + emit_str( &buf[pos] ); + emit(' '); + memmove( &buf[pos-1], &buf[pos], n+1-pos ); + move_cursor( pos-n-1 ); + pos--; + n--; + break; + + case 1: /* ^a */ +go_home: + move_cursor( -pos ); + pos = 0; + break; + + case 5: /* ^e */ +go_end: + pos += emit_str( &buf[pos] ); + break; + + //case 68: /* left */ + // drop = 1; + case 2: /* ^b */ +go_left: + if( pos ) { + move_cursor( -1 ); + pos--; + } + break; + + //case 67: /* right */ + // drop = 1; + case 6: /* ^f */ +go_right: + if( pos < n ) + emit( buf[pos++] ); + break; + + case 11: /* ^k */ + strcpy( ci->killbuf, &buf[pos] ); + clear( n-pos ); + n = pos; + buf[pos] = 0; + break; + + case 25: /* ^y */ + for( i=0; n < ci->ncol && ci->killbuf[i] ; i++, n++ ) { + memmove( &buf[pos+1], &buf[pos], n+1-pos ); + buf[pos] = ci->killbuf[i]; + move_cursor( 1-emit_str(&buf[pos++]) ); + } + break; + + case 9: /* TAB */ + for( i=0; n < ci->ncol && (!i || (pos%4)) ; i++, n++ ) { + memmove( &buf[pos+1], &buf[pos], n+1-pos ); + buf[pos] = ' '; + move_cursor( 1-emit_str(&buf[pos++]) ); + } + break; + + case 12: /* ^l */ + move_cursor( -ci->ncol -pos ); + fword("print-prompt"); + move_cursor( pos-emit_str(buf) ); + break; + + //case 66: /* down */ + // drop = 1; + case 14: /* ^n */ +go_down: + if( !histind ) + break; + history_get( ci, --histind - 1); + clearline( pos, n ); + emit_str( buf ); + pos = n = strlen( buf ); + if( !histind && cur_added ) { + cur_added = 0; + history_remove( ci, 0 ); + } + break; + + //case 65: /* up */ + // drop = 1; + case 16: /* ^p */ +go_up: + if( !histind && add_to_history(ci, ci->buf) ) { + cur_added = 1; + histind++; + } + if( history_get(ci, histind) ) + histind++; + clearline( pos, n ); + emit_str( buf ); + pos = n = strlen( buf ); + break; + } + if( (unsigned int)ch < 32 ) + drop = 1; + + if( !drop && n < ci->ncol ) { + memmove( &buf[pos+1], &buf[pos], n+1-pos ); + n++; + buf[pos] = ch; + move_cursor( 1-emit_str(&buf[pos++]) ); + } + } + + /* we only get here if terminate? is non-zero; this should + * only ever be done for a subordinate forth interpreter + * e.g. for debugging */ + + /* Reset stack and terminate? */ + rstackcnt = dbgrstackcnt; + feval("0 to terminate?"); +} + +NODE_METHODS( cmdline ) = { + { "open", cmdline_open }, + { "close", cmdline_close }, + { "cmdline", cmdline_prompt }, +}; + +void +cmdline_init( void ) +{ + REGISTER_NODE( cmdline ); +} diff --git a/qemu/roms/openbios/packages/cmdline.fs b/qemu/roms/openbios/packages/cmdline.fs new file mode 100644 index 000000000..70d3aa2d5 --- /dev/null +++ b/qemu/roms/openbios/packages/cmdline.fs @@ -0,0 +1,41 @@ +\ tag: Utility functions +\ +\ deblocker / filesystem support +\ +\ Copyright (C) 2003, 2004 Samuel Rydh +\ +\ See the file "COPYING" for further information about +\ the copyright and warranty status of this work. +\ + +\ ------------------------------------------------------------- +\ command line editor (/packages/cmdline) +\ ------------------------------------------------------------- + +[IFDEF] CONFIG_CMDLINE + +dev /packages +new-device + " cmdline" device-name + + :noname + " " [active-package], open-package + ?dup if + " cmdline" rot $call-method + else + ." cmdline is missing!" cr + then + \ cmdline must close itself upon return + ; + + :noname + [ ['] (lit) , swap , ] to outer-interpreter + ; SYSTEM-initializer + + external + : prepare 0 to my-self ; + +finish-device + +[THEN] +device-end diff --git a/qemu/roms/openbios/packages/deblocker.c b/qemu/roms/openbios/packages/deblocker.c new file mode 100644 index 000000000..50071854c --- /dev/null +++ b/qemu/roms/openbios/packages/deblocker.c @@ -0,0 +1,221 @@ +/* + * Creation Date: <2003/12/03 21:20:58 samuel> + * Time-stamp: <2004/01/07 19:34:50 samuel> + * + * <deblocker.c> + * + * deblocker implementation + * + * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#include "config.h" +#include "libopenbios/bindings.h" +#include "libc/diskio.h" +#include "packages.h" + +typedef struct { + ucell mark_hi, mark_lo; + xt_t read_xt; + xt_t write_xt; + + int max_xfer; + int blksize; + char *buf; +} deblk_info_t; + +DECLARE_NODE( deblocker, 0, sizeof(deblk_info_t), "+/packages/deblocker" ); + +/* ( -- flag ) */ +static void +deblk_open( deblk_info_t *di ) +{ + xt_t xt; + + di->read_xt = find_parent_method("read-blocks"); + di->write_xt = find_parent_method("write-blocks"); + + if( !di->read_xt ) + RET(0); + + di->blksize = di->max_xfer = 512; + if( (xt=find_parent_method("block-size")) ) { + call_parent( xt ); + di->blksize = POP(); + } + if( (xt=find_parent_method("max-transfer")) ) { + call_parent( xt ); + di->max_xfer = POP(); + } + /* printk("block-size: %x max_xfer: %x read_xt %x write_xt %x\n", + di->blksize, di->max_xfer, di->write_xt, di->read_xt ); */ + + di->buf = malloc( di->blksize ); + PUSH(-1); +} + +/* ( -- ) */ +static void +deblk_close( deblk_info_t *di ) +{ + free( di->buf ); +} + +/* ( pos_lo pos_hi -- status ) */ +static void +deblk_seek( deblk_info_t *di ) +{ + ucell pos_hi = POP(); + ucell pos_lo = POP(); + ducell mark = ((ducell)pos_hi << BITS) | pos_lo; + + /* printk("deblk_seek %x %08x\n", pos_hi, pos_lo ); */ + + /* -1 means seek to EOF (at least in our implementation) */ + if( (dcell)mark == -1 ) + RET(-1); + di->mark_hi = pos_hi; + di->mark_lo = pos_lo; + + /* 0,1 == success, -1 == error */ + PUSH(0); +} + +/* ( -- mark.d ) */ +static void +deblk_tell( deblk_info_t *di ) +{ + PUSH( di->mark_lo ); + PUSH( di->mark_hi ); +} + + +#define DO_IO( xt, buf, blk, n ) \ + ({ PUSH3(pointer2cell(buf), blk, n); call_parent(xt); POP(); }) + +typedef struct { + /* block operation */ + char *blk_buf; + int nblks; + + /* byte operation */ + cell offs; + int len; + char *data; /* start of data */ +} work_t; + +static void +split( deblk_info_t *di, char *data, int len, work_t w[3] ) +{ + ducell mark = ((ducell)di->mark_hi << BITS) | di->mark_lo; + memset( w, 0, sizeof(work_t[3]) ); + + w[0].offs = mark % di->blksize; + w[0].blk_buf = di->buf; + w[0].data = data; + if( w[0].offs ) { + w[0].len = MIN( len, di->blksize - w[0].offs ); + w[0].nblks = w[0].len ? 1:0; + data += w[0].len; + len -= w[0].len; + } + + w[1].blk_buf = data; + w[1].nblks = (len / di->blksize); + w[1].len = w[1].nblks * di->blksize; + data += w[1].len; + len -= w[1].len; + + w[2].blk_buf = di->buf; + w[2].data = data; + w[2].len = len; + w[2].nblks = len ? 1:0; +} + +static int +do_readwrite( deblk_info_t *di, int is_write, xt_t xt ) +{ + int blk, i, n, len = POP(); + char *dest = (char*)cell2pointer(POP()); + int last=0, retlen=0; + work_t w[3]; + ducell mark = ((ducell)di->mark_hi << BITS) | di->mark_lo; + + /* printk("read: %x %x\n", (int)dest, len ); */ + + if( !xt ) + return -1; + + blk = mark / di->blksize; + split( di, dest, len, w ); + + for( i=0; !last && i<3; i++ ) { + if( !w[i].nblks ) + continue; + + if( is_write && i != 1 ) { + DO_IO( di->read_xt, w[i].blk_buf, blk, w[i].nblks ); + memcpy( w[i].blk_buf + w[i].offs, w[i].data, w[i].len ); + } + + n = DO_IO( xt, w[i].blk_buf, blk, w[i].nblks ); + if( n < 0 ) { + if( !retlen ) + retlen = -1; + break; + } + if( n != w[i].nblks ) { + w[i].len = MIN( n*di->blksize, w[i].len ); + last = 1; + } + if( !is_write && i != 1 ) + memcpy( w[i].data, w[i].blk_buf + w[i].offs, w[i].len ); + retlen += w[i].len; + blk += n; + } + if( retlen > 0 ) { + mark += retlen; + di->mark_hi = mark >> BITS; + di->mark_lo = mark & (ucell) -1; + } + return retlen; +} + +/* ( addr len -- actual ) */ +static void +deblk_read( deblk_info_t *di ) +{ + /* printk("deblk_read\n"); */ + int ret = do_readwrite( di, 0, di->read_xt ); + PUSH( ret ); +} + +/* ( buf len --- actlen ) */ +static void +deblk_write( deblk_info_t *di ) +{ + int ret = do_readwrite( di, 1, di->write_xt ); + PUSH( ret ); +} + +/* remember to fix is-deblocker if new methods are added */ +NODE_METHODS( deblocker ) = { + { "open", deblk_open }, + { "close", deblk_close }, + { "read", deblk_read }, + { "write", deblk_write }, + { "seek", deblk_seek }, + { "tell", deblk_tell }, +}; + + +void +deblocker_init( void ) +{ + REGISTER_NODE( deblocker ); +} diff --git a/qemu/roms/openbios/packages/disk-label.c b/qemu/roms/openbios/packages/disk-label.c new file mode 100644 index 000000000..1ca9bd867 --- /dev/null +++ b/qemu/roms/openbios/packages/disk-label.c @@ -0,0 +1,245 @@ +/* + * Creation Date: <2003/12/03 22:10:45 samuel> + * Time-stamp: <2004/01/07 19:17:45 samuel> + * + * <disk-label.c> + * + * Partition support + * + * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#include "config.h" +#include "libopenbios/bindings.h" +#include "libopenbios/load.h" +#include "libc/diskio.h" +#include "libc/vsprintf.h" +#include "packages.h" + +//#define DEBUG_DISK_LABEL + +#ifdef DEBUG_DISK_LABEL +#define DPRINTF(fmt, args...) \ +do { printk("DISK-LABEL - %s: " fmt, __func__ , ##args); } while (0) +#else +#define DPRINTF(fmt, args...) do { } while (0) +#endif + +typedef struct { + xt_t parent_seek_xt; + xt_t parent_tell_xt; + xt_t parent_read_xt; + + ucell offs_hi, offs_lo; + ucell size_hi, size_lo; + int block_size; + int type; /* partition type or -1 */ + + ihandle_t part_ih; + phandle_t filesystem_ph; +} dlabel_info_t; + +DECLARE_NODE( dlabel, 0, sizeof(dlabel_info_t), "/packages/disk-label" ); + + +/* ( -- ) */ +static void +dlabel_close( __attribute__((unused))dlabel_info_t *di ) +{ +} + +/* ( -- success? ) */ +static void +dlabel_open( dlabel_info_t *di ) +{ + char *path; + char block0[512]; + phandle_t ph; + int success=0; + cell status; + + path = my_args_copy(); + + DPRINTF("dlabel-open '%s'\n", path ); + + di->part_ih = 0; + + /* Find parent methods */ + di->filesystem_ph = 0; + di->parent_seek_xt = find_parent_method("seek"); + di->parent_tell_xt = find_parent_method("tell"); + di->parent_read_xt = find_parent_method("read"); + + /* If arguments have been passed, determine the partition/filesystem type */ + if (path && strlen(path)) { + + /* Read first block from parent device */ + DPUSH(0); + call_package(di->parent_seek_xt, my_parent()); + POP(); + + PUSH(pointer2cell(block0)); + PUSH(sizeof(block0)); + call_package(di->parent_read_xt, my_parent()); + status = POP(); + if (status != sizeof(block0)) + goto out; + + /* Find partition handler */ + PUSH( pointer2cell(block0) ); + selfword("find-part-handler"); + ph = POP_ph(); + if( ph ) { + /* We found a suitable partition handler, so interpose it */ + DPRINTF("Partition found on disk - scheduling interpose with ph " FMT_ucellx "\n", ph); + + push_str(path); + PUSH_ph(ph); + fword("interpose"); + + success = 1; + } else { + /* unknown (or missing) partition map, + * try the whole disk + */ + + DPRINTF("Unknown or missing partition map; trying whole disk\n"); + + /* Probe for filesystem from start of device */ + DPUSH ( 0 ); + PUSH_ih( my_self() ); + selfword("find-filesystem"); + ph = POP_ph(); + if( ph ) { + /* If we have been asked to open a particular file, interpose the filesystem package with the passed filename as an argument */ + di->filesystem_ph = ph; + + DPRINTF("Located filesystem with ph " FMT_ucellx "\n", ph); + DPRINTF("path: %s length: %d\n", path, strlen(path)); + + if (path && strlen(path)) { + DPRINTF("INTERPOSE!\n"); + + push_str( path ); + PUSH_ph( ph ); + fword("interpose"); + } + } else if (path && strcmp(path, "%BOOT") != 0) { + goto out; + } + + success = 1; + } + } else { + /* No arguments were passed, so we just use the parent raw device directly */ + success = 1; + } + +out: + if( path ) + free( path ); + if( !success ) { + dlabel_close( di ); + RET(0); + } + PUSH(-1); +} + +/* ( addr len -- actual ) */ +static void +dlabel_read( dlabel_info_t *di ) +{ + /* Call back up to parent */ + call_package(di->parent_read_xt, my_parent()); +} + +/* ( pos.d -- status ) */ +static void +dlabel_seek( dlabel_info_t *di ) +{ + /* Call back up to parent */ + call_package(di->parent_seek_xt, my_parent()); +} + +/* ( -- filepos.d ) */ +static void +dlabel_tell( dlabel_info_t *di ) +{ + /* Call back up to parent */ + call_package(di->parent_tell_xt, my_parent()); +} + +/* ( addr len -- actual ) */ +static void +dlabel_write( __attribute__((unused)) dlabel_info_t *di ) +{ + DDROP(); + PUSH( -1 ); +} + +/* ( addr -- size ) */ +static void +dlabel_load( __attribute__((unused)) dlabel_info_t *di ) +{ + /* Try the load method of the part package */ + xt_t xt; + + /* If we have a partition handle, invoke the load word on it */ + if (di->part_ih) { + xt = find_ih_method("load", di->part_ih); + if (!xt) { + forth_printf("load currently not implemented for ihandle " FMT_ucellx "\n", di->part_ih); + PUSH(0); + return; + } + + DPRINTF("calling load on ihandle " FMT_ucellx "\n", di->part_ih); + + call_package(xt, di->part_ih); + } else { + /* Otherwise attempt load directly on the raw disk */ + DPRINTF("calling load on raw disk ihandle " FMT_ucellx "\n", my_self()); + + load(my_self()); + } +} + +/* ( pathstr len -- ) */ +static void +dlabel_dir( dlabel_info_t *di ) +{ + if ( di->filesystem_ph ) { + PUSH( my_self() ); + push_str("dir"); + PUSH( di->filesystem_ph ); + fword("find-method"); + POP(); + fword("execute"); + } else { + forth_printf("disk-label: Unable to determine filesystem\n"); + POP(); + POP(); + } +} + +NODE_METHODS( dlabel ) = { + { "open", dlabel_open }, + { "close", dlabel_close }, + { "load", dlabel_load }, + { "read", dlabel_read }, + { "write", dlabel_write }, + { "seek", dlabel_seek }, + { "tell", dlabel_tell }, + { "dir", dlabel_dir }, +}; + +void +disklabel_init( void ) +{ + REGISTER_NODE( dlabel ); +} diff --git a/qemu/roms/openbios/packages/disk-label.fs b/qemu/roms/openbios/packages/disk-label.fs new file mode 100644 index 000000000..8354f878e --- /dev/null +++ b/qemu/roms/openbios/packages/disk-label.fs @@ -0,0 +1,102 @@ +\ tag: Utility functions +\ +\ deblocker / filesystem support +\ +\ Copyright (C) 2003, 2004 Samuel Rydh +\ +\ See the file "COPYING" for further information about +\ the copyright and warranty status of this work. +\ + +dev /packages + +\ ------------------------------------------------------------- +\ /packages/disk-label (partition handling) +\ ------------------------------------------------------------- + +[IFDEF] CONFIG_DISK_LABEL + +new-device + " disk-label" device-name + external + + variable part-handlers \ list with (probe-xt, phandle) elements + variable fs-handlers \ list with (fs-probe-xt, phandle) elements + + : find-part-handler ( block0 -- phandle | 0 ) + >r part-handlers + begin list-get while + ( nextlist dictptr ) + r@ over @ execute if + ( nextlist dictptr ) + na1+ @ r> rot 2drop exit + then + drop + repeat + r> drop 0 + ; + + : find-filesystem ( offs.d ih -- ph | 0 ) + >r fs-handlers ( offs.d listhead ) + begin list-get while + 2over ( offs.d nextlist dictptr offs.d ) + r@ ( offs.d nextlist dictptr offs.d ih ) + 3 pick ( offs.d nextlist dictptr offs.d ih dictptr ) + @ ( offs.d nextlist dictptr offs.d ih probe-xt ) + execute ( offs.d nextlist dictptr flag? ) + if + ( offs.d nextlist dictptr ) + na1+ ( offs.d nextlist dictptr+1 ) + @ ( offs.d nextlist phandle ) + r> ( offs.d nextlist phandle ih ) + rot ( offs.d phandle ih nextlist ) + 2drop ( offs.d phandle ) + -rot ( phandle offs.d ) + 2drop ( phandle ) + exit + then + drop ( offs.d nextlist ) + repeat + 2drop ( offs.d ) + r> drop 0 + ; + + + : register-part-handler ( handler-ph -- ) + dup " probe" rot find-method + 0= abort" Missing probe method!" + ( phandle probe-xt ) + part-handlers list-add , , + ; + + : register-fs-handler ( handler-ph -- ) + dup " probe" rot find-method + 0= abort" Missing probe method!" + ( phandle probe-xt ) + fs-handlers list-add , , + ; +finish-device + +\ --------------------------------------------------------------------------- +\ methods to register partion and filesystem packages used by disk-label +\ --------------------------------------------------------------------------- + +device-end +: register-partition-package ( -- ) + " register-part-handler" " disk-label" $find-package-method ?dup if + active-package swap execute + else + ." [disk-label] internal error" cr + then +; + +: register-fs-package ( -- ) + " register-fs-handler" " disk-label" $find-package-method ?dup if + active-package swap execute + else + ." [misc-files] internal error" cr + then +; + +[THEN] +device-end diff --git a/qemu/roms/openbios/packages/elf-loader.c b/qemu/roms/openbios/packages/elf-loader.c new file mode 100644 index 000000000..1665f0d0b --- /dev/null +++ b/qemu/roms/openbios/packages/elf-loader.c @@ -0,0 +1,31 @@ +/* + * + * <elf-loader.c> + * + * ELF file loader + * + * Copyright (C) 2009 Laurent Vivier (Laurent@vivier.eu) + * + * Some parts Copyright (C) 2002, 2003, 2004 Samuel Rydh (samuel@ibrium.se) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#include "config.h" +#include "libopenbios/bindings.h" +#include "libopenbios/elf_load.h" +#include "packages.h" + +DECLARE_NODE(elf_loader, INSTALL_OPEN, 0, "+/packages/elf-loader" ); + +NODE_METHODS( elf_loader ) = { + { "init-program", elf_init_program }, +}; + +void elf_loader_init( void ) +{ + REGISTER_NODE( elf_loader ); +} diff --git a/qemu/roms/openbios/packages/init.c b/qemu/roms/openbios/packages/init.c new file mode 100644 index 000000000..bff8558ab --- /dev/null +++ b/qemu/roms/openbios/packages/init.c @@ -0,0 +1,67 @@ +/* + * Creation Date: <2003/12/23 00:28:05 samuel> + * Time-stamp: <2003/12/28 19:43:41 samuel> + * + * <init.c> + * + * Module intialization + * + * Copyright (C) 2003 Samuel Rydh (samuel@ibrium.se) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#include "config.h" +#include "kernel/kernel.h" +#include "packages.h" + +void +modules_init( void ) +{ +#ifdef CONFIG_CMDLINE + cmdline_init(); +#endif +#ifdef CONFIG_DEBLOCKER + deblocker_init(); +#endif +#ifdef CONFIG_DISK_LABEL + disklabel_init(); +#endif +#ifdef CONFIG_HFSP + hfsp_init(); +#endif +#ifdef CONFIG_HFS + hfs_init(); +#endif +#ifdef CONFIG_EXT2 + ext2_init(); +#endif +#ifdef CONFIG_ISO9660 + iso9660_init(); +#endif +#ifdef CONFIG_GRUBFS + grubfs_init(); +#endif +#ifdef CONFIG_MAC_PARTS + macparts_init(); +#endif +#ifdef CONFIG_PC_PARTS + pcparts_init(); +#endif +#ifdef CONFIG_SUN_PARTS + sunparts_init(); +#endif +#ifdef CONFIG_LOADER_XCOFF + xcoff_loader_init(); +#endif +#ifdef CONFIG_LOADER_ELF + elf_loader_init(); +#endif +#ifdef CONFIG_LOADER_BOOTINFO + bootinfo_loader_init(); +#endif + +} diff --git a/qemu/roms/openbios/packages/mac-parts.c b/qemu/roms/openbios/packages/mac-parts.c new file mode 100644 index 000000000..16c87caf8 --- /dev/null +++ b/qemu/roms/openbios/packages/mac-parts.c @@ -0,0 +1,447 @@ +/* + * Creation Date: <2003/12/04 17:07:05 samuel> + * Time-stamp: <2004/01/07 19:36:09 samuel> + * + * <mac-parts.c> + * + * macintosh partition support + * + * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#include "config.h" +#include "libopenbios/bindings.h" +#include "libopenbios/load.h" +#include "mac-parts.h" +#include "libc/byteorder.h" +#include "libc/vsprintf.h" +#include "packages.h" + +//#define CONFIG_DEBUG_MAC_PARTS + +#ifdef CONFIG_DEBUG_MAC_PARTS +#define DPRINTF(fmt, args...) \ +do { printk("MAC-PARTS: " fmt , ##args); } while (0) +#else +#define DPRINTF(fmt, args...) do {} while(0) +#endif + +typedef struct { + xt_t seek_xt, read_xt; + ucell offs_hi, offs_lo; + ucell size_hi, size_lo; + ucell bootcode_addr, bootcode_entry; + unsigned int blocksize; + phandle_t filesystem_ph; +} macparts_info_t; + +DECLARE_NODE( macparts, INSTALL_OPEN, sizeof(macparts_info_t), "+/packages/mac-parts" ); + +#define SEEK( pos ) ({ DPUSH(pos); call_parent(di->seek_xt); POP(); }) +#define READ( buf, size ) ({ PUSH(pointer2cell(buf)); PUSH(size); call_parent(di->read_xt); POP(); }) + +/* ( open -- flag ) */ +static void +macparts_open( macparts_info_t *di ) +{ + char *str = my_args_copy(); + char *parstr = NULL, *argstr = NULL; + char *tmpstr; + int bs, parnum=-1, apple_parnum=-1; + int parlist[2], parlist_size = 0; + desc_map_t dmap; + part_entry_t par; + int ret = 0, i = 0, j = 0; + int want_bootcode = 0; + phandle_t ph; + ducell offs = 0, size = -1; + + DPRINTF("macparts_open '%s'\n", str ); + + /* + Arguments that we accept: + id: [0-7] + [(id)][,][filespec] + */ + + if ( str && strlen(str) ) { + /* Detect the arguments */ + if ((*str >= '0' && *str <= '9') || (*str == ',')) { + push_str(str); + PUSH(','); + fword("left-parse-string"); + parstr = pop_fstr_copy(); + argstr = pop_fstr_copy(); + } else { + argstr = str; + } + + /* Make sure argstr is not null */ + if (argstr == NULL) + argstr = strdup(""); + + /* Convert the id to a partition number */ + if (parstr && strlen(parstr)) + parnum = atol(parstr); + + /* Detect if we are looking for the bootcode */ + if (strcmp(argstr, "%BOOT") == 0) { + want_bootcode = 1; + } + } + + DPRINTF("parstr: %s argstr: %s parnum: %d\n", parstr, argstr, parnum); + + DPRINTF("want_bootcode %d\n", want_bootcode); + DPRINTF("macparts_open %d\n", parnum); + + di->filesystem_ph = 0; + di->read_xt = find_parent_method("read"); + di->seek_xt = find_parent_method("seek"); + + SEEK( 0 ); + if( READ(&dmap, sizeof(dmap)) != sizeof(dmap) ) + goto out; + + /* partition maps might support multiple block sizes; in this case, + * pmPyPartStart is typically given in terms of 512 byte blocks. + */ + bs = __be16_to_cpu(dmap.sbBlockSize); + if( bs != 512 ) { + SEEK( 512 ); + READ( &par, sizeof(par) ); + if( __be16_to_cpu(par.pmSig) == DESC_PART_SIGNATURE ) + bs = 512; + } + SEEK( bs ); + if( READ(&par, sizeof(par)) != sizeof(par) ) + goto out; + if (__be16_to_cpu(par.pmSig) != DESC_PART_SIGNATURE) + goto out; + + /* + * Implement partition selection as per the PowerPC Microprocessor CHRP bindings + */ + + if (argstr == NULL || parnum == 0) { + /* According to the spec, partition 0 as well as no arguments means the whole disk */ + offs = (long long)0; + size = (long long)__be32_to_cpu(dmap.sbBlkCount) * bs; + + di->blocksize = (unsigned int)bs; + + di->offs_hi = offs >> BITS; + di->offs_lo = offs & (ucell) -1; + + di->size_hi = size >> BITS; + di->size_lo = size & (ucell) -1; + + ret = -1; + goto out; + + } else if (parnum == -1) { + + DPRINTF("mac-parts: counted %d partitions\n", __be32_to_cpu(par.pmMapBlkCnt)); + + /* No partition was explicitly requested so let's find a suitable partition... */ + for (i = 1; i <= __be32_to_cpu(par.pmMapBlkCnt); i++) { + SEEK( bs * i ); + READ( &par, sizeof(par) ); + if ( __be16_to_cpu(par.pmSig) != DESC_PART_SIGNATURE || + !__be32_to_cpu(par.pmPartBlkCnt) ) + continue; + + DPRINTF("found partition %d type: %s with status %x\n", i, par.pmPartType, __be32_to_cpu(par.pmPartStatus)); + + /* If we have a valid, allocated and readable partition... */ + if( (__be32_to_cpu(par.pmPartStatus) & kPartitionAUXIsValid) && + (__be32_to_cpu(par.pmPartStatus) & kPartitionAUXIsAllocated) && + (__be32_to_cpu(par.pmPartStatus) & kPartitionAUXIsReadable) ) { + + /* Unfortunately Apple's OF implementation doesn't follow the OF PowerPC CHRP bindings + * and instead will brute-force boot the first valid partition it finds with a + * type of either "Apple_Boot", "Apple_HFS" or "DOS_FAT_". Here we store the id + * of the first partition that matches these criteria to use as a fallback later + * if required. */ + + if (apple_parnum == -1 && + (strcmp(par.pmPartType, "Apple_Boot") == 0 || + strcmp(par.pmPartType, "Apple_Bootstrap") == 0 || + strcmp(par.pmPartType, "Apple_HFS") == 0 || + strcmp(par.pmPartType, "DOS_FAT_") == 0)) { + apple_parnum = i; + + DPRINTF("Located Apple OF fallback partition %d\n", apple_parnum); + } + + /* If the partition is also bootable and the pmProcessor field matches "PowerPC" (insensitive + * match), then according to the CHRP bindings this is our chosen partition */ + for (j = 0; j < strlen(par.pmProcessor); j++) { + par.pmProcessor[j] = tolower(par.pmProcessor[j]); + } + + if ((__be32_to_cpu(par.pmPartStatus) & kPartitionAUXIsBootValid) && + strcmp(par.pmProcessor, "powerpc") == 0) { + parnum = i; + + DPRINTF("Located CHRP-compliant boot partition %d\n", parnum); + } + } + } + + /* If we found a valid CHRP partition, add it to the list */ + if (parnum > 0) { + parlist[parlist_size++] = parnum; + } + + /* If we found an Apple OF fallback partition, add it to the list */ + if (apple_parnum > 0 && apple_parnum != parnum) { + parlist[parlist_size++] = apple_parnum; + } + + } else { + /* Another partition was explicitly requested */ + parlist[parlist_size++] = parnum; + + DPRINTF("Partition %d explicitly requested\n", parnum); + } + + /* Attempt to use our CHRP partition, optionally followed by our Apple OF fallback partition */ + for (j = 0; j < parlist_size; j++) { + + /* Make sure our partition is valid */ + parnum = parlist[j]; + + DPRINTF("Selected partition %d\n", parnum); + + SEEK( bs * parnum ); + READ( &par, sizeof(par) ); + + if(! ((__be32_to_cpu(par.pmPartStatus) & kPartitionAUXIsValid) && + (__be32_to_cpu(par.pmPartStatus) & kPartitionAUXIsAllocated) && + (__be32_to_cpu(par.pmPartStatus) & kPartitionAUXIsReadable)) ) { + DPRINTF("Partition %d is not valid, allocated and readable\n", parnum); + goto out; + } + + ret = -1; + + offs = (long long)__be32_to_cpu(par.pmPyPartStart) * bs; + size = (long long)__be32_to_cpu(par.pmPartBlkCnt) * bs; + + if (want_bootcode) { + + /* If size == 0 then fail because we requested bootcode but it doesn't exist */ + size = (long long)__be32_to_cpu(par.pmBootSize); + if (!size) { + ret = 0; + goto out; + } + + /* Adjust seek position so 0 = start of bootcode */ + offs += (long long)__be32_to_cpu(par.pmLgBootStart) * bs; + + di->bootcode_addr = __be32_to_cpu(par.pmBootLoad); + di->bootcode_entry = __be32_to_cpu(par.pmBootEntry); + } + + di->blocksize = (unsigned int)bs; + + di->offs_hi = offs >> BITS; + di->offs_lo = offs & (ucell) -1; + + di->size_hi = size >> BITS; + di->size_lo = size & (ucell) -1; + + /* If we're trying to execute bootcode then we're all done */ + if (want_bootcode) { + goto out; + } + + /* We have a valid partition - so probe for a filesystem at the current offset */ + DPRINTF("mac-parts: about to probe for fs\n"); + DPUSH( offs ); + PUSH_ih( my_parent() ); + parword("find-filesystem"); + DPRINTF("mac-parts: done fs probe\n"); + + ph = POP_ph(); + if( ph ) { + DPRINTF("mac-parts: filesystem found on partition %d with ph " FMT_ucellx " and args %s\n", parnum, ph, argstr); + di->filesystem_ph = ph; + + /* In case no partition was specified, set a special selected-partition-args property + giving the device parameters that we can use to generate bootpath */ + tmpstr = malloc(strlen(argstr) + 2 + 1); + if (strlen(argstr)) { + sprintf(tmpstr, "%d,%s", parnum, argstr); + } else { + sprintf(tmpstr, "%d", parnum); + } + + push_str(tmpstr); + feval("strdup encode-string \" selected-partition-args\" property"); + + free(tmpstr); + + /* If we have been asked to open a particular file, interpose the filesystem package with + the passed filename as an argument */ + if (strlen(argstr)) { + push_str( argstr ); + PUSH_ph( ph ); + fword("interpose"); + } + + goto out; + } else { + DPRINTF("mac-parts: no filesystem found on partition %d; bypassing misc-files interpose\n", parnum); + + /* Here we have a valid partition; however if we tried to pass in a file argument for a + partition that doesn't contain a filesystem, then we must fail */ + if (strlen(argstr)) { + ret = 0; + } + } + } + + free( str ); + +out: + PUSH( ret ); +} + +/* ( block0 -- flag? ) */ +static void +macparts_probe( macparts_info_t *dummy ) +{ + desc_map_t *dmap = (desc_map_t*)cell2pointer(POP()); + + DPRINTF("macparts_probe %x ?= %x\n", dmap->sbSig, DESC_MAP_SIGNATURE); + if( __be16_to_cpu(dmap->sbSig) != DESC_MAP_SIGNATURE ) + RET(0); + RET(-1); +} + +/* ( -- type offset.d size.d ) */ +static void +macparts_get_info( macparts_info_t *di ) +{ + DPRINTF("macparts_get_info"); + + PUSH( -1 ); /* no type */ + PUSH( di->offs_lo ); + PUSH( di->offs_hi ); + PUSH( di->size_lo ); + PUSH( di->size_hi ); +} + +/* ( -- size entry addr ) */ +static void +macparts_get_bootcode_info( macparts_info_t *di ) +{ + DPRINTF("macparts_get_bootcode_info"); + + PUSH( di->size_lo ); + PUSH( di->bootcode_entry ); + PUSH( di->bootcode_addr ); +} + +static void +macparts_block_size( macparts_info_t *di ) +{ + DPRINTF("macparts_block_size = %x\n", di->blocksize); + PUSH(di->blocksize); +} + +static void +macparts_initialize( macparts_info_t *di ) +{ + fword("register-partition-package"); +} + +/* ( pos.d -- status ) */ +static void +macparts_seek(macparts_info_t *di ) +{ + long long pos = DPOP(); + long long offs, size; + + DPRINTF("macparts_seek %llx:\n", pos); + + /* Seek is invalid if we reach the end of the device */ + size = ((ducell)di->size_hi << BITS) | di->size_lo; + if (pos > size) + RET( -1 ); + + /* Calculate the seek offset for the parent */ + offs = ((ducell)di->offs_hi << BITS) | di->offs_lo; + offs += pos; + DPUSH(offs); + + DPRINTF("macparts_seek parent offset %llx:\n", offs); + + call_package(di->seek_xt, my_parent()); +} + +/* ( buf len -- actlen ) */ +static void +macparts_read(macparts_info_t *di ) +{ + DPRINTF("macparts_read\n"); + + /* Pass the read back up to the parent */ + call_package(di->read_xt, my_parent()); +} + +/* ( addr -- size ) */ +static void +macparts_load( __attribute__((unused))macparts_info_t *di ) +{ + /* Invoke the loader */ + load(my_self()); +} + +/* ( pathstr len -- ) */ +static void +macparts_dir( macparts_info_t *di ) +{ + /* On PPC Mac, the first partition chosen according to the CHRP boot + specification (i.e. marked as bootable) may not necessarily contain + a valid FS */ + if ( di->filesystem_ph ) { + PUSH( my_self() ); + push_str("dir"); + PUSH( di->filesystem_ph ); + fword("find-method"); + POP(); + fword("execute"); + } else { + forth_printf("mac-parts: Unable to determine filesystem\n"); + POP(); + POP(); + } +} + +NODE_METHODS( macparts ) = { + { "probe", macparts_probe }, + { "open", macparts_open }, + { "seek", macparts_seek }, + { "read", macparts_read }, + { "load", macparts_load }, + { "dir", macparts_dir }, + { "get-info", macparts_get_info }, + { "get-bootcode-info", macparts_get_bootcode_info }, + { "block-size", macparts_block_size }, + { NULL, macparts_initialize }, +}; + +void +macparts_init( void ) +{ + REGISTER_NODE( macparts ); +} diff --git a/qemu/roms/openbios/packages/mac-parts.h b/qemu/roms/openbios/packages/mac-parts.h new file mode 100644 index 000000000..acfcbe04b --- /dev/null +++ b/qemu/roms/openbios/packages/mac-parts.h @@ -0,0 +1,88 @@ +/* + * Creation Date: <1999/07/06 15:45:12 samuel> + * Time-stamp: <2002/10/20 16:31:48 samuel> + * + * <partition_table.h> + * + * Headers describing the partition table + * + * Copyright (C) 1999, 2002 Samuel Rydh (samuel@ibrium.se) + * + * 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 + * + */ + +#ifndef _H_PARTITION_TABLE +#define _H_PARTITION_TABLE + +/* This information is based upon IM vol V. */ + +#define DESC_MAP_SIGNATURE 0x4552 +#define DESC_PART_SIGNATURE 0x504d + +enum { + kPartitionAUXIsValid = 0x00000001, + kPartitionAUXIsAllocated = 0x00000002, + kPartitionAUXIsInUse = 0x00000004, + kPartitionAUXIsBootValid = 0x00000008, + kPartitionAUXIsReadable = 0x00000010, + kPartitionAUXIsWriteable = 0x00000020, + kPartitionAUXIsBootCodePositionIndependent = 0x00000040, + kPartitionISMountedAtStartup = 0x40000000, + kPartitionIsStartup = 0x80000000, + kPartitionIsChainCompatible = 0x00000100, + kPartitionIsRealDeviceDriver = 0x00000200, + kPartitionCanChainToNext = 0x00000400, +}; + +typedef struct { + u32 ddBlock; /* first block of driver */ + u16 ddSize; /* driver size in blocks */ + s16 ddType; /* 1 & -1 for SCSI */ +} driver_entry_t; + +typedef struct { /* Block 0 of a device */ + u16 sbSig; /* always 0x4552 */ + u16 sbBlockSize; /* 512 */ + s32 sbBlkCount; /* #blocks on device */ + u16 sbDevType; /* 0 */ + u16 sbDevID; /* 0 */ + u32 sbData; /* 0 */ + s16 sbDrvrCount; /* #driver descriptors */ + + /* driver entries goes here */ + driver_entry_t drivers[61] __attribute__ ((packed)); + + u16 filler1; + u32 filler2; +} desc_map_t; + +typedef struct { /* Partition descriptor */ + u16 pmSig; /* always 0x504d 'PM' */ + u16 pmSigPad; /* 0 */ + u32 pmMapBlkCnt; /* #blocks in partition map */ + u32 pmPyPartStart; /* first physical block of part. */ + u32 pmPartBlkCnt; /* #blocks in partition */ + char pmPartName[32]; /* partition name */ + char pmPartType[32]; /* partition type */ + + /* these fields may or may not be used */ + u32 pmLgDataStart; + u32 pmDataCnt; + u32 pmPartStatus; + u32 pmLgBootStart; + u32 pmBootSize; + u32 pmBootLoad; + u32 pmBootLoad2; + u32 pmBootEntry; + u32 pmBootEntry2; + u32 pmBootCksum; + char pmProcessor[16]; + + char filler[376]; /* might contain extra information */ +} part_entry_t; + + +#endif /* _H_PARTITION_TABLE */ diff --git a/qemu/roms/openbios/packages/molvideo.c b/qemu/roms/openbios/packages/molvideo.c new file mode 100644 index 000000000..787c4dc08 --- /dev/null +++ b/qemu/roms/openbios/packages/molvideo.c @@ -0,0 +1,124 @@ +/* + * Creation Date: <2002/10/23 20:26:40 samuel> + * Time-stamp: <2004/01/07 19:39:15 samuel> + * + * <molvideo.c> + * + * Mac-on-Linux display node + * + * Copyright (C) 2002, 2003, 2004 Samuel Rydh (samuel@ibrium.se) + * + * 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 + * + */ + +#include "config.h" +#include "libopenbios/bindings.h" +#include "libc/diskio.h" +#include "libopenbios/ofmem.h" +#include "drivers/drivers.h" +#include "packages/video.h" +#include "libopenbios/video.h" +#include "drivers/vga.h" + + +/************************************************************************/ +/* OF methods */ +/************************************************************************/ + +DECLARE_NODE( video, 0, 0, "Tdisplay" ); + +/* ( r g b index -- ) */ +static void +molvideo_color_bang( void ) +{ + int index = POP(); + int b = POP(); + int g = POP(); + int r = POP(); + unsigned long col = ((r << 16) & 0xff0000) | ((g << 8) & 0x00ff00) | (b & 0xff); + /* printk("color!: %08lx %08lx %08lx %08lx\n", r, g, b, index ); */ + + if( VIDEO_DICT_VALUE(video.depth) == 8 ) { + OSI_SetColor( index, col ); + OSI_RefreshPalette(); + } +} + +/* ( -- ) - really should be reworked as draw-logo */ +static void +molvideo_startup_splash( void ) +{ + int fd, s, i, y, x, dx, dy; + int width, height; + char *pp, *p; + char buf[64]; + + /* only draw logo in 24-bit mode (for now) */ + if( VIDEO_DICT_VALUE(video.depth) < 15 ) + return; + + for( i=0; i<2; i++ ) { + if( !BootHGetStrResInd("bootlogo", buf, sizeof(buf), 0, i) ) + return; + *(!i ? &width : &height) = atol(buf); + } + + if( (s=width * height * 3) > 0x20000 ) + return; + + if( (fd=open_io("pseudo:,bootlogo")) >= 0 ) { + p = malloc( s ); + if( read_io(fd, p, s) != s ) + printk("bootlogo size error\n"); + close_io( fd ); + + dx = (VIDEO_DICT_VALUE(video.w) - width)/2; + dy = (VIDEO_DICT_VALUE(video.h) - height)/3; + + pp = (char*)VIDEO_DICT_VALUE(video.mvirt) + dy * VIDEO_DICT_VALUE(video.rb) + dx * (VIDEO_DICT_VALUE(video.depth) >= 24 ? 4 : 2); + + for( y=0 ; y<height; y++, pp += VIDEO_DICT_VALUE(video.rb) ) { + if( VIDEO_DICT_VALUE(video.depth) >= 24 ) { + unsigned long *d = (unsigned long*)pp; + for( x=0; x<width; x++, p+=3, d++ ) + *d = ((int)p[0] << 16) | ((int)p[1] << 8) | p[2]; + } else if( VIDEO_DICT_VALUE(video.depth) == 15 ) { + unsigned short *d = (unsigned short*)pp; + for( x=0; x<width; x++, p+=3, d++ ) { + int col = ((int)p[0] << 16) | ((int)p[1] << 8) | p[2]; + *d = ((col>>9) & 0x7c00) | ((col>>6) & 0x03e0) | ((col>>3) & 0x1f); + } + } + } + free( p ); + } + + /* No bootlogo support yet on other platforms */ + return; +} + + +NODE_METHODS( video ) = { + {"mol-startup-splash", molvideo_startup_splash }, +}; + + +/************************************************************************/ +/* init */ +/************************************************************************/ + +void +molvideo_init(void) +{ + xt_t color_bang; + + REGISTER_NODE( video ); + + /* Bind the MOL graphic routines to the mol-color! defer */ + color_bang = bind_noname_func(molvideo_color_bang); + PUSH(color_bang); + feval(" to mol-color!"); +} diff --git a/qemu/roms/openbios/packages/nvram.c b/qemu/roms/openbios/packages/nvram.c new file mode 100644 index 000000000..3182edf58 --- /dev/null +++ b/qemu/roms/openbios/packages/nvram.c @@ -0,0 +1,308 @@ +/* + * Creation Date: <2003/12/01 00:26:13 samuel> + * Time-stamp: <2004/01/07 19:59:53 samuel> + * + * <nvram.c> + * + * medium-level NVRAM handling + * + * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#include "config.h" +#include "libopenbios/bindings.h" +#include "arch/common/nvram.h" +#include "packages/nvram.h" + +//#define CONFIG_DEBUG_NVRAM 1 + +#ifdef CONFIG_DEBUG_NVRAM +#define DPRINTF(fmt, args...) \ +do { printk("NVRAM: " fmt , ##args); } while (0) +#else +#define DPRINTF(fmt, args...) do {} while(0) +#endif + +#define DEF_SYSTEM_SIZE 0xc10 + +#define NV_SIG_SYSTEM 0x70 +#define NV_SIG_FREE 0x7f + + +typedef struct { + unsigned char signature; + unsigned char checksum; + unsigned char len_hi; + unsigned char len_lo; + char name[12]; + char data[0]; +} nvpart_t; + +static struct { + char *data; + int size; + + nvpart_t *config; + int config_size; +} nvram; + + +/************************************************************************/ +/* generic */ +/************************************************************************/ + +static unsigned int +nvpart_checksum( nvpart_t* hdr ) +{ + unsigned char *p = (unsigned char*)hdr; + int i, val = p[0]; + + for( i=2; i<16; i++ ) { + val += p[i]; + if( val > 255 ) + val = (val - 256 + 1) & 0xff; + } + return val; +} + +static inline int +nvpart_size( nvpart_t *p ) +{ + return (p->len_lo | ((int)p->len_hi<<8)) * 16; +} + +static int +next_nvpart( nvpart_t **p ) +{ + nvpart_t *end = (nvpart_t*)(nvram.data + nvram.size); + int len; + + if( !*p ) { + *p = (nvpart_t*)nvram.data; + return 1; + } + + if( !(len=nvpart_size(*p)) ) { + printk("invalid nvram partition length\n"); + return -1; + } + *p = (nvpart_t*)((char*)*p + len); + if( *p < end ) + return 1; + if( *p == end ) + return 0; + return -1; +} + +static void +create_free_part( char *ptr, int size ) +{ + nvpart_t *nvp = (nvpart_t*)ptr; + memset( nvp, 0, size ); + + strncpy( nvp->name, "777777777777", sizeof(nvp->name) ); + nvp->signature = NV_SIG_FREE; + nvp->len_hi = (size /16) >> 8; + nvp->len_lo = size /16; + nvp->checksum = nvpart_checksum(nvp); +} + +static int +create_nv_part( int signature, const char *name, int size ) +{ + nvpart_t *p = NULL; + int fs; + + while( next_nvpart(&p) > 0 ) { + if( p->signature != NV_SIG_FREE ) + continue; + + fs = nvpart_size( p ); + if( fs < size ) + size = fs; + p->signature = signature; + memset( p->name, 0, sizeof(p->name) ); + strncpy( p->name, name, sizeof(p->name) ); + p->len_hi = (size>>8)/16; + p->len_lo = size/16; + p->checksum = nvpart_checksum(p); + if( fs > size ) { + char *fp = (char*)p + size; + create_free_part( fp, fs-size ); + } + return size; + } + printk("create-failed\n"); + return -1; +} + +static void +zap_nvram( void ) +{ + create_free_part( nvram.data, nvram.size ); + create_nv_part( NV_SIG_SYSTEM, "common", DEF_SYSTEM_SIZE ); +} + +#if 0 +static void +show_partitions( void ) +{ + nvpart_t *p = NULL; + char buf[13]; + + while( next_nvpart(&p) > 0 ) { + memcpy( buf, p->name, sizeof(p->name) ); + buf[12] = 0; + printk("[%02x] %-13s: %03x\n", + p->signature, buf, nvpart_size(p)); + } +} +#endif + +void +update_nvram( void ) +{ + PUSH( pointer2cell(nvram.config->data) ); + PUSH( nvram.config_size ); + fword("nvram-store-configs"); + arch_nvram_put( nvram.data ); +} + +void +nvconf_init( void ) +{ + int once=0; + + /* initialize nvram structure completely */ + nvram.config = NULL; + nvram.config_size = 0; + + nvram.size = arch_nvram_size(); + nvram.data = malloc( nvram.size ); + arch_nvram_get( nvram.data ); + + bind_func( "update-nvram", update_nvram ); + + for( ;; ) { + nvpart_t *p = NULL; + int err; + + while( (err=next_nvpart(&p)) > 0 ) { + if( nvpart_checksum(p) != p->checksum ) { + err = -1; + break; + } + if( p->signature == NV_SIG_SYSTEM ) { + nvram.config = p; + nvram.config_size = nvpart_size(p) - 0x10; + + if( !once++ ) { + PUSH( pointer2cell(p->data) ); + PUSH( nvram.config_size ); + fword("nvram-load-configs"); + } + } + } + if( err || !nvram.config ) { + printk("nvram error detected, zapping pram\n"); + zap_nvram(); + if( !once++ ) + fword("set-defaults"); + continue; + } + break; + } +} + + +/************************************************************************/ +/* nvram */ +/************************************************************************/ + +typedef struct { + unsigned int mark_hi; + unsigned int mark_lo; +} nvram_ibuf_t; + +DECLARE_UNNAMED_NODE( nvram, INSTALL_OPEN, sizeof(nvram_ibuf_t )); + +/* ( pos_lo pos_hi -- status ) */ +static void +nvram_seek( nvram_ibuf_t *nd ) +{ + int pos_hi = POP(); + int pos_lo = POP(); + + DPRINTF("seek %08x %08x\n", pos_hi, pos_lo ); + nd->mark_lo = pos_lo; + nd->mark_hi = pos_hi; + + if( nd->mark_lo >= nvram.size ) { + PUSH(-1); + return; + } + + /* 0=success, -1=failure (1=legacy success) */ + PUSH(0); +} + +/* ( addr len -- actual ) */ +static void +nvram_read( nvram_ibuf_t *nd ) +{ + int len = POP(); + char *p = (char*)cell2pointer(POP()); + int n=0; + + while( nd->mark_lo < nvram.size && n < len ) { + *p++ = nvram.data[nd->mark_lo++]; + n++; + } + PUSH(n); + DPRINTF("read %p %x -- %x\n", p, len, n); +} + +/* ( addr len -- actual ) */ +static void +nvram_write( nvram_ibuf_t *nd ) +{ + int len = POP(); + char *p = (char*)cell2pointer(POP()); + int n=0; + + while( nd->mark_lo < nvram.size && n < len ) { + nvram.data[nd->mark_lo++] = *p++; + n++; + } + PUSH(n); + DPRINTF("write %p %x -- %x\n", p, len, n ); +} + +/* ( -- size ) */ +static void +nvram_size( __attribute__((unused)) nvram_ibuf_t *nd ) +{ + DPRINTF("nvram_size %d\n", nvram.size); + PUSH( nvram.size ); +} + +NODE_METHODS( nvram ) = { + { "size", (void*)nvram_size }, + { "read", (void*)nvram_read }, + { "write", (void*)nvram_write }, + { "seek", (void*)nvram_seek }, +}; + + +void +nvram_init( const char *path ) +{ + nvconf_init(); + + REGISTER_NAMED_NODE( nvram, path ); +} diff --git a/qemu/roms/openbios/packages/packages.h b/qemu/roms/openbios/packages/packages.h new file mode 100644 index 000000000..1ed6f1caa --- /dev/null +++ b/qemu/roms/openbios/packages/packages.h @@ -0,0 +1,36 @@ +/* + * Creation Date: <2003/12/23 00:32:12 samuel> + * Time-stamp: <2003/12/28 14:47:02 samuel> + * + * <packages.h> + * + * Package initialization + * + * Copyright (C) 2003 Samuel Rydh (samuel@ibrium.se) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#ifndef _H_MODULES +#define _H_MODULES + +extern void deblocker_init( void ); +extern void disklabel_init( void ); +extern void files_init( void ); +extern void iso9660_init( void ); +extern void hfsp_init( void ); +extern void hfs_init( void ); +extern void ext2_init( void ); +extern void grubfs_init( void ); +extern void macparts_init( void ); +extern void pcparts_init( void ); +extern void sunparts_init( void ); +extern void cmdline_init( void ); +extern void elf_loader_init( void ); +extern void xcoff_loader_init( void ); +extern void bootinfo_loader_init( void ); + +#endif /* _H_MODULES */ diff --git a/qemu/roms/openbios/packages/pc-parts.c b/qemu/roms/openbios/packages/pc-parts.c new file mode 100644 index 000000000..771923efe --- /dev/null +++ b/qemu/roms/openbios/packages/pc-parts.c @@ -0,0 +1,393 @@ +/* + * pc partition support + * + * Copyright (C) 2004 Stefan Reinauer + * + * This code is based (and copied in many places) from + * mac partition support by Samuel Rydh (samuel@ibrium.se) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#include "config.h" +#include "libopenbios/bindings.h" +#include "libopenbios/load.h" +#include "libc/byteorder.h" +#include "libc/vsprintf.h" +#include "packages.h" + +//#define DEBUG_PC_PARTS + +#ifdef DEBUG_PC_PARTS +#define DPRINTF(fmt, args...) \ + do { printk(fmt , ##args); } while (0) +#else +#define DPRINTF(fmt, args...) +#endif + +typedef struct { + xt_t seek_xt, read_xt; + ucell offs_hi, offs_lo; + ucell size_hi, size_lo; + phandle_t filesystem_ph; +} pcparts_info_t; + +DECLARE_NODE( pcparts, INSTALL_OPEN, sizeof(pcparts_info_t), "+/packages/pc-parts" ); + +#define SEEK( pos ) ({ DPUSH(pos); call_parent(di->seek_xt); POP(); }) +#define READ( buf, size ) ({ PUSH(pointer2cell(buf)); PUSH(size); call_parent(di->read_xt); POP(); }) + +/* three helper functions */ + +static inline int has_pc_valid_partition(unsigned char *sect) +{ + /* Make sure the partition table contains at least one valid entry */ + return (sect[0x1c2] != 0 || sect[0x1d2] != 0 || sect[0x1e2] != 0); +} + +static inline int has_pc_part_magic(unsigned char *sect) +{ + return sect[0x1fe]==0x55 && sect[0x1ff]==0xAA; +} + +static inline int is_pc_extended_part(unsigned char type) +{ + return type==5 || type==0xf || type==0x85; +} + +/* ( open -- flag ) */ +static void +pcparts_open( pcparts_info_t *di ) +{ + char *str = my_args_copy(); + char *argstr = strdup(""); + char *parstr = strdup(""); + int bs, parnum=-1; + int found = 0; + phandle_t ph; + ducell offs, size; + + /* Layout of PC partition table */ + struct pc_partition { + unsigned char boot; + unsigned char head; + unsigned char sector; + unsigned char cyl; + unsigned char type; + unsigned char e_head; + unsigned char e_sector; + unsigned char e_cyl; + u32 start_sect; /* unaligned little endian */ + u32 nr_sects; /* ditto */ + } *p, *partition; + + unsigned char buf[512]; + + DPRINTF("pcparts_open '%s'\n", str ); + + /* + Arguments that we accept: + id: [0-7] + [(id)][,][filespec] + */ + + if ( strlen(str) ) { + /* Detect the arguments */ + if ((*str >= '0' && *str <= '7') || (*str == ',')) { + push_str(str); + PUSH(','); + fword("left-parse-string"); + parstr = pop_fstr_copy(); + argstr = pop_fstr_copy(); + } else { + argstr = str; + } + + /* Convert the id to a partition number */ + if (parstr && strlen(parstr)) + parnum = atol(parstr); + } + + /* Make sure argstr is not null */ + if (argstr == NULL) + argstr = strdup(""); + + DPRINTF("parstr: %s argstr: %s parnum: %d\n", parstr, argstr, parnum); + free(parstr); + + if( parnum < 0 ) + parnum = 0; + + di->filesystem_ph = 0; + di->read_xt = find_parent_method("read"); + di->seek_xt = find_parent_method("seek"); + + SEEK( 0 ); + if( READ(buf, 512) != 512 ) + RET(0); + + /* Check Magic */ + if (!has_pc_part_magic(buf)) { + DPRINTF("pc partition magic not found.\n"); + RET(0); + } + + /* Actual partition data */ + partition = (struct pc_partition *) (buf + 0x1be); + + /* Make sure we use a copy accessible from an aligned pointer (some archs + e.g. SPARC will crash otherwise) */ + p = malloc(sizeof(struct pc_partition)); + + bs = 512; + + if (parnum < 4) { + /* primary partition */ + partition += parnum; + memcpy(p, partition, sizeof(struct pc_partition)); + + if (p->type == 0 || is_pc_extended_part(p->type)) { + DPRINTF("partition %d does not exist\n", parnum+1 ); + RET( 0 ); + } + + offs = (long long)(__le32_to_cpu(p->start_sect)) * bs; + di->offs_hi = offs >> BITS; + di->offs_lo = offs & (ucell) -1; + + size = (long long)(__le32_to_cpu(p->nr_sects)) * bs; + di->size_hi = size >> BITS; + di->size_lo = size & (ucell) -1; + + DPRINTF("Primary partition at sector %x\n", __le32_to_cpu(p->start_sect)); + + found = 1; + } else { + /* Extended partition */ + int i, cur_part; + unsigned long ext_start, cur_table; + + /* Search for the extended partition + * which contains logical partitions */ + for (i = 0; i < 4; i++) { + if (is_pc_extended_part(p[i].type)) + break; + } + + if (i >= 4) { + DPRINTF("Extended partition not found\n"); + RET( 0 ); + } + + DPRINTF("Extended partition at %d\n", i+1); + + /* Visit each logical partition labels */ + ext_start = __le32_to_cpu(p[i].start_sect); + cur_table = ext_start; + cur_part = 4; + + while (cur_part <= parnum) { + DPRINTF("cur_part=%d at %lx\n", cur_part, cur_table); + + SEEK( cur_table * bs ); + if( READ(buf, sizeof(512)) != sizeof(512) ) + RET( 0 ); + + if (!has_pc_part_magic(buf)) { + DPRINTF("Extended partition has no magic\n"); + break; + } + + /* Read the extended partition, making sure we are aligned again */ + partition = (struct pc_partition *) (buf + 0x1be); + memcpy(p, partition, sizeof(struct pc_partition)); + + /* First entry is the logical partition */ + if (cur_part == parnum) { + if (p->type == 0) { + DPRINTF("Partition %d is empty\n", parnum+1); + RET( 0 ); + } + + offs = (long long)(cur_table+__le32_to_cpu(p->start_sect)) * bs; + di->offs_hi = offs >> BITS; + di->offs_lo = offs & (ucell) -1; + + size = (long long)__le32_to_cpu(p->nr_sects) * bs; + di->size_hi = size >> BITS; + di->size_lo = size & (ucell) -1; + + found = 1; + break; + } + + /* Second entry is link to next partition */ + if (!is_pc_extended_part(p[1].type)) { + DPRINTF("no link\n"); + break; + } + + cur_table = ext_start + __le32_to_cpu(p[1].start_sect); + cur_part++; + } + + if (!found) { + DPRINTF("Logical partition %d does not exist\n", parnum+1); + RET( 0 ); + } + } + + free(p); + + if (found) { + /* We have a valid partition - so probe for a filesystem at the current offset */ + DPRINTF("pc-parts: about to probe for fs\n"); + DPUSH( offs ); + PUSH_ih( my_parent() ); + parword("find-filesystem"); + DPRINTF("pc-parts: done fs probe\n"); + + ph = POP_ph(); + if( ph ) { + DPRINTF("pc-parts: filesystem found with ph " FMT_ucellx " and args %s\n", ph, argstr); + di->filesystem_ph = ph; + + /* If we have been asked to open a particular file, interpose the filesystem package with + the passed filename as an argument */ + if (strlen(argstr)) { + push_str( argstr ); + PUSH_ph( ph ); + fword("interpose"); + } + } else { + DPRINTF("pc-parts: no filesystem found; bypassing misc-files interpose\n"); + } + + free( str ); + RET( -1 ); + } else { + DPRINTF("pc-parts: unable to locate partition\n"); + + free( str ); + RET( 0 ); + } +} + +/* ( block0 -- flag? ) */ +static void +pcparts_probe( pcparts_info_t *dummy ) +{ + unsigned char *buf = (unsigned char *)cell2pointer(POP()); + + DPRINTF("probing for PC partitions\n"); + + /* We also check that at least one valid partition exists; this is because + some CDs seem broken in that they have a partition table but it is empty + e.g. MorphOS. */ + RET ( has_pc_part_magic(buf) && has_pc_valid_partition(buf) ); +} + +/* ( -- type offset.d size.d ) */ +static void +pcparts_get_info( pcparts_info_t *di ) +{ + DPRINTF("PC get_info\n"); + PUSH( -1 ); /* no type */ + PUSH( di->offs_lo ); + PUSH( di->offs_hi ); + PUSH( di->size_lo ); + PUSH( di->size_hi ); +} + +static void +pcparts_block_size( __attribute__((unused))pcparts_info_t *di ) +{ + PUSH(512); +} + +static void +pcparts_initialize( pcparts_info_t *di ) +{ + fword("register-partition-package"); +} + +/* ( pos.d -- status ) */ +static void +pcparts_seek(pcparts_info_t *di ) +{ + long long pos = DPOP(); + long long offs, size; + + DPRINTF("pcparts_seek %llx:\n", pos); + + /* Seek is invalid if we reach the end of the device */ + size = ((ducell)di->size_hi << BITS) | di->size_lo; + if (pos > size) + RET( -1 ); + + /* Calculate the seek offset for the parent */ + offs = ((ducell)di->offs_hi << BITS) | di->offs_lo; + offs += pos; + DPUSH(offs); + + DPRINTF("pcparts_seek parent offset %llx:\n", offs); + + call_package(di->seek_xt, my_parent()); +} + +/* ( buf len -- actlen ) */ +static void +pcparts_read(pcparts_info_t *di ) +{ + DPRINTF("pcparts_read\n"); + + /* Pass the read back up to the parent */ + call_package(di->read_xt, my_parent()); +} + +/* ( addr -- size ) */ +static void +pcparts_load( __attribute__((unused))pcparts_info_t *di ) +{ + /* Invoke the loader */ + load(my_self()); +} + +/* ( pathstr len -- ) */ +static void +pcparts_dir( pcparts_info_t *di ) +{ + if ( di->filesystem_ph ) { + PUSH( my_self() ); + push_str("dir"); + PUSH( di->filesystem_ph ); + fword("find-method"); + POP(); + fword("execute"); + } else { + forth_printf("pc-parts: Unable to determine filesystem\n"); + POP(); + POP(); + } +} + +NODE_METHODS( pcparts ) = { + { "probe", pcparts_probe }, + { "open", pcparts_open }, + { "seek", pcparts_seek }, + { "read", pcparts_read }, + { "load", pcparts_load }, + { "dir", pcparts_dir }, + { "get-info", pcparts_get_info }, + { "block-size", pcparts_block_size }, + { NULL, pcparts_initialize }, +}; + +void +pcparts_init( void ) +{ + REGISTER_NODE( pcparts ); +} diff --git a/qemu/roms/openbios/packages/sun-parts.c b/qemu/roms/openbios/packages/sun-parts.c new file mode 100644 index 000000000..16b281b6e --- /dev/null +++ b/qemu/roms/openbios/packages/sun-parts.c @@ -0,0 +1,343 @@ +/* + * Sun (Sparc32/64) partition support + * + * Copyright (C) 2004 Stefan Reinauer + * + * This code is based (and copied in many places) from + * mac partition support by Samuel Rydh (samuel@ibrium.se) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#include "config.h" +#include "libopenbios/bindings.h" +#include "libopenbios/load.h" +#include "libc/byteorder.h" +#include "libc/vsprintf.h" +#include "packages.h" + +//#define DEBUG_SUN_PARTS + +#ifdef DEBUG_SUN_PARTS +#define DPRINTF(fmt, args...) \ + do { printk(fmt , ##args); } while (0) +#else +#define DPRINTF(fmt, args...) +#endif + +typedef struct { + xt_t seek_xt, read_xt; + ucell offs_hi, offs_lo; + ucell size_hi, size_lo; + int type; + phandle_t filesystem_ph; +} sunparts_info_t; + +DECLARE_NODE( sunparts, INSTALL_OPEN, sizeof(sunparts_info_t), "+/packages/sun-parts" ); + +#define SEEK( pos ) ({ DPUSH(pos); call_parent(di->seek_xt); POP(); }) +#define READ( buf, size ) ({ PUSH((ucell)buf); PUSH(size); call_parent(di->read_xt); POP(); }) + +/* Layout of SUN partition table */ +struct sun_disklabel { + uint8_t info[128]; /* Informative text string */ + uint8_t spare0[14]; + struct sun_info { + uint16_t id; + uint16_t flags; + } infos[8]; + uint8_t spare[246]; /* Boot information etc. */ + uint16_t rspeed; /* Disk rotational speed */ + uint16_t pcylcount; /* Physical cylinder count */ + uint16_t sparecyl; /* extra sects per cylinder */ + uint8_t spare2[4]; /* More magic... */ + uint16_t ilfact; /* Interleave factor */ + uint16_t ncyl; /* Data cylinder count */ + uint16_t nacyl; /* Alt. cylinder count */ + uint16_t ntrks; /* Tracks per cylinder */ + uint16_t nsect; /* Sectors per track */ + uint8_t spare3[4]; /* Even more magic... */ + struct sun_partition { + uint32_t start_cylinder; + uint32_t num_sectors; + } partitions[8]; + uint16_t magic; /* Magic number */ + uint16_t csum; /* Label xor'd checksum */ +}; + +/* two helper functions */ + +static inline int +has_sun_part_magic(unsigned char *sect) +{ + struct sun_disklabel *p = (struct sun_disklabel *)sect; + uint16_t csum, *ush, tmp16; + + if (__be16_to_cpu(p->magic) != 0xDABE) + return 0; + + csum = 0; + for (ush = (uint16_t *)p; ush < (uint16_t *)(p + 1); ush++) { + tmp16 = __be16_to_cpu(*ush); + csum ^= tmp16; + } + return csum == 0; +} + +/* ( open -- flag ) */ +static void +sunparts_open( sunparts_info_t *di ) +{ + char *str = my_args_copy(); + char *argstr = NULL; + char *parstr = NULL; + int parnum = -1; + unsigned char buf[512]; + struct sun_disklabel *p; + unsigned int i, bs; + ducell offs, size; + phandle_t ph; + + DPRINTF("sunparts_open '%s'\n", str ); + + /* + Arguments that we accept: + id: [0-7] | [a-h] + [(id)][,][filespec] + */ + + if ( str && strlen(str) ) { + /* Detect the arguments */ + if ((*str >= '0' && *str <= '9') || (*str >= 'a' && *str < ('a' + 8)) || (*str == ',')) { + push_str(str); + PUSH(','); + fword("left-parse-string"); + parstr = pop_fstr_copy(); + argstr = pop_fstr_copy(); + } else { + argstr = str; + } + + /* Convert the id to a partition number */ + if (parstr && strlen(parstr)) { + if (parstr[0] >= 'a' && parstr[0] < ('a' + 8)) + parnum = parstr[0] - 'a'; + else + parnum = atol(parstr); + } + } + + /* Make sure argstr is not null */ + if (argstr == NULL) + argstr = strdup(""); + + DPRINTF("parstr: %s argstr: %s parnum: %d\n", parstr, argstr, parnum); + + di->filesystem_ph = 0; + di->read_xt = find_parent_method("read"); + di->seek_xt = find_parent_method("seek"); + + SEEK( 0 ); + if (READ(buf, 512) != 512) { + free(str); + RET(0); + } + + /* Check Magic */ + if (!has_sun_part_magic(buf)) { + DPRINTF("Sun partition magic not found.\n"); + free(str); + RET(0); + } + + bs = 512; + /* get partition data */ + p = (struct sun_disklabel *)buf; + + for (i = 0; i < 8; i++) { + DPRINTF("%c: %d + %d, id %x, flags %x\n", 'a' + i, + __be32_to_cpu(p->partitions[i].start_cylinder), + __be32_to_cpu(p->partitions[i].num_sectors), + __be16_to_cpu(p->infos[i].id), + __be16_to_cpu(p->infos[i].flags)); + } + + if (parnum < 0) + parnum = 0; + + DPRINTF("Selected partition %d\n", parnum); + + offs = (long long)__be32_to_cpu(p->partitions[parnum].start_cylinder) * + __be16_to_cpu(p->ntrks) * __be16_to_cpu(p->nsect) * bs; + + di->offs_hi = offs >> BITS; + di->offs_lo = offs & (ucell) -1; + size = (long long)__be32_to_cpu(p->partitions[parnum].num_sectors) * bs; + if (size == 0) { + DPRINTF("Partition size is 0, exiting\n"); + free(str); + RET(0); + } + di->size_hi = size >> BITS; + di->size_lo = size & (ucell) -1; + di->type = __be16_to_cpu(p->infos[parnum].id); + + DPRINTF("Found Sun partition, offs %lld size %lld\n", + (long long)offs, (long long)size); + + /* Probe for filesystem at current offset */ + DPRINTF("sun-parts: about to probe for fs\n"); + DPUSH( offs ); + PUSH_ih( my_parent() ); + parword("find-filesystem"); + DPRINTF("sun-parts: done fs probe\n"); + + ph = POP_ph(); + if( ph ) { + DPRINTF("sun-parts: filesystem found with ph " FMT_ucellx " and args %s\n", ph, argstr); + di->filesystem_ph = ph; + + /* If we have been asked to open a particular file, interpose the filesystem package with + the passed filename as an argument */ + if (argstr && strlen(argstr)) { + push_str( argstr ); + PUSH_ph( ph ); + fword("interpose"); + } + } else { + DPRINTF("sun-parts: no filesystem found; bypassing misc-files interpose\n"); + + /* Solaris Fcode boot blocks assume that the disk-label package will always + automatically interpose the "ufs-file-system" package if it exists! We + need to mimic this behaviour in order for the boot to work. */ + push_str("ufs-file-system"); + feval("find-package"); + ph = POP_ph(); + + if (argstr && strlen(argstr) && ph) { + ph = POP_ph(); + push_str(argstr); + PUSH_ph(ph); + fword("interpose"); + } + } + + free( str ); + RET( -1 ); +} + +/* ( block0 -- flag? ) */ +static void +sunparts_probe( __attribute__((unused))sunparts_info_t *dummy ) +{ + unsigned char *buf = (unsigned char *)POP(); + + DPRINTF("probing for Sun partitions\n"); + + RET ( has_sun_part_magic(buf) ); +} + +/* ( -- type offset.d size.d ) */ +static void +sunparts_get_info( sunparts_info_t *di ) +{ + DPRINTF("Sun get_info\n"); + PUSH( di->type ); + PUSH( di->offs_lo ); + PUSH( di->offs_hi ); + PUSH( di->size_lo ); + PUSH( di->size_hi ); +} + +static void +sunparts_block_size( __attribute__((unused))sunparts_info_t *di ) +{ + PUSH(512); +} + +static void +sunparts_initialize( __attribute__((unused))sunparts_info_t *di ) +{ + fword("register-partition-package"); +} + +/* ( pos.d -- status ) */ +static void +sunparts_seek(sunparts_info_t *di ) +{ + long long pos = DPOP(); + long long offs, size;; + + DPRINTF("sunparts_seek %llx:\n", pos); + + /* Seek is invalid if we reach the end of the device */ + size = ((ducell)di->size_hi << BITS) | di->size_lo; + if (pos > size) + RET( -1 ); + + /* Calculate the seek offset for the parent */ + offs = ((ducell)di->offs_hi << BITS) | di->offs_lo; + offs += pos; + DPUSH(offs); + + DPRINTF("sunparts_seek parent offset %llx:\n", offs); + + call_package(di->seek_xt, my_parent()); +} + +/* ( buf len -- actlen ) */ +static void +sunparts_read(sunparts_info_t *di ) +{ + DPRINTF("sunparts_read\n"); + + /* Pass the read back up to the parent */ + call_package(di->read_xt, my_parent()); +} + +/* ( addr -- size ) */ +static void +sunparts_load( __attribute__((unused))sunparts_info_t *di ) +{ + /* Invoke the loader */ + load(my_self()); +} + +/* ( pathstr len -- ) */ +static void +sunparts_dir( sunparts_info_t *di ) +{ + if ( di->filesystem_ph) { + PUSH( my_self() ); + push_str("dir"); + PUSH( di->filesystem_ph ); + fword("find-method"); + POP(); + fword("execute"); + } else { + forth_printf("sun-parts: Unable to determine filesystem\n"); + POP(); + POP(); + } +} + +NODE_METHODS( sunparts ) = { + { "probe", sunparts_probe }, + { "open", sunparts_open }, + { "get-info", sunparts_get_info }, + { "block-size", sunparts_block_size }, + { "seek", sunparts_seek }, + { "read", sunparts_read }, + { "load", sunparts_load }, + { "dir", sunparts_dir }, + { NULL, sunparts_initialize }, +}; + +void +sunparts_init( void ) +{ + REGISTER_NODE( sunparts ); +} diff --git a/qemu/roms/openbios/packages/xcoff-loader.c b/qemu/roms/openbios/packages/xcoff-loader.c new file mode 100644 index 000000000..5213cc104 --- /dev/null +++ b/qemu/roms/openbios/packages/xcoff-loader.c @@ -0,0 +1,31 @@ +/* + * + * <xcoff-loader.c> + * + * XCOFF file loader + * + * Copyright (C) 2009 Laurent Vivier (Laurent@vivier.eu) + * + * from original XCOFF loader by Steven Noonan <steven@uplinklabs.net> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#include "config.h" +#include "libopenbios/bindings.h" +#include "libopenbios/xcoff_load.h" +#include "packages.h" + +DECLARE_NODE(xcoff_loader, INSTALL_OPEN, 0, "+/packages/xcoff-loader" ); + +NODE_METHODS( xcoff_loader ) = { + { "init-program", xcoff_init_program }, +}; + +void xcoff_loader_init( void ) +{ + REGISTER_NODE( xcoff_loader ); +} diff --git a/qemu/roms/openbios/utils/README b/qemu/roms/openbios/utils/README new file mode 100644 index 000000000..1cfea456b --- /dev/null +++ b/qemu/roms/openbios/utils/README @@ -0,0 +1,52 @@ +Here you find utilities useful for development and debugging of Open +Firmware systems. + +ofclient +-------- + +Sample OpenFirmware client. Can be booted directly from OpenFirmware +and demonstrates how an operating system can use the OpenFirmware +client interface. This example should work on PPC and x86 without +changes. + +romheaders +---------- +Romheaders is a small utility that dumps PCI expansion rom header +information in human readable form. It knows about Images with +multiple platform support and prints platform dependant information +for x86 and open firmware roms. + + +detok +----- +Detok is a GPLed FCode detokenizer. It can detokenize (disassemble) +fcode bytecode files as described by the IEEE 1275-1994 standard. This +program aims towards IEEE 1275-1994 compliancy, but there is no +warranty that it is actually compliant. bytecode files normally +contain Open Firmware drivers or other packages for use with an Open +Firmware compliant system. +See http://www.openbios.org/development/detok.html for more +information. + +devbios +------- +This is a kernel driver for different kind of (Flash)BIOSs that are +available in today's x86, ia64 (Itantium) or Alpha based hardware. + +fccc +---- +initial, incomplete implementation of an C to forth compiler. + + +dist +---- +rpm specfile and debian files for packing openbios with various +distributions. Changes/addons from distributors are explicitly +welcome. + + + + + + + diff --git a/qemu/roms/openbios/utils/devbios/COPYING b/qemu/roms/openbios/utils/devbios/COPYING new file mode 100644 index 000000000..486e6387f --- /dev/null +++ b/qemu/roms/openbios/utils/devbios/COPYING @@ -0,0 +1,353 @@ + + NOTE! The GPL below is copyrighted by the Free Software + Foundation, but the instance of code that it refers to (/dev/bios + driver)is copyrighted by me and others who actually wrote it. + + Also note that the only valid version of the GPL as far as this driver + is concerned is _this_ particular version of the license (ie v2, not + v2.2 or v3.x or whatever), unless explicitly otherwise stated. + + Stefan Reinauer + +---------------------------------------- + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) 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 +this service 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 make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. 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. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute 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 and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +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 +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the 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 a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, 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. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE 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. + + 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 +convey 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) 19yy <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 2 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, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision 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, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + <signature of Ty Coon>, 1 April 1989 + Ty Coon, President of Vice + +This 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 Library General +Public License instead of this License. diff --git a/qemu/roms/openbios/utils/devbios/CREDITS b/qemu/roms/openbios/utils/devbios/CREDITS new file mode 100644 index 000000000..cd642676c --- /dev/null +++ b/qemu/roms/openbios/utils/devbios/CREDITS @@ -0,0 +1,4 @@ + +Thanks to Michael Gibson from eSeSiX for donating a cs5530 +based thin client for porting /dev/bios. + diff --git a/qemu/roms/openbios/utils/devbios/ChangeLog b/qemu/roms/openbios/utils/devbios/ChangeLog new file mode 100644 index 000000000..3c8e5654d --- /dev/null +++ b/qemu/roms/openbios/utils/devbios/ChangeLog @@ -0,0 +1,295 @@ +NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! + +/dev/bios is obsolete and no longer under development. Please adapt all +changes to the "flashrom" utility of LinuxBIOS. This utility can be found +at LinuxBIOSv2/utils/flashrom in the LinuxBIOS v2 repository. LinuxBIOS +is available at http://www.linuxbios.org/ + +I'm also looking for volunteers to port all features available in /dev/bios +to flashrom so /dev/bios can be dropped from the OpenBIOS tree. These features +include + +- block information about flash chips +- block wise writing of flash chips +- lots of supported flash chips and vendors. + +If you have questions, contact Stefan Reinauer <stepan@coresystems.de> + +NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! + + +ChangeLog for /dev/bios + +** 2004/03/31 ******************************************************** + + * Added fix from Alex Beregszaszi to remove global *bios + +** 2004/03/05 ******************************************************** + + * fix compiling for 2.6 kernels. + +** 03/06/04 ********************************************************** + + * add SST49LF080A + * small 2.5 fix. + +** 02/06/10 ********************************************************** + + * some changes to detect pci cards firmware. + * pci cards firmware can be read even if flashing is not possible. + This is a new feature and might cause problems on some systems. + +** 02/04/16 ********************************************************** + + * reorganize Makefile, include .config from kernel. + * platform fixes for clean compilation. + +** 02/04/12 ********************************************************** + + * proprietary x86-64 support. + * change ruffian probe address + +** 02/03/28 ********************************************************** + + * proper implementation of system firmware detection on LX164 Alphas + * partly include jedec command cleanup patch from Pierrick Hascoet + <pierrick.hascoet@hydromel.net> + +** 02/03/11 ********************************************************** + + * only probe 512k on CS5530(A) + * add EON EN29F002 chips. + +** 02/02/22 ********************************************************** + + * rewrite major parts of bridge probing to make driver more generic. + * add Ali chipset support + * Saner iounmap() of flash devices. + +** 02/02/18 * 0.3.2 ************************************************** + + * change cs5530 driver to map high rom range instead of low one + and don't use positive decode. + * remove ruffian flag. Alpha (164LX/UX) almost works with pc code. + * don't rely on register defaults in intel 8xx driver. + * updated pci device list. more entries, join amd and via entry. + * fix error handling in chipset detection. + * add support for Reliance/ServerWorks chipsets + * enable 1M 512k on intel 4x0 chips where it's possible + * cleanup proc file handling + +** 02/02/17 ********************************************************** + + * rewrote chipset initialisation skeleton. + * fix pci bios (un)mapping. + * experimental support for AlphaPC 164UX (Ruffian) + (probes at 0xfffffffffffc0000 instead of 0xfffffc87C0000000 + * initial code for FWH mode chips + * Fix Toggle-Until-Ready code. + +** 02/02/16 ********************************************************** + + * iounmapping fixed. no more address space wasted. + * /proc/bios shows physical address now. dmesg shows + physical address and virtual memory area and offset. + +** 02/02/13 ********************************************************** + + * added i820/i830 chipset support + * added AMD 751/760MP(X) support + * added support for Itanium and 84460GX chipset + * added experimental support for some flash chips (ST, Intel, + Winbond) + * use spinlocks instead of hard cli() + +** 02/02/11 ********************************************************** + + * added GPL licence tag + * remove low bios area access tweaking for intel drivers + * speed up SST 39SF020 write + * fix compilation for 2.5 kernels + +** 02/02/05 ********************************************************** + + * added support for cs5530 (nsc/cyrix mediagx) chipset + * reorganized shadow/wp handling + * probe for 2mb high memory area instead of 256k only + +** 01/08/01 * 0.3.1 ************************************************** + + * compiles and works with Linux kernel 2.4 + * rewrote flash chip probing + * always use ioremap now + * flash chips above 128k should work transparent + * Support for newer VIA chipsets + +** 00/10/15 * 0.3.0pre1 ********************************************** + + * added patch from Eric Estabrook + * support for 256k flash chips on intel 430/440 chipsets and via vp3 + * split up source into several files + * Changes for Ruffian AXP machines. Does not work (yet). + +** 99/07/29 * 0.2.101 ************************************************ + + * Oh well.. 11 months? Impossible. I am a lazy guy. Implemented + some support for VIA Apollo VP3. Don't know whether it works, since + I don't have one. + +** 98/09/06 ********************************************************** + +patches by prumpf@jcsbs.lanobis.de: + * The pointer to bios_release in bios.c was on the flush pointer's + position. This caused Oopses. + * When bios_read was called with a file position after the actual end + of bios, it tried to read non-existant memory positions due to size + being unsigned (it isn't anymore) , causing spontaneous reboots on + my system + +** 98/08/22 ********************************************************** + + * Well,.. The diskless spectacle (0.2.100) was caused by a little bug + in in handling Intel PCI chipsets. Works now. + * Threw out the chipset_backout stuff. the PCI chipset handling should + always leave the machine in the same state it was before. ALWAYS. + +** 98/08/18 * 0.2.100 ************************************************ + + * Threw out the mem_type stuff. There are more important things than + this. + * Argh! After flashing fine on an Intel 28F001BT, the computer kept + hanging in an endless loop and refused writing the emergency boot + block to the end :-( There's some work until 0.3 is ready. + Implemented a timeout so that the system will not hang forever if + the flashchip behaves unexpected. + * Removed x86 probing in a loop. I think it never found anything else + but the system bios and *maybe* the graphics adapter bios. On the + other hand, it reconfigures some networking cards to silence. + Bad thing on diskless Linux boxes :) + +** 98/08/15 ********************************************************** + + * added some changes for intel to compile without warnings.. + +** 98/08/02 ********************************************************** + + * What a boring job! Checked some dozen of flash chip entries today + and added a lot of new ones. I bet it gets hard to find anything + this driver does not know. + +** 98/07/28 ********************************************************** + + * Yeah! Atmel Chips finally work.. These Atmel guys are really weird. + * Testing last instead of first written byte now, when polling for the + end of a write access. + +** 98/07/28 ********************************************************** + + * Well, I am definitely spending too much time in IRC, but detecting + PCI cards' bioses works now (at least for me) + * Thrown out some obsolete stuff. + * Declared PCI and Flash reading/writing __inline__. Don't know, + whether this is a good idea. But let's try it for a while. + * Aaaargh! Some major mistakes in handling whether a flash has to + be erased before programming. FIXED! + * Even worse. An endless loop made it into writing in 0.2.99. Sorry! + I had no chance to test writing on an intel board with that release. + At least my warning, not to write, made sense. + * Intel flashchips are supported now!! It's at least tested on my + Alpha AXP LX164 Board (1MByte i28f008 chip) But all Intel flash chips + seem to work in the same way. + * Atmel 64kByte flash chips supported. + +** 98/07/27 ********************************************************** + + * Split up flash_probe in 2 parts to be able to expand probing on + PCI bioses and others correctly. + * Turned around 1st and 2nd probing codes. This is funny, Atmel + Flashroms give some wrong numbers if they are probed with the + 0x80/0x60 way. I only hope that no flashchips react on the + 0x90 method with wrong values. + +** 98/07/19 * V0.2.99 ************************************************ + + * Reading the flashchip works now on Alpha AXP (at least on my LX164 + Board) + Writing ought to work, too, but Intel Flashchips are not supported + yet. This should be done until 0.3.0. + NOTE: I have no idea whether this driver still works on intel + boards or not. There have been too many changes. Please try, but + do not flash with this release of the driver. + * Minor Changes and fixes. Naming scheme changed a bit. This version + might work on James Mastros' machine again ?!? + +** 98/07/11 ********************************************************** + + * Started porting stuff to Alpha AXP architecture to continue testing + the flashing routines. We have a lot of tests next week, so I + won't get much stuff done.. + Porting to AXP seems to be much more work than I thought. It may + take some time until the next version is released. + * Moved major number again. This time we have an official major + number for /dev/bios. Thanks to Hans Peter Anvin. + (Well, we have this one since May 1st, sorry for the delay) + +** 98/06/26 * V0.2.95 ************************************************ + + * added all Manufacturer IDs from the JEDEC standards publication. + * sorry for not having released a new version since months, but + my x86 machine died and I have no chance to do any testing right + now. I guess I must get a new Intel box, as Alpha AXP are all + delivered with the same Intel flash chips. + +** 98/04/30 * V0.2.9 ************************************************* + + * removed ioctls. They have been really unneccesary and did not fit + into the new driver layout. + * cleaned up the code. Hey, it should be readable again. + * Moved device minors from 10+ to 0+ + * Rewrote most of the documentation + * changed intel shadowing routines. Now original values are saved + and shadowing is turned off for 0xc0000 to 0xdffff, too (This + was needed to support 2MBit system bios flash chips. Thanks again + to Matthew Harrell for intensive testing. + * Removed dirty hacks from bios_read_proc() + * Added some fields to struct flashdevice to support all ROM types, + not only flash roms. Probing for other types still missing. + * Implemented probing for some strange Winbond chips (0x80/0x20). + +** 98/04/27 * V0.2.8 ************************************************* + + *** Attention *** This version has a lot of changes since + 0.2.7, so be very careful, when testing. Things may + be broken that used to work. + + * Rewrote big parts of the driver to (theoretically) support + multiple flash chips and/or ROM areas. + * Tried to implement support for 2MBit System BIOS chips, but + I have no idea, whether it works. I don't have one. + * added some more OPTi, SiS and VIA PCI chipsets to chipset list. + They have no function yet, though. + * Some weird computers have an ISA bridge, but don't have it declared + as one. Now probing for known ISA bridge IDs. (Thanks to Matthew + Harrell for reporting this.) + * Added some new flashchip IDs and made some old ones work. + +** 98/04/24 * V0.2.7 ************************************************* + + * rewrote shadowing and wp functions to use a pci_functions structure + This makes it very easy to include new PCI chipsets. + * function chipset_init() detects PCI chipset. + * modversions support. Thanks to Matthew Harrell. + * moved PCI bridge detection to chipset_init() + +** 98/04/23 * V0.2.6 ************************************************* + + * repaired flashchip_ready_toggle and flashchip_ready_poll. + * Set WRITE_DELAY to 300 as it should be (works now) + * NOTE: These two changes make the operation of /dev/bios + theoretically correct, and by that quite secure. + +********************************************************************** + +There was no ChangeLog for versions prior to 0.2.6 + +Stefan Reinauer, <stepan@openbios.org> diff --git a/qemu/roms/openbios/utils/devbios/Makefile b/qemu/roms/openbios/utils/devbios/Makefile new file mode 100644 index 000000000..b6f7611bd --- /dev/null +++ b/qemu/roms/openbios/utils/devbios/Makefile @@ -0,0 +1,22 @@ +# comment this if you don't want debugging information +CFLAGS += -DDEBUG + +TARGET = bios.o +OBJS = bios_core.o flashchips.o pcisets.o \ + filesystem.o procfs.o programming.o + +obj-m := $(TARGET) +bios-objs := $(OBJS) + +all: module comp + +clean: + -rm -f $(TARGET) $(OBJS) comp *.o bios.ko + -rm -rf .*.cmd .tmp_versions +module: + make -C /usr/src/linux SUBDIRS=`pwd` modules + +comp: comp.c + $(CC) comp.c -O2 -o comp + strip comp + diff --git a/qemu/roms/openbios/utils/devbios/Makefile.24 b/qemu/roms/openbios/utils/devbios/Makefile.24 new file mode 100644 index 000000000..85717c4d4 --- /dev/null +++ b/qemu/roms/openbios/utils/devbios/Makefile.24 @@ -0,0 +1,81 @@ +CC = gcc +LD = ld + +KERNEL = /usr/src/linux +#KERNEL = /lib/modules/`uname -r`/build + +ARCH = $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/) + +ifeq ($(KERNEL)/.config,$(wildcard $(KERNEL)/.config)) +include $(KERNEL)/.config +endif + +CFLAGS = -D__KERNEL__ -I${KERNEL}/include -Wall \ + -Wstrict-prototypes -Wno-trigraphs -O2 \ + -fomit-frame-pointer -fno-common \ + -fno-strict-aliasing -pipe -DMODULE + +# comment this if you don't want debugging information +CFLAGS += -DDEBUG + +# see if we need module versions +ifdef CONFIG_MODVERSIONS +CFLAGS += -DMODVERSIONS +endif + +ifeq ($(ARCH),alpha) +CFLAGS += -mno-fp-regs -ffixed-8 -mcpu=ev5 -Wa,-mev6 +LDFLAGS = -m elf64alpha +endif + +ifeq ($(ARCH),sparc64) +CFLAGS += -mno-fpu -mtune=ultrasparc -mmedlow -ffixed-g4 \ + -fcall-used-g5 -fcall-used-g7 +LDFLAGS = -m elf_sparc64 +endif + +ifeq ($(ARCH),i386) +CFLAGS += -mpreferred-stack-boundary=2 -march=i586 +LDFLAGS = -m elf_i386 +endif + +ifeq ($(ARCH), x86_64) +CFLAGS += -mno-red-zone -mcmodel=kernel -fno-reorder-blocks \ + -finline-limit=2000 -fno-strength-reduce +LDFLAGS = -m elf_x86_64 +endif + +ifeq ($(ARCH),ia64) +CFLAGS += -ffixed-r13 -mfixed-range=f10-f15,f32-f127 \ + -falign-functions=32 +LDFLAGS = -m elf64_ia64 +endif + +.SUFFIXES: .o .c .h + +TARGET = bios.o +OBJS = bios_core.o flashchips.o pcisets.o \ + filesystem.o procfs.o programming.o + +all: $(TARGET) comp + +$(TARGET): $(OBJS) + $(LD) $(LDFLAGS) -r -o $(TARGET) $(OBJS) + +clean: + -rm -f $(TARGET) $(OBJS) comp *.o + +.c.o: + $(CC) $(INCLUDES) -c $(INCDIRS) $(CFLAGS) $(X_CFLAGS) $(DEBUGFLAGS) $*.c -o $@ + +comp: comp.c + $(CC) comp.c -O2 -o comp + strip comp + +bios_core.o: bios_core.c bios.h pcisets.h flashchips.h programming.h +filesystem.o: filesystem.c bios.h pcisets.h flashchips.h programming.h +flashchips.o: flashchips.c bios.h flashchips.h +pcisets.o: pcisets.c bios.h pcisets.h flashchips.h programming.h +procfs.o: procfs.c bios.h pcisets.h flashchips.h programming.h +programming.o: programming.c bios.h pcisets.h flashchips.h programming.h + diff --git a/qemu/roms/openbios/utils/devbios/README.bios b/qemu/roms/openbios/utils/devbios/README.bios new file mode 100644 index 000000000..45bd9a809 --- /dev/null +++ b/qemu/roms/openbios/utils/devbios/README.bios @@ -0,0 +1,256 @@ +NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! + +/dev/bios is obsolete and no longer under development. Please adapt all +changes to the "flashrom" utility of LinuxBIOS. This utility can be found +at LinuxBIOSv2/utils/flashrom in the LinuxBIOS v2 repository. LinuxBIOS +is available at http://www.linuxbios.org/ + +I'm also looking for volunteers to port all features available in /dev/bios +to flashrom so /dev/bios can be dropped from the OpenBIOS tree. These features +include + +- block information about flash chips +- block wise writing of flash chips +- lots of supported flash chips and vendors. + +If you have questions, contact Stefan Reinauer <stepan@coresystems.de> + +NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! + + +/dev/bios documentation 2002/02/19 + +Table of contents +------------------ + + 1. What is /dev/bios? + 2. What hardware/software do I need to run /dev/bios? + 3. Where to get the latest release of /dev/bios + 4. How to get /dev/bios work + 5. Writing to the devices + 6. About PCI chipsets (ix86 only) + 7. About APM Powermanagement (ix86 only) + 8. About different flashchips. + 9. Hints for BIOS flashing + +If you want better information on this driver, read the ChangeLog, +mail me or read the source, Luke :-) + +1. What is /dev/bios? +---------------------- + +This is a kernel driver for different kinds of (Flash)BIOSs that are +available in today's hardware. + +There are well known BIOSs for + - System BIOS (resides at 0xe0000 on Intel PCs) + - graphics hardware + - SCSI host adapters + - networking interfaces with 'BOOT ROM' + - ... + +While in former times these BIOSs were implemented by using ROM or +EPROM (both can't be updated without opening your computer) today's +PC hardware is often delivered with so called FLASH ROMs. These +can simply be updated by software. This driver has the approach to +make Linux read and write flash roms. + +One word before you read ahead: This is still alpha software and +writing to your flash roms may destroy them. So if you notice anything +strange, don't even think about going on, but write some mail to: + + Stefan Reinauer <stepan@openbios.org> + +Please note that I am not responsible in any way for what you +do with this code or for what this code does with your computer. + +2. What hardware/software do I need to run /dev/bios? +------------------------------------------------------ + +Currently this driver supports ix86 (mainly Pentium, +PPro, PII/III, Athlon, but some 486s), Itanium and Alpha +architecture. +It supports all flash chips from 32k to 2M (theoretically). +Minimum kernel version is v2.2.x, but it's wise to use a +2.4.x kernel. + +3. Where to get the latest release of /dev/bios? +------------------------------------------------- + +/dev/bios was recently integrated into the OpenBIOS CVS +tree for easier maintainance. General information can be +found on the /dev/bios status page: +http://www.freiburg.linux.de/OpenBIOS/status/devbios.html +Latest releases of /dev/bios can be found at the download page: +http://www.freiburg.linux.de/OpenBIOS/dev/download.html +Latest development trees of /dev/bios can be found in the +OpenBIOS CVS. For information how to access it, go to +http://www.freiburg.linux.de/OpenBIOS/dev/cvs.html + +4. How do I get /dev/bios work +------------------------------- + +Create the system bios device with + + mknod /dev/bios c 104 0 + +Now you can add devices for the other BIOSs (often known as option +roms) in your Computer, i.e. like this: + + mknod /dev/gfxbios c 104 1 + mknod /dev/hddbios c 104 2 + mknod /dev/netbios c 104 3 + +The order of the devices may vary on your computer, maybe you even don't +have a flash bios on your network card or on your scsi host adapter. You will +have to decide this after playing around a bit. + +Now you have to compile and insert the kernel driver module: + + cd devbios + make clean && make + insmod bios.o + +Now you have a new device, /dev/bios and, if you have +your kernel configured to have the /proc/ interface, +you have a status file /proc/bios. + +Since this driver is in an early state, you should have +a look at dmesg very often. + +5. Writing to the devices +-------------------------- + +If you insert bios.o without any options, you are not able +to write any of the devices. To enable writing, you should +use + insmod bios.o write=1 + +Writing is now possible with i.e. + dd if=yourbios.bin of=/dev/bios bs=128k count=1 +or + dd if=yourbios.bin of=/dev/bios bs=256k count=1 + +depending on the size of your flash chip. + +You can use 'cat' for flashing as well. Note: Many flashchips are +sectored and the whole sector has to be rewritten, the 4k clusters +of cat may be very slow (and an 112 kb sector has to be written 28 +times completely instead of 1 time with dd) + +Make sure that your file "yourbios.bin" is a valid bios image for +your motherboard and that it is not pkzipped or exe-pkzipped. +(Usually, a 128kb bios images consist of 112kb lha-compressed data, +2*4kb ESCD and DMI (PnP) Data and an 8 kb emergency boot block.) + +Writing to /dev/bios does not work for many chips right now. Write +accesses are ignored in this case. If you want an unsupported flash +rom supported, please mail me. +WARNING: Setting an unsupported chip to "supported" without changing +the rest of the code will *very likely* destroy the contents of your +chip. + +On machines with an AWARD bios you can test whether writing works +safely by only deleting the ESCD/DMI memory on the flash chip. +This data is rewritten by the bios when empty, corrupted or when +you put in a new expansion device. In that case you should see a +message stating "Updating ESCD" during the next boot. + +Please have a close look at the size of your flash chip. For 128k +flash chips, try + + dd if=/dev/zero of=/dev/bios bs=4096 seek=28 count=2 + +For 256k flash chips, you _MUST_ use the following line instead, +or your system bios is going byebye: + + dd if=/dev/zero of=/dev/bios bs=4096 seek=56 count=2 + +Attention: I found other machines with their ESCD memory in the +first sectors of the flash chip. These are afaics 512k+ chips +often connected via a firmware hub. +Behaviour of other BIOSs may be similar, but I can't give you +any warranty it works. + +NOTE: If you listen to music from your soundcard while flashing, +you may get errors like this: + Sound: DMA (output) timed out - IRQ/DRQ config error? + +Second, sound switches off while flashing. This is because all +IRQs are blocked while the write procedure to ensure it doesn't +get disturbed by any other hardware. + +6. About PCI chipsets +---------------------- + +Because this driver uses direct PCI accesses to switch shadowing +and write protection of the bios off on PC architecture, each PCI +chipset (or at least chipset group) has to be implemented and +tested seperately. Successfully tested PCI chipsets are + + * Intel 430HX/TX, 440BX/ZX, 460, 8x0 + * UMC 486 (8881F/8886A) + * VIA (M)VP3 + * AMD Irongate and others + * ServerWorks chipsets + * NSC CS5530 (geode companion) + +Any success/error reports are highly welcome. If you need a certain +system type supported, contact me. + + +7. About APM Power Management (ix86 only) +------------------------------------------ + +This driver is known to cause kernel oopses with some of the chipset +drivers when APM is enabled. Reason is that the flash chip is mapped +to the low bios address space which makes the unpacked bios image vanish +so all pointers to APM functions are invalid. +Nowadays most of the chipset drivers only map the high bios area, so +this problem should not occur on any but old UMC/SiS chipsets. If you +encounter oopses while reading/probing flash devices, disable power +management before any write attempts. To achieve so, please pass "apm=off" +as a kernel option, if your kernel is compiled with APM support. + + + +8. About different flashchips +------------------------------ + +Flash chips, /dev/bios has been successfully tested (writing) on: + + * Winbond 29EE011 + * Intel 28F008(SA) + * Atmel AT29C512 + * SST 29EE010, 39SF020 + +It *should* work, if you see a "Supported: yes" in /proc/bios, but +I am not responsible in any way for what you do.. Please be careful. +Please report any working flash chips so that this list can be completed. +Currently many more flash chips than mentioned here will work. +If you need a certain flash device supported, contact me. + +9. Hints for BIOS-Flashing +--------------------------- + +* Always try to write to the ESCD/DMI Memory before you overwrite the rest + of a bios (ix86) If you get ANY errors in dmesg output, DO NOT CONTINUE! +* Always "diff" the new bios with the written image before rebooting +* You may use comp, a little utility in the devbios source tree instead + of diff. It has a nicer output for binary files. +* on Intel, only write the first 120k of an image to the System ROM, this keeps + the emergency bootblock working. + +************** FINAL NOTE ***************************** + +If you want to help this project, send me + + * /proc/bios-output + * dmesg-output (after insmodding the driver) + * your system-configuration + (e.g. output of lspci or /proc/bus/pci/devices) + * any comments + * any ideas + + Stefan Reinauer <stepan@openbios.org> + diff --git a/qemu/roms/openbios/utils/devbios/ToDo b/qemu/roms/openbios/utils/devbios/ToDo new file mode 100644 index 000000000..2d320a9ee --- /dev/null +++ b/qemu/roms/openbios/utils/devbios/ToDo @@ -0,0 +1,33 @@ +ToDo-/Buglist 2003/06/04 (0.4pre6) +---------------------------------- + +Memory Stuff + * devbios does not find any flash chip on some systems even though + they are supported. One of the reasons this might happen is that + the flash memory area is hidden using the CPUs mtrrs. If you have + a Pentium II/III/IV or AMD K6/K7 board, you might try + echo "base=0xffe00000 size=0x200000 type=uncachable" >| /proc/mtrr + before loading the module. + +Misc Stuff + * port this driver to fit into the linux kernel's + mtd device drivers. + * join with ctflasher code + * port to *BSD (if anybody wants that) + * disable NMI watchdog while flashing, if active + +PCI Stuff + * unshadow functions do not work on certain 440BX/GX chipsets? + when loading the module, no system flashchip is detected. + * change unshadow functions not to touch low bios area to + be apm and pci bios safe. + +Module stuff + * /proc/sys/kernel/bios-writable + +Flashchip Stuff + * Finnish FWH support. + * Implement writing for Macronix and AMD. + (Catalyst have Intel and AMD compatible chips) + * Implement write protection checking some flash chips have. + * Test/complete existing support diff --git a/qemu/roms/openbios/utils/devbios/bios.h b/qemu/roms/openbios/utils/devbios/bios.h new file mode 100644 index 000000000..b27372d04 --- /dev/null +++ b/qemu/roms/openbios/utils/devbios/bios.h @@ -0,0 +1,38 @@ +/* + * OpenBIOS - free your system! + * ( firmware/flash device driver for Linux ) + * + * bios.h - compile time configuration and globals + * + * This program is part of a free implementation of the IEEE 1275-1994 + * Standard for Boot (Initialization Configuration) Firmware. + * + * Copyright (C) 1998-2004 Stefan Reinauer, <stepan@openbios.org> + * + * 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; version 2 of the License. + * + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + * + */ + +#include <linux/spinlock.h> + +#define BIOS_MAJOR 104 +#define BIOS_MAXDEV 8 +#define BIOS_VERSION "0.4rc1" + +// #define UTC_BIOS + +extern int write; +extern unsigned char *bios; +extern spinlock_t bios_lock; + diff --git a/qemu/roms/openbios/utils/devbios/bios_core.c b/qemu/roms/openbios/utils/devbios/bios_core.c new file mode 100644 index 000000000..d165cdb3e --- /dev/null +++ b/qemu/roms/openbios/utils/devbios/bios_core.c @@ -0,0 +1,198 @@ +/* + * OpenBIOS - free your system! + * ( firmware/flash device driver for Linux ) + * + * bios_core.c - core skeleton + * + * This program is part of a free implementation of the IEEE 1275-1994 + * Standard for Boot (Initialization Configuration) Firmware. + * + * Copyright (C) 1998-2004 Stefan Reinauer, <stepan@openbios.org> + * + * 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; version 2 of the License. + * + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + * + */ + +#include <linux/config.h> +#include <linux/version.h> +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) +#ifdef MODULE +#ifdef MODVERSIONS +#include <linux/modversions.h> +#endif +#endif +#include <linux/module.h> +#endif +#include <linux/pci.h> +#include <linux/errno.h> +#include <linux/vmalloc.h> +#include <linux/init.h> + +#include <asm/io.h> + +#include "bios.h" +#include "pcisets.h" +#include "flashchips.h" +#include "programming.h" + +extern struct file_operations bios_fops; +int bios_proc_register(void); +int bios_proc_unregister(void); + +int write = 0; + +spinlock_t bios_lock = SPIN_LOCK_UNLOCKED; + +/* + * ****************************************** + * + * Cleanup + * + * ****************************************** + */ + +static void free_iomaps(void) +{ + unsigned long lastmapped=0; + unsigned int i; + + /* We remember the last mapped area to be sure that we only iounmap + * every mapped area once. If two flash devices are in the same + * area but do not occur sequentially during probing you have a + * seriously strange hardware + */ + for (i=0; i<flashcount; i++) { + if (lastmapped==flashdevices[i].mapped) + continue; + iounmap((void *)flashdevices[i].mapped); + lastmapped=flashdevices[i].mapped; + } +} + +/* + * ****************************************** + * + * Initialization + * + * ****************************************** + */ + +void probe_system(void) +{ +#ifdef __alpha__ + probe_alphafw(); +#endif + /* This function checks all flash media attached to + * PCI devices in the system. This means NON-PCI systems + * don't work. This causes machine checks on my LX164 test + * machine, so leave it away until it's fixed. This is + * needed for Ruffians, so we check the machine type + * in probe_alphafw() and call probe_pcibus from there. + * This could use some cleanup + */ +#ifndef __alpha__ + probe_pcibus(); +#endif +} + +static __init int bios_init(void) +{ + printk(KERN_INFO "BIOS driver v" BIOS_VERSION " (writing %s) for " + UTS_RELEASE "\n", write?"enabled":"disabled"); + +#if !defined(UTC_BIOS) && LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) + if (!pci_present()) { + printk(KERN_WARNING "BIOS: No PCI system."); + return -EBUSY; + } +#endif + + /* Probe for flash devices */ + probe_system(); + + if (flashcount==0) { + printk(KERN_WARNING "BIOS: No flash devices found.\n"); + return -EBUSY; + } + + if (register_chrdev(BIOS_MAJOR, "bios", &bios_fops) == -EBUSY) { + printk(KERN_WARNING "BIOS: Could not register bios device.\n"); + free_iomaps(); + return -EBUSY; + } + +#ifdef CONFIG_PROC_FS + bios_proc_register(); +#endif + return 0; +} + +/* + * ****************************************** + * + * module handling + * + * ****************************************** + */ + +#ifdef MODULE +MODULE_PARM(write,"i"); +MODULE_AUTHOR("Stefan Reinauer <stepan@openbios.org>"); +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,10) +MODULE_LICENSE("GPL"); +#endif + +static __exit void cleanup_bios_module (void) +{ +#ifdef CONFIG_PROC_FS + bios_proc_unregister(); +#endif + free_iomaps(); + + unregister_chrdev(BIOS_MAJOR, "bios"); + printk(KERN_INFO "BIOS driver removed.\n"); +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) +int init_module(void) +{ + return bios_init(); +} + +void cleanup_module(void) +{ + cleanup_bios_module(); +} +#endif + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,74) +module_init(bios_init); +module_exit(cleanup_bios_module); +#endif + +void inc_mod(void) +{ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) + MOD_INC_USE_COUNT; +#endif +} + +void dec_mod(void) +{ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) + MOD_DEC_USE_COUNT; +#endif +} + +#endif diff --git a/qemu/roms/openbios/utils/devbios/comp.c b/qemu/roms/openbios/utils/devbios/comp.c new file mode 100644 index 000000000..9d2acb147 --- /dev/null +++ b/qemu/roms/openbios/utils/devbios/comp.c @@ -0,0 +1,47 @@ +/* Simple utility to compare 2 files. + * Diff or cmp are not sufficient, when + * comparing bioses :-) + * + * Copyright (c) 1998-2000 by Stefan Reinauer + */ + + +#include <stdio.h> + +int main (int argc, char *argv[]) +{ + FILE *eins,*zwei; + int a,b,i=0,flag=0; + + if(argv[1]==NULL||argv[2]==NULL) { + printf ("Usage: %s file1 file2\n %s compares two files.\n",argv[0],argv[0]); + return 0; + } + eins=fopen(argv[1],"r"); + zwei=fopen(argv[2],"r"); + + if (eins==NULL) { + printf ("File %s not found or unreadable.\n",argv[1]); + return 0; + } + if (zwei==NULL) { + printf ("File %s not found or unreadable.\n",argv[2]); + fclose (eins); + return 0; + } + + while (!feof(eins)) { + a=fgetc(eins); + b=fgetc(zwei); + if (flag==0 && (a==-1||b==-1) && (a!=-1||b!=-1)) { + printf ("One file ended. Printing the rest of the other.\n"); + flag=1; + } + if(a!=b) printf ("0x%06x: 0x%02x -> 0x%02x\n",i,a,b); + i++; + } + + fclose(eins); + fclose(zwei); + return 0; +} diff --git a/qemu/roms/openbios/utils/devbios/filesystem.c b/qemu/roms/openbios/utils/devbios/filesystem.c new file mode 100644 index 000000000..0dab71128 --- /dev/null +++ b/qemu/roms/openbios/utils/devbios/filesystem.c @@ -0,0 +1,300 @@ +/* + * OpenBIOS - free your system! + * ( firmware/flash device driver for Linux ) + * + * filesystem.c - vfs character device interface + * + * This program is part of a free implementation of the IEEE 1275-1994 + * Standard for Boot (Initialization Configuration) Firmware. + * + * Copyright (C) 1998-2004 Stefan Reinauer, <stepan@openbios.org> + * + * 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; version 2 of the License. + * + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + * + */ + +#include <linux/config.h> +#include <linux/version.h> +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) && defined(MODVERSIONS) +#include <linux/modversions.h> +#endif +#include <linux/module.h> +#include <linux/errno.h> +#include <linux/types.h> +#include <linux/vmalloc.h> +#include <linux/fcntl.h> +#include <linux/delay.h> + +#include <asm/uaccess.h> + +#include "bios.h" +#include "flashchips.h" +#include "pcisets.h" +#include "programming.h" + +#ifdef MODULE +void inc_mod(void); +void dec_mod(void); +#endif + +/* + * ****************************************** + * + * /dev/bios filesystem operations + * + * ****************************************** + */ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +#define FDEV (MINOR(file->f_dentry->d_inode->i_rdev)) +#else +#define FDEV (iminor(file->f_dentry->d_inode)) +#endif +#define CFLASH flashdevices[FDEV] +// #define BIOS_SIZE ((flashchips[CFLASH.flashnum].size)*1024) +#define BIOS_SIZE (CFLASH.size) + +static loff_t bios_llseek(struct file *file, loff_t offset, int origin ) +{ + currflash=FDEV; + switch(origin) { + case 0: + break; + case 1: + offset += file->f_pos; + break; + case 2: + offset += BIOS_SIZE; + break; + } + return((offset >= 0)?(file->f_pos = offset):-EINVAL); +} + +static ssize_t bios_read(struct file *file, char *buffer, size_t count, loff_t *ppos) +{ + signed int size=((BIOS_SIZE-*ppos>count) ? count : BIOS_SIZE-*ppos); + unsigned char *addr = (unsigned char*)CFLASH.mapped + CFLASH.offset; + int i; + + currflash = FDEV; + + devices[flashdevices[currflash].idx].activate(); + + for (i=0;i<size;i++) + buffer[i]=flash_readb(addr,*ppos+i); + + devices[flashdevices[currflash].idx].deactivate(); + + *ppos+=size; + return size; +} + +static ssize_t bios_write(struct file *file, const char *buffer, size_t count, loff_t *ppos) +{ + unsigned long flags; + unsigned int offset=0, startsec=0, endsec=0; + unsigned int secnum=0, size=0, writeoffs=0; + unsigned int i, fn; + unsigned char *clipboard; + unsigned char *addr = (unsigned char*)CFLASH.mapped + CFLASH.offset; + + currflash=FDEV; + fn=CFLASH.flashnum; + + /* Some security checks. */ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) + if (!suser()) + return -EACCES; +#endif + + if (!write) { + printk (KERN_WARNING "Writing is disabled for security reasons. RTFM.\n"); + return -EACCES; + } + + if (!flashchips[fn].supported) { + printk (KERN_ERR "BIOS: Flash device not supported.\n"); + return -EMEDIUMTYPE; + } + + if ( count > BIOS_SIZE-*ppos ) + return -EFBIG; + + /* FIXME: Autoselect(AMD) BC-90 + * -> 00/MID; + * 01/PID; + * 02/Protected (1=yes/0=no) + */ + + /* Determine size of data to be written */ + + if (!(flashchips[fn].flags & f_needs_erase) ) { + offset=(unsigned int)*ppos&~(flashchips[fn].pagesize-1); + size=(((unsigned int)*ppos+count+(flashchips[fn].pagesize-1))& + ~(flashchips[CFLASH.flashnum].pagesize-1))-offset; + } else { + while (flashchips[fn].sectors[secnum] <= flashchips[fn].size ) { + if ((unsigned int)*ppos >= flashchips[fn].sectors[secnum]*1024) { + offset=flashchips[fn].sectors[secnum]*1024; + startsec=secnum; + } + if ((unsigned int)*ppos+count-1 <= flashchips[fn].sectors[secnum]*1024) { + size=(flashchips[fn].sectors[secnum]*1024)-offset; + endsec=secnum-1; + break; + } + secnum++; + } + } + +#ifdef DEBUG + printk (KERN_DEBUG "BIOS: Write [0x%06x..0x%06x] [0x%06x..0x%06x]\n", + (unsigned int)(*ppos),(unsigned int)(*ppos+count-1),offset,offset+size-1); +#endif + + /* prepare data for writing */ + + clipboard=vmalloc(size); + + spin_lock_irqsave(&bios_lock, flags); + + devices[flashdevices[currflash].idx].activate(); + + for (i=0; i < size; i++) + clipboard[i] = flash_readb(addr,offset+i); + + copy_from_user(clipboard+(*ppos-offset), buffer, count); + + /* start write access */ + + if (flashchips[fn].flags & f_intel_compl) { + iflash_erase_sectors(addr,fn,startsec,endsec); + + for (i=0;i<size;i++) + iflash_program_byte(addr, offset+i, clipboard[i]); + + flash_command(addr, 0xff); + + } else { + + if (flashchips[fn].flags & f_needs_erase) { + if (size == flashchips[fn].size*1024) { /* whole chip erase */ + printk (KERN_DEBUG "BIOS: Erasing via whole chip method\n"); + flash_erase(addr, fn); + } else { + printk (KERN_DEBUG "BIOS: Erasing via sector method\n"); + flash_erase_sectors(addr, fn,startsec,endsec); + } + } + + while (size>0) { + if ((flashchips[fn].flags & f_manuf_compl) != f_atmel_compl) { + flash_program(addr); + } else { + flash_program_atmel(addr); + } + for (i=0;i<flashchips[fn].pagesize;i++) { + flash_writeb(addr,offset+writeoffs+i,clipboard[writeoffs+i]); + } + if ((flashchips[fn].flags & f_manuf_compl) == f_atmel_compl) { + udelay(750); + } else { + if (flashchips[fn].pagesize==1) + udelay(30); + else + udelay(300); + } + + if (flash_ready_poll(addr,offset+writeoffs+flashchips[fn].pagesize-1, + clipboard[writeoffs+flashchips[fn].pagesize-1])) { + printk (KERN_ERR "BIOS: Error occured, please repeat write operation.\n"); + } + flash_command(addr, 0xf0); + + writeoffs += flashchips[fn].pagesize; + size -= flashchips[fn].pagesize; + } + } + + devices[flashdevices[currflash].idx].deactivate(); + + spin_unlock_irqrestore(&bios_lock, flags); + + vfree(clipboard); + + *ppos+=count; + return count; +} + +static int bios_open(struct inode *inode, struct file *file) +{ + currflash=FDEV; + + if (flashcount<=FDEV) { + printk (KERN_ERR "BIOS: There is no device (%d).\n",FDEV); + return -ENODEV; + } + +#ifdef DEBUG + printk(KERN_DEBUG "BIOS: Opening device %d\n",FDEV); +#endif + /* Only one shall open for writing */ + + if ((CFLASH.open_cnt && (file->f_flags & O_EXCL)) || + (CFLASH.open_mode & O_EXCL) || + ((file->f_mode & 2) && (CFLASH.open_mode & O_RDWR))) + return -EBUSY; + + if (file->f_flags & O_EXCL) + CFLASH.open_mode |= O_EXCL; + + if (file->f_mode & 2) + CFLASH.open_mode |= O_RDWR; + + CFLASH.open_cnt++; + + +#ifdef MODULE + inc_mod(); +#endif + return 0; +} + +static int bios_release(struct inode *inode, struct file *file) +{ + currflash=FDEV; + if (file->f_flags & O_EXCL) + CFLASH.open_mode &= ~O_EXCL; + + if (file->f_mode & 2) + CFLASH.open_mode &= ~O_RDWR; + + CFLASH.open_cnt--; + +#ifdef MODULE + dec_mod(); +#endif + return 0; +} + +struct file_operations bios_fops = { + .owner = THIS_MODULE, + .llseek = bios_llseek, + .read = bios_read, + .write = bios_write, + .open = bios_open, + .release = bios_release, +}; + diff --git a/qemu/roms/openbios/utils/devbios/flashchips.c b/qemu/roms/openbios/utils/devbios/flashchips.c new file mode 100644 index 000000000..460a85def --- /dev/null +++ b/qemu/roms/openbios/utils/devbios/flashchips.c @@ -0,0 +1,313 @@ +/* + * OpenBIOS - free your system! + * ( firmware/flash device driver for Linux ) + * + * flashchips.c - contains all information about supported flash devices. + * + * This program is part of a free implementation of the IEEE 1275-1994 + * Standard for Boot (Initialization Configuration) Firmware. + * + * Copyright (C) 1998-2004 Stefan Reinauer, <stepan@openbios.org> + * + * 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; version 2 of the License. + * + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + * + */ +// <-- C++ style comments are for experimental comments only. +// They will disappear as soon as I fixed all the stuff. + +#include "bios.h" +#include "flashchips.h" + +unsigned int currflash=0; + +const manufacturer_t manufacturers[] = +{ + { "AMD", 0x01 }, + { "AMI", 0x02 }, + { "Fairchild", 0x83 }, + { "Fujitsu", 0x04 }, + { "GTE", 0x85 }, + { "Harris", 0x86 }, + { "Hitachi", 0x07 }, + { "Inmos", 0x08 }, + { "Intel", 0x89 }, + { "I.T.T.", 0x8A }, + { "Intersil", 0x0B }, + { "Monolithic Memories",0x8C }, + { "Mostek", 0x0D }, + { "Motorola", 0x0E }, + { "National", 0x8F }, + { "NEC", 0x10 }, + { "RCA", 0x91 }, + { "Raytheon", 0x92 }, + { "Rockwell", 0x13 }, + { "Seeq", 0x94 }, + { "Philips Semi.", 0x15 }, + { "Synertek", 0x16 }, + { "Texas Instruments", 0x97 }, + { "Toshiba", 0x98 }, + { "Xicor", 0x19 }, + { "Zilog", 0x1A }, + { "Eurotechnique", 0x9B }, + { "Mitsubishi", 0x1C }, + { "PMC Flash", 0x9D }, + { "Exel", 0x9E }, + { "Atmel", 0x1F }, + { "SGS/Thomson", 0x20 }, + { "Lattice Semi.", 0xA1 }, + { "NCR", 0xA2 }, + { "Wafer Scale Integr.",0x23 }, + { "IBM", 0xA4 }, + { "Tristar", 0x25 }, + { "Visic", 0x26 }, + { "Intl. CMOS Tech.", 0xA7 }, + { "SSSI", 0xA8 }, + { "MicrochipTech.", 0x29 }, + { "Ricoh Ltd.", 0x2A }, + { "VLSI", 0xAB }, + { "Micron Technology", 0x2C }, + { "Hyundai Elect.", 0xAD }, + { "OKI Semiconductor", 0xAE }, + { "ACTEL", 0x2F }, + { "Sharp", 0xB0 }, + { "Catalyst", 0x31 }, + { "Panasonic", 0x32 }, + { "IDT", 0xB3 }, + { "Cypress", 0x34 }, + { "DEC", 0xB5 }, + { "LSI Logic", 0xB6 }, + { "Plessey", 0x37 }, + { "UTMC", 0x38 }, + { "Thinking Machine", 0xB9 }, + { "Thomson CSF", 0xBA }, + { "Integ. CMOS(Vertex)",0x3B }, + { "Honeywell", 0xBC }, + { "Tektronix", 0x3D }, + { "Sun Microsystems", 0x3E }, + { "SST", 0xBF }, + { "MOSEL", 0x40 }, + { "Siemens", 0xC1 }, + { "Macronix", 0xC2 }, + { "Xerox", 0x43 }, + { "Plus Logic", 0xC4 }, + { "SunDisk", 0x45 }, + { "Elan Circuit Tech.", 0x46 }, + { "Europ. Silicon Str.",0xC7 }, + { "Apple Computer", 0xC8 }, + { "Xilinx", 0xC9 }, + { "Compaq", 0x4A }, + { "Protocol Engines", 0xCB }, + { "SCI", 0x4C }, + { "Seiko Instruments", 0xCD }, + { "Samsung", 0xCE }, + { "I3 Design System", 0x4F }, + { "Klic", 0xD0 }, + { "Crosspoint Sol.", 0x51 }, + { "Alliance Semicond.", 0x52 }, + { "Tandem", 0xD3 }, + { "Hewlett-Packard", 0x54 }, + { "Intg. Silicon Sol.", 0xD5 }, + { "Brooktree", 0xD6 }, + { "New Media", 0x57 }, + { "MHS Electronic", 0x58 }, + { "Performance Semi.", 0xD9 }, + { "Winbond", 0xDA }, + { "Kawasaki Steel", 0x5B }, + { "Bright Micro", 0xDC }, + { "TECMAR", 0x5D }, + { "Exar", 0x5E }, + { "PCMCIA", 0xDF }, + { "Goldstar", 0xE0 }, + { "Northern Telecom", 0x61 }, + { "Sanyo", 0x62 }, + { "Array Microsystems", 0xE3 }, + { "Crystal Semicond.", 0x64 }, + { "Analog Devices", 0xE5 }, + { "PMC-Sierra", 0xE6 }, + { "Asparix", 0x67 }, + { "Convex Computer", 0x68 }, + { "Quality Semicond.", 0xE9 }, + { "Nimbus Technology", 0xEA }, + { "Transwitch", 0x6B }, + { "ITT Intermetall", 0xEC }, + { "Cannon", 0x6D }, + { "Altera", 0x6E }, + { "NEXCOM", 0xEF }, + { "QUALCOMM", 0x70 }, + { "Sony", 0xF1 }, + { "Cray Research", 0xF2 }, + { "AMS(Austria Micro)", 0x73 }, + { "Vitesse", 0xF4 }, + { "Aster Electronics", 0x75 }, + { "Bay Networks(Synoptic)", 0x76 }, + { "Zentrum Mikroelec.", 0xF7 }, + { "TRW", 0xF8 }, + { "Thesys", 0x79 }, + { "Solbourne Computer", 0x7A }, + { "Allied-Signal", 0xFB }, + { "Dialog", 0x7C }, + { "Media Vision", 0xFD }, + { "Level One Commun.", 0xFE }, + { "Eon", 0x7F }, + + { "Unknown", 0x00 } +}; + +const flashchip_t flashchips[] = +{ + /* AMD */ + { "29F016B", 0xad01, 5, 2048, 0, 1, 1, (int []) { 0,2048 } }, + { "29F080B", 0xd501, 5, 1024, 0, 1, 1, (int []) { 0,1024 } }, + { "29F800BT", 0xd601, 5, 1024, 0, 1, 1, (int []) { 0,1024 } }, + { "29F800BB", 0x5801, 5, 1024, 0, 1, 1, (int []) { 0,1024 } }, + { "29F040B", 0xa401, 5, 512, 0, 1, 1, (int []) { 0, 512 } }, + { "29F400T", 0x2301, 5, 512, 0, 1, 1, (int []) { 0, 512 } }, + { "29LV004T", 0xb501, 3, 512, 0, 1, 1, (int []) { 0, 512 } }, + { "29LV400T", 0xb901, 3, 512, 0, 1, 1, (int []) { 0, 512 } }, + { "29F400B", 0xab01, 5, 512, 0, 1, 1, (int []) { 0, 512 } }, + { "29LV004B", 0xb601, 3, 512, 0, 1, 1, (int []) { 0, 512 } }, + { "29LV400B", 0xba01, 3, 512, 0, 1, 1, (int []) { 0, 512 } }, + { "28F020A", 0x2901, 12, 256, 0, 1, 1, (int []) { 0, 256 } }, + { "28F020", 0x2a01, 12, 256, 0, 1, 1, (int []) { 0, 256 } }, + { "29F002T", 0xb001, 5, 256, 0, 1, 1, (int []) { 0, 256 } }, + { "29LV002T", 0x4001, 3, 256, 0, 1, 1, (int []) { 0, 256 } }, + { "29LV200T", 0x3b01, 3, 256, 0, 1, 1, (int []) { 0, 256 } }, + { "29F200T", 0x5101, 5, 256, 0, 1, 1, (int []) { 0, 256 } }, + { "29F002B", 0x3401, 5, 256, 0, 1, 1, (int []) { 0, 256 } }, + { "29LV002B", 0xc201, 3, 256, 0, 1, 1, (int []) { 0, 256 } }, + { "29LV200B", 0xbf01, 3, 256, 0, 1, 1, (int []) { 0, 256 } }, + { "29F200B", 0x5701, 5, 256, 0, 1, 1, (int []) { 0, 256 } }, + { "29F010", 0x2001, 5, 128, 0, 1, 1, (int []) { 0, 128 } }, + { "28F010A", 0xa201, 12, 128, 0, 1, 1, (int []) { 0, 128 } }, + { "28F010", 0xa701, 12, 128, 0, 1, 1, (int []) { 0, 128 } }, + { "29F100T", 0xd901, 5, 64, 0, 1, 1, (int []) { 0, 64 } }, + { "29F100B", 0xdf01, 5, 64, 0, 1, 1, (int []) { 0, 64 } }, + { "28F512A", 0xae01, 12, 64, 0, 1, 1, (int []) { 0, 64 } }, + { "28F512", 0x2501, 12, 64, 0, 1, 1, (int []) { 0, 64 } }, + { "28F256A", 0x2f01, 12, 32, 0, 1, 1, (int []) { 0, 32 } }, + { "28F256", 0xa101, 12, 32, 0, 128, 1, (int []) { 0, 32 } }, + + /* Atmel */ + { "AT49BV010", 0x851f, 3, 128, 0, 128, 1, (int []) { 0, 128 } }, +//Word { "AT49F1025", 0x851f, 5, 128, 0, 256, 1, (int []) { 0, 128 } }, + { "AT49x020", 0x0b1f, 5, 256, 0, 128, 1, (int []) { 0, 256 } }, + { "AT49F040", 0x131f, 5, 512, 0, 128, 1, (int []) { 0, 512 } }, + { "AT49F010", 0x171f, 5, 128, 0, 128, 1, (int []) { 0, 128 } }, + { "AT49F080", 0x231f, 5, 1024, 0, 128, 1, (int []) { 0,1024 } }, + { "AT29C040A", 0xa41f, 5, 512, 1, 256, 4, (int []) { 0, 512 } }, +//Word { "AT29C1024", 0x251f, 3, 128, 0, 128, 0, (int []) { 0, 128 } }, +//Word { "AT29LV1024", 0x261f, 3, 128, 0, 128, 0, (int []) { 0, 128 } }, + { "AT49F080T", 0xa71f, 5, 1024, 0, 128, 1, (int []) { 0,1024 } }, + { "AT29BV010A", 0x351f, 3, 128, 1, 128, 4, (int []) { 0, 128 } }, + { "AT29BV020", 0xba1f, 3, 256, 1, 256, 4, (int []) { 0, 256 } }, + { "AT29LV256", 0xbc1f, 3, 32, 1, 64, 4, (int []) { 0, 32 } }, + { "AT29LV512", 0x3d1f, 3, 64, 1, 128, 4, (int []) { 0, 64 } }, + { "AT29BV040A", 0xc41f, 3, 512, 1, 256, 4, (int []) { 0, 512 } }, + { "AT29C010A", 0xd51f, 5, 128, 1, 128, 4, (int []) { 0, 128 } }, + { "AT29C020", 0xda1f, 5, 256, 1, 256, 4, (int []) { 0, 256 } }, + { "AT29C256", 0xdc1f, 3, 32, 1, 64, 4, (int []) { 0, 32 } }, + { "AT29C512", 0x5d1f, 5, 64, 1, 128, 4, (int []) { 0, 64 } }, + + /* Catalyst */ + { "CAT28F150T", 0x0431, 12, 192, 1, 128, 3, (int []) { 0, 64,160,168,176,192 } }, + { "CAT28F150B", 0x8531, 12, 192, 1, 128, 3, (int []) { 0, 16, 24, 32,128, 192 } }, + { "CAT28F001T", 0x9431, 12, 128, 1, 128, 3, (int []) { 0,112,116,120,128 } }, + { "CAT28F001B", 0x1531, 12, 128, 1, 128, 3, (int []) { 0, 8, 12, 16,128 } }, + { "CAT29F002T", 0xb031, 5, 256, 0, 128, 1, (int []) { 0, 64,128,192,224,232,240,256 } }, + { "CAT29F002B", 0x3431, 5, 256, 0, 128, 1, (int []) { 0, 16, 24, 32, 64,128,192,256 } }, + { "CAT28F002T", 0x7c31, 12, 256, 1, 128, 3, (int []) { 0,128,224,232,240,256 } }, + { "CAT28F002B", 0xfd31, 12, 256, 1, 128, 3, (int []) { 0, 16, 24, 32,128,256 } }, + { "CAT28F020" , 0xbd31, 12, 256, 0, 1, 1, (int []) { 0,256 } }, +//Word { "CAT28F102" , 0x5131, 12, 128, 0, 0, 0, (int []) { 0,128 } }, + { "CAT28F010" , 0xb431, 12, 128, 0, 1, 1, (int []) { 0,128 } }, + { "CAT28F512" , 0xb831, 12, 64, 0, 1, 1, (int []) { 0, 64 } }, + + { "29F040", 0xa404, 5, 512, 1, 1, 1, (int []) { 0, 64, 128, 192, 256, 320, 384, 448, 512 } }, /* Fujitsu */ + + + /* Intel */ + { "28F010", 0x3489, 12, 128, 0, 128, 1, (int []) { 0,128 } }, + { "28F020", 0x3d89, 12, 256, 0, 128, 1, (int []) { 0,256 } }, + { "28F001BX-T", 0x9489, 12, 128, 1, 128, 3, (int []) { 0,112,116,120,128 } }, + { "28F001BX-B", 0x9589, 12, 128, 1, 128, 3, (int []) { 0, 8, 12, 16,128 } }, +//Word { "28F400BX-T", 0x7089, 12, 512, 0, 256, 3, (int []) { 0,128,256,384,480,488,496,512 } }, +//Word { "28F400BX-B", 0xF189, 12, 512, 0, 256, 3, (int []) { 0, 16, 24, 32,128,256,384,512 } }, +//Word { "28F200-T", 0xF489, 12, 256, 0, 256, 3, (int []) { 0,128,224,232,240,256} }, +//Word { "28F200-B", 0x7589, 12, 256, 0, 256, 3, (int []) { 0, 16, 24, 32,128,256 } }, + { "28F016B3-T", 0xd089, 3, 1024, 0, 1, 3, (int []) { 0, 2048 } }, + { "28F016B3-B", 0xd189, 3, 1024, 0, 1, 3, (int []) { 0, 2048 } }, + { "28F008B3-T", 0xd289, 3, 1024, 0, 1, 3, (int []) { 0, 1024 } }, + { "28F008B3-B", 0xd389, 3, 1024, 0, 1, 3, (int []) { 0, 1024 } }, + { "28F004B3-T", 0xd489, 3, 512, 0, 128, 3, (int []) { 0,128,256,384,480,488,496,512 } }, + { "28F004B3-B", 0xd589, 3, 512, 0, 128, 3, (int []) { 0, 16, 24, 32,128,256,384,512 } }, + { "28F004BX-T", 0xF889, 12, 512, 1, 128, 3, (int []) { 0,128,256,384,480,488,496,512 } }, + { "28F004BX-B", 0x7989, 12, 512, 1, 128, 3, (int []) { 0, 16, 24, 32,128,256,384,512 } }, + { "28F002-T", 0x7c89, 12, 256, 1, 128, 3, (int []) { 0,128,224,232,240,256 } }, + { "28F002-B", 0xfd89, 12, 256, 1, 256, 3, (int []) { 0, 16, 24, 32,128,256 } }, + { "28F008??", 0xa289, 12, 1024, 1, 1, 3, (int []) { 0, 64,128,192,256,320,384,448,512,576,640,704,768,832,896,960,1024 } }, + { "28F008SA", 0xa189, 12, 1024, 1, 1, 3, (int []) { 0, 64,128,192,256,320,384,448,512,576,640,704,768,832,896,960,1024 } }, + { "28F004??", 0xad89, 5, 512, 0, 1, 3, (int []) { 0, 512} }, + { "28F008??", 0xac89, 5, 1024, 0, 1, 3, (int []) { 0,1024} }, + + /* Eon */ + { "E28F004S5", 0x7f8f, 5, 512, 1, 1, 3, (int []) { 0, 64,128,192,256,320,384,448,512 } }, + { "EN29F002B", 0x977f, 5, 256, 1, 1, 1, (int []) { 0, 16, 24, 32,128,256 } }, + { "EN29F002T", 0x927f, 5, 256, 1, 1, 1, (int []) { 0,128,224,232,240,256 } }, + + /* SST */ + { "28EE011", 0x01bf, 5, 128, 0, 128, 0, (int []) { 0, 128 } }, + { "28EE040", 0x04bf, 5, 512, 0, 128, 0, (int []) { 0, 512 } }, + { "29EE010", 0x07bf, 5, 128, 1, 128, 0, (int []) { 0, 128 } }, + { "29x010", 0x08bf, 3, 128, 0, 128, 0, (int []) { 0, 128 } }, + { "29EE020", 0x10bf, 5, 256, 0, 128, 0, (int []) { 0, 256 } }, + { "29x020", 0x92bf, 3, 256, 0, 128, 0, (int []) { 0, 256 } }, + { "29x512", 0x3dbf, 3, 64, 0, 128, 0, (int []) { 0, 64 } }, + { "29EE512", 0x5dbf, 5, 64, 0, 128, 0, (int []) { 0, 64 } }, + { "29x020", 0x92bf, 3, 256, 0, 128, 0, (int []) { 0, 256 } }, + { "39SF020", 0xb6bf, 5, 256, 1, 1, 0x81, (int []) { 0,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84,88,92,96,100,104,108,112,116,120,124,128,132,136,140,144,148,152,156,160,164,168,172,176,180,184,188,192,196,200,204,208,212,216,220,224,228,232,236,240,244,248,252,256 } }, + { "49LF002A", 0x57bf, 3, 256, 0, 1, 0x81, (int[]) {0,256} }, + { "49LF003A", 0x1bbf, 3, 384, 0, 1, 0x81, (int[]) {0,384} }, + { "49LF004A", 0x60bf, 3, 512, 1, 1, 0x09, (int[]) {0, 4, 8, 12, 16, 24,28, 32, 512} }, + { "49LF008A", 0x5abf, 3, 1024, 0, 1, 0x81, (int[]) {0,1024} }, + { "49LF020", 0x61bf, 3, 256, 1, 4096, 0, (int[]) {0,256} }, + { "49LF040", 0x51bf, 3, 512, 1, 4096, 0, (int[]) {0,512} }, + { "49LF080A", 0x5bbf, 3, 1024, 1, 4096, 0, (int[]) {0,1024} }, + + /* Macronix */ + { "MX28F1000AP",0x1ac2, 12, 128, 0, 1, 1, (int []) { 0, 16, 32, 48, 64, 80, 96,112,116,120,124,128 } }, + { "MX28F1000P", 0x91c2, 12, 128, 0, 1, 1, (int []) { 0, 16, 32, 48, 64, 80, 96,112,128 } }, + { "MX28F1000PC",0xf7c2, 12, 128, 0, 1, 1, (int []) { 0, 16, 32, 48, 64, 80, 96,112,128 } }, +//id? { "MX28F1000PPC",0x7fc2,12, 128, 0, 1, 1, (int []) { 0, 16, 32, 48, 64, 80, 96,112,116,120,124,128 } }, + { "MX29F1610A", 0xfac2, 5, 2048, 1, 128, 0, (int []) { 0, 2048} }, + + /* Winbond */ + { "W29EE011", 0xc1da, 5, 128, 1, 128, 0, (int []) { 0, 128 } }, + { "W29C020", 0x45da, 5, 256, 1, 128, 0, (int []) { 0, 256 } }, + { "W29C040/042",0x46da, 5, 512, 1, 256, 0, (int []) { 0, 512 } }, + { "W29EE512", 0xc8da, 5, 64, 1, 128, 0, (int []) { 0, 64 } }, + { "W29C101", 0x4fda, 5, 128, 1, 256, 0, (int []) { 0, 128 } }, + { "W49V002", 0xb0da, 3, 256, 1, 1, 1, (int []) { 0, 64, 128, 192, 224, 232, 240, 256 } }, + //{ "W49F002", 0x0bda, 5, 256, 1, 1, 1, (int []) { 0, 64, 128, 192, 224, 232, 240, 256 } }, + { "W49F002U", 0x0bda, 5, 256, 1, 1,0x09, (int []) { 0, 128, 224, 232, 240, 256 } }, /* Winbond */ + + /* SGS/Thomson */ + { "M29F002B(N)T", 0xb020, 5, 256, 0, 1, 0, (int[]) {0, 64, 128, 256 } }, + { "M29F002B(N)B", 0x3420, 5, 256, 0, 1, 0, (int[]) {0, 256 } }, + { "M50FW040", 0x2c20, 3, 512, 1, 128, 0x0b, (int []) { 0, 64, 128, 192, 256, 320, 384, 448, 512 } }, + + { "Pm29F002T", 0x1d9d, 5, 256, 1, 1, 0x1, (int []) { 0,128,224,232,240,256 } }, + /* default entry */ + { "Unknown", 0x0000, 0, 0, 0, 0, 0, (int []) { 0 } } +}; + diff --git a/qemu/roms/openbios/utils/devbios/flashchips.h b/qemu/roms/openbios/utils/devbios/flashchips.h new file mode 100644 index 000000000..3e6e5a6e0 --- /dev/null +++ b/qemu/roms/openbios/utils/devbios/flashchips.h @@ -0,0 +1,81 @@ +/* + * OpenBIOS - free your system! + * ( firmware/flash device driver for Linux ) + * + * flashchips.h - flash device structures. + * + * This program is part of a free implementation of the IEEE 1275-1994 + * Standard for Boot (Initialization Configuration) Firmware. + * + * Copyright (C) 1998-2004 Stefan Reinauer, <stepan@openbios.org> + * + * 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; version 2 of the License. + * + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + * + */ + +/* + * flags structure + * bit 0 = needs erase before write (f_needs_erase) + * bit 1-3 flash manu type + * bit 4-6 probably needed for more manu + * bit 7 = sector erase happens one sector at a time + * (f_slow_sector_erase) + */ + +#define f_needs_erase 0x01 + +/* 3 bit for flashtype */ +#define f_manuf_compl 0x0e /* Mask out bits 1-3 */ +#define f_intel_compl 0x02 /* 001 */ +#define f_atmel_compl 0x04 /* 010 */ +#define f_fwh_compl 0x08 /* 100 */ + +#define f_slow_sector_erase 0x80 + +#define FLASH_UNKNOWN 0 +#define FLASH_CFI 1 +#define FLASH_JEDEC 2 + +typedef struct flashdevice { + unsigned long mapped; + unsigned long physical; + unsigned long offset; + unsigned int flashnum, manufnum; + unsigned short id; + unsigned int size, sectors; + unsigned int idx; + void *data; + int open_mode, open_cnt; +} flashdevice_t; + +typedef struct flashchip { + char *name; + unsigned short id; + unsigned int voltage; + unsigned int size; /* KBytes */ + unsigned int supported; + unsigned int pagesize; /* Bytes */ + unsigned int flags; + unsigned int *sectors; /* Kbytes[] including end of last sector */ +} flashchip_t; + +typedef struct manufacturer { + char *name; + unsigned short id; +} manufacturer_t; + +extern unsigned int currflash; +extern flashdevice_t flashdevices[BIOS_MAXDEV]; +extern const flashchip_t flashchips[]; +extern const manufacturer_t manufacturers[]; diff --git a/qemu/roms/openbios/utils/devbios/pcisets.c b/qemu/roms/openbios/utils/devbios/pcisets.c new file mode 100644 index 000000000..91b9e0ea0 --- /dev/null +++ b/qemu/roms/openbios/utils/devbios/pcisets.c @@ -0,0 +1,630 @@ +/* + * OpenBIOS - free your system! + * ( firmware/flash device driver for Linux ) + * + * pcisets.c - support functions to map flash devices to kernel space + * + * This program is part of a free implementation of the IEEE 1275-1994 + * Standard for Boot (Initialization Configuration) Firmware. + * + * Copyright (C) 1998-2004 Stefan Reinauer, <stepan@openbios.org> + * + * 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; version 2 of the License. + * + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + * + */ + +#include <linux/config.h> +#include <linux/version.h> +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) +#ifdef MODVERSIONS +#include <linux/modversions.h> +#endif +#endif +#include <linux/pci.h> +#include <linux/types.h> +#include <linux/ioport.h> +#include <asm/io.h> +#ifdef __alpha__ +#include <asm/hwrpb.h> +#endif + +#include "bios.h" +#include "flashchips.h" +#include "pcisets.h" +#include "programming.h" + +#ifdef CONFIG_PCI +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10) +#define pci_find_class pci_get_class +#endif + +#define pci_id(dev) ((dev->vendor<<16) | (dev->device)) +struct pci_dev *hostbridge=NULL; +static unsigned char pci_dummy[4]; + +/* + * ****************************************** + * + * own pci/shadow handling; We can't use + * the PCI bios here as it would sweep + * itself out! + * + * ****************************************** + */ + +static int pci_read(struct pci_dev *dev, unsigned char where) +{ + if (!dev) return 0; + + outl((0x80000000 | (dev->bus->number << 16) | (dev->devfn << 8) | + (where & ~3)), 0xCF8); + mb(); + return inb(0xCFC + (where&3)); +} + +static void pci_write(struct pci_dev *dev, unsigned char where, unsigned char value) +{ + if (!dev) return; + outl((0x80000000 | (dev->bus->number << 16) | (dev->devfn << 8) | + (where & ~3)), 0xCF8); + mb(); + outb(value, 0xCFC + (where&3)); +} + +/* + * standard system firmware adress emitter + */ + +static int system_memarea(unsigned long *address, unsigned long *size, + struct pci_dev *dev) +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + const struct pci_driver *drv; + drv = pci_dev_driver(dev); +#endif +#ifndef __alpha__ + *address=0xffe00000; + *size=2048*1024; +#else + *address=0xfffffffffc000000; + *size=512*1024; +#endif + printk(KERN_INFO "BIOS: Probing system firmware with " + "%ldk rom area @0x%lx (%04x:%04x)\n", + (*size>>10), *address, dev->vendor, dev->device ); +#ifdef CONFIG_PCI_NAMES +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + if (drv) printk(KERN_INFO "BIOS: System device is %s\n", drv->name); +#else + printk(KERN_INFO "BIOS: System device is %s\n", dev->name); +#endif +#endif + return 0; +} + +static int memarea_256k(unsigned long *address, unsigned long *size, + struct pci_dev *dev) +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + const struct pci_driver *drv; + drv = pci_dev_driver(dev); +#endif + *address=0xfffc0000; + *size=256*1024; + printk(KERN_INFO "BIOS: Probing system firmware with " + "%ldk rom area @0x%lx (%04x:%04x)\n", + (*size>>10), *address, dev->vendor, dev->device ); +#ifdef CONFIG_PCI_NAMES +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + if (drv) printk(KERN_INFO "BIOS: System device is %s\n", drv->name); +#else + printk(KERN_INFO "BIOS: System device is %s\n", dev->name); +#endif +#endif + return 0; +} + +/* + * standard address emitter for normal pci devices + */ + +static int default_memarea(unsigned long *address, unsigned long *size, + struct pci_dev *dev) +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + *address=dev->resource[PCI_ROM_RESOURCE].start; + *size=dev->resource[PCI_ROM_RESOURCE].end - *address + 1; +#else + *address=0xdeadbeef; + *size=0x00000000; +#endif + if (*address && (signed long)*address!=-1 ) { + printk (KERN_DEBUG "BIOS: Probing PCI device %02x:%02x.%01x " + "with %ldk rom area @ 0x%lx\n", + dev->bus->number, PCI_SLOT(dev->devfn), + PCI_FUNC(dev->devfn), + (*size>>10), *address); + return 1; + } + *address=0xdeadbeef; + *size=0x00000000; + return 0; +} + +#ifdef __alpha__ +void probe_alphafw(void) +{ + switch(hwrpb->sys_type) { + case ST_DEC_EB164: + /* Fall through */ + break; + case ST_DTI_RUFFIAN: + /* case ST_DEC_TSUNAMI: // This crashes for whatever reason */ + probe_pcibus(); + return; + default: + printk(KERN_INFO "BIOS: unsupported alpha motherboard.\n"); + return; + } + + /* LX164 has system variation 0x2000 */ + if (hwrpb->sys_variation == 0x2000) + printk(KERN_INFO "BIOS: LX164 detected\n"); + else + printk(KERN_INFO "BIOS: EB164 board detected. Sys_var=0x%lx\n", + hwrpb->sys_variation); + + flashdevices[flashcount].data=(void *)0xfff80000; + flash_probe_area(0xfff80000, 512*1024, 0); +} +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) +#define pci_for_each_dev(dev) \ + for(dev = pci_devices->next; dev != pci_devices; dev = dev->next) +#endif +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,74) +#define pci_for_each_dev(dev) \ + while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev))) +#endif + +#define DEVICE(x) devices[g].pcidevs[x] +void probe_pcibus(void) +{ + struct pci_dev *dev=NULL; + unsigned int g=0, d, map_always=0; + unsigned long addr, size; + + /* Look whether we find something supported */ + pci_for_each_dev(dev) { + /* Search all device groups */ + for (g=0; DEVICE(0); g++ ) { + /* Search all devices in group */ + for (d=0; DEVICE(d) && DEVICE(d) != pci_id(dev); d++); + if(DEVICE(d) == pci_id(dev)) + break; + } + + flashdevices[flashcount].idx=g; + flashdevices[flashcount].data=dev; + + map_always=devices[g].memarea(&addr, &size, dev); +#ifdef DEBUG_PCI + printk(KERN_INFO "BIOS: device=%x, cs=%d addr=%lx, size=%ld\n", + pci_id(dev),g, addr,size); +#endif + if(!size) + continue; + + flash_probe_area(addr, size, map_always); + } +} +#undef DEVICE + +/* Intel 430, 440, 450 PCI Chipsets */ + +#define CURRENT ((struct pci_dev *)flashdevices[currflash].data) +static int gporeg_save; +static void intel4x0_activate(void) +{ +#ifdef __ABIT_BE6II_v11__ +#define GPONUM 26 +#define GPOREG_OFFSET 0x34 + register unsigned int gporeg; + /* Read Bus 0, Dev 7, Func 3, Reg 40-44 (Power Managment Base Address) */ + outl (0x80003B40, 0x0CF8); + /* calc General Purpose Output Register I/O port address */ + gporeg = (0xFFFFFFFE & inl (0x0CFC)) + GPOREG_OFFSET; + + /* Set GPO26 to 0 */ + gporeg_save=inl(gporeg); + printk(KERN_DEBUG "BIOS: GPOREG=0x%08x, mask=0x%x, new=0x%x\n",gporeg_save, (~(1<<GPONUM)), gporeg_save&(~(1<<GPONUM))); + outl (gporeg_save&(~(1<<GPONUM)), gporeg); +#undef GPOREG_OFFSET +#endif + + pci_dummy[0]=pci_read(CURRENT, 0x4e); + pci_dummy[1]=pci_read(CURRENT, 0x4f); + + /* Write and 128k enable */ + pci_dummy[2]=0x44; //0xC4 + + if (CURRENT->device < 0x7000) { + /* enable 512k */ + pci_dummy[2]|=0x80; + } else { + /* enable 1M */ + pci_write(CURRENT, 0x4f, pci_dummy[1] | 0x02); + } + + pci_write(CURRENT, 0x4e, pci_dummy[0] | pci_dummy[2]); + + // printk(KERN_DEBUG "BIOS: isa bridge cfg is 0x%02x\n", pci_dummy[0]); +} + +static void intel4x0_deactivate(void) +{ +#ifdef __ABIT_BE6II_v11__ +#define GPOREG_OFFSET 0x34 + register unsigned long gporeg; + + /* Read Bus 0, Dev 7, Func 3, Reg 40-44 (Power Managment Base Address) */ + outl (0x80003B40, 0x0CF8); + /* calc General Purpose Output Register I/O port address */ + gporeg = (0xFFFFFFFE & inl (0x0CFC)) + GPOREG_OFFSET; + + /* Reset GBO26 */ + outl (gporeg_save, gporeg); +#undef GPOREG_OFFSET +#endif + pci_write(CURRENT, 0x4e, pci_dummy[0]); + pci_write(CURRENT, 0x4f, pci_dummy[1]); +} + +/* preliminary support for Intel 830 mobile chipset. untested!! */ + +static void intel8x0_activate(void) +{ + pci_dummy[0]=pci_read(CURRENT, 0x4e); + pci_dummy[1]=pci_read(CURRENT, 0xe3); + pci_write(CURRENT, 0x4e, pci_dummy[0] | 0x01); + pci_write(CURRENT, 0xe3, pci_dummy[1] | 0xC0); + + // We don't have to change FWH_DEC_EN1, as it decodes + // all memory areas to the FWH per default. + // We try it anyways. + + // FWH_DEC_EN1: isabridge, 0xe3, 8bit, default 0xff. + // FWH_SEL1: isabridge, 0xe8, 32bit, default 0x00112233 (??) + + //printk(KERN_DEBUG "BIOS: BIOS_CNTL is 0x%02x\n", pci_dummy[0]); + //printk(KERN_DEBUG "BIOS: FWH_DEC_EN1 is 0x%02x\n", pci_dummy[1]); +} + +static void intel8x0_deactivate(void) +{ + pci_write(CURRENT, 0x4e, pci_dummy[0]); + pci_write(CURRENT, 0xe3, pci_dummy[1]); +} + +/* AMD 760/756/751 & VIA (M)VP3 */ + +static void amd7xx_activate(void) +{ + pci_dummy[0]=pci_read(CURRENT, 0x40); /* IO Control 1 */ + pci_dummy[1]=pci_read(CURRENT, 0x43); /* SEGEN */ + + pci_write(CURRENT, 0x40, pci_dummy[0] | 0x01); + pci_write(CURRENT, 0x43, pci_dummy[1] | 0x80); +} + +static void amd7xx_deactivate(void) +{ + pci_write(CURRENT, 0x43, pci_dummy[1]); + pci_write(CURRENT, 0x40, pci_dummy[0]); +} + +static void viamvp3_activate(void) +{ + hostbridge = pci_find_class(PCI_CLASS_BRIDGE_HOST<<8,NULL); + if (!hostbridge) + return; + pci_dummy[0]=pci_read(hostbridge,0x52); + pci_write(hostbridge, 0x52, pci_dummy[0] & 0xcf); + pci_dummy[1]=pci_read(hostbridge, 0x63); + pci_write(hostbridge, 0x63, pci_dummy[1] & 0x0f); + pci_dummy[2]=pci_read(CURRENT,0x43); + pci_write(CURRENT, 0x43, pci_dummy[2] |0xF8); + + pci_write(CURRENT, 0x40, pci_read(CURRENT,0x40) | 0x01); +} + +static void viamvp3_deactivate(void) +{ + if (!hostbridge) + return; + pci_write(CURRENT, 0x40, pci_read(CURRENT,0x40) & 0xfe); + pci_write(hostbridge, 0x63, pci_dummy[1]); + pci_write(hostbridge, 0x52, pci_dummy[0]); + pci_write(CURRENT, 0x43, pci_dummy[2]); +} + +/* SiS works with 530/5595 chipsets */ + +static void sis_activate(void) +{ + char b; + hostbridge = pci_find_class(PCI_CLASS_BRIDGE_HOST<<8,NULL); + if (!hostbridge) + return; + + pci_dummy[0]=pci_read(hostbridge, 0x76); + pci_dummy[1]=readb(0x51); + pci_dummy[2]=pci_read(CURRENT, 0x40); + pci_dummy[3]=pci_read(CURRENT, 0x45); + + /* disable shadow */ + pci_write(hostbridge, 0x76, 0x00); + /* disable cache */ + writeb(pci_dummy[1] & 0x7f, 0x51); + + /* Enable 0xFFF8000~0xFFFF0000 decoding on SiS 540/630 */ + pci_write(CURRENT, 0x40, pci_dummy[2]|0x0b); + /* Flash write enable on SiS 540/630 */ + pci_write(CURRENT, 0x45, pci_dummy[3]|0x40); + + /* The same thing on SiS 950 SuperIO side */ + outb(0x87, 0x2e); + outb(0x01, 0x2e); + outb(0x55, 0x2e); + outb(0x55, 0x2e); + if (inb(0x2f) != 0x87) { + /* printf("Can not access SiS 950\n"); */ + return; + } + + outb(0x24, 0x2e); + b = inb(0x2f) | 0xfc; + outb(0x24, 0x2e); + outb(b, 0x2f); + outb(0x02, 0x2e); + outb(0x02, 0x2f); +} + +static void sis_deactivate(void) +{ + if (!hostbridge) + return; + + /* Restore PCI Registers */ + pci_write(hostbridge, 0x76, pci_dummy[0]); + pci_write(CURRENT, 0x45, pci_dummy[2]); + pci_write(CURRENT, 0x45, pci_dummy[3]); + /* restore cache to original status */ + writeb(pci_dummy[1], 0x51); +} + +/* UMC 486 Chipset 8881/886a */ + +static void umc_activate(void) +{ + hostbridge = pci_find_class(PCI_CLASS_BRIDGE_HOST<<8,NULL); + if (!hostbridge) + return; + + pci_dummy[0]=pci_read(hostbridge, 0x54); + pci_dummy[1]=pci_read(hostbridge, 0x55); + + pci_write(hostbridge, 0x54, 0x00); + pci_write(hostbridge, 0x55, 0x40); + + pci_write(CURRENT,0x47, pci_read(CURRENT,0x47) & ~0x40); +} + +static void umc_deactivate(void) +{ + if (!hostbridge) + return; + + pci_write(CURRENT, 0x47, pci_read(CURRENT,0x47) | 0x40); + + pci_write(hostbridge, 0x54, pci_dummy[0]); + pci_write(hostbridge, 0x55, pci_dummy[1]); +} + +/* CS5530 functions */ + +static void cs5530_activate(void) +{ + /* Save modified registers for later reset */ + pci_dummy[0]=pci_read(CURRENT,0x52); + pci_dummy[1]=pci_read(CURRENT,0x5b); + + /* enable rom write access */ + pci_write(CURRENT, 0x52, pci_dummy[0]|0x06); + + /* enable rom positive decode */ + // pci_write(CURRENT,0x5b, pci_dummy[1]|0x20); + // pci_write(CURRENT,0x52, pci_read(CURRENT,0x52)|0x01); +} + +static void cs5530_deactivate(void) +{ + pci_write(CURRENT, 0x52, pci_dummy[0]); + // pci_write(CURRENT, 0x5b, pci_dummy[1]); +} + +/* Reliance / ServerWorks */ + +static void reliance_activate(void) +{ + pci_dummy[0]=pci_read(CURRENT,0x41); + pci_dummy[1]=pci_read(CURRENT,0x70); + pci_dummy[2]=inb(0xc6f); + + /* Enable 512k */ + pci_write(CURRENT, 0x41, pci_dummy[0] | 0x02); + /* Enable 4MB */ + pci_write(CURRENT, 0x70, pci_dummy[1] | 0x80); + /* Enable flash write */ + outb(pci_dummy[2] | 0x40, 0xc6f); +} + +static void reliance_deactivate(void) +{ + pci_write(CURRENT, 0x41, pci_dummy[0]); + pci_write(CURRENT, 0x70, pci_dummy[1]); + outb(pci_dummy[2], 0xc6f); +} + +/* ALi Methods - untested */ +static void ali_activate(void) +{ + pci_dummy[0]=pci_read(CURRENT, 0x47); + pci_dummy[1]=pci_read(CURRENT, 0x79); + pci_dummy[2]=pci_read(CURRENT, 0x7f); + + /* write enable, 256k enable */ +#ifdef OLD_ALi + pci_write(CURRENT, 0x47, pci_dummy[0]|0x47); +#else + pci_write(CURRENT, 0x47, pci_dummy[0]|0x43); +#endif + + /* M1543C rev B1 supports 512k. Register reserved before */ +#ifdef OLD_ALi + pci_write(CURRENT, 0x79, pci_dummy[1]|0x10); + pci_write(CURRENT, 0x7f, pci_dummy[2]|0x01); +#else + pci_write(CURRENT, 0x7b, pci_dummy[1]|0x10); +#endif +} + +static void ali_deactivate(void) +{ + pci_write(CURRENT, 0x47, pci_dummy[0]); + pci_write(CURRENT, 0x79, pci_dummy[1]); + pci_write(CURRENT, 0x7f, pci_dummy[2]); +} + +/* Default routines. Use these if nothing else works */ +#if 0 +static unsigned int def_addr; +#endif +static void default_activate(void) +{ +#if 0 && LINUX_VERSION_CODE > KERNEL_VERSION(2,4,0) + struct resource *r; + + r=&CURRENT->resource[PCI_ROM_RESOURCE]; + + r->flags |= PCI_ROM_ADDRESS_ENABLE; + r->flags &= ~(IORESOURCE_READONLY|IORESOURCE_CACHEABLE); + pci_read_config_dword(CURRENT, CURRENT->rom_base_reg, &def_addr); + if (def_addr) + pci_write_config_dword (CURRENT, CURRENT->rom_base_reg, + def_addr|PCI_ROM_ADDRESS_ENABLE); +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + long ret; + + if (pci_enable_device(CURRENT)) + return; + + pci_write_config_dword (CURRENT, CURRENT->rom_base_reg, + pci_resource_start(CURRENT, PCI_ROM_RESOURCE)| + PCI_ROM_ADDRESS_ENABLE); + + ret=(long)request_mem_region( pci_resource_start(CURRENT, + PCI_ROM_RESOURCE), pci_resource_len(CURRENT, + PCI_ROM_RESOURCE), "Firmware memory"); + if (!ret) + printk (KERN_ERR "BIOS: cannot reserve MMROM region " + "0x%lx+0x%lx\n", + pci_resource_start(CURRENT, PCI_ROM_RESOURCE), + pci_resource_len(CURRENT, PCI_ROM_RESOURCE)); + else + printk (KERN_INFO "BIOS: mapped rom region to 0x%lx\n", ret); +#endif +} + +static void default_deactivate(void) +{ +#if 0 && LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + struct resource *r; + r=&CURRENT->resource[PCI_ROM_RESOURCE]; + r->flags &= ~PCI_ROM_ADDRESS_ENABLE; + r->flags |= (IORESOURCE_READONLY|IORESOURCE_CACHEABLE); + pci_write_config_dword (CURRENT, CURRENT->rom_base_reg, def_addr); +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) + release_mem_region(pci_resource_start(CURRENT, PCI_ROM_RESOURCE), + pci_resource_len(CURRENT, PCI_ROM_RESOURCE)); +#endif +} + +const struct flashdev devices[] = { + /* Intel 4x0 chipsets */ + { (int[]) { 0x8086122e, 0x80861234, 0x80867000, 0x80867110, + 0x80867198, 0 }, + intel4x0_activate, intel4x0_deactivate, system_memarea }, + + /* Intel 8x0 chipsets */ + { (int[]) { 0x80862410, 0x80862420, 0x80862440, 0x8086244c, + 0x80862480, 0x8086248c, 0x80867600, 0 }, + intel8x0_activate, intel8x0_deactivate, system_memarea }, + + /* Irongate 75x, AMD-76xMP(X), VT8231/3 */ + { (int[]) { 0x10227400, 0x10227408, 0x10227410, 0x10227440, + 0x11068231, 0x11063074, 0 }, + amd7xx_activate, amd7xx_deactivate, system_memarea }, + + /* AMD Hammer (thor chipset) */ + { (int[]) { 0x10227468, 0 }, + amd7xx_activate, amd7xx_deactivate, system_memarea }, + + /* VIA (M)VP3, VT82C686 [Apollo Super South] */ + { (int[]) { 0x11060586, 0x11060596, 0x11060686, 0 }, + viamvp3_activate, viamvp3_deactivate, memarea_256k }, + + /* UMC */ + { (int[]) { 0x1060886a, 0x10600886, 0x1060e886, 0x10608886, 0 }, + umc_activate, umc_deactivate, system_memarea }, + + /* SiS */ + { (int[]) { 0x10390008, 0x10390018, 0 }, + sis_activate, sis_deactivate, system_memarea }, + + /* OPTi */ + { (int[]) { 0x1045c558, 0 }, + default_activate, default_deactivate, system_memarea }, + + /* NSC CS5530(A) */ + { (int[]) { 0x10780100, 0 }, + cs5530_activate, cs5530_deactivate, memarea_256k }, + + /* Reliance/ServerWorks NB6xxx */ + { (int[]) { 0x11660200, 0 }, + reliance_activate, reliance_deactivate, system_memarea }, + + /* ALi */ + { (int[]) { 0x10b91523, 0x10b91533, 0x10b91543, 0 }, + ali_activate, ali_deactivate, system_memarea }, + + { (int[]) { 0x00000000 }, + default_activate, default_deactivate, default_memarea } +}; + +#endif /* CONFIG_PCI */ + diff --git a/qemu/roms/openbios/utils/devbios/pcisets.h b/qemu/roms/openbios/utils/devbios/pcisets.h new file mode 100644 index 000000000..1045f0a42 --- /dev/null +++ b/qemu/roms/openbios/utils/devbios/pcisets.h @@ -0,0 +1,45 @@ +/* + * OpenBIOS - free your system! + * ( firmware/flash device driver for Linux ) + * + * pcisets.h - structures for device bindings + * + * This program is part of a free implementation of the IEEE 1275-1994 + * Standard for Boot (Initialization Configuration) Firmware. + * + * Copyright (C) 1998-2004 Stefan Reinauer, <stepan@openbios.org> + * + * 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; version 2 of the License. + * + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + * + */ + +#include <linux/pci.h> + +#ifdef CONFIG_PCI + +struct flashdev { + unsigned int *pcidevs; + void (*activate)(void); + void (*deactivate) (void); + int (*memarea)(unsigned long *address, unsigned long *size, + struct pci_dev *dev); +}; + +extern const struct flashdev devices[]; + +void probe_pcibus(void); +#ifdef __alpha__ +void probe_alphafw(void); +#endif +#endif diff --git a/qemu/roms/openbios/utils/devbios/procfs.c b/qemu/roms/openbios/utils/devbios/procfs.c new file mode 100644 index 000000000..12ad17e3e --- /dev/null +++ b/qemu/roms/openbios/utils/devbios/procfs.c @@ -0,0 +1,162 @@ +/* + * OpenBIOS - free your system! + * ( firmware/flash device driver for Linux ) + * + * procfs.c - proc filesystem handling for flash device listing. + * + * This program is part of a free implementation of the IEEE 1275-1994 + * Standard for Boot (Initialization Configuration) Firmware. + * + * Copyright (C) 1998-2004 Stefan Reinauer, <stepan@openbios.org> + * + * 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; version 2 of the License. + * + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + * + */ + +#include <linux/config.h> +#include <linux/version.h> +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) && defined(MODVERSIONS) +#include <linux/modversions.h> +#endif +#include <linux/proc_fs.h> + +#ifdef CONFIG_PROC_FS +#include "bios.h" +#include "pcisets.h" +#include "flashchips.h" +#include "programming.h" + +struct proc_dir_entry *proc_bios; + +#define PRINT_PROC(fmt,args...) \ + do { \ + if (!run) \ + break; \ + len += sprintf( buffer+len, fmt, ##args ); \ + if (begin + len > offset + size) \ + run=0; \ + else if (begin + len < offset) { \ + begin += len; \ + len = 0; \ + } \ + } while (0) + +/* + * ****************************************** + * + * /proc/bios handling + * + * ****************************************** + */ + +#define CFLASH flashdevices[i] +#define FLASH flashchips[CFLASH.flashnum] +#define MANUF manufacturers[CFLASH.manufnum] + +int bios_read_proc(char *buffer, char **start, off_t offset, int size, int *eof, void *data) +{ + int len=0, run=1, i; + off_t begin = 0; + + for (i=0;i<flashcount;i++) { +#ifdef DEBUG_PROC + printk(KERN_DEBUG "BIOS: processing proc info for " + "flashchip %d\n",i+1); +#endif + if (i) /* empty line is seperator between flash chips */ + PRINT_PROC("\n"); + + PRINT_PROC("Memory Address : 0x%08lx\n", + (unsigned long)CFLASH.physical); + PRINT_PROC("Memory Size : %d kByte\n", CFLASH.size>>10); + PRINT_PROC("Flash Type : "); + + if (CFLASH.id == 0) { + PRINT_PROC("ROM\n"); + continue; + } + + /* Flash chip completely unknown -> output ID and proceed */ + if (FLASH.id == 0) { + PRINT_PROC("unknown %s device (id 0x%04x)\n", + MANUF.name, CFLASH.id); + PRINT_PROC("Supported : no\n"); + continue; + } + + PRINT_PROC("%s %s (%dV)\n", MANUF.name, + FLASH.name, FLASH.voltage); + + PRINT_PROC("Supported : %s\n", + FLASH.supported ? "yes": "no"); +#ifdef DEBUG + PRINT_PROC("Pagetable : %d Byte\n", FLASH.pagesize ); + + PRINT_PROC("Erase first : %s\n", + FLASH.flags & f_needs_erase ? "yes": "no"); + + PRINT_PROC("Intel compliant : %s\n", + FLASH.flags & f_intel_compl ? "yes": "no"); + + PRINT_PROC("FWH compliant : %s\n", + FLASH.flags & f_fwh_compl ? "yes": "no"); + + if (CFLASH.sectors > 1) + PRINT_PROC("Sectors : %d\n", CFLASH.sectors); +#endif + } +#ifdef DEBUG_PROC + printk(KERN_DEBUG "BIOS: read_proc done.\n"); +#endif + /* set to 1 if we're done */ + *eof=run; + + if (offset >= begin + len) + return 0; + + *start = buffer + (begin - offset); + + return (size < begin + len - offset ? size : begin + len - offset); +} +#undef FLASH +#undef MANUF +#undef CFLASH + +#ifdef PROC_WRITEABLE +int bios_write_proc(struct file *file, const char *buffer, unsigned long count, void *data) +{ + printk (KERN_INFO "%s\n",buffer); + return count; +} +#endif + +int bios_proc_register(void) +{ + if ((proc_bios = create_proc_entry("bios", 0, 0))) { + proc_bios->read_proc = bios_read_proc; +#ifdef PROC_WRITABLE + proc_bios->write_proc = bios_write_proc; +#endif + return 0; + } + return 1; +} + +int bios_proc_unregister(void) +{ + if (proc_bios) + remove_proc_entry("bios", 0); + return 0; +} +#endif diff --git a/qemu/roms/openbios/utils/devbios/programming.c b/qemu/roms/openbios/utils/devbios/programming.c new file mode 100644 index 000000000..e1b35a34b --- /dev/null +++ b/qemu/roms/openbios/utils/devbios/programming.c @@ -0,0 +1,539 @@ +/* + * OpenBIOS - free your system! + * ( firmware/flash device driver for Linux ) + * + * programming.c - flash device programming and probing algorithms. + * + * This program is part of a free implementation of the IEEE 1275-1994 + * Standard for Boot (Initialization Configuration) Firmware. + * + * Copyright (C) 1998-2004 Stefan Reinauer, <stepan@openbios.org> + * + * 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; version 2 of the License. + * + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + * + */ + +// <-- C++ style comments are for experimental comments only. +// They will disappear as soon as I fixed all the stuff. + +/* #define DEBUG_PROBING */ + +#include <linux/config.h> +#include <linux/version.h> +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) && defined(MODVERSIONS) +#include <linux/modversions.h> +#endif + +#include <linux/pci.h> +#include <linux/errno.h> +#include <linux/types.h> +#include <linux/vmalloc.h> +#include <linux/delay.h> +#include <linux/spinlock.h> +#include <asm/io.h> +#include <asm/delay.h> +#include <asm/uaccess.h> + +#include "bios.h" +#include "pcisets.h" +#include "flashchips.h" +#include "programming.h" + +struct flashdevice flashdevices[BIOS_MAXDEV]; +int flashcount; + +/* + * ****************************************** + * + * flashchip handling + * + * ****************************************** + */ + + +void flash_command (unsigned char *addr, unsigned char command) +#if 1 +{ + flash_writeb(addr, 0x5555, 0xaa); + flash_writeb(addr, 0x2AAA, 0x55); + flash_writeb(addr, 0x5555, command); +} +void fwh_flash_command(unsigned char *addr, unsigned char command) +#endif +{ + flash_writeb(addr, 0x75555, 0xaa); + flash_writeb(addr, 0x72aaa, 0x55); + flash_writeb(addr, 0x75555, command); +} + +#define CFLASH flashdevices[flashcount] +int flash_probe_address(void *address) +{ + int flashnum=0, manufnum=0, sectors=0; + unsigned short flash_id, testflash; + unsigned long flags; +#ifdef DEBUG_PROBING + printk( KERN_DEBUG "BIOS: Probing for flash chip @0x%08lx\n", (unsigned long) address); +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) + save_flags(flags); +#endif + spin_lock_irqsave(&bios_lock, flags); + + testflash= (flash_readb(address, 0))+(flash_readb(address, 1)<<8); + + /* 1st method: Intel, Atmel listen to this.. */ + + flash_command(address, 0x90); + udelay(20); + + flash_id = (flash_readb(address, 0))+(flash_readb(address, 1)<<8); + +#ifdef DEBUG_PROBING + printk (KERN_DEBUG "BIOS: testflash[%04x] flash_id[%04x]\n", + testflash, flash_id); +#endif + + /* 2nd method: Winbond (I think this is Jedec standard) */ + + if (flash_id==testflash) { +#ifdef DEBUG_PROBING + printk (KERN_DEBUG "BIOS: Trying 2nd ID method.\n"); +#endif + flash_command(address, 0xf0); /* Reset */ + udelay(20); + + flash_command(address, 0x80); + flash_command(address, 0x60); + udelay(20); + + flash_id = (flash_readb(address, 0))+(flash_readb(address, 1)<<8); +#ifdef DEBUG_PROBING + printk (KERN_DEBUG "BIOS: testflash[%04x] flash_id[%04x]\n", + testflash, flash_id); +#endif + } + + /* 3rd Method: Some Winbonds seem to want this */ + + if (flash_id==testflash) { +#ifdef DEBUG_PROBING + printk (KERN_DEBUG "BIOS: Trying 3rd ID method.\n"); +#endif + flash_command(address, 0xf0); /* Reset again */ + udelay(20); + + flash_command(address, 0x80); + flash_command(address, 0x20); + udelay(20); + + flash_id = (flash_readb(address, 0))+(flash_readb(address, 1)<<8); +#ifdef DEBUG_PROBING + printk (KERN_DEBUG "BIOS: testflash[%04x] flash_id[%04x]\n", + testflash, flash_id); +#endif + } + + if (flash_id==0x7f7f && flash_readb(address, 0x100)==0x1c) { + /* We have an Eon flashchip. They keep their + * device id at 0x101 instead of 0x1 + */ + printk(KERN_INFO "BIOS: Eon flash device detected\n"); + flash_id=(flash_readb(address, 0x1))+(flash_readb(address, 0x101)<<8); + } + + flash_command(address, 0xf0); + udelay(20); + + spin_unlock_irqrestore(&bios_lock, flags); + + if (flash_id==testflash) return 0; /* Nothing found :-( */ + + while (flashchips[flashnum].id!=0) { + if (flash_id==flashchips[flashnum].id) + break; + flashnum++; + } + + while (manufacturers[manufnum].id!=0) { + if ((flash_id&0xff)==manufacturers[manufnum].id) + break; + manufnum++; + } + + if (flashchips[flashnum].id) { + while (flashchips[flashnum].sectors[sectors]<flashchips[flashnum].size) + sectors++; + } + + if (flashcount >= BIOS_MAXDEV) { + printk(KERN_DEBUG "BIOS: Too many flash devices found.\n"); + return -1; + } + + CFLASH.flashnum = flashnum; + CFLASH.manufnum = manufnum; + CFLASH.id = flash_id; + CFLASH.size = (flashchips[flashnum].size<<10); + CFLASH.sectors = sectors; + CFLASH.open_mode= 0; + CFLASH.open_cnt = 0; + + return 1; +} + +void flash_probe_area(unsigned long romaddr, unsigned long romsize, + int map_always) +{ + unsigned long probeaddr; + unsigned char *mapped; + + mapped=ioremap(romaddr, romsize); + + devices[flashdevices[currflash].idx].activate(); + + probeaddr=(unsigned long)mapped; + + while ( probeaddr < (unsigned long)mapped + romsize - 0x5555 ) { + if ( flash_probe_address ((void *)probeaddr) != 1) { + probeaddr += 4*1024; + continue; + } + + CFLASH.offset = probeaddr-(unsigned long)mapped; + CFLASH.mapped = (unsigned long)mapped; + CFLASH.physical = romaddr+CFLASH.offset; + + printk( KERN_INFO "BIOS: flash device with size " + "%dk (ID 0x%04x) found.\n", + CFLASH.size >> 10, CFLASH.id); + + printk( KERN_INFO "BIOS: physical address " + "0x%08lx (va=0x%08lx+0x%lx).\n", + CFLASH.physical, (unsigned long)CFLASH.mapped, + CFLASH.offset); + + if (flashchips[CFLASH.flashnum].flags&f_fwh_compl) { + unsigned long t_lk; + unsigned int i=7; + printk(KERN_INFO "BIOS: FWH compliant " + "chip detected.\n"); + for (t_lk=0xffb80002; t_lk<=0xffbf0002; t_lk+=0x10000) + { + printk(KERN_INFO "Lock register %d " + "(0x%08lx): 0x%x\n", + i, t_lk, (unsigned int) + (readb(phys_to_virt(t_lk)))); + i--; + } + } + flashcount++; + currflash++; +#ifdef MULTIPLE_FLASH + probeaddr += flashdevices[flashcount-1].size; + flashdevices[flashcount].mapped=flashdevices[flashcount-1].mapped; + flashdevices[flashcount].data=flashdevices[flashcount-1].data; + continue; +#else + break; +#endif + } + + /* We might want to always map the memory + * region in certain cases + */ + + if (map_always) { + CFLASH.flashnum = 0; + CFLASH.manufnum = 0; + CFLASH.id = 0; + CFLASH.size = romsize; + CFLASH.sectors = 0; + CFLASH.open_mode= 0; + CFLASH.open_cnt = 0; + CFLASH.offset = 0; + CFLASH.mapped = (unsigned long)mapped; + CFLASH.physical = romaddr; + printk( KERN_INFO "BIOS: rom device with size " + "%dk registered.\n", CFLASH.size >> 10); + flashcount++; currflash++; + return; + } + + /* We found nothing in this area, so let's unmap it again */ + + if (flashcount && flashdevices[flashcount-1].mapped != (unsigned long)mapped) + iounmap(mapped); + + devices[flashdevices[currflash].idx].deactivate(); +} + +#undef CFLASH + +void flash_program (unsigned char *addr) +{ + flash_command(addr, 0xa0); +} + +void flash_program_atmel (unsigned char *addr) +{ + flash_command(addr, 0x80); + flash_command(addr, 0x20); +} + +int flash_erase (unsigned char *addr, unsigned int flashnum) +{ + flash_command(addr, 0x80); + flash_command(addr, 0x10); + udelay(80); + return flash_ready_toggle(addr, 0); +} + +int flash_erase_sectors (unsigned char *addr, unsigned int flashnum, unsigned int startsec, unsigned int endsec) +{ + unsigned int sector; + + if (!(flashchips[flashnum].flags & f_slow_sector_erase)) { + flash_command(addr, 0x80); + + if (flashchips[flashnum].flags&f_fwh_compl) { + flash_writeb(addr, 0x75555,0xaa); + flash_writeb(addr, 0x72aaa,0x55); + } else { + flash_writeb(addr, 0x5555,0xaa); + flash_writeb(addr, 0x2aaa,0x55); + } + + for (sector=startsec; sector <= endsec; sector++) { + flash_writeb (addr, flashchips[flashnum].sectors[sector]*1024, 0x30); + } + + udelay(150); // 80 max normally, wait 150usec to be sure +#if 0 + if (flashchips[flashnum].flags&f_fwh_compl) +#endif + return flash_ready_toggle(addr, flashchips[flashnum].sectors[sector-1]*1024); +#if 0 + else + return flash_ready_poll(addr, flashchips[flashnum].sectors[sector-1]*1024, 0xff); +#endif + } + + /* sectors must be sent the sector erase command for every sector */ + for (sector=startsec; sector <= endsec; sector++) { + flash_command(addr, 0x80); + if (flashchips[flashnum].flags&f_fwh_compl) { + flash_writeb(addr, 0x75555,0xaa); + flash_writeb(addr, 0x72aaa,0x55); + } else { + flash_writeb(addr, 0x5555,0xaa); + flash_writeb(addr, 0x2aaa,0x55); + } + + flash_writeb(addr, flashchips[flashnum].sectors[sector]*1024, 0x30); + udelay(150); +#if 0 + if (flashchips[flashnum].flags&f_fwh_compl) +#endif + flash_ready_toggle(addr, flashchips[flashnum].sectors[sector] *1024); +#if 0 + else + flash_ready_poll(addr, flashchips[flashnum].sectors[sector]*1024, 0xff); +#endif + } + + return 0; + +} + +/* waiting for the end of programming/erasure by using the toggle method. + * As long as there is a programming procedure going on, bit 6 of the last + * written byte is toggling it's state with each consecutive read. + * The toggling stops as soon as the procedure is completed. + * This function returns 0 if everything is ok, 1 if an error occured + * while programming was in progress. + */ + +int flash_ready_toggle (unsigned char *addr, unsigned int offset) +{ + unsigned long int timeout=0; + unsigned char oldflag, flag; + int loop=1; + + oldflag=flash_readb(addr, offset) & 0x40; + + while (loop && (timeout<0x7fffffff)) { + flag=flash_readb(addr, offset) & 0x40; + + if (flag == oldflag) + loop=0; + + oldflag=flag; + timeout++; + } + + if (loop) { + printk(KERN_DEBUG "BIOS: operation timed out (Toggle)\n"); + return 1; + } + + return 0; +} + +/* This functions is similar to the above one. While a programming + * procedure is going on, bit 7 of the last written data byte is + * inverted. When the procedure is completed, bit 7 contains the + * correct data value + */ + +int flash_ready_poll (unsigned char *addr, unsigned int offset, unsigned char data) +{ + unsigned long int timeout=0; + unsigned char flag; + + flag=flash_readb(addr, offset); + + while ( ( flag & 0x80) != ( data & 0x80)) { + if ( ( flag & 0x80 ) == ( data & 0x80 ) ) { +#ifdef DBGTIMEOUT + printk(KERN_DEBUG "BIOS: Timeout value (EOT Polling) %ld\n",timeout); +#endif + return 0; + } + flag=flash_readb(addr, offset); + if (timeout++>12800) { // 10 times more than usual. + printk(KERN_ERR "BIOS: EOT Polling timed out at 0x%08x." + " Try again or increase max. timeout.\n",offset); + return 1; + } + if ((flag & 0x80) == ( data & 0x80)) { + flag=flash_readb(addr, offset); + } + } +#ifdef DBGTIMEOUT + printk(KERN_DEBUG "BIOS: Timeout value (EOT Polling) %ld\n",timeout); +#endif + + flag=flash_readb(addr, offset); + if ( ( flag & 0x80 ) == ( data & 0x80 ) ) return 0; else return 1; +} + + + +void iflash_program_byte (unsigned char *addr, unsigned int offset, unsigned char data) +{ + unsigned long int timeout=0; + unsigned char flag; + + flash_writeb (addr, offset, 0x40); + flash_writeb (addr, offset, data); + + flash_writeb (addr, offset, 0x70); /* Read Status */ + do { + flag=flash_readb (addr, offset); + if (timeout++>100) { // usually 2 or 3 :-) + printk(KERN_ERR "BIOS: Intel programming timed out at" + "0x%08x. Try again or increase max. timeout.\n",offset); + return; + } + } while ((flag&0x80) != 0x80); + +#ifdef DBGTIMEOUT + printk (KERN_DEBUG"BIOS: Timeout value (Intel byte program) %ld\n",timeout); +#endif + + if (flag&0x18) { + flash_writeb (addr, offset, 0x50); /* Reset Status Register */ + printk (KERN_ERR "BIOS: Error occured, please repeat write operation. (intel)\n"); + } + + flash_writeb (addr, offset, 0xff); +} + + + +int iflash_erase_sectors (unsigned char *addr, unsigned int flashnum, unsigned int startsec, unsigned int endsec) +{ + unsigned long int timeout; + unsigned int sector, offset=0; + unsigned char flag; + + for (sector=startsec; sector<=endsec; sector++) { + offset=(flashchips[flashnum].sectors[sector]*1024); + flash_writeb (addr, offset, 0x20); + flash_writeb (addr, offset, 0xd0); + + flash_writeb (addr, offset, 0x70); /* Read Status */ + timeout=0; + do { + flag=flash_readb (addr, offset); + if (timeout++>1440000) { // usually 144000 + printk(KERN_ERR "BIOS: Intel sector erase timed out at 0x%08x. Try again or increase max. timeout.\n",offset); + return 1; + } + } while ((flag&0x80) != 0x80); + +#ifdef DBGTIMEOUT + printk (KERN_DEBUG "BIOS: Timeout value (Intel sector erase) %ld\n",timeout); +#endif + + if (flag&0x28) { + flash_writeb (addr, offset, 0x50); + flash_writeb (addr, offset, 0xff); + return 1; /* Error! */ + } + } + + flash_writeb (addr, offset, 0xff); + return 0; +} + + + +unsigned char flash_readb(unsigned char *addr, unsigned int offset) +{ +#if defined(__alpha__) + if (flashdevices[currflash].data==(void *)0xfff80000) { + if (offset<0x80000) + outb(0x00,0x800); + else { + outb(0x01, 0x800); + offset-=0x80000; + } + } +#endif + return readb(addr+offset); +} + + + +void flash_writeb(unsigned char *addr, unsigned int offset, unsigned char data) +{ +#if defined(__alpha__) + if (flashdevices[currflash].data==(void *)0xfff80000) { + if (offset<0x80000) + outb(0x00,0x800); + else { + outb(0x01, 0x800); + offset-=0x80000; + } + } +#endif +/* + printk(KERN_DEBUG "BIOS: writing 0x%02x to 0x%lx+0x%x\n", + data,bios,offset); + */ + writeb(data,addr+offset); +} diff --git a/qemu/roms/openbios/utils/devbios/programming.h b/qemu/roms/openbios/utils/devbios/programming.h new file mode 100644 index 000000000..3ad104e86 --- /dev/null +++ b/qemu/roms/openbios/utils/devbios/programming.h @@ -0,0 +1,73 @@ +/* + * OpenBIOS - free your system! + * ( firmware/flash device driver for Linux ) + * + * programming.h - prototypes for flash device programming + * + * This program is part of a free implementation of the IEEE 1275-1994 + * Standard for Boot (Initialization Configuration) Firmware. + * + * Copyright (C) 1998-2004 Stefan Reinauer, <stepan@openbios.org> + * + * 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; version 2 of the License. + * + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + * + */ + +/* Addresses */ +#define ADDR_MANUFACTURER 0x0000 +#define ADDR_DEVICE_ID 0x0001 +#define ADDR_SECTOR_LOCK 0x0002 +#define ADDR_HANDSHAKE 0x0003 + +#define ADDR_UNLOCK_1 0x5555 +#define ADDR_UNLOCK_2 0x2AAA +#define ADDR_COMMAND 0x5555 + +/* Commands */ +#define CMD_UNLOCK_DATA_1 0xAA +#define CMD_UNLOCK_DATA_2 0x55 +#define CMD_MANUFACTURER_UNLOCK_DATA 0x90 +#define CMD_UNLOCK_BYPASS_MODE 0x20 +#define CMD_PROGRAM_UNLOCK_DATA 0xA0 +#define CMD_RESET_DATA 0xF0 +#define CMD_SECTOR_ERASE_UNLOCK_DATA 0x80 +#define CMD_SECTOR_ERASE_UNLOCK_DATA_2 0x30 +#define CMD_ERASE_DATA 0x10 +#define CMD_UNLOCK_SECTOR 0x60 + +extern int flashcount; + +void flash_command(unsigned char *addr, unsigned char command); + +void flash_program (unsigned char *addr); +void flash_program_atmel (unsigned char *addr); + +int flash_ready_toggle (unsigned char *addr, unsigned int offset); +int flash_ready_poll (unsigned char *addr, unsigned int offset, unsigned char data); + +int flash_erase (unsigned char *addr, unsigned int flashnum); +int flash_erase_sectors (unsigned char *addr, unsigned int flashnum, + unsigned int startsec, unsigned int endsec); + +void iflash_program_byte (unsigned char *addr, unsigned int offset, unsigned char data); +int iflash_erase_sectors (unsigned char *addr, unsigned int flashnum, unsigned int startsec, unsigned int endsec); + +unsigned char flash_readb(unsigned char *addr, unsigned int offset); +void flash_writeb(unsigned char *addr, unsigned int offset, unsigned char data); + + +int flash_probe_address(void *address); +void flash_probe_area(unsigned long romaddr, unsigned long romsize, + int map_always); + diff --git a/qemu/roms/openbios/utils/dist/debian/changelog b/qemu/roms/openbios/utils/dist/debian/changelog new file mode 100644 index 000000000..d3c96a56f --- /dev/null +++ b/qemu/roms/openbios/utils/dist/debian/changelog @@ -0,0 +1,6 @@ +openbios (0.1-1) unstable; urgency=low + + * Initial Debian version. + + -- Patrick Mauritz <oxygene@studentenbude.ath.cx> Mon, 22 Jul 2002 23:24:56 +0200 + diff --git a/qemu/roms/openbios/utils/dist/debian/control b/qemu/roms/openbios/utils/dist/debian/control new file mode 100644 index 000000000..5bf02d765 --- /dev/null +++ b/qemu/roms/openbios/utils/dist/debian/control @@ -0,0 +1,16 @@ +Source: openbios +Maintainer: Patrick Mauritz <oxygene@studentenbude.ath.cx> +Section: devel +Priority: optional +Standards-Version: 3.5.2 +Build-Depends: grep-dctrl, yada (>= 0.9.9) + +Package: openbios +Architecture: any +Depends: ${openbios:Depends} +Description: OpenBIOS - OpenFirmware development tools + It contains: + - toke: tokenizer for fcode programs + - detok: decompiler for fcode programs + - paflof: (yet) incomplete forth environment which will be + _the_ core of OpenBIOS diff --git a/qemu/roms/openbios/utils/dist/debian/packages b/qemu/roms/openbios/utils/dist/debian/packages new file mode 100644 index 000000000..5dc56c01f --- /dev/null +++ b/qemu/roms/openbios/utils/dist/debian/packages @@ -0,0 +1,45 @@ +Source: openbios +Section: devel +Priority: optional +Maintainer: Patrick Mauritz <oxygene@studentenbude.ath.cx> +Packager: Patrick Mauritz <oxygene@studentenbude.ath.cx> +Standards-Version: 3.5.2 +Upstream-Source: <URL:http://www.openbios.net> +Home-Page: <URL:http://www.openbios.net> +Description: OpenBIOS - OpenFirmware development tools +Copyright: GPL + Copyright 2001-2002 Stefan Reinauer, Segher Boessenkool +Major-Changes: + First release +Build: sh + CC=gcc + CFLAGS="-O2 -Wall" + cd toke; make; strip toke; cd .. + cd detok; make; strip detok; cd .. + cd paflof; make; strip paflof; cd .. + find toke/examples -name .cvsignore | xargs rm -f +Clean: sh + cd toke; make clean; cd .. + cd detok; make clean; cd .. + cd paflof; make clean; cd .. + +Package: openbios +Architecture: any +Depends: [/usr/bin/*] +Description: OpenBIOS - OpenFirmware development tools + It contains: + - toke: tokenizer for fcode programs + - detok: decompiler for fcode programs + - paflof: (yet) incomplete forth environment which will be + _the_ core of OpenBIOS +Install: sh + mkdir -p $ROOT/usr/bin + mkdir -p $ROOT/usr/share/openbios + mkdir -p $ROOT/usr/share/doc/packages/openbios + cp toke/toke $ROOT/usr/bin + cp detok/detok $ROOT/usr/bin + cp paflof/paflof $ROOT/usr/bin + cp -a toke/examples $ROOT/usr/share/doc/openbios + cp -a forth $ROOT/usr/share/openbios + cp toke/README $ROOT/usr/share/doc/openbios/README.toke + cp detok/README $ROOT/usr/share/doc/openbios/README.detok diff --git a/qemu/roms/openbios/utils/dist/debian/rules b/qemu/roms/openbios/utils/dist/debian/rules new file mode 100755 index 000000000..6bf532691 --- /dev/null +++ b/qemu/roms/openbios/utils/dist/debian/rules @@ -0,0 +1,189 @@ +#! /usr/bin/make -f +# Generated automatically from debian/packages +# by yada v0.9.9, of Tue, 07 Dec 1999 +# Modified by Piotr Roszatycki <dexter@debian.org>, Mon, 1 Oct 2001 13:14:11 +0200 + +DEB_HOST_GNU_CPU := $(shell dpkg-architecture -qDEB_HOST_GNU_CPU) +DEB_HOST_GNU_TYPE := $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE) +DEB_HOST_GNU_SYSTEM := $(shell dpkg-architecture -qDEB_HOST_GNU_SYSTEM) + +DEB_BUILD_GNU_CPU := $(shell dpkg-architecture -qDEB_BUILD_GNU_CPU) +DEB_BUILD_GNU_TYPE := $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE) +DEB_BUILD_GNU_SYSTEM := $(shell dpkg-architecture -qDEB_BUILD_GNU_SYSTEM) + +VERSION:=$(shell LC_ALL=C dpkg-parsechangelog | sed -ne 's/^Version: *\([^2]*\)/\1/p') + +SHELL=/bin/bash + +.PHONY: default +default: + @echo "Specify a target:"; \ + echo " build compile the package"; \ + echo " binary make all binary packages"; \ + echo " binary-arch make all architecture-dependent binary packages"; \ + echo " binary-indep make all architecture-independent binary packages"; \ + echo " clean clean up the source package"; \ + echo; \ + echo " depends check build-time dependencies"; \ + echo " install-tree compile the package and create the install trees"; \ + echo " clean-install-tree clean up only under debian/"; \ + echo + +# Check build dependencies and conflicts + +.PHONY: depends +depends: chmod-yada debian/depends-stamp +debian/depends-stamp: + @echo 'Checking build conflicts and dependencies; just a minute...' + @echo -n 'grep-dctrl...'; v=$$(grep-status -X -F Package 'grep-dctrl' | grep Version | head -1 | sed -e 's/^Version: //'); \ + if test ! "$$v"; then echo -n 'grep-dctrl (virtual package)...'; v=$$(grep-status -e -F Provides '(^grep-dctrl, |, grep-dctrl$$|^grep-dctrl$$)' | grep Version | head -1 | sed -e 's/^Version: //'); fi; \ + if test "$$v"; then \ + exit 0; \ + fi; \ + echo 'Build depends on `grep-dctrl'\'' (any version), which is not satisfied' | fmt; exit 1 + @echo -n 'yada...'; v=$$(grep-status -X -F Package 'yada' | grep Version | head -1 | sed -e 's/^Version: //'); \ + if test ! "$$v"; then echo -n 'yada (virtual package)...'; v=$$(grep-status -e -F Provides '(^yada, |, yada$$|^yada$$)' | grep Version | head -1 | sed -e 's/^Version: //'); fi; \ + if test "$$v"; then \ + if dpkg --compare-versions "$$v" '>=' '0.9.9'; then \ + exit 0; \ + fi; \ + fi; \ + echo 'Build depends on `yada'\'' (version >= 0.9.9), which is not satisfied' | fmt; exit 1 + @echo + @echo 'Conflicts and dependencies all satisfied!' + touch debian/depends-stamp + +# Build the package and prepare the install tree + +.PHONY: build-only build +build-only: debian/build-stamp +build: chmod-yada build-only + +# Make sure these rules and the control file are up-to-date + +.PHONY: rules control +rules: debian/rules +debian/rules: $(shell which yada) debian/packages + $(shell which yada) rebuild rules + +control: debian/control +debian/control: $(shell which yada) debian/packages + $(shell which yada) rebuild control + +debian/build-stamp: debian/depends-stamp + @[ -f $(shell which yada) -a -f debian/rules ] + @umask 022 \ + && export PACKAGE="openbios" \ + && export VERSION="$(VERSION)" \ + && export DEB_HOST_GNU_CPU="$(DEB_HOST_GNU_CPU)" \ + && export DEB_HOST_GNU_TYPE="$(DEB_HOST_GNU_TYPE)" \ + && export DEB_HOST_GNU_SYSTEM="$(DEB_HOST_GNU_SYSTEM)" \ + && export DEB_BUILD_GNU_CPU="$(DEB_BUILD_GNU_CPU)" \ + && export DEB_BUILD_GNU_TYPE="$(DEB_BUILD_GNU_TYPE)" \ + && export DEB_BUILD_GNU_SYSTEM="$(DEB_BUILD_GNU_SYSTEM)" \ + && (\ + echo -E 'eval "yada () { perl $$(which yada) \"\$$@\"; }"; set -e; set -v';\ + echo -E 'CC=gcc';\ + echo -E 'CFLAGS="-O2 -Wall"';\ + echo -E 'cd toke; make; strip toke; cd ..';\ + echo -E 'cd detok; make; strip detok; cd ..';\ + echo -E 'cd paflof; make; strip paflof; cd ..';\ + echo -E 'find toke/examples -name .cvsignore | xargs rm -f') | /bin/sh + touch debian/build-stamp + +.PHONY: install-tree +install-tree: chmod-yada install-tree-any +install-tree-any: \ + debian/tmp-openbios/DEBIAN/control + +debian/tmp-openbios/DEBIAN/control: debian/build-stamp debian/control + rm -rf debian/tmp-openbios + umask 022 && install -d debian/tmp-openbios/DEBIAN + install -d debian/tmp-openbios/usr/share/doc/openbios + umask 022; $(shell which yada) generate copyright \ + >debian/tmp-openbios/usr/share/doc/openbios/copyright + install -m 644 -p debian/changelog \ + debian/tmp-openbios/usr/share/doc/openbios/changelog.Debian + @umask 022 \ + && export PACKAGE="openbios" \ + && export ROOT="$$(pwd)/debian/tmp-openbios" \ + && export CONTROL="$$(pwd)/debian/tmp-openbios/DEBIAN" \ + && export VERSION="$(VERSION)" \ + && export DEB_HOST_GNU_CPU="$(DEB_HOST_GNU_CPU)" \ + && export DEB_HOST_GNU_TYPE="$(DEB_HOST_GNU_TYPE)" \ + && export DEB_HOST_GNU_SYSTEM="$(DEB_HOST_GNU_SYSTEM)" \ + && export DEB_BUILD_GNU_CPU="$(DEB_BUILD_GNU_CPU)" \ + && export DEB_BUILD_GNU_TYPE="$(DEB_BUILD_GNU_TYPE)" \ + && export DEB_BUILD_GNU_SYSTEM="$(DEB_BUILD_GNU_SYSTEM)" \ + && (\ + echo -E 'eval "yada () { perl $$(which yada) \"\$$@\"; }"; set -e; set -v';\ + echo -E 'mkdir -p $$ROOT/usr/bin';\ + echo -E 'mkdir -p $$ROOT/usr/share/openbios';\ + echo -E 'mkdir -p $$ROOT/usr/share/doc/packages/openbios';\ + echo -E 'cp toke/toke $$ROOT/usr/bin';\ + echo -E 'cp detok/detok $$ROOT/usr/bin';\ + echo -E 'cp paflof/paflof $$ROOT/usr/bin';\ + echo -E 'cp -a toke/examples $$ROOT/usr/share/doc/openbios';\ + echo -E 'cp -a forth $$ROOT/usr/share/openbios';\ + echo -E 'cp toke/README $$ROOT/usr/share/doc/openbios/README.toke';\ + echo -E 'cp detok/README $$ROOT/usr/share/doc/openbios/README.detok') | /bin/sh + LD_LIBRARY_PATH="debian/tmp-openbios/lib:debian/tmp-openbios/usr/lib:$$LD_LIBRARY_PATH" dpkg-shlibdeps -pshlibs:openbios -dDepends debian/tmp-openbios/usr/bin/* + $(shell which yada) compress openbios + $(shell which yada) generate maintscripts openbios + find debian/tmp-openbios -type f -print \ + | sed -n 's/^debian\/tmp-openbios\(\/etc\/.*\)$$/\1/p' \ + > debian/tmp-openbios/DEBIAN/conffiles + if test ! -s debian/tmp-openbios/DEBIAN/conffiles; then rm -f debian/tmp-openbios/DEBIAN/conffiles; fi + $(shell which yada) rebuild control + $(shell which yada) generate substvars openbios + umask 022 && dpkg-gencontrol -isp -popenbios -Pdebian/tmp-openbios + +# Build package files + +.PHONY: binary binary-arch binary-indep +binary: binary-arch binary-indep +binary-arch: chmod-yada binary-arch-any + +.PHONY: binary-arch-any +binary-arch-any: \ + binary-package-openbios +binary-indep: chmod-yada + +.PHONY: binary-package-openbios +binary-package-openbios: check-root debian/tmp-openbios/DEBIAN/control + @[ -f $(shell which yada) -a -f debian/rules ] + chown -R 0.0 debian/tmp-openbios + chmod -R u=rwX,go=rX debian/tmp-openbios + @if [ -d debian/tmp-openbios/usr/doc/openbios ]; then \ + echo "*** Yada warning: /usr/doc/openbios should be /usr/share/doc/openbios";\ + fi + dpkg-deb --build debian/tmp-openbios .. + +.PHONY: check-root +check-root: + @[ `id -u` = 0 ] || (echo "You must be root to do this!"; false) + +.PHONY: chmod-yada +chmod-yada: + @if [ -f debian/yada -a ! -x debian/yada ]; then \ + chmod +x debian/yada; \ + fi + +# Clean up afterwards + +.PHONY: clean clean-install-tree clean-build +clean: chmod-yada clean-install-tree clean-build debian/control debian/rules + +clean-build: + @[ -f $(shell which yada) -a -f debian/rules ] + rm -f debian/build-stamp debian/depends-stamp + @umask 022 && (\ + echo -E 'eval "yada () { perl $$(which yada) \"\$$@\"; }"; set -e; set -v';\ + echo -E 'cd toke; make clean; cd ..';\ + echo -E 'cd detok; make clean; cd ..';\ + echo -E 'cd paflof; make clean; cd ..') | /bin/sh + +clean-install-tree: chmod-yada debian/rules + @[ -f $(shell which yada) -a -f debian/rules ] + rm -f debian/install-tree-stamp + rm -rf debian/tmp* debian/files* debian/substvars diff --git a/qemu/roms/openbios/utils/dist/openbios.spec b/qemu/roms/openbios/utils/dist/openbios.spec new file mode 100644 index 000000000..fcce7ab46 --- /dev/null +++ b/qemu/roms/openbios/utils/dist/openbios.spec @@ -0,0 +1,61 @@ +# +# spec file for package openbios +# + +Name: openbios +Version: 0.1 +Release: 0 +Summary: OpenBIOS development utilities +License: GNU General Public License (GPL) - all versions, Other License(s), see package +Group: Development/Tools/Other +Autoreqprov: on +# Scripts and programs +Source0: OpenBIOS.tar.bz2 +BuildRoot: %{_tmppath}/%{name}-%{version}-build + +%description +This package contains the OpenBIOS development utilities. + +There are +* toke - an IEEE 1275-1994 compliant FCode tokenizer +* detok - an IEEE 1275-1994 compliant FCode detokenizer +* paflof - a forth kernel running in user space +* an fcode bytecode evaluator running in paflof + +See /usr/share/doc/packages/openbios for details and examples. + +Authors: +-------- + Stefan Reinauer <stepan@openbios.net> + Segher Boessenkool <segher@openbios.net> + +%prep +%setup -n openbios + +%build +( cd toke; make; strip toke ) +( cd detok; make; strip detok ) +( cd paflof; make; strip paflof ) +( find toke/examples -name .cvsignore | xargs rm -f ) + +%install +rm -rf ${RPM_BUILD_ROOT} +mkdir -p ${RPM_BUILD_ROOT}/usr/bin/ +mkdir -p ${RPM_BUILD_ROOT}/usr/share/openbios +mkdir -p ${RPM_BUILD_ROOT}/usr/share/doc/packages/openbios +cp toke/toke ${RPM_BUILD_ROOT}/usr/bin/ +cp detok/detok ${RPM_BUILD_ROOT}/usr/bin/ +cp paflof/paflof ${RPM_BUILD_ROOT}/usr/bin/ +cp -a toke/examples ${RPM_BUILD_ROOT}/usr/share/doc/packages/openbios +cp -a forth ${RPM_BUILD_ROOT}/usr/share/openbios +cp toke/README ${RPM_BUILD_ROOT}/usr/share/doc/packages/openbios/README.toke +cp detok/README ${RPM_BUILD_ROOT}/usr/share/doc/packages/openbios/README.detok + +%files +/usr/bin +/usr/share/openbios +%doc /usr/share/doc/packages/openbios + +%changelog -n openbios +* Mon Jul 22 2002 - stepan@suse.de +- initial version diff --git a/qemu/roms/openbios/utils/iso/README b/qemu/roms/openbios/utils/iso/README new file mode 100644 index 000000000..9211bc058 --- /dev/null +++ b/qemu/roms/openbios/utils/iso/README @@ -0,0 +1,5 @@ +The files in this directory are packed into the ISO image created with + + $ make runiso + + diff --git a/qemu/roms/openbios/utils/iso/boot/grub/README b/qemu/roms/openbios/utils/iso/boot/grub/README new file mode 100644 index 000000000..07ba5bb56 --- /dev/null +++ b/qemu/roms/openbios/utils/iso/boot/grub/README @@ -0,0 +1 @@ +stage2_eltorito is part of grub and therefore (C) by the FSF. diff --git a/qemu/roms/openbios/utils/iso/boot/grub/menu.lst b/qemu/roms/openbios/utils/iso/boot/grub/menu.lst new file mode 100644 index 000000000..33e96d3a2 --- /dev/null +++ b/qemu/roms/openbios/utils/iso/boot/grub/menu.lst @@ -0,0 +1,7 @@ +timeout 0 +default 0 +hiddenmenu +title openbios +kernel (cd)/openbios.multiboot +module (cd)/openbios-x86.dict +boot diff --git a/qemu/roms/openbios/utils/iso/boot/grub/stage2_eltorito b/qemu/roms/openbios/utils/iso/boot/grub/stage2_eltorito Binary files differnew file mode 100644 index 000000000..32b87dd48 --- /dev/null +++ b/qemu/roms/openbios/utils/iso/boot/grub/stage2_eltorito diff --git a/qemu/roms/openbios/utils/ofclient/Makefile b/qemu/roms/openbios/utils/ofclient/Makefile new file mode 100644 index 000000000..f3c515964 --- /dev/null +++ b/qemu/roms/openbios/utils/ofclient/Makefile @@ -0,0 +1,14 @@ +PROGRAM := ofclient +OBJECTS := of1275.o of1275_io.o ofclient.o +CC := gcc +CFLAGS := -m32 -fpic -fno-builtin-strlen -Os +LDFLAGS := -melf_i386 -s -N -Ttext 0x200000 -e _start + +$(PROGRAM): $(OBJECTS) + $(LD) $(LDFLAGS) -Map $(PROGRAM).map -o $(PROGRAM) $(OBJECTS) + +clean: + rm -f $(OBJECTS) + +distclean: clean + rm -f $(PROGRAM) $(PROGRAM).map diff --git a/qemu/roms/openbios/utils/ofclient/README b/qemu/roms/openbios/utils/ofclient/README new file mode 100644 index 000000000..785f6ec2d --- /dev/null +++ b/qemu/roms/openbios/utils/ofclient/README @@ -0,0 +1,4 @@ +This is an example program using the openfirmware client +interface on x86. The same program can be compiled on ppc. + + diff --git a/qemu/roms/openbios/utils/ofclient/endian.h b/qemu/roms/openbios/utils/ofclient/endian.h new file mode 100644 index 000000000..4d20e7171 --- /dev/null +++ b/qemu/roms/openbios/utils/ofclient/endian.h @@ -0,0 +1,18 @@ + +#define __bswap32(x) \ + ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \ + (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24)) + +static int little_endian(void) +{ + static short one=1; + return *(char *)&one==1; +} + +static unsigned int ntohl(unsigned int netlong) +{ + if(little_endian()) + return __bswap32(netlong); + + return netlong; +} diff --git a/qemu/roms/openbios/utils/ofclient/of1275.c b/qemu/roms/openbios/utils/ofclient/of1275.c new file mode 100644 index 000000000..ff0778279 --- /dev/null +++ b/qemu/roms/openbios/utils/ofclient/of1275.c @@ -0,0 +1,451 @@ + +#include "of1275.h" +#include "endian.h" +static int (*of1275_server) (void *) = (int (*)(void *)) -1; + +_start(void *residual_data_structure, + void *program_entry_point, + int (*client_interface_handler) (void *), void *args, int argslen) +{ + int status; + of1275_server = client_interface_handler; + status = main(); + of1275_exit(status); +} + +/* 6.3.2.1 Client interface */ + + +int of1275_test(const char *name, int *missing) +{ + int result; + static of1275_test_service s; + s.service = "test"; + s.n_args = 1; + s.n_returns = 1; + s.name = name; + result = of1275_server(&s); + *missing = s.missing; + return result; +} + + +/* 6.3.2.2 Device tree */ + + +int of1275_peer(int phandle, int *sibling_phandle) +{ + int result; + static of1275_peer_service s; + s.service = "peer"; + s.n_args = 1; + s.n_returns = 1; + s.phandle = phandle; + result = of1275_server(&s); + *sibling_phandle = s.sibling_phandle; + return result; +} + +int of1275_child(int phandle, int *child_phandle) +{ + int result; + static of1275_child_service s; + s.service = "child"; + s.n_args = 1; + s.n_returns = 1; + s.phandle = phandle; + result = of1275_server(&s); + *child_phandle = s.child_phandle; + return result; +} + +int of1275_parent(int phandle, int *parent_phandle) +{ + int result; + static of1275_parent_service s; + s.service = "parent"; + s.n_args = 1; + s.n_returns = 1; + s.phandle = phandle; + result = of1275_server(&s); + *parent_phandle = s.parent_phandle; + return result; +} + +int of1275_instance_to_package(int ihandle, int *phandle) +{ + int result; + static of1275_instance_to_package_service s; + s.service = "instance-to-package"; + s.n_args = 1; + s.n_returns = 1; + s.ihandle = ihandle; + result = of1275_server(&s); + *phandle = s.phandle; + return result; +} + +int of1275_getproplen(int phandle, const char *name, int *proplen) +{ + int result; + static of1275_getproplen_service s; + s.service = "getproplen"; + s.n_args = 2; + s.n_returns = 1; + s.phandle = phandle; + s.name = name; + result = of1275_server(&s); + *proplen = s.proplen; + return result; +} + +int +of1275_getprop(int phandle, const char *name, void *buf, int buflen, + int *size) +{ + int result; + static of1275_getprop_service s; + s.service = "getprop"; + s.n_args = 4; + s.n_returns = 1; + s.phandle = phandle; + s.name = name; + s.buf = buf; + s.buflen = buflen; + result = of1275_server(&s); + *size = s.size; + return result; +} + +int +of1275_nextprop(int phandle, const char *previous, void *buf, int *flag) +{ + int result; + static of1275_nextprop_service s; + s.service = "nextprop"; + s.n_args = 3; + s.n_returns = 1; + s.phandle = phandle; + s.previous = previous; + s.buf = buf; + result = of1275_server(&s); + *flag = s.flag; + return result; +} + +int +of1275_setprop(int phandle, const char *name, void *buf, int len, + int *size) +{ + int result; + static of1275_setprop_service s; + s.service = "setprop"; + s.n_args = 4; + s.n_returns = 1; + s.phandle = phandle; + s.name = name; + s.buf = buf; + s.len = len; + result = of1275_server(&s); + *size = s.size; + return result; +} + +int +of1275_canon(const char *device_specifier, void *buf, int buflen, + int *length) +{ + int result; + static of1275_canon_service s; + s.service = "canon"; + s.n_args = 3; + s.n_returns = 1; + s.device_specifier = device_specifier; + s.buf = buf; + s.buflen = buflen; + result = of1275_server(&s); + *length = s.length; + return result; +} + +int of1275_finddevice(const char *device_specifier, int *phandle) +{ + int result; + static of1275_finddevice_service s; + s.service = "finddevice"; + s.n_args = 1; + s.n_returns = 1; + s.device_specifier = device_specifier; + result = of1275_server(&s); + *phandle = s.phandle; + return result; +} + +int +of1275_instance_to_path(int ihandle, void *buf, int buflen, int *length) +{ + int result; + static of1275_instance_to_path_service s; + s.service = "instance-to-path"; + s.n_args = 3; + s.n_returns = 1; + s.ihandle = ihandle; + s.buf = buf; + s.buflen = buflen; + result = of1275_server(&s); + *length = s.length; + return result; +} + +int of1275_package_to_path(int phandle, void *buf, int buflen, int *length) +{ + int result; + static of1275_package_to_path_service s; + s.service = "package-to-path"; + s.n_args = 3; + s.n_returns = 1; + s.phandle = phandle; + s.buf = buf; + s.buflen = buflen; + result = of1275_server(&s); + *length = s.length; + return result; +} + +/* int of1275_call_method(const char *method, int ihandle, ...); */ + + +/* 6.3.2.3 Device I/O */ + + +int of1275_open(const char *device_specifier, int *ihandle) +{ + int result; + static of1275_open_service s; + s.service = "open"; + s.n_args = 1; + s.n_returns = 1; + s.device_specifier = device_specifier; + result = of1275_server(&s); + *ihandle = s.ihandle; + return result; +} + +int of1275_close(int ihandle) +{ + int result; + static of1275_close_service s; + s.service = "close"; + s.n_args = 1; + s.n_returns = 0; + s.ihandle = ihandle; + result = of1275_server(&s); + return result; +} + +int of1275_read(int ihandle, void *addr, int len, int *actual) +{ + int result; + static of1275_read_service s; + s.service = "read"; + s.n_args = 3; + s.n_returns = 1; + s.ihandle = ihandle; + s.addr = addr; + s.len = len; + result = of1275_server(&s); + *actual = s.actual; + return result; +} + +int of1275_write(int ihandle, void *addr, int len, int *actual) +{ + int result; + static of1275_write_service s; + s.service = "write"; + s.n_args = 3; + s.n_returns = 1; + s.ihandle = ihandle; + s.addr = addr; + s.len = len; + result = of1275_server(&s); + *actual = s.actual; + return result; +} + +int of1275_seek(int ihandle, int pos_hi, int pos_lo, int *status) +{ + int result; + static of1275_seek_service s; + s.service = "seek"; + s.n_args = 3; + s.n_returns = 1; + s.ihandle = ihandle; + s.pos_hi = pos_hi; + s.pos_lo = pos_lo; + result = of1275_server(&s); + *status = s.status; + return result; +} + + +/* 6.3.2.4 Memory */ + + +int of1275_claim(void *virt, int size, int align, void **baseaddr) +{ + int result; + static of1275_claim_service s; + s.service = "claim"; + s.n_args = 3; + s.n_returns = 1; + s.virt = virt; + s.size = size; + s.align = align; + result = of1275_server(&s); + *baseaddr = s.baseaddr; + return result; +} + +int of1275_release(void *virt, int size) +{ + int result; + static of1275_release_service s; + s.service = "release"; + s.n_args = 2; + s.n_returns = 0; + s.virt = virt; + s.size = size; + result = of1275_server(&s); + return result; +} + + +/* 6.3.2.5 Control transfer */ + + +int of1275_boot(const char *bootspec) +{ + int result; + static of1275_boot_service s; + s.service = "boot"; + s.n_args = 1; + s.n_returns = 0; + s.bootspec = bootspec; + result = of1275_server(&s); + return result; +} + +int of1275_enter(void) +{ + int result; + static of1275_enter_service s; + s.service = "enter"; + s.n_args = 0; + s.n_returns = 0; + result = of1275_server(&s); + return result; +} + +int of1275_exit(int status) +{ + int result; + static of1275_exit_service s; + s.service = "exit"; + s.n_args = 1; + s.n_returns = 0; + s.status = status; + result = of1275_server(&s); + return result; +} + +/* int of1275_chain(void *virt, int size, void *entry, void *args, int len); */ + + +/* 6.3.2.6 User interface */ + + +/* int of1275_interpret(const char *arg, ...); */ + +int of1275_set_callback(void *newfunc, void **oldfunc) +{ + int result; + static of1275_set_callback_service s; + s.service = "set-callback"; + s.n_args = 1; + s.n_returns = 1; + s.newfunc = newfunc; + result = of1275_server(&s); + *oldfunc = s.oldfunc; + return result; +} + +int of1275_set_symbol_lookup(void *sym_to_value, void *value_to_sym) +{ + int result; + static of1275_set_symbol_lookup_service s; + s.service = "set-symbol-lookup"; + s.n_args = 2; + s.n_returns = 0; + s.sym_to_value = sym_to_value; + s.value_to_sym = s.value_to_sym; + result = of1275_server(&s); + return result; +} + + +/* 6.3.2.7 Time */ + +int of1275_milliseconds(int *ms) +{ + int result; + static of1275_milliseconds_service s; + s.service = "milliseconds"; + s.n_args = 0; + s.n_returns = 1; + result = of1275_server(&s); + *ms = s.ms; + return result; +} + + +int of_find_integer_property(const char *device, const char *property) +{ + int phandle; + int integer; + int size; + /* find the device's phandle */ + if (of1275_finddevice(device, &phandle) < 0) { + //printk("of1275: no such device '%s'\n", device); + exit(1); + } + /* find the device's property */ + of1275_getprop(phandle, property, &integer, + sizeof(integer), &size); + if (size < sizeof(integer)) { + //printk("of1275: unknown integer property '%s'\n", property); + exit(1); + } + return ntohl(integer); +} + +void +of_find_string_property(const char *device, + const char *property, + char *string, int sizeof_string) +{ + int phandle; + int size; + /* find the device's phandle */ + if (of1275_finddevice(device, &phandle) < 0) { + //printk("of1275: no such device '%s'\n", device); + exit(1); + } + + /* find the device's property */ + of1275_getprop(phandle, property, string, sizeof_string, &size); + if (size == 0 || size >= sizeof_string) { + //printk("of1275: unknown string property '%s'\n", property); + exit(1); + } +} diff --git a/qemu/roms/openbios/utils/ofclient/of1275.h b/qemu/roms/openbios/utils/ofclient/of1275.h new file mode 100644 index 000000000..a73bb19a8 --- /dev/null +++ b/qemu/roms/openbios/utils/ofclient/of1275.h @@ -0,0 +1,437 @@ +/* OpenFirmware interface */ + + +/* 6.3.2.1 Client interface */ + + +typedef struct _of1275_test_service { + const char *service; + int n_args; + int n_returns; + /*in */ + const char *name; + /*out */ + int missing; +} of1275_test_service; + +int of1275_test(const char *name, int *missing); + + +/* 6.3.2.2 Device tree */ + + +typedef struct _of1275_peer_service { + const char *service; + int n_args; + int n_returns; + /*in */ + int phandle; + /*out */ + int sibling_phandle; +} of1275_peer_service; + +int of1275_peer(int phandle, int *sibling_phandle); + + +typedef struct _of1275_child_service { + const char *service; + int n_args; + int n_returns; + /*in */ + int phandle; + /*out */ + int child_phandle; +} of1275_child_service; + +int of1275_child(int phandle, int *child_phandle); + + +typedef struct _of1275_parent_service { + const char *service; + int n_args; + int n_returns; + /*in */ + int phandle; + /*out */ + int parent_phandle; +} of1275_parent_service; + +int of1275_child(int phandle, int *parent_phandle); + + +typedef struct _of1275_instance_to_package_service { + const char *service; + int n_args; + int n_returns; + /*in */ + int ihandle; + /*out */ + int phandle; +} of1275_instance_to_package_service; + +int of1275_instance_to_package(int ihandle, int *phandle); + + +typedef struct _of1275_getproplen_service { + const char *service; + int n_args; + int n_returns; + /*in */ + int phandle; + const char *name; + /*out */ + int proplen; +} of1275_getproplen_service; + +int of1275_getproplen(int phandle, const char *name, int *proplen); + + +typedef struct _of1275_getprop_service { + const char *service; + int n_args; + int n_returns; + /*in */ + int phandle; + const char *name; + void *buf; + int buflen; + /*out */ + int size; +} of1275_getprop_service; + +int of1275_getprop(int phandle, const char *name, void *buf, int buflen, + int *size); + + +typedef struct _of1275_nextprop_service { + const char *service; + int n_args; + int n_returns; + /*in */ + int phandle; + const char *previous; + void *buf; + /*out */ + int flag; +} of1275_nextprop_service; + +int of1275_nextprop(int phandle, const char *previous, void *buf, + int *flag); + + +typedef struct _of1275_setprop_service { + const char *service; + int n_args; + int n_returns; + /*in */ + int phandle; + const char *name; + void *buf; + int len; + /*out */ + int size; +} of1275_setprop_service; + +int of1275_setprop(int phandle, const char *name, void *buf, int len, + int *size); + + +typedef struct _of1275_canon_service { + const char *service; + int n_args; + int n_returns; + /*in */ + const char *device_specifier; + void *buf; + int buflen; + /*out */ + int length; +} of1275_canon_service; + +int of1275_canon(const char *device_specifier, void *buf, int buflen, + int *length); + + +typedef struct _of1275_finddevice_service { + const char *service; + int n_args; + int n_returns; + /*in */ + const char *device_specifier; + /*out */ + int phandle; +} of1275_finddevice_service; + +int of1275_finddevice(const char *device_specifier, int *phandle); + + +typedef struct _of1275_instance_to_path_service { + const char *service; + int n_args; + int n_returns; + /*in */ + int ihandle; + void *buf; + int buflen; + /*out */ + int length; +} of1275_instance_to_path_service; + +int of1275_instance_to_path(int ihandle, void *buf, int buflen, + int *length); + + +typedef struct _of1275_package_to_path_service { + const char *service; + int n_args; + int n_returns; + /*in */ + int phandle; + void *buf; + int buflen; + /*out */ + int length; +} of1275_package_to_path_service; + +int of1275_package_to_path(int phandle, void *buf, int buflen, + int *length); + + +typedef struct _of1275_call_method_service { + const char *service; + int n_args; + int n_returns; + /*in */ + const char *method; + int ihandle; + /*... */ + int args[0]; +} of1275_call_method_service; + +int of1275_call_method(const char *method, int ihandle, ...); + + +/* 6.3.2.3 Device I/O */ + + +typedef struct _of1275_open_service { + const char *service; + int n_args; + int n_returns; + /*in */ + const char *device_specifier; + /*out */ + int ihandle; +} of1275_open_service; + +int of1275_open(const char *device_specifier, int *ihandle); + + +typedef struct _of1275_close_service { + const char *service; + int n_args; + int n_returns; + /*in */ + int ihandle; + /*out */ +} of1275_close_service; + +int of1275_close(int ihandle); + + +typedef struct _of1275_read_service { + const char *service; + int n_args; + int n_returns; + /*in */ + int ihandle; + void *addr; + int len; + /*out */ + int actual; +} of1275_read_service; + +int of1275_read(int ihandle, void *addr, int len, int *actual); + + +typedef struct _of1275_write_service { + const char *service; + int n_args; + int n_returns; + /*in */ + int ihandle; + void *addr; + int len; + /*out */ + int actual; +} of1275_write_service; + +int of1275_write(int ihandle, void *addr, int len, int *actual); + + +typedef struct _of1275_seek_service { + const char *service; + int n_args; + int n_returns; + /*in */ + int ihandle; + int pos_hi; + int pos_lo; + /*out */ + int status; +} of1275_seek_service; + +int of1275_seek(int ihandle, int pos_hi, int pos_lo, int *status); + + +/* 6.3.2.4 Memory */ + + +typedef struct _of1275_claim_service { + const char *service; + int n_args; + int n_returns; + /*in */ + void *virt; + int size; + int align; + /*out */ + void *baseaddr; +} of1275_claim_service; + +int of1275_claim(void *virt, int size, int align, void **baseaddr); + + +typedef struct _of1275_release_service { + const char *service; + int n_args; + int n_returns; + /*in */ + void *virt; + int size; + int align; + /*out */ +} of1275_release_service; + +int of1275_release(void *virt, int size); + + +/* 6.3.2.5 Control transfer */ + + +typedef struct _of1275_boot_service { + const char *service; + int n_args; + int n_returns; + /*in */ + const char *bootspec; + /*out */ +} of1275_boot_service; + +int of1275_boot(const char *bootspec); + + +typedef struct _of1275_enter_service { + const char *service; + int n_args; + int n_returns; + /*in */ + /*out */ +} of1275_enter_service; + +int of1275_enter(void); + +typedef struct _of1275_exit_service { + const char *service; + int n_args; + int n_returns; + /*in */ + int status; + /*out */ +} of1275_exit_service; + +int of1275_exit(int status); + + +typedef struct _of1275_chain_service { + const char *service; + int n_args; + int n_returns; + /*in */ + void *virt; + int size; + void *entry; + void *args; + int len; + /*out */ +} of1275_chain_service; + +int of1275_chain(void *virt, int size, void *entry, void *args, int len); + + +/* 6.3.2.6 User interface */ + + +typedef struct _of1275_interpret_service { + const char *service; + int n_args; + int n_returns; + /*in */ + const char *cmd; + int args[0]; + /*... */ + /*out */ + /*... */ +} of1275_interpret_service; + +int of1275_interpret(const char *arg, ...); + + +typedef struct _of1275_set_callback_service { + const char *service; + int n_args; + int n_returns; + /*in */ + void *newfunc; + /*out */ + void *oldfunc; +} of1275_set_callback_service; + +int of1275_set_callback(void *newfunc, void **oldfunc); + + +typedef struct _of1275_set_symbol_lookup_service { + const char *service; + int n_args; + int n_returns; + /*in */ + void *sym_to_value; + void *value_to_sym; + /*out */ +} of1275_set_symbol_lookup_service; + +int of1275_set_symbol_lookup(void *sym_to_value, void *value_to_sym); + + +/* 6.3.2.7 Time */ + + +typedef struct _of1275_milliseconds_service { + const char *service; + int n_args; + int n_returns; + /*in */ + /*out */ + int ms; +} of1275_milliseconds_service; + +int of1275_milliseconds(int *ms); + + +/* Common and useful utilities */ + + +int of_find_integer_property(const char *path, const char *property); + +void of_find_string_property(const char *path, const char *property, + char *string, int sizeof_string); diff --git a/qemu/roms/openbios/utils/ofclient/of1275_io.c b/qemu/roms/openbios/utils/ofclient/of1275_io.c new file mode 100644 index 000000000..25d1132c3 --- /dev/null +++ b/qemu/roms/openbios/utils/ofclient/of1275_io.c @@ -0,0 +1,51 @@ +#include "of1275.h" + +static int of_write_initialized = 0; +static int stdout_ihandle = 0; +static int of_read_initialized = 0; +static int stdin_ihandle = 0; + +int write(int fd, char *buf, int len) +{ + int actual; + + if (fd != 1 && fd != 2) { + // printk("write: bad id %x\n", fd); + exit(1); + } + + if (!of_write_initialized) { + stdout_ihandle = + of_find_integer_property("/chosen", "stdout"); + // printk("stdout_ihandle: %x\n",stdout_ihandle); + of_write_initialized = 1; + } + + of1275_write(stdout_ihandle, buf, len, &actual); + return actual; +} + +int read(int fd, char *buf, int len) +{ + int actual; + + if (fd != 0) { + // printk("write: bad id %x\n", fd); + exit(1); + } + + if (!of_read_initialized) { + stdin_ihandle = + of_find_integer_property("/chosen", "stdin"); + of_read_initialized = 1; + } + + of1275_read(stdin_ihandle, buf, len, &actual); + return actual; +} + +exit(int status) +{ + of1275_exit(status); + while (1); +} diff --git a/qemu/roms/openbios/utils/ofclient/ofclient.c b/qemu/roms/openbios/utils/ofclient/ofclient.c new file mode 100644 index 000000000..94214c6ca --- /dev/null +++ b/qemu/roms/openbios/utils/ofclient/ofclient.c @@ -0,0 +1,9 @@ +#include "of1275.h" + +int write(int fd, char *buf, int len); + +int main(void) +{ + write(1, "Hello world!\n", 13 ); + return 0; +} |