ast@cs.vu.nl (Andy Tanenbaum) (08/16/87)
Although MINIX 1.2 is now been sent off and I don't plan on 1.3 until 1988, I did make some changes to 1.2 that will eventually be in 1.3 and which are worth passing on. They essentially incorporate Larry Hubble's patches of several months ago, but in a more flexible way. The changes have the following effect. When the initial menu comes up, you can insert the root file system floppy, and it is read in, as before. However, if you leave the boot diskette in drive 0 and hit the = key, MINIX reads the "superblock" of the boot diskette, sees that it is not a valid file system, and loads the root file system from a dedicated hard disk partition containing a bit-for-bit image of the root file system. The hard disk partition to use is determined by RAM_IMAGE in fs/main.c. This fix is compatible with the old way of booting, allows the hard disk to be used, but also allows floppies to override the hard disk. The other change is only applicable to AT's, but the binary will work on a PC as well. If the root file system is 256K or more (either read from the floppy or from the hard disk, it doesn't matter), the root file system is placed in extended memory (above 1 MB), otherwise it goes in "low" core. The current distributions use either 240K or 116K root devices, and these will continue to go in low core. While this distinction is somewhat heuristic, it seems unlikely that anyone will want more than 255K of root file system in a computer with only 640K of memory. It seems equally unlikely that anyone with extended memory will have less than 256K of it. In any event, the constant MAX_CRD (MAXimum Core Ram Disk) can be changed if need be. The advantage of these two fixes is that the binary remains compatible for PCs, ATs, machines with root file systems on hard disk, those without, machines with extended memory and those without. It is all determined dynamically. Needless to say, when making a root file system to be used in extended RAM, be sure to set the root file system size <= to the size of the extended memory. If you try to put a 1M RAM disk in a 512K extended memory, it won't work (you didn't expect that really, did you)? There are five files affected: kernel/main.c kernel/klib88.s kernel/memory.c fs/main.c mm/main.c If there are problems, please post them. The diff listings below were made with Erik Baalbergen's diff program and the new files can be generated with his fix program, e.g. fix klib88.s klib88.diff >newklib88.s THE DIFFS ARE RELATIVE TO 1.2, NOT 1.1, SO WHEN YOU RUN FIX, USE THE 1.2 KLIB88.S, NOT THE 1.1 VERSION, (DITTO FOR THE OTHER FILES). Andy Tanenbaum (ast@cs.vu.nl) --------------- : This is a shar archive. Extract with sh, not csh. : This archive ends with exit, so do not worry about trailing junk. : --------------------------- cut here -------------------------- PATH=/bin:/usr/bin echo Extracting \f\s\:\m\a\i\n\.\d\i\f\f sed 's/^X//' > \f\s\:\m\a\i\n\.\d\i\f\f << '+ END-OF-FILE '\f\s\:\m\a\i\n\.\d\i\f\f X27c27,30 X< #define MAX_RAM 512 /* maxium RAM disk size in blocks */ X--- X> #define MAX_RAM 16384 /* maximum RAM disk size in blocks */ X> #define RAM_IMAGE (dev_nr)0x303 /* major-minor dev where root image is kept */ X> #define EM_ORIGIN 0x100000 /* origin of extended memory RAM disk on AT */ X> #define MAX_CRD 255 /* if root fs > MAX_CRD, use extended mem */ X225c228,230 X< phys_clicks ram_clicks, init_org, init_text_clicks, init_data_clicks; X--- X> dev_nr root_device; X> phys_clicks ram_clicks, init_org, init_text_clicks, init_data_clicks; X> long base; X233,239c238,256 X< X< /* Get size of RAM disk by reading root file system's super block */ X< bp = get_block(BOOT_DEV, SUPER_BLOCK, NORMAL); /* get RAM super block */ X< copy(super_block, bp->b_data, sizeof(struct super_block)); X< sp = &super_block[0]; X< if (sp->s_magic != SUPER_MAGIC) X< panic("Diskette in drive 0 is not root file system", NO_NUM); X--- X> base = (long) init_org + (long) init_text_clicks + (long) init_data_clicks; X> base = base << CLICK_SHIFT; X> X> /* Get size of RAM disk by reading root file system's super block. X> * First read block 0 from the floppy. If this is a valid file system, use X> * it as the root image, otherwise try the hard disk (RAM_IMAGE). X> */ X> root_device = BOOT_DEV; /* try floppy disk first */ X> bp = get_block(root_device, SUPER_BLOCK, NORMAL); /* get RAM super block */ X> copy(super_block, bp->b_data, sizeof(struct super_block)); X> sp = &super_block[0]; X> if (sp->s_magic != SUPER_MAGIC) { X> root_device = RAM_IMAGE; X> bp = get_block(root_device, SUPER_BLOCK, NORMAL); /* get RAM super block */ X> copy(super_block, bp->b_data, sizeof(struct super_block)); X> sp = &super_block[0]; X> } X> if (sp->s_magic != SUPER_MAGIC) X> panic("Invalid root file system", NO_NUM); X244a262,272 X> /* There are two possibilities now (by convention): X> * count < MAX_CRD ==> RAM disk is in core X> * count >=MAX_CRD ==> RAM disk is in extended memory (AT only) X> * In the latter case, tell MM that RAM disk size is 0 and tell the ram disk X> * driver than the device begins at 1MB. X> */ X> if (count > MAX_CRD) { X> ram_clicks = 0; /* MM does not have to allocate any core */ X> base = EM_ORIGIN; /* tell RAM disk driver RAM disk origin */ X> } X> X258,259c286 X< m1.POSITION = (long) init_org + (long) init_text_clicks + init_data_clicks; X< m1.POSITION = m1.POSITION << CLICK_SHIFT; X--- X> m1.POSITION = base; X264,266c291,295 X< printf("Loading RAM disk from root diskette. Loaded: 0K "); X< for (i = 0; i < count; i++) { X< bp = get_block(BOOT_DEV, (block_nr) i, NORMAL); X--- X> if (ram_clicks == 0) X> printf("RAM disk of %d blocks is in extended memory\n\n", count); X> printf("Loading RAM disk. Loaded: 0K "); X> for (i = 0; i < count; i++) { X> bp = get_block(root_device, (block_nr) i, NORMAL); X273,276c302,307 X< if (k_loaded % 5 == 0) printf("\b\b\b\b\b%3DK %c", k_loaded, 0); X< } X< X< printf("\rRAM disk loaded. Please remove root diskette. \n\n"); X--- X> if (k_loaded % 5 == 0) printf("\b\b\b\b\b\b%4DK %c", k_loaded, 0); X> } X> if (root_device == BOOT_DEV) X> printf("\rRAM disk loaded. Please remove root diskette. \n\n"); X> else X> printf("\rRAM disk loaded. \n\n"); + END-OF-FILE fs:main.diff chmod 'u=rw,g=r,o=r' \f\s\:\m\a\i\n\.\d\i\f\f set `sum \f\s\:\m\a\i\n\.\d\i\f\f` sum=$1 case $sum in 52706) :;; *) echo 'Bad sum in '\f\s\:\m\a\i\n\.\d\i\f\f >&2 esac echo Extracting \k\e\r\n\:\m\a\i\n\.\d\i\f\f sed 's/^X//' > \k\e\r\n\:\m\a\i\n\.\d\i\f\f << '+ END-OF-FILE '\k\e\r\n\:\m\a\i\n\.\d\i\f\f X29a30 X> #define EM_VEC 0x15 /* vector for extended memory BIOS calls */ X128,131c129,134 X< if (pc_at) X< set_vec(AT_WINI_VECTOR, wini_int, base_click); X< else X< set_vec(XT_WINI_VECTOR, wini_int, base_click); X--- X> if (pc_at) { X> set_vec(AT_WINI_VECTOR, wini_int, base_click); X> phys_copy(phys_b + 4L*EM_VEC, 4L*EM_VEC, 4L); /* extended mem vec */ X> } else { X> set_vec(XT_WINI_VECTOR, wini_int, base_click); X> } + END-OF-FILE kern:main.diff chmod 'u=rw,g=r,o=r' \k\e\r\n\:\m\a\i\n\.\d\i\f\f set `sum \k\e\r\n\:\m\a\i\n\.\d\i\f\f` sum=$1 case $sum in 48322) :;; *) echo 'Bad sum in '\k\e\r\n\:\m\a\i\n\.\d\i\f\f >&2 esac echo Extracting \k\l\i\b\8\8\.\d\i\f\f sed 's/^X//' > \k\l\i\b\8\8\.\d\i\f\f << '+ END-OF-FILE '\k\l\i\b\8\8\.\d\i\f\f X20a21 X> | em_xfer: read or write AT extended memory using the BIOS X25c26 X< .globl _wreboot, _dma_read, _dma_write X--- X> .globl _wreboot, _dma_read, _dma_write, _em_xfer X495,561c496,692 X< X< X< X< |*===========================================================================* X< |* reboot & wreboot * X< |*===========================================================================* X< | This code reboots the PC X< X< _reboot: X< cli | disable interrupts X< mov ax,#0x20 | re-enable interrupt controller X< out 0x20 X< call resvec | restore the vectors in low core X< mov ax,#0x40 X< mov ds,ax X< mov ax,#0x1234 X< mov 0x72,ax X< mov ax,#0xFFFF X< mov ds,ax X< mov ax,3 X< push ax X< mov ax,1 X< push ax X< reti X< X< _wreboot: X< cli | disable interrupts X< mov ax,#0x20 | re-enable interrupt controller X< out 0x20 X< call resvec | restore the vectors in low core X< xor ax,ax | wait for character before continuing X< int 0x16 | get char X< mov ax,#0x40 X< mov ds,ax X< mov ax,#0x1234 X< mov 0x72,ax X< mov ax,#0xFFFF X< mov ds,ax X< mov ax,3 X< push ax X< mov ax,1 X< push ax X< reti X< X< | Restore the interrupt vectors in low core. X< resvec: cld X< mov cx,#2*71 X< mov si,#_vec_table X< xor di,di X< mov es,di X< rep X< movw X< ret X< X< | Some library routines use exit, so this label is needed. X< | Actual calls to exit cannot occur in the kernel. X< .globl _exit X< _exit: sti X< jmp _exit X< X< .data X< lockvar: .word 0 | place to store flags for lock()/restore() X< vidlock: .word 0 | dummy variable for use with lock prefix X< splimit: .word 0 | stack limit for current task (kernel only) X< tmp: .word 0 | count of bytes already copied X< stkoverrun: .asciz "Kernel stack overrun, task = " X< _vec_table: .zerow 142 | storage for interrupt vectors X--- X> |=========================================================================== X> | em_xfer X> |=========================================================================== X> | X> | This file contains one routine which transfers words between user memory X> | and extended memory on an AT or clone. A BIOS call (INT 15h, Func 87h) X> | is used to accomplish the transfer. The BIOS call is "faked" by pushing X> | the processor flags on the stack and then doing a far call to the actual X> | BIOS location. An actual INT 15h would get a MINIX complaint from an X> | unexpected trap. X> | X> | NOTE: WARNING: CAUTION: ... X> | Before using this routine, you must find your BIOS address for INT 15h. X> | The debug command "d 0:54 57" will give you the segment and address of X> | the BIOS call. On my machine this generates: X> | 0000:0050 59 F8 00 F0 Y... X> | These values are then plugged into the two strange ".word xxxx" lines X> | near the end of this routine. They correspond to offset=0xf859 and X> | seg=0xf000. The offset is the first two bytes and the segment is the X> | last two bytes (Note the byte swap). X> | X> | This particular BIOS routine runs with interrupts off since the 80286 X> | must be placed in protected mode to access the memory above 1 Mbyte. X> | So there should be no problems using the BIOS call. X> | X> .text X> gdt: | Begin global descriptor table X> | Dummy descriptor X> .word 0 | segment length (limit) X> .word 0 | bits 15-0 of physical address X> .byte 0 | bits 23-16 of physical address X> .byte 0 | access rights byte X> .word 0 | reserved X> | descriptor for GDT itself X> .word 0 | segment length (limit) X> .word 0 | bits 15-0 of physical address X> .byte 0 | bits 23-16 of physical address X> .byte 0 | access rights byte X> .word 0 | reserved X> src: | source descriptor X> srcsz: .word 0 | segment length (limit) X> srcl: .word 0 | bits 15-0 of physical address X> srch: .byte 0 | bits 23-16 of physical address X> .byte 0x93 | access rights byte X> .word 0 | reserved X> tgt: | target descriptor X> tgtsz: .word 0 | segment length (limit) X> tgtl: .word 0 | bits 15-0 of physical address X> tgth: .byte 0 | bits 23-16 of physical address X> .byte 0x93 | access rights byte X> .word 0 | reserved X> | BIOS CS descriptor X> .word 0 | segment length (limit) X> .word 0 | bits 15-0 of physical address X> .byte 0 | bits 23-16 of physical address X> .byte 0 | access rights byte X> .word 0 | reserved X> | stack segment descriptor X> .word 0 | segment length (limit) X> .word 0 | bits 15-0 of physical address X> .byte 0 | bits 23-16 of physical address X> .byte 0 | access rights byte X> .word 0 | reserved X> X> | X> | X> | Execute a transfer between user memory and extended memory. X> | X> | status = em_xfer(source, dest, count); X> | X> | Where: X> | status => return code (0 => OK) X> | source => Physical source address (32-bit) X> | dest => Physical destination address (32-bit) X> | count => Number of words to transfer X> | X> | X> | X> _em_xfer: X> X> push bp | Save registers X> mov bp,sp X> push si X> push es X> push cx X> | X> | Pick up source and destination addresses and update descriptor tables X> | X> mov ax,4(bp) X> seg cs X> mov srcl,ax X> mov ax,6(bp) X> seg cs X> movb srch,al X> mov ax,8(bp) X> seg cs X> mov tgtl,ax X> mov ax,10(bp) X> seg cs X> movb tgth,al X> | X> | Update descriptor table segment limits X> | X> mov cx,12(bp) X> mov ax,cx X> add ax,ax X> seg cs X> mov tgtsz,ax X> seg cs X> mov srcsz,ax X> | X> | Now do actual DOS call X> | X> push cs X> pop es X> seg cs X> mov si,#gdt X> movb ah,#0x87 X> pushf X> int 0x15 | Do a far call to BIOS routine X> | X> | All done, return to caller. X> | X> X> pop cx | restore registers X> pop es X> pop si X> mov sp,bp X> pop bp X> ret X> X> X> X> |*===========================================================================* X> |* reboot & wreboot * X> |*===========================================================================* X> | This code reboots the PC X> X> _reboot: X> cli | disable interrupts X> mov ax,#0x20 | re-enable interrupt controller X> out 0x20 X> call resvec | restore the vectors in low core X> mov ax,#0x40 X> mov ds,ax X> mov ax,#0x1234 X> mov 0x72,ax X> mov ax,#0xFFFF X> mov ds,ax X> mov ax,3 X> push ax X> mov ax,1 X> push ax X> reti X> X> _wreboot: X> cli | disable interrupts X> mov ax,#0x20 | re-enable interrupt controller X> out 0x20 X> call resvec | restore the vectors in low core X> xor ax,ax | wait for character before continuing X> int 0x16 | get char X> mov ax,#0x40 X> mov ds,ax X> mov ax,#0x1234 X> mov 0x72,ax X> mov ax,#0xFFFF X> mov ds,ax X> mov ax,3 X> push ax X> mov ax,1 X> push ax X> reti X> X> | Restore the interrupt vectors in low core. X> resvec: cld X> mov cx,#2*71 X> mov si,#_vec_table X> xor di,di X> mov es,di X> rep X> movw X> ret X> X> | Some library routines use exit, so this label is needed. X> | Actual calls to exit cannot occur in the kernel. X> .globl _exit X> _exit: sti X> jmp _exit X> X> .data X> lockvar: .word 0 | place to store flags for lock()/restore() X> vidlock: .word 0 | dummy variable for use with lock prefix X> splimit: .word 0 | stack limit for current task (kernel only) X> tmp: .word 0 | count of bytes already copied X> stkoverrun: .asciz "Kernel stack overrun, task = " X> _vec_table: .zerow 142 | storage for interrupt vectors + END-OF-FILE klib88.diff chmod 'u=rw,g=r,o=r' \k\l\i\b\8\8\.\d\i\f\f set `sum \k\l\i\b\8\8\.\d\i\f\f` sum=$1 case $sum in 16428) :;; *) echo 'Bad sum in '\k\l\i\b\8\8\.\d\i\f\f >&2 esac echo Extracting \m\e\m\o\r\y\.\d\i\f\f sed 's/^X//' > \m\e\m\o\r\y\.\d\i\f\f << '+ END-OF-FILE '\m\e\m\o\r\y\.\d\i\f\f X35c35 X< X--- X> #define EM_ORIGIN 0x100000 /* origin of extended memory on the AT */ X93c93 X< int device, count; X--- X> int device, count, words, status; X116,120c116,133 X< /* Copy the data. */ X< if (m_ptr->m_type == DISK_READ) X< phys_copy(mem_phys, user_phys, (long) count); X< else X< phys_copy(user_phys, mem_phys, (long) count); X--- X> /* Copy the data. Origin above EM_ORIGIN means AT extended memory */ X> if (ram_origin[device] < EM_ORIGIN) { X> /* Ordinary case. RAM disk is below 640K. */ X> if (m_ptr->m_type == DISK_READ) X> phys_copy(mem_phys, user_phys, (long) count); X> else X> phys_copy(user_phys, mem_phys, (long) count); X> } else { X> /* AT with RAM disk in extended memory (above 1 MB). */ X> if (count & 1) panic("RAM disk got odd byte count\n", m_ptr); X> words = count >> 1; /* # words is half # bytes */ X> if (m_ptr->m_type == DISK_READ) { X> status = em_xfer(mem_phys, user_phys, words); X> } else { X> status = em_xfer(user_phys, mem_phys, words); X> } X> if (status != 0) count = -1; X> } + END-OF-FILE memory.diff chmod 'u=rw,g=r,o=r' \m\e\m\o\r\y\.\d\i\f\f set `sum \m\e\m\o\r\y\.\d\i\f\f` sum=$1 case $sum in 12743) :;; *) echo 'Bad sum in '\m\e\m\o\r\y\.\d\i\f\f >&2 esac echo Extracting \m\m\:\m\a\i\n\.\d\i\f\f sed 's/^X//' > \m\m\:\m\a\i\n\.\d\i\f\f << '+ END-OF-FILE '\m\m\:\m\a\i\n\.\d\i\f\f X166,168c166,168 X< printf("Memory size = %dK ", mem1); X< printf("MINIX = %dK ", mem2); X< printf("RAM disk = %dK ", mem3); X--- X> printf("Memory size = %3dK ", mem1); X> printf("MINIX = %3dK ", mem2); X> printf("RAM disk = %3dK ", mem3); + END-OF-FILE mm:main.diff chmod 'u=rw,g=r,o=r' \m\m\:\m\a\i\n\.\d\i\f\f set `sum \m\m\:\m\a\i\n\.\d\i\f\f` sum=$1 case $sum in 25416) :;; *) echo 'Bad sum in '\m\m\:\m\a\i\n\.\d\i\f\f >&2 esac exit 0