initial import of openbios--main--1.0--patch-26

git-svn-id: svn://coreboot.org/openbios/openbios-devel@1 f158a5a8-5612-0410-a976-696ce0be7e32
This commit is contained in:
Stefan Reinauer
2006-04-26 15:08:19 +00:00
commit 5c9eb9b45b
522 changed files with 83237 additions and 0 deletions

341
COPYING Normal file
View File

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

1895
Documentation/ChangeLog.arch Normal file

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

11
Documentation/kernel/TODO Normal file
View File

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

View File

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

View File

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

View File

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

59
Makefile Normal file
View File

@ -0,0 +1,59 @@
ARCH= $(shell cat rules.xml |grep ^ARCH|cut -d\= -f2|tr -d \ )
HOSTARCH=$(shell config/scripts/archname)
ODIR=obj-$(ARCH)
all: info build
info:
@echo "Building OpenBIOS on $(HOSTARCH) for $(ARCH)"
clean:
@echo -n "Cleaning up..."
@rm -rf $(ODIR) forth.dict.core
@echo " ok"
directories: clean
@echo -n "Initializing build tree..."
@mkdir $(ODIR)
@mkdir -p $(ODIR)/target/include
@mkdir -p $(ODIR)/target/arch/unix
@mkdir -p $(ODIR)/target/arch/$(ARCH)
@mkdir -p $(ODIR)/target/arch/ppc/briq # no autodetection of those..
@mkdir -p $(ODIR)/target/arch/ppc/pearpc
@mkdir -p $(ODIR)/target/arch/ppc/mol
@mkdir -p $(ODIR)/target/arch/x86/xbox
@mkdir -p $(ODIR)/target/kernel
@mkdir -p $(ODIR)/target/modules
@mkdir -p $(ODIR)/target/fs/grubfs
@mkdir -p $(ODIR)/target/fs/hfs
@mkdir -p $(ODIR)/target/fs/hfsplus
@mkdir -p $(ODIR)/target/drivers
@mkdir -p $(ODIR)/target/libc
@mkdir -p $(ODIR)/host/include
@mkdir -p $(ODIR)/host/kernel
@mkdir -p $(ODIR)/host/toke
@mkdir -p $(ODIR)/forth
@ln -s $(PWD)/include/$(ARCH) $(ODIR)/target/include/asm
@#compile the host binary with target settings instead
@#ln -s $(PWD)/include/$(HOSTARCH) $(ODIR)/host/include/asm
@echo "ok."
xml: directories
@echo -n "Creating target Makefile..."
@xsltproc config/xml/xinclude.xsl build.xml > $(ODIR)/build-full.xml
@xsltproc config/xml/makefile.xsl $(ODIR)/build-full.xml > $(ODIR)/Makefile
@echo "ok."
@echo -n "Creating config files..."
@xsltproc config/xml/config-c.xsl config.xml > $(ODIR)/host/include/autoconf.h
@xsltproc config/xml/config-c.xsl config.xml > $(ODIR)/target/include/autoconf.h
@xsltproc config/xml/config-forth.xsl config.xml > $(ODIR)/forth/config.fs
@echo "ok."
build: xml
@echo -n "Building..."
@( $(MAKE) -f $(ODIR)/Makefile > $(ODIR)/build.log 2>&1 && echo "ok." ) || \
( echo "error:"; tail -15 $(ODIR)/build.log )
run:
@echo "Running..."
@$(ODIR)/openbios-unix $(ODIR)/openbios-unix.dict

131
README Normal file
View File

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

50
arch/amd64/Kconfig Normal file
View File

@ -0,0 +1,50 @@
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 "modules/Kconfig"
source "drivers/Kconfig"

43
arch/amd64/boot.c Normal file
View File

@ -0,0 +1,43 @@
/*
*
*/
#undef BOOTSTRAP
#include "openbios/config.h"
#include "openbios/bindings.h"
#include "openbios/elfload.h"
#include "openbios/nvram.h"
#include "libc/diskio.h"
#include "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);
struct sys_info sys_info;
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);
}

6
arch/amd64/build.xml Normal file
View File

@ -0,0 +1,6 @@
<build condition="AMD64">
<dictionary name="openbios-amd64" init="openbios" target="forth">
<object source="init.fs"/>
</dictionary>
</build>

26
arch/amd64/builtin.c Normal file
View File

@ -0,0 +1,26 @@
/* 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 "openbios/config.h"
#include <asm/types.h>
#include "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));
}

412
arch/amd64/console.c Normal file
View File

@ -0,0 +1,412 @@
/*
* Copyright (C) 2003, 2004 Stefan Reinauer
*
* See the file "COPYING" for further information about
* the copyright and warranty status of this work.
*/
#include "openbios/config.h"
#include "openbios/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 putchar(int c)
{
#ifdef CONFIG_DEBUG_CONSOLE_SERIAL
serial_putchar(c);
#endif
#ifdef CONFIG_DEBUG_CONSOLE_VGA
video_putchar(c);
#endif
return c;
}
int 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 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
}
#endif // CONFIG_DEBUG_CONSOLE

124
arch/amd64/context.c Normal file
View File

@ -0,0 +1,124 @@
/*
* context switching
* 2003-10 by SONE Takeshi
*/
#include "openbios/config.h"
#include "openbios/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;
}

48
arch/amd64/context.h Normal file
View File

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

65
arch/amd64/defconfig Normal file
View File

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

387
arch/amd64/elfload.c Normal file
View File

@ -0,0 +1,387 @@
/* ELF Boot loader
* As we have seek, this implementation can be straightforward.
* 2003-07 by SONE Takeshi
*/
#include "openbios/config.h"
#include "openbios/kernel.h"
#include "openbios/elf.h"
#include "asm/elf.h"
#include "elf_boot.h"
#include "sys_info.h"
#include "ipchecksum.h"
#include "loadfs.h"
#define printf printk
#define debug printk
extern unsigned int start_elf(unsigned long entry_point, unsigned long param);
extern char _start, _end;
static char *image_name, *image_version;
static void *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 0;
}
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 = 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)
{
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);
file_seek(phdr[i].p_offset);
if (lfile_read(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 = calloc(1, nhdr->n_descsz + 1);
memcpy(image_name, desc, nhdr->n_descsz);
}
if (nhdr->n_type == EIN_PROGRAM_VERSION) {
image_version = 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:
if (buf)
free(buf);
return retval;
}
static int load_segments(Elf_phdr *phdr, int phnum,
unsigned long checksum_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:%#x file:%#x mem:%#x ",
i, phdr[i].p_paddr, phdr[i].p_filesz, phdr[i].p_memsz);
file_seek(phdr[i].p_offset);
debug("loading... ");
if (lfile_read(phys_to_virt(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(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(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(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 const 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);
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);
addr += 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 elf_load(struct sys_info *info, const char *filename, const char *cmdline)
{
Elf_ehdr ehdr;
Elf_phdr *phdr = NULL;
unsigned long phdr_size;
unsigned long checksum_offset;
unsigned short checksum;
Elf_Bhdr *boot_notes = NULL;
int retval = -1;
int image_retval;
image_name = image_version = 0;
if (!file_open(filename))
goto out;
if (lfile_read(&ehdr, sizeof ehdr) != sizeof ehdr) {
debug("Can't read ELF header\n");
retval = LOADER_NOT_SUPPORT;
goto out;
}
if (ehdr.e_ident[EI_MAG0] != ELFMAG0
|| ehdr.e_ident[EI_MAG1] != ELFMAG1
|| ehdr.e_ident[EI_MAG2] != ELFMAG2
|| ehdr.e_ident[EI_MAG3] != ELFMAG3
|| ehdr.e_ident[EI_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)) {
debug("Not a bootable ELF image\n");
retval = LOADER_NOT_SUPPORT;
goto out;
}
phdr_size = ehdr.e_phnum * sizeof *phdr;
phdr = malloc(phdr_size);
file_seek(ehdr.e_phoff);
if (lfile_read(phdr, phdr_size) != phdr_size) {
printf("Can't read program header\n");
goto out;
}
if (!check_mem_ranges(info, phdr, ehdr.e_phnum))
goto out;
checksum_offset = process_image_notes(phdr, ehdr.e_phnum, &checksum);
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))
goto out;
if (checksum_offset) {
if (!verify_image(&ehdr, phdr, ehdr.e_phnum, checksum))
goto out;
}
boot_notes = build_boot_notes(info, cmdline);
//debug("current time: %lu\n", currticks());
debug("entry point is %#x\n", ehdr.e_entry);
printf("Jumping to entry point...\n");
image_retval = start_elf(ehdr.e_entry, virt_to_phys(boot_notes));
// console_init(); FIXME
printf("Image returned with return value %#x\n", image_retval);
retval = 0;
out:
if (phdr)
free(phdr);
if (boot_notes)
free(boot_notes);
if (image_name)
free(image_name);
if (image_version)
free(image_version);
return retval;
}

77
arch/amd64/init.fs Normal file
View File

@ -0,0 +1,77 @@
: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

73
arch/amd64/ldscript Normal file
View File

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

58
arch/amd64/lib.c Normal file
View File

@ -0,0 +1,58 @@
/* 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 "openbios/config.h"
#include "asm/types.h"
#include <stdarg.h>
#include "libc/stdlib.h"
#include "libc/vsprintf.h"
#include "openbios/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]; /* XXX: no buffer overflow protection... */
va_list args;
int i;
va_start(args, fmt);
i=vsprintf(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 */
}

647
arch/amd64/linux_load.c Normal file
View File

@ -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 "openbios/config.h"
#include "openbios/kernel.h"
#include "openbios/bindings.h"
#include "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;
}

46
arch/amd64/loadfs.c Normal file
View File

@ -0,0 +1,46 @@
#include "openbios/config.h"
#include "openbios/kernel.h"
#include "libc/diskio.h"
#include "loadfs.h"
static int load_fd=-1;
int file_open(const char *filename)
{
load_fd=open_io(filename);
/* if(load_fd!=-1) */ seek_io(load_fd, 0);
return load_fd>-1;
}
int lfile_read(void *buf, unsigned long len)
{
int ret;
ret=read_io(load_fd, buf, len);
return ret;
}
int file_seek(unsigned long offset)
{
return seek_io(load_fd, offset);
}
unsigned long file_size(void)
{
llong fpos, fsize;
/* save current position */
fpos=tell(load_fd);
/* go to end of file and get position */
seek_io(load_fd, -1);
fsize=tell(load_fd);
/* go back to old position */
seek_io(load_fd, 0);
seek_io(load_fd, fpos);
return fsize;
}

7
arch/amd64/loadfs.h Normal file
View File

@ -0,0 +1,7 @@
int file_open(const char *filename);
int lfile_read(void *buf, unsigned long len);
int file_seek(unsigned long offset);
unsigned long file_size(void);

125
arch/amd64/multiboot.c Normal file
View File

@ -0,0 +1,125 @@
/* Support for Multiboot */
#include "openbios/config.h"
#include "asm/io.h"
#include "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;
}

96
arch/amd64/multiboot.h Normal file
View File

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

109
arch/amd64/openbios.c Normal file
View File

@ -0,0 +1,109 @@
/* 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 "openbios/config.h"
#include "openbios/bindings.h"
#include "asm/types.h"
#include "dict.h"
#include "openbios/kernel.h"
#include "openbios/stack.h"
#include "sys_info.h"
#include "openbios.h"
#include "relocate.h"
void boot(void);
void ob_ide_init(void);
static char intdict[256 * 1024];
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);
}
void exception(cell no)
{
/* The exception mechanism is used during bootstrap to catch
* build errors. In a running system this is a noop since we
* can't break out to the unix host os anyways.
*/
}
static void
arch_init( void )
{
void setup_timers(void);
modules_init();
#ifdef CONFIG_DRIVER_IDE
setup_timers();
ob_ide_init();
#endif
device_end();
bind_func("platform-boot", boot );
}
int openbios(void)
{
extern struct sys_info sys_info;
#ifdef CONFIG_DEBUG_CONSOLE
#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;
load_dictionary((char *)sys_info.dict_start,
sys_info.dict_end-sys_info.dict_start);
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;
}

29
arch/amd64/openbios.h Normal file
View File

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

22
arch/amd64/plainboot.c Normal file
View File

@ -0,0 +1,22 @@
/* 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 "openbios/config.h"
#include "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;
}

2
arch/amd64/relocate.h Normal file
View File

@ -0,0 +1,2 @@
void relocate(struct sys_info *);

134
arch/amd64/segment.c Normal file
View File

@ -0,0 +1,134 @@
/* Segmentation of the AMD64 architecture.
*
* 2003-07 by SONE Takeshi
*/
#include "openbios/config.h"
#include "openbios/kernel.h"
#include "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

30
arch/amd64/segment.h Normal file
View File

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

116
arch/amd64/switch.S Normal file
View File

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

57
arch/amd64/sys_info.c Normal file
View File

@ -0,0 +1,57 @@
#include "openbios/config.h"
#include "openbios/kernel.h"
#include "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)
{
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);
}

8
arch/build.xml Normal file
View File

@ -0,0 +1,8 @@
<?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"/>
</build>

24
arch/ia64/Kconfig Normal file
View File

@ -0,0 +1,24 @@
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 "modules/Kconfig"
source "drivers/Kconfig"

6
arch/ia64/build.xml Normal file
View File

@ -0,0 +1,6 @@
<build condition="IPF">
<dictionary name="openbios-ia64" init="openbios" target="forth">
<object source="init.fs"/>
</dictionary>
</build>

65
arch/ia64/defconfig Normal file
View File

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

77
arch/ia64/init.fs Normal file
View File

@ -0,0 +1,77 @@
: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

48
arch/ppc/Kconfig Normal file
View File

@ -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 "modules/Kconfig"
source "drivers/Kconfig"

79
arch/ppc/Makefile Normal file
View File

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

32
arch/ppc/Makefile.asm Normal file
View File

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

194
arch/ppc/briq/briq.c Normal file
View File

@ -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 "openbios/config.h"
#include "openbios/kernel.h"
#include "openbios/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]; /* XXX: no buffer overflow protection... */
va_list args;
int i;
va_start(args, fmt);
i=vsprintf(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();
}

115
arch/ppc/briq/briq.fs Normal file
View File

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

24
arch/ppc/briq/briq.h Normal file
View File

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

129
arch/ppc/briq/init.c Normal file
View File

@ -0,0 +1,129 @@
/*
* 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 "openbios/config.h"
#include "openbios/bindings.h"
#include "openbios/nvram.h"
#include "briq/briq.h"
#include "ofmem.h"
#include "openbios-version.h"
extern void unexpected_excep( int vector );
extern void ob_ide_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("briQ panic: Unexpected exception %x\n", vector );
for( ;; )
;
}
void
entry( void )
{
printk("\n");
printk("=============================================================\n");
printk("OpenBIOS %s [%s]\n", OPENBIOS_RELEASE, 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 USE_RTAS
phandle_t ph;
#endif
int autoboot;
devtree_init();
node_methods_init();
nvram_init();
modules_init();
#ifdef CONFIG_DRIVER_PCI
ob_pci_init();
#endif
#ifdef CONFIG_DRIVER_IDE
setup_timers();
ob_ide_init();
#endif
#if USE_RTAS
if( !(ph=find_dev("/rtas")) )
printk("Warning: No /rtas node\n");
else {
ulong size = 0x1000;
while( size < (ulong)of_rtas_end - (ulong)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 );
}

17
arch/ppc/briq/kernel.c Normal file
View File

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

145
arch/ppc/briq/main.c Normal file
View File

@ -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 "openbios/config.h"
#include "openbios/bindings.h"
#include "openbios/elfload.h"
#include "openbios/nvram.h"
#include "libc/diskio.h"
#include "libc/vsprintf.h"
#include "briq/briq.h"
#include "ofmem.h"
static void
transfer_control_to_elf( ulong entry )
{
extern void call_elf( ulong 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( ulong *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",
(ulong)phdr[i].p_vaddr, (ulong)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 };
ulong 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();
}

333
arch/ppc/briq/methods.c Normal file
View File

@ -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 "openbios/config.h"
#include "openbios/bindings.h"
#include "libc/string.h"
#include "briq/briq.h"
#include "ofmem.h"
/************************************************************************/
/* RTAS (run-time abstraction services) */
/************************************************************************/
#ifdef USE_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;
ulong 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( ulong args[], ulong ret[] )
{
#if 0
ulong 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( ulong args[], ulong ret[] )
{
extern unsigned long get_timer_freq();
static ulong mticks=0, usecs=0;
ulong 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 )
{
ulong mode;
int virt = POP();
int phys = ofmem_translate( virt, &mode );
if( phys == -1 ) {
PUSH( 0 );
} else {
PUSH( phys );
PUSH( (int)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 ) = {
{ "claim", ciface_claim },
{ "release", ciface_release },
};
/************************************************************************/
/* init */
/************************************************************************/
void
node_methods_init( void )
{
#ifdef USE_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 );
}

23
arch/ppc/briq/tree.c Normal file
View File

@ -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 "openbios/config.h"
#include "openbios/bindings.h"
void devtree_init( void )
{
fword("init-briq-tree");
}

247
arch/ppc/briq/tree.fs Normal file
View File

@ -0,0 +1,247 @@
\ 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
" 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

42
arch/ppc/briq/vfd.c Normal file
View File

@ -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 "openbios/config.h"
#include "openbios/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;
}

217
arch/ppc/build.xml Normal file
View File

@ -0,0 +1,217 @@
<?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"/>
</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"/>
</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"/>
</dictionary>
<!-- HACK ALERT -->
<executable name="target/include/briq-dict.h" target="target" condition="BRIQ">
<rule><![CDATA[
@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[
$(CC) $$EXTRACFLAGS $(CFLAGS) $(INCLUDES) -c -o $@ arch/ppc/briq/kernel.c
]]></rule>
<external-object source="target/include/briq-dict.h"/>
</executable>
<executable name="target/include/pearpc-dict.h" target="target" condition="PEARPC">
<rule><![CDATA[
@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[
$(CC) $$EXTRACFLAGS $(CFLAGS) $(INCLUDES) -c -o $@ arch/ppc/pearpc/kernel.c
]]></rule>
<external-object source="target/include/pearpc-dict.h"/>
</executable>
<executable name="target/include/mol-dict.h" target="target" condition="MOL">
<rule><![CDATA[
@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[
$(CC) $$EXTRACFLAGS $(CFLAGS) $(INCLUDES) -c -o $@ arch/ppc/mol/kernel.c
]]></rule>
<external-object source="target/include/mol-dict.h"/>
</executable>
<!-- END OF HACK ALERT -->
<library name="briq" target="target" type="static" condition="BRIQ">
<object source="misc.S">
<rule><![CDATA[
$(CPP) -D__ASSEMBLY__ $(INCLUDES) $< | $(M4) -s $(M4_NO_GNU) | tr ';' '\n' > $@.s
$(AS) $@.s $(AS_FLAGS) -o $@
]]></rule>
</object>
<object source="ofmem.c"/>
<object source="briq/briq.c" flags="-Iarch/ppc"/>
<object source="briq/init.c" flags="-Iarch/ppc"/>
<external-object source="target/arch/ppc/briq/kernel.o"/>
<object source="briq/main.c" flags="-Iarch/ppc"/>
<object source="briq/methods.c" flags="-Iarch/ppc"/>
<object source="briq/tree.c" flags="-Iarch/ppc"/>
<object source="briq/vfd.c" flags="-Iarch/ppc"/>
</library>
<library name="pearpc" target="target" type="static" condition="PEARPC">
<object source="misc.S">
<rule><![CDATA[
$(CPP) -D__ASSEMBLY__ $(INCLUDES) $< | $(M4) -s $(M4_NO_GNU) | tr ';' '\n' > $@.s
$(AS) $@.s $(AS_FLAGS) -o $@
]]></rule>
</object>
<object source="ofmem.c"/>
<object source="pearpc/pearpc.c" flags="-Iarch/ppc"/>
<object source="pearpc/init.c" flags="-Iarch/ppc"/>
<external-object source="target/arch/ppc/pearpc/kernel.o"/>
<object source="pearpc/main.c" flags="-Iarch/ppc"/>
<object source="pearpc/methods.c" flags="-Iarch/ppc"/>
<object source="pearpc/tree.c" flags="-Iarch/ppc"/>
<object source="pearpc/vfd.c" flags="-Iarch/ppc"/>
<!-- taken from mol: generalize -->
<object source="pearpc/console.c" flags="-Iarch/ppc"/>
</library>
<library name="mol" target="target" type="static" condition="MOL">
<object source="misc.S">
<rule><![CDATA[
$(CPP) -D__ASSEMBLY__ $(INCLUDES) $< | $(M4) -s $(M4_NO_GNU) | tr ';' '\n' > $@.s
$(AS) $@.s $(AS_FLAGS) -o $@
]]></rule>
</object>
<object source="ofmem.c"/>
<object source="mol/init.c" flags="-Iarch/ppc"/>
<object source="mol/main.c" flags="-Iarch/ppc"/>
<object source="mol/mol.c" flags="-Iarch/ppc"/>
<object source="mol/console.c" flags="-Iarch/ppc"/>
<object source="mol/osi-blk.c" flags="-Iarch/ppc"/>
<object source="mol/osi-scsi.c" flags="-Iarch/ppc"/>
<object source="mol/pseudodisk.c" flags="-Iarch/ppc"/>
<object source="mol/methods.c" flags="-Iarch/ppc"/>
<object source="mol/prom.c" flags="-Iarch/ppc"/>
<object source="mol/tree.c" flags="-Iarch/ppc"/>
<external-object source="target/arch/ppc/mol/kernel.o"/>
</library>
<executable name="openbios-briq.elf" target="target" condition="BRIQ">
<rule>
$(LD) -g -Ttext=0x01e01000 -Bstatic $^ $(shell $(CC) -print-libgcc-file-name) -o $@
$(NM) $@ | sort > $(ODIR)/openbios-briq.syms
cp $@ $@.nostrip
$(STRIP) $@
</rule>
<object source="start.S">
<rule><![CDATA[
$(CPP) -D__ASSEMBLY__ $(INCLUDES) $< | $(M4) -s $(M4_NO_GNU) | tr ';' '\n' > $@.s
$(AS) $@.s $(AS_FLAGS) -o $@
]]></rule>
</object>
<object source="timebase.S">
<rule><![CDATA[
$(CPP) -D__ASSEMBLY__ $(INCLUDES) $< | $(M4) -s $(M4_NO_GNU) | tr ';' '\n' > $@.s
$(AS) $@.s $(AS_FLAGS) -o $@
]]></rule>
</object>
<external-object source="libbriq.a"/>
<external-object source="libbootstrap.a"/>
<external-object source="libmodules.a"/>
<external-object source="libdrivers.a"/>
<external-object source="liblibc.a"/>
<external-object source="libfs.a"/>
</executable>
<executable name="openbios-pearpc.elf" target="target" condition="PEARPC">
<rule>
$(LD) -g -Ttext=0x01e01000 -Bstatic $^ $(shell $(CC) -print-libgcc-file-name) -o $@
$(NM) $@ | sort > $(ODIR)/openbios-pearpc.syms
cp $@ $@.nostrip
$(STRIP) $@
</rule>
<object source="start.S">
<rule><![CDATA[
$(CPP) -D__ASSEMBLY__ $(INCLUDES) $< | $(M4) -s $(M4_NO_GNU) | tr ';' '\n' > $@.s
$(AS) $@.s $(AS_FLAGS) -o $@
]]></rule>
</object>
<object source="timebase.S">
<rule><![CDATA[
$(CPP) -D__ASSEMBLY__ $(INCLUDES) $< | $(M4) -s $(M4_NO_GNU) | tr ';' '\n' > $@.s
$(AS) $@.s $(AS_FLAGS) -o $@
]]></rule>
</object>
<external-object source="libpearpc.a"/>
<external-object source="libbootstrap.a"/>
<external-object source="libmodules.a"/>
<external-object source="libdrivers.a"/>
<external-object source="liblibc.a"/>
<external-object source="libfs.a"/>
</executable>
<executable name="openbios-mol.elf" target="target" condition="MOL">
<rule>
$(LD) -g -Ttext=0x01e01000 -Bstatic $^ $(shell $(CC) -print-libgcc-file-name) -o $@
$(NM) $@ | sort > $(ODIR)/openbios-mol.syms
cp $@ $@.nostrip
$(STRIP) $@
</rule>
<object source="start.S">
<rule><![CDATA[
$(CPP) -D__ASSEMBLY__ $(INCLUDES) $< | $(M4) -s $(M4_NO_GNU) | tr ';' '\n' > $@.s
$(AS) $@.s $(AS_FLAGS) -o $@
]]></rule>
</object>
<external-object source="libmol.a"/>
<external-object source="libbootstrap.a"/>
<external-object source="libmodules.a"/>
<external-object source="libdrivers.a"/>
<external-object source="liblibc.a"/>
<external-object source="libfs.a"/>
</executable>
</build>

48
arch/ppc/defconfig Normal file
View File

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

106
arch/ppc/kernel.c Normal file
View File

@ -0,0 +1,106 @@
/*
* 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 "openbios/config.h"
#include "dict.h"
#include "openbios/bindings.h"
#include "openbios/stack.h"
#include "openbios/kernel.h"
#include "libc/string.h"
#include "kernel.h"
#define MEMORY_SIZE (256*1024) /* 256K ram for hosted system */
#define DICTIONARY_SIZE (512*1024) /* 128K for the dictionary */
extern unsigned char *dict;
extern cell dicthead;
static ucell *memory;
/************************************************************************/
/* F U N C T I O N S */
/************************************************************************/
void
exception( int errcode )
{
/* no-op */
}
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) );
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;
}

41
arch/ppc/kernel.h Normal file
View File

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

76
arch/ppc/misc.S Normal file
View File

@ -0,0 +1,76 @@
/*
* 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
*
*/
changequote([[[[[,]]]]]) [[[[[ /* shield includes from m4-expansion */
#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

76
arch/ppc/mmutypes.h Normal file
View File

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

32
arch/ppc/mol/console.c Normal file
View File

@ -0,0 +1,32 @@
/*
* 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 "openbios/config.h"
#include "openbios/bindings.h"
#include "libc/diskio.h"
#include "osi_calls.h"
#include "ofmem.h"
#include "mol/mol.h"
#include "boothelper_sh.h"
#include "video_sh.h"
#define openbios_GetFBInfo(x) OSI_GetFBInfo(x)
#include "../../../modules/video.c"
#include "../../../modules/console.c"

112
arch/ppc/mol/init.c Normal file
View File

@ -0,0 +1,112 @@
/*
* 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 "openbios/config.h"
#include "openbios/bindings.h"
#include "openbios/nvram.h"
#include "mol/mol.h"
#include "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( ;; )
;
}
void
entry( void )
{
printk("\n");
printk("=============================================================\n");
printk("OpenBIOS %s [%s]\n", OPENBIOS_RELEASE, 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();
modules_init();
pseudodisk_init();
osiblk_init();
osiscsi_init();
init_video();
if( (ph=prom_find_device("/rtas")) == -1 )
printk("Warning: No /rtas node\n");
else {
ulong size = 0x1000;
while( size < (ulong)of_rtas_end - (ulong)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 );
}

17
arch/ppc/mol/kernel.c Normal file
View File

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

369
arch/ppc/mol/main.c Normal file
View File

@ -0,0 +1,369 @@
/*
* 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 "openbios/config.h"
#include "openbios/bindings.h"
#include "openbios/elfload.h"
#include "openbios/nvram.h"
#include "libc/diskio.h"
#include "libc/vsprintf.h"
#include "mol/mol.h"
#include "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( ulong entry )
{
extern void call_elf( ulong entry );
printk("Starting ELF boot loader\n");
call_elf( entry );
fatal_error("call_elf returned unexpectedly\n");
}
static int
load_elf_rom( ulong *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",
(ulong)phdr[i].p_vaddr, (ulong)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;
ulong 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);
((ulong*)(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;
ulong 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 ulong 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 ulong
load_newworld_rom( int fd )
{
int lszz_offs, lszz_size;
ulong 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++ ) {
sprintf( 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( (ulong)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 };
ulong 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();
}

475
arch/ppc/mol/methods.c Normal file
View File

@ -0,0 +1,475 @@
/*
* 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 "openbios/config.h"
#include "openbios/bindings.h"
#include "libc/string.h"
#include "mol/mol.h"
#include "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;
ulong 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();
char *s = malloc( len + 1 );
strncpy_nopad( s, addr, len );
s[len]=0;
/* printk( "%s", s ); */
console_draw_str( s );
free( s );
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 uchar 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 uchar 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( ulong args[], ulong ret[] )
{
#if 0
ulong 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( ulong args[], ulong ret[] )
{
static ulong mticks=0, usecs=0;
ulong 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 )
{
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 )
{
ulong mode;
int virt = POP();
int phys = ofmem_translate( virt, &mode );
if( phys == -1 ) {
PUSH( 0 );
} else {
PUSH( phys );
PUSH( (int)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 ) = {
{ "claim", ciface_claim },
{ "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 );
}

166
arch/ppc/mol/mol.c Normal file
View File

@ -0,0 +1,166 @@
/*
* 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 "openbios/config.h"
#include "openbios/kernel.h"
#include "openbios/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]; /* XXX: no buffer overflow protection... */
va_list args;
int i;
va_start(args, fmt);
i=vsprintf(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 );
}

107
arch/ppc/mol/mol.fs Normal file
View File

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

44
arch/ppc/mol/mol.h Normal file
View File

@ -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, ulong color );
/* console.c */
extern int console_draw_str( const char *str );
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 */

119
arch/ppc/mol/osi-blk.c Normal file
View File

@ -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 "openbios/config.h"
#include "openbios/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 );
}

271
arch/ppc/mol/osi-scsi.c Normal file
View File

@ -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 "openbios/config.h"
#include "openbios/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( (uint)prelen > sizeof(prebuf) || (uint)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 );
}

177
arch/ppc/mol/prom.c Normal file
View File

@ -0,0 +1,177 @@
/*
* 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 "openbios/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 );
}

47
arch/ppc/mol/prom.h Normal file
View File

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

178
arch/ppc/mol/pseudodisk.c Normal file
View File

@ -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 "openbios/config.h"
#include "openbios/bindings.h"
#include "osi_calls.h"
#include "libc/string.h"
#include "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 );
}

165
arch/ppc/mol/tree.c Normal file
View File

@ -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 "openbios/config.h"
#include "openbios/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");
}

104
arch/ppc/mol/tree.fs Normal file
View File

@ -0,0 +1,104 @@
: 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

705
arch/ppc/ofmem.c Normal file
View File

@ -0,0 +1,705 @@
/*
* 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 "openbios/config.h"
#include "openbios/bindings.h"
#include "libc/string.h"
#include "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( ulong code_base, ulong code_size, ulong 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 */
typedef struct alloc_desc {
struct alloc_desc *next;
int size; /* size (including) this struct */
} alloc_desc_t;
typedef struct mem_range {
struct mem_range *next;
ulong start;
ulong size;
} range_t;
typedef struct trans {
struct trans *next;
ulong virt; /* chain is sorted by virt */
ulong size;
ulong phys;
int mode;
} translation_t;
static struct {
char *next_malloc;
alloc_desc_t *mfree; /* list of free malloc blocks */
range_t *phys_range;
range_t *virt_range;
translation_t *trans; /* this is really a translation_t */
} ofmem;
/************************************************************************/
/* OF private allocations */
/************************************************************************/
void *
malloc( int size )
{
alloc_desc_t *d, **pp;
char *ret;
if( !size )
return NULL;
if( !ofmem.next_malloc )
ofmem.next_malloc = (char*)OF_MALLOC_BASE;
if( size & 3 )
size += 4 - (size & 3);
size += sizeof(alloc_desc_t);
/* 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 ) {
ret = (char*)*pp + sizeof(alloc_desc_t);
memset( ret, 0, (**pp).size - sizeof(alloc_desc_t) );
*pp = (**pp).next;
return ret;
}
if( (ulong)ofmem.next_malloc + size > HASH_BASE ) {
printk("out of malloc memory (%x)!\n", size );
return NULL;
}
d = (alloc_desc_t*) ofmem.next_malloc;
ofmem.next_malloc += size;
d->next = NULL;
d->size = size;
ret = (char*)d + sizeof(alloc_desc_t);
memset( ret, 0, size - sizeof(alloc_desc_t) );
return ret;
}
void
free( void *ptr )
{
alloc_desc_t **pp, *d;
/* it is legal to free NULL pointers (size zero allocations) */
if( !ptr )
return;
d = (alloc_desc_t*)(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 *
realloc( void *ptr, size_t size )
{
alloc_desc_t *d = (alloc_desc_t*)(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;
}
/************************************************************************/
/* debug */
/************************************************************************/
#if 0
static void
print_range( range_t *r, char *str )
{
printk("--- Range %s ---\n", str );
for( ; r; r=r->next )
printk("%08lx - %08lx\n", r->start, r->start + r->size -1 );
printk("\n");
}
static void
print_phys_range()
{
print_range( ofmem.phys_range, "phys" );
}
static void
print_virt_range()
{
print_range( ofmem.virt_range, "virt" );
}
static void
print_trans( void )
{
translation_t *t = ofmem.trans;
printk("--- Translations ---\n");
for( ; t; t=t->next )
printk("%08lx -> %08lx [size %lx]\n", t->virt, t->phys, t->size );
printk("\n");
}
#endif
/************************************************************************/
/* misc */
/************************************************************************/
static inline int
def_memmode( ulong phys )
{
/* XXX: Guard bit not set as it should! */
if( phys < 0x80000000 || phys >= 0xffc00000 )
return 0x02; /*0xa*/ /* wim GxPp */
return 0x6a; /* WIm GxPp, I/O */
}
/************************************************************************/
/* client interface */
/************************************************************************/
static int
is_free( ulong ea, ulong 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_( ulong ea, ulong 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( ulong ea, ulong size, range_t **r )
{
if( !is_free( ea, size, *r ) ) {
printk("add_entry: range not free!\n");
return -1;
}
add_entry_( ea, size, r );
return 0;
}
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( ulong ea, int size, range_t **rr )
{
add_entry_( ea, size, rr );
join_ranges( rr );
}
static ulong
find_area( ulong align, ulong size, range_t *r, ulong min, ulong max, int reverse )
{
ulong base = min;
range_t *r2;
if( (align & (align-1)) ) {
printk("bad alignment %ld\n", align);
align = 0x1000;
}
if( !align )
align = 0x1000;
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 (ulong)-1;
}
static ulong
ofmem_claim_phys_( ulong phys, ulong size, ulong align, int min, int max, int reverse )
{
if( !align ) {
if( !is_free( phys, size, ofmem.phys_range ) ) {
printk("Non-free physical memory claimed!\n");
return -1;
}
add_entry( phys, size, &ofmem.phys_range );
return phys;
}
phys = find_area( align, size, ofmem.phys_range, min, max, reverse );
if( phys == (ulong)-1 ) {
printk("ofmem_claim_phys - out of space\n");
return -1;
}
add_entry( phys, size, &ofmem.phys_range );
return phys;
}
/* if align != 0, phys is ignored. Returns -1 on error */
ulong
ofmem_claim_phys( ulong phys, ulong size, ulong align )
{
/* printk("+ ofmem_claim phys %08lx %lx %ld\n", phys, size, align ); */
return ofmem_claim_phys_( phys, size, align, 0, RAMSIZE, 0 );
}
static ulong
ofmem_claim_virt_( ulong virt, ulong size, ulong align, int min, int max, int reverse )
{
if( !align ) {
if( !is_free( virt, size, ofmem.virt_range ) ) {
printk("Non-free physical memory claimed!\n");
return -1;
}
add_entry( virt, size, &ofmem.virt_range );
return virt;
}
virt = find_area( align, size, ofmem.virt_range, min, max, reverse );
if( virt == (ulong)-1 ) {
printk("ofmem_claim_virt - out of space\n");
return -1;
}
add_entry( virt, size, &ofmem.virt_range );
return virt;
}
ulong
ofmem_claim_virt( ulong virt, ulong size, ulong align )
{
/* printk("+ ofmem_claim virt %08lx %lx %ld\n", virt, size, align ); */
return ofmem_claim_virt_( virt, size, align, RAMSIZE, 0x80000000, 0 );
}
/* allocate both physical and virtual space and add a translation */
ulong
ofmem_claim( ulong addr, ulong size, ulong align )
{
ulong virt, phys;
ulong offs = addr & 0xfff;
/* printk("+ ofmem_claim %08lx %lx %ld\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 {
printk("**** ofmem_claim failure ***!\n");
return -1;
}
} else {
if( align < 0x1000 )
align = 0x1000;
phys = ofmem_claim_phys_( addr, size, align, 0, RAMSIZE, 1 /* reverse */ );
virt = ofmem_claim_virt_( addr, size, align, 0, RAMSIZE, 1 /* reverse */ );
if( phys == (ulong)-1 || virt == (ulong)-1 ) {
printk("ofmem_claim failed\n");
return -1;
}
/* printk("...phys = %08lX, virt = %08lX, size = %08lX\n", phys, virt, size ); */
}
/* align */
if( phys & 0xfff ) {
size += (phys & 0xfff);
virt -= (phys & 0xfff);
phys &= ~0xfff;
}
if( size & 0xfff )
size = (size + 0xfff) & ~0xfff;
/* printk("...free memory found... phys: %08lX, virt: %08lX, size %lX\n", phys, virt, size ); */
ofmem_map( phys, virt, size, def_memmode(phys) );
return virt + offs;
}
/************************************************************************/
/* keep track of ea -> phys translations */
/************************************************************************/
static void
split_trans( ulong virt )
{
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;
}
}
}
static int
map_page_range( ulong virt, ulong phys, ulong size, int mode )
{
translation_t *t, **tt;
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 ) {
printk("mapping altered (ea %08lx)\n", t->virt );
} else if( t->mode != mode ){
printk("mapping mode altered\n");
}
for( tt=&ofmem.trans; *tt != t ; tt=&(**tt).next )
;
*tt = t->next;
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;
return 0;
}
int
ofmem_map( ulong phys, ulong virt, ulong size, int mode )
{
/* printk("+ofmem_map: %08lX --> %08lX (size %08lX, mode 0x%02X)\n",
virt, phys, size, mode ); */
if( (phys & 0xfff) || (virt & 0xfff) || (size & 0xfff) ) {
printk("ofmem_map: Bad parameters (%08lX %08lX %08lX)\n", phys, virt, size );
phys &= ~0xfff;
virt &= ~0xfff;
size = (size + 0xfff) & ~0xfff;
}
#if 1
/* 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
//printk("map_page_range %08lx -> %08lx %08lx\n", virt, phys, size );
map_page_range( virt, phys, size, (mode==-1)? def_memmode(phys) : mode );
return 0;
}
/* virtual -> physical. */
ulong
ofmem_translate( ulong virt, ulong *mode )
{
translation_t *t;
for( t=ofmem.trans; t && t->virt <= virt ; t=t->next ) {
ulong 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;
}
/* release memory allocated by ofmem_claim */
void
ofmem_release( ulong virt, ulong size )
{
/* printk("ofmem_release unimplemented (%08lx, %08lx)\n", virt, size ); */
}
/************************************************************************/
/* page fault handler */
/************************************************************************/
static ulong
ea_to_phys( ulong ea, int *mode )
{
ulong phys;
/* hardcode our translation needs */
if( ea >= OF_CODE_START && ea < FREE_BASE_2 ) {
*mode = def_memmode( ea );
return ea;
}
if( (phys=ofmem_translate(ea, (ulong*)mode)) == (ulong)-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 = def_memmode( 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( ulong ea, ulong phys, int mode )
{
static int next_grab_slot=0;
ulong *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 &= (HASH_SIZE-1) >> 6;
pp = (mPTE_t*)(HASH_BASE + (hash1 << 6));
upte = (ulong*)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 )
{
ulong dar, dsisr;
int mode;
asm volatile("mfdar %0" : "=r" (dar) : );
asm volatile("mfdsisr %0" : "=r" (dsisr) : );
//printk("dsi-exception @ %08lx <%08lx>\n", dar, dsisr );
hash_page( dar, ea_to_phys(dar, &mode), mode );
}
void
isi_exception( void )
{
ulong nip, srr1;
int mode;
asm volatile("mfsrr0 %0" : "=r" (nip) : );
asm volatile("mfsrr1 %0" : "=r" (srr1) : );
//printk("isi-exception @ %08lx <%08lx>\n", nip, srr1 );
hash_page( nip, ea_to_phys(nip, &mode), mode );
}
/************************************************************************/
/* init / cleanup */
/************************************************************************/
void
setup_mmu( ulong code_base, ulong code_size, ulong ramsize )
{
ulong sdr1 = HASH_BASE | ((HASH_SIZE-1) >> 16);
ulong sr_base = (0x20 << 24) | SEGR_BASE;
ulong 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 )
{
/* In case we can't rely on memory being zero initialized */
memset(&ofmem, 0, sizeof(ofmem));
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 );
}

170
arch/ppc/osi.h Normal file
View File

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

454
arch/ppc/osi_calls.h Normal file
View File

@ -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 = (ulong)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 = (ulong)a1; \
__oc_r7 = (ulong)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 = (ulong)a1; \
__oc_r7 = (ulong)a2; \
__oc_r8 = (ulong)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 = (ulong)a1; \
__oc_r7 = (ulong)a2; \
__oc_r8 = (ulong)a3; \
__oc_r9 = (ulong)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 = (ulong)a1; \
__oc_r7 = (ulong)a2; \
__oc_r8 = (ulong)a3; \
__oc_r9 = (ulong)a4; \
__oc_r10 = (ulong)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 = (ulong)a1; \
__oc_r7 = (ulong)a2; \
__oc_r8 = (ulong)a3; \
__oc_r9 = (ulong)a4; \
__oc_r10 = (ulong)a5; \
__oc_r11 = (ulong)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() \
((ulong*)retarg1)[0] = __oc_r4; \
((ulong*)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() \
((ulong*)retarg1)[0] = __oc_r4; \
((ulong*)retarg1)[1] = __oc_r5; \
((ulong*)retarg1)[2] = __oc_r6; \
((ulong*)retarg1)[3] = __oc_r7; \
((ulong*)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 = (ulong)a1; \
_oc_syscall( number, rr(r4) ) \
_oc_input( ir(r6) ) \
((ulong*)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 = (ulong)a1; \
_oc_syscall( number, rr(r4), rr(r5) ) \
_oc_input( ir(r6) ) \
((ulong*)retarg1)[0] = __oc_r4; \
((ulong*)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 = (ulong)a1; \
_oc_syscall( number, rr(r4), rr(r5), rr(r6) ) \
_oc_input( ir(r6) ) \
((ulong*)retarg1)[0] = __oc_r4; \
((ulong*)retarg2)[0] = __oc_r5; \
((ulong*)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 = (ulong)a1; \
_oc_syscall( number, rr(r4), rr(r5) ) \
_oc_input( ir(r6) ) \
((ulong*)retarg)[0] = __oc_r4; \
((ulong*)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 = (ulong)a1; \
_oc_syscall( number, rr(r4), rr(r5), rr(r6), rr(r7) ) \
_oc_input( ir(r6) ) \
((ulong*)retarg)[0] = __oc_r4; \
((ulong*)retarg)[1] = __oc_r5; \
((ulong*)retarg)[2] = __oc_r6; \
((ulong*)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 = (ulong)a1; \
__oc_r7 = (ulong)a2; \
_oc_syscall( number, rr(r4), rr(r5) ) \
_oc_input( ir(r6), ir(r7) ) \
((ulong*)retarg)[0] = __oc_r4; \
((ulong*)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 = (ulong)a1; \
__oc_r7 = (ulong)a2; \
_oc_syscall( number, rr(r4), rr(r5), rr(r6), rr(r7) ) \
_oc_input( ir(r6), ir(r7) ) \
((ulong*)retarg)[0] = __oc_r4; \
((ulong*)retarg)[1] = __oc_r5; \
((ulong*)retarg)[2] = __oc_r6; \
((ulong*)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 = (ulong)a1; \
__oc_r7 = (ulong)a2; \
__oc_r10 = (ulong)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 = (ulong)a1; \
__oc_r7 = (ulong)a2; \
_oc_syscall( number, rr(r4), rr(r5), rr(r6), rr(r7), rr(r8), rr(r9) ) \
_oc_input( ir(r6), ir(r7) ) \
((ulong*)retarg)[0] = __oc_r4; \
((ulong*)retarg)[1] = __oc_r5; \
((ulong*)retarg)[2] = __oc_r6; \
((ulong*)retarg)[3] = __oc_r7; \
((ulong*)retarg)[4] = __oc_r8; \
((ulong*)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( ulong, OSI_GetLocalTime, OSI_GET_LOCALTIME );
static inline _osi_call0( ulong, 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, ulong *, 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, ulong, mphys, int, size );
static inline _osi_call5( int, OSI_ABlkSyncWrite, OSI_ABLK_SYNC_WRITE, int, channel, int, unit,
int, blk, ulong, 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, ulong *, retbuf );
static inline int OSI_Enet2GetHWAddr( unsigned char *addr ) {
int ret;
ulong buf[2];
ret = OSI_Enet2GetHWAddr__( buf );
((ulong*)addr)[0] = buf[0];
((ushort*)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, ulong, 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, ulong, mticks );
static inline _osi_call1( int, OSI_UsecsToMticks, OSI_USECS_TO_MTICKS, ulong, 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 */

47
arch/ppc/pearpc/console.c Normal file
View File

@ -0,0 +1,47 @@
/*
* <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 "openbios/config.h"
#include "openbios/bindings.h"
#include "libc/diskio.h"
#include "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 "../../../modules/video.c"
#include "../../../modules/console.c"

137
arch/ppc/pearpc/init.c Normal file
View File

@ -0,0 +1,137 @@
/*
* 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 "openbios/config.h"
#include "openbios/bindings.h"
#include "openbios/nvram.h"
#include "pearpc/pearpc.h"
#include "ofmem.h"
#include "openbios-version.h"
extern void unexpected_excep( int vector );
extern void ob_ide_init( void );
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( ;; )
;
}
void
entry( void )
{
printk("\n");
printk("=============================================================\n");
printk("OpenBIOS %s [%s]\n", OPENBIOS_RELEASE, 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 USE_RTAS
phandle_t ph;
#endif
int autoboot;
devtree_init();
nvram_init();
modules_init();
#ifdef CONFIG_DRIVER_PCI
ob_pci_init();
#endif
#ifdef CONFIG_DRIVER_IDE
setup_timers();
ob_ide_init();
#endif
#ifdef CONFIG_DRIVER_ADB
ob_adb_init();
#endif
node_methods_init();
init_video();
#if USE_RTAS
if( !(ph=find_dev("/rtas")) )
printk("Warning: No /rtas node\n");
else {
ulong size = 0x1000;
while( size < (ulong)of_rtas_end - (ulong)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 );
}

17
arch/ppc/pearpc/kernel.c Normal file
View File

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

145
arch/ppc/pearpc/main.c Normal file
View File

@ -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 "openbios/config.h"
#include "openbios/bindings.h"
#include "openbios/elfload.h"
#include "openbios/nvram.h"
#include "libc/diskio.h"
#include "libc/vsprintf.h"
#include "pearpc/pearpc.h"
#include "ofmem.h"
static void
transfer_control_to_elf( ulong entry )
{
extern void call_elf( ulong 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( ulong *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",
(ulong)phdr[i].p_vaddr, (ulong)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 };
ulong 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();
}

335
arch/ppc/pearpc/methods.c Normal file
View File

@ -0,0 +1,335 @@
/*
* 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 "openbios/config.h"
#include "openbios/bindings.h"
#include "libc/string.h"
#include "pearpc/pearpc.h"
#include "ofmem.h"
/************************************************************************/
/* RTAS (run-time abstraction services) */
/************************************************************************/
#ifdef USE_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;
ulong 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();
char *s = malloc( len + 1 );
strncpy_nopad( s, addr, len );
s[len]=0;
printk( "%s", s );
//vfd_draw_str( s );
console_draw_str( s );
free( s );
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( ulong args[], ulong ret[] )
{
#if 0
ulong 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( ulong args[], ulong ret[] )
{
extern unsigned long get_timer_freq();
static ulong mticks=0, usecs=0;
ulong 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 )
{
ulong mode;
int virt = POP();
int phys = ofmem_translate( virt, &mode );
if( phys == -1 ) {
PUSH( 0 );
} else {
PUSH( phys );
PUSH( (int)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 ) = {
{ "claim", ciface_claim },
{ "release", ciface_release },
};
/************************************************************************/
/* init */
/************************************************************************/
void
node_methods_init( void )
{
#ifdef USE_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 );
}

206
arch/ppc/pearpc/pearpc.c Normal file
View File

@ -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 "openbios/config.h"
#include "openbios/kernel.h"
#include "openbios/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]; /* XXX: no buffer overflow protection... */
va_list args;
int i;
va_start(args, fmt);
i=vsprintf(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();
}

116
arch/ppc/pearpc/pearpc.fs Normal file
View File

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

26
arch/ppc/pearpc/pearpc.h Normal file
View File

@ -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_str( const char *str );
#include "kernel.h"
#endif /* _H_PEARPC */

23
arch/ppc/pearpc/tree.c Normal file
View File

@ -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 "openbios/config.h"
#include "openbios/bindings.h"
void devtree_init( void )
{
fword("init-pearpc-tree");
}

247
arch/ppc/pearpc/tree.fs Normal file
View File

@ -0,0 +1,247 @@
\ 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
" 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

42
arch/ppc/pearpc/vfd.c Normal file
View File

@ -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 "openbios/config.h"
#include "openbios/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;
}

47
arch/ppc/ppc.fs Normal file
View File

@ -0,0 +1,47 @@
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

324
arch/ppc/start.S Normal file
View File

@ -0,0 +1,324 @@
/*
* 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
*
*/
changequote([[[[[,]]]]]) [[[[[ /* shield includes from m4-expansion */
#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
MACRO(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
LOADI r1,estack
mtsprg0 r1 // setup exception stack
LOADI r1,stack
// copy exception vectors
LOADI 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 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
LOADI r8,saved_stack // save our stack pointer
stw r1,0(r8)
LOADI r1,client_stack
LOADI 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
mtmsr r0
blrl
LOADI r8,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):
LOADI r4,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
LOADI r3,OSI_SC_MAGIC_R3
LOADI r4,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):
LOADI r3,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
LOADI r3,dsi_exception
mtctr r3
bctrl
b exception_return
VECTOR( 0x400, "ISI" ):
EXCEPTION_PREAMBLE
LOADI r3,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( ulong start, ulong 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

35
arch/ppc/timebase.S Normal file
View File

@ -0,0 +1,35 @@
changequote([[[[[,]]]]]) [[[[[ /* shield includes from m4-expansion */
#include "asm/asmdefs.h"
#include "asm/processor.h"
/*
* unsigned long long _get_ticks(void);
*/
GLOBL(_get_ticks):
1: mftbu r3
mftb r4
mftbu r5
cmpw 0,r3,r5
bne 1b
blr
/*
* Delay for a number of ticks
*/
GLOBL(_wait_ticks):
mflr r8 /* save link register */
mr r7, r3 /* save tick count */
bl _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 _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

18
arch/unix/Kconfig Normal file
View File

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

29
arch/unix/Makefile Normal file
View File

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

115
arch/unix/blk.c Normal file
View File

@ -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 "openbios/config.h"
#include "openbios/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( 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( blk_data_t *pb )
{
PUSH( 512 );
}
/* ( -- maxbytes ) */
static void
blk_max_transfer( blk_data_t *pb )
{
PUSH( 1024*1024 );
}
static void
blk_initialize( 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 );
}

8
arch/unix/blk.h Normal file
View File

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

80
arch/unix/boot.c Normal file
View File

@ -0,0 +1,80 @@
/*
*
*/
#undef BOOTSTRAP
#include "openbios/config.h"
#include "openbios/bindings.h"
#include "openbios/elfload.h"
#include "openbios/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;
}
(ullong *)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",
(ulong)phdr[i].p_vaddr, (ulong)phdr[i].p_memsz);
}
free( phdr );
return entry;
#else
return NULL;
#endif
}
void
boot( void )
{
char *path=pop_fstr_copy();
void *entry;
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 %x.\n", (ucell)entry);
else
printk("failed.\n");
}

22
arch/unix/build.xml Normal file
View File

@ -0,0 +1,22 @@
<build condition="HOST_UNIX">
<dictionary name="openbios-unix" init="openbios" target="forth">
<object source="tree.fs"/>
</dictionary>
<executable name="openbios-unix" target="target">
<rule>
$(CC) $(CFLAGS) -rdynamic $(LIBDL_LDFLAGS) -o $@ $^
</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="libmodules.a"/>
<external-object source="libdrivers.a"/>
<external-object source="liblibc.a"/>
<external-object source="libfs.a"/>
</executable>
</build>

42
arch/unix/gui_qt/Makefile Normal file
View File

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

129
arch/unix/gui_qt/gui-qt.cpp Normal file
View File

@ -0,0 +1,129 @@
/* 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;
runforth=0;
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;
}
}

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