quik-2.1/0000755000175000001440000000000007062261060012630 5ustar simonusers00000000000000quik-2.1/BitKeeper/0000755000175000001440000000000007062261060014502 5ustar simonusers00000000000000quik-2.1/BitKeeper/etc/0000755000175000001440000000000007062261060015255 5ustar simonusers00000000000000quik-2.1/BitKeeper/etc/config0000644000175000001440000000637007062261060016453 0ustar simonusers00000000000000# This is the BitKeeper configuration file. # @(#)bitkeeper.config 1.4 zack@zack.bitmover.com # # It defines the contact information for the responsible party for this # project. This information is used by BitKeeper to provide support to # BitKeeper users. Please take a minute to fill it out carefully, it # needs to be accurate. # Open Logging server. This site is where users can go to see what has # happened in all instances of this repository. # If this repository is non commercial, i.e. BitKeeper is being used for # free, the site must be in the openlogging.org domain, otherwise it can # be an internal site. # Anyone may apply for an alias (CNAME) in the openlogging.org domain # if they are willing to maintain a BitKeeper Open Logging web server. # linux.openlogging.org could host the Linux kernel effort, for example. logging: logging@openlogging.org logging_ok: cort@medea.fsmlabs.com # Commercial seats. If the logging field is *.openlogging.org, then this # field is ignored. If the previous field is some internal site, such as # bitkeeper.mycompany.com, then this file is included in diagnostic messages # sent back to bitkeeper.com. The value of this field determines the number # of users which can work on the repository within a 6 month period. # It's an upper bound on the number of users allowed in the repository, # which determines the price which your company will be billed for the # use of BitKeeper. This field allows management to limit the number of # seats in use. A "seat" is a user. seats: 1 # Security of diagnostic messages. BitKeeper sends periodic # status back to BitKeeper.com. This information is used as part of # the support process, i.e., if you are using an older version of # BitKeeper, we'll let you know automatically when an update is available. # # Commercial customers can arrange for greater levels of security # the diagnostics sent back to BitMover, Inc. Contact your sales # representative for assistance. # # Note: BitMover does not and will not make any information gathered through # this mechanism available to the public. The information is used solely # by BitMover for support and will not be disclosed, forwarded, or sold # to any third party for any purpose. # # Values for this field are currently "none" or "ssh". The "ssh" field # requires that ssh is installed in order to operate and you must have # prearranged for high security support service. security: ssh # Contact person for this project. This is whoever is the person that # should be contacted with update information or contacted if BitKeeper # discovers a problem which requires local intervention. Please make the # contact information accurate so we can support you. contact: Cort Dougan # Preferred email for the contact email: cort@ppc.kernel.org # Postal address. Street: New Mexico Tech Computer Science Department City: Socorro Postal: 87801 Country: USA # A phone number which may be used to call in support. Fields are also # provided for cell phones and pagers. phone: 505 835 0205 cell: 505 480 7341 pager: # Times which are reasonable to call. If this is not filled out, we # assume 10am to 9pm local time, assuming we can determine local time # The time format is ``military'' i.e., 6pm is 18:00. business hours: 10:00-21:00 quik-2.1/COPYING0000644000175000001440000004307007062261060013667 0ustar simonusers00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 675 Mass Ave, Cambridge, MA 02139, 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. Copyright (C) 19yy 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., 675 Mass Ave, Cambridge, MA 02139, 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. , 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. quik-2.1/Makefile0000644000175000001440000000126407062261060014273 0ustar simonusers00000000000000DIRS= util first second quik .EXPORT_ALL_VARIABLES: CC=gcc all clean dep depend: @for I in $(DIRS); do cd $$I; make $@ || exit 1; cd ..; done install: install -d -m 755 $(DESTDIR)/sbin install -d -m 755 $(DESTDIR)/boot install -d -m 755 $(DESTDIR)/etc install -d -m 755 $(DESTDIR)/usr/man/man5 install -d -m 755 $(DESTDIR)/usr/man/man8 install -s quik/quik $(DESTDIR)/sbin install -m 444 first/first.b second/second.b second/second $(DESTDIR)/boot if [ -f $(DESTDIR)/etc/quik.conf ]; then :; \ else set -x; install -m 644 etc/quik.conf $(DESTDIR)/etc; fi install -m 444 man/quik.conf.5 $(DESTDIR)/usr/man/man5 install -m 444 man/quik.8 man/bootstrap.8 $(DESTDIR)/usr/man/man8 quik-2.1/etc/0000755000175000001440000000000007062261060013403 5ustar simonusers00000000000000quik-2.1/etc/quik.conf0000644000175000001440000000022307062261060015220 0ustar simonusers00000000000000# Example of how can be quik.conf set up timeout = 100 default = linux image = /boot/vmlinux label = linux image = /boot/vmlinux.old label = old quik-2.1/first/0000755000175000001440000000000007062261060013757 5ustar simonusers00000000000000quik-2.1/first/Makefile0000644000175000001440000000051407062261060015417 0ustar simonusers00000000000000ASFLAGS = -D__ASSEMBLY__ -I../include LDFLAGS = -T ld.script -Ttext 3f4000 all: first.b first.b: first size first # ../util/elfextract first first.b dd if=first of=first.b bs=1k count=1 skip=16 OBJS = first.o first.o: ../include/layout.h first: $(OBJS) ld -o first $(LDFLAGS) $(OBJS) clean: rm -f *.o *.s *~ first first.b quik-2.1/first/first.S0000644000175000001440000001074007062261060015234 0ustar simonusers00000000000000/* * First stage bootstrap for Power Macintosh. * Because of space restrictions, the original C code * has been turned into hand-trimmed assembly * (with a little bit of help from gcc :-). */ #include .file "first.c" /* * Register usage in main: * 14 high part of address * 20 bp * 21 i * 22 prom_entry * 25 start * 26 fp * 27 bdev * 28 addr * 29 bs * * Register usage in call_prom: * 23 nargs * */ .section .rodata .LC0: .string "finddevice" .LC1: .string "/chosen" .LC1a: .string "/options" .LC2: .string "getprop" .LC3: .string "bootpath" .LC3a: .string "boot-device" .LC4: .string "open" .LC5: .string "seek" .LC6: .string "read" .LC7: .string "exit" .LC8: .string "enter" .section ".text" .align 2 .globl main .type main,@function /* main(a1, a2, void (*prom_entry)(struct prom_args *)) */ main: lis 14,.LC0@ha /* Make sure our code is consistent in the I and D caches. */ addi 3,14,main@l li 4,32 mtctr 4 1: dcbf 0,3 icbi 0,3 addi 3,3,0x20 bdnz 1b sync isync /* Use the BAT3 registers to map the 1st 8MB of RAM to 0. */ mfpvr 9 rlwinm 9,9,16,16,31 /* r9 = 1 for 601, 4 for 604 */ cmpi 0,9,1 bne 4f li 7,4 /* set up BAT registers for 601 */ li 8,0x7f b 5f 4: li 7,0xff /* set up BAT registers for 604 */ li 8,2 mtdbatu 3,7 mtdbatl 3,8 5: mtibatu 3,7 mtibatl 3,8 isync /* Load up an initial stack pointer */ lis 1,STACK_TOP@h subi 1,1,0x180 mr 22,5 /* prom = prom_entry */ addi 3,14,.LC0@l /* chosen_handle = call_prom("finddevice, */ li 4,1 /* 1, "/chosen"); */ addi 5,14,.LC1@l bl call_prom addi 7,1,8 /* bootpath[0] = 0 */ li 0,0 stw 0,0(7) mr 5,3 addi 3,14,.LC2@l /* call_prom("getprop", 4, chosen_handle, */ li 4,4 /* "bootpath", bootpath, */ addi 6,14,.LC3@l /* sizeof(bootpath)); */ li 8,256 bl call_prom lbz 0,8(1) /* if (bootpath[0] == 0) { */ cmpi 0,0,0 bne 11f addi 3,14,.LC0@l /* options_handle = call_prom("finddevice", */ li 4,1 /* 1, "/options"); */ addi 5,14,.LC1a@l bl call_prom mr 5,3 /* call_prom("getprop", 4, options_handle, */ addi 3,14,.LC2@l /* "boot-device", bootpath, */ li 4,4 /* sizeof(bootpath)); */ addi 6,14,.LC3a@l li 8,256 bl call_prom 11: addi 3,1,7 /* for (s = bootpath; *s != 0; ++s) */ 1: lbzu 0,1(3) cmpwi 0,0,0 beq 2f cmpwi 0,0,58 /* if (*s == ':') { */ bne 1b li 0,0 /* *s = 0; break; } */ stb 0,0(3) 2: addi 3,14,.LC4@l /* bdev = call_prom("open", 1, bootpath); */ li 4,1 addi 5,1,8 bl call_prom mr 27,3 addi 0,27,1 /* if (bdev == 0 || bdev == -1) */ cmplwi 0,0,1 ble out /* goto out; */ addi 26,14,FIRST_INFO@l /* fp = FIRST_INFO; */ lwz 28,16(26) /* addr = fp->second_base; */ mr 25,28 /* start = (void *) addr; */ lwz 29,12(26) /* bs = fp->blocksize; */ addi 20,26,0x38-4 /* bp = &fp->blknos[-1]; */ lwz 21,8(26) /* i = fp->nblocks; do { */ 3: addi 3,14,.LC5@l /* call_prom("seek", 3, bdev, */ li 4,3 /* 0, *++bp * 512); */ mr 5,27 lwzu 31,4(20) srwi 6,31,23 slwi 7,31,9 bl call_prom mr 16,3 addi 3,14,.LC6@l /* if (call_prom("read", 3, bdev, */ li 4,3 /* addr, bs) != bs) */ mr 5,27 mr 6,28 mr 7,29 bl call_prom mr 30,3 cmpw 0,3,29 /* goto out; */ bne out add 28,28,29 /* addr += bs; */ addic. 21,21,-1 /* } while (--i > 0); */ bgt 3b mr 3,25 /* flush_cache(start, addr); */ 4: dcbf 0,3 icbi 0,3 addi 3,3,0x20 cmplw 3,28 blt 4b sync isync #if 0 addi 3,14,.LC8@l /* call_prom("enter", 0); */ li 4,0 bl call_prom #endif mtlr 25 /* (*start)(prom_entry, fp); */ mr 3,22 mr 4,26 /* * Let the second stage know that it's being called from the PowerMac * first stage bootloader * -- Cort */ lis 5,0xdeadbeef@h ori 5,5,0xdeadbeef@l blrl out: addi 3,14,.LC8@l /* call_prom("enter", 0); */ li 4,0 bl call_prom addi 3,14,.LC7@l /* call_prom("exit", 0); */ li 4,0 bl call_prom b out .Lfe1: .size main,.Lfe1-main .align 2 .globl call_prom .type call_prom,@function .long 0x403c /* call_prom(service, nargs, a0, a1, a2, a3) */ call_prom: stwu 1,-80(1) mflr 0 stw 0,84(1) mr 23,4 /* nargs */ stw 3,8(1) /* args.service = service; */ stw 23,12(1) /* args.nargs = nargs; */ li 0,1 /* args.nret = 1; */ stw 0,16(1) stw 5,20(1) /* args.params[0] = a0; */ stw 6,24(1) /* args.params[1] = a1; */ mtlr 22 stw 7,28(1) /* args.params[2] = a2; */ stw 8,32(1) /* args.params[3] = a3; */ addi 3,1,8 blrl /* (*prom)(&args); */ slwi 23,23,2 /* return args.params[nargs]; */ add 9,1,23 lwz 3,20(9) lwz 0,84(1) mtlr 0 addi 1,1,80 blr .Lfe2: .size call_prom,.Lfe2-call_prom quik-2.1/first/ld.script0000644000175000001440000000316307062261060015607 0ustar simonusers00000000000000OUTPUT_ARCH(powerpc) SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib); /* Do we need any of these for elf? __DYNAMIC = 0; */ SECTIONS { /* Read-only sections, merged into text segment: */ . = + SIZEOF_HEADERS; .interp : { *(.interp) } .hash : { *(.hash) } .dynsym : { *(.dynsym) } .dynstr : { *(.dynstr) } .rel.text : { *(.rel.text) } .rela.text : { *(.rela.text) } .rel.data : { *(.rel.data) } .rela.data : { *(.rela.data) } .rel.rodata : { *(.rel.rodata) } .rela.rodata : { *(.rela.rodata) } .rel.got : { *(.rel.got) } .rela.got : { *(.rela.got) } .rel.ctors : { *(.rel.ctors) } .rela.ctors : { *(.rela.ctors) } .rel.dtors : { *(.rel.dtors) } .rela.dtors : { *(.rela.dtors) } .rel.bss : { *(.rel.bss) } .rela.bss : { *(.rela.bss) } .rel.plt : { *(.rel.plt) } .rela.plt : { *(.rela.plt) } .init : { *(.init) } =0 .plt : { *(.plt) } .text : { *(.text) *(.rodata) *(.rodata1) *(.got1) } _etext = .; PROVIDE (etext = .); .fini : { *(.fini) } =0 .ctors : { *(.ctors) } .dtors : { *(.dtors) } /* Read-write section, merged into data segment: */ .data : { *(.data) CONSTRUCTORS *(.data1) *(.got.plt) *(.got) *(.dynamic) *(.sdata) *(.sdata2) *(.sbss) *(.scommon) *(.dynbss) *(.bss) *(COMMON) } _edata = .; PROVIDE (edata = .); __bss_start = .; .bss : { } _end = . ; PROVIDE (end = .); } quik-2.1/include/0000755000175000001440000000000007062261060014253 5ustar simonusers00000000000000quik-2.1/include/asm/0000755000175000001440000000000007062261060015033 5ustar simonusers00000000000000quik-2.1/include/asm/mac-part.h0000644000175000001440000000304607062261060016713 0ustar simonusers00000000000000/* * Structure of a Macintosh driver descriptor (block 0) * and partition table (blocks 1..n). * * Copyright 1996 Paul Mackerras. */ #define MAC_PARTITION_MAGIC 0x504d /* type field value for A/UX or other Unix partitions */ #define APPLE_AUX_TYPE "Apple_UNIX_SVR2" struct mac_partition { __u16 signature; /* expected to be MAC_PARTITION_MAGIC */ __u16 res1; __u32 map_count; /* # blocks in partition map */ __u32 start_block; /* absolute starting block # of partition */ __u32 block_count; /* number of blocks in partition */ char name[32]; /* partition name */ char type[32]; /* string type description */ __u32 data_start; /* rel block # of first data block */ __u32 data_count; /* number of data blocks */ __u32 status; /* partition status */ __u32 boot_start; /* logical start block no. of bootstrap */ __u32 boot_size; /* no. of bytes in bootstrap */ __u32 boot_load; /* bootstrap load address in memory */ __u32 boot_load2; /* reserved for extension of boot_load */ __u32 boot_entry; /* entry point address for bootstrap */ __u32 boot_entry2; /* reserved for extension of boot_entry */ __u32 boot_cksum; char processor[16]; /* name of processor that boot is for */ }; /* Bit in status field */ #define STATUS_BOOTABLE 8 /* partition is bootable */ #define MAC_DRIVER_MAGIC 0x4552 /* Driver descriptor structure, in block 0 */ struct mac_driver_desc { __u16 signature; /* expected to be MAC_DRIVER_MAGIC */ __u16 block_size; __u32 block_count; /* ... more stuff */ }; quik-2.1/include/layout.h0000644000175000001440000000221507062261060015741 0ustar simonusers00000000000000/* * layout.h - definitions for where the 1st and 2nd stage bootstraps * go in memory and the structures they use to communicate. * * Copyright (C) 1996 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; either version 2 of the License, or * (at your option) any later version. */ #define VERSION "2.0" #define FIRST_BASE 0x3f4000 #define FIRST_SIZE 0x400 #define SECOND_BASE 0x3e0000 #define SECOND_SIZE 0x10000 #define STACK_TOP 0x400000 /* 0x400000 - 0x500000 is one of OF's favourite places to be. */ #define MALLOC_BASE 0x500000 #ifndef __ASSEMBLY__ struct first_info { char quik_vers[8]; int nblocks; int blocksize; unsigned second_base; int conf_part; char conf_file[32]; unsigned blknos[64]; }; #endif /* __ASSEMBLY__ */ /* * If you change FIRST_SIZE or sizeof(struct first_info), * be sure to change the definition of FIRST_INFO_OFF. */ #define FIRST_INFO_OFF 0x2c8 /* == FIRST_SIZE - sizeof(struct first_info) */ #define FIRST_INFO (FIRST_BASE + FIRST_INFO_OFF) quik-2.1/man/0000755000175000001440000000000007062261060013403 5ustar simonusers00000000000000quik-2.1/man/bootstrap.80000644000175000001440000001146507062261060015520 0ustar simonusers00000000000000.\" bootstrap - Description of the disk boot process for Powermacs .TH bootstrap 8 "16 March 1997" "" "PowerMac/Linux" .SH NAME bootstrap \- Disk boot process for PowerMac/Linux .SH DESCRIPTION The process of booting PowerMac/Linux from a disk starts with Open Firmware loading the boot block from the first bootable partition of the boot disk into memory. The user specifies which device is to be the boot disk by setting the \fBboot-device\fR environment variable to the Open Firmware name of the boot disk, or by giving it as an explicit argument to the Open Firmware \fBboot\fR command. Open Firmware then transfers control to the first-stage bootstrap (\fBfirst.b\fR), located at the beginning of the boot block. The boot block also contains the list of block numbers for the second-stage bootstrap. \fBFirst.b\fR reads these blocks into memory, thus loading the second-stage bootstrap. The task of the second-stage bootstrap (\fBsecond.b\fR) is to load the Linux kernel into memory and pass it any arguments given by the user. \fBSecond.b\fR can also be used for loading other programs, such as diagnostic programs or other operating systems, as long as they are present as an ELF binary in an ext2 filesystem. \fBSecond.b\fR gets two string values from Open Firmware, called \fIbootpath\fR and \fIbootargs\fR. \fIBootpath\fR is the Open Firmware name of the boot disk (i.e., the device that the first-stage bootstrap was loaded from). If Open Firmware auto-booted, or if the \fBboot\fR command was given without arguments, then \fIbootpath\fR and \fIbootargs\fR are set to the values of the \fBboot-device\fR and \fBboot-file\fR variables, respectively. If the \fBboot\fR command was given with arguments, the first argument becomes \fIbootpath\fR and any subsequent arguments are saved in \fIbootargs\fR. \fBSecond.b\fR uses the Open Firmware input and output devices for communicating with the user. By default, the modem port is used for both, but this can be changed by setting the Open Firmware \fBinput-device\fR and \fBoutput-device\fR variables. \fBSecond.b\fR starts by printing a message to indicate that it has started, and then reads the configuration file. By default, the configuration file is \fB/etc/quik.conf\fR on the same partition as the boot block, but this can be overridden with quik(1). The configuration file must be on the same disk as the boot block. The format of the configuration file is described in quik.conf(5). Then \fBsecond.b\fR prints its \fBboot:\fR prompt and waits for the user to type a command line. Normally the configuration file specifies a timeout, and if the user does not type anything within that period of time, \fBsecond.b\fR proceeds using the \fIbootargs\fR value as the command line. If the timeout value is 0, \fBsecond.b\fR will always use the \fIbootargs\fR value, ignoring anything the user types. This can be useful when a modem is connected to the modem port. Having obtained a command line, \fBsecond.b\fR takes the first word (whitespace-separated) as the name of the program to load. Any remaining words on the line become arguments to be passed to the program when it is loaded. If the command line is empty, \fBsecond.b\fR uses the value of the \fBdefault\fR keyword in the configuration file, or failing that, the first program specified in the configuration file. The configuration file can specify several alternative programs to load (referred to as \fIimages\fR in the configuration file syntax), along with shorthand labels for them and extra arguments to be prepended to those specified by the user. The program name given in the command line can be either an explicit path name or a shorthand label. If it is a shorthand label, the configuration file gives the corresponding path name. Path names are of the form .RS .RI [ device\fB: ][ partno ]\fB/ filepath .RE where \fIdevice\fR is the Open Firmware name of the disk, \fIpartno\fR is the (decimal) number of the partition on that disk, and \fIfilepath\fR is the path to the file in the ext2 filesystem on that partition. The default for \fIdevice\fR is \fIbootpath\fR, and the default for \fIpartno\fR is the first bootable partition on \fIdevice\fR. Alternatively, the \fB/\fIfilepath\fR section can be replaced by a span of 512-byte blocks to load using the syntax .BI [ start - end ] where \fIstart\fR and \fIend\fR are decimal block numbers. \fBSecond.b\fR will attempt to open the file identified by the path name and load it into memory as an ELF binary. If the file cannot be found, or if it is not an ELF binary, \fBsecond.b\fR will print an error message and print its \fBboot:\fR prompt again. In this case there is no timeout and \fBsecond.b\fR does not use the \fIbootargs\fR value. Once \fBsecond.b\fR has loaded the program into memory, it transfers control to it, passing it the list of arguments. .SH SEE ALSO .I quik(8), quik.conf(5) quik-2.1/man/quik.80000644000175000001440000000603607062261060014452 0ustar simonusers00000000000000.\" quik - Powermac/Linux disk bootstrap installer .TH quik 8 "16 March 1997" "" "PowerMac/Linux" .SH NAME quik \- Install disk bootstrap for PowerMac/Linux .SH SYNOPSIS .B /sbin/quik .RB [ \-b\ \fIsecond-stage\fB ] .RB [ \-C\ \fIconfig-file\fB ] .RB [ \-f ] .RB [ \-i\ \fIfirst-stage\fB ] .RB [ \-r\ \fIroot-path\fB ] .RB "[ [" \-s | \-S ] \ \fIbackup ] .RB [ \-v ] .RB [ \-V ] .SH DESCRIPTION .B Quik installs a disk bootstrap on a partition, enabling Linux to be booted from that partition. Specifically, it writes the first-stage bootstrap together with a table of block numbers to the first 1024 bytes of the partition (the .IR boot\ block ), and modifies the entry for the partition in the partition table to make the partition bootable. .B Quik creates the table of block numbers by finding out where on the disk the blocks of the second-stage bootstrap are stored. It then writes these block numbers into the boot block so that the first-stage bootstrap can load the second-stage bootstrap without having to incorporate ext2 filesystem code. The second-stage bootstrap file must therefore be on the same disk as the boot block (although it need not be on the same partition), and if the second-stage bootstrap file is subsequently moved or replaced, quik must be re-run to update the block number table. .SH OPTIONS .TP .TP .B \-b \fIsecond-stage Use \fIsecond-stage\fR as the second-stage boot image, instead of the default \fB/boot/second.b\fR. The second-stage boot image must be on the same disk as the boot block, though not necessarily on the same partition. .TP .B \-C \fIconfig-file Record \fIconfig-file\fR as the name of the configuration file for the second-stage bootstrap to use, instead of the default \fB/etc/quik.conf\fR. The configuration file must be on the same disk as the boot block, though not necessarily on the same partition. .B \-f Force installation of first-stage bootstrap, even if the version number currently in the boot block matches quik's current version. .TP .B \-i \fIfirst-stage Use \fIfirst-stage\fR as the first-stage boot image, instead of the default \fB/boot/first.b\fR. .TP .B \-r \fIroot-path Install the boot block on the partition on which \fIroot-path\fR is mounted. The default is the root partition. With this option, quik will by default use the first and second stage bootstraps found in \fIroot-path\fB/boot\fR, and the default configuration file name will be \fIroot-path\fB/etc/quik.conf\fR. .TP .B \-S \fIbackup Save a copy of the current boot block in .IR backup . .TP .B \-s \fIbackup Save a copy of the current boot block in \fIbackup\fR if it does not already exist. By default, quik will save a copy of the current boot block in \fB/boot/old.b\fR if that file does not already exist. .TP .B \-v Verbose mode: print messages indicating what quik is doing. .TP .B \-V Print quik's version number and exit. .SH FILES .nf /boot/first.b /boot/second.b /etc/quik.conf .fi .SH AUTHORS Paul Mackerras, based on the Sparc bootstrap installation program by Maurizio Plaza and Jakub Jelinek. .SH SEE ALSO .I quik.conf(5), bootstrap(8) quik-2.1/man/quik.conf.50000644000175000001440000001271007062261060015367 0ustar simonusers00000000000000.\" quik.conf - description of the format of the /etc/quik.conf file .TH quik.conf 5 "19 March 1997" "" "PowerMac/Linux" .SH NAME quik.conf \- Configuration file for PowerMac/Linux disk bootstrap .SH DESCRIPTION The \fB/etc/quik.conf\fR file is read by the second-stage bootstrap (see bootstrap(8)). It allows the user to customize various aspects of the second-stage bootstrap's behaviour, and to specify various programs (referred to in the configuration file as \fIimages\fR) which can be booted using just a shorthand label. (Other programs not listed in the configuration file can also be booted, but the user must enter the path name for the program rather than just a shorthand label.) The configuration file is parsed into tokens separated by white space or the equals sign. Comments begin with a hash character and continue to the end of the line. Words containing whitespace or other special characters should be surrounded by double quotes, or the special characters should be quoted by preceding them with a backslash. The configuration file is structured as a list of global options, followed by a list of images, each of which can have local options. Local options are used when the corresponding image is booted, and override the global options. Each \fBimage\fR option in the configuration file defines a new image, and options between that and the next \fBimage\fR option are local options for that image. Options before the first \fBimage\fR option are global options. There are two kinds of options: flag options and string options. Flag options are specified simply by giving the option name. String options are specified by giving the option name, an equals sign, and the value (as a single token). Whitespace around the equals sign is ignored. .SH OPTIONS .TP .BI device= path Specifies the Open Firmware name of the default disk to use if no explicit device name is given in the image path. If this is not specified, the boot device (the device from which Open Firmware loaded the first-stage bootstrap) is used. .TP .BI partition= partno Specifies which partition to use if no explicit partition number is given in the image path. If this is not specified, the default is to use the first bootable partition on the device. .TP .BI default= label Specifies the default image to boot if no image name or label is entered by the user or specified via the Open Firmware \fIboot-file\fR variable. \fILabel\fR can be either a path name or a shorthand label. This is a global option only. .TP .BI timeout= n Specifies the timeout period for the second-stage bootstrap to wait for the user to type a command line. \fIN\fR is a decimal integer specifying the timeout period in units of 0.1 seconds. This is a global option only. .TP .BI init-message= string Specifies a string to print out when the second-stage bootstrap starts. This is a global option only. .TP .BI message= path Specifies the path name for a file to print out when the second-stage bootstrap starts, before it prompts the user for a command line. This is a global option only. .TP .BI root= string Specifies that the argument .BI root= string should be inserted in the arguments to the kernel being booted, before the arguments specified by the user. .TP .BI ramdisk= string Specifies that the argument .BI ramdisk= string should be inserted in the arguments to the kernel being booted, before the arguments specified by the user. .TP .B read-only Specifies that the argument .B ro should be inserted in the arguments to the kernel being booted, before the arguments specified by the user. .TP .B read-write Specifies that the argument .B rw should be inserted in the arguments to the kernel being booted, before the arguments specified by the user. .TP .BI append= string Specifies that the argument .I string should be inserted in the arguments to the kernel being booted, before the arguments specified by the user. .TP .BI literal= string Specifies that the argument .I string followed by the arguments (if any) specified by the user should be the only arguments passed to the kernel being booted (thus overriding the \fBroot\fR and similar options). This is a local option only. .TP .BI image= path Specifies the path for an program which can be booted. Options from here until the next \fBimage\fR option are local options for this program. If the image name begins with a dollar sign ($), the rest of the image name is taken as a forth command which will be executed by Open Firmware, instead of loading and running an executable program. .TP .BI label= label Specifies that \fIlabel\fR is a shorthand name for the current image. This is a local option only. .TP .BI alias= label Specifies that \fIlabel\fR is an alternative shorthand name for the current image. This is a local option only. .TP .B pause-after Specifies that the second-stage bootstrap should pause after loading the program and before transferring control to it. The second-stage bootstrap pauses by transferring control to Open Firmware; the user can transfer control back with the \fBgo\fR command (i.e. forth word). .TP .BI pause-message= string Specifies the message that the second-stage bootstrap should print after loading the program and before waiting for the user to press a key. Only useful when the \fBpause-after\fR option is given. .TP .BI init-code= string Specifies that the second-stage bootstrap should call Open Firmware to execute the string given (a series of forth commands) before printing the boot prompt. This is a global option only. .SH SEE ALSO .I bootstrap(8) quik-2.1/quik/0000755000175000001440000000000007062261060013601 5ustar simonusers00000000000000quik-2.1/quik/Makefile0000644000175000001440000000020607062261060015237 0ustar simonusers00000000000000all: quik COPTS = -static -O CFLAGS = -I../include $(COPTS) quik: quik.c $(CC) $(CFLAGS) -o quik quik.c clean: rm -f *.o *~ quik quik-2.1/quik/quik.c0000644000175000001440000003727507062261060014734 0ustar simonusers00000000000000/* quik - bootblock installation program for Linux on Power Macintosh. Copyright (C) 1996 Paul Mackerras. Derived from silo.c in the silo-0.6.4 distribution, therefore: Copyright (C) 1996 Maurizio Plaza 1996 Jakub Jelinek 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* This program generates a lists of blocks where the secondary loader lives */ #include #include #include #include #include #include #include #include #include #include #include #include #include #define DFL_CONFIG "/etc/quik.conf" #define ALT_CONFIG "/etc/milo.conf" #define DFL_BACKUP "/boot/old.b" #define DFL_PRIMARY "/boot/first.b" #define DFL_SECONDARY "/boot/second.b" #define SD_MAJOR 8 /* Major device no. for scsi disks */ #define HDA_MAJOR 3 /* major number for hda and hdb */ #define HDC_MAJOR 22 #define HDE_MAJOR 33 #define HDG_MAJOR 34 #ifndef MAJOR #define MAJOR(dev) ((dev) >> 8) #define MINOR(dev) ((dev) & 0xff) #endif int unit_shift; int part_mask; #define UNIT(dev) (MINOR(dev) >> unit_shift) #define PART(dev) (MINOR(dev) & part_mask) #define swab_32(x) ((((x) >> 24) & 0xff) + (((x) >> 8) & 0xff00) \ + (((x) & 0xff00) << 8) + (((x) & 0xff) << 24)) #define swab_16(x) ((((x) >> 8) & 0xff) + (((x) & 0xff) << 8)) unsigned nsect; /* # (512-byte) sectors per f.s. block */ unsigned bs; /* f.s. block size */ int part_block; /* block # of partition map entry */ int secsize; /* disk sector size */ int first_bootable; /* part map entry # of 1st bootable part */ unsigned long doff; /* start of partition containing 2nd boot */ char *first, *second, *old; /* File names */ struct first_info finfo; int verbose; void fatal(char *fmt,...) { va_list ap; va_start(ap, fmt); fprintf(stderr, "Fatal error: "); vfprintf(stderr, fmt, ap); putc('\n', stderr); va_end(ap); exit(1); } int check_fs(int fd) { struct ext2_super_block sb; /* Super Block Info */ if (lseek(fd, 1024, 0) != 1024 || read(fd, &sb, sizeof(sb)) != sizeof (sb)) fatal("Cannot read superblock"); if (sb.s_magic == EXT2_SUPER_MAGIC) return 1024 << sb.s_log_block_size; if (swab_16(sb.s_magic) == EXT2_SUPER_MAGIC) return 1024 << swab_32(sb.s_log_block_size); return -1; } void read_sb(char *device, char *bootdev) { int fd, partno, part; int offset, upart, maxpart; struct mac_partition *mp; struct mac_driver_desc *md; char *p; char buff[512]; if ((fd = open(device, O_RDONLY)) == -1) fatal("Cannot open %s", device); bs = check_fs(fd); if (bs == -1) fatal("Filesystems other than ext2 are not supported"); close(fd); p = device + strlen(device); while (p > device && isdigit(p[-1])) --p; partno = atoi(p); if (partno == 0) fatal("Can't determine partition number for %s", device); upart = 0; mp = (struct mac_partition *) buff; md = (struct mac_driver_desc *) buff; if ((fd = open(bootdev, O_RDONLY)) == -1) fatal("Can't open %s", bootdev); if (read(fd, buff, sizeof (buff)) != sizeof (buff)) fatal("Error reading %s (block 0)", bootdev); if (md->signature != MAC_DRIVER_MAGIC) fatal("%s is not a mac-formatted disk", bootdev); secsize = md->block_size; maxpart = 1; doff = 0; for (part = 1; part <= maxpart; ++part) { lseek(fd, part * secsize, 0); if (read(fd, buff, sizeof (buff)) != sizeof (buff)) fatal("Error reading partition map from %s", bootdev); if (mp->signature != MAC_PARTITION_MAGIC) break; if (part == 1) maxpart = mp->map_count; else if (maxpart != mp->map_count) break; if (first_bootable == 0 && (mp->status & STATUS_BOOTABLE) != 0 && strcasecmp(mp->processor, "PowerPC") == 0) first_bootable = part; if (++upart == partno) { /* This is the one we want */ part_block = part; doff = mp->start_block * (secsize >> 9); break; } } if (upart < partno) fatal("Couldn't locate partition %d on %s", partno, bootdev); } void make_bootable(char *device, char *spart) { int fd; struct mac_partition *mp; char buff[512]; if (part_block == 0) return; if (verbose) printf("Making %s bootable (map entry %d)\n", spart, part_block); if (first_bootable > 0 && first_bootable < part_block) fprintf(stderr, "Warning: prior partition (entry %d) is bootable\n", first_bootable); if ((fd = open(device, O_RDWR)) < 0) fatal("Cannot open %s for writing\n", device); lseek(fd, part_block * secsize, 0); if (read(fd, buff, sizeof(buff)) != sizeof(buff)) fatal("Error reading partition map entry %d from %s\n", part_block, device); mp = (struct mac_partition *) buff; mp->status |= STATUS_BOOTABLE; mp->boot_start = 0; mp->boot_size = 1024; mp->boot_load = FIRST_BASE; mp->boot_load2 = 0; mp->boot_entry = FIRST_BASE; mp->boot_entry2 = 0; strncpy(mp->processor, "PowerPC", sizeof(mp->processor)); if (lseek(fd, part_block * secsize, 0) < 0 || write(fd, buff, sizeof(buff)) != sizeof(buff)) fatal("Couldn't make %s%d bootable: write error\n", device, part_block); } int get_partition_blocks(char *filename) { int fd; int block, i, k; struct stat st; if ((fd = open(filename, O_RDONLY)) == -1) fatal("Cannot find %s", filename); if (fstat(fd, &st) < 0) fatal("Couldn't stat %s", filename); finfo.blocksize = bs; nsect = bs >> 9; for (i = 0;; i++) { block = i; if (i * bs >= st.st_size || ioctl(fd, FIBMAP, &block) < 0 || !block) break; finfo.blknos[i] = block * nsect + doff; } finfo.nblocks = i; close(fd); return 0; } char *new_root = NULL; char *chrootcpy(char *path) { if (new_root && *new_root) { char *buffer = malloc(strlen(new_root) + strlen(path) + 1); strcpy(buffer, new_root); if (new_root[strlen(new_root) - 1] != '/') strcat(buffer, path); else strcat(buffer, path + 1); return buffer; } else return strdup(path); } void write_block_table(char *device, char *config_file, int partno) { int fd; if (verbose) printf("Writing block table to boot block on %s\n", device); strncpy(finfo.quik_vers, "QUIK" VERSION, sizeof(finfo.quik_vers)); finfo.second_base = SECOND_BASE; finfo.conf_part = partno; strncpy(finfo.conf_file, config_file, sizeof(finfo.conf_file)); if ((fd = open(device, O_RDWR)) == -1) fatal("Cannot open %s", device); if (lseek(fd, FIRST_INFO_OFF, SEEK_SET) != FIRST_INFO_OFF) fatal("Seek error on %s", device); if (write(fd, &finfo, sizeof(finfo)) != sizeof(finfo)) fatal("Couldn't update boot block on %s", device); close(fd); } void usage(char *s) { printf("\ QUIK " VERSION " Disk bootstrap installer for Powermac/Linux\n\ Usage: %s [options]\n\ Options:\n\ -r root_path chroots into root_path (all paths relative to this)\n\ -b secondary use secondary as second stage boot instead of /boot/second.b\n\ -i primary install primary as first stage boot, instead of /boot/first.b\n\ -C config specify alternate config file instead of /etc/silo.conf\n\ (the config file has to reside on the same physical disk as\n\ the second stage loader, but can be in a different partition)\n\ -s backup save your old bootblock only if backup doesn't exist yet\n\ -S backup force saving your old bootblock into backup\n\ -f force overwriting of bootblock, even if quik already installed\n\ -v verbose mode\n\ -V show version\n" ,s); exit (1); } int examine_bootblock(char *device, char *filename, int do_backup) { union { char buffer[1024]; int first_word; struct { char pad[FIRST_INFO_OFF]; struct first_info fi; } fi; } u; int fd, rc; FILE *fp; int ret = 0; if ((fd = open(device, O_RDONLY)) == -1) fatal("Cannot open %s", device); if (read (fd, &u, sizeof(u)) != sizeof(u)) fatal("Couldn't read old bootblock"); close(fd); if (u.first_word != 0 && memcmp(u.fi.fi.quik_vers, "QUIK" VERSION, 7) == 0 && u.fi.fi.quik_vers[7] >= '0' && u.fi.fi.quik_vers[7] <= '9') { if (verbose) printf("%s already has QUIK boot block installed\n", device); ret = 1; } if (do_backup) { if (verbose) printf("Copying old bootblock from %s to %s\n", device, filename); if ((fp = fopen(filename, "w")) == NULL) fatal("Cannot create %s", filename); if (rc = fwrite(&u, 1, sizeof(u), fp) != sizeof(u)) fatal("Couldn't write old bootblock to %s", filename); fclose (fp); } return ret; } void install_first_stage(char *device, char *filename) { char buff[1024]; int rc; int fd; FILE *fp; if (verbose) printf("Writing first-stage QUIK boot block to %s\n", device); if ((fd = open(device, O_WRONLY)) == -1) fatal("Couldn't open device %s for writing", device); if ((fp = fopen(filename, "r")) == NULL) fatal("Couldn't open primary boot file %s", filename); rc = fread(buff, 1, 1024, fp); if (rc <= 0) fatal("Couldn't read new quik bootblock from %s", filename); if (lseek(fd, 0, 0) != 0) fatal("Couldn't seek on %s", device); if (write(fd, buff, rc) != rc) fatal("Couldn't write quik bootblock to %s", device); close(fd); fclose(fp); } char *find_dev(int number) { #define DEVNAME "/dev" DIR *dp; char *p; struct dirent *dir; static char name[PATH_MAX+1]; struct stat s; if (!number) return NULL; if ((dp = opendir(DEVNAME)) == NULL) return NULL; strcpy(name, DEVNAME "/"); p = strchr(name, 0); while (dir = readdir(dp)) { strcpy(p, dir->d_name); if (stat(name, &s) < 0) return NULL; if (S_ISBLK(s.st_mode) && s.st_rdev == number) return name; } return NULL; } char * resolve_to_dev(char *buffer, dev_t dev) { char *p, *q, *b, *r; char *fn; int len, c; struct stat st3; char readlinkbuf[2048]; char buffer2[2048]; for (p = buffer;;) { q = strchr (p, '/'); if (q) { c = *q; *q = 0; } else c = 0; fn = *buffer? buffer: "/"; if (lstat(fn, &st3) < 0) fatal("Couldn't stat %s\n", fn); if (st3.st_dev == dev) { *q = c; return q; } if (S_ISLNK(st3.st_mode)) { len = readlink(buffer, readlinkbuf, 2048); if (len < 0) fatal ("Couldn't readlink %s\n", fn); readlinkbuf[len] = 0; if (*readlinkbuf == '/') { b = r = readlinkbuf; } else { b = buffer2; strcpy (b, buffer); r = strchr(b, 0); *r++ = '/'; strcpy(r, readlinkbuf); } if (c) { r += len; if (r[-1] != '/') *r++ = '/'; strcpy (r, q + 1); } strcpy (buffer, b); p = buffer + 1; } else { *q = c; p = q + 1; if (!c) fatal("Internal error\n"); } } } int main(int argc,char **argv) { char *name = NULL, *config_file, *install = NULL, *secondary, *backup; int c; int version = 0; struct stat st1, st2; int fd; int force_backup = 0; int config_file_partno = 1; char *p, *basedev; char bootdev[1024]; char spart[1024]; char buffer[1024]; int force = 0; int f, inc_name; extern int optind; extern char *optarg; /* * Test if we're being run on a chrp machine. We don't * need to be run on a chrp machine so print a message * to this effect and exit gracefully. * -- Cort */ { FILE *f; char s[256]; if ( (f = fopen("/proc/cpuinfo","r")) == NULL ) { fprintf(stderr,"Could not open /proc/cpuinfo!\n"); exit(1); } while (!feof(f)) { fgets(s, 256, f); if ( !strncmp(s,"machine\t\t: CHRP", 15 ) ) { fprintf(stderr, "Quik does not need to be run " "on CHRP machines.\n"); exit(0); } } } config_file = NULL; backup = DFL_BACKUP; secondary = DFL_SECONDARY; new_root = NULL; name = argv[0]; while ((c = getopt(argc, argv, "b:i:fC:S:s:r:vVh")) != -1) { switch(c) { case 'b': secondary = optarg; break; case 'i': install = optarg; break; case 'f': force = 1; break; case 'C': config_file = optarg; break; case 'S': backup = optarg; force_backup = 1; break; case 's': backup = optarg; break; case 'r': new_root = optarg; break; case 'v': verbose = 1; break; case 'V': version = 1; break; case 'h': usage(name); break; } } if (version) { printf("QUIK version " VERSION "\n"); exit(0); } if (optind < argc) usage(name); if (!new_root) new_root = getenv("ROOT"); secondary = chrootcpy(secondary); if (stat(secondary, &st1) < 0) fatal("Cannot open second stage loader %s", secondary); /* work out what sort of disk this is and how to interpret the minor number */ unit_shift = 6; part_mask = 0x3f; inc_name = 1; switch (MAJOR(st1.st_dev)) { case SD_MAJOR: unit_shift = 4; part_mask = 0x0f; basedev = "/dev/sda"; break; case HDA_MAJOR: basedev = "/dev/hda"; break; case HDC_MAJOR: basedev = "/dev/hdc"; break; case HDE_MAJOR: basedev = "/dev/hde"; break; case HDG_MAJOR: basedev = "/dev/hdg"; break; default: p = find_dev(st1.st_dev); if (p == NULL) fatal("Couldn't find out what device second stage boot is on"); basedev = p; unit_shift = 0; part_mask = 0; inc_name = 0; } strcpy(bootdev, basedev); if (inc_name) bootdev[7] += UNIT(st1.st_dev); strcpy(spart, bootdev); if (PART(st1.st_dev) != 0) sprintf(spart+8, "%d", PART(st1.st_dev)); if (verbose) printf("Second-stage loader is on %s\n", spart); backup = chrootcpy (backup); if (config_file == NULL) { config_file = chrootcpy(DFL_CONFIG); if (stat(config_file, &st2) < 0) { char *p = chrootcpy(ALT_CONFIG); if (stat(p, &st2) == 0) { if (verbose) printf("Using alternate config file %s\n", ALT_CONFIG); config_file = p; } } } else config_file = chrootcpy (config_file); if (stat(config_file, &st2) >= 0) { if (MAJOR(st2.st_dev) != MAJOR(st1.st_dev) || UNIT(st2.st_dev) != UNIT(st1.st_dev) || PART(st2.st_dev) != PART(st1.st_dev)) fatal("Config file %s has to be on the %s device (any partition)", config_file, bootdev); strcpy(buffer, config_file); config_file = resolve_to_dev(buffer, st2.st_dev); if (inc_name) config_file_partno = PART(st2.st_dev); else config_file_partno = 1; if (verbose) printf("Config file is on partition %d\n", config_file_partno); } if (backup && !force_backup) { if (stat(backup, &st2) < 0) force_backup = 1; } read_sb(spart, bootdev); if (!examine_bootblock(spart, backup, force_backup) || install || force) { if (!install) install = chrootcpy(DFL_PRIMARY); else if (*install == '/') install = chrootcpy(install); install_first_stage(spart, install); make_bootable(bootdev, spart); } get_partition_blocks(secondary); write_block_table(spart, config_file, config_file_partno); sync(); exit(0); } quik-2.1/quik.spec0000644000175000001440000000640007062261060014455 0ustar simonusers00000000000000Summary: Disk bootstrap and installer for Linux/PPC Name: quik Version: 2.0 Release: 0e Copyright: GPL Group: Base URL: http://www.ppc.kernel.org/ Packager: Cort Dougan Source: ftp://ftp.ppc.kernel.org/pub/linuxppc/quik/quik-2.0.tar.gz BuildRoot: /tmp/quik-root ExclusiveArch: ppc %description The quik package provides the functionality necessary for booting a Linux/PPC PowerMac or CHRP system from disk. It includes first and second stage disk bootstrap and a program for installing the first stage bootstrap on the root disk. %prep %setup %build make %install make install DESTDIR="$RPM_BUILD_ROOT" %post leave() { echo '*****************************************************************' echo '* The Quik installer script was not able to find a partition *' echo '* to install into. This may be due to an error or if you are *' echo '* installing onto a drive other than /dev/sda quik errs on the *' echo '* side of caution when installing and doesn''t not write itself *' echo '* out to disk. If you do want to finish the install you can do *' echo '* it by hand with: dd if=/boot/second of=/dev/XXX where XXX is *' echo '* the partition you want to install the bootloader into. *' echo '*****************************************************************' exit } if [ ! -z "`grep CHRP /proc/cpuinfo`" ] ; then echo CHRP system detected. # PART=`fdisk -l | fgrep "PPC PReP"` PART=`cfdisk -P s | fgrep "PPC PReP"` if [ -z "$PART" ] ; then echo '*********************************************************' echo '* You must create a PPC PReP Boot partition (type 0x41) *' echo '* for the CHRP bootloader to be installed. *' echo '*********************************************************' leave fi if [ `echo "$PART" | wc -l` != 1 ] ; then echo '**************************************************************' echo '* There are more than 1 PPC PReP Boot partitions (type 0x41) *' echo '* on this system. Aborting install rather than picking one. *' echo '**************************************************************' leave fi if [ -z "`echo "$PART" | grep "Boot (80)"`" ] ; then echo '***************************************************************' echo '* The PPC PReP Boot partition (type 0x41) is not marked as *' echo '* bootable. You will need to mark this partition as bootable *' echo '* before Quik can be installed onto it. *' echo '**************************************************************' leave fi P=`echo "$PART" | awk '{print $1}'` # assume /dev/sda!!! if [ "${P}" != "1" ] ; then echo '***************************************************************' echo '* You do not have sda1 setup as the boot partition. This *' echo '* will work but Quik will not know where the configuration *' echo '* file is. *' echo '***************************************************************' fi P=/dev/sda${P} echo Installing onto $P dd if=/boot/second of=$P fi %clean rm -rf $RPM_BUILD_ROOT %files /sbin/quik /boot/first.b /boot/second.b /boot/second %config /etc/quik.conf /usr/man/man5/quik.conf.5 /usr/man/man8/quik.8 /usr/man/man8/bootstrap.8 quik-2.1/second/0000755000175000001440000000000007062261060014103 5ustar simonusers00000000000000quik-2.1/second/Makefile0000644000175000001440000000122507062261060015543 0ustar simonusers00000000000000## ## Linux Loader for Macintosh ## CFLAGS = -I../include -O2 -D__NO_STRING_INLINES LDFLAGS= -Ttext 0x3e0000 OBJS = crt0.o printf.o malloc.o main.o cmdline.o disk.o file.o \ cfg.o strtol.o prom.o cache.o string.o setjmp.o ctype.o \ nosys.o all: second.b second: $(OBJS) $(LD) $(LDFLAGS) -Bstatic -o second $(OBJS) -lext2fs crt0.o: crt0.S main.o: main.c quik.h malloc.o: malloc.c quik.h printf.o: printf.c quik.h cmdline.o: cmdline.c quik.h disk.o: disk.c quik.h file.o: file.c quik.h cfg.o: cfg.c quik.h clean: $(RM) *.o second second.b core *~ second.b: second ../util/elfextract second second.b quik-2.1/second/cache.S0000644000175000001440000000044307062261060015273 0ustar simonusers00000000000000/* * Flush the dcache and invalidate the icache for a range of addresses. * * flush_cache(addr, len) */ .global flush_cache flush_cache: addi 4,4,0x1f /* len = (len + 0x1f) / 0x20 */ rlwinm. 4,4,27,5,31 mtctr 4 beqlr 1: dcbf 0,3 icbi 0,3 addi 3,3,0x20 bdnz 1b sync isync blr quik-2.1/second/cfg.c0000644000175000001440000002235207062261060015012 0ustar simonusers00000000000000/* Handling and parsing of silo.conf Copyright (C) 1995 Werner Almesberger 1996 Jakub Jelinek 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include "quik.h" typedef enum { cft_strg, cft_flag, cft_end } CONFIG_TYPE; typedef struct { CONFIG_TYPE type; char *name; void *data; } CONFIG; #define MAX_TOKEN 200 #define MAX_VAR_NAME MAX_TOKEN #define EOF -1 CONFIG cf_options[] = { {cft_strg, "device", NULL}, {cft_strg, "partition", NULL}, {cft_strg, "default", NULL}, {cft_strg, "timeout", NULL}, {cft_strg, "message", NULL}, {cft_strg, "root", NULL}, {cft_strg, "ramdisk", NULL}, {cft_flag, "read-only", NULL}, {cft_flag, "read-write", NULL}, {cft_strg, "append", NULL}, {cft_strg, "initrd", NULL}, {cft_flag, "initrd-prompt", NULL}, {cft_strg, "initrd-size", NULL}, {cft_flag, "pause-after", NULL}, {cft_strg, "pause-message", NULL}, {cft_strg, "init-code", NULL}, {cft_strg, "init-message", NULL}, {cft_end, NULL, NULL}}; CONFIG cf_image[] = { {cft_strg, "image", NULL}, {cft_strg, "label", NULL}, {cft_strg, "alias", NULL}, {cft_strg, "device", NULL}, {cft_strg, "partition", NULL}, {cft_strg, "root", NULL}, {cft_strg, "ramdisk", NULL}, {cft_flag, "read-only", NULL}, {cft_flag, "read-write", NULL}, {cft_strg, "append", NULL}, {cft_strg, "literal", NULL}, {cft_strg, "initrd", NULL}, {cft_flag, "initrd-prompt", NULL}, {cft_strg, "initrd-size", NULL}, {cft_flag, "pause-after", NULL}, {cft_strg, "pause-message", NULL}, {cft_end, NULL, NULL}}; static char flag_set; static char *last_token = NULL, *last_item = NULL, *last_value = NULL; static int line_num; static int back = 0; /* can go back by one char */ static char *currp; static char *endp; static char *file_name; static CONFIG *curr_table = cf_options; static jmp_buf env; static struct IMAGES { CONFIG table[sizeof (cf_image) / sizeof (cf_image[0])]; struct IMAGES *next; } *images = NULL; void cfg_error (char *msg,...) { va_list ap; va_start (ap, msg); printf ("Config file error: "); vprintf (msg, ap); va_end (ap); printf (" near line %d in file %s\n", line_num, file_name); longjmp (env, 1); } void cfg_warn (char *msg,...) { va_list ap; va_start (ap, msg); printf ("Config file warning: "); vprintf (msg, ap); va_end (ap); printf (" near line %d in file %s\n", line_num, file_name); } inline int getc () { if (currp == endp) return EOF; return *currp++; } #define next_raw next static int next (void) { int ch; if (!back) return getc (); ch = back; back = 0; return ch; } static void again (int ch) { back = ch; } static char *cfg_get_token (void) { char buf[MAX_TOKEN + 1]; char *here; int ch, escaped; if (last_token) { here = last_token; last_token = NULL; return here; } while (1) { while (ch = next (), ch == ' ' || ch == '\t' || ch == '\n') if (ch == '\n') line_num++; if (ch == EOF) return NULL; if (ch != '#') break; while (ch = next_raw (), ch != '\n') if (ch == EOF) return NULL; line_num++; } if (ch == '=') return strdup ("="); if (ch == '"') { here = buf; while (here - buf < MAX_TOKEN) { if ((ch = next ()) == EOF) cfg_error ("EOF in quoted string"); if (ch == '"') { *here = 0; return strdup (buf); } if (ch == '\\') { ch = next (); switch (ch) { case '"': case '\\': break; case '\n': while ((ch = next ()), ch == ' ' || ch == '\t'); if (!ch) continue; again (ch); ch = ' '; break; case 'n': ch = '\n'; break; default: cfg_error ("Bad use of \\ in quoted string"); } } else if (ch == '\n') cfg_error ("newline is not allowed in quoted strings"); *here++ = ch; } cfg_error ("Quoted string is too long"); return 0; /* not reached */ } here = buf; escaped = 0; while (here - buf < MAX_TOKEN) { if (escaped) { if (ch == EOF) cfg_error ("\\ precedes EOF"); if (ch == '\n') line_num++; else *here++ = ch == '\t' ? ' ' : ch; escaped = 0; } else { if (ch == ' ' || ch == '\t' || ch == '\n' || ch == '#' || ch == '=' || ch == EOF) { again (ch); *here = 0; return strdup (buf); } if (!(escaped = (ch == '\\'))) *here++ = ch; } ch = next (); } cfg_error ("Token is too long"); return 0; /* not reached */ } static void cfg_return_token (char *token) { last_token = token; } static int cfg_next (char **item, char **value) { char *this; if (last_item) { *item = last_item; *value = last_value; last_item = NULL; return 1; } *value = NULL; if (!(*item = cfg_get_token ())) return 0; if (!strcmp (*item, "=")) cfg_error ("Syntax error"); if (!(this = cfg_get_token ())) return 1; if (strcmp (this, "=")) { cfg_return_token (this); return 1; } if (!(*value = cfg_get_token ())) cfg_error ("Value expected at EOF"); if (!strcmp (*value, "=")) cfg_error ("Syntax error after %s", *item); return 1; } static void cfg_return (char *item, char *value) { last_item = item; last_value = value; } static int cfg_set (char *item, char *value) { CONFIG *walk; if (!strcasecmp (item, "image")) { struct IMAGES **p = &images; while (*p) p = &((*p)->next); *p = malloc (sizeof (struct IMAGES)); (*p)->next = 0; curr_table = ((*p)->table); memcpy (curr_table, cf_image, sizeof (cf_image)); } for (walk = curr_table; walk->type != cft_end; walk++) { if (walk->name && !strcasecmp (walk->name, item)) { if (value && walk->type != cft_strg) cfg_warn ("'%s' doesn't have a value", walk->name); else if (!value && walk->type == cft_strg) cfg_warn ("Value expected for '%s'", walk->name); else { if (walk->data) cfg_warn ("Duplicate entry '%s'", walk->name); if (walk->type == cft_flag) walk->data = &flag_set; else if (walk->type == cft_strg) walk->data = value; } break; } } if (walk->type != cft_end) return 1; cfg_return (item, value); return 0; } int cfg_parse (char *cfg_file, char *buff, int len) { char *item, *value; file_name = cfg_file; currp = buff; endp = currp + len; if (setjmp (env)) return -1; while (1) { if (!cfg_next (&item, &value)) return 0; if (!cfg_set (item, value)) return -1; free (item); } } static char *cfg_get_strg_i (CONFIG * table, char *item) { CONFIG *walk; for (walk = table; walk->type != cft_end; walk++) if (walk->name && !strcasecmp (walk->name, item)) return walk->data; return 0; } char *cfg_get_strg (char *image, char *item) { struct IMAGES *p; char *label, *alias; char *ret; if (!image) return cfg_get_strg_i (cf_options, item); for (p = images; p; p = p->next) { label = cfg_get_strg_i (p->table, "label"); if (!label) { label = cfg_get_strg_i (p->table, "image"); alias = strrchr (label, '/'); if (alias) label = alias + 1; } alias = cfg_get_strg_i (p->table, "alias"); if (!strcmp (label, image) || (alias && !strcmp (alias, image))) { ret = cfg_get_strg_i (p->table, item); if (!ret) ret = cfg_get_strg_i (cf_options, item); return ret; } } return 0; } int cfg_get_flag (char *image, char *item) { return !!cfg_get_strg (image, item); } static int printl_count = 0; static void printlabel (char *label) { int len = strlen (label); if (!printl_count) printf ("\n"); printf ("%s", label); while (len++ < 25) putchar (' '); printl_count++; if (printl_count == 3) printl_count = 0; } void cfg_print_images (void) { struct IMAGES *p; char *label, *alias; printl_count = 0; for (p = images; p; p = p->next) { label = cfg_get_strg_i (p->table, "label"); if (!label) { label = cfg_get_strg_i (p->table, "image"); alias = strrchr (label, '/'); if (alias) label = alias + 1; } alias = cfg_get_strg_i (p->table, "alias"); printlabel (label); if (alias) printlabel (alias); } printf ("\nYou can also type in custom image locations, in the form\n" "{prom_path;}partno/path_to_image or {prom_path;}{partno}[start-end]\n"); } char *cfg_get_default (void) { char *label; char *ret = cfg_get_strg_i (cf_options, "default"); if (ret) return ret; if (!images) return 0; ret = cfg_get_strg_i (images->table, "label"); if (!ret) { ret = cfg_get_strg_i (images->table, "image"); label = strrchr (ret, '/'); if (label) ret = label + 1; } return ret; } quik-2.1/second/cmdline.c0000644000175000001440000000271707062261060015671 0ustar simonusers00000000000000/* Prompt handling Copyright (C) 1996 Maurizio Plaza 1996 Jakub Jelinek 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "quik.h" #define CMD_LENG 512 char cbuff[CMD_LENG]; void cmdinit() { cbuff[0] = 0; } void cmdedit(void (*tabfunc)(void), int c) { int x; for (x = 0; x < CMD_LENG - 1 && cbuff[x] != 0; x++) ; prom_print(cbuff); if (c == -1) c = getchar(); while (c != -1 && c != '\n' && c != '\r') { if (c == '\t' && tabfunc) (*tabfunc)(); if (c == '\b' || c == 0x7F) { if (x > 0) { --x; prom_print("\b \b"); } } else if (c >= ' ' && x < CMD_LENG - 1) { cbuff[x] = c; putchar(c); ++x; } c = getchar(); } cbuff[x] = 0; return; } void cmdfill(const char *d) { strncpy(cbuff, d, CMD_LENG); cbuff[CMD_LENG - 1] = 0; } quik-2.1/second/crt0.S0000644000175000001440000000003607062261060015076 0ustar simonusers00000000000000 .globl _start _start: b main quik-2.1/second/ctype.c0000644000175000001440000000056207062261060015376 0ustar simonusers00000000000000#include int tolower(int c) { if ('A' <= c && c <= 'Z') c += 'a' - 'A'; return c; } int strcasecmp(const char *s1, const char *s2) { int c1, c2; for (;;) { c1 = *s1++; if ('A' <= c1 && c1 <= 'Z') c1 += 'a' - 'A'; c2 = *s2++; if ('A' <= c2 && c2 <= 'Z') c2 += 'a' - 'A'; if (c1 != c2 || c1 == 0) return c1 - c2; } } quik-2.1/second/disk.c0000644000175000001440000000354407062261060015207 0ustar simonusers00000000000000#include "quik.h" #include "prom.h" #include char bootdevice[512]; static char current_devname[512]; static ihandle current_dev; int open(char *device) { current_dev = call_prom("open", 1, 1, device); if (current_dev == (ihandle) 0 || current_dev == (ihandle) -1) { printf("\nCouldn't open %s\n", device); return -1; } strcpy(current_devname, device); return 0; } char * strstr(const char * s1,const char * s2) { int l1, l2; l2 = strlen(s2); if (!l2) return (char *) s1; l1 = strlen(s1); while (l1 >= l2) { l1--; if (!memcmp(s1,s2,l2)) return (char *) s1; s1++; } return NULL; } int diskinit() { char *p; extern unsigned int is_chrp; prom_get_chosen("bootpath", bootdevice, sizeof(bootdevice)); if (bootdevice[0] == 0) { prom_get_options("boot-device", bootdevice, sizeof(bootdevice)); if (bootdevice[0] == 0) fatal("Couldn't determine boot device"); } p = strchr(bootdevice, ':'); if (p != 0) *p = 0; /* * Hack for the time being. We need at the raw disk device, not * just a few partitions. -- Cort */ if ( is_chrp ) sprintf(bootdevice, "disk:0"); if( open(bootdevice) ) { /* * Some chrp machines do not have a 'disk' alias so * try this if disk:0 fails * -- Cort */ sprintf(bootdevice, "/pci@fee00000/scsi@c/sd@8:0"); return open(bootdevice); } return 0; } int read(char *buf, int nbytes, long long offset) { int nr; if (nbytes == 0) return 0; nr = (int)call_prom("seek", 3, 1, current_dev, (unsigned int) (offset >> 32), (unsigned int) (offset & 0xFFFFFFFF)); nr = (int) call_prom("read", 3, 1, current_dev, buf, nbytes); return nr; } void close() { } int setdisk(char *device) { if (strcmp(device, current_devname) == 0) return 0; close(); return open(device); } quik-2.1/second/file.c0000644000175000001440000002531207062261060015171 0ustar simonusers00000000000000/* File related stuff Copyright (C) 1996 Maurizio Plaza 1996 Jakub Jelinek 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #define _STDLIB_H #include #include #include #include "quik.h" typedef int FILE; #include #include #include #include static errcode_t linux_open (const char *name, int flags, io_channel * channel); static errcode_t linux_close (io_channel channel); static errcode_t linux_set_blksize (io_channel channel, int blksize); static errcode_t linux_read_blk (io_channel channel, unsigned long block, int count, void *data); static errcode_t linux_write_blk (io_channel channel, unsigned long block, int count, const void *data); static errcode_t linux_flush (io_channel channel); /* * Some firmware trashes the first part of the data section - * this protects it. * -- Cort */ char protect[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; static struct struct_io_manager struct_linux_manager = { EXT2_ET_MAGIC_IO_MANAGER, "linux I/O Manager", linux_open, linux_close, linux_set_blksize, linux_read_blk, linux_write_blk, linux_flush }; extern int read(char *, int, long long); ext2_filsys fs = 0; static ino_t root, cwd; static io_manager linux_io_manager = &struct_linux_manager; static unsigned int bs; /* Blocksize */ static unsigned long long doff; /* Byte offset where partition starts */ static int decompress; static unsigned char *filebuffer; static unsigned char *filelimit; static unsigned long block_no; static unsigned long lblock; static int block_cnt; static enum { ext2 } type; static unsigned long size; static int read_mac_partition(int part) { int rc, upart, blocks_in_map, i; int secsize; char blk[512]; struct mac_partition *mp = (struct mac_partition *) blk; struct mac_driver_desc *md = (struct mac_driver_desc *) blk; rc = read(blk, 512, 0LL); if (rc != 512) { fatal("Cannot read driver descriptor"); return 0; } if (md->signature != MAC_DRIVER_MAGIC) { /*fatal("Not a macintosh-formatted disk");*/ return 0; } secsize = md->block_size; blocks_in_map = 1; upart = 0; for (i = 1; i <= blocks_in_map; ++i) { if (read(blk, 512, (long long) i * secsize) != 512) { /*fatal("Error reading partition map");*/ return 0; } if (mp->signature != MAC_PARTITION_MAGIC) break; if (i == 1) blocks_in_map = mp->map_count; ++upart; /* If part is 0, use the first bootable partition. */ if (part == upart || (part == 0 && (mp->status & STATUS_BOOTABLE) != 0 && strcasecmp(mp->processor, "powerpc") == 0)) { doff = (long long) mp->start_block * secsize; return 1; } } /*fatal("Partition %d not found", part);*/ return 0; } unsigned long swab32(unsigned long value) { __u32 result; __asm__("rlwimi %0,%1,24,16,23\n\t" "rlwimi %0,%1,8,8,15\n\t" "rlwimi %0,%1,24,0,7" : "=r" (result) : "r" (value), "0" (value >> 24)); return result; } static int read_dos_partition(int part) { int rc, i, v; char blk[512]; struct partition { unsigned char boot_ind; /* 0x80 - active */ unsigned char head; /* starting head */ unsigned char sector; /* starting sector */ unsigned char cyl; /* starting cylinder */ unsigned char sys_ind; /* What partition type */ unsigned char end_head; /* end head */ unsigned char end_sector; /* end sector */ unsigned char end_cyl; /* end cylinder */ unsigned int start_sect; /* starting sector counting from 0 */ unsigned int nr_sects; /* nr of sectors in partition */ }; struct partition *p; rc = read(blk, 512, 0LL); if (rc != 512) { fatal("Cannot read first block"); return 0; } /* check the MSDOS partition magic */ if ( (blk[0x1fe] != 0x55) || (blk[0x1ff] != 0xaa) ) { printf("No MSDOS partition magic number on disk!\n"); return 0; } if ( part >= 4 ) fatal("msdos partition numbers > 4"); p = (struct partition *)&blk[0x1be]; for ( i = 1 ; i != part ; i++,p++) /* nothing */ ; doff = swab32(p->start_sect)*512; return 1; } int sprintf (char *buf, char *fmt,...) { strcpy (buf, fmt); } void com_err (const char *a, long i, const char *fmt,...) { printf ((char *) fmt); } static errcode_t linux_open (const char *name, int flags, io_channel * channel) { int partno; io_channel io; if (!name) return EXT2_ET_BAD_DEVICE_NAME; io = (io_channel) malloc (sizeof (struct struct_io_channel)); if (!io) return EXT2_ET_BAD_DEVICE_NAME; memset (io, 0, sizeof (struct struct_io_channel)); io->magic = EXT2_ET_MAGIC_IO_CHANNEL; io->manager = linux_io_manager; io->name = (char *) malloc (strlen (name) + 1); strcpy (io->name, name); io->block_size = bs; io->read_error = 0; io->write_error = 0; doff = 0; partno = *(name + strlen (name) - 1) - '0'; if (!read_mac_partition(partno) && !read_dos_partition(partno) ) return EXT2_ET_BAD_DEVICE_NAME; *channel = io; return 0; } static errcode_t linux_close (io_channel channel) { } static errcode_t linux_set_blksize (io_channel channel, int blksize) { channel->block_size = bs = blksize; } static errcode_t linux_read_blk (io_channel channel, unsigned long block, int count, void *data) { int size; long long tempb; tempb = (((long long) block) * ((long long)bs)) + doff; size = (count < 0) ? -count : count * bs; if (read (data, size, tempb) != size) { printf ("\nRead error on block %d", block); return EXT2_ET_SHORT_READ; } return 0; } static errcode_t linux_write_blk (io_channel channel, unsigned long block, int count, const void *data) { } static errcode_t linux_flush (io_channel channel) { } static int open_ext2 (char *device) { int retval; retval = ext2fs_open (device, EXT2_FLAG_RW, 0, 0, linux_io_manager, &fs); if (retval) return 0; root = cwd = EXT2_ROOT_INO; return 1; } static void rotate (int freq) { static int i = 0; static char rot[] = "\\|/-"; if (!(i % freq)) printf ("%c\b", rot[(i / freq) % 4]); i++; } static int dump_block(ext2_filsys fs, blk_t *blocknr, int lg_block, void *private) { size_t nbytes, nzero; if (lg_block < 0) return 0; rotate(5); if (block_no && block_cnt < 256 && *blocknr == block_no + block_cnt && lg_block == lblock + block_cnt) { ++block_cnt; return 0; } if (block_no) { nbytes = block_cnt * bs; if (io_channel_read_blk(fs->io, block_no, block_cnt, filebuffer)) return BLOCK_ABORT; filebuffer += nbytes; lblock += block_cnt; block_no = 0; } if (lg_block && lg_block != lblock) { nzero = (lg_block - lblock) * bs; memset(filebuffer, 0, nzero); filebuffer += nzero; lblock = lg_block; } if (*blocknr) { block_no = *blocknr; block_cnt = 1; } return 0; } static int dump_finish (void) { if (block_no) { blk_t tmp = 0; if (dump_block(fs, &tmp, 0, 0)) return 0; } if (lblock * bs < size) memset(filebuffer, 0, size - lblock * bs); return 1; } static int dump_ext2(ino_t inode, char *filename) { errcode_t retval; block_no = lblock = 0; block_cnt = 0; retval = ext2fs_block_iterate(fs, inode, 0, 0, dump_block, 0); if (retval) { printf ("Error %d reading %s", retval, filename); return 0; } return dump_finish(); } int dump_device_range(char *filename, char *bogusdev, int *len, void (*lenfunc)(int, char **, char **)) { /* Range of blocks on physical block device */ int start, end = -1; int retval; char *p; bs = 512; p = strchr (filename, '-'); filename++; if (p && *filename >= '0' && *filename <= '9') { *p = 0; start = strtol(filename, NULL, 0); filename = p + 1; p = strchr(filename, ']'); if (p && *filename >= '0' && *filename <= '9' && !p[1]) { *p = 0; end = strtol(filename, NULL, 0); } } if (end == -1) { printf ("\n" "Ranges of physical blocks are specified as {prom_path:}{partno}[xx-yy]\n" "where {} means optional part, partno defaults to 0 (i.e. whole disk)\n" "and xx is the starting block (chunk of 512 bytes) and yy end (not\n" "inclusive, i.e. yy won't be read)\n"); return 0; } if (lenfunc) (*lenfunc)((end - start) << 9, (char **)&filebuffer, (char **)&filelimit); fs = (ext2_filsys) malloc (sizeof (struct struct_ext2_filsys)); if (fs) { if (!linux_open(bogusdev, 0, &fs->io)) { blk_t tmp; block_no = 0; for (tmp = start; tmp < end; tmp++) { if (dump_block (fs, &tmp, tmp - start, 0)) break; } if (tmp == end && dump_finish()) { if (len) *len = (end - start) << 9; return 1; } } } printf ("\nInternal error while loading blocks from device\n"); return 0; } int get_len(ino_t inode) { struct ext2_inode ei; if (ext2fs_read_inode (fs, inode, &ei)) return 0; return ei.i_size; } int load_file(char *device, int partno, char *filename, char *buffer, char *limit, int *len, int dogunzip, void (*lenfunc)(int, char **, char **)) { ino_t inode; int retval; char bogusdev[] = "/dev/sdaX"; if (device == 0) device = bootdevice; if (setdisk(device) < 0) return 0; bogusdev[8] = partno + '0'; filebuffer = buffer; filelimit = limit; decompress = dogunzip & 1; if (*filename == '[') return dump_device_range (filename, bogusdev, len, lenfunc); if (!open_ext2(bogusdev)) { fatal ("Unable to open filesystem"); return 0; } type = ext2; if (retval = ext2fs_namei(fs, root, cwd, filename, &inode)) { printf("\nInode error #%d while loading file %s.", retval, filename); ext2fs_close(fs); return 0; } size = get_len(inode); if (buffer + size > limit) { fatal ("Image too large to fit in destination"); return 0; } if (lenfunc) (*lenfunc)(size, (char **)&filebuffer, (char **)&filelimit); retval = 0; if (inode) retval = dump_ext2(inode, filename); if (retval && len) *len = size; ext2fs_close(fs); return retval; } quik-2.1/second/main.c0000644000175000001440000003001207062261060015167 0ustar simonusers00000000000000/* Second stage boot loader Copyright (C) 1996 Paul Mackerras. Because this program is derived from the corresponding file in the silo-0.64 distribution, it is also Copyright (C) 1996 Pete A. Zaitcev 1996 Maurizio Plaza 1996 David S. Miller 1996 Miguel de Icaza 1996 Jakub Jelinek 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ #undef BOOTINFO #include "quik.h" #include #include #include #ifdef BOOTINFO #include #endif #define TMP_BUF ((unsigned char *) 0x14000) #define TMP_END ((unsigned char *) SECOND_BASE) #define ADDRMASK 0x0fffffff char quik_conf[40]; int quik_conf_part; unsigned int is_chrp = 0; extern int start; extern char bootdevice[]; int useconf = 0; static int pause_after; static char *pause_message = "Type go to continue.\n"; static char given_bootargs[512]; static int given_bootargs_by_user = 0; #define DEFAULT_TIMEOUT -1 void fatal(const char *msg) { printf("\nFatal error: %s\n", msg); } void maintabfunc (void) { if (useconf) { cfg_print_images(); printf("boot: %s", cbuff); } } void parse_name(char *imagename, int defpart, char **device, int *part, char **kname) { int n; char *endp; /* * Assume partition 2 if no other has been explicitly set * in the config file on chrp -- Cort */ if ( defpart == -1 ) defpart = 2; *kname = strchr(imagename, ':'); if (!*kname) { *kname = imagename; *device = 0; } else { **kname = 0; (*kname)++; *device = imagename; } n = strtol(*kname, &endp, 0); if (endp != *kname) { *part = n; *kname = endp; } else if (defpart != -1) *part = defpart; else *part = 0; /* Range */ if (**kname == '[') return; /* Path */ if (**kname != '/') *kname = 0; } void word_split(char **linep, char **paramsp) { char *p; *paramsp = 0; p = *linep; if (p == 0) return; while (*p == ' ') ++p; if (*p == 0) { *linep = 0; return; } *linep = p; while (*p != 0 && *p != ' ') ++p; while (*p == ' ') *p++ = 0; if (*p != 0) *paramsp = p; } char * make_params(char *label, char *params) { char *p, *q; static char buffer[2048]; q = buffer; *q = 0; p = cfg_get_strg(label, "literal"); if (p) { strcpy(q, p); q = strchr(q, 0); if (*params) { if (*p) *q++ = ' '; strcpy(q, params); } return buffer; } p = cfg_get_strg(label, "root"); if (p) { strcpy (q, "root="); strcpy (q + 5, p); q = strchr (q, 0); *q++ = ' '; } if (cfg_get_flag(label, "read-only")) { strcpy (q, "ro "); q += 3; } if (cfg_get_flag(label, "read-write")) { strcpy (q, "rw "); q += 3; } p = cfg_get_strg(label, "ramdisk"); if (p) { strcpy (q, "ramdisk="); strcpy (q + 8, p); q = strchr (q, 0); *q++ = ' '; } p = cfg_get_strg (label, "append"); if (p) { strcpy (q, p); q = strchr (q, 0); *q++ = ' '; } *q = 0; pause_after = cfg_get_flag (label, "pause-after"); p = cfg_get_strg(label, "pause-message"); if (p) pause_message = p; if (*params) strcpy(q, params); return buffer; } int get_params(char **device, int *part, char **kname, char **params) { int defpart = -1; char *defdevice = 0; char *p, *q, *endp; int c, n; char *imagename = 0, *label; int timeout = -1; int beg = 0, end; static int first = 1; static char bootargs[512]; pause_after = 0; *params = ""; if (first) { first = 0; prom_get_chosen("bootargs", bootargs, sizeof(bootargs)); imagename = bootargs; word_split(&imagename, params); /* CHRP has garbage here -- Cort */ if ( is_chrp ) imagename[0] = 0; timeout = DEFAULT_TIMEOUT; if (useconf && (q = cfg_get_strg(0, "timeout")) != 0 && *q != 0) timeout = strtol(q, NULL, 0); } printf("boot: "); c = -1; if (timeout != -1) { beg = get_ms(); if (timeout > 0) { end = beg + 100 * timeout; do { c = nbgetchar(); } while (c == -1 && get_ms() <= end); } if (c == -1) c = '\n'; } if (c == '\n') { printf("%s", imagename); if (*params) printf(" %s", *params); printf("\n"); } else { cmdinit(); cmdedit(maintabfunc, c); printf("\n"); strcpy(given_bootargs, cbuff); given_bootargs_by_user = 1; imagename = cbuff; word_split(&imagename, params); } /* chrp gets this wrong, force it -- Cort */ if ( useconf && (imagename[0] == 0) ) imagename = cfg_get_default(); label = 0; defdevice = bootdevice; if (useconf) { defdevice = cfg_get_strg(0, "device"); p = cfg_get_strg(0, "partition"); if (p) { n = strtol(p, &endp, 10); if (endp != p && *endp == 0) defpart = n; } p = cfg_get_strg(0, "pause-message"); if (p) pause_message = p; p = cfg_get_strg(imagename, "image"); if (p && *p) { label = imagename; imagename = p; defdevice = cfg_get_strg(label, "device"); p = cfg_get_strg(label, "partition"); if (p) { n = strtol(p, &endp, 10); if (endp != p && *endp == 0) defpart = n; } *params = make_params(label, *params); } } if (!strcmp (imagename, "halt")) { prom_pause(); *kname = 0; return 0; } if (imagename[0] == '$') { /* forth command string */ call_prom("interpret", 1, 1, imagename+1); *kname = 0; return 0; } parse_name(imagename, defpart, device, part, kname); if (!*device) *device = defdevice; if (!*kname) printf( "Enter the kernel image name as [device:][partno]/path, where partno is a\n" "number from 0 to 16. Instead of /path you can type [mm-nn] to specify a\n" "range of disk blocks (512B)\n"); return 0; } /* * Print the specified message file. */ static void print_message_file(char *p) { char *q, *endp; int len = 0; int n, defpart = -1; char *device, *kname; int part; q = cfg_get_strg(0, "partition"); if (q) { n = strtol(q, &endp, 10); if (endp != q && *endp == 0) defpart = n; } parse_name(p, defpart, &device, &part, &kname); if (kname) { if (!device) device = cfg_get_strg(0, "device"); if (load_file(device, part, kname, TMP_BUF, TMP_END, &len, 1, 0)) { TMP_BUF[len] = 0; printf("\n%s", (char *)TMP_BUF); } } } /* Here we are launched */ int main(void *prom_entry, struct first_info *fip, unsigned long id) { unsigned off; int i, len, image_len; char *kname, *params, *device; int part; int isfile, fileok = 0; unsigned int ret_offset; Elf32_Ehdr *e; Elf32_Phdr *p; unsigned load_loc, entry, start; extern char __bss_start, _end; struct first_info real_fip; #ifdef BOOTINFO struct boot_info binf; #endif /* * If we're not being called by the first stage bootloader * and we don't have the BootX signature assume we're * chrp. -- Cort */ if ( (id != 0xdeadbeef) && ((unsigned long)prom_entry != 0x426f6f58) ) { is_chrp = 1; prom_entry = (void *)id; /* chrp passes prom_entry in r5 */ /* * Make our own information packet with some default values * we can assume are true on chrp. */ fip = &real_fip; strcpy( fip->quik_vers, "chrp" ); /* * Assume root partition is partition 2. We should * scan the disk looking for a linux FS with /etc/quik.conf. * -- Cort */ fip->conf_part = 2; strcpy( fip->conf_file, "/etc/quik.conf" ); } if ( (unsigned long)prom_entry == 0x426f6f58 ) { printf("BootX launched us\n"); prom_entry = (void *)id; /* * These should come from the bootx info. */ fip = &real_fip; strcpy( fip->quik_vers, "BootX" ); /* Assume root partition is partition 9 -- Cort */ fip->conf_part = 9; strcpy( fip->conf_file, "/etc/quik.conf" ); } memset(&__bss_start, 0, &_end - &__bss_start); prom_init(prom_entry); printf("Second-stage QUIK loader\n"); if (diskinit() == -1) prom_exit(); quik_conf_part = fip->conf_part; strncpy(quik_conf, fip->conf_file, sizeof(fip->conf_file)); if (*quik_conf && quik_conf_part >= 0) { int len; fileok = load_file(0, quik_conf_part, quik_conf, TMP_BUF, TMP_END, &len, 1, 0); if (!fileok || (unsigned) len >= 65535) printf("\nCouldn't load %s\n", quik_conf); else { char *p; if (cfg_parse(quik_conf, TMP_BUF, len) < 0) printf ("Syntax error or read error in %s.\n", quik_conf); useconf = 1; p = cfg_get_strg(0, "init-code"); if (p) call_prom("interpret", 1, 1, p); p = cfg_get_strg(0, "init-message"); if (p) printf("%s", p); p = cfg_get_strg(0, "message"); if (p) print_message_file(p); } } else printf ("\n"); for (;;) { get_params(&device, &part, &kname, ¶ms); if (!kname) continue; fileok = load_file(device, part, kname, TMP_BUF, TMP_END, &image_len, 1, 0); if (!fileok) { printf ("\nImage not found.... try again\n"); continue; } if (image_len > TMP_END - TMP_BUF) { printf("\nImage is too large (%u > %u)\n", image_len, TMP_END - TMP_BUF); continue; } /* By this point the first sector is loaded (and the rest of */ /* the kernel) so we check if it is an executable elf binary. */ e = (Elf32_Ehdr *) TMP_BUF; if (!(e->e_ident[EI_MAG0] == ELFMAG0 && e->e_ident[EI_MAG1] == ELFMAG1 && e->e_ident[EI_MAG2] == ELFMAG2 && e->e_ident[EI_MAG3] == ELFMAG3)) { printf ("\n%s: unknown image format\n", kname); continue; } if (e->e_ident[EI_CLASS] != ELFCLASS32 || e->e_ident[EI_DATA] != ELFDATA2MSB) { printf("Image is not a 32bit MSB ELF image\n"); continue; } len = 0; p = (Elf32_Phdr *) (TMP_BUF + e->e_phoff); for (i = 0; i < e->e_phnum; ++i, ++p) { if (p->p_type != PT_LOAD || p->p_offset == 0) continue; if (len == 0) { off = p->p_offset; len = p->p_filesz; load_loc = p->p_vaddr & ADDRMASK; } else len = p->p_offset + p->p_filesz - off; } if (len == 0) { printf("Cannot find a loadable segment in ELF image\n"); continue; } entry = e->e_entry & ADDRMASK; if (len + off > image_len) len = image_len - off; break; } /* chrp expects to start at 0x10000 */ if ( is_chrp ) load_loc = entry = 0x10000; /* After this memmove, *p and *e may have been overwritten. */ memmove((void *)load_loc, TMP_BUF + off, len); flush_cache(load_loc, len); close(); if (pause_after) { printf("%s", pause_message); prom_pause(); printf("\n"); } /* * For the sake of the Open Firmware XCOFF loader, the entry * point may actually be a procedure descriptor. */ start = *(unsigned *)entry; if (start < load_loc || start >= load_loc + len || ((unsigned *)entry)[2] != 0) /* doesn't look like a procedure descriptor */ start += entry; printf("Starting at %x\n", start); #ifdef BOOTINFO /* setup the bootinfo */ binf.magic_start = bin.magic_end = BOOT_INFO_MAGIC; sprintf( binf.cmd_line, "%s", params ); sprintf( binf.boot_loader, "Quik" ); if ( is_chrp ) binf._machine = _MACH_chrp; else binf._machine = _MACH_Pmac; binf.initrd_start = binf.initrd_size = 0; binf.systemmap_start = binf.systemmap_size = 0; /* put the boot info at the nearest 0x10000 boundry from the end -- Cort */ memcpy( ((load_loc + len)+0x10000) & ~0x10000, binf, sizeof(struct boot_info) ); #endif (* (void (*)()) start)(params, 0, prom_entry, 0, 0); prom_exit(); } quik-2.1/second/malloc.c0000644000175000001440000000350107062261060015515 0ustar simonusers00000000000000/* Dumb memory allocation routines Copyright (C) 1997 Paul Mackerras 1996 Maurizio Plaza 1996 Jakub Jelinek 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include static char *malloc_ptr = (char *) MALLOC_BASE; static char *last_alloc = 0; void *malloc (unsigned int size) { char *caddr; *(int *)malloc_ptr = size; caddr = malloc_ptr + sizeof(int); malloc_ptr += size + sizeof(int); last_alloc = caddr; malloc_ptr = (char *) ((((unsigned int) malloc_ptr) + 3) & (~3)); return caddr; } void *realloc(void *ptr, unsigned int size) { char *caddr, *oaddr = ptr; if (oaddr == last_alloc) { *(int *)(oaddr - sizeof(int)) = size; malloc_ptr = oaddr + size; return oaddr; } caddr = malloc(size); if (caddr != 0 && oaddr != 0) memcpy(caddr, oaddr, *(int *)(oaddr - sizeof(int))); return caddr; } void free (void *m) { if (m == last_alloc) malloc_ptr = (char *) last_alloc - sizeof(int); } void mark (void **ptr) { *ptr = (void *) malloc_ptr; } void release (void *ptr) { malloc_ptr = (char *) ptr; } void *strdup(char *str) { char *p = malloc(strlen(str) + 1); strcpy(p, str); return p; } quik-2.1/second/nosys.c0000644000175000001440000000006307062261060015421 0ustar simonusers00000000000000/* we got no time */ long time() { return 0; } quik-2.1/second/p10000644000175000001440000000312307062261060014345 0ustar simonusers00000000000000--- disk.c~ Fri Apr 11 03:56:00 1997 +++ disk.c Thu Aug 13 10:39:37 1998 @@ -33,13 +33,14 @@ return open(bootdevice); } -int read(char *buf, int nbytes, int offset) +int read(char *buf, int nbytes, long long offset) { int nr; if (nbytes == 0) return 0; - call_prom("seek", 3, 1, current_dev, 0, offset); + call_prom("seek", 3, 1, current_dev, (int) (offset >> 32), + (unsigned int) offset); nr = (int) call_prom("read", 3, 1, current_dev, buf, nbytes); return nr; } --- file.c~ Fri Apr 11 03:59:58 1997 +++ file.c Thu Aug 13 10:39:09 1998 @@ -47,6 +47,8 @@ linux_flush }; +extern int read(char *, int, long long); + ext2_filsys fs = 0; static ino_t root, cwd; static io_manager linux_io_manager = &struct_linux_manager; @@ -71,7 +73,7 @@ struct mac_partition *mp = (struct mac_partition *) blk; struct mac_driver_desc *md = (struct mac_driver_desc *) blk; - rc = read(blk, 512, 0); + rc = read(blk, 512, 0LL); if (rc != 512) { fatal("Cannot read driver descriptor"); return 0; @@ -84,7 +86,7 @@ blocks_in_map = 1; upart = 0; for (i = 1; i <= blocks_in_map; ++i) { - if (read(blk, 512, i * secsize) != 512) { + if (read(blk, 512, (long long) i * secsize) != 512) { fatal("Error reading partition map"); return 0; } @@ -156,7 +158,7 @@ int size; size = (count < 0) ? -count : count * bs; - if (read (data, size, block * bs + doff) != size) { + if (read (data, size, (long long) block * bs + doff) != size) { printf ("\nRead error on block %d", block); return EXT2_ET_SHORT_READ; } quik-2.1/second/printf.c0000644000175000001440000000403007062261060015546 0ustar simonusers00000000000000/* Dumb printing routines Copyright (C) 1996 Pete A. Zaitcev 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include "quik.h" static void printn(long, int); extern void vprintf(char *, va_list); /* * Scaled down version of C Library printf. * Only %c %s %u %d (==%u) %o %x %D %O are recognized. */ void printf (char *fmt,...) { va_list x1; va_start (x1, fmt); vprintf (fmt, x1); va_end (x1); } void vprintf (char *fmt, va_list adx) { register c; char *s; for (;;) { while ((c = *fmt++) != '%') { if (c == '\0') { putchar (0); return; } putchar (c); } c = *fmt++; if (c == 'd' || c == 'o' || c == 'x' || c == 'X') { printn ((long) va_arg (adx, unsigned), c == 'o' ? 8 : (c == 'd' ? 10 : 16)); } else if (c == 'c') { putchar (va_arg (adx, unsigned)); } else if (c == 's') { s = va_arg (adx, char *); while (c = *s++) putchar (c); } else if (c == 'l' || c == 'O') { printn ((long) va_arg (adx, long), c == 'l' ? 10 : 8); } } } /* * Print an unsigned integer in base b, avoiding recursion. */ static void printn (long n, int b) { char prbuf[24]; register char *cp; if (b == 10 && n < 0) { putchar ('-'); n = -n; } cp = prbuf; do *cp++ = "0123456789ABCDEF"[(int) (n % b)]; while (n = n / b & 0x0FFFFFFF); do putchar (*--cp); while (cp > prbuf); } quik-2.1/second/prom.c0000644000175000001440000000540507062261060015230 0ustar simonusers00000000000000/* * Procedures for interfacing to the Open Firmware PROM on * Power Macintosh computers. * * Paul Mackerras October 1996. * Copyright (C) 1996 Paul Mackerras. */ #include #include "prom.h" #define getpromprop(node, name, buf, len) \ ((int)call_prom("getprop", 4, 1, (node), (name), (buf), (len))) ihandle prom_stdin; ihandle prom_stdout; ihandle prom_chosen; ihandle prom_options; struct prom_args { char *service; int nargs; int nret; void *args[10]; } prom_args; void (*prom_entry)(void *); void prom_exit() { struct prom_args args; args.service = "exit"; args.nargs = 0; args.nret = 0; prom_entry(&args); for (;;) /* should never get here */ ; } void * call_prom(char *service, int nargs, int nret, ...) { va_list list; int i; prom_args.service = service; prom_args.nargs = nargs; prom_args.nret = nret; va_start(list, nret); for (i = 0; i < nargs; ++i) prom_args.args[i] = va_arg(list, void *); va_end(list); for (i = 0; i < nret; ++i) prom_args.args[i + nargs] = 0; prom_entry(&prom_args); return prom_args.args[nargs]; } void prom_print(char *msg) { char *p, *q; char *crlf = "\r\n"; for (p = msg; *p != 0; p = q) { for (q = p; *q != 0 && *q != '\n'; ++q) ; if (q > p) call_prom("write", 3, 1, prom_stdout, p, q - p); if (*q != 0) { ++q; call_prom("write", 3, 1, prom_stdout, crlf, 2); } } } int putchar(int c) { char ch = c; if (c == '\n') putchar('\r'); return (int) call_prom("write", 3, 1, prom_stdout, &ch, 1); } int getchar() { char ch; int r; while ((r = (int) call_prom("read", 3, 1, prom_stdin, &ch, 1)) == 0) ; return r > 0? ch: -1; } int nbgetchar() { char ch; return (int) call_prom("read", 3, 1, prom_stdin, &ch, 1) > 0? ch: -1; } void prom_init(void (*pp)(void *)) { prom_entry = pp; /* First get a handle for the stdout device */ prom_chosen = call_prom("finddevice", 1, 1, "/chosen"); if (prom_chosen == (void *)-1) prom_exit(); getpromprop(prom_chosen, "stdout", &prom_stdout, sizeof(prom_stdout)); getpromprop(prom_chosen, "stdin", &prom_stdin, sizeof(prom_stdin)); prom_options = call_prom("finddevice", 1, 1, "/options"); } void prom_get_chosen(char *name, char *buf, int buflen) { buf[0] = 0; getpromprop(prom_chosen, name, buf, buflen); } void prom_get_options(char *name, char *buf, int buflen) { buf[0] = 0; if (prom_options != (void *) -1) getpromprop(prom_options, name, buf, buflen); } int get_ms() { return (int) call_prom("milliseconds", 0, 1); } void prom_pause() { call_prom("enter", 0, 0); } void set_bootargs(char *params) { call_prom("setprop", 4, 1, prom_chosen, "bootargs", params, strlen(params) + 1); } quik-2.1/second/prom.h0000644000175000001440000000126507062261060015235 0ustar simonusers00000000000000/* * Definitions for talking to the Open Firmware PROM on * Power Macintosh computers. * * Copyright (C) 1996 Paul Mackerras. */ typedef void *phandle; typedef void *ihandle; extern ihandle prom_stdin; extern ihandle prom_stdout; extern ihandle prom_chosen; /* Prototypes */ void prom_init(void (*pp)(void *)); void prom_exit(void); void *call_prom(char *service, int nargs, int nret, ...); void prom_print(char *msg); int putchar(int c); int getchar(void); int nbgetchar(void); void prom_get_chosen(char *name, char *buf, int buflen); void prom_get_options(char *name, char *buf, int buflen); void prom_map(unsigned char *addr, unsigned len); int get_ms(void); void prom_pause(void); quik-2.1/second/quik.h0000644000175000001440000000056707062261060015235 0ustar simonusers00000000000000/* * Global procedures and variables for the quik second-stage bootstrap. */ extern char cbuff[]; extern char bootdevice[]; int cfg_parse(char *cfg_file, char *buff, int len); char *cfg_get_strg(char *image, char *item); int cfg_get_flag(char *image, char *item); void cfg_print_images(void); char *cfg_get_default(void); void *malloc(unsigned); void prom_pause(void); quik-2.1/second/setjmp.S0000644000175000001440000000130407062261060015527 0ustar simonusers00000000000000 .globl __sigsetjmp __sigsetjmp: mflr 0 stw 1,0(3) stw 2,4(3) stw 0,8(3) stw 14,12(3) stw 15,16(3) stw 16,20(3) stw 17,24(3) stw 18,28(3) stw 19,32(3) stw 20,36(3) stw 21,40(3) stw 22,44(3) stw 23,48(3) stw 24,52(3) stw 25,56(3) stw 26,60(3) stw 27,64(3) stw 28,68(3) stw 29,72(3) stw 30,76(3) stw 31,80(3) li 3,0 blr .globl longjmp longjmp: cmpwi 0,4,0 bne 1f li 4,1 1: lwz 1,0(3) lwz 2,4(3) lwz 0,8(3) lwz 14,12(3) lwz 15,16(3) lwz 16,20(3) lwz 17,24(3) lwz 18,28(3) lwz 19,32(3) lwz 20,36(3) lwz 21,40(3) lwz 22,44(3) lwz 23,48(3) lwz 24,52(3) lwz 25,56(3) lwz 26,60(3) lwz 27,64(3) lwz 28,68(3) lwz 29,72(3) lwz 30,76(3) lwz 31,80(3) mtlr 0 mr 3,4 blr quik-2.1/second/string.S0000644000175000001440000000656107062261060015545 0ustar simonusers00000000000000/* * String handling functions for PowerPC. * * Copyright (C) 1996 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; either version * 2 of the License, or (at your option) any later version. */ #define r0 0 #define r3 3 #define r4 4 #define r5 5 #define r6 6 #define r7 7 #define r8 8 .globl strcpy strcpy: addi r5,r3,-1 addi r4,r4,-1 1: lbzu r0,1(r4) cmpwi 0,r0,0 stbu r0,1(r5) bne 1b blr .globl strncpy strncpy: cmpwi 0,r5,0 beqlr mtctr r5 addi r6,r3,-1 addi r4,r4,-1 1: lbzu r0,1(r4) cmpwi 0,r0,0 stbu r0,1(r6) bdnzf 2,1b /* dec ctr, branch if ctr != 0 && !cr0.eq */ blr .globl strcat strcat: addi r5,r3,-1 addi r4,r4,-1 1: lbzu r0,1(r5) cmpwi 0,r0,0 bne 1b addi r5,r5,-1 1: lbzu r0,1(r4) cmpwi 0,r0,0 stbu r0,1(r5) bne 1b blr .globl strcmp strcmp: addi r5,r3,-1 addi r4,r4,-1 1: lbzu r3,1(r5) cmpwi 1,r3,0 lbzu r0,1(r4) subf. r3,r0,r3 beqlr 1 beq 1b blr .globl strncmp strncmp: cmpwi 0,r5,0 addi r6,r3,-1 addi r4,r4,-1 beqlr mtctr r5 1: lbzu r3,1(r6) cmpwi 1,r3,0 lbzu r0,1(r4) subf. r3,r0,r3 beqlr 1 bdnzt 2,1b /* dec ctr, branch if ctr != 0 && cr0.eq */ blr .globl strlen strlen: addi r4,r3,-1 1: lbzu r0,1(r4) cmpwi 0,r0,0 bne 1b subf r3,r3,r4 blr .globl strchr strchr: addi r3,r3,-1 1: lbzu r0,1(r3) cmpw 0,r0,r4 cmpwi 1,r0,0 beqlr bne 1,1b li r3,0 blr .globl strrchr strrchr: addi r5,r3,-1 li r3,0 1: lbzu r0,1(r5) cmpwi 0,r0,0 cmpw 1,r0,r4 beqlr bne 1,1b mr r3,r5 b 1b .globl memset memset: rlwimi r4,r4,8,16,23 rlwimi r4,r4,16,0,15 addi r6,r3,-4 cmplwi 0,r5,4 blt 7f stwu r4,4(r6) beqlr andi. r0,r6,3 add r5,r0,r5 subf r6,r0,r6 rlwinm r0,r5,32-2,2,31 mtctr r0 bdz 6f 1: stwu r4,4(r6) bdnz 1b 6: andi. r5,r5,3 7: cmpwi 0,r5,0 beqlr mtctr r5 addi r6,r6,3 8: stbu r4,1(r6) bdnz 8b blr .globl bcopy bcopy: mr r6,r3 mr r3,r4 mr r4,r6 b memcpy .globl memmove memmove: cmplw 0,r3,r4 bgt backwards_memcpy /* fall through */ .globl memcpy memcpy: rlwinm. r7,r5,32-3,3,31 /* r0 = r5 >> 3 */ addi r6,r3,-4 addi r4,r4,-4 beq 2f /* if less than 8 bytes to do */ andi. r0,r6,3 /* get dest word aligned */ mtctr r7 bne 5f 1: lwz r7,4(r4) lwzu r8,8(r4) stw r7,4(r6) stwu r8,8(r6) bdnz 1b andi. r5,r5,7 2: cmplwi 0,r5,4 blt 3f lwzu r0,4(r4) addi r5,r5,-4 stwu r0,4(r6) 3: cmpwi 0,r5,0 beqlr mtctr r5 addi r4,r4,3 addi r6,r6,3 4: lbzu r0,1(r4) stbu r0,1(r6) bdnz 4b blr 5: subfic r0,r0,4 mtctr r0 6: lbz r7,4(r4) addi r4,r4,1 stb r7,4(r6) addi r6,r6,1 bdnz 6b subf r5,r0,r5 rlwinm. r7,r5,32-3,3,31 beq 2b mtctr r7 b 1b .globl backwards_memcpy backwards_memcpy: rlwinm. r7,r5,32-3,3,31 /* r0 = r5 >> 3 */ add r6,r3,r5 add r4,r4,r5 beq 2f andi. r0,r6,3 mtctr r7 bne 5f 1: lwz r7,-4(r4) lwzu r8,-8(r4) stw r7,-4(r6) stwu r8,-8(r6) bdnz 1b andi. r5,r5,7 2: cmplwi 0,r5,4 blt 3f lwzu r0,-4(r4) subi r5,r5,4 stwu r0,-4(r6) 3: cmpwi 0,r5,0 beqlr mtctr r5 4: lbzu r0,-1(r4) stbu r0,-1(r6) bdnz 4b blr 5: mtctr r0 6: lbzu r7,-1(r4) stbu r7,-1(r6) bdnz 6b subf r5,r0,r5 rlwinm. r7,r5,32-3,3,31 beq 2b mtctr r7 b 1b .globl memcmp memcmp: cmpwi 0,r5,0 blelr mtctr r5 addi r6,r3,-1 addi r4,r4,-1 1: lbzu r3,1(r6) lbzu r0,1(r4) subf. r3,r0,r3 bdnzt 2,1b blr .globl __bzero __bzero: mr r5, r4 li r4, 0 b memset quik-2.1/second/strtol.c0000644000175000001440000000713607062261060015605 0ustar simonusers00000000000000/* Copyright (C) 1991, 1992, 1994, 1995 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The GNU C Library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the GNU C Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* Convert NPTR to an `unsigned long int' or `long int' in base BASE. If BASE is 0 the base is determined by the presence of a leading zero, indicating octal or a leading "0x" or "0X", indicating hexadecimal. If BASE is < 2 or > 36, it is reset to 10. If ENDPTR is not NULL, a pointer to the character after the last one converted is stored in *ENDPTR. */ int strtol (nptr, endptr, base) const char *nptr; char **endptr; int base; { int negative; register unsigned int cutoff; register unsigned int cutlim; register unsigned int i; register const char *s; register unsigned char c; const char *save, *end; int overflow; if (base < 0 || base == 1 || base > 36) base = 10; save = s = nptr; /* Skip white space. */ while (((unsigned char) *s) <= 32 && *s) ++s; if (*s == '\0') goto noconv; /* Check for a sign. */ if (*s == '-') { negative = 1; ++s; } else if (*s == '+') { negative = 0; ++s; } else negative = 0; if (base == 16 && s[0] == '0' && (s[1] == 'X') || (s[1] == 'x')) s += 2; /* If BASE is zero, figure it out ourselves. */ if (base == 0) if (*s == '0') { if (s[1] == 'X' || s[1] == 'x') { s += 2; base = 16; } else base = 8; } else base = 10; /* Save the pointer so we can check later if anything happened. */ save = s; end = 0; cutoff = 0x7FFFFFFF / (unsigned int) base; cutlim = 0x7FFFFFFF % (unsigned int) base; overflow = 0; i = 0; for (c = *s; c != '\0'; c = *++s) { if (s == end) break; if (c >= '0' && c <= '9') c -= '0'; else if (c >= 'A' && c <= 'Z') c = c - 'A' + 10; else if (c >= 'a' && c <= 'z') c = c - 'a' + 10; else break; if (c >= base) break; /* Check for overflow. */ if (i > cutoff || (i == cutoff && c > cutlim)) overflow = 1; else { i *= (unsigned int) base; i += c; } } /* Check if anything actually happened. */ if (s == save) goto noconv; /* Store in ENDPTR the address of one character past the last character we converted. */ if (endptr) *endptr = (char *) s; if (overflow) return negative ? (int) 0x80000000 : (int) 0x7FFFFFFF; /* Return the result of the appropriate sign. */ return (negative ? -i : i); noconv: /* We must handle a special case here: the base is 0 or 16 and the first two characters and '0' and 'x', but the rest are no hexadecimal digits. This is no error case. We return 0 and ENDPTR points to the `x`. */ if (endptr) if (save - nptr >= 2 && tolower (save[-1]) == 'x' && save[-2] == '0') *endptr = (char *) &save[-1]; else /* There was no number to convert. */ *endptr = (char *) nptr; return 0L; } quik-2.1/util/0000755000175000001440000000000007062261060013605 5ustar simonusers00000000000000quik-2.1/util/Makefile0000644000175000001440000000021207062261060015240 0ustar simonusers00000000000000CFLAGS= -O2 all: elfextract elfextract: elfextract.c $(CC) $(CFLAGS) -o elfextract elfextract.c clean: rm -f *~ elfextract install: quik-2.1/util/elfextract.c0000644000175000001440000000365407062261060016122 0ustar simonusers00000000000000/* * Extract the loadable program segment from an elf file. * * Copyright 1996 Paul Mackerras. */ #include #include FILE *fi, *fo; char *ni, *no; char buf[65536]; void rd(void *buf, int len) { int nr; nr = fread(buf, 1, len, fi); if (nr == len) return; if (ferror(fi)) fprintf(stderr, "%s: read error\n", ni); else fprintf(stderr, "%s: short file\n", ni); exit(1); } main(int ac, char **av) { unsigned nb, len, i; Elf32_Ehdr eh; Elf32_Phdr ph; unsigned long phoffset, phsize, prevaddr; if (ac > 3 || ac > 1 && av[1][0] == '-') { fprintf(stderr, "Usage: %s [elf-file [image-file]]\n", av[0]); exit(0); } fi = stdin; ni = "(stdin)"; fo = stdout; no = "(stdout)"; if (ac > 1) { ni = av[1]; fi = fopen(ni, "rb"); if (fi == NULL) { perror(ni); exit(1); } } rd(&eh, sizeof(eh)); if (eh.e_ident[EI_MAG0] != ELFMAG0 || eh.e_ident[EI_MAG1] != ELFMAG1 || eh.e_ident[EI_MAG2] != ELFMAG2 || eh.e_ident[EI_MAG3] != ELFMAG3) { fprintf(stderr, "%s: not an ELF file\n", ni); exit(1); } fseek(fi, eh.e_phoff, 0); phsize = 0; for (i = 0; i < eh.e_phnum; ++i) { rd(&ph, sizeof(ph)); if (ph.p_type != PT_LOAD) continue; if (phsize == 0 || prevaddr == 0) { phoffset = ph.p_offset; phsize = ph.p_filesz; } else phsize = ph.p_offset + ph.p_filesz - phoffset; prevaddr = ph.p_vaddr; } if (phsize == 0) { fprintf(stderr, "%s: doesn't have a loadable segment\n", ni); exit(1); } if (ac > 2) { no = av[2]; fo = fopen(no, "wb"); if (fo == NULL) { perror(no); exit(1); } } fseek(fi, phoffset, 0); for (len = phsize; len != 0; len -= nb) { nb = len; if (nb > sizeof(buf)) nb = sizeof(buf); rd(buf, nb); if (fwrite(buf, 1, nb, fo) != nb) { fprintf(stderr, "%s: write error\n", no); exit(1); } } fclose(fo); fclose(fi); exit(0); }