--- quik-2.1.orig/Makefile +++ quik-2.1/Makefile @@ -1,6 +1,7 @@ DIRS= util first second quik .EXPORT_ALL_VARIABLES: CC=gcc +CFLAGS=-Wall all clean dep depend: @for I in $(DIRS); do cd $$I; make $@ || exit 1; cd ..; done @@ -9,11 +10,11 @@ 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 -d -m 755 $(DESTDIR)/usr/share/man/man5 + install -d -m 755 $(DESTDIR)/usr/share/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 + install -m 444 man/quik.conf.5 $(DESTDIR)/usr/share/man/man5 + install -m 444 man/quik.8 man/bootstrap.8 $(DESTDIR)/usr/share/man/man8 --- quik-2.1.orig/first/first.S +++ quik-2.1/first/first.S @@ -56,21 +56,30 @@ sync isync -/* Use the BAT3 registers to map the 1st 8MB of RAM to 0. */ +/* Use the BAT2 & 3 registers to map the 1st 16MB of RAM to 0. */ mfpvr 9 rlwinm 9,9,16,16,31 /* r9 = 1 for 601, 4 for 604 */ + /* the 604 case now works on G3, and should */ + /* work on everything else too */ 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 */ +4: li 7,0x1ff /* set up BAT registers for 604 et al */ li 8,2 - mtdbatu 3,7 mtdbatl 3,8 + mtdbatu 3,7 + mtibatl 3,8 + mtibatu 3,7 + b 6f 5: mtibatu 3,7 mtibatl 3,8 - isync + oris 7,7,0x80 + oris 8,8,0x80 + mtibatu 2,7 + mtibatl 2,8 +6: isync /* Load up an initial stack pointer */ lis 1,STACK_TOP@h --- quik-2.1.orig/include/layout.h +++ quik-2.1/include/layout.h @@ -10,19 +10,23 @@ * (at your option) any later version. */ -#define VERSION "2.0" +#define VERSION "2.1" -#define FIRST_BASE 0x3f4000 -#define FIRST_SIZE 0x400 +#define FIRST_BASE 0x3f4000 /* dec: 4145152 */ +#define FIRST_SIZE 0x400 /* dec: 1024 */ -#define SECOND_BASE 0x3e0000 -#define SECOND_SIZE 0x10000 +#define SECOND_BASE 0x3e0000 /* dec: 4063232 */ +#define SECOND_SIZE 0x10000 /* dec: 65536 */ -#define STACK_TOP 0x400000 +#define STACK_TOP 0x400000 /* dec: 4194304 */ /* 0x400000 - 0x500000 is one of OF's favourite places to be. */ -#define MALLOC_BASE 0x500000 +/* We malloc in low memory now and load kernel at 0x500000 instead, we + * also map 16Mb with BATs. This is all done to help loading larger + * kernels. --BenH. + */ +#define MALLOC_BASE 0x300000 /* dec: 3145728 */ #ifndef __ASSEMBLY__ struct first_info { --- quik-2.1.orig/include/linux/raid/md_u.h +++ quik-2.1/include/linux/raid/md_u.h @@ -0,0 +1,116 @@ +/* + md_u.h : user <=> kernel API between Linux raidtools and RAID drivers + Copyright (C) 1998 Ingo Molnar + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + You should have received a copy of the GNU General Public License + (for example /usr/src/linux/COPYING); if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef _MD_U_H +#define _MD_U_H + +/* ioctls */ + +/* status */ +#define RAID_VERSION _IOR (MD_MAJOR, 0x10, mdu_version_t) +#define GET_ARRAY_INFO _IOR (MD_MAJOR, 0x11, mdu_array_info_t) +#define GET_DISK_INFO _IOR (MD_MAJOR, 0x12, mdu_disk_info_t) +#define PRINT_RAID_DEBUG _IO (MD_MAJOR, 0x13) +#define RAID_AUTORUN _IO (MD_MAJOR, 0x14) + +/* configuration */ +#define CLEAR_ARRAY _IO (MD_MAJOR, 0x20) +#define ADD_NEW_DISK _IOW (MD_MAJOR, 0x21, mdu_disk_info_t) +#define HOT_REMOVE_DISK _IO (MD_MAJOR, 0x22) +#define SET_ARRAY_INFO _IOW (MD_MAJOR, 0x23, mdu_array_info_t) +#define SET_DISK_INFO _IO (MD_MAJOR, 0x24) +#define WRITE_RAID_INFO _IO (MD_MAJOR, 0x25) +#define UNPROTECT_ARRAY _IO (MD_MAJOR, 0x26) +#define PROTECT_ARRAY _IO (MD_MAJOR, 0x27) +#define HOT_ADD_DISK _IO (MD_MAJOR, 0x28) +#define SET_DISK_FAULTY _IO (MD_MAJOR, 0x29) + +/* usage */ +#define RUN_ARRAY _IOW (MD_MAJOR, 0x30, mdu_param_t) +#define START_ARRAY _IO (MD_MAJOR, 0x31) +#define STOP_ARRAY _IO (MD_MAJOR, 0x32) +#define STOP_ARRAY_RO _IO (MD_MAJOR, 0x33) +#define RESTART_ARRAY_RW _IO (MD_MAJOR, 0x34) + +typedef struct mdu_version_s { + int major; + int minor; + int patchlevel; +} mdu_version_t; + +typedef struct mdu_array_info_s { + /* + * Generic constant information + */ + int major_version; + int minor_version; + int patch_version; + int ctime; + int level; + int size; + int nr_disks; + int raid_disks; + int md_minor; + int not_persistent; + + /* + * Generic state information + */ + int utime; /* 0 Superblock update time */ + int state; /* 1 State bits (clean, ...) */ + int active_disks; /* 2 Number of currently active disks */ + int working_disks; /* 3 Number of working disks */ + int failed_disks; /* 4 Number of failed disks */ + int spare_disks; /* 5 Number of spare disks */ + + /* + * Personality information + */ + int layout; /* 0 the array's physical layout */ + int chunk_size; /* 1 chunk size in bytes */ + +} mdu_array_info_t; + +typedef struct mdu_disk_info_s { + /* + * configuration/status of one particular disk + */ + int number; + int major; + int minor; + int raid_disk; + int state; + +} mdu_disk_info_t; + +typedef struct mdu_start_info_s { + /* + * configuration/status of one particular disk + */ + int major; + int minor; + int raid_disk; + int state; + +} mdu_start_info_t; + +typedef struct mdu_param_s +{ + int personality; /* 1,2,3,4 */ + int chunk_size; /* in bytes */ + int max_fault; /* unused for now */ +} mdu_param_t; + +#endif + --- quik-2.1.orig/include/quik_md.h +++ quik-2.1/include/quik_md.h @@ -0,0 +1,101 @@ +/* + * quik-md.h - definitions for md handling in quik + * + * Copyright (C) 2005 Simon Vallet + * + * Information retrieval code for md devices is derived from + * Detail.c in mdadm version 1.9.0, and therefore: + * + * Copyright (C) 2001-2002 Neil Brown + * + * 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. + */ + +#ifndef _QUIKMD_H +#define _QUIKMD_H + +#define __u32 u_int32_t +#define __u64 u_int64_t + +#define MD_MAJOR 9 +#define DEV_BUFSZ 1024 + +#define u32 u_int32_t +#define u8 u_int8_t + +#include +#include + +/* From md_p.h */ +#define MD_SB_DISKS 27 +#include + +struct devmap { + int major, minor; + char *name; + struct devmap *next; +}; + +typedef struct mapping { + char *name; + int num; +} mapping_t; + +#define __USE_XOPEN_EXTENDED +#include + +char *map_num(mapping_t *, int); +char *map_dev(int, int); +int is_standard(char *, int *); +int add_dev(const char *, const struct stat *, int, struct FTW *); +int digit_offset (const char *); + +//void fatal (const char *); + +typedef struct dev_info { + char * bootdev; /* Physical device, e.g. /dev/hda */ + char * spart; /* Filesystem device for second.b, e.g. /dev/hda2 */ + int cpart; /* Conffile part. number */ + 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 part. containing second.b */ + struct first_info finfo; /* Boot block structure */ +} dev_info_t; + +typedef struct mdev_info { + char * metadev; /* Metadevice, e.g. /dev/md0, if necessary */ + char * fs_dev; /* Device containing the filesystem */ + dev_info_t ** devs; + unsigned int bs; + unsigned int nsect; + unsigned char ndevs; + int rlevel; +} mdev_info_t; + +#define BOOTDEV(dev,i) ((dev)->devs[(i)]->bootdev) +#define SPART(dev,i) ((dev)->devs[(i)]->spart) + +dev_info_t * new_dev_info (unsigned char); +void free_dev_info (dev_info_t *); +int md_get_version (int); +mdev_info_t * md_get_info (const char *); + +dev_info_t * new_dev_info (); +void free_dev_info (dev_info_t *); +mdev_info_t * new_mdev_info (unsigned char); +void free_mdev_info (mdev_info_t *); + +#endif --- quik-2.1.orig/man/bootstrap.8 +++ quik-2.1/man/bootstrap.8 @@ -1,3 +1,4 @@ +\# -*- coding: utf-8 -*- .\" bootstrap - Description of the disk boot process for Powermacs .TH bootstrap 8 "16 March 1997" "" "PowerMac/Linux" .SH NAME @@ -6,44 +7,44 @@ 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 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 +.PP +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 +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 +the second\-stage bootstrap. +.PP +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. - +.PP \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 +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 +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. - +.PP \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. - +\fBinput\-device\fR and \fBoutput\-device\fR variables. +.PP \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). - +.PP 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 @@ -52,15 +53,15 @@ 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. - +.PP Having obtained a command line, \fBsecond.b\fR takes the first word -(whitespace-separated) as the name of the program to load. Any +(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. - +.PP 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 @@ -68,32 +69,32 @@ 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. - +.PP Path names are of the form - +.PP .RS .RI [ device\fB: ][ partno ]\fB/ filepath .RE - +.PP 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 ] +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. - +.PP \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. - +.PP Once \fBsecond.b\fR has loaded the program into memory, it transfers control to it, passing it the list of arguments. - +.PP .SH SEE ALSO .I quik(8), quik.conf(5) --- quik-2.1.orig/man/quik.8 +++ quik-2.1/man/quik.8 @@ -1,79 +1,80 @@ +\# -*- coding: utf-8 -*- .\" 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 [ \-b\ \fIsecond\-stage\fB ] +.RB [ \-C\ \fIconfig\-file\fB ] .RB [ \-f ] -.RB [ \-i\ \fIfirst-stage\fB ] -.RB [ \-r\ \fIroot-path\fB ] +.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 +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. - +.PP .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 +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 +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. - +.PP .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 +.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 +.PP +.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 +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 +.PP +.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 +.PP +.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 +\fIroot\-path\fB/boot\fR, and the default configuration file name will +be \fIroot\-path\fB/etc/quik.conf\fR. +.PP .B \-S \fIbackup Save a copy of the current boot block in .IR backup . -.TP +.PP .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 +.PP .B \-v Verbose mode: print messages indicating what quik is doing. -.TP +.PP .B \-V Print quik's version number and exit. .SH FILES --- quik-2.1.orig/man/quik.conf.5 +++ quik-2.1/man/quik.conf.5 @@ -1,23 +1,24 @@ +\# -*- coding: utf-8 -*- .\" 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 +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 +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.) - +.PP 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. - +.PP 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 @@ -25,112 +26,115 @@ 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. - +.PP 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. - +.PP .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 +the first\-stage bootstrap) is used. +.PP .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 +.PP .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 +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 +.PP .BI timeout= n -Specifies the timeout period for the second-stage bootstrap to wait +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 +.PP +.BI init\-message= string +Specifies a string to print out when the second\-stage bootstrap starts. This is a global option only. -.TP +.PP .BI message= path -Specifies the path name for a file to print out when the second-stage +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 +.PP .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 +.PP .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 +.PP +.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 +.PP +.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 +.PP .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 +.PP .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 +.PP .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 +.PP +.BI initrd= path +Specifies the path for the initrd to be loaded. +.PP .BI label= label Specifies that \fIlabel\fR is a shorthand name for the current image. This is a local option only. -.TP +.PP .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 +.PP +.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 +.PP +.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 +key. Only useful when the \fBpause\-after\fR option is given. +.PP +.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 --- quik-2.1.orig/man/quikconfig.8 +++ quik-2.1/man/quikconfig.8 @@ -0,0 +1,21 @@ +\# -*- coding: utf-8 -*- +.\" quikconfig - configure quik automatically +.TH quikconfig 8 "15 April 2002" "" "PowerMac/Linux" +.SH NAME +quikconfig \- Configure quik automatically +.SH SYNOPSIS +.B /usr/sbin/quikconfig +.SH DESCRIPTION +.B Quikconfig +attempts to determine a sensible configuration for quik and writes it +to hard disk. Before any potentially destructive steps, the user is +prompted for approval. +.SH FILES +.nf +/etc/fstab +/etc/quik.conf +.fi +.SH AUTHORS +Matt McLean, based on liloconfig by Bruce Perens and Bernd Eckenfels. +.SH SEE ALSO +.I quik(8), quik.conf(5), bootstrap(8) --- quik-2.1.orig/quik/Makefile +++ quik-2.1/quik/Makefile @@ -1,10 +1,12 @@ -all: quik +objects= quik_md.o quik.o -COPTS = -static -O +COPTS = -O -Wall CFLAGS = -I../include $(COPTS) -quik: quik.c - $(CC) $(CFLAGS) -o quik quik.c +all: quik + +quik: $(objects) + $(CC) $(CFLAGS) -o quik $(objects) clean: rm -f *.o *~ quik --- quik-2.1.orig/quik/quik.c +++ quik-2.1/quik/quik.c @@ -2,6 +2,8 @@ Copyright (C) 1996 Paul Mackerras. + Copyright (C) 2005 Simon Vallet for the MD handling code + Derived from silo.c in the silo-0.6.4 distribution, therefore: Copyright (C) 1996 Maurizio Plaza @@ -25,16 +27,22 @@ #include #include #include +#include +#include #include #include -#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" @@ -47,6 +55,10 @@ #define HDC_MAJOR 22 #define HDE_MAJOR 33 #define HDG_MAJOR 34 +#define DAC960_MAJOR 48 /* Major dev. no. for 1st DAC960 card */ +#define DAC960_SD0_MINOR 0 /* Minor dev. no. for 1st System Drive */ +#define DAC960_SD1_MINOR 8 /* Minor dev. no. for 2nd System Drive */ + #ifndef MAJOR #define MAJOR(dev) ((dev) >> 8) @@ -55,24 +67,19 @@ int unit_shift; int part_mask; -#define UNIT(dev) (MINOR(dev) >> unit_shift) -#define PART(dev) (MINOR(dev) & part_mask) +#define UNIT(dev) (((int)MINOR(dev)) >> unit_shift) +#define PART(dev) (((int)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,...) +void fatal(char *fmt,...) __attribute__ ((noreturn)); + +void fatal(char *fmt,...) { va_list ap; va_start(ap, fmt); @@ -97,83 +104,106 @@ return -1; } -void read_sb(char *device, char *bootdev) +int part_from_dev (char * spart) +{ + char * p = spart + strlen(spart); + while (p > spart && isdigit(p[-1])) + --p; + return atoi(p); +} + + +void read_sb (mdev_info_t * devs) { - int fd, partno, part; - int offset, upart, maxpart; + int fd, partno, part, i; + int 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) + if ((fd = open(devs->fs_dev, O_RDONLY)) == -1) + fatal("Cannot open %s", devs->fs_dev); + devs->bs = check_fs(fd); + if (devs->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); + for (i=0; indevs; i++) { + if (devs->devs[i]->bootdev) { /* Handle "missing" raid devices */ + partno = part_from_dev(SPART(devs,i)); + if (partno == 0) + fatal("Can't determine partition number for %s", SPART(devs,i)); + upart = 0; + mp = (struct mac_partition *) buff; + md = (struct mac_driver_desc *) buff; + if ((fd = open(devs->devs[i]->bootdev, O_RDONLY)) == -1) + fatal("Can't open %s", BOOTDEV(devs, i)); if (read(fd, buff, sizeof (buff)) != sizeof (buff)) - fatal("Error reading partition map from %s", bootdev); - if (mp->signature != MAC_PARTITION_MAGIC) + fatal("Error reading %s (block 0)", BOOTDEV(devs, i)); + if (md->signature != MAC_DRIVER_MAGIC) + fatal("%s is not a mac-formatted disk", BOOTDEV(devs, i)); + + devs->devs[i]->secsize = md->block_size; + devs->devs[i]->doff = 0; + maxpart = 1; + for (part = 1; part <= maxpart; ++part) { + lseek(fd, part * devs->devs[i]->secsize, 0); + + if (read(fd, buff, sizeof (buff)) != sizeof (buff)) + fatal("Error reading partition map from %s", BOOTDEV(devs, i)); + if (mp->signature != MAC_PARTITION_MAGIC) break; - if (part == 1) + if (part == 1) maxpart = mp->map_count; - else if (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) { + + if (devs->devs[i]->first_bootable == 0 + && (mp->status & STATUS_BOOTABLE) != 0 + && strcasecmp(mp->processor, "PowerPC") == 0) + devs->devs[i]->first_bootable = part; + + if (++upart == partno) { /* This is the one we want */ - part_block = part; - doff = mp->start_block * (secsize >> 9); + devs->devs[i]->part_block = part; + devs->devs[i]->doff = mp->start_block * (devs->devs[i]->secsize >> 9); break; + } } + if (upart < partno) + fatal("Couldn't locate partition %d on %s", partno, BOOTDEV(devs, i)); + } } - if (upart < partno) - fatal("Couldn't locate partition %d on %s", partno, bootdev); } -void make_bootable(char *device, char *spart) +void make_bootable (mdev_info_t * devs) { - int fd; - struct mac_partition *mp; - char buff[512]; + int fd; int i; + struct mac_partition *mp; + char buff[512]; + off_t seek_offset; - if (part_block == 0) - return; + for (i=0; indevs; i++) { + if (devs->devs[i]->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); + printf("Making %s bootable (map entry %d)\n", + SPART(devs, i), + devs->devs[i]->part_block); + if (devs->devs[i]->first_bootable > 0 + && devs->devs[i]->first_bootable < devs->devs[i]->part_block) + fprintf(stderr, "Warning: prior partition (entry %d) is bootable\n", + devs->devs[i]->first_bootable); + if ((fd = open(BOOTDEV(devs,i), O_RDWR)) < 0) + fatal("Cannot open %s for writing\n", BOOTDEV(devs,i)); + seek_offset = (off_t)devs->devs[i]->part_block * devs->devs[i]->secsize; + lseek(fd, seek_offset, 0); + if (read(fd, buff, sizeof(buff)) != sizeof(buff)) { + close(fd); + fatal("Error reading partition map entry %d from %s\n", + devs->devs[i]->part_block, + BOOTDEV(devs,i)); + } mp = (struct mac_partition *) buff; mp->status |= STATUS_BOOTABLE; mp->boot_start = 0; @@ -183,31 +213,41 @@ 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); + if (lseek(fd, seek_offset, 0) < 0 + || write(fd, buff, sizeof(buff)) != sizeof(buff)) { + close(fd); + fatal("Couldn't make %s%d bootable: write error\n", + BOOTDEV(devs,i), + devs->devs[i]->part_block); + } + close(fd); + } } -int get_partition_blocks(char *filename) +int get_partition_blocks(char *filename, mdev_info_t * devs) { int fd; - int block, i, k; + int block, i, j; 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) + devs->nsect = devs->bs >> 9; + for (j=0; jndevs; j++) { + if (SPART(devs,j)) { + devs->devs[j]->finfo.blocksize = devs->bs; + + for (i = 0;; i++) { + block = i; + if (i * devs->bs >= st.st_size || ioctl(fd, FIBMAP, &block) < 0 || !block) break; - finfo.blknos[i] = block * nsect + doff; + devs->devs[j]->finfo.blknos[i] = block * devs->nsect + devs->devs[j]->doff; + } + devs->devs[j]->finfo.nblocks = i; + } } - finfo.nblocks = i; close(fd); return 0; } @@ -228,22 +268,36 @@ return strdup(path); } -void write_block_table(char *device, char *config_file, int partno) +void write_block_table(mdev_info_t *devs, char *config_file) { - int fd; + int fd, i; + struct first_info * finfo_p = NULL; - 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); + for (i=0; indevs; i++) { + if (SPART(devs,i)) { + if (verbose) + printf("Writing block table to boot block on %s\n", SPART(devs,i)); + strncpy(devs->devs[i]->finfo.quik_vers, + "QUIK" VERSION, + sizeof(devs->devs[i]->finfo.quik_vers)); + devs->devs[i]->finfo.second_base = SECOND_BASE; + devs->devs[i]->finfo.conf_part = devs->devs[i]->cpart; + strncpy(devs->devs[i]->finfo.conf_file, + config_file, + sizeof(devs->devs[i]->finfo.conf_file)); + finfo_p = &(devs->devs[i]->finfo); /* All should be equal */ + } + } + /* Seems we have to have all our bootable md devices on + * the SAME partitions , e.g. /dev/hda2 & /dev/hdc2. + * seems difficult to circumvent as we write the block table to /dev/md? + */ + if ((fd = open(devs->fs_dev, O_RDWR)) == -1) + fatal("Cannot open %s", devs->fs_dev); 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); + fatal("Seek error on %s", devs->fs_dev); + if (write(fd, finfo_p, sizeof(struct first_info)) != sizeof(struct first_info)) + fatal("Couldn't update boot block on %s", devs->fs_dev); close(fd); } @@ -261,7 +315,7 @@ 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\ + -f force overwriting of bootblock, even if quik already installed\n\ -v verbose mode\n\ -V show version\n" ,s); exit (1); @@ -299,7 +353,7 @@ 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)) + if ((rc = fwrite(&u, 1, sizeof(u), fp) != sizeof(u))) fatal("Couldn't write old bootblock to %s", filename); fclose (fp); } @@ -327,8 +381,8 @@ 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); + close(fd); } char *find_dev(int number) @@ -346,7 +400,7 @@ return NULL; strcpy(name, DEVNAME "/"); p = strchr(name, 0); - while (dir = readdir(dp)) { + while ((dir = readdir(dp))) { strcpy(p, dir->d_name); if (stat(name, &s) < 0) return NULL; @@ -411,24 +465,58 @@ } } +mdev_info_t * get_dev_info (const char * basedev, int is_md, int is_raid, int inc_name, const struct stat st) +{ + mdev_info_t * out; + char buffer[DEV_BUFSZ]; + /* No partitions on md devices, + but this macro gets the correct md minor */ + int part = PART(st.st_dev); + + if (is_md) { + /* We need to have the device before we can get any info */ + strcpy(buffer, basedev); + if (part >= 0) { sprintf(buffer+strlen(buffer), "%d", part); } + + out = md_get_info(buffer); + out->fs_dev = out->metadev; + } else { + out = new_mdev_info(1); + + strncpy(buffer, basedev, DEV_BUFSZ); + if (inc_name) { buffer[7] += UNIT(st.st_dev); } + out->devs[0]->bootdev = (char *)malloc(strlen(buffer)+1); + strcpy(out->devs[0]->bootdev, buffer); + + if (is_raid) { strcat(buffer, "p"); } + if (part != 0) { + sprintf(buffer+strlen(buffer), "%d", (is_raid) ? part & 7 : part); + } + out->devs[0]->spart = (char *)malloc(strlen(buffer)+1); + strcpy(out->devs[0]->spart, buffer); + out->fs_dev = out->devs[0]->spart; + } + + return out; +} + int main(int argc,char **argv) { char *name = NULL, *config_file, *install = NULL, *secondary, *backup; - int c; + int c; int i; 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 *p, *basedev=NULL; char buffer[1024]; int force = 0; - int f, inc_name; + int inc_name, raid_dev, md_dev; extern int optind; extern char *optarg; + /* md */ + mdev_info_t * devs = NULL; /* * Test if we're being run on a chrp machine. We don't @@ -515,6 +603,8 @@ unit_shift = 6; part_mask = 0x3f; inc_name = 1; + raid_dev = 0; + md_dev = 0; switch (MAJOR(st1.st_dev)) { case SD_MAJOR: unit_shift = 4; @@ -533,6 +623,25 @@ case HDG_MAJOR: basedev = "/dev/hdg"; break; + case DAC960_MAJOR: + raid_dev = 1; + switch(MINOR(st1.st_dev)) { + case DAC960_SD0_MINOR + 2: + basedev="/dev/rd/c0d0"; + break; + case DAC960_SD1_MINOR + 2: + basedev="/dev/rd/c0d1"; + break; + default: + if (verbose) + fatal("We only support the 2 first system drives for now"); + } + break; + case MD_MAJOR: + basedev = "/dev/md"; + inc_name = 0; + md_dev = 1; + break; default: p = find_dev(st1.st_dev); if (p == NULL) @@ -542,18 +651,15 @@ 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); + devs = get_dev_info(basedev, md_dev, raid_dev, inc_name, st1); - backup = chrootcpy (backup); + if (devs->metadev && devs->rlevel != 1) + fatal("RAID level other than 1 (mirror) are not supported"); + if (verbose) + printf("Second-stage loader is on %s\n", devs->fs_dev); + if (config_file == NULL) { config_file = chrootcpy(DFL_CONFIG); if (stat(config_file, &st2) < 0) { @@ -564,41 +670,74 @@ config_file = p; } } - } else + } else { config_file = chrootcpy (config_file); + } + + if (verbose) + printf("Conffile is %s\n", 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 we have a metadevice, the following test + * prevents having a separate /boot device, which should be + * possible in theory. But checking for PART() seems to make this + * impossible even for non-md devices -- OK for now. + */ + 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(devs, 0)); + strcpy(buffer, config_file); + buffer[strlen(config_file)] = 0x00; + + config_file = resolve_to_dev(buffer, st2.st_dev); + if (devs->metadev) { + /* We are positive that conffile and second.b are + * on the same md device. Just get the part # from spart + */ + for (i=0; indevs; i++) { + if (SPART(devs,i)) { + devs->devs[i]->cpart = part_from_dev(SPART(devs,i)); + if (devs->devs[i]->cpart == 0) + fatal("Can't determine partition number for %s\n", SPART(devs,i)); + } + } + } else { if (inc_name) - config_file_partno = PART(st2.st_dev); + if(raid_dev) + config_file_partno = PART(st2.st_dev) & 7; + else + config_file_partno = PART(st2.st_dev); else - config_file_partno = 1; + config_file_partno = 1; if (verbose) - printf("Config file is on partition %d\n", config_file_partno); + printf("Config file is on partition %d\n", config_file_partno); + } } + + backup = chrootcpy (backup); + if (backup && !force_backup) { if (stat(backup, &st2) < 0) force_backup = 1; } - read_sb(spart, bootdev); - if (!examine_bootblock(spart, backup, force_backup) + read_sb(devs); + + if (!examine_bootblock(devs->fs_dev, 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); + if (!install) + install = chrootcpy(DFL_PRIMARY); + else if (*install == '/') + install = chrootcpy(install); + install_first_stage(devs->fs_dev, install); + make_bootable(devs); } - get_partition_blocks(secondary); - write_block_table(spart, config_file, config_file_partno); + get_partition_blocks(secondary, devs); + write_block_table(devs, config_file); + + free_mdev_info(devs); sync(); exit(0); } --- quik-2.1.orig/quik/quik_md.c +++ quik-2.1/quik/quik_md.c @@ -0,0 +1,313 @@ +/* + * quik_md.c -- This file implements /dev/md device handling for quik. + * + * Copyright (C) 2005 Simon Vallet + * + * Information retrieval code for md devices is derived from + * Detail.c in mdadm version 1.9.0, and therefore: + * + * Copyright (C) 2001-2002 Neil Brown + * + * 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 +#include +#include +#include +#include + +#include +#include + +mapping_t pers[] = { + { "linear", -1}, + { "raid0", 0}, + { "0", 0}, + { "stripe", 0}, + { "raid1", 1}, + { "1", 1}, + { "mirror", 1}, + { "raid4", 4}, + { "4", 4}, + { "raid5", 5}, + { "5", 5}, + { "multipath", -4}, + { "mp", -4}, + { "raid6", 6}, + { "6", 6}, + { "raid10", 10}, + { "10", 10}, + { NULL, 0} +}; + +struct devmap * devlist = NULL; +int devlist_ready = 0; + +/* From quik.c */ +void fatal(char *fmt,...) __attribute__ ((noreturn)); + +mdev_info_t * md_get_info (const char * device) +{ + + int d; int i=0; char * c; + int vers; int mdev_fd; + mdu_array_info_t array; + mdev_info_t * out = NULL; + + if ((mdev_fd = open(device, O_RDONLY)) > 0) { + vers = md_get_version(mdev_fd); + if (vers > 0) { + if (ioctl(mdev_fd, GET_ARRAY_INFO, &array) < 0) { + close(mdev_fd); + fatal("Couldn't get array info for device %s\n", device); + } + + out = new_mdev_info(array.raid_disks); + out->rlevel = array.level; + + /* Not needed for the moment */ + c = map_num(pers, array.level); + + /* fprintf(stderr, "ARRAY %s level=%s num-devices=%d\n", + md_dev, c?c:"unknown", array.raid_disks); */ + + /* Get devices */ + for (d=0; d < MD_SB_DISKS; d++) { + mdu_disk_info_t disk; + char *dv; + int o; + disk.number = d; + if (ioctl(mdev_fd, GET_DISK_INFO, &disk) < 0) { continue; } + if (d > array.raid_disks && + disk.major == 0 && + disk.minor == 0) { continue; } + + if ((dv=map_dev(disk.major, disk.minor))) { + out->devs[i]->spart = (char *) malloc(strlen(dv)+1); + strcpy(out->devs[i]->spart, dv); + o = digit_offset(out->devs[i]->spart); + out->devs[i]->bootdev = (char *) malloc(o+1); + strncpy(out->devs[i]->bootdev, out->devs[i]->spart, o); + out->devs[i]->bootdev[o+1] = 0x00; + i++; + } + } + + out->metadev = (char *)malloc(strlen(device)+1); + strcpy(out->metadev, device); + out->metadev[strlen(device)] = 0x00; + } else { + close(mdev_fd); + fatal("%s does not seem to be an md device. Exiting.", device); + } + close(mdev_fd); + } else { + fatal("Could not open device %s.\n", device); + } + + return out; +} + +int md_get_version (int fd) +{ + mdu_version_t vers; + struct stat stb; + + if (fstat(fd, &stb)<0) { + return -1; + } + if ((S_IFMT&stb.st_mode) != S_IFBLK) { + fprintf(stderr, "This is not a block device.\n"); + return -1; + } + + if (ioctl(fd, RAID_VERSION, &vers) == 0) { + return (vers.major*10000) + (vers.minor*100) + vers.patchlevel; + } + + if (errno == EACCES) { + perror("Could not access the given device"); + return -1; + } else { + perror("get_version"); + } + + if (major(stb.st_rdev) == MD_MAJOR) + return (3600); + + return -1; +} + +/* + * Returns the offset of the first digit + */ +int digit_offset (const char * str) +{ + int l; int o = -1; + + if (str) { + l = strlen(str); + while (++oname) { + if (map->num == num) + return map->name; + map++; + } + return NULL; +} + +/* + * Find a block device with the right major/minor number. + * Avoid /dev/mdNN and /dev/md/dNN if possible + */ +char * map_dev(int major, int minor) +{ + struct devmap *p; + char *std = NULL; + if (!devlist_ready) { + nftw("/dev", add_dev, 10, FTW_PHYS); + devlist_ready=1; + } + + for (p=devlist; p; p=p->next) + if (p->major == major && + p->minor == minor) { + if (is_standard(p->name, NULL)) + std = p->name; + else + return p->name; + } + return std; +} + + +int is_standard(char *dev, int *nump) +{ + /* tests if dev is a "standard" md dev name. + * i.e if the last component is "/dNN" or "/mdNN", + * where NN is a string of digits + */ + char *d = strrchr(dev, '/'); + int type=0; + int num; + if (!d) + return 0; + if (strncmp(d, "/d",2)==0) + d += 2, type=1; /* /dev/md/dN{pM} */ + else if (strncmp(d, "/md_d", 5)==0) + d += 5, type=1; /* /dev/md_dNpM */ + else if (strncmp(d, "/md", 3)==0) + d += 3, type=-1; /* /dev/mdN */ + else if (d-dev > 3 && strncmp(d-2, "md/", 3)==0) + type = -1; /* /dev/md/N */ + else + return 0; + if (!*d) + return 0; + num = atoi(d); + while (isdigit(*d)) + d++; + if (*d) + return 0; + if (nump) *nump = num; + + return type; +} + +int add_dev(const char *name, const struct stat *stb, int flag, struct FTW *s) +{ + if ((stb->st_mode&S_IFMT)== S_IFBLK) { + char *n = strdup(name); + struct devmap *dm = malloc(sizeof(*dm)); + if (dm) { + dm->major = major(stb->st_rdev); + dm->minor = minor(stb->st_rdev); + dm->name = n; + dm->next = devlist; + devlist = dm; + } + } + return 0; +} + +/* Does NOT allocate space for individual strings, + * i.e. bootdevs[i] or metadev + */ +mdev_info_t * new_mdev_info (unsigned char ndevs) +{ + int i; + mdev_info_t * out = (mdev_info_t *)malloc(sizeof(mdev_info_t)); + + out->ndevs = ndevs; + out->bs = out->nsect = 0; + out->devs = (dev_info_t **)malloc(ndevs*sizeof(dev_info_t *)); + for (i=0; idevs[i] = new_dev_info(); + } + out->metadev = out->fs_dev = NULL; + out->rlevel = INT_MAX; + + return out; +} + +dev_info_t * new_dev_info () +{ + dev_info_t * out = (dev_info_t *)malloc(sizeof(dev_info_t)); + + out->spart = out->bootdev = NULL; + out->part_block = out->secsize = 0; + out->first_bootable = 0; + out->doff = 0; + out->cpart = 0; + + return out; +} + +void free_mdev_info(mdev_info_t * obs) +{ + int i; + + if (obs) { + /* fs_dev is a convenience pointer, not free()ed */ + if (obs->metadev) free(obs->metadev); + if (obs->devs) { + for (i=0; indevs; i++) { + free_dev_info(obs->devs[i]); + } + free(obs->devs); + } + free(obs); + } +} + +void free_dev_info (dev_info_t * obs) +{ + if (obs) { + if (obs->bootdev) free(obs->bootdev); + if (obs->spart) free(obs->spart); + free(obs); + } +} --- quik-2.1.orig/quik.spec +++ quik-2.1/quik.spec @@ -1,12 +1,12 @@ -Summary: Disk bootstrap and installer for Linux/PPC +Summary: Disk bootstrap and installer for GNU/Linux PPC Name: quik -Version: 2.0 -Release: 0e +Version: 2.1 +#Release: 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 +URL: http://dav.kisikew.org/cgi/viewarch.cgi, http://dav.kisikew.org/cgi/archzoom.cgi +Packager: Eric Côté , Peter 'p2' De Schrijver +Source: ftp://simonraven.nuit.ca/src/quik/quik-daily.tar.gz, ftp://ftp.penguinppc.org/simon/quik/quik-daily.tar.gz BuildRoot: /tmp/quik-root ExclusiveArch: ppc @@ -89,6 +89,6 @@ /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 +/usr/share/man/man5/quik.conf.5 +/usr/share/man/man8/quik.8 +/usr/share/man/man8/bootstrap.8 --- quik-2.1.orig/second/Makefile +++ quik-2.1/second/Makefile @@ -2,13 +2,13 @@ ## Linux Loader for Macintosh ## -CFLAGS = -I../include -O2 -D__NO_STRING_INLINES +CFLAGS = -I../include -O2 -D__NO_STRING_INLINES -Wall -ffreestanding -LDFLAGS= -Ttext 0x3e0000 +LDFLAGS=-N -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 + nosys.o stricmp.o misc.o inflate.o unzip.o all: second.b --- quik-2.1.orig/second/cfg.c +++ quik-2.1/second/cfg.c @@ -17,10 +17,11 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include +/* NOT glibc's - see note in ./setjmp.h */ +#include "setjmp.h" #include -#include #include "quik.h" +#include "prom.h" typedef enum { cft_strg, cft_flag, cft_end @@ -92,15 +93,20 @@ struct IMAGES *next; } *images = NULL; +static inline int myputchar(int c, void *dummy) +{ + return putchar(c); +} + void cfg_error (char *msg,...) { va_list ap; va_start (ap, msg); - printf ("Config file error: "); - vprintf (msg, ap); + qprintf ("Config file error: "); + qvprintf (msg, myputchar, NULL, ap); va_end (ap); - printf (" near line %d in file %s\n", line_num, file_name); + qprintf (" near line %d in file %s\n", line_num, file_name); longjmp (env, 1); } @@ -109,10 +115,10 @@ va_list ap; va_start (ap, msg); - printf ("Config file warning: "); - vprintf (msg, ap); + qprintf ("Config file warning: "); + qvprintf (msg, myputchar, NULL, ap); va_end (ap); - printf (" near line %d in file %s\n", line_num, file_name); + qprintf (" near line %d in file %s\n", line_num, file_name); } inline int getc () @@ -270,7 +276,7 @@ { CONFIG *walk; - if (!strcasecmp (item, "image")) { + if (!stricmp (item, "image")) { struct IMAGES **p = &images; while (*p) @@ -281,7 +287,7 @@ 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 (walk->name && !stricmp (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) @@ -326,9 +332,10 @@ { CONFIG *walk; - for (walk = table; walk->type != cft_end; walk++) - if (walk->name && !strcasecmp (walk->name, item)) + for (walk = table; walk->type != cft_end; walk++) + if (walk->name && !stricmp (walk->name, item)) return walk->data; + return 0; } @@ -349,7 +356,7 @@ label = alias + 1; } alias = cfg_get_strg_i (p->table, "alias"); - if (!strcmp (label, image) || (alias && !strcmp (alias, image))) { + if (!stricmp (label, image) || (alias && !stricmp (alias, image))) { ret = cfg_get_strg_i (p->table, item); if (!ret) ret = cfg_get_strg_i (cf_options, item); @@ -370,8 +377,8 @@ int len = strlen (label); if (!printl_count) - printf ("\n"); - printf ("%s", label); + qprintf ("\n"); + qprintf ("%s", label); while (len++ < 25) putchar (' '); printl_count++; @@ -398,7 +405,7 @@ if (alias) printlabel (alias); } - printf ("\nYou can also type in custom image locations, in the form\n" + qprintf ("\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"); } --- quik-2.1.orig/second/cmdline.c +++ quik-2.1/second/cmdline.c @@ -18,6 +18,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "quik.h" +#include "prom.h" #define CMD_LENG 512 char cbuff[CMD_LENG]; --- quik-2.1.orig/second/ctype.c +++ quik-2.1/second/ctype.c @@ -7,18 +7,3 @@ 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.orig/second/disk.c +++ quik-2.1/second/disk.c @@ -1,6 +1,5 @@ #include "quik.h" #include "prom.h" -#include char bootdevice[512]; static char current_devname[512]; @@ -10,7 +9,7 @@ { current_dev = call_prom("open", 1, 1, device); if (current_dev == (ihandle) 0 || current_dev == (ihandle) -1) { - printf("\nCouldn't open %s\n", device); + qprintf("\nCouldn't open %s\n", device); return -1; } strcpy(current_devname, device); @@ -53,7 +52,7 @@ * just a few partitions. -- Cort */ if ( is_chrp ) - sprintf(bootdevice, "disk:0"); + qsprintf(bootdevice, "disk:0"); if( open(bootdevice) ) { /* @@ -61,7 +60,7 @@ * try this if disk:0 fails * -- Cort */ - sprintf(bootdevice, "/pci@fee00000/scsi@c/sd@8:0"); + qsprintf(bootdevice, "/pci@fee00000/scsi@c/sd@8:0"); return open(bootdevice); } return 0; --- quik-2.1.orig/second/file.c +++ quik-2.1/second/file.c @@ -17,14 +17,13 @@ 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 +#define _STDIO_H #include #include #include "quik.h" typedef int FILE; -#include +#include #include #include #include @@ -107,7 +106,7 @@ /* If part is 0, use the first bootable partition. */ if (part == upart || (part == 0 && (mp->status & STATUS_BOOTABLE) != 0 - && strcasecmp(mp->processor, "powerpc") == 0)) { + && stricmp(mp->processor, "powerpc") == 0)) { doff = (long long) mp->start_block * secsize; return 1; } @@ -130,7 +129,7 @@ static int read_dos_partition(int part) { - int rc, i, v; + int rc, i; char blk[512]; struct partition { unsigned char boot_ind; /* 0x80 - active */ @@ -155,7 +154,7 @@ /* check the MSDOS partition magic */ if ( (blk[0x1fe] != 0x55) || (blk[0x1ff] != 0xaa) ) { - printf("No MSDOS partition magic number on disk!\n"); + qprintf("No MSDOS partition magic number on disk!\n"); return 0; } if ( part >= 4 ) @@ -167,14 +166,9 @@ 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); + qprintf ((char *) fmt); } static errcode_t linux_open (const char *name, int flags, io_channel * channel) @@ -197,7 +191,7 @@ io->write_error = 0; doff = 0; - partno = *(name + strlen (name) - 1) - '0'; + partno = strtol(name + strlen("/dev/sda"), 0, 0); if (!read_mac_partition(partno) && !read_dos_partition(partno) ) return EXT2_ET_BAD_DEVICE_NAME; @@ -207,11 +201,13 @@ static errcode_t linux_close (io_channel channel) { + return 0; } static errcode_t linux_set_blksize (io_channel channel, int blksize) { channel->block_size = bs = blksize; + return 0; } static errcode_t linux_read_blk (io_channel channel, unsigned long block, int count, void *data) @@ -222,7 +218,7 @@ 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); + qprintf ("\nRead error on block %lu", block); return EXT2_ET_SHORT_READ; } return 0; @@ -230,10 +226,12 @@ static errcode_t linux_write_blk (io_channel channel, unsigned long block, int count, const void *data) { + return 0; } static errcode_t linux_flush (io_channel channel) -{ +{ + return 0; } static int open_ext2 (char *device) @@ -253,7 +251,7 @@ static char rot[] = "\\|/-"; if (!(i % freq)) - printf ("%c\b", rot[(i / freq) % 4]); + qprintf ("%c\b", rot[(i / freq) % 4]); i++; } @@ -314,18 +312,17 @@ block_cnt = 0; retval = ext2fs_block_iterate(fs, inode, 0, 0, dump_block, 0); if (retval) { - printf ("Error %d reading %s", retval, filename); + qprintf ("Error %d reading %s", (int)retval, filename); return 0; } return dump_finish(); } int dump_device_range(char *filename, char *bogusdev, int *len, - void (*lenfunc)(int, char **, char **)) + void (*lenfunc)(int, unsigned char **, unsigned char **)) { /* Range of blocks on physical block device */ int start, end = -1; - int retval; char *p; bs = 512; @@ -342,15 +339,15 @@ } } if (end == -1) { - printf ("\n" + qprintf ("\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"); +"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); + (*lenfunc)((end - start) << 9, &filebuffer, &filelimit); fs = (ext2_filsys) malloc (sizeof (struct struct_ext2_filsys)); if (fs) { if (!linux_open(bogusdev, 0, &fs->io)) { @@ -369,7 +366,7 @@ } } } - printf ("\nInternal error while loading blocks from device\n"); + qprintf ("\nInternal error while loading blocks from device\n"); return 0; } @@ -384,17 +381,19 @@ int load_file(char *device, int partno, char *filename, char *buffer, char *limit, int *len, - int dogunzip, void (*lenfunc)(int, char **, char **)) + int dogunzip, void (*lenfunc)(int, unsigned char **, + unsigned char **)) { - ino_t inode; + ext2_ino_t inode; int retval; - char bogusdev[] = "/dev/sdaX"; + char bogusdev[11]; if (device == 0) device = bootdevice; if (setdisk(device) < 0) return 0; - bogusdev[8] = partno + '0'; + partno &= 0xf; + qsprintf(bogusdev, "/dev/sda%d", partno); filebuffer = buffer; filelimit = limit; decompress = dogunzip & 1; @@ -405,8 +404,8 @@ return 0; } type = ext2; - if (retval = ext2fs_namei(fs, root, cwd, filename, &inode)) { - printf("\nInode error #%d while loading file %s.", retval, filename); + if ((retval = ext2fs_namei_follow(fs, root, cwd, filename, &inode))) { + qprintf("\nInode error #%d while loading file %s.", retval, filename); ext2fs_close(fs); return 0; } @@ -417,7 +416,7 @@ } if (lenfunc) - (*lenfunc)(size, (char **)&filebuffer, (char **)&filelimit); + (*lenfunc)(size, &filebuffer, &filelimit); retval = 0; if (inode) --- quik-2.1.orig/second/main.c +++ quik-2.1/second/main.c @@ -28,7 +28,9 @@ #undef BOOTINFO #include "quik.h" -#include +#include "prom.h" +#include "gzip.h" +#define __KERNEL__ #include #include #ifdef BOOTINFO @@ -45,25 +47,28 @@ extern int start; extern char bootdevice[]; +extern char *out; +extern unsigned int input_len; 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; +static unsigned char *elf_image; #define DEFAULT_TIMEOUT -1 void fatal(const char *msg) { - printf("\nFatal error: %s\n", msg); + qprintf("\nFatal error: %s\n", msg); } void maintabfunc (void) { if (useconf) { cfg_print_images(); - printf("boot: %s", cbuff); + qprintf("boot: %s", cbuff); } } @@ -110,7 +115,7 @@ { char *p; - *paramsp = 0; + *paramsp = "\0"; p = *linep; if (p == 0) return; @@ -189,65 +194,187 @@ return buffer; } -int get_params(char **device, int *part, char **kname, char **params) +void boot_kernel_initrd(void *prom_entry,char *device, int part, char *kname, + char *params, char *initrdname) { - 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]; + int i, len, image_len, image_memsize,initrd_size=0; + Elf32_Ehdr *e; + Elf32_Phdr *p; + unsigned load_loc, entry, start,off; + unsigned char *initrd_start=NULL; - pause_after = 0; - *params = ""; + if (!kname) + return; + + if (!load_file(device, part, kname, IMAGE_BUF, IMAGE_END, + &image_len, 1, 0)) { + qprintf ("\nImage not found.... try again\n"); + return; + } + + if (image_len > IMAGE_END - IMAGE_BUF) { + qprintf("\nImage is too large (%u > %u)\n", image_len, + IMAGE_END - IMAGE_BUF); + return; + } + + if(memcmp(IMAGE_BUF, GZIP_MAGIC,2) == 0 || + memcmp(IMAGE_BUF, OLD_GZIP_MAGIC, 2) == 0) { + qprintf("compressed image !\n"); + elf_image=IMAGE_BUF + ((image_len + 3) & (~3)); + out=elf_image; + input_len=image_len; + uncompress_kernel(0); + } + else + elf_image=IMAGE_BUF; + + /* 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 *) elf_image; + 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)) { + qprintf ("\n%s: unknown image format\n", kname); + return; + } + + if (e->e_ident[EI_CLASS] != ELFCLASS32 + || e->e_ident[EI_DATA] != ELFDATA2MSB) { + qprintf("Image is not a 32bit MSB ELF image\n"); + return; + } + len = 0; + image_memsize = 0; + load_loc = 0; + off = 0; + + p = (Elf32_Phdr *) (elf_image + 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; + image_memsize = p->p_memsz; + } else { + len = p->p_offset + p->p_filesz - off; + image_memsize = p->p_offset + p->p_memsz ; + } + } + if (len == 0) { + qprintf("Cannot find a loadable segment in ELF image\n"); + return; + } + entry = e->e_entry & ADDRMASK; + if (len + off > image_len) + len = image_len - off; + + qprintf("initrd imagename = %s, mem_size: %d\n",initrdname,image_memsize); + image_memsize=(image_memsize + 0x1000) & (~0xfff); + if(initrdname[0]!=0) { + initrd_start=elf_image + image_memsize + off + 0x80000; + qprintf("initrd_start: %p\n",initrd_start); + if(!load_file(device, part, initrdname, initrd_start, + IMAGE_END, &image_len, 1, 0)) { + qprintf("\ninitrd image not found....\n"); + } + else if (image_len > IMAGE_END - initrd_start) { + qprintf("\ninitrd Image is too large (%u > %u)\n", image_len, + IMAGE_END - initrd_start); + } + else { + initrd_size=image_len; + } + } + + set_bootargs(params); + + /* Execute in place, the kernel can relocate itself */ + entry = (entry - load_loc) + off + (unsigned int)elf_image; + load_loc = off + (unsigned int)elf_image; + prom_map((unsigned int)load_loc, (unsigned int)load_loc, len+0x200000 + + initrd_size); + + flush_cache(load_loc, len); + + close(); + if (pause_after) { + qprintf("%s", pause_message); + prom_pause(); + qprintf("\n"); + } + + /* + * For the sake of the Open Firmware XCOFF loader, the entry + * point may actually be a procedure descriptor. + */ + start = *(unsigned *)entry; + /* new boot strategy - see head.S in the kernel for more info -- Cort */ + if (start == 0x60000000/* nop */ ) + start = load_loc; + /* not the new boot strategy, use old logic -- Cort */ + else + { + if (start < load_loc || start >= load_loc + len + || ((unsigned *)entry)[2] != 0) + /* doesn't look like a procedure descriptor */ + start += entry; + } + qprintf("Starting at %x, %p, %d\n", start,initrd_start,initrd_size); +#ifdef BOOTINFO + /* setup the bootinfo */ + binf.magic_start = bin.magic_end = BOOT_INFO_MAGIC; + sqprintf( binf.cmd_line, "%s", params ); + sqprintf( 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)(initrd_start,initrd_size, prom_entry, 0, 0); + + prom_exit(); +} + +int get_char_timeout(int timeout) { + + int c=-1,beg=0,end; - 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) { + 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 == -1) + c = '\r'; + + return c; - 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); - } +} + +int get_params(char *imagename, char **device, int *part, char **kname, + char **params, char **initrdname) +{ + int defpart = -1; + char *defdevice = 0; + char *p, *endp; + int n; + char *label; - /* chrp gets this wrong, force it -- Cort */ - if ( useconf && (imagename[0] == 0) ) - imagename = cfg_get_default(); + pause_after = 0; + *initrdname = ""; label = 0; defdevice = bootdevice; @@ -268,16 +395,19 @@ label = imagename; imagename = p; defdevice = cfg_get_strg(label, "device"); + *initrdname = cfg_get_strg(label, "initrd"); + 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; @@ -295,7 +425,7 @@ if (!*device) *device = defdevice; if (!*kname) - printf( + qprintf( "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"); @@ -327,7 +457,7 @@ 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); + qprintf("\n%s", (char *)TMP_BUF); } } } @@ -335,17 +465,13 @@ /* 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; + char *kname, *params, *device, *initrdname, *q, *imagename; + int part,c; + int fileok = 0,timeout; extern char __bss_start, _end; struct first_info real_fip; + char bootargs[512]; + #ifdef BOOTINFO struct boot_info binf; #endif @@ -355,6 +481,7 @@ * and we don't have the BootX signature assume we're * chrp. -- Cort */ + if ( (id != 0xdeadbeef) && ((unsigned long)prom_entry != 0x426f6f58) ) { is_chrp = 1; @@ -376,7 +503,7 @@ if ( (unsigned long)prom_entry == 0x426f6f58 ) { - printf("BootX launched us\n"); + qprintf("BootX launched us\n"); prom_entry = (void *)id; /* * These should come from the bootx info. @@ -390,7 +517,8 @@ memset(&__bss_start, 0, &_end - &__bss_start); prom_init(prom_entry); - printf("Second-stage QUIK loader\n"); + qprintf("Second-stage QUIK loader\n"); + qprintf("Welcome to quik. mate is good.\n"); if (diskinit() == -1) prom_exit(); @@ -402,122 +530,71 @@ 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); + qprintf("\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); + qprintf ("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); + qprintf("%s", p); p = cfg_get_strg(0, "message"); if (p) print_message_file(p); } } else - printf ("\n"); + qprintf ("\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; + timeout = DEFAULT_TIMEOUT; + if (useconf && (q = cfg_get_strg(0, "timeout")) != 0 && *q != 0) + timeout = strtol(q, NULL, 0); + + prom_get_chosen("bootargs", bootargs, sizeof(bootargs)); + imagename = bootargs; +qprintf("chosen/bootargs = %s\n",imagename); + word_split(&imagename, ¶ms); + + qprintf("boot: "); + c=get_char_timeout(timeout); + + if (c == '\r' && !is_chrp) { + qprintf("%s", imagename); + if (params) + qprintf(" %s", params); + qprintf("\n"); + + if(imagename[0]!=0) { + get_params(imagename, &device, &part, &kname, ¶ms, &initrdname); + boot_kernel_initrd(prom_entry,device,part,kname,params,initrdname); + qprintf("boot: "); + } } - 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 (;;) { + if (c == '\r' && useconf) { + imagename = cfg_get_default(); + qprintf("%s\n", imagename); + } + else { + cmdinit(); + cmdedit(maintabfunc, c); + qprintf("\n"); + strcpy(given_bootargs, cbuff); + given_bootargs_by_user = 1; + imagename = cbuff; + word_split(&imagename, ¶ms); + } + get_params(imagename, &device, &part, &kname, ¶ms, &initrdname); + boot_kernel_initrd(prom_entry,device,part,kname,params,initrdname); + + params=""; + qprintf("boot: "); + c=getchar(); } - - /* - * 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.orig/second/malloc.c +++ quik-2.1/second/malloc.c @@ -19,6 +19,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include +#include static char *malloc_ptr = (char *) MALLOC_BASE; static char *last_alloc = 0; @@ -32,6 +33,7 @@ malloc_ptr += size + sizeof(int); last_alloc = caddr; malloc_ptr = (char *) ((((unsigned int) malloc_ptr) + 3) & (~3)); + return caddr; } @@ -47,6 +49,7 @@ caddr = malloc(size); if (caddr != 0 && oaddr != 0) memcpy(caddr, oaddr, *(int *)(oaddr - sizeof(int))); + return caddr; } @@ -66,7 +69,7 @@ malloc_ptr = (char *) ptr; } -void *strdup(char *str) +char *strdup(const char *str) { char *p = malloc(strlen(str) + 1); --- quik-2.1.orig/second/printf.c +++ quik-2.1/second/printf.c @@ -18,49 +18,80 @@ #include #include "quik.h" +#include "prom.h" -static void printn(long, int); -extern void vprintf(char *, va_list); +static int printn(long, int,int (*outchar)(int c, void *),void *); +extern int qvprintf(const char *,int (*outchar)(int c, void *), void *,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,...) +static inline int myputchar(int c, void *dummy) +{ + return putchar(c); +} + +void qprintf (const char *fmt,...) { va_list x1; va_start (x1, fmt); - vprintf (fmt, x1); + qvprintf (fmt, myputchar, NULL, x1); va_end (x1); } -void vprintf (char *fmt, va_list adx) +static int putbyte(int c, void *buffer) +{ + + char **buf=(char **)buffer; + + *(buf[0]++)=c; + + return c; +} + +int qsprintf (char *buf, char *fmt,...) +{ + int result; + va_list x1; + + va_start (x1, fmt); + result=qvprintf (fmt, putbyte, &buf,x1); + va_end (x1); + + return result; +} + +int qvprintf (const char *fmt, int (*outchar)(int c,void *buffer), + void *buffer,va_list adx) { - register c; + int c,len=0; char *s; for (;;) { while ((c = *fmt++) != '%') { if (c == '\0') { - putchar (0); - return; + outchar (0,buffer); len++; + return len; } - putchar (c); + outchar (c,buffer); len++; } c = *fmt++; if (c == 'd' || c == 'o' || c == 'x' || c == 'X') { - printn ((long) va_arg (adx, unsigned), - c == 'o' ? 8 : (c == 'd' ? 10 : 16)); + len+=printn ((long) va_arg (adx, unsigned), + c == 'o' ? 8 : (c == 'd' ? 10 : 16),outchar,buffer); } else if (c == 'c') { - putchar (va_arg (adx, unsigned)); + outchar (va_arg (adx, unsigned),buffer); } else if (c == 's') { s = va_arg (adx, char *); - while (c = *s++) - putchar (c); + while ((c = *s++)) { + outchar (c,buffer); len++; + } } else if (c == 'l' || c == 'O') { - printn ((long) va_arg (adx, long), c == 'l' ? 10 : 8); + len+=printn ((long) va_arg (adx, long), c == 'l' ? 10 : 8,outchar, + buffer); } } } @@ -68,20 +99,24 @@ /* * Print an unsigned integer in base b, avoiding recursion. */ -static void printn (long n, int b) +static int printn (long n, int b,int (*outchar)(int c,void *buffer), + void *buffer) { char prbuf[24]; - register char *cp; + char *cp; + int len=0; if (b == 10 && n < 0) { - putchar ('-'); + outchar ('-',buffer); len++; n = -n; } cp = prbuf; - do + do { *cp++ = "0123456789ABCDEF"[(int) (n % b)]; - while (n = n / b & 0x0FFFFFFF); - do - putchar (*--cp); - while (cp > prbuf); + } while ((n = n / b & 0x0FFFFFFF)); + do { + outchar (*--cp,buffer); len++; + } while (cp > prbuf); + + return len; } --- quik-2.1.orig/second/prom.c +++ quik-2.1/second/prom.c @@ -8,6 +8,7 @@ #include #include "prom.h" +#include "quik.h" #define getpromprop(node, name, buf, len) \ ((int)call_prom("getprop", 4, 1, (node), (name), (buf), (len))) @@ -16,6 +17,7 @@ ihandle prom_stdout; ihandle prom_chosen; ihandle prom_options; +ihandle prom_mmu; struct prom_args { char *service; @@ -77,6 +79,40 @@ } int +prom_map(unsigned int phys, unsigned int virt, unsigned int size) +{ + struct prom_args { + char *service; + int nargs; + int nret; + char *method; + ihandle mmu_ihandle; + int misc; + unsigned int size; + unsigned int virt; + unsigned int phys; + int ret0; + } args; + + if (prom_mmu == 0) { + qprintf("map() called, no MMU found\n"); + return -1; + } + args.service = "call-method"; + args.nargs = 6; + args.nret = 1; + args.method = "map"; + args.mmu_ihandle = prom_mmu; + args.misc = 0; + args.phys = phys; + args.virt = virt; + args.size = size; + prom_entry(&args); + + return (int)args.ret0; +} + +int putchar(int c) { char ch = c; @@ -115,6 +151,7 @@ prom_exit(); getpromprop(prom_chosen, "stdout", &prom_stdout, sizeof(prom_stdout)); getpromprop(prom_chosen, "stdin", &prom_stdin, sizeof(prom_stdin)); + getpromprop(prom_chosen, "mmu", &prom_mmu, sizeof(prom_mmu)); prom_options = call_prom("finddevice", 1, 1, "/options"); } --- quik-2.1.orig/second/prom.h +++ quik-2.1/second/prom.h @@ -22,6 +22,8 @@ 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 prom_map(unsigned int phys, unsigned int virt, unsigned int size); int get_ms(void); void prom_pause(void); +void set_bootargs(char *params); + --- quik-2.1.orig/second/quik.h +++ quik-2.1/second/quik.h @@ -2,6 +2,12 @@ * Global procedures and variables for the quik second-stage bootstrap. */ +#include +#include + +#define IMAGE_BUF ((unsigned char *) 0x500000) +#define IMAGE_END ((unsigned char *) 0x1000000) + extern char cbuff[]; extern char bootdevice[]; @@ -11,6 +17,44 @@ void cfg_print_images(void); char *cfg_get_default(void); +void qprintf(const char *fmt,...) __attribute__((format(printf,1,2))); +int qsprintf (char *buf, char *fmt,...) __attribute__((format(printf,2,3))); +int qvprintf (const char *fmt, int (*outchar)(int c,void *buffer), + void *buffer,va_list adx); + +int strtol (const char *nptr, char **endptr, int base); +int tolower(int c); +int stricmp(const char *s1, const char *s2); +int strncmp(const char * cs,const char * ct,size_t count); +int strlen(const char *s1); +char *strcpy(char * dest,const char *src); +char *strncpy(char * dest,const char *src,size_t count); +char *strchr(const char * s, int c); +char *strrchr(const char * s, int c); +int strcmp(const char * cs,const char * ct); +char *strdup(const char *str); +void *memset(void * s,int c,size_t count); +int memcmp(const void * cs,const void * ct,size_t count); +void *memcpy(void * dest,const void *src,size_t count); + +void fatal(const char *msg); + void *malloc(unsigned); +void free (void *m); + +void flush_cache(unsigned int addr, unsigned int len); + +void close(void); +int setdisk(char *device); + + +int load_file(char *device, int partno, char *filename, + char *buffer, char *limit, int *len, + int dogunzip, void (*lenfunc)(int, unsigned char **, + unsigned char **)); + +int diskinit(); + +void cmdinit(); +void cmdedit(void (*tabfunc)(void), int c); -void prom_pause(void); --- quik-2.1.orig/second/strtol.c +++ quik-2.1/second/strtol.c @@ -24,10 +24,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; + +#include "quik.h" + +int strtol (const char *nptr, char **endptr, int base) { int negative; register unsigned int cutoff; @@ -59,11 +59,11 @@ } else negative = 0; - if (base == 16 && s[0] == '0' && (s[1] == 'X') || (s[1] == 'x')) + 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 (base == 0) { if (*s == '0') { if (s[1] == 'X' || s[1] == 'x') { s += 2; @@ -72,6 +72,7 @@ base = 8; } else base = 10; + } /* Save the pointer so we can check later if anything happened. */ save = s; @@ -125,12 +126,13 @@ 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 (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.orig/second/gzip.h +++ quik-2.1/second/gzip.h @@ -0,0 +1,94 @@ +/* gzip.h -- common declarations for all gzip modules + * Copyright (C) 1992-1993 Jean-loup Gailly. + * This is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License, see the file COPYING. + */ +#ifndef GZIP_H +#define GZIP_H + +#define memzero(s, n) memset ((s), 0, (n)) + +/* Return codes from gzip */ +#define OK 0 +#define ERROR 1 +#define WARNING 2 + +/* Compression methods (see algorithm.doc) */ +#define STORED 0 +#define COMPRESSED 1 +#define PACKED 2 +/* + * methods 3 to 7 reserved + */ +#define DEFLATED 8 + +extern unsigned long bytes_out; /* # of uncompressed bytes */ +extern int method; /* compression method */ + +#define INBUFSIZ 0x20000 /* input buffer size */ +#define WSIZE 0x8000 /* window size--must be a power of two, and */ + /* at least 32K for zip's deflate method */ + +unsigned char *inbuf; /* input buffer */ +unsigned char *window; /* sliding window and suffix table (unlzw) */ + +extern unsigned insize; /* valid bytes in inbuf */ +extern unsigned inptr; /* index of next byte to be processed in inbuf */ +extern unsigned outcnt; /* bytes in output buffer */ + +#define GZIP_MAGIC "\037\213" /* Magic header for gzip files, 1F 8B */ +#define OLD_GZIP_MAGIC "\037\236" /* Magic header for gzip 0.5 = freeze 1.x */ +#define PKZIP_MAGIC "PK\003\004" /* Magic header for pkzip files */ +#define PACK_MAGIC "\037\036" /* Magic header for packed files */ + +/* gzip flag byte */ +#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ +#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */ +#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ +#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ +#define COMMENT 0x10 /* bit 4 set: file comment present */ +#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */ +#define RESERVED 0xC0 /* bit 6,7: reserved */ + +/* internal file attribute */ +#define UNKNOWN (-1) +#define BINARY 0 +#define ASCII 1 + + +#define MIN_MATCH 3 +#define MAX_MATCH 258 +/* The minimum and maximum match lengths */ + +#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) +/* Minimum amount of lookahead, except at the end of the input file. + * See deflate.c for comments about the MIN_MATCH+1. + */ + +#define MAX_DIST (WSIZE-MIN_LOOKAHEAD) +/* In order to simplify the code, particularly on 16 bit machines, match + * distances are limited to MAX_DIST instead of WSIZE. + */ + +#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf()) +#define put_char(c) {window[outcnt++]=(unsigned char)(c); if (outcnt==WSIZE)\ + flush_window();} + +/* Macros for getting two-byte and four-byte header values */ +#define SH(p) ((unsigned short)(unsigned char)((p)[0]) | ((unsigned short)(unsigned char)((p)[1]) << 8)) +#define LG(p) ((unsigned long)(SH(p)) | ((unsigned long)(SH((p)+2)) << 16)) + +/* in unzip.c */ +extern void unzip (int in, int out); + +/* in misc.c: */ +extern unsigned long updcrc (unsigned char *s, unsigned n); +extern void clear_bufs (void); +extern int fill_inbuf (void); +extern void flush_window (void); +extern void unzip_error (char *m); + +/* in inflate.c */ +extern int inflate (void); + +#endif /* GZIP_H */ --- quik-2.1.orig/second/inflate.c +++ quik-2.1/second/inflate.c @@ -0,0 +1,829 @@ +/* + * inflate.c -- Not copyrighted 1992 by Mark Adler + * version c10p1, 10 January 1993 + */ +/* + * Adapted for booting Linux by Hannu Savolainen 1993 + * based on gzip-1.0.3 + */ + +#include "gzip.h" +#include "quik.h" +#define slide window + +#include + +extern void *malloc(size_t size); +extern void free(void *ptr); + +#if 0 +#define DEBG(x) {register long sp asm("30"); \ + printf("%s (sp=%lx)\n", x, sp);} +#define DEBG1(x) {register long sp asm("30"); \ + printf(" %s (sp=%lx)\n", x, sp);} +#else +#define DEBG(x) +#define DEBG1(x) +#endif + +#define NOMEMCPY 1 + +struct huft { + unsigned char e; /* number of extra bits or operation */ + unsigned char b; /* number of bits in this code or subcode */ + union { + unsigned short n; /* literal, length base, or distance base */ + struct huft *t; /* pointer to next level of table */ + } v; +}; + + +/* Function prototypes */ +int huft_build (unsigned *, unsigned, unsigned, unsigned short *, + unsigned short *, struct huft **, int *); +int huft_free (struct huft *); +int inflate_codes (struct huft *, struct huft *, int, int); +int inflate_stored (void); +int inflate_fixed (void); +int inflate_dynamic (void); +int inflate_block (int *); +int inflate (void); + + +#define wp outcnt +#define flush_output(w) (wp=(w),flush_window()) + +/* Tables for deflate from PKZIP's appnote.txt. */ +static unsigned border[] = { + /* Order of the bit length code lengths */ + 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 +}; + +static unsigned short cplens[] = { + /* Copy lengths for literal codes 257..285 */ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0 +}; + +/* note: see note #13 above about the 258 in this list. */ +static unsigned short cplext[] = { + /* Extra bits for literal codes 257..285 */ + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, + 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 99, 99 /* 99==invalid */ +}; + +static unsigned short cpdist[] = { + /* Copy offsets for distance codes 0..29 */ + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577 +}; + +static unsigned short cpdext[] = { + /* Extra bits for distance codes */ + 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, + 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, + 12, 12, 13, 13 +}; + + +unsigned long bb; /* bit buffer */ +unsigned bk; /* bits in bit buffer */ + +unsigned short mask_bits[] = { + 0x0000, + 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, + 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff +}; + +#define NEXTBYTE() (unsigned char)get_byte() +#define NEEDBITS(n) {while(k<(n)){b|=((unsigned long)NEXTBYTE())<>=(n);k-=(n);} + +int lbits = 9; /* bits in base literal/length lookup table */ +int dbits = 6; /* bits in base distance lookup table */ + + +/* + * If BMAX needs to be larger than 16, then h and x[] should be + * unsigned long. + */ +#define BMAX 16 /* maximum bit length of any code (16 for explode) */ +#define N_MAX 288 /* maximum number of codes in any set */ + + +unsigned hufts; /* track memory usage */ + + +/* + * Given a list of code lengths and a maximum table size, make a set + * of tables to decode that set of codes. Return zero on success, one + * if the given code set is incomplete (the tables are still built in + * this case), two if the input is invalid (all zero length codes or + * an oversubscribed set of lengths), and three if not enough + * memory. + */ +int +huft_build(b, n, s, d, e, t, m) +unsigned *b; /* code lengths in bits (all assumed <= BMAX) */ +unsigned n; /* number of codes (assumed <= N_MAX) */ +unsigned s; /* number of simple-valued codes (0..s-1) */ +unsigned short *d; /* list of base values for non-simple codes */ +unsigned short *e; /* list of extra bits for non-simple codes */ +struct huft **t; /* result: starting table */ +int *m; /* maximum lookup bits, returns actual */ +{ + unsigned a; /* counter for codes of length k */ + unsigned c[BMAX+1]; /* bit length count table */ + unsigned f; /* i repeats in table every f entries */ + int g; /* maximum code length */ + int h; /* table level */ + register unsigned i; /* counter, current code */ + register unsigned j; /* counter */ + register int k; /* number of bits in current code */ + int l; /* bits per table (returned in m) */ + register unsigned *p; /* pointer into c[], b[], or v[] */ + register struct huft *q; /* points to current table */ + struct huft r; /* table entry for structure assignment */ + struct huft *u[BMAX]; /* table stack */ + unsigned v[N_MAX]; /* values in order of bit length */ + register int w; /* bits before this table == (l * h) */ + unsigned x[BMAX+1]; /* bit offsets, then code stack */ + unsigned *xp; /* pointer into x */ + int y; /* number of dummy codes added */ + unsigned z; /* number of entries in current table */ + +DEBG("huft1 "); + + /* Generate counts for each bit length */ + memzero(c, sizeof(c)); + p = b; i = n; + do { + c[*p++]++; /* assume all entries <= BMAX */ + } while (--i); + if (c[0] == n) /* null input--all zero length codes */ + { + *t = (struct huft *)NULL; + *m = 0; + return 0; + } + +DEBG("huft2 "); + + /* Find minimum and maximum length, bound *m by those */ + l = *m; + for (j = 1; j <= BMAX; j++) + if (c[j]) + break; + k = j; /* minimum code length */ + if ((unsigned)l < j) + l = j; + for (i = BMAX; i; i--) + if (c[i]) + break; + g = i; /* maximum code length */ + if ((unsigned)l > i) + l = i; + *m = l; + +DEBG("huft3 "); + + /* Adjust last length count to fill out codes, if needed */ + for (y = 1 << j; j < i; j++, y <<= 1) + if ((y -= c[j]) < 0) + return 2; /* bad input: more codes than bits */ + if ((y -= c[i]) < 0) + return 2; + c[i] += y; + +DEBG("huft4 "); + + /* Generate starting offsets into the value table for each length */ + x[1] = j = 0; + p = c + 1; xp = x + 2; + while (--i) { /* note that i == g from above */ + *xp++ = (j += *p++); + } + +DEBG("huft5 "); + + /* Make a table of values in order of bit lengths */ + p = b; i = 0; + do { + if ((j = *p++) != 0) + v[x[j]++] = i; + } while (++i < n); + +DEBG("h6 "); + + /* Generate the Huffman codes and for each, make the table entries */ + x[0] = i = 0; /* first Huffman code is zero */ + p = v; /* grab values in bit order */ + h = -1; /* no tables yet--level -1 */ + w = -l; /* bits decoded == (l * h) */ + u[0] = (struct huft *)NULL; /* just to keep compilers happy */ + q = (struct huft *)NULL; /* ditto */ + z = 0; /* ditto */ +DEBG("h6a "); + + /* go through the bit lengths (k already is bits in shortest code) */ + for (; k <= g; k++) + { +DEBG("h6b "); + a = c[k]; + while (a--) + { +DEBG("h6b1 "); + /* here i is the Huffman code of length k bits for value *p */ + /* make tables up to required level */ + while (k > w + l) + { +DEBG1("1 "); + h++; + w += l; /* previous table always l bits */ + + /* compute minimum size table less than or equal to l bits */ + z = (z = g - w) > (unsigned)l ? l : z; /* upper limit on table size */ + if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */ + { /* too few codes for k-w bit table */ +DEBG1("2 "); + f -= a + 1; /* deduct codes from patterns left */ + xp = c + k; + while (++j < z) /* try smaller tables up to z bits */ + { + if ((f <<= 1) <= *++xp) + break; /* enough codes to use up j bits */ + f -= *xp; /* else deduct codes from patterns */ + } + } +DEBG1("3 "); + z = 1 << j; /* table entries for j-bit table */ + + /* allocate and link in new table */ + q = (struct huft *)malloc((z + 1)*sizeof(struct huft)); +DEBG1("4 "); + hufts += z + 1; /* track memory usage */ + *t = q + 1; /* link to list for huft_free() */ + *(t = &(q->v.t)) = (struct huft *)NULL; + u[h] = ++q; /* table starts after link */ + +DEBG1("5 "); + /* connect to last table, if there is one */ + if (h) + { + x[h] = i; /* save pattern for backing up */ + r.b = (unsigned char)l; /* bits to dump before this table */ + r.e = (unsigned char)(16 + j); /* bits in this table */ + r.v.t = q; /* pointer to this table */ + j = i >> (w - l); /* (get around Turbo C bug) */ + u[h-1][j] = r; /* connect to last table */ + } +DEBG1("6 "); + } +DEBG("h6c "); + + /* set up table entry in r */ + r.b = (unsigned char)(k - w); + if (p >= v + n) + r.e = 99; /* out of values--invalid code */ + else if (*p < s) + { + r.e = (unsigned char)(*p < 256 ? 16 : 15); /* 256 is end-of-block code */ + r.v.n = *p++; /* simple code is just the value */ + } + else + { + r.e = (unsigned char)e[*p - s]; /* non-simple--look up in lists */ + r.v.n = d[*p++ - s]; + } +DEBG("h6d "); + + /* fill code-like entries with r */ + f = 1 << (k - w); + for (j = i >> w; j < z; j += f) + q[j] = r; + + /* backwards increment the k-bit code i */ + for (j = 1 << (k - 1); i & j; j >>= 1) + i ^= j; + i ^= j; + + /* backup over finished tables */ + while ((i & ((1 << w) - 1)) != x[h]) + { + h--; /* don't need to update q */ + w -= l; + } +DEBG("h6e "); + } +DEBG("h6f "); + } + +DEBG("huft7 "); + + /* Return true (1) if we were given an incomplete table */ + return y != 0 && g != 1; +} + + + +int huft_free(t) +struct huft *t; /* table to free */ +/* Free the malloc'ed tables built by huft_build(), which makes a linked + list of the tables it made, with the links in a dummy first entry of + each table. */ +{ + register struct huft *p, *q; + + + /* Go through linked list, freeing from the malloced (t[-1]) address. */ + p = t; + while (p != (struct huft *)NULL) + { + q = (--p)->v.t; + free(p); + p = q; + } + return 0; +} + + +int inflate_codes(tl, td, bl, bd) +struct huft *tl, *td; /* literal/length and distance decoder tables */ +int bl, bd; /* number of bits decoded by tl[] and td[] */ +/* inflate (decompress) the codes in a deflated (compressed) block. + Return an error code or zero if it all goes ok. */ +{ + register unsigned e; /* table entry flag/number of extra bits */ + unsigned n, d; /* length and index for copy */ + unsigned w; /* current window position */ + struct huft *t; /* pointer to table entry */ + unsigned ml, md; /* masks for bl and bd bits */ + register unsigned long b; /* bit buffer */ + register unsigned k; /* number of bits in bit buffer */ + + + /* make local copies of globals */ + b = bb; /* initialize bit buffer */ + k = bk; + w = wp; /* initialize window position */ + + /* inflate the coded data */ + ml = mask_bits[bl]; /* precompute masks for speed */ + md = mask_bits[bd]; + for (;;) /* do until end of block */ + { + NEEDBITS((unsigned)bl) + if ((e = (t = tl + ((unsigned)b & ml))->e) > 16) + do { + if (e == 99) + return 1; + DUMPBITS(t->b) + e -= 16; + NEEDBITS(e) + } while ((e = (t = t->v.t + ((unsigned)b & mask_bits[e]))->e) > 16); + DUMPBITS(t->b) + if (e == 16) /* then it's a literal */ + { + slide[w++] = (unsigned char)t->v.n; + if (w == WSIZE) + { + flush_output(w); + w = 0; + } + } + else /* it's an EOB or a length */ + { + /* exit if end of block */ + if (e == 15) + break; + + /* get length of block to copy */ + NEEDBITS(e) + n = t->v.n + ((unsigned)b & mask_bits[e]); + DUMPBITS(e); + + /* decode distance of block to copy */ + NEEDBITS((unsigned)bd) + if ((e = (t = td + ((unsigned)b & md))->e) > 16) + do { + if (e == 99) + return 1; + DUMPBITS(t->b) + e -= 16; + NEEDBITS(e) + } while ((e = (t = t->v.t + ((unsigned)b & mask_bits[e]))->e) > 16); + DUMPBITS(t->b) + NEEDBITS(e) + d = w - t->v.n - ((unsigned)b & mask_bits[e]); + DUMPBITS(e) + + /* do the copy */ + do { + n -= (e = (e = WSIZE - ((d &= WSIZE-1) > w ? d : w)) > n ? n : e); +#if !defined(NOMEMCPY) && !defined(DEBUG) + if (w - d >= e) /* (this test assumes unsigned comparison) */ + { + memcpy(slide + w, slide + d, e); + w += e; + d += e; + } + else /* do it slow to avoid memcpy() overlap */ +#endif /* !NOMEMCPY */ + do { + slide[w++] = slide[d++]; + } while (--e); + if (w == WSIZE) + { + flush_output(w); + w = 0; + } + } while (n); + } + } + + + /* restore the globals from the locals */ + wp = w; /* restore global window pointer */ + bb = b; /* restore global bit buffer */ + bk = k; + + /* done */ + return 0; +} + + + +int inflate_stored() +/* "decompress" an inflated type 0 (stored) block. */ +{ + unsigned n; /* number of bytes in block */ + unsigned w; /* current window position */ + register unsigned long b; /* bit buffer */ + register unsigned k; /* number of bits in bit buffer */ + +DEBG(""); + return 0; +} + + + +int inflate_fixed() +/* decompress an inflated type 1 (fixed Huffman codes) block. We should + either replace this with a custom decoder, or at least precompute the + Huffman tables. */ +{ + int i; /* temporary variable */ + struct huft *tl; /* literal/length code table */ + struct huft *td; /* distance code table */ + int bl; /* lookup bits for tl */ + int bd; /* lookup bits for td */ + unsigned l[288]; /* length list for huft_build */ + +DEBG(" 1) + { + huft_free(tl); + + DEBG(">"); + return i; + } + + + /* decompress until an end-of-block code */ + if (inflate_codes(tl, td, bl, bd)) + return 1; + + + /* free the decoding tables, return */ + huft_free(tl); + huft_free(td); + return 0; +} + + + +int inflate_dynamic() +/* decompress an inflated type 2 (dynamic Huffman codes) block. */ +{ + int i; /* temporary variables */ + unsigned j; + unsigned l; /* last length */ + unsigned m; /* mask for bit lengths table */ + unsigned n; /* number of lengths to get */ + struct huft *tl; /* literal/length code table */ + struct huft *td; /* distance code table */ + int bl; /* lookup bits for tl */ + int bd; /* lookup bits for td */ + unsigned nb; /* number of bit length codes */ + unsigned nl; /* number of literal/length codes */ + unsigned nd; /* number of distance codes */ +#ifdef PKZIP_BUG_WORKAROUND + unsigned ll[288+32]; /* literal/length and distance code lengths */ +#else + unsigned ll[286+30]; /* literal/length and distance code lengths */ +#endif + register unsigned long b; /* bit buffer */ + register unsigned k; /* number of bits in bit buffer */ + +DEBG(" 288 || nd > 32) +#else + if (nl > 286 || nd > 30) +#endif + return 1; /* bad lengths */ + +DEBG("dyn1 "); + + /* read in bit-length-code lengths */ + for (j = 0; j < nb; j++) + { + NEEDBITS(3) + ll[border[j]] = (unsigned)b & 7; + DUMPBITS(3) + } + for (; j < 19; j++) + ll[border[j]] = 0; + +DEBG("dyn2 "); + + /* build decoding table for trees--single level, 7 bit lookup */ + bl = 7; + if ((i = huft_build(ll, 19, 19, NULL, NULL, &tl, &bl)) != 0) + { + if (i == 1) + huft_free(tl); + return i; /* incomplete code set */ + } + +DEBG("dyn3 "); + + /* read in literal and distance code lengths */ + n = nl + nd; + m = mask_bits[bl]; + i = l = 0; + while ((unsigned)i < n) + { + NEEDBITS((unsigned)bl) + j = (td = tl + ((unsigned)b & m))->b; + DUMPBITS(j) + j = td->v.n; + if (j < 16) /* length of code in bits (0..15) */ + ll[i++] = l = j; /* save last length in l */ + else if (j == 16) /* repeat last length 3 to 6 times */ + { + NEEDBITS(2) + j = 3 + ((unsigned)b & 3); + DUMPBITS(2) + if ((unsigned)i + j > n) + return 1; + while (j--) + ll[i++] = l; + } + else if (j == 17) /* 3 to 10 zero length codes */ + { + NEEDBITS(3) + j = 3 + ((unsigned)b & 7); + DUMPBITS(3) + if ((unsigned)i + j > n) + return 1; + while (j--) + ll[i++] = 0; + l = 0; + } + else /* j == 18: 11 to 138 zero length codes */ + { + NEEDBITS(7) + j = 11 + ((unsigned)b & 0x7f); + DUMPBITS(7) + if ((unsigned)i + j > n) + return 1; + while (j--) + ll[i++] = 0; + l = 0; + } + } + +DEBG("dyn4 "); + + /* free decoding table for trees */ + huft_free(tl); + +DEBG("dyn5 "); + + /* restore the global bit buffer */ + bb = b; + bk = k; + +DEBG("dyn5a "); + + /* build the decoding tables for literal/length and distance codes */ + bl = lbits; + if ((i = huft_build(ll, nl, 257, cplens, cplext, &tl, &bl)) != 0) + { +DEBG("dyn5b "); + if (i == 1) { + unzip_error("incomplete literal tree"); + huft_free(tl); + } + return i; /* incomplete code set */ + } +DEBG("dyn5c "); + bd = dbits; + if ((i = huft_build(ll + nl, nd, 0, cpdist, cpdext, &td, &bd)) != 0) + { +DEBG("dyn5d "); + if (i == 1) { + unzip_error("incomplete distance tree"); +#ifdef PKZIP_BUG_WORKAROUND + i = 0; + } +#else + huft_free(td); + } + huft_free(tl); + return i; /* incomplete code set */ +#endif + } + +DEBG("dyn6 "); + + /* decompress until an end-of-block code */ + if (inflate_codes(tl, td, bl, bd)) + return 1; + +DEBG("dyn7 "); + + /* free the decoding tables, return */ + huft_free(tl); + huft_free(td); + +DEBG(">"); + return 0; +} + + + +int inflate_block(e) +int *e; /* last block flag */ +/* decompress an inflated block */ +{ + unsigned t; /* block type */ + register unsigned long b; /* bit buffer */ + register unsigned k; /* number of bits in bit buffer */ + + DEBG(""); + + /* bad block type */ + return 2; +} + + + +int inflate() +/* decompress an inflated entry */ +{ + int e; /* last block flag */ + int r; /* result code */ + unsigned h; /* maximum struct huft's malloc'ed */ + + + /* initialize window, bit buffer */ + wp = 0; + bk = 0; + bb = 0; + + + /* decompress until the last block */ + h = 0; + do { + hufts = 0; + if ((r = inflate_block(&e)) != 0) + return r; + if (hufts > h) + h = hufts; + } while (!e); + + /* Undo too much lookahead. The next read will be byte aligned so we + * can discard unused bits in the last meaningful byte. + */ + while (bk >= 8) { + bk -= 8; + inptr--; + } + + /* flush out slide */ + flush_output(wp); + + /* return success */ + return 0; +} --- quik-2.1.orig/second/misc.c +++ quik-2.1/second/misc.c @@ -0,0 +1,253 @@ +/* + * misc.c + * + * This is a collection of several routines from gzip-1.0.3 + * adapted for Linux. + * + * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994 + * puts by Nick Holloway 1993 + * + * Adapted to Linux/Alpha boot by David Mosberger (davidm@cs.arizona.edu). + */ +#include + +#include + +#include +#include "setjmp.h" +#include "gzip.h" +#include "quik.h" + + + +unsigned char *out; +unsigned char *inbuf; +unsigned char *window; +unsigned outcnt; +unsigned insize; +unsigned inptr; +unsigned long bytes_out; +unsigned int input_len; +int method; + +static int block_number = 0; +static unsigned long crc_32_tab[256]; +static int input_fd = -1; +static int chunk; /* current segment */ +size_t file_offset; + +void +makecrc(void) +{ + /* Not copyrighted 1990 Mark Adler */ + unsigned long c; /* crc shift register */ + unsigned long e; /* polynomial exclusive-or pattern */ + int i; /* counter for all possible eight bit values */ + int k; /* byte being shifted into crc apparatus */ + + /* terms of polynomial defining this crc (except x^32): */ + static int p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; + + /* Make exclusive-or pattern from polynomial */ + e = 0; + for (i = 0; i < (int) (sizeof(p)/sizeof(int)); i++) + e |= 1L << (31 - p[i]); + + crc_32_tab[0] = 0; + + for (i = 1; i < 256; i++) { + c = 0; + for (k = i | 256; k != 1; k >>= 1) { + c = c & 1 ? (c >> 1) ^ e : c >> 1; + if (k & 1) + c ^= e; + } + crc_32_tab[i] = c; + } +} + + +/* + * Run a set of bytes through the crc shift register. If s is a NULL + * pointer, then initialize the crc shift register contents instead. + * Return the current crc in either case. + * + * Input: + * S pointer to bytes to pump through. + * N number of bytes in S[]. + */ +unsigned long +updcrc(unsigned char *s, unsigned n) +{ + register unsigned long c; + static unsigned long crc = 0xffffffffUL; /* shift register contents */ + + if (!s) { + c = 0xffffffffL; + } else { + c = crc; + while (n--) { + c = crc_32_tab[((int)c ^ (*s++)) & 0xff] ^ (c >> 8); + } + } + crc = c; + return c ^ 0xffffffffL; /* (instead of ~c for 64-bit machines) */ +} + + +/* + * Clear input and output buffers + */ +void +clear_bufs(void) +{ + outcnt = 0; + insize = inptr = 0; + block_number = 0; + bytes_out = 0; + chunk = 0; + file_offset = 0; +} + + +/* + * Check the magic number of the input file and update ofname if an + * original name was given and to_stdout is not set. + * Return the compression method, -1 for error, -2 for warning. + * Set inptr to the offset of the next byte to be processed. + * This function may be called repeatedly for an input file consisting + * of several contiguous gzip'ed members. + * IN assertions: there is at least one remaining compressed member. + * If the member is a zip file, it must be the only one. + */ +static int +get_method(void) +{ + unsigned char flags; + char magic[2]; /* magic header */ + + magic[0] = get_byte(); + magic[1] = get_byte(); + + method = -1; /* unknown yet */ + if (memcmp(magic, GZIP_MAGIC, 2) == 0 + || memcmp(magic, OLD_GZIP_MAGIC, 2) == 0) { + + method = get_byte(); + flags = get_byte(); + if ((flags & ENCRYPTED) != 0) { + unzip_error("input is encrypted"); + return -1; + } + if ((flags & CONTINUATION) != 0) { + unzip_error("multi part input"); + return -1; + } + if ((flags & RESERVED) != 0) { + unzip_error("input has invalid flags"); + return -1; + } + get_byte(); /* skip over timestamp */ + get_byte(); + get_byte(); + get_byte(); + + get_byte(); /* skip extra flags */ + get_byte(); /* skip OS type */ + + if ((flags & EXTRA_FIELD) != 0) { + unsigned len = get_byte(); + len |= get_byte() << 8; + while (len--) get_byte(); + } + + /* Get original file name if it was truncated */ + if ((flags & ORIG_NAME) != 0) { + /* skip name */ + while (get_byte() != 0) /* null */ ; + } + + /* Discard file comment if any */ + if ((flags & COMMENT) != 0) { + while (get_byte() != 0) /* null */ ; + } + } else { + unzip_error("unknown compression method"); + return -1; + } + return method; +} + +/* + * Fill the input buffer and return the first byte in it. This is called + * only when the buffer is empty and at least one byte is really needed. + */ +int +fill_inbuf(void) +{ + if (insize != 0) { + qprintf("ran out of input data"); + while(1); + } + + inbuf = (unsigned char *)IMAGE_BUF; + insize = input_len; + inptr = 1; + return inbuf[0]; +} + + +/* + * Write the output window window[0..outcnt-1] holding uncompressed + * data and update crc. + */ +void +flush_window(void) +{ + if (!outcnt) { + return; + } + + updcrc(window, outcnt); + + memcpy(out,window,outcnt); + + out+=outcnt; + bytes_out+=outcnt; + +} + + +/* + * We have to be careful with the memory-layout during uncompression. + * The stack we're currently executing on lies somewhere between the + * end of this program (given by _end) and lastfree. However, as I + * understand it, there is no guarantee that the stack occupies the + * lowest page-frame following the page-frames occupied by this code. + * + * Thus, we are stuck allocating memory towards decreasing addresses, + * starting with lastfree. Unfortunately, to know the size of the + * kernel-code, we need to uncompress the image and we have a circular + * dependency. To make the long story short: we put a limit on + * the maximum kernel size at MAX_KERNEL_SIZE and allocate dynamic + * memory starting at (lastfree << ALPHA_PG_SHIFT) - MAX_KERNEL_SIZE. + */ +int +uncompress_kernel(int fd) +{ + input_fd = fd; + + inbuf = malloc(INBUFSIZ); + window = malloc(WSIZE); + + clear_bufs(); + makecrc(); + + method = get_method(); + if(method < 0) + return 0; + + unzip(0, 0); + + return 1; +} --- quik-2.1.orig/second/unzip.c +++ quik-2.1/second/unzip.c @@ -0,0 +1,145 @@ +/* unzip.c -- decompress files in gzip or pkzip format. + * Copyright (C) 1992-1993 Jean-loup Gailly + * + * Adapted for Linux booting by Hannu Savolainen 1993 + * + * This is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License, see the file COPYING. + * + * The code in this file is derived from the file funzip.c written + * and put in the public domain by Mark Adler. + */ + +/* + * This version can extract files in gzip or pkzip format. For the + * latter, only the first entry is extracted, and it has to be either + * deflated or stored. + */ + +#include "gzip.h" +#include "quik.h" + +/* PKZIP header definitions */ +#define LOCSIG 0x04034b50L /* four-byte lead-in (lsb first) */ +#define LOCFLG 6 /* offset of bit flag */ +#define CRPFLG 1 /* bit for encrypted entry */ +#define EXTFLG 8 /* bit for extended local header */ +#define LOCHOW 8 /* offset of compression method */ +#define LOCTIM 10 /* file mod time (for decryption) */ +#define LOCCRC 14 /* offset of crc */ +#define LOCSIZ 18 /* offset of compressed size */ +#define LOCLEN 22 /* offset of uncompressed length */ +#define LOCFIL 26 /* offset of file name field length */ +#define LOCEXT 28 /* offset of extra field length */ +#define LOCHDR 30 /* size of local header, including sig */ +#define EXTHDR 16 /* size of extended local header, inc sig */ + + +/* Globals */ + +int pkzip = 0; /* set for a pkzip file */ +int extended = 0; /* set if extended local header */ + + +void unzip_error(char *x) +{ + qprintf(x); +} +/* + * Unzip in to out. This routine works on both gzip and pkzip files. + * + * IN assertions: the buffer inbuf contains already the beginning of + * the compressed data, from offsets inptr to insize-1 included. + * The magic header has already been checked. The output buffer is cleared. + */ +void unzip(in, out) + int in, out; /* input and output file descriptors */ +{ + unsigned long orig_crc = 0; /* original crc */ + unsigned long orig_len = 0; /* original uncompressed length */ + int n; + unsigned char buf[EXTHDR]; /* extended local header */ + + /* ifd = in; + ofd = out; */ + + updcrc(NULL, 0); /* initialize crc */ + + if (pkzip && !extended) { /* crc and length at the end otherwise */ + orig_crc = LG(inbuf + LOCCRC); + orig_len = LG(inbuf + LOCLEN); + } + + /* Decompress */ + if (method == DEFLATED) { + + int res = inflate(); + + if (res == 3) { + unzip_error("out of memory"); + } else if (res != 0) { + unzip_error("invalid compressed format"); + } + + } else if (pkzip && method == STORED) { + register unsigned long n = LG(inbuf + LOCLEN); + + if (n != LG(inbuf + LOCSIZ)) { + unzip_error("length mismatch"); + } + while (n--) { + unsigned char c = get_byte(); + put_char(c); + } + } else { + unzip_error("internal error, invalid method"); + } + + /* Get the crc and original length */ +#ifdef DEBUG + printf("getting CRC and length\n"); +#endif + if (!pkzip) { + /* crc32 (see algorithm.doc) + * uncompressed input size modulo 2^32 + */ + for (n = 0; n < 8; n++) { + buf[n] = get_byte(); /* may cause an error if EOF */ +#ifdef DEBUG + printf("nonext: doing CRC, get_byte (ptr %d) returned %d\n", + inptr, buf[n]); +#endif + } + orig_crc = LG(buf); + orig_len = LG(buf+4); + + } else if (extended) { /* If extended header, check it */ + /* signature - 4bytes: 0x50 0x4b 0x07 0x08 + * CRC-32 value + * compressed size 4-bytes + * uncompressed size 4-bytes + */ + for (n = 0; n < EXTHDR; n++) { + buf[n] = get_byte(); /* may cause an error if EOF */ +#ifdef DEBUG + printf("ext: doing CRC, get_byte returned %d\n", buf[n]); +#endif + } + orig_crc = LG(buf+4); + orig_len = LG(buf+12); + } + + /* Validate decompression */ + if (orig_crc != updcrc(buf, 0)) { + unzip_error("crc error"); + } + if (orig_len != bytes_out) { + unzip_error("length error"); + } + + /* Check if there are more entries in a pkzip file */ + if (pkzip && inptr + 4 < insize && LG(inbuf+inptr) == LOCSIG) { + unzip_error("zip file has more than one entry"); + } + extended = pkzip = 0; /* for next file */ +} --- quik-2.1.orig/second/setjmp.h +++ quik-2.1/second/setjmp.h @@ -0,0 +1,110 @@ +/* glibc 2.1.3 defines setjmp(env) as __sigsetjmp((env),0) + * glibc 2.2's setjmp.h changes to #define setjmp _setjmp(env) + * + * quik uses glibc headers but not glibc, and _setjmp is a glibc internal + * function. IOW, quik doesn't like glibc updates. + * + * The following is setjmp.h copied from glibc 2.1.3: + */ + +/* Copyright (C) 1991,92,93,94,95,96,97,98 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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* + * ISO C Standard: 4.6 NON-LOCAL JUMPS + */ + +#ifndef _SETJMP_H +#define _SETJMP_H 1 + +#include + +__BEGIN_DECLS + +#include /* Get `__jmp_buf'. */ +#include /* Get `__sigset_t'. */ + +/* Calling environment, plus possibly a saved signal mask. */ +typedef struct __jmp_buf_tag /* C++ doesn't like tagless structs. */ + { + /* NOTE: The machine-dependent definitions of `__sigsetjmp' + assume that a `jmp_buf' begins with a `__jmp_buf'. + Do not move this member or add others before it. */ + __jmp_buf __jmpbuf; /* Calling environment. */ + int __mask_was_saved; /* Saved the signal mask? */ + __sigset_t __saved_mask; /* Saved signal mask. */ + } jmp_buf[1]; + + +/* Store the calling environment in ENV, also saving the + signal mask if SAVEMASK is nonzero. Return 0. + This is the internal name for `sigsetjmp'. */ +extern int __sigsetjmp __P ((jmp_buf __env, int __savemask)); + +#ifndef __FAVOR_BSD +/* Set ENV to the current position and return 0, not saving the signal mask. + This is just like `sigsetjmp (ENV, 0)'. + The ISO C standard says `setjmp' is a macro. */ +# define setjmp(env) __sigsetjmp ((env), 0) +#else +/* We are in 4.3 BSD-compatibility mode in which `setjmp' + saves the signal mask like `sigsetjmp (ENV, 1)'. */ +# define setjmp(env) __sigsetjmp ((env), 1) +#endif /* Favor BSD. */ + +#if defined __USE_BSD || defined __USE_XOPEN +/* Set ENV to the current position and return 0, not saving the signal mask. + This is the 4.3 BSD name for ISO `setjmp'. */ +# define _setjmp(env) __sigsetjmp ((env), 0) +#endif + + +/* Jump to the environment saved in ENV, making the + `setjmp' call there return VAL, or 1 if VAL is 0. */ +extern void longjmp __P ((jmp_buf __env, int __val)) + __attribute__ ((__noreturn__)); +#if defined __USE_BSD || defined __USE_XOPEN +/* Same. Usually `_longjmp' is used with `_setjmp', which does not save + the signal mask. But it is how ENV was saved that determines whether + `longjmp' restores the mask; `_longjmp' is just an alias. */ +extern void _longjmp __P ((jmp_buf __env, int __val)) + __attribute__ ((__noreturn__)); +#endif + + +#ifdef __USE_POSIX +/* Use the same type for `jmp_buf' and `sigjmp_buf'. + The `__mask_was_saved' flag determines whether + or not `longjmp' will restore the signal mask. */ +typedef jmp_buf sigjmp_buf; + +/* Store the calling environment in ENV, also saving the + signal mask if SAVEMASK is nonzero. Return 0. */ +# define sigsetjmp(env, savemask) __sigsetjmp ((env), (savemask)) + +/* Jump to the environment saved in ENV, making the + sigsetjmp call there return VAL, or 1 if VAL is 0. + Restore the signal mask if that sigsetjmp call saved it. + This is just an alias `longjmp'. */ +extern void siglongjmp __P ((sigjmp_buf __env, int __val)) + __attribute__ ((__noreturn__)); +#endif /* Use POSIX. */ + +__END_DECLS + +#endif /* setjmp.h */ --- quik-2.1.orig/second/stricmp.c +++ quik-2.1/second/stricmp.c @@ -0,0 +1,42 @@ +/* stricmp.c - string processing + + Copyright (C) 2004 Peter 'p2' De Schrijver . + + Because quik is under the GPL, it comes under that licence. + + 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" + +int stricmp(const char *s1, const char *s2) +{ + /* Yes, Virginia, it had better be unsigned */ + unsigned char c1, c2; + + c1 = 0; c2 = 0; + do { + c1 = *s1; c2 = *s2; + s1++; s2++; + if (c1 == c2) + continue; + c1 = tolower(c1); + c2 = tolower(c2); + if (c1 != c2) + break; + } while (c1 && c2); + + return (int)c1 - (int)c2; +} + --- quik-2.1.orig/util/Makefile +++ quik-2.1/util/Makefile @@ -1,4 +1,4 @@ -CFLAGS= -O2 +CFLAGS= -O2 -Wall all: elfextract --- quik-2.1.orig/util/elfextract.c +++ quik-2.1/util/elfextract.c @@ -4,6 +4,8 @@ * Copyright 1996 Paul Mackerras. */ #include +#include +#define __KERNEL__ #include FILE *fi, *fo; @@ -25,14 +27,14 @@ exit(1); } -main(int ac, char **av) +int 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] == '-') { + if ((ac > 3) || (ac > 1 && av[1][0] == '-')) { fprintf(stderr, "Usage: %s [elf-file [image-file]]\n", av[0]); exit(0); } @@ -62,6 +64,8 @@ fseek(fi, eh.e_phoff, 0); phsize = 0; + prevaddr = 0; + phoffset = 0; for (i = 0; i < eh.e_phnum; ++i) { rd(&ph, sizeof(ph)); if (ph.p_type != PT_LOAD) --- quik-2.1.orig/ChangeLog +++ quik-2.1/ChangeLog @@ -0,0 +1,51 @@ +Changelog for quik +================== + +TODO list at the bottom, it also includes fun stuff as well as useful stuff. + + + +Changes for 2.1: +---------------- + +* Add a README to the source; viewarch.cgi access at: + or + . +* Compiles and works with gcc 3 (!). +* Fixed sprintf. +* Added initrd= to man page. +* Added support to quik for booting from the ANS RAID controller. +* Added initrd support. +* Read chosen/bootargs in OF. +* 'pause-after' works. +* *Really* fix increased maximum kernel size that quik can handle. + + +Changes for 2.0e: +----------------- + +* Edited the top Makefile to point to /usr/share/man instead of /usr/man. +* Corrected some typos in conf.empty. +* Include ext2fs/ext2_fs.h instead of linux/ext2_fs.h in two places, + so it builds from source again. +* Add a patch by Mich Lanners to fix a bug concerning the scsi disk device + designation. +* Add a patch by Benjamin Herrenschmidt to increase the maximum size of the + kernel that quik can handle. +* Add a patch by Ethan Benson to handle symbolic links for kernel images. +* Add a patch to make G3-equipped PowerSurges boot. Thanks to Michael Lanners, + who wrote the patch for Quik 1.3.1, and to Lee Cremeans, who ported it to + the current version. +* force use of our own setjmp implementation based on glibc 6.1 implementation. +* properly set kernel args to use a null pointer. +* (I'll add more changes later as time permits). + + +TODO: +----- + +* Floppy support so we can get rid of miboot on a lot of machines. +* Simple framebuffer support for machines which lack an OF-supported + framebuffer (eg. 7200, 5400, 5500, 6400). +* Splash screen support. + --- quik-2.1.orig/README +++ quik-2.1/README @@ -0,0 +1,18 @@ +README +------ + +As the first.b is a binary file, and I'm not sure of the legalese attached to +it, I'm posting an URI here so people can download the first.b for "Beige" G3 +machines. Some of these machines need this thing; however, I won't be held +responsible for any breakages that may happen as a consequence of the usage of +this file. Not all Beige G3s require this, so as usual, YMMV. + +. + + +UPDATE: Um, I must've been braindead when I wrote the above, but as first.b is +created from these sources, the beige G3 first.b is reproducible. However, I +need to find out *how* to reproduce it. When I do, I will add the required +build stuff to make it, and place it in the /usr/share/doc/quik/examples +directory. + --- quik-2.1.orig/debian/README.Debian +++ quik-2.1/debian/README.Debian @@ -0,0 +1,14 @@ +README.Debian +------------- + +ViewARCH or archzoom access is available at: + or at: +. + +This is to see what the current stable (defined as what is present in Debian's +sid archive), and the development tree, which is where new changes will first +appear, with the intent of having stabilised changes from the quik--devel tree +added to the quik--stable tree, to then appear in Debian sid eventually. + +-- Eric Côté Wed, 15 Dec 2004 20:47:18 -0500 + --- quik-2.1.orig/debian/bootinfo.txt +++ quik-2.1/debian/bootinfo.txt @@ -0,0 +1,5 @@ + + Debian GNU/Linux PowerPC Quik Bootloader + Debian GNU/Linux PowerPC + boot &device:\ppc\second + --- quik-2.1.orig/debian/changelog +++ quik-2.1/debian/changelog @@ -0,0 +1,258 @@ +quik (2.1-6) unstable; urgency=low + + * Added support for gzipped kernels. + + -- Peter De Schrijver (p2) Wed, 6 Apr 2005 01:05:43 +0200 + +quik (2.1-5) unstable; urgency=low + + * Added support for md devices. Thanks to Simon Vallet. (Closes: #298606) + + -- Peter De Schrijver (p2) Sun, 20 Mar 2005 22:58:46 -0600 + +quik (2.1-4) unstable; urgency=low + + * Cleanup source tree + * Fixed wrong calls to qvprintf (closes: #294958) + * Update maintainer field. (closes: #275935) + + -- Peter De Schrijver (p2) Mon, 14 Feb 2005 00:08:25 +0100 + +quik (2.1-3) unstable; urgency=low + + * Fixed Maintainers: and Uploaders: fields. + (closes: #288096) + * Made man pages UTF-8 safe. + * Linda and Lintian are happy campers. + + -- Eric Côté Sun, 02 Jan 2005 05:34:58 -0500 + +quik (2.1-2) unstable; urgency=high + + * New version. A lot of added features, and changes. + * Compiles and works with gcc 3.x. + * Fixed sprintf(). + * Added initrd= to man page. + * Added support to quik for booting from the ANS RAID controller. + * Try to get this into sarge, as this will help with issues + there. + * Sponsored by Jaakko Niemi . + + -- Eric Côté Thu, 09 Dec 2004 04:41:34 -0500 + +quik (2.1-1) unstable; urgency=high + + * New version. A lot of added support, new features. + * Added initrd support. + * Added full support for kernels larger than ~5.1 MB + (closes: #259359). + * See NEWS.Debian. + * Many, many thanks and gratitude go to Peter 'p2' + De Schrijver for his tremendous help in making + this possible. + * Try to get this into sarge, as this will help with issues + there. + + -- Eric Côté Fri, 26 Nov 2004 04:16:33 -0500 + +quik (2.0e-11) unstable; urgency=low + + * Sponsored Upload + * Hopefully *really* fix the postinst this time *sigh*, and + really close #275912 (closes: #275912). + + -- Jaakko Niemi Thu, 28 Oct 2004 20:45:07 +0300 + +quik (2.0e-10) unstable; urgency=low + + * Added some check in the postinst to check for Pegasos machines; + these should not run quik, but yaboot instead, as they are + NewWorld machines, not OldWorld (closes: #275912). + * Sponsored by Jaakko Niemi . + * Added Jaakko Niemi to Uploaders. + * Added an URI for where people can get the first.b for "Beige" G3s + machines to NEWS.Debian. + + -- Eric Côté Thu, 21 Oct 2004 11:56:42 -0400 + +quik (2.0e-9) unstable; urgency=low + + * Adopted package. + * Edited the top Makefile to point to /usr/share/man instead of + /usr/man. + * Corrected some typos in conf.empty. + + -- Eric Côté Mon, 18 Oct 2004 12:46:17 -0400 + +quik (2.0e-8) unstable; urgency=low + + * Orphaned the package, changed maintainer accordingly. + + -- Jens Schmalzing Sat, 16 Oct 2004 20:30:08 +0200 + +quik (2.0e-7) unstable; urgency=low + + * Add a patch by David Weinehall to make the postinst and preinst more + POSIX compliant and hence more portable (closes: Bug#254929). + + * Include ext2fs/ext2_fs.h instead of linux/ext2_fs.h in two places, so + the package builds from source again. + + * Updated to current policy version. + + -- Jens Schmalzing Thu, 17 Jun 2004 22:17:03 +0200 + +quik (2.0e-6) unstable; urgency=low + + * Add a patch by Mich Lanners to fix a bug concerning the scsi disk + device designation (closes: Bug#217181). Thanks to Chris Tillman for + forwarding this. + + -- Jens Schmalzing Thu, 23 Oct 2003 07:29:27 +0200 + +quik (2.0e-5) unstable; urgency=low + + * Add a patch by Benjamin Herrenschmidt to increase the maximum size of + the kernel that quik can handle (closes: Bug#215651, Bug#216584). + + -- Jens Schmalzing Tue, 21 Oct 2003 17:14:48 +0200 + +quik (2.0e-4) unstable; urgency=low + + * Add a patch by Ethan Benson to handle symbolic links for kernel images + (closes: Bug#181468). + + * Minor cleanup to appease lintian. + + -- Jens Schmalzing Thu, 20 Feb 2003 09:36:40 +0100 + +quik (2.0e-3) unstable; urgency=low + + * Add a patch to make G3-equipped PowerSurges boot (closes: Bug#173484). + Thanks to Michael Lanners, who wrote the patch for Quik 1.3.1, and to + Lee Cremeans, who ported it to the current version. + + * Add some remarks about the relationship to yaboot to the package + description (closes: Bug#173626). + + * Force the use of gcc-2.95 for building. + + -- Jens Schmalzing Wed, 22 Jan 2003 15:30:49 +0100 + +quik (2.0e-2) unstable; urgency=low + + * Make sure that quik does not run on NewWorld machines (closes: + Bug#153675). Thanks to Colin Walters for pointing this out and + providing a patch. + + -- Jens Schmalzing Sat, 20 Jul 2002 20:34:31 +0200 + +quik (2.0e-1) unstable; urgency=low + + * New maintainer (closes: Bug#104291). + * Made package lintian clean by adding a manpage for the quikconfig + script, dynamically linking the quik binary, and updating the + Standards-Version. + + -- Jens Schmalzing Mon, 15 Apr 2002 15:40:41 +0200 + +quik (2.0e-0.7) unstable; urgency=low + + * QA upload. + * Recompile with e2fsprogs 1.27-2, per request of e2fsprogs maintainer. + + -- Colin Walters Wed, 27 Mar 2002 20:27:12 -0500 + +quik (2.0e-0.6) unstable; urgency=low + + * NMU + * Potato version is newer than current woody version, and has the + bootstrap.8 man page, which conflicts with yaboot's bootstrap.8. So + just bump this version, and don't include that man page + (Closes: #119164). + + -- Colin Walters Mon, 26 Nov 2001 00:01:52 -0500 + +quik (2.0e-0.5) unstable; urgency=medium + + * NMU + * postinst installing /etc/quik.conf, and not as a conffile, so it was + getting blown away on each upgrade. Sorry. + * please, some maintainer who actually uses this successfully, please + take over this package + + -- Adam Di Carlo Mon, 18 Jun 2001 10:18:54 -0400 + +quik (2.0e-0.4) unstable; urgency=low + + * postinst redux: inhibit running of quikconfig if + DEBIAN_FRONTEND=Noninteractive as well, for the same reason as before + closes: #100127 + + -- Adam Di Carlo Tue, 12 Jun 2001 20:43:50 -0400 + +quik (2.0e-0.3) unstable; urgency=high + + * NMU + * debian maintainer no longer able to maintain this package, + orphaning it; maintainer changed to packages@qa.debian.org + + * postinst: inhibit running of quikconfig if + DEBIAN_FRONTEND=noninteractive -- this caused bad failures during base + bootstrapping + closes: #100127 + + * /etc/quik.conf is machine generated, so should not be a conffile + (policy violation) + * don't install useless /boot/ppc dir and contents + * postinst: remove the early exit, which prevented the debhelper stuff + from running + + -- Adam Di Carlo Tue, 12 Jun 2001 00:38:20 -0400 + +quik (2.0e-0.2) unstable; urgency=medium + + * NMU (RC bugs older than 1 month) + * force use of our own setjmp implementation based on glibc 6.1 + implementation + closes: #93871 + * properly set kernel args to use a null pointer + closes: #93870 + * add Build-Depends for debhelper and e2fslibs-dev + * add debhelper tokens to postinst and preinst scripts + * debian/rules: remove dh_testversion + * debian/rules: don't install bootstrap(8) man page, which is also in yaboot + + -- Adam Di Carlo Mon, 21 May 2001 06:48:12 -0400 + +quik (2.0e-0.1) frozen unstable; urgency=medium + + * NMU with maintainer approval. + * Patches to make Quik functional on powermac again. + * The upstream source no longer includes a bootinfo.txt (chrpboot + script) but I have left it in place for the moment. + + -- Daniel Jacobowitz Tue, 28 Mar 2000 15:05:13 -0500 + +quik (2.0-2) unstable; urgency=low + + * added a patch from Benjamin Herrenschmidt + + -- Hartmut Koptein Wed, 22 Sep 1999 18:33:41 +0200 + + +quik (2.0-1) unstable; urgency=low + + * New upstream version. + * New Standards Version: 3.0.1.1 + + -- Hartmut Koptein Sun, 19 Sep 1999 22:59:45 +0200 + + +quik (1.3.1-1) unstable; urgency=low + + * Initial Release. + + -- Hartmut Koptein Fri, 20 Feb 1998 18:08:30 -0800 + + --- quik-2.1.orig/debian/conf.empty +++ quik-2.1/debian/conf.empty @@ -0,0 +1,13 @@ +# +# This is an empty quik.conf file distributed with the Debian GNU/Linux +# package of quik. You should normally not see this file, since it is +# replaced by a new copy at installation time of the package. +# +# You can run /usr/sbin/quikconfig to generate a new config file, which will +# probably suit your needs. +# +# Wed, 9 Dec 1998 02:26:20 +0100 Bernd Eckenfels +# +# Note: /usr/sbin/quikconfig will consider all files which contain only +# comments as non-existent and generate new ones +# --- quik-2.1.orig/debian/control +++ quik-2.1/debian/control @@ -0,0 +1,22 @@ +Source: quik +Section: base +Priority: important +Maintainer: Peter De Schrijver (p2) +Uploaders: Jaakko Niemi , Eric Côté +Standards-Version: 3.6.1.0 +Build-Depends: debhelper (>> 2.0.0), e2fslibs-dev, gcc (>= 1:2.95.4) + +Package: quik +Architecture: powerpc +Depends: ${shlibs:Depends} +Description: Bootloader for PowerMac or CHRP systems + The quik package provides the functionality necessary for booting a + Linux Debian/PowerPC 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. + . + Note that if you are running on a NewWorld machine, quik will be of + limited use to you. You should install yaboot instead. It may even + come handy on an OldWorld machine, since it provides the ofpath + program and some documentation. + --- quik-2.1.orig/debian/copyright +++ quik-2.1/debian/copyright @@ -0,0 +1,23 @@ +Sources were downloaded from ftp://ftp.ppc.kernel.org/pub/linuxppc/quik. + +This package was debianized by Hartmut Koptein on +Mon, 22 Feb 1999 02:52:15 +0100. + +Copyright: + +This is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 2, or (at your option) any later +version. + +This 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 with +your Debian GNU/Linux system, in /usr/share/common-licenses/GPL, or with +the dpkg source package as the file COPYING. If not, write to the Free +Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +02111-1307, USA. + --- quik-2.1.orig/debian/postinst +++ quik-2.1/debian/postinst @@ -0,0 +1,69 @@ +#!/bin/sh + +set -e + +#if [ ! -z "`grep CHRP /proc/cpuinfo`" ] ; then +# echo CHRP system detected. +## PART=`fdisk -l | grep -F "PPC PReP Boot"` +# PART=`cfdisk -P s | grep -F "PPC PReP boot"` +# 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 '*********************************************************' +# exit -1 +# 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 '**************************************************************' +# exit -1 +# 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 '**************************************************************' +# exit -1 +# fi +# P=`echo "$PART" | awk '{print $1}'` +# # assume /dev/sda!!! +# P=/dev/sda${P} +# echo Installing onto $P +# dd if=/boot/ppc/second of=$P +## mkdosfs $P +## mkdir /quikchrp +## mount -t msdos $P /quikchrp +## cp -rf /boot/ppc /quikchrp +## umount /quikchrp +## rm -f /quikchrp +#fi + +if [ "$1" = "configure" ]; then + if test -f /proc/cpuinfo; then + if ! grep -q 'pmac-generation.*OldWorld' /proc/cpuinfo; then + echo "Quik should only be installed on OldWorld PowerMac machines." + exit 0; + fi + else + echo "Warning: couldn't stat /proc/cpuinfo." + echo "Please run /usr/sbin/quikconfig when /proc " + echo "becomes available as soon as possible." + exit 0 + fi +fi + +if + [ "$1" = "configure" ] && [ "$DEBIAN_FRONTEND" != noninteractive ] \ + && [ "$DEBIAN_FRONTEND" != Noninteractive ]; then + echo "running /usr/sbin/quikconfig" + echo + /usr/sbin/quikconfig || \ + echo "WARNING: your system might not boot, check /etc/quik.conf and rerun '/sbin/quik -v'" +fi + +#DEBHELPER# + +exit 0 --- quik-2.1.orig/debian/preinst +++ quik-2.1/debian/preinst @@ -0,0 +1,33 @@ +#!/bin/sh + +( [ x"install" = x"$1" ] || [ x"upgrade" = x"$1" ] ) || exit 0 + +set -e + +preserve() { + if [ -f "$1" ]; then + if [ "$1" -ef "$1".preserved ]; then + echo "already preserved: $1" + else + echo "preserving $1" + ln -f "$1" "$1".preserved || echo "Warning: Cant link $1 to $1.preserved in /boot/" + fi + fi +} + +echo "Since your boot sector or MBR might still need some files from /boot" +echo "this script will preserve them as /boot/filename.preserved" +echo "IMPORTANT: In the dpkg prompt answer 'N' to overwriting quik.conf" + +cd /boot + +set +e # Turn it off! + +preserve first.b +preserve second.b + +set -e + +#DEBHELPER# + +exit 0 --- quik-2.1.orig/debian/quikconfig +++ quik-2.1/debian/quikconfig @@ -0,0 +1,99 @@ +#!/usr/bin/perl +# +# /usr/sbin/quikconfig configure quik automatically +# this program is a modified version of siloconfig +# (C) 1998 Davide Barbieri +# +# based on liloconfig, which is copyrighted by +# Author: Bruce Perens +# Maintainer: Bernd Eckenfels +# +# quikconfig (C) 1998 Matt McLean +# this software is GPLed + +$|=1; + +if ( ! (-f "/etc/fstab") ) { + exit(0); +} + +print "QUIK, the Linux Loader for PowerMac and CHRP, sets up your system\n"; +print "to boot directly from your hard disk, without the need for a boot\n"; +print "floppy or a net boot.\n"; + +@boilerplate = ( + "# Generated by quikconfig\n", + "# (C) 1998 Matt McLean \n", + "# partition=3\n", + "# map=/boot/map\n", + "timeout=20\n", + "image=/boot/vmlinux\n", + "label=Linux\n", + "read-only\n" +); + +sub asky { + print @_,"? [Yes] "; + $answer=; + return ( !($answer =~ /^[nN].*/) ); +} + +sub askn { + print @_,"? [No] "; + $answer=; + return ( $answer =~ /^[yY].*/ ); +} + +if (-T "/etc/quik.conf") { + # Trust and use the existing quik.conf. + print "\n"; + print "You already have a QUIK configuration in the file /etc/quik.conf\n"; + if ( &asky("Install a boot block using your current QUIK configuration") ) { + print "Running quik\n"; + system("/sbin/quik"); + exit(0); + } + else { + print "\n"; + if ( &askn("Wipe out your old QUIK configuration and make a new one") ) { + print "Saving configuration in /etc/quik.conf.OLD\n"; + rename("/etc/quik.conf", "/etc/quik.conf.OLD"); + } + else { + print "No changes made.\n"; + exit(0); + } + } +} + +# Create a quik.conf if one doesn't exist. +open(FSTAB, " ) { + if ( $line =~ m/^\#/ ) { + next; + } + ($device,$filesystem)=split(/[ \t]+/, $line); + if ( $filesystem =~ m:^/$: ) { + last; + } +} +if ( ! $filesystem =~ m:^/$: ) { + exit(0); +} + +$disk = $device; +$disk =~ s/[0-9]+$//; +$partition = $device; +$partition =~ s/$disk//; + +if ( &asky("Install a partition boot record to boot Linux from ", $device)) { + print "Creating small quik.conf and running quik.\n"; + umask(022); + open(CONF, ">/etc/quik.conf"); + chown(0, 0, "/etc/quik.conf"); + print CONF "root=".$device, "\n", @boilerplate; + close(CONF); + system("/sbin/quik"); +} + +exit(0); --- quik-2.1.orig/debian/rules +++ quik-2.1/debian/rules @@ -0,0 +1,54 @@ +#!/usr/bin/make -f +# -*- makefile -*- +# debian/rules file for the Debian/GNU Linux quik package +# Copyright 1998, 1999 by Hartmut Koptein + +export DH_COMPAT=2 +export DH_VERBOSE=1 + +package = quik + +build: build-stamp +build-stamp: + dh_testdir + $(MAKE) + chmod +x debian/quikconfig + touch build-stamp + +clean: + dh_testdir + dh_testroot + -rm -f build-stamp + -$(MAKE) clean + dh_clean + +binary-indep: build + +binary-arch: build + dh_testdir + dh_testroot + dh_clean -k + dh_installdirs boot etc sbin usr/share/man usr/sbin usr/share/doc + install -m 755 -g root -o root quik/quik debian/$(package)/sbin/$(package) + install -m 644 -g root -o root first/first.b second/second.b debian/$(package)/boot +# install -m 644 -g root -o root debian/bootinfo.txt debian/$(package)/boot/ppc +# install -m 755 -g root -o root second/second debian/$(package)/boot/ppc + install -m 755 -g root -o root debian/quikconfig debian/$(package)/usr/sbin + dh_installdocs + dh_installman man/quik.conf.5 man/quik.8 man/quikconfig.8 + dh_installexamples etc/quik.conf + dh_installchangelogs ChangeLog + dh_strip -v + dh_compress + dh_fixperms +# chmod +x debian/$(package)/boot/ppc/second + dh_shlibdeps + dh_installdeb + dh_gencontrol + dh_md5sums + dh_builddeb + + +binary: binary-indep binary-arch + +.PHONY: binary binary-arch binary-indep clean --- quik-2.1.orig/README.md +++ quik-2.1/README.md @@ -0,0 +1,33 @@ + +----------------------------- +README -- MD support for quik +----------------------------- + +This version of quik includes linux-style /dev/md support, with the +following limitations : + +* It supports n-way mirrors (RAID1 arrays) only, and it is unlikely +that support for other RAID levels will be added, unless we can +find a reliable way to get the conffile partition number on +a striped filesystem. + +* Further, the bootable metadevice (typically /) *must* be assembled +from partitions having the same partition number (e.g. /dev/hda2 and +/dev/hdc2, *not* /dev/hda2 and /dev/hdc3). This is necessary because +we write the bootblock to the metadevice, not the underlying +partitions. Again, it is unlikely that this will change. + +* The conffile *must* reside on the bootable partition/metadevice. +This means that a separate /boot partition will *not* work, unless +the configuration file is in /boot. + +* This version does not recognize spare devices, and will try +to write a boot block on them -- if you have any spare drives in +your array, remove them before running quik. You can always re-add +them later +This will be fixed in a future version. + +* LVM volumes are not supported, but will be if at all possible. + + +Simon Vallet -- 2005/03