ncoverby@ndsuvax.UUCP (Glen Overby) (05/11/89)
#! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create the files: # README # MANIFEST # b1/bootblok.asm3 # b1/bootblok.uu # b2b/Makefile # b2b/bsu.s # b2b/hdparam.h # b2b/main.c # b2b/partition.h # b2b/stack.c # b2b/standalone.c # b2b/type.h # kernel/main.c.diff # fs/cache.c.diff # This archive created: Tue May 9 12:01:09 1989 export PATH; PATH=/bin:$PATH echo shar: extracting "'README'" '(10220 characters)' if test -f 'README' then echo shar: will not over-write existing file "'README'" else sed 's/^X//' << \SHAR_EOF > 'README' X A New Bootstrapper for Minix X X Glen Overby X North Dakota State University X Fargo, North Dakota X X X X April 30, 1989 X X X XThe objective of this project is to improve the verasility of the XMinix boot-up process by reading the major pieces of the system Xfrom files on a filesystem, rather than from an image diskette. X XTo achieve this, I have developed a two-stage process to load the Xsystem. The first stage resides in the boot block of a Minix Xfilesystem and is loaded by the PC's ROM. When stage 1 takes Xover, it reads the root directory of /dev/fd0 looking for a Xstripped file (no "a.out" header) named "boot" to load. After Xcontrol is passed to stage 2, it loads four "a.out" files con- Xtaining the Kernel, Memory Manager, File System and Init, build- Xing a normal process stacks with process arguments for each. X XThe first stage is written entirely in assembler by an associate Xof mine, Dan Thureen. Dan used the MicroSoft Macro Assembler X(version 4.0 works OK; I've had trouble with 5.0 complaining Xabout not having a stack segment and such). Microsoft's assem- Xbler was used because we did not know all of the syntax of XMinix's asld, and there were a few required addressing modes X(such as jump indirect) that we did not know how to code. X XStage 2 is written primarily in C, with some assembler support Xroutines. It loads "a.out" format files from Minix format Xfilesystems on any disk or partition; it knows about partitioned Xhard disks as well as floppy diskettes. After all processes are Xloaded, stacks are built for each of the processes. The kernel's Xstack contains "struct proc" entries for kernel memory, MM, FS Xand Init. These are used by the proc table initialization rou- Xtines as a replacement for the sizes[] array. X XFile loader.c contains the code that does all of the filesystem Xreading. Routines with double sides are the only ones intended Xfor use outside this module. X X X ================= X || Open_File || X ================= X _______/ | \_______ X / | \ X --------------- | -------------- X | Follow_Path | | | Device_Map | X --------------- | -------------- X _______/ / \ | X / / \ | X------------- / -------------- | X| Next_Name | / | Search_Dir | | X------------- / -------------- | X / / | X / / | X / =============== | =============== X | || Read_File || | || Load_File || X | =============== \ =============== X | | \_________ \ / | X | | | \ / | X-------------- ----------------- | ____ \ _____/ ----------------- X| Read_Inode | | L_Load_Blocks | | | \ | F_Load_Blocks | X-------------- ----------------- | | \ ----------------- X \ \ | | _______ \ _________/ | X \ \ | | | \ | X \ \ | | | -------------- ------------- X \ \ | | | | Read_Super | | Phys_Copy | X \ \ | | | -------------- ------------- X \_____________ \ | | | _____/ \ X \ \ | | | / \ X -------------- ------------- X | Block_Read | | Read_Part | X -------------- ------------- X | ________________/ X | / X ----------------- X | LL_Block_Read | X ----------------- X | X ---------- X | diskio | X ---------- X X XThe filenames used by the loader have been extended to allow Xspecification of what device to load the file from, in the for- Xmat: X device[.partition]:path X XThe devices that loader knows about are: X fd0, fd1, fd2, fd3 floppy diskettes X hd0.1, hd0.2, hd0.3, hd0.4 hard disk 0 parititons 1-4 X hd1.1, hd1.2, hd1.3, hd1.4 hard disk 1 parititons 1-4 X X XCHANGES TO MINIX X XI attempted to keep the number of changes to the Minix internals Xto a minimum. I think I have succeeded fairly well with this. X XThe Kernel start-up in mpx88 was changed to expect arguments on Xthe stack for main. This is passed along in the same manner as Xfor a normal process. The kernel's "proc" table initialization Xsection copies from the arguments rather than calculating it from Xthe "sizes" array, which no longer exists. The first element X(argv[0]) contains information about the kernel; the next three Xelements (argv[1,2,3]) are for MM, FS and Init, respectively. XWith the removal of the sizes array, changes to the interrupt Xvector initialization and memory driver initialization (for X/dev/kmem) were requred. Set_Vec was changed to use the physical Xdata segment of the "Hardware" process rather than calculating it Xfrom "base_click+sizes[0]". The memory driver was similarily Xmodified, but using the virtual address of the stack segment for Xthe size of the kmem driver. X XThe Memory Manager no longer waits for the file system to tell it Xthe top of the ram disk; instead, it uses a call added to the XSYSTEM process, GET_MAP, to get a process' segment maps. The X"BRK2" call has now been changed to allocate any size out of the Xglobal memory pool, rather than within a process' 64K data seg- Xment. This call is used by the file system to allocate the ram Xdisk's memory. X XThe File System uses it's parameters to determine which device to Xmount as the root filesystem, and if it is necessary to pre-load Xthat device from another device (i.e. if it's a ram disk). This Xchange wasn't necessary to to the bootstrap process, but it was Xat the top of my list of change I wanted to make and I did it Xwhile giving the bootstrapper some time to "break in". X XFUTURE ENHACNEMENTS X XThe block-read makes two ROM calls to read each sector of the Xblock. This should be changed to one call, with logic for the Xerrors returned when a track or cylinder is crossed. X XMemory size should be acquired from the ROM and passed on the XMemory Manager's stack rather than using the current memory size Xcalculation which twiddles with the segment registers and pokes Xthru all existing memory to find out how much there is there. X XAll RAM disk types should be separate minor devices in the Memory Xdriver. This would theoretically allow three RAM disks: PC X(under 640K), AT (Extended memory) and EMS. Currently, it is ei- Xther PC or AT type RAM disk, determined by the size of the RAM Xdisk. X XConfiguration of some device driver parameters (such as keyboard Xtype, primary printer port, video adapter type, and CPU type) Xcould be done in the second stage and passed in on the Kernel's Xstack. X XMore server processes could be configured into the system. This Xwould require the constant "LOW_USER" to become a variable passed Xto the kernel. X XA Hard-Disk stage 1 bootstrapper needs to be written so Minix can Xboot fully off the hard drive. One that might work, called X"BOOTCODE.ASM" by W.D. Caglewas posted in Oct. 87. X XINSTALLING THE CHANGES X XMy changes add two directories to the Minix hierarchy, "b1" and X"b2b". The directory "b2b" was origionally named "b2", but what XI'm sending out is the third major revision and I put each in Xseparate directories. Directory "b1" contains the first stage of Xthe bootsrapper in source and binary. If you wish to reassemble Xthe sources, write bootblok.asm to a dos disk and reassemble it Xfrom dos. Follow the instructions at the beginning of the code Xfor writing it directly to a Minix filesystem disk's boot block; Xotherwise, run uudecode on the ".uu" file in the "b1" directory, Xand use X dd if=bootblok of=/dev/fd0 Xto write it to the boot block of a Minix filesystem. X XCompiling the second stage, in "b2b" simply requires a "make" in Xthat directory. Before compiling you may want to change the dev- Xice and file names of the system files in main.c. It would real- Xly be nice to have a configuration file to tell what files to Xload for each piece of the system, but I haven't written that Xyet. X XNext, patch all the diffs into your Kernel, FS, MM, header and Xlibrary files, and copy in the new mpx88.s file. All diffs are Xcontext diffs and require "patch" to install them. If you are Xpatching into a full set of Minix sources, you will not be able Xto use the makefiles. The way I do most of my development is Xwith a parallel copy of the sources, only copying necessary Xfiles. My work source directory is /usr/src/minix, and the Xparallel directory is /usr/src/minix/newboot. If you do not use Xthe makefiles, you will need to merge some changes I have made to Xthem into the generic Minix ones; first, I use "crtso.s" rather Xthan "head.s" for FS, MM and Init. This allows me to link with X"cc" rather than "asld". I have added the changed library file X"syslib.s" to the end of my link commands so that I don't have to Xrebuild my entire library with the changed file. This was simply Xeasier for testing. Lastly, I "chmem" all executables down to X2000 bytes of stack space. X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X SHAR_EOF if test 10220 -ne "`wc -c < 'README'`" then echo shar: error transmitting "'README'" '(should have been 10220 characters)' fi fi # end of overwriting check echo shar: extracting "'MANIFEST'" '(1004 characters)' if test -f 'MANIFEST' then echo shar: will not over-write existing file "'MANIFEST'" else sed 's/^X//' << \SHAR_EOF > 'MANIFEST' XFile Name Kit Number X-------------- ---------- XMANIFEST 1 XMANIFEST 3 XREADME 1 Xb1/bootblok.asm3 1 Xb1/bootblok.uu 1 Xb2b/Makefile 1 Xb2b/bsu.s 1 Xb2b/hdparam.h 1 Xb2b/loader.c 2 Xb2b/main.c 1 Xb2b/partition.h 1 Xb2b/stack.c 1 Xb2b/standalone.c 1 Xb2b/type.h 1 Xfs/cache.c.diff 1 Xfs/glo.h.diff 2 Xfs/inode.c.diff 2 Xfs/main.c.diff 3 Xfs/makefile 2 Xfs/misc.c.diff 3 Xfs/super.c.diff 3 Xfs/utility.c.diff 3 Xh/com.diff 3 Xkernel/main.c.diff 1 Xkernel/makefile 2 Xkernel/memory.c.diff 2 Xkernel/mpx88.s 2 Xkernel/system.c.diff 2 Xlib/syslib.diff 3 Xmm/main.diff 3 SHAR_EOF if test 1004 -ne "`wc -c < 'MANIFEST'`" then echo shar: error transmitting "'MANIFEST'" '(should have been 1004 characters)' fi fi # end of overwriting check echo shar: extracting "'b1/bootblok.asm3'" '(16625 characters)' if test -f 'b1/bootblok.asm3' then echo shar: will not over-write existing file "'b1/bootblok.asm3'" else sed 's/^X//' << \SHAR_EOF > 'b1/bootblok.asm3' X;----------------------------------------------------------------------------- X; X; MINIX primary bootstrap loader X; Dan Thureen X; CS548 X; Jan. 10, 1988 X; X; Modified for inteligent second-stage loader X; Glen Overby X; March 1, 1988 X; X; 1) ROM monitor loads bootstrap sector from floppy (512 bytes) X; to address 0000:7C00 and executes starting at 7C00. X; X; 2) Bootstrap program relocates itself to address 3000:7C00 to X; get out of the way of the MINIX kernel area by reloading X; the first block (1024 bytes) of the floppy to this address X; and restarting. X; (REMOVED 3/1/88GlenOverby) X; X; 3) Loader reads superblock, loads root directory (inode #1) X; into memory and searches for file named "boot". X; X; 4) The file "boot" is loaded into memory at address 0060:0000 X; and executed. X; X; (Load Address changed to 7C00:0, and a more intelligent 2nd stage X; is now used, so ignore the "build" stuff. X; 3/1/88 GlenOverby) X; X; The file boot is currently the entire MINIX kernel image as X; constructed by "build", with the initial boot sector stripped X; off. X; dd if=image of=boot bs=512 skip=1 X; X; The normal fsck startup utility is bypassed and can also be X; omitted from the image if desired. X; X; The file "boot" can be replaced by a more intelligent 2nd stage X; boot program which is driven by a configuration table to X; permit more flexibility in loading selected modules, configuring X; system parameters, etc. A subroutine "gets" is provided for X; string input if the user should want to select a different boot X; file during system initialization. The current version does not X; call this but uses the hard coded file "boot". X; X; A small library of character and string I/O routines is provided X; for future expansion. Also some small debugging routines for X; doing memory dumps, etc. X; X; Note: All of the code below will not fit into the 1K block X; allocated by the MINIX file system for the boot block. The X; optional sections are placed at the very end and the executable X; image truncated to the 1K size limit. An expanded ( 1K+ ) X; version can be run on a ZENITH clone by the following steps: X; X; Load it into memory with the DOS DEBUG program X; Move it to 3000:7C00 X; Trap to the ROM monitor <ctrl><alt><del> X; Use the monitor routines to execute, single-step, etc. X; X; Because the .EXE file starting address is not CS:0100 the EXE2BIN X; utility cannot be used to convert to a straight binary image. This X; can, however, be done with DEBUG. X; X; DEBUG BOOTBLOK.EXE - loads at CS:7C00 X; -WCS:7C00 0 0 2 - writes 2 sectors to block 0,1 of drive A. X; MINIX file system disk must be in drive A X; for this step X; X; If a DOS file image is desired use DEBUG again: X; X; DEBUG BOOTBLOK.EXE - loads at CS:7C00, sets BX:CS to file size X; -NBOOTBLOK - select name for image file X; -RBX X; BX xxxx X; :0000 - set image file size to 1024 bytes (400h) X; -RCX X; CX xxxx X; :0400 X; -WCS:7C00 - write 1024 bytes to file from CS:7C00 X; X; This can be transferred to MINIX using dosread and patched in with X; dd. X; X; Additional Changes by: X; Glen Overby <ncoverby@plains.nodak.edu> X; {uunet,umn-cs}!ndsuvax!ncoverby, X; ncoverby@ndsuvax (bitnet) X; X; 03/01/88 GPO Leave 1st stage at 0:7C00 and load second stage to 3200:0 X; change segment stuff, remove boot sector reload X; 04/29/88 GPO Reduce the ammount of chatter X;----------------------------------------------------------------------------- X X X X_text segment para public 'code' X assume cs:_text, ds:_text ; Tiny data model with CS=DS=SS X XDEBUG EQU 0 ; Set non-0 if debug code to be X ; included X XS_IMAP_BLOCKS_OFF equ 4 XS_ZMAP_BLOCKS_OFF equ 6 XNR_DZONE_NUM equ 7 XI_ZONE_OFF equ 14 XI_SIZE_OFF equ 4 XIND_ZONE_OFF equ 28 XBOOT_2_SEG equ 3200h ;gpo 3/1/88 XBOOT_2_OFF equ 0000h ;gpo 3/1/88 X X X;MINIX segment at 60h ; Define starting segment address X;kernel label byte ; for minix kernel. Entry point at X;MINIX ends ; at offset 0000. X X XHIGH_BOOT segment at BOOT_2_SEG ; Define segment for relocated boot X org BOOT_2_OFF ; program at (3200:0000) Xhstart2 label byte ; Relocated program must have same X ; relative location within segment X ; as the original, otherwise there X ; are problems accessing static X ; variables XHIGH_BOOT ends X X X org 7C00h Xstart1: X mov ax, cs ; set up segment registers X mov ds, ax ; tiny memory model CS=DS=SS X mov ss, ax X mov sp, offset estack ; CS=AX=BOOT_2_SEG? X; X; Re-load entire boot block on top of executing code. Looks gross, but X; the second 512 bytes has to be loaded somewhere, somehow. X; Only real problem is possibly the stack; just make sure it's out of X; the 1K block range. X X; cmp ax, BOOT_2_SEG ; check if primary or secondary boot X; je start2 ; if secondary (relocated) skip the X; ; next relocations step X X X call reset ; reset drive X X mov lbn, 0 ; read boot block into relocation X mov bseg_no, 0 ; area, so MINIX kernel will not X mov boff_no, 7C00h ; overlay it when it loads (3000:7C00) X call read_block X jnc cont_1 X X call read_error ; error reading boot block - debug X mov bx, offset boot_err ; only (read_error notin 1st sector) X jmp terminate X Xcont_1: Xif DEBUG X mov ax, offset block_buf ; hex dump of boot block X push ax X call _print_block X pop ax X call getchar ; wait for key pressed Xendif X X; jmp far ptr hstart2 ; restart at relocated boot program X Xstart2: X mov inode_no, 1 ; load root directory (inode=1) X mov fseg, ds X mov foff, offset dir_buf X call load_file X X; call _newline X; mov ax, n_blocks ; show file size X; call put4x X; call _newline X X mov ax, n_blocks ; loop to search for file "boot" X mov cl, 10 X shl ax, cl ; ax = # of bytes in directory X mov bx, 0 Xsearch_loop: X cmp bx, ax ; bx = byte offset within directory X jge no_match X cmp word ptr dir_buf[bx], 0 ; ignore files with inode# 0 X je next_name X lea si, dir_buf+2[bx] ; compare filename with boot_file_name X lea di, boot_file_name X call strcmp X je found_file Xnext_name: X add bx, 16 ; next directory entry X jmp search_loop Xno_match: X mov bx, offset not_found_err ; file not found X jmp terminate Xfound_file: X mov ax, word ptr dir_buf[bx] ; get inode # X mov inode_no, ax X X mov fseg, BOOT_2_SEG ; 3/1/88gpo X ;60h ; load file at 0060:0000 X mov foff, 0 X; mov fseg, ds ; test load into data segment X; mov foff, offset fil_buf X X call load_file X Xif DEBUG X mov bx, offset file_loaded X call puts X mov ax, n_blocks X call put4x X call _newline X call getchar Xendif X Xget_equals: X; remove '=' key stuff 3/1/88gpo X mov bx, offset ram_load ; MINIX uses scan code from X call puts ; '=' key to select keyboard X; call getchar ; type and initialize console X; cmp al, '=' ; driver X; jne get_equals X; X; mov bx, ax ; scan code for '=' X; jmp far ptr kernel ; Jump to MINIX starting point X; ; 0060:0000 X jmp far ptr hstart2 X Xreset: xor ah, ah X mov dl, drive X int 13h X ret X Xread_block: ; lbn = logical block # X ; bseg_no = segment# X ; boff_no = offset X mov ax, lbn X add ax, ax ; sector # = 2 * block # X mov lsn, ax X X mov bx, ds ; es:bx = block load address X mov es, bx ; use double buffering to avoid X mov bx, offset block_buf ; DMA across 64K boundary problems X X call read_sector X jc done_read_block ; read error X inc lsn X X mov bx, offset block_buf + 512 ; load 2nd sector of block X call read_sector X jc done_read_block ; read error X Xmovit: lea si, block_buf ; move block form buffer X mov di, bseg_no ; to desired address (bseg_no:boff_no) X mov es, di X mov di, boff_no X mov cx, 512 X cld X rep movsw X Xdone_read_block: X ret X Xread_sector: ; lsn = logical sector # X ; sseg_no = segment# X ; soff_no = offset X mov retry, 10 Xread_again: X dec retry ; retry 9 more times on error X js done_read_sector ; abort X X mov ax, lsn X X xor dx, dx ; dx:ax / cylinder size X div cylsize X mov cl, ah ; high bits of cl get bits 8,9 of X ror cl, 1 ; cylinder # X ror cl, 1 X mov ch, al ; low byte of cylinder # X mov ax, dx X xor dx, dx X div tracksize X mov dh, al ; dh = head # X or cl, dl ; or in sector # bits X inc cl ; start sector # at 1 rather than 0 X mov dl, drive ; drive # X mov ax, 0201h ; read 1 sector X int 13h X X jc read_again ; try again on error Xdone_read_sector: X ret X X Xcylsize dw 12h ; The following variables must Xtracksize dw 09h ; be located in the first 512 bytes Xdrive db 0 ; because they are used in the primary Xblock_size dw 1024 ; stage running at 0000:7C00 and the Xinodes_per_block dw 32 ; BIOS ROM only loads 1 sector X Xget_inode: ; input: inode_no X ; returns pointer to corresponding X ; inode in inode_p X X mov lbn, 1 ; fetch super_block X mov bseg_no, ds X mov boff_no, offset super_buf X call read_block X jnc okay_super X call read_error X mov bx, offset super_err X jmp terminate X Xokay_super: X Xif DEBUG X mov ax, offset super_buf X push ax X call _print_block X pop ax X call getchar Xendif X X mov ax, inode_no X dec ax X xor dx, dx X div inodes_per_block X mov i_offset, dx X add ax, super_buf + S_IMAP_BLOCKS_OFF X add ax, super_buf + S_ZMAP_BLOCKS_OFF X add ax, 2 X mov i_block, ax X mov lbn, ax X mov bseg_no, ds X mov boff_no, offset inode_buf X call read_block X jnc okay_inode X X call read_error X mov bx, offset inode_err X jmp terminate X Xokay_inode: X Xif DEBUG X mov ax, offset inode_buf X push ax X call _print_block X pop ax X call getchar Xendif X X mov bx, i_offset X mov cx, 5 X shl bx, cl X add bx, offset inode_buf X mov inode_p, bx X ret X Xload_file: ; load file at fseg:foff given inode_no X ; returns file size in n_blocks X call get_inode X mov bx, inode_p X mov ax, I_SIZE_OFF[bx] X mov dx, I_SIZE_OFF+2[bx] X div block_size X mov n_blocks, ax ; calculate # of blocks to load X test dx, dx X jz no_spill X inc n_blocks ; partial block Xno_spill: X cmp n_blocks, NR_DZONE_NUM ; are there indirect blocks? X jle no_indirect X mov ax, IND_ZONE_OFF[bx] ; if so, read indirect block first X mov lbn, ax X mov bseg_no, ds X mov boff_no, offset ind_buf X call read_block X jnc no_indirect X X call read_error X mov bx, offset ind_err X jmp terminate X Xno_indirect: ; set up loop to read all blocks in file X mov ax, fseg X mov bseg_no, ax X mov ax, foff X mov boff_no, ax X mov load_i, 0 Xload_loop: X mov bx, load_i ; for load_i := 0 to n_blocks-1 do X cmp bx, n_blocks X jge done_load X add bx, bx ; calculate block# X cmp bx, NR_DZONE_NUM*2 X jge indirect_block X add bx, inode_p X mov ax, I_ZONE_OFF[bx] X jmp cont_load Xindirect_block: X mov ax, ind_buf-14[bx] Xcont_load: ; read the block X mov lbn, ax X call read_block X jnc next_block X X call read_error X mov bx, offset file_err X jmp terminate X Xnext_block: X X; mov ax, bseg_no ; reduce chatter 4/28/88GPO X; call put4x X; mov al, ':' X; call putchar X; mov ax, 0 X; call put4x X; call _newline X X add bseg_no, 40h ; increment seg for next block X inc load_i X jmp load_loop Xdone_load: X ret X Xram_load db 'Second boot stage loaded, Starting ...', 13, 10, 0 X ;'Type "=" to load RAM disk -> ', 0 Xboot_err db 'Error reading Boot block', 13, 10, 0 Xsuper_err db 'Error reading Super_block', 13, 10, 0 Xinode_err db 'Error reading Inode', 13, 10, 0 Xind_err db 'Error reading Indirect Block', 13, 10, 0 Xfile_err db 'Error reading file', 13, 10, 0 Xnot_found_err db 'Boot file not found', 13, 10, 0 Xfile_loaded db 'File loaded - blocks = ', 0 Xboot_file_name db 'boot', 12 dup (0) X X X;----------------------------------------------------------------------------- X; X; All routines which follow are optional, mostly character I/O X; procedures for debugging purposes, which can be stripped out X; if necessary. Total code and initialized data must come first X; and must fit into 1K. X; X;----------------------------------------------------------------------------- X Xterminate: X call puts Xexit: jmp exit ; hang in harmless loop on error X X Xputchar: ; char in AL, return code in AX X mov ah, 0Eh X xor bl, bl X int 10h X ret X Xputs: ; print string, address in BX X mov al, byte ptr [bx] X test al, al X je doneputs X push bx X call putchar X pop bx X inc bx X jmp puts Xdoneputs: X ret X X_newline: X mov al, 13 X call putchar X mov al, 10 X call putchar X ret X Xgetchar: ; char returned in AL X xor ah, ah X int 16h X cmp al, 03h X je exit X push ax X push bx X call putchar X pop bx X pop ax X ret X Xgets: ; read string into buffer X call getchar ; address in bx X cmp al, 0Dh X je done_gets X mov byte ptr [bx], al X inc bx X jmp gets Xdone_gets: X mov byte ptr [bx], 0 X ret X Xput2x: ; print hex byte in AL X push ax X shr ax, 1 X shr ax, 1 X shr ax, 1 X shr ax, 1 X call put_byte X pop ax Xput_byte: X and al, 0Fh X add al, 30h X cmp al, 39h X jle nothex X add al, 07h Xnothex: call putchar X ret X Xput4x: ; print hex word in AX X push ax X xchg al, ah X call put2x X pop ax X call put2x X ret X Xstrcmp: ; string compare X push ds X pop es ; addresses in SI & DI X cld X mov cx, 0Eh X repe cmpsb X ret ; returns with flags set based X ; upon compare result X Xread_error: X push ax X push bx X push es X push cx X push dx X push cx X push dx X call _newline X X pop ax ; print drive# X call put2x X mov al, ' ' X call putchar X X pop ax ; print cylinder# X xchg ah, al X call put2x X mov al, ' ' X call putchar X X pop ax ; print head# X xchg ah, al X call put2x X mov al, ' ' X call putchar X X pop ax ; print sector# X call put2x X mov al, ' ' X call putchar X X pop ax ; print segment X call put4x X mov al, ':' X call putchar X X pop ax ; print offset X call put4x X call _newline X X pop ax X mov al, ah X call put2x X mov al, ' ' X call putchar X ret X X X_print_block proc near X push bp X mov bp,sp X push word ptr [bp+4] X call near ptr _print_sector X pop cx X mov ax,word ptr [bp+4] X add ax,512 X push ax X call near ptr _print_sector X pop cx X@1: X pop bp X ret X_print_block endp X X X_print_sector proc near X push si X push di X push bp X mov bp,sp X dec sp X dec sp X xor si,si X call near ptr _newline X xor di,di X jmp short @6 X@5: X mov ax, si X call put4x X mov bx, offset _s@ X mov word ptr [bp-2],0 X jmp short @10 X@9: X mov ax,si X inc si X mov bx,ax X add bx,word ptr [bp+8] X mov al,byte ptr [bx] X call put2x X mov al,' ' X call putchar X@8: X inc word ptr [bp-2] X@10: X cmp word ptr [bp-2],16 X jb @9 X@7: X mov ax,16 X push ax X mov ax,word ptr [bp+8] X add ax,si X add ax,-16 X push ax X call near ptr _prints X pop cx X pop cx X@4: X inc di X@6: X cmp di,32 X jb @5 X@3: X call near ptr _newline X@2: X mov sp,bp X pop bp X pop di X pop si X ret X_print_sector endp X X X_prints proc near X push si X push di X push bp X mov bp,sp X mov si,word ptr [bp+8] X mov bx,offset _s@+3 X call puts X xor di,di X jmp short @15 X@14: X cmp byte ptr [si],32 X jl @16 X cmp byte ptr [si],126 X jg @16 X mov al,byte ptr [si] X call putchar X jmp short @17 X@16: X mov al, '.' X call putchar X@17: X@13: X inc di X inc si X@15: X cmp di,word ptr [bp+10] X jl @14 X@12: X call near ptr _newline X@11: X pop bp X pop di X pop si X ret X_prints endp X X_s@ label byte X db 32 X db 32 X db 0 X db 32 X db 32 X db 32 X db 32 X db 0 X X X;----------------------------------------------------------------------------- X; X; Most of the following declarations are necessary but are all X; uninitialized data areas so they can go anywhere after the X; necessary code. Declarations which are followed by * are for X; debug purposes only. X; X;----------------------------------------------------------------------------- X X Xretry db ? ; dist read retry counter Xlbn dw ? ; logical block # Xbseg_no dw ? ; block load segment # Xboff_no dw ? ; block load offset # Xlsn dw ? ; logical sector # X Xi_block dw ? ; inode block # Xi_offset dw ? ; inode block offset Xinode_no dw ? ; inode number Xinode_p dw ? ; pointer to inode structure X Xload_i dw ? ; loop counter for file load Xfseg dw ? ; segment for file load Xfoff dw ? ; offset for file load Xn_blocks dw ? ; file size in blocks X Xblock_buf db 1024 dup (?) ; I/O buffer for all disk reads X;boot_buf db 1024 dup (?) ; Boot block copied here Xsuper_buf dw 512 dup (?) ; Super block loaded here Xinode_buf dw 512 dup (?) ; Inode block loaded here Xind_buf dw 512 dup (?) ; Indirect block loaded here (sometimes) Xdir_buf dw 512 dup (?) ; root file directory loaded here X;fil_buf db 20 dup (1024 dup (?)) ; temporary file load area X Xstack dw 100 dup (?) ; small stack area for boot only Xestack label word ; init SP here X X X_text ends X X end start1 SHAR_EOF if test 16625 -ne "`wc -c < 'b1/bootblok.asm3'`" then echo shar: error transmitting "'b1/bootblok.asm3'" '(should have been 16625 characters)' fi fi # end of overwriting check echo shar: extracting "'b1/bootblok.uu'" '(1439 characters)' if test -f 'b1/bootblok.uu' then echo shar: will not over-write existing file "'b1/bootblok.uu'" else sed 's/^X//' << \SHAR_EOF > 'b1/bootblok.uu' Xbegin 644 bootblok XMC,B.V([0O#V5Z($ QP9=@ QP9?@ QP9A@ !\Z'4 <PGH. .[*G[IO0+' XM!FF 0",'F^ QP9Q@'60Z#,!H7. L0K3X+L #O8?1F#OW60 '0-C;=WD(T^ XMV7[H]@)T"X/#$.OCNZM^Z7T"BX=UD*-I@,<&;X ,L<&<8 .CP +L!?NAM XM NH R,N2*%@9]S1/#H5V \"C8X",VX[#NW6 Z", <B#_!F. NW6"Z!< XM<A2--G6 BSY?@(['BSYA@+D OSSI</&!ER "I#^#ER >"JA8X STO<V GV* XMS-#)T,F*Z(O",]+W-@1]BO *RO[!BA8&?;@! LT3<M##$@ ) !" QP9= XM@ $ C!Y?@,<&88!UA.AX_W,)Z#L"NT5^Z< !H6F 2#/2]S8)?8D69X #!GF$ XM P9[A 4" *-E@*-=@(P>7X#'!F& =8CH0?]S">@$ KMA?NF) 8L>9X"Y!0#3 XMXX'#=8B)'FN P^B6_XL>:X"+1P2+5P;W-@=]HW. A=)T!/\&<X"#/G. !WX> XMBT<<HUV C!Y?@,<&88!UC.CN_G,)Z+$!NW=^Z38!H6^ HU^ H7& HV& QP9M XM@ BQYM@#L><X!],0/;@_L.?0H#'FN BT<.ZP60BX=GC*-=@.BL_G,)Z&\! XMNY9^Z?0 @P9?@$#_!FV Z\7#4V5C;VYD(&)O;W0@<W1A9V4@;&]A9&5D+"!3 XM=&%R=&EN9R N+BX-"@!%<G)O<B!R96%D:6YG($)O;W0@8FQO8VL-"@!%<G)O XM<B!R96%D:6YG(%-U<&5R7V)L;V-K#0H 17)R;W(@<F5A9&EN9R!);F]D90T* XM $5R<F]R(')E861I;F<@26YD:7)E8W0@0FQO8VL-"@!%<G)O<B!R96%D:6YG XM(&9I;&4-"@!";V]T(&9I;&4@;F]T(&9O=6YD#0H 1FEL92!L;V%D960@+2!B XM;&]C:W,@/2 8F]O= .@) .O^M XRV\T0PXH'A,!T"%/H XM[_];0^ORP[ -Z.7_L KHX/_#,N3-%CP#=-504^C2_UM8P^CM_SP-= 6(!T/K XM],8' ,-0T>C1Z-'HT>CH 0!8) \$,#PY?@($!^BE_\-0AL3HW_]8Z-O_PQX' XM_+D. /.FPU!3!E%245+HG/]8Z,/_L"#H??]8AN#HN/^P(.AR_UB&X.BM_[ @ XMZ&?_6.BD_[ @Z%[_6.BV_[ ZZ%7_6.BM_^AD_UB*Q.B)_[ @Z$/_PU6+[/]V XM!.@. %F+1@0% )0Z , 65W#5E=5B^Q,3#/VZ#7_,__K/8O&Z'+_NU2 QT;^ XB #K%8O&1HO8 UX(B@?H0/^P(.CZ_O]&_H-^_A!RY;@0 (O& X Xend SHAR_EOF if test 1439 -ne "`wc -c < 'b1/bootblok.uu'`" then echo shar: error transmitting "'b1/bootblok.uu'" '(should have been 1439 characters)' fi fi # end of overwriting check echo shar: extracting "'b2b/Makefile'" '(235 characters)' if test -f 'b2b/Makefile' then echo shar: will not over-write existing file "'b2b/Makefile'" else sed 's/^X//' << \SHAR_EOF > 'b2b/Makefile' XCFLAGS=-I/usr/src/minix -Di8088 X X#.c.s: X# cc $(CFLAGS) -c $*.c X Xall: loader.s stack.s standalone.s main.s X asld -s -o b2 bsu.s main.s loader.s stack.s standalone.s /usr/lib/libc.a /usr/lib/end.s > b2.sym X dd if=b2 of=boot bs=32 skip=1 SHAR_EOF if test 235 -ne "`wc -c < 'b2b/Makefile'`" then echo shar: error transmitting "'b2b/Makefile'" '(should have been 235 characters)' fi fi # end of overwriting check echo shar: extracting "'b2b/bsu.s'" '(5153 characters)' if test -f 'b2b/bsu.s' then echo shar: will not over-write existing file "'b2b/bsu.s'" else sed 's/^X//' << \SHAR_EOF > 'b2b/bsu.s' X| X| Second-Stage Bootstrap assembly level run-time support X| Derrived from "tools/fsck1.s" and "kernel/klib88.s" X| XSTACKSIZE = 16384 X X.globl _main, endtext, enddata, endbss X.globl __putc, __getc, _reset_diskette, _diskio X.globl csv, cret, begtext, begdata, begbss X.globl _cylsiz, _tracksiz X|, _drive X.globl _ds, _lcopy, _sp X X.text Xbegtext: Xstart: X mov ax,cs | ds=es=ss=cs X mov es,ax X mov ds,ax X mov ss,ax X| mov dx,bx | bootblok puts # sectors/track in bx X xor ax,ax X mov bx,#enddata | prepare to clear bss X mov cx,#endbss X sub cx,bx X shr cx,*1 Xst.1: mov (bx),ax | clear bss X add bx,#2 X loop st.1 X X| mov _tracksiz,dx | dx (was bx) is # sectors/track X| add dx,dx X| mov _cylsiz,dx | # sectors/cylinder X mov sp,#kerstack+STACKSIZE X call _main Xst.2: mov bx,ax | put scan code for '=' in bx X| mov bp,#_sizes | bp points to 'sizes' array X mov sp,_ksp | sp first 'cause we'll destroy ds X mov dx,_kds X mov ds,dx X mov ss,dx X nop X cli X| mov dx,#0x60 X|leave ES where it is so kernel can find the a.out table... X| mov es,dx X nop X jmpi 0,0x60 | jmp to kernel X X|_exit: X| mov bx,_tracksiz X jmp start X X X__putc: X xor ax,ax X call csv X movb al,4(bp) | al contains char to be printed X movb ah,#14 | 14 = print char X movb bl,*1 | foreground color X push bp | not preserved X int 0x10 | call BIOS VIDEO_IO X pop bp X jmp cret X X__getc: X xorb ah,ah X int 0x16 X ret X X_ds: X mov ax,ds X ret X_sp: X mov ax,sp X ret X X_reset_diskette: X xor ax,ax X call csv X push es | not preserved X int 0x13 | call BIOS DISKETTE_IO X pop es X jmp cret X X X| handle diskio(RW, sector_number, buffer, sector_count, drive) call X| Do not issue a BIOS call that crosses a track boundary X_diskio: X xor ax,ax X call csv X mov tmp1,#0 | tmp1 = # sectors actually transferred X mov di,10(bp) | di = # sectors to transfer X mov tmp2,di | di = # sectors to transfer Xd0: mov ax,6(bp) | ax = sector number to start at X xor dx,dx | dx:ax is dividend X div _cylsiz | ax = cylinder, dx = sector within cylinder X movb cl,ah | cl = hi-order bits of cylinder X rorb cl,#1 | BIOS expects hi bits in a funny place X rorb cl,#1 | ditto X movb ch,al | cx = sector # in BIOS format X mov ax,dx | ax = sector offset within cylinder X xor dx,dx | dx:ax is dividend X div _tracksiz | ax = head, dx = sector X movb dh,al | dh = head X orb cl,dl | cl = 2 high-order cyl bits || sector X incb cl | BIOS counts sectors starting at 1 X movb dl,12(bp) | dl = drive code (0-3 or 0x80 - 0x81) X mov bx,8(bp) | bx = address of buffer X movb al,cl | al = sector # X addb al,10(bp) | compute last sector X decb al | al = last sector to transfer X cmpb al,_tracksiz | see if last sector is on next track X jle d1 | jump if last sector is on this track X mov 10(bp),#1 | transfer 1 sector at a time Xd1: movb ah,4(bp) | ah = READING or WRITING X addb ah,*2 | BIOS codes are 2 and 3, not 0 and 1 X movb al,10(bp) | al = # sectors to transfer X mov tmp,ax | al is # sectors to read/write X push es | BIOS ruins es X int 0x13 | issue BIOS call X pop es | restore es X cmpb ah,*0 | ah != 0 means BIOS detected error X jne d2 | exit with error X mov ax,tmp | fetch count of sectors transferred X xorb ah,ah | count is in ax X add tmp1,ax | tmp1 accumulates sectors transferred X mov si,tmp1 | are we done yet? X cmp si,tmp2 | ditto X je d2 | jump if done X inc 6(bp) | next time around, start 1 sector higher X add 8(bp),#0x200 | move up in buffer by 512 bytes X jmp d0 Xd2: jmp cret X Xcsv: X pop bx X push bp X mov bp,sp X push di X push si X sub sp,ax X jmp (bx) X Xcret: X lea sp,*-4(bp) X pop si X pop di X pop bp X ret X X|*===========================================================================* X|* phys_copy * X|*===========================================================================* X| This routine copies a block of physical memory. It is called by: X| lcopy(destination segment, offset, source segment, offset, length) X| phys_copy( (long) source, (long) destination, (long) bytecount) X X_lcopy: X pushf | save flags X cli | disable interrupts X push bp | save the registers X push ax | save ax X push bx | save bx X push cx | save cx X push dx | save dx X push si | save si X push di | save di X push ds | save ds X push es | save es X mov bp,sp | set bp to point to saved es X X L0: mov ax,22(bp) | ax = segment of destination X mov di,24(bp) | di = offset of destination X mov es,ax | es = destination click X X mov ax,26(bp) | ax = segment of source X mov si,28(bp) | si = offset of source X X mov cx,30(bp) | cx = low-order word of byte count X X mov ds,ax | ds = source click X X test cx,*0x0001 | should we copy a byte or a word at a time? X jz L5 | jump if even X rep | copy 1 byte at a time X movb | byte copy X jmp L6 | check for more bytes X X L5: shr cx,*1 | word copy X rep | copy 1 word at a time X movw | word copy X X L6: pop es | restore all the saved registers X pop ds | restore ds X pop di | restore di X pop si | restore si X pop dx | restore dx X pop cx | restore cx X pop bx | restore bx X pop ax | restore ax X pop bp | restore bp X popf | restore flags X ret | return to caller X X.data Xbegdata: Xtmp: .word 0 Xtmp1: .word 0 Xtmp2: .word 0 X.bss Xbegbss: Xkerstack: .zerow STACKSIZE/2 | kernel stack SHAR_EOF if test 5153 -ne "`wc -c < 'b2b/bsu.s'`" then echo shar: error transmitting "'b2b/bsu.s'" '(should have been 5153 characters)' fi fi # end of overwriting check echo shar: extracting "'b2b/hdparam.h'" '(580 characters)' if test -f 'b2b/hdparam.h' then echo shar: will not over-write existing file "'b2b/hdparam.h'" else sed 's/^X//' << \SHAR_EOF > 'b2b/hdparam.h' X/* X * Hard Disk ROM Parameter Table structure X * X * Hawked from Minix's kernel/xt_wini.c X * note: this table is not EXACT; it is intened to be loaded by a routine X * that does the actual memory poking X */ X X struct param { X int nr_cyl; /* Number of cylinders */ X int nr_heads; /* Number of heads */ X int reduced_wr; /* First cylinder with reduced write current */ X int wr_precomp; /* First cylinder with write precompensation */ X int max_ecc; /* Maximum ECC burst length */ X int ctrl_byte; /* Copied control-byte from bios tables */ X int sectors; /* sectors per track */ X}; SHAR_EOF if test 580 -ne "`wc -c < 'b2b/hdparam.h'`" then echo shar: error transmitting "'b2b/hdparam.h'" '(should have been 580 characters)' fi fi # end of overwriting check echo shar: extracting "'b2b/main.c'" '(3309 characters)' if test -f 'b2b/main.c' then echo shar: will not over-write existing file "'b2b/main.c'" else sed 's/^X//' << \SHAR_EOF > 'b2b/main.c' X/* X Minix Second Stage Boot Loader X XIn this program, all the elements of the Minix system are loaded into memory Xfrom binary files on a filesystem. All parts of the system are loaded Xlike any other Minix process, with Text, Data and Stack areas and command Xoptions on a "command line" (which is actually in a binary format). X X*/ X#include <minix/const.h> X#include <minix/type.h> X#include <fs/const.h> X#include <fs/type.h> X#include <fs/inode.h> X#include <fs/super.h> X#include <stdio.h> X#include <errno.h> X#include <a.out.h> X#include "type.h" X X/*#define FLOPPY /* define for fd(0) rather than hd(0,2) */ X/*#undef printf /* defined in fs/const.h as 'printk' */ X#undef getchar /* don't want the macros */ X#undef putchar X#undef putc X#undef getc X Xextern int sizes[], kds, ksp; Xint error = 0; Xint segment = 0x60; Xint filenum = 0; X X/*#define DEBUG*/ X XAOUT load(file) Xchar *file; X{ INODE inode; X AOUT aout; X long t, d, b, s; /* sizes of Text, Data, BSS and Stack segs */ X X/* printf("**********************************************************\n");*/ X printf("%s\n",file); X#ifdef DEBUG X printf("Segment = 0x%x\n", segment); X fgetc(); X#endif X if((inode = open_file(file)) == NULL) { X error = 1; X perror("boot"); X } X aout = load_file(inode, segment); X#ifdef DEBUG X dump_exec(aout); X#endif X if(aout->a_flags & A_SEP) { X t = aout->a_text; X d = aout->a_data; X } else { X t = 0; X d = aout->a_data + aout->a_text; X } X b = aout->a_bss; X s = aout->a_total - d - b; X X#ifdef DEBUG X printf("t=%ld d=%ld b=%ld s=%ld\n", t, d, b, s); X#endif X /* write Text, (Data+BSS+STACK) segment info on top of header X * relocation info (that won't be used on 80x86 machines) X */ X aout->a_trsize = t; X aout->a_drsize = d + b; /* data segment (not including stack) */ X aout->a_tbase = (long) segment; X aout->a_dbase = (long) (segment + clicks(t)); X#ifdef DEBUG X printf("trsize=0x%x tbase=0x%x drsize=0x%x dbase=0x%x total=0x%x\n", X (int) aout->a_trsize, (int) aout->a_tbase, X (int) aout->a_drsize, (int) aout->a_dbase, aout->a_total); X#endif X X zero_mem(segment + clicks(t + d), 0, (int) b); X X segment += clicks(t + d + b + s); X/* sizes[filenum * 2] = clicks(t); X sizes[filenum * 2 +1] = clicks(d + b + s); */ X filenum++; X X return(aout); X} X Xmain() X{ AOUT aout[10]; X char eq = '\0'; X int i, stack[5]; X X printf("Hello World\n"); X X#ifdef FLOPPY X aout[0] = load("fd0:/etc/kernel"); X aout[1] = load("fd0:/etc/mm"); X aout[2] = load("fd0:/etc/fs"); X aout[3] = load("fd0:/etc/init"); X#else X aout[0] = load("hd0.2:/etc/kernel"); X aout[1] = load("hd0.2:/etc/mm"); X aout[2] = load("hd0.2:/etc/fs"); X aout[3] = load("hd0.2:/etc/init"); X#endif X X#ifdef DEBUG X printf("System Loaded, Initializing...\n"); X fgetc(); X#endif X X stack[0] = aout[0]->a_dbase + aout[0]->a_total; X mmstack(aout[1],stack+1); X fsstack(aout[2],stack+2); X ksp = kstack(aout, stack); X X/* for(i = 0;i < 8;i++) X printf("sizes[%d] = %d %x\n", i, sizes[i], sizes[i]);*/ X X/* printf("Segment = 0x%x\n", segment);*/ X X kds = 0x60 + ((aout[0]->a_flags & A_SEP) ? clicks(aout[0]->a_text) : 0); X printf("Kernel CS=0x%x DS=0x%x SP=0x%x\n", aout[0]->a_text, kds, ksp); X X if(error) { X printf("\n\n\nError occured durring system load!!\n"); X printf(" REBOOT NOW!\n"); X fgetc(); X } else { X printf("\n\nStrike '=' to execute system:"); X while((eq=fgetc()) != '='); X return(eq); X } X} SHAR_EOF if test 3309 -ne "`wc -c < 'b2b/main.c'`" then echo shar: error transmitting "'b2b/main.c'" '(should have been 3309 characters)' fi fi # end of overwriting check echo shar: extracting "'b2b/partition.h'" '(729 characters)' if test -f 'b2b/partition.h' then echo shar: will not over-write existing file "'b2b/partition.h'" else sed 's/^X//' << \SHAR_EOF > 'b2b/partition.h' X/* X * Description of entry in the hard disks's partition table X * X * Hawked from Minix's commands/fdisk.c program X */ X Xstruct part_entry { X char bootind; /* boot indicator 0/0x80 */ X char start_head; /* head value for first sector */ X char start_sec; /* sector value for first sector*/ X char start_cyl; /* track value for first sector */ X char sysind; /* system indicator 00=?? 01=DOS*/ X char last_head; /* head value for last sector */ X char last_sec; /* sector value for last sector */ X char last_cyl; /* track value for last sector */ X long lowsec; /* logical first sector */ X long size; /* size of partion in sectors */ X}; X X/*#define SECSIZE 512 /* sector size */ X#define TABLEOFFSET 0x1be /* offset in boot sector*/ SHAR_EOF if test 729 -ne "`wc -c < 'b2b/partition.h'`" then echo shar: error transmitting "'b2b/partition.h'" '(should have been 729 characters)' fi fi # end of overwriting check echo shar: extracting "'b2b/stack.c'" '(7832 characters)' if test -f 'b2b/stack.c' then echo shar: will not over-write existing file "'b2b/stack.c'" else sed 's/^X//' << \SHAR_EOF > 'b2b/stack.c' X/* X Boot Stage 2 Stack construction X XThese routines will construct an initial stack for ther Kernel, Memory Manager, XFile System and Init programs. X X*/ X#include <minix/const.h> X#include <minix/type.h> X#include <kernel/const.h> X#include <kernel/type.h> X#include <kernel/proc.h> X#include <a.out.h> X#include <errno.h> X#include "type.h" X Xextern char **environ; /* environment pointer */ X X#define PTRSIZE sizeof(char *) X X/*#define DEBUG /**/ X X/* X * Build a stack from a set of arguments. X * X * This function is derived from Minix's lib/exec.c(execve) function. X */ Xint buildstack(argv, argsize, envp, envsize, stack) Xchar *argv[]; /* pointer to argument array */ Xint argsize; /* size of argument array elements (fixed)*/ Xchar *envp[]; /* pointer to environment */ Xint envsize; /* size of environment array elements (fixed)*/ Xchar *stack; /* memory to build the stack in */ X{ X/* char stack[MAX_ISTACK_BYTES];*/ X char **argorg, **envorg, *hp, **ap, *p; X int i, nargs, nenvps, stackbytes, offset; X extern errno; X X /* Count the argument pointers and environment pointers. */ X nargs = 0; X nenvps = 0; X argorg = argv; X envorg = envp; X while (*argorg++ != NIL_PTR) nargs++; X while (*envorg++ != NIL_PTR) nenvps++; X X /* Prepare to set up the initial stack. */ X hp = &stack[(nargs + nenvps + 3) * PTRSIZE]; X#ifdef DEBUG Xprintf("nargs=%d nenvps=%d hp=0x%x\n",nargs,nenvps,hp); X#endif X if (hp + nargs + nenvps >= &stack[MAX_ISTACK_BYTES]) { X errno = E2BIG; X return(-1); X } X ap = (char **) stack; X *ap++ = (char *) nargs; X X /* Prepare the argument pointers and strings. */ X for (i = 0; i < nargs; i++) { X offset = hp - stack; X *ap++ = (char *) offset; X p = *argv++; X copy(hp, p, argsize); X hp += argsize; X if (hp >= &stack[MAX_ISTACK_BYTES]) { X errno = E2BIG; X return(-1); X } X } X *ap++ = NIL_PTR; X X /* Prepare the environment pointers and strings. */ X for (i = 0; i < nenvps; i++) { X offset = hp - stack; X *ap++ = (char *) offset; X p = *envp++; X X hp += envsize; X if (hp >= &stack[MAX_ISTACK_BYTES]) { X errno = E2BIG; X return(-1); X } X } X *ap++ = NIL_PTR; X stackbytes = ( ( (int)(hp - stack) + PTRSIZE - 1)/PTRSIZE) * PTRSIZE; X return(stackbytes); X} X X/*===========================================================================* X * patch_ptr * X *===========================================================================*/ X/* taken from Minix's mm/exec.c */ XPRIVATE patch_ptr(stack, base) Xchar stack[MAX_ISTACK_BYTES]; /* pointer to stack image within MM */ Xvir_bytes base; /* virtual address of stack base inside user */ X{ X/* When doing an exec(name, argv, envp) call, the user builds up a stack X * image with arg and env pointers relative to the start of the stack. Now X * these pointers must be relocated, since the stack is not positioned at X * address 0 in the user's address space. X */ X X char **ap, flag; X vir_bytes v; X X flag = 0; /* counts number of 0-pointers seen */ X ap = (char **) stack; /* points initially to 'nargs' */ X ap++; /* now points to argv[0] */ X while (flag < 2) { X if (ap >= (char **) &stack[MAX_ISTACK_BYTES]) return; /* too bad */ X if (*ap != NIL_PTR) { X v = (vir_bytes) *ap; /* v is relative pointer */ X v += base; /* relocate it */ X *ap = (char *) v; /* put it back */ X } else { X flag++; X } X ap++; X } X} X X/* X * ProcStack - give a process a stack X * X * A stack is built up from the arguments (argv, envp) given, and copied X * into the process' stack space. The address that the stack pointer should X * be assigned is returned. X */ Xprocstack(argv, sizeargv, envp, sizeenvp, proc) Xchar **argv; Xint sizeargv; Xchar **envp; Xint sizeenvp; XAOUT proc; X{ static char stack[MAX_ISTACK_BYTES]; X int size, /* size of process' stack */ X seg, offset; /* segment and offset of stack dest. */ X X#ifdef DEBUG X printf("Procstack...\n"); X#endif X size=buildstack(argv, sizeargv, envp, sizeenvp, stack); X seg = (int) proc->a_dbase; X offset = (int) proc->a_total - size; X patch_ptr(stack, offset); X#ifdef DEBUG X printf("seg= 0x%x offset=0x%x length=0x%x\n", seg, offset, size); X printf("trsize=0x%x tbase=0x%x drsize=0x%x dbase=0x%x total=0x%x\n", X (int) proc->a_trsize, (int) proc->a_tbase, X (int) proc->a_drsize, (int) proc->a_dbase, X (int) proc->a_total); X#endif X lcopy(seg, offset, ds(), stack, size); X return(offset); X} X X/* X * Kernel Stack X * X * The kernel stack consists of a "proc" array as argv and a device X * configuration array as envp. The processes present in the proc X * array start with PID 0 (MM) and end with the first user process (INIT). X * X * Initially the device configuration is nonexistant. X */ Xkstack(procinfo, sps) XAOUT *procinfo; Xint *sps; X{ static struct proc proc[4], /* Kernel, MM, FS, INIT */ X *pproc[] = { proc, proc+1, proc+2, proc+3, 0 }; X static int *kenv[] = { 0, 0 }; X X struct proc *p; X int *s, sp; X X /* Build a process table for the kernel */ X p = proc; s = sps; X X kproc(p++, s++, procinfo[0]); /* kernel*/ X kproc(p++, s++, procinfo[1]); /* MM */ X kproc(p++, s++, procinfo[2]); /* FS */ X kproc(p++, s++, procinfo[3]); /* init */ X X dmpproc(proc); X sp = procstack(pproc, sizeof(struct proc), kenv, sizeof(int), procinfo[0]); X return(sp); /* initial stack */ X} X X/* X * Set Up Kernel Process Table X */ Xkproc(p, s, procinfo) Xstruct proc *p; Xint *s; XAOUT procinfo; X{ p->p_map[T].mem_vir = 0; X p->p_map[T].mem_phys = (int) procinfo->a_tbase; X p->p_map[T].mem_len = clicks(procinfo->a_trsize); X X p->p_map[D].mem_vir = (procinfo->a_trsize == 0) ? X (int) procinfo->a_trsize : 0; X p->p_map[D].mem_phys = (int) procinfo->a_dbase; X p->p_map[D].mem_len = clicks(procinfo->a_total); X X p->p_map[S].mem_vir = p->p_map[D].mem_vir + clicks(procinfo->a_total); X p->p_map[S].mem_phys = p->p_map[D].mem_phys +clicks(procinfo->a_total); X p->p_map[S].mem_len = 0; X X p->p_sp = *s; X} X Xdmpproc(proc) Xstruct proc *proc; X{ X register struct proc *rp; X vir_bytes base, limit, first, last; X phys_bytes ltmp; X X printf("\nPROC -----TEXT----- -----DATA----- ----STACK----- BASE SIZE SP\r\n"); X for (rp = proc; rp < proc+4; rp++) { X if (rp->p_flags & P_SLOT_FREE) continue; X first = rp->p_map[T].mem_phys; X last = rp->p_map[S].mem_phys + rp->p_map[S].mem_len; X ltmp = ((long) first << 4) + 512L; X base = (vir_bytes) (ltmp/1024L); X ltmp = (((long) (last-first) << 4) + 512L); X limit = (vir_bytes) (ltmp/1024L); X printf("%4d", rp - proc); X X printf(" %4x %4x %4x %4x %4x %4x %4x %4x %4x %3dK %3dK %4x\r\n", X rp->p_map[T].mem_vir, rp->p_map[T].mem_phys, rp->p_map[T].mem_len, X rp->p_map[D].mem_vir, rp->p_map[D].mem_phys, rp->p_map[D].mem_len, X rp->p_map[S].mem_vir, rp->p_map[S].mem_phys, rp->p_map[S].mem_len, X base, limit, rp->p_sp); X } X} X X/* X * Memory Manager Stack X * X * The memory manager's stack consists of only the memory size of the system. X */ Xmmstack(mmproc, sp) XAOUT mmproc; Xint *sp; X{ static int mminfo[] = { 0x55AA }, X *mmptr[] = { mminfo, 0 }; X static int *mmenv[] = { 0 }; X X#ifdef DEBUG X printf("MM "); X#endif X *sp = procstack(mmptr, sizeof(int), mmenv, sizeof(int), mmproc); X} X X/* X * File System Stack X * X * The File System's stack consists of five integers in "argv": X * [0] Device to load ram disk image (0 if root doesn't need loading) X * [1] Device to mount as root X * [2] Size of Local RAM disk X * [3] Size of Extended Memory (AT) RAM disk X * [4] Size of EMS RAM disk X */ X#define RAM_IMAGE (dev_nr)0x303 /* major-minor dev where root image is kept */ Xfsstack(fsproc, sp) XAOUT fsproc; Xint *sp; X{ static int fsinfo[] = { 0, RAM_IMAGE, 0x1234, 0x5678, 0x9abc, 0 }, X *fsptr[] = { fsinfo, fsinfo+1, fsinfo+2, fsinfo+3, fsinfo+4, 0 }; X static int *fsenv[] = { 0, 0 }; X X#ifdef DEBUG X printf("FS "); X#endif X *sp=procstack(fsptr, sizeof(int), fsenv, sizeof(int), fsproc); X#ifdef DEBUG X printf("FS: 0x%x 0x%x 0x%x 0x%x 0x%x\n", *fsptr[0], *fsptr[1], *fsptr[2], *fsptr[3], *fsptr[4]); X#endif X} SHAR_EOF if test 7832 -ne "`wc -c < 'b2b/stack.c'`" then echo shar: error transmitting "'b2b/stack.c'" '(should have been 7832 characters)' fi fi # end of overwriting check echo shar: extracting "'b2b/standalone.c'" '(540 characters)' if test -f 'b2b/standalone.c' then echo shar: will not over-write existing file "'b2b/standalone.c'" else sed 's/^X//' << \SHAR_EOF > 'b2b/standalone.c' X/* X Stand-Alone (No OS) Support Routines X */ X Xprintf(fmt,args) Xchar *fmt; Xint args; X{ X _doprintf(0, fmt, &args); X} X X/* Print the given character. */ Xputc(c) Xchar c; X{ X fputc(c,0); X} X Xfputc(c,f) Xchar c; Xint f; X{ X if (c == '\n') X _putc('\r'); X _putc(c); X} X X/*putchar(c) { putc(c); }*/ X X/*write(d, buf, cnt) Xint d; Xchar *buf; Xint cnt; X{ X fputc('!',0); X while(--cnt) fputc(*buf++); X}*/ X X/* Get a character from the user and echo it. */ Xfgetc(f) Xint f; X{ X register c; X X if ((c = _getc() & 0xFF) == '\r') X c = '\n'; X fputc(c,0); X return(c); X} X SHAR_EOF if test 540 -ne "`wc -c < 'b2b/standalone.c'`" then echo shar: error transmitting "'b2b/standalone.c'" '(should have been 540 characters)' fi fi # end of overwriting check echo shar: extracting "'b2b/type.h'" '(140 characters)' if test -f 'b2b/type.h' then echo shar: will not over-write existing file "'b2b/type.h'" else sed 's/^X//' << \SHAR_EOF > 'b2b/type.h' X/* X Types for the Stage 2 Bootstrapper X X*/ X Xtypedef struct inode *INODE; Xtypedef struct super_block *SUPERBLOCK; Xtypedef struct exec *AOUT; SHAR_EOF if test 140 -ne "`wc -c < 'b2b/type.h'`" then echo shar: error transmitting "'b2b/type.h'" '(should have been 140 characters)' fi fi # end of overwriting check echo shar: extracting "'kernel/main.c.diff'" '(5503 characters)' if test -f 'kernel/main.c.diff' then echo shar: will not over-write existing file "'kernel/main.c.diff'" else sed 's/^X//' << \SHAR_EOF > 'kernel/main.c.diff' X*** /usr/src/minix/kernel/main.c Fri Dec 2 00:01:47 1988 X--- main.c Fri Apr 21 11:17:30 1989 X*************** X*** 47,65 **** X /*===========================================================================* X * main * X *===========================================================================*/ X! PUBLIC main() X { X /* Start the ball rolling. */ X X register struct proc *rp; X register int t; X int i, old_state; X! vir_clicks size; X! phys_clicks base_click, mm_base, previous_base; X phys_bytes phys_b; X int stack_size; X int * ktsb; /* kernel task stack base */ X- extern unsigned sizes[8]; /* table filled in by build */ X extern int port_65, ega, color, get_chrome(); X extern int s_call(), disk_int(), tty_int(), clock_int(), disk_int(); X extern int wini_int(), lpr_int(), trp(), rs232_int(), secondary_int(); X--- 47,65 ---- X /*===========================================================================* X * main * X *===========================================================================*/ X! PUBLIC main(argc, argv) X! int argc; X! struct proc **argv; X { X /* Start the ball rolling. */ X X register struct proc *rp; X register int t; X int i, old_state; X! phys_clicks base_click; X phys_bytes phys_b; X int stack_size; X int * ktsb; /* kernel task stack base */ X extern int port_65, ega, color, get_chrome(); X extern int s_call(), disk_int(), tty_int(), clock_int(), disk_int(); X extern int wini_int(), lpr_int(), trp(), rs232_int(), secondary_int(); X*************** X*** 84,131 **** X X old_state = lock(); /* we can't handle interrupts yet */ X base_click = BASE >> CLICK_SHIFT; X- size = sizes[0] + sizes[1]; /* kernel text + data size in clicks */ X- mm_base = base_click + size; /* place where MM starts (in clicks) */ X X for (ktsb = t_stack, t = -NR_TASKS, rp = &proc[0]; X rp <= &proc[NR_TASKS+LOW_USER]; rp++, t++) { X! for (i = 0; i < NR_REGS; i++) rp->p_reg[i] = 0100 * i; /* debugging */ X! if (t < 0) { X stack_size = tasktab[t+NR_TASKS].stksize; X ktsb += stack_size / sizeof (int); X rp->p_sp = ktsb; X rp->p_splimit = ktsb - (stack_size - SAFETY) / sizeof(int); X! } else { X! rp->p_sp = INIT_SP; X! rp->p_splimit = rp->p_sp; X! } X rp->p_pcpsw.pc = tasktab[t + NR_TASKS].initial_pc; X if (rp->p_pcpsw.pc != 0 || t >= 0) ready(rp); X rp->p_pcpsw.psw = INIT_PSW; X rp->p_flags = 0; X X- /* Set up memory map for tasks and MM, FS, INIT. */ X- if (t < 0) { X- /* I/O tasks. */ X- rp->p_map[T].mem_len = VERY_BIG; X- rp->p_map[T].mem_phys = base_click; X- rp->p_map[D].mem_len = VERY_BIG; X- rp->p_map[D].mem_phys = base_click + sizes[0]; X- rp->p_map[S].mem_len = VERY_BIG; X- rp->p_map[S].mem_phys = base_click + sizes[0] + sizes[1]; X- rp->p_map[S].mem_vir = sizes[0] + sizes[1]; X- } else { X- /* MM, FS, and INIT. */ X- previous_base = proc[NR_TASKS + t - 1].p_map[S].mem_phys; X- rp->p_map[T].mem_len = sizes[2*t + 2]; X- rp->p_map[T].mem_phys = (t == 0 ? mm_base : previous_base); X- rp->p_map[D].mem_len = sizes[2*t + 3]; X- rp->p_map[D].mem_phys = rp->p_map[T].mem_phys + sizes[2*t + 2]; X- rp->p_map[S].mem_vir = sizes[2*t + 3]; X- rp->p_map[S].mem_phys = rp->p_map[D].mem_phys + sizes[2*t + 3]; X- } X- X- X #ifdef i8088 X rp->p_reg[CS_REG] = rp->p_map[T].mem_phys; X rp->p_reg[DS_REG] = rp->p_map[D].mem_phys; X--- 84,111 ---- X X old_state = lock(); /* we can't handle interrupts yet */ X base_click = BASE >> CLICK_SHIFT; X X for (ktsb = t_stack, t = -NR_TASKS, rp = &proc[0]; X rp <= &proc[NR_TASKS+LOW_USER]; rp++, t++) { X! /* Set up memory map for tasks and MM, FS, INIT. */ X! if (t < 0) { /* I/O tasks. */ X! copy(rp, argv[0], sizeof(struct proc)); X stack_size = tasktab[t+NR_TASKS].stksize; X ktsb += stack_size / sizeof (int); X rp->p_sp = ktsb; X rp->p_splimit = ktsb - (stack_size - SAFETY) / sizeof(int); X! } else { /* MM, FS, and INIT. */ X! copy(rp, argv[t+1], sizeof(struct proc)); X! /* rp->p_sp = INIT_SP;*/ X! rp->p_splimit = rp->p_sp; X! } X! X! for (i = 0; i < NR_REGS; i++) rp->p_reg[i] = 0100 * i; /* debugging */ X rp->p_pcpsw.pc = tasktab[t + NR_TASKS].initial_pc; X if (rp->p_pcpsw.pc != 0 || t >= 0) ready(rp); X rp->p_pcpsw.psw = INIT_PSW; X rp->p_flags = 0; X X #ifdef i8088 X rp->p_reg[CS_REG] = rp->p_map[T].mem_phys; X rp->p_reg[DS_REG] = rp->p_map[D].mem_phys; X*************** X*** 275,281 **** X unsigned vec[2]; X unsigned u; X phys_bytes phys_b; X- extern unsigned sizes[8]; X X /* Build the vector in the array 'vec'. */ X vec[0] = (unsigned) addr; X--- 255,260 ---- X*************** X*** 283,289 **** X u = (unsigned) vec; X X /* Copy the vector into place. */ X! phys_b = ( (phys_bytes) base_click + (phys_bytes) sizes[0]) << CLICK_SHIFT; X phys_b += u; X phys_copy(phys_b, (phys_bytes) vec_nr*4, (phys_bytes) 4); X } X--- 262,268 ---- X u = (unsigned) vec; X X /* Copy the vector into place. */ X! phys_b = proc[NR_TASKS + HARDWARE].p_map[D].mem_phys << CLICK_SHIFT; X phys_b += u; X phys_copy(phys_b, (phys_bytes) vec_nr*4, (phys_bytes) 4); X } X*************** X*** 300,302 **** X--- 279,292 ---- X PUBLIC dp8390_int(){} /* Ethernet interrupt */ X #endif X X+ /* X+ Intra-Segment Copy X+ X+ copy(destination, source, length) X+ */ X+ copy(d,s,l) X+ char *d, *s; X+ int l; X+ { X+ while(--l) *d++ = *s++; X+ } SHAR_EOF if test 5503 -ne "`wc -c < 'kernel/main.c.diff'`" then echo shar: error transmitting "'kernel/main.c.diff'" '(should have been 5503 characters)' fi fi # end of overwriting check echo shar: extracting "'fs/cache.c.diff'" '(662 characters)' if test -f 'fs/cache.c.diff' then echo shar: will not over-write existing file "'fs/cache.c.diff'" else sed 's/^X//' << \SHAR_EOF > 'fs/cache.c.diff' X*** /usr/src/minix/fs/cache.c Sat Aug 13 14:20:45 1988 X--- cache.c Tue Apr 18 11:31:22 1989 X*************** X*** 210,216 **** X err_code = ENOSPC; X major = (int) (sp->s_dev >> MAJOR) & BYTE; X minor = (int) (sp->s_dev >> MINOR) & BYTE; X! if (sp->s_dev == ROOT_DEV) X printf("No space on root device (RAM disk)\n"); X else X printf("No space on device %d/%d\n", major, minor); X--- 210,216 ---- X err_code = ENOSPC; X major = (int) (sp->s_dev >> MAJOR) & BYTE; X minor = (int) (sp->s_dev >> MINOR) & BYTE; X! if (sp->s_dev == root_dev) X printf("No space on root device (RAM disk)\n"); X else X printf("No space on device %d/%d\n", major, minor); SHAR_EOF if test 662 -ne "`wc -c < 'fs/cache.c.diff'`" then echo shar: error transmitting "'fs/cache.c.diff'" '(should have been 662 characters)' fi fi # end of overwriting check # End of shell archive exit 0