aboutsummaryrefslogtreecommitdiffstats
path: root/boot
diff options
context:
space:
mode:
authorLinus Benedict Torvalds <torvalds@klaava.Helsinki.FI>1991-11-04 00:00:00 +0000
committerNicolas Pitre <nico@cam.org>2007-08-19 14:19:01 -0400
commitbe068f1a017608faa9b4a0652686426df2e87689 (patch)
treefff959a22d75c4a82192c99f1b4caa26a236eafc /boot
parent8331b82c1ac6ebe96db75d5853b4329b1502d5d3 (diff)
downloadarchive-be068f1a017608faa9b4a0652686426df2e87689.tar.gz
Linux-0.10v0.10
[ Committer's note: official announcement and exact release date unknown. Some posts are included below to narrow the possible release date. There is a possibility that this version might not be pristine. Also this commit folds the 0.02 version which is apparently lost. ] <INSTALL-0.10> Warning: I have personally not done this the hard way, so I don't know what problems could surface. In general, this version is still meant for people with minix: they are more used to the system, and can do some things that DOS-based persons cannot. If you have only DOS, expect some troubles. As the version number suggests, this is still not the final product. This is a "fast hack", meant as a minimal guide to what you must do. I'll expand this as soon as people tell me what they have problems with etc etc. If somebody who has successfully installed the system wants to write something better, I'd be delighted. This guide stinks to high heaven. Installing Linux-0.10 on your system There are 5 major steps in installing linux on your system: 1 - BACK UP ANY IMPORTANT DATA. Linux accesses your hardware directly, and if your hardware differs from mine, you could be in for a nasty surprise. Doublecheck that your hardware is compatible: AT style harddisk, VGA controller. (If somebody has EGA, please tell me if the screen driver should happen to work) 2 - Make a file-system on your harddisk. This is easy if you have minix, but if you haven't got minix, you'll have to get the minix demo-disk from somewhere (plains.nodak.edu is one place), and use that. There should be a manual accompanying the demo-disk, and you had better read that carefully. Although this version of linux will boot up without minix, a knowledge of minix would help. Especially if you have never done any unix work, you'll be very confused. Making a filesystem means getting a empty partition (with DOS fdisk or similar), and using the 'mkfs /dev/hdX nnn' command to write out a empty file-system. 3 - copy the diskimages to two floppies. Again, under minix (or any unix), this is easy, as you can just do a simple 'dd' to a floppy, but from within MS-DOS this might be a bit trickier. 'debug' should be able to write diskettes directly, or you could get the sources to "raw-write" from the same place as you got the minix demo disk, and modify them to write out any disk image (or do they do that already?). NOTE! The floppies MUST be of the same type: even though the boot-image will fit nicely on a 360kB floppy, you have to write it to the same type of floppy as the root-image. That means a 1.2M or 1.44M floppy. The reason is that the floppy-type is determined at boot-time from the boot-floppy. Thus the same binary works on both 3.5" and 5.25" drives. 4 - boot up from floppy. This should be obvious. Having a floppy as root-device isn't very fast (especially on a machine with less than 6MB total ram -> small buffer cache), but it works (I hope). Test the programs on the root-floppy (cat mkdir etc). 5 - Mount the harddisk partition (I do it on /user: ie 'mount /dev/hdX /user'), and copy the file system over to the new partition. The following is a example of how to do this: $ cd /user $ mkdir usr $ for i in bin etc usr/bin usr/root mtools > do > mkdir $i > cp `ls -A /$i` $i > done $ mkdir dev $ cd dev $ for i in 0 1 2 3 4 5 6 7 8 9 > do > mknod 'hd'$i b 3 $i > done $ mknod tty c 5 0 $ mknod tty0 c 4 0 $ mknod tty1 c 4 1 $ mknod tty2 c 4 2 You should now have a filesystem you could boot from. Play around a bit, try to get aquainted with the new system. Log out when you've had enough. 6 - Changing the boot-diskette use your new harddisk partition as root. The root device to be used for linux is encoded in a word at offset 508 in the boot image. Normally this is 0, meaning that the root is to be the same type of floppy as was used in the boot process. This can be changed to whatever you like. Use a short program like the one at the end to change the word (I assume everybody has access to some kind of C compiler, be it under dos or unix). You can then write out the new bootdisk, and boot from it, now using the harddisk as root (much faster). Once you have successfully done that you might want to install additional programs (gcc etc) by reading them from a dos-floppy with 'mcopy'. Linus (torvalds@kruuna.helsinki.fi) ------ example program: use 'a.out < oldboot > newboot' ---- #include <unistd.h> char tmp[512]; void main(void) { int i; if (512 != read(0,tmp,512)) exit(1); if (0xAA55 != *((unsigned short *)(tmp+510))) exit(2); *((unsigned short *)(tmp+508)) = NEW_DEV; if (512 != write(1,tmp,512)) exit(3); while ((i=read(0,tmp,512)) > 0) if (i != write(1,tmp,i)) exit(4); exit(0); } ------- Devices: Harddisks: 0x301 - /dev/hd1 - first partition on first drive ... 0x304 - /dev/hd2 - fourth partition on first drive 0x306 - /dev/hd1 - first partition on second drive ... 0x309 - /dev/hd2 - fourth partition on second drive 0x300 - /dev/hd0 - the whole first drive. BE CAREFUL 0x305 - /dev/hd5 - the whole second drive. BE CAREFUL Floppies: 0x208 - 1.2M in A 0x209 - 1.2M in B 0x21C - 1.44M in A 0x21D - 1.44M in B ----- From: torvalds@klaava.Helsinki.FI (Linus Benedict Torvalds) Newsgroups: comp.os.minix Subject: Free minix-like kernel sources for 386-AT Keywords: 386, preliminary version Message-ID: <1991Oct5.054106.4647@klaava.Helsinki.FI> Date: 5 Oct 91 05:41:06 GMT Organization: University of Helsinki Do you pine for the nice days of minix-1.1, when men were men and wrote their own device drivers? Are you without a nice project and just dying to cut your teeth on a OS you can try to modify for your needs? Are you finding it frustrating when everything works on minix? No more all- nighters to get a nifty program working? Then this post might be just for you :-) As I mentioned a month(?) ago, I'm working on a free version of a minix-lookalike for AT-386 computers. It has finally reached the stage where it's even usable (though may not be depending on what you want), and I am willing to put out the sources for wider distribution. It is just version 0.02 (+1 (very small) patch already), but I've successfully run bash/gcc/gnu-make/gnu-sed/compress etc under it. Sources for this pet project of mine can be found at nic.funet.fi (128.214.6.100) in the directory /pub/OS/Linux. The directory also contains some README-file and a couple of binaries to work under linux (bash, update and gcc, what more can you ask for :-). Full kernel source is provided, as no minix code has been used. Library sources are only partially free, so that cannot be distributed currently. The system is able to compile "as-is" and has been known to work. Heh. Sources to the binaries (bash and gcc) can be found at the same place in /pub/gnu. ALERT! WARNING! NOTE! These sources still need minix-386 to be compiled (and gcc-1.40, possibly 1.37.1, haven't tested), and you need minix to set it up if you want to run it, so it is not yet a standalone system for those of you without minix. I'm working on it. You also need to be something of a hacker to set it up (?), so for those hoping for an alternative to minix-386, please ignore me. It is currently meant for hackers interested in operating systems and 386's with access to minix. The system needs an AT-compatible harddisk (IDE is fine) and EGA/VGA. If you are still interested, please ftp the README/RELNOTES, and/or mail me for additional info. I can (well, almost) hear you asking yourselves "why?". Hurd will be out in a year (or two, or next month, who knows), and I've already got minix. This is a program for hackers by a hacker. I've enjouyed doing it, and somebody might enjoy looking at it and even modifying it for their own needs. It is still small enough to understand, use and modify, and I'm looking forward to any comments you might have. I'm also interested in hearing from anybody who has written any of the utilities/library functions for minix. If your efforts are freely distributable (under copyright or even public domain), I'd like to hear from you, so I can add them to the system. I'm using Earl Chews estdio right now (thanks for a nice and working system Earl), and similar works will be very wellcome. Your (C)'s will of course be left intact. Drop me a line if you are willing to let me use your code. Linus ----- From: torvalds@klaava.Helsinki.FI (Linus Benedict Torvalds) Newsgroups: comp.os.minix Subject: Re: [comp.os.minix] Free minix-like kernel sources for 386-AT Summary: Still only ftp Message-ID: <1991Oct31.101252.13981@klaava.Helsinki.FI> Date: 31 Oct 91 10:12:52 GMT References: <3255@cluster.cs.su.oz.au> <AA7ig3fuR5@inzer.demos.su> Organization: University of Helsinki In article <AA7ig3fuR5@inzer.demos.su> moroz@inzer.demos.su writes: >chrisa@extro.ucc.su.OZ.AU (C. G. Albone) writes: >>Hello all.. >> I missed the original posting, so could someone please tell me >>how I may obtain the sources. > And me too !!!!!!!!!!!!!! > Also, are them available via e-mail (mail server or smth), as I'm >in the former Soviet Union and can't do any FTP. Ok, as I've gotten quite a few questions, I guess I'd better follow up again. Linux is currently ONLY available via ftp from nic.funet.fi, directory /pub/OS/Linux. As the sources change rather rapidly (next release due out this weekend after I have tested some more), it is also currently impractical to make them available from other places. There is a mail-server possibility fron nic, but I think it's still in testing (you could try mailing "mailserver@nic.funet.fi" with "help" in the body, but I don't know if it will work). Linux is a full kernel that has so far worked on a number (5-10?) of at-386 (and one 486 as far as I know). It supports GNU cc (gcc), bash and some other free stuff. It is currently more of a hackers kernel (and minix-386 is needed, but that will change with this weeks release), and the current version number is 0.03 (next is 0.10 I think). Good things about linux: - it's free, full source, and I try to correct bugs you find. - it's a bit faster than minix, I think. - uses paging for memory management (not to disk yet) - multithreaded fs (but then you can get patches to minix that do similar stuff) - mostly full termios and vt100-console. - most things easy to port (easier than to minix). Bad points: - ONLY 386/486 - early versions: there might be lots of bugs, and you might need to port/hack things to work. - minix is recommended even for the upcoming version that doesn't absolutely need it. - currently only VGA (EGA?) support, limited keyboard drivers (US and Finnish) etc You can mail me for more info. "finger torvalds@kruuna.helsinki.fi" might tell you something too. Linus (torvalds@kruuna.helsinki.fi) ----- Date: Thu, 7 Nov 91 14:19:23 -0500 To: linux-activists-mtg@tsx-11.MIT.EDU From: Robert Lund <rml@bighorn.uswest.com> Reply-To: tytso@Athena.MIT.EDU Hello, I have installed Linux 0.10 using the minix demo to build the root file system on a hd partition. I couldn't figure out how to use the mtools commands to get gccbin, utils, etc. from DOS to linux but I did discover an alternate approach that might prove useful to others. I happen to have a 1.44 drive as my A drive so ubder linux I did mknod /dev/PS0 B 2 28 Next, I formated a 1.44 floppy under DOS. Then, I uncompressed the tar files that I wanted to get from DOS to linux (I actually uncompressed under UNIX but I assume that a 16 bit uncompress utility under DOS would work). Then, I used the rawrite command available with the minix demo to dump a tar file, e.g. gccbin.tar, to the 1.44 floppy in the A drive (back under DOS again) Next, I booted Linux and did tar -xvf /dev/PS0 and lo and behold, it worked; tar read the raw device and successfully extracted the files. Hope this helps someone. Bob Lund
Diffstat (limited to 'boot')
-rw-r--r--boot/boot.s329
-rw-r--r--boot/bootsect.s254
-rw-r--r--boot/head.s85
-rw-r--r--boot/setup.s215
4 files changed, 536 insertions, 347 deletions
diff --git a/boot/boot.s b/boot/boot.s
deleted file mode 100644
index e19bbd2..0000000
--- a/boot/boot.s
+++ /dev/null
@@ -1,329 +0,0 @@
-|
-| boot.s
-|
-| boot.s is loaded at 0x7c00 by the bios-startup routines, and moves itself
-| out of the way to address 0x90000, and jumps there.
-|
-| It then loads the system at 0x10000, using BIOS interrupts. Thereafter
-| it disables all interrupts, moves the system down to 0x0000, changes
-| to protected mode, and calls the start of system. System then must
-| RE-initialize the protected mode in it's own tables, and enable
-| interrupts as needed.
-|
-| NOTE! currently system is at most 8*65536 bytes long. This should be no
-| problem, even in the future. I want to keep it simple. This 512 kB
-| kernel size should be enough - in fact more would mean we'd have to move
-| not just these start-up routines, but also do something about the cache-
-| memory (block IO devices). The area left over in the lower 640 kB is meant
-| for these. No other memory is assumed to be "physical", ie all memory
-| over 1Mb is demand-paging. All addresses under 1Mb are guaranteed to match
-| their physical addresses.
-|
-| NOTE1 abouve is no longer valid in it's entirety. cache-memory is allocated
-| above the 1Mb mark as well as below. Otherwise it is mainly correct.
-|
-| NOTE 2! The boot disk type must be set at compile-time, by setting
-| the following equ. Having the boot-up procedure hunt for the right
-| disk type is severe brain-damage.
-| The loader has been made as simple as possible (had to, to get it
-| in 512 bytes with the code to move to protected mode), and continuos
-| read errors will result in a unbreakable loop. Reboot by hand. It
-| loads pretty fast by getting whole sectors at a time whenever possible.
-
-| 1.44Mb disks:
-sectors = 18
-| 1.2Mb disks:
-| sectors = 15
-| 720kB disks:
-| sectors = 9
-
-.globl begtext, begdata, begbss, endtext, enddata, endbss
-.text
-begtext:
-.data
-begdata:
-.bss
-begbss:
-.text
-
-BOOTSEG = 0x07c0
-INITSEG = 0x9000
-SYSSEG = 0x1000 | system loaded at 0x10000 (65536).
-ENDSEG = SYSSEG + SYSSIZE
-
-entry start
-start:
- mov ax,#BOOTSEG
- mov ds,ax
- mov ax,#INITSEG
- mov es,ax
- mov cx,#256
- sub si,si
- sub di,di
- rep
- movw
- jmpi go,INITSEG
-go: mov ax,cs
- mov ds,ax
- mov es,ax
- mov ss,ax
- mov sp,#0x400 | arbitrary value >>512
-
- mov ah,#0x03 | read cursor pos
- xor bh,bh
- int 0x10
-
- mov cx,#24
- mov bx,#0x0007 | page 0, attribute 7 (normal)
- mov bp,#msg1
- mov ax,#0x1301 | write string, move cursor
- int 0x10
-
-| ok, we've written the message, now
-| we want to load the system (at 0x10000)
-
- mov ax,#SYSSEG
- mov es,ax | segment of 0x010000
- call read_it
- call kill_motor
-
-| if the read went well we get current cursor position ans save it for
-| posterity.
-
- mov ah,#0x03 | read cursor pos
- xor bh,bh
- int 0x10 | save it in known place, con_init fetches
- mov [510],dx | it from 0x90510.
-
-| now we want to move to protected mode ...
-
- cli | no interrupts allowed !
-
-| first we move the system to it's rightful place
-
- mov ax,#0x0000
- cld | 'direction'=0, movs moves forward
-do_move:
- mov es,ax | destination segment
- add ax,#0x1000
- cmp ax,#0x9000
- jz end_move
- mov ds,ax | source segment
- sub di,di
- sub si,si
- mov cx,#0x8000
- rep
- movsw
- j do_move
-
-| then we load the segment descriptors
-
-end_move:
-
- mov ax,cs | right, forgot this at first. didn't work :-)
- mov ds,ax
- lidt idt_48 | load idt with 0,0
- lgdt gdt_48 | load gdt with whatever appropriate
-
-| that was painless, now we enable A20
-
- call empty_8042
- mov al,#0xD1 | command write
- out #0x64,al
- call empty_8042
- mov al,#0xDF | A20 on
- out #0x60,al
- call empty_8042
-
-| well, that went ok, I hope. Now we have to reprogram the interrupts :-(
-| we put them right after the intel-reserved hardware interrupts, at
-| int 0x20-0x2F. There they won't mess up anything. Sadly IBM really
-| messed this up with the original PC, and they haven't been able to
-| rectify it afterwards. Thus the bios puts interrupts at 0x08-0x0f,
-| which is used for the internal hardware interrupts as well. We just
-| have to reprogram the 8259's, and it isn't fun.
-
- mov al,#0x11 | initialization sequence
- out #0x20,al | send it to 8259A-1
- .word 0x00eb,0x00eb | jmp $+2, jmp $+2
- out #0xA0,al | and to 8259A-2
- .word 0x00eb,0x00eb
- mov al,#0x20 | start of hardware int's (0x20)
- out #0x21,al
- .word 0x00eb,0x00eb
- mov al,#0x28 | start of hardware int's 2 (0x28)
- out #0xA1,al
- .word 0x00eb,0x00eb
- mov al,#0x04 | 8259-1 is master
- out #0x21,al
- .word 0x00eb,0x00eb
- mov al,#0x02 | 8259-2 is slave
- out #0xA1,al
- .word 0x00eb,0x00eb
- mov al,#0x01 | 8086 mode for both
- out #0x21,al
- .word 0x00eb,0x00eb
- out #0xA1,al
- .word 0x00eb,0x00eb
- mov al,#0xFF | mask off all interrupts for now
- out #0x21,al
- .word 0x00eb,0x00eb
- out #0xA1,al
-
-| well, that certainly wasn't fun :-(. Hopefully it works, and we don't
-| need no steenking BIOS anyway (except for the initial loading :-).
-| The BIOS-routine wants lots of unnecessary data, and it's less
-| "interesting" anyway. This is how REAL programmers do it.
-|
-| Well, now's the time to actually move into protected mode. To make
-| things as simple as possible, we do no register set-up or anything,
-| we let the gnu-compiled 32-bit programs do that. We just jump to
-| absolute address 0x00000, in 32-bit protected mode.
-
- mov ax,#0x0001 | protected mode (PE) bit
- lmsw ax | This is it!
- jmpi 0,8 | jmp offset 0 of segment 8 (cs)
-
-| This routine checks that the keyboard command queue is empty
-| No timeout is used - if this hangs there is something wrong with
-| the machine, and we probably couldn't proceed anyway.
-empty_8042:
- .word 0x00eb,0x00eb
- in al,#0x64 | 8042 status port
- test al,#2 | is input buffer full?
- jnz empty_8042 | yes - loop
- ret
-
-| This routine loads the system at address 0x10000, making sure
-| no 64kB boundaries are crossed. We try to load it as fast as
-| possible, loading whole tracks whenever we can.
-|
-| in: es - starting address segment (normally 0x1000)
-|
-| This routine has to be recompiled to fit another drive type,
-| just change the "sectors" variable at the start of the file
-| (originally 18, for a 1.44Mb drive)
-|
-sread: .word 1 | sectors read of current track
-head: .word 0 | current head
-track: .word 0 | current track
-read_it:
- mov ax,es
- test ax,#0x0fff
-die: jne die | es must be at 64kB boundary
- xor bx,bx | bx is starting address within segment
-rp_read:
- mov ax,es
- cmp ax,#ENDSEG | have we loaded all yet?
- jb ok1_read
- ret
-ok1_read:
- mov ax,#sectors
- sub ax,sread
- mov cx,ax
- shl cx,#9
- add cx,bx
- jnc ok2_read
- je ok2_read
- xor ax,ax
- sub ax,bx
- shr ax,#9
-ok2_read:
- call read_track
- mov cx,ax
- add ax,sread
- cmp ax,#sectors
- jne ok3_read
- mov ax,#1
- sub ax,head
- jne ok4_read
- inc track
-ok4_read:
- mov head,ax
- xor ax,ax
-ok3_read:
- mov sread,ax
- shl cx,#9
- add bx,cx
- jnc rp_read
- mov ax,es
- add ax,#0x1000
- mov es,ax
- xor bx,bx
- jmp rp_read
-
-read_track:
- push ax
- push bx
- push cx
- push dx
- mov dx,track
- mov cx,sread
- inc cx
- mov ch,dl
- mov dx,head
- mov dh,dl
- mov dl,#0
- and dx,#0x0100
- mov ah,#2
- int 0x13
- jc bad_rt
- pop dx
- pop cx
- pop bx
- pop ax
- ret
-bad_rt: mov ax,#0
- mov dx,#0
- int 0x13
- pop dx
- pop cx
- pop bx
- pop ax
- jmp read_track
-
-/*
- * This procedure turns off the floppy drive motor, so
- * that we enter the kernel in a known state, and
- * don't have to worry about it later.
- */
-kill_motor:
- push dx
- mov dx,#0x3f2
- mov al,#0
- outb
- pop dx
- ret
-
-gdt:
- .word 0,0,0,0 | dummy
-
- .word 0x07FF | 8Mb - limit=2047 (2048*4096=8Mb)
- .word 0x0000 | base address=0
- .word 0x9A00 | code read/exec
- .word 0x00C0 | granularity=4096, 386
-
- .word 0x07FF | 8Mb - limit=2047 (2048*4096=8Mb)
- .word 0x0000 | base address=0
- .word 0x9200 | data read/write
- .word 0x00C0 | granularity=4096, 386
-
-idt_48:
- .word 0 | idt limit=0
- .word 0,0 | idt base=0L
-
-gdt_48:
- .word 0x800 | gdt limit=2048, 256 GDT entries
- .word gdt,0x9 | gdt base = 0X9xxxx
-
-msg1:
- .byte 13,10
- .ascii "Loading system ..."
- .byte 13,10,13,10
-
-.text
-endtext:
-.data
-enddata:
-.bss
-endbss:
diff --git a/boot/bootsect.s b/boot/bootsect.s
new file mode 100644
index 0000000..77fbb04
--- /dev/null
+++ b/boot/bootsect.s
@@ -0,0 +1,254 @@
+|
+| bootsect.s (C) 1991 Linus Torvalds
+|
+| bootsect.s is loaded at 0x7c00 by the bios-startup routines, and moves
+| iself out of the way to address 0x90000, and jumps there.
+|
+| It then loads 'setup' directly after itself (0x90200), and the system
+| at 0x10000, using BIOS interrupts.
+|
+| NOTE! currently system is at most 8*65536 bytes long. This should be no
+| problem, even in the future. I want to keep it simple. This 512 kB
+| kernel size should be enough, especially as this doesn't contain the
+| buffer cache as in minix
+|
+| The loader has been made as simple as possible, and continuos
+| read errors will result in a unbreakable loop. Reboot by hand. It
+| loads pretty fast by getting whole sectors at a time whenever possible.
+
+.globl begtext, begdata, begbss, endtext, enddata, endbss
+.text
+begtext:
+.data
+begdata:
+.bss
+begbss:
+.text
+
+SETUPLEN = 4 | nr of setup-sectors
+BOOTSEG = 0x07c0 | original address of boot-sector
+INITSEG = 0x9000 | we move boot here - out of the way
+SETUPSEG = 0x9020 | setup starts here
+SYSSEG = 0x1000 | system loaded at 0x10000 (65536).
+ENDSEG = SYSSEG + SYSSIZE | where to stop loading
+
+| ROOT_DEV: 0x000 - same type of floppy as boot.
+| 0x301 - first partition on first drive etc
+ROOT_DEV = 0 | 0x306
+
+entry start
+start:
+ mov ax,#BOOTSEG
+ mov ds,ax
+ mov ax,#INITSEG
+ mov es,ax
+ mov cx,#256
+ sub si,si
+ sub di,di
+ rep
+ movw
+ jmpi go,INITSEG
+go: mov ax,cs
+ mov ds,ax
+ mov es,ax
+| put stack at 0x9ff00.
+ mov ss,ax
+ mov sp,#0xFF00 | arbitrary value >>512
+
+| load the setup-sectors directly after the bootblock.
+| Note that 'es' is already set up.
+
+load_setup:
+ mov dx,#0x0000 | drive 0, head 0
+ mov cx,#0x0002 | sector 2, track 0
+ mov bx,#0x0200 | address = 512, in INITSEG
+ mov ax,#0x0200+SETUPLEN | service 2, nr of sectors
+ int 0x13 | read it
+ jnc ok_load_setup | ok - continue
+ mov dx,#0x0000
+ mov ax,#0x0000 | reset the diskette
+ int 0x13
+ j load_setup
+
+ok_load_setup:
+
+| Get disk drive parameters, specifically nr of sectors/track
+
+ mov dl,#0x00
+ mov ax,#0x0800 | AH=8 is get drive parameters
+ int 0x13
+ mov ch,#0x00
+ seg cs
+ mov sectors,cx
+ mov ax,#INITSEG
+ mov es,ax
+
+| Print some inane message
+
+ mov ah,#0x03 | read cursor pos
+ xor bh,bh
+ int 0x10
+
+ mov cx,#24
+ mov bx,#0x0007 | page 0, attribute 7 (normal)
+ mov bp,#msg1
+ mov ax,#0x1301 | write string, move cursor
+ int 0x10
+
+| ok, we've written the message, now
+| we want to load the system (at 0x10000)
+
+ mov ax,#SYSSEG
+ mov es,ax | segment of 0x010000
+ call read_it
+ call kill_motor
+
+| After that we check which root-device to use. If the device is
+| defined (!= 0), nothing is done and the given device is used.
+| Otherwise, either /dev/PS0 (2,28) or /dev/at0 (2,8), depending
+| on the number of sectors that the BIOS reports currently.
+
+ seg cs
+ mov ax,root_dev
+ cmp ax,#0
+ jne root_defined
+ seg cs
+ mov bx,sectors
+ mov ax,#0x0208 | /dev/ps0 - 1.2Mb
+ cmp bx,#15
+ je root_defined
+ mov ax,#0x021c | /dev/PS0 - 1.44Mb
+ cmp bx,#18
+ je root_defined
+undef_root:
+ jmp undef_root
+root_defined:
+ seg cs
+ mov root_dev,ax
+
+| after that (everyting loaded), we jump to
+| the setup-routine loaded directly after
+| the bootblock:
+
+ jmpi 0,SETUPSEG
+
+| This routine loads the system at address 0x10000, making sure
+| no 64kB boundaries are crossed. We try to load it as fast as
+| possible, loading whole tracks whenever we can.
+|
+| in: es - starting address segment (normally 0x1000)
+|
+sread: .word 1+SETUPLEN | sectors read of current track
+head: .word 0 | current head
+track: .word 0 | current track
+
+read_it:
+ mov ax,es
+ test ax,#0x0fff
+die: jne die | es must be at 64kB boundary
+ xor bx,bx | bx is starting address within segment
+rp_read:
+ mov ax,es
+ cmp ax,#ENDSEG | have we loaded all yet?
+ jb ok1_read
+ ret
+ok1_read:
+ seg cs
+ mov ax,sectors
+ sub ax,sread
+ mov cx,ax
+ shl cx,#9
+ add cx,bx
+ jnc ok2_read
+ je ok2_read
+ xor ax,ax
+ sub ax,bx
+ shr ax,#9
+ok2_read:
+ call read_track
+ mov cx,ax
+ add ax,sread
+ seg cs
+ cmp ax,sectors
+ jne ok3_read
+ mov ax,#1
+ sub ax,head
+ jne ok4_read
+ inc track
+ok4_read:
+ mov head,ax
+ xor ax,ax
+ok3_read:
+ mov sread,ax
+ shl cx,#9
+ add bx,cx
+ jnc rp_read
+ mov ax,es
+ add ax,#0x1000
+ mov es,ax
+ xor bx,bx
+ jmp rp_read
+
+read_track:
+ push ax
+ push bx
+ push cx
+ push dx
+ mov dx,track
+ mov cx,sread
+ inc cx
+ mov ch,dl
+ mov dx,head
+ mov dh,dl
+ mov dl,#0
+ and dx,#0x0100
+ mov ah,#2
+ int 0x13
+ jc bad_rt
+ pop dx
+ pop cx
+ pop bx
+ pop ax
+ ret
+bad_rt: mov ax,#0
+ mov dx,#0
+ int 0x13
+ pop dx
+ pop cx
+ pop bx
+ pop ax
+ jmp read_track
+
+/*
+ * This procedure turns off the floppy drive motor, so
+ * that we enter the kernel in a known state, and
+ * don't have to worry about it later.
+ */
+kill_motor:
+ push dx
+ mov dx,#0x3f2
+ mov al,#0
+ outb
+ pop dx
+ ret
+
+sectors:
+ .word 0
+
+msg1:
+ .byte 13,10
+ .ascii "Loading system ..."
+ .byte 13,10,13,10
+
+.org 508
+root_dev:
+ .word ROOT_DEV
+boot_flag:
+ .word 0xAA55
+
+.text
+endtext:
+.data
+enddata:
+.bss
+endbss:
diff --git a/boot/head.s b/boot/head.s
index c008ba8..2c4970a 100644
--- a/boot/head.s
+++ b/boot/head.s
@@ -1,4 +1,10 @@
/*
+ * linux/boot/head.s
+ *
+ * (C) 1991 Linus Torvalds
+ */
+
+/*
* head.s contains the 32-bit startup code.
*
* NOTE!!! Startup happens at absolute address 0x00000000, which is also where
@@ -6,7 +12,7 @@
* the page directory.
*/
.text
-.globl _idt,_gdt,_pg_dir
+.globl _idt,_gdt,_pg_dir,_tmp_floppy_area
_pg_dir:
startup_32:
movl $0x10,%eax
@@ -25,14 +31,22 @@ startup_32:
lss _stack_start,%esp
xorl %eax,%eax
1: incl %eax # check that A20 really IS enabled
- movl %eax,0x000000
+ movl %eax,0x000000 # loop forever if it isn't
cmpl %eax,0x100000
je 1b
+/*
+ * NOTE! 486 should set bit 16, to check for write-protect in supervisor
+ * mode. Then it would be unnecessary with the "verify_area()"-calls.
+ * 486 users probably want to set the NE (#5) bit also, so as to use
+ * int 16 for math errors.
+ */
movl %cr0,%eax # check math chip
andl $0x80000011,%eax # Save PG,ET,PE
+/* "orl $0x10020,%eax" here for 486 might be good */
+ orl $2,%eax # set MP
testl $0x10,%eax
jne 1f # ET is set - 387 is present
- orl $4,%eax # else set emulate bit
+ xorl $6,%eax # else reset MP and set EM
1: movl %eax,%cr0
jmp after_page_tables
@@ -78,6 +92,11 @@ setup_gdt:
lgdt gdt_descr
ret
+/*
+ * I put the kernel page tables right after the page directory,
+ * using 4 of them to span 16 Mb of physical memory. People with
+ * more than 16MB will have to expand this.
+ */
.org 0x1000
pg0:
@@ -85,11 +104,20 @@ pg0:
pg1:
.org 0x3000
-pg2: # This is not used yet, but if you
- # want to expand past 8 Mb, you'll have
- # to use it.
+pg2:
.org 0x4000
+pg3:
+
+.org 0x5000
+/*
+ * tmp_floppy_area is used by the floppy-driver when DMA cannot
+ * reach to a buffer-block. It needs to be aligned, so that it isn't
+ * on a 64kB border.
+ */
+_tmp_floppy_area:
+ .fill 1024,1,0
+
after_page_tables:
pushl $0 # These are the parameters to main :-)
pushl $0
@@ -102,11 +130,30 @@ L6:
# just in case, we know what happens.
/* This is the default interrupt "handler" :-) */
+int_msg:
+ .asciz "Unknown interrupt\n\r"
.align 2
ignore_int:
- incb 0xb8000+160 # put something on the screen
- movb $2,0xb8000+161 # so that we know something
- iret # happened
+ pushl %eax
+ pushl %ecx
+ pushl %edx
+ push %ds
+ push %es
+ push %fs
+ movl $0x10,%eax
+ mov %ax,%ds
+ mov %ax,%es
+ mov %ax,%fs
+ pushl $int_msg
+ call _printk
+ popl %eax
+ pop %fs
+ pop %es
+ pop %ds
+ popl %edx
+ popl %ecx
+ popl %eax
+ iret
/*
@@ -114,7 +161,7 @@ ignore_int:
*
* This routine sets up paging by setting the page bit
* in cr0. The page tables are set up, identity-mapping
- * the first 8MB. The pager assumes that no illegal
+ * the first 16MB. The pager assumes that no illegal
* addresses are produced (ie >4Mb on a 4Mb machine).
*
* NOTE! Although all physical memory should be identity
@@ -124,25 +171,27 @@ ignore_int:
* will be mapped to some other place - mm keeps track of
* that.
*
- * For those with more memory than 8 Mb - tough luck. I've
+ * For those with more memory than 16 Mb - tough luck. I've
* not got it, why should you :-) The source is here. Change
* it. (Seriously - it shouldn't be too difficult. Mostly
- * change some constants etc. I left it at 8Mb, as my machine
+ * change some constants etc. I left it at 16Mb, as my machine
* even cannot be extended past that (ok, but it was cheap :-)
* I've tried to show which constants to change by having
- * some kind of marker at them (search for "8Mb"), but I
+ * some kind of marker at them (search for "16Mb"), but I
* won't guarantee that's all :-( )
*/
.align 2
setup_paging:
- movl $1024*3,%ecx
+ movl $1024*5,%ecx /* 5 pages - pg_dir+4 page tables */
xorl %eax,%eax
xorl %edi,%edi /* pg_dir is at 0x000 */
cld;rep;stosl
movl $pg0+7,_pg_dir /* set present bit/user r/w */
movl $pg1+7,_pg_dir+4 /* --------- " " --------- */
- movl $pg1+4092,%edi
- movl $0x7ff007,%eax /* 8Mb - 4096 + 7 (r/w user,p) */
+ movl $pg2+7,_pg_dir+8 /* --------- " " --------- */
+ movl $pg3+7,_pg_dir+12 /* --------- " " --------- */
+ movl $pg3+4092,%edi
+ movl $0xfff007,%eax /* 16Mb - 4096 + 7 (r/w user,p) */
std
1: stosl /* fill pages backwards - more efficient :-) */
subl $0x1000,%eax
@@ -169,7 +218,7 @@ gdt_descr:
_idt: .fill 256,8,0 # idt is uninitialized
_gdt: .quad 0x0000000000000000 /* NULL descriptor */
- .quad 0x00c09a00000007ff /* 8Mb */
- .quad 0x00c09200000007ff /* 8Mb */
+ .quad 0x00c09a0000000fff /* 16Mb */
+ .quad 0x00c0920000000fff /* 16Mb */
.quad 0x0000000000000000 /* TEMPORARY - don't use */
.fill 252,8,0 /* space for LDT's and TSS's etc */
diff --git a/boot/setup.s b/boot/setup.s
new file mode 100644
index 0000000..5034a65
--- /dev/null
+++ b/boot/setup.s
@@ -0,0 +1,215 @@
+|
+| setup.s (C) 1991 Linus Torvalds
+|
+| setup.s is responsible for getting the system data from the BIOS,
+| and putting them into the appropriate places in system memory.
+| both setup.s and system has been loaded by the bootblock.
+|
+| This code asks the bios for memory/disk/other parameters, and
+| puts them in a "safe" place: 0x90000-0x901FF, ie where the
+| boot-block used to be. It is then up to the protected mode
+| system to read them from there before the area is overwritten
+| for buffer-blocks.
+|
+
+| NOTE! These had better be the same as in bootsect.s!
+
+INITSEG = 0x9000 | we move boot here - out of the way
+SYSSEG = 0x1000 | system loaded at 0x10000 (65536).
+SETUPSEG = 0x9020 | this is the current segment
+
+.globl begtext, begdata, begbss, endtext, enddata, endbss
+.text
+begtext:
+.data
+begdata:
+.bss
+begbss:
+.text
+
+entry start
+start:
+
+| ok, the read went well so we get current cursor position and save it for
+| posterity.
+
+ mov ax,#INITSEG | this is done in bootsect already, but...
+ mov ds,ax
+ mov ah,#0x03 | read cursor pos
+ xor bh,bh
+ int 0x10 | save it in known place, con_init fetches
+ mov [0],dx | it from 0x90000.
+
+| Get memory size (extended mem, kB)
+
+ mov ah,#0x88
+ int 0x15
+ mov [2],ax
+
+| Get hd0 data
+
+ mov ax,#0x0000
+ mov ds,ax
+ lds si,[4*0x41]
+ mov ax,#INITSEG
+ mov es,ax
+ mov di,#0x0080
+ mov cx,#0x10
+ rep
+ movsb
+
+| Get hd1 data
+
+ mov ax,#0x0000
+ mov ds,ax
+ lds si,[4*0x46]
+ mov ax,#INITSEG
+ mov es,ax
+ mov di,#0x0090
+ mov cx,#0x10
+ rep
+ movsb
+
+| Check that there IS a hd1 :-)
+
+ mov ax,#0x01500
+ mov dl,#0x81
+ int 0x13
+ jc no_disk1
+ cmp ah,#3
+ je is_disk1
+no_disk1:
+ mov ax,#INITSEG
+ mov es,ax
+ mov di,#0x0090
+ mov cx,#0x10
+ mov ax,#0x00
+ rep
+ stosb
+is_disk1:
+
+| now we want to move to protected mode ...
+
+ cli | no interrupts allowed !
+
+| first we move the system to it's rightful place
+
+ mov ax,#0x0000
+ cld | 'direction'=0, movs moves forward
+do_move:
+ mov es,ax | destination segment
+ add ax,#0x1000
+ cmp ax,#0x9000
+ jz end_move
+ mov ds,ax | source segment
+ sub di,di
+ sub si,si
+ mov cx,#0x8000
+ rep
+ movsw
+ jmp do_move
+
+| then we load the segment descriptors
+
+end_move:
+ mov ax,#SETUPSEG | right, forgot this at first. didn't work :-)
+ mov ds,ax
+ lidt idt_48 | load idt with 0,0
+ lgdt gdt_48 | load gdt with whatever appropriate
+
+| that was painless, now we enable A20
+
+ call empty_8042
+ mov al,#0xD1 | command write
+ out #0x64,al
+ call empty_8042
+ mov al,#0xDF | A20 on
+ out #0x60,al
+ call empty_8042
+
+| well, that went ok, I hope. Now we have to reprogram the interrupts :-(
+| we put them right after the intel-reserved hardware interrupts, at
+| int 0x20-0x2F. There they won't mess up anything. Sadly IBM really
+| messed this up with the original PC, and they haven't been able to
+| rectify it afterwards. Thus the bios puts interrupts at 0x08-0x0f,
+| which is used for the internal hardware interrupts as well. We just
+| have to reprogram the 8259's, and it isn't fun.
+
+ mov al,#0x11 | initialization sequence
+ out #0x20,al | send it to 8259A-1
+ .word 0x00eb,0x00eb | jmp $+2, jmp $+2
+ out #0xA0,al | and to 8259A-2
+ .word 0x00eb,0x00eb
+ mov al,#0x20 | start of hardware int's (0x20)
+ out #0x21,al
+ .word 0x00eb,0x00eb
+ mov al,#0x28 | start of hardware int's 2 (0x28)
+ out #0xA1,al
+ .word 0x00eb,0x00eb
+ mov al,#0x04 | 8259-1 is master
+ out #0x21,al
+ .word 0x00eb,0x00eb
+ mov al,#0x02 | 8259-2 is slave
+ out #0xA1,al
+ .word 0x00eb,0x00eb
+ mov al,#0x01 | 8086 mode for both
+ out #0x21,al
+ .word 0x00eb,0x00eb
+ out #0xA1,al
+ .word 0x00eb,0x00eb
+ mov al,#0xFF | mask off all interrupts for now
+ out #0x21,al
+ .word 0x00eb,0x00eb
+ out #0xA1,al
+
+| well, that certainly wasn't fun :-(. Hopefully it works, and we don't
+| need no steenking BIOS anyway (except for the initial loading :-).
+| The BIOS-routine wants lots of unnecessary data, and it's less
+| "interesting" anyway. This is how REAL programmers do it.
+|
+| Well, now's the time to actually move into protected mode. To make
+| things as simple as possible, we do no register set-up or anything,
+| we let the gnu-compiled 32-bit programs do that. We just jump to
+| absolute address 0x00000, in 32-bit protected mode.
+
+ mov ax,#0x0001 | protected mode (PE) bit
+ lmsw ax | This is it!
+ jmpi 0,8 | jmp offset 0 of segment 8 (cs)
+
+| This routine checks that the keyboard command queue is empty
+| No timeout is used - if this hangs there is something wrong with
+| the machine, and we probably couldn't proceed anyway.
+empty_8042:
+ .word 0x00eb,0x00eb
+ in al,#0x64 | 8042 status port
+ test al,#2 | is input buffer full?
+ jnz empty_8042 | yes - loop
+ ret
+
+gdt:
+ .word 0,0,0,0 | dummy
+
+ .word 0x07FF | 8Mb - limit=2047 (2048*4096=8Mb)
+ .word 0x0000 | base address=0
+ .word 0x9A00 | code read/exec
+ .word 0x00C0 | granularity=4096, 386
+
+ .word 0x07FF | 8Mb - limit=2047 (2048*4096=8Mb)
+ .word 0x0000 | base address=0
+ .word 0x9200 | data read/write
+ .word 0x00C0 | granularity=4096, 386
+
+idt_48:
+ .word 0 | idt limit=0
+ .word 0,0 | idt base=0L
+
+gdt_48:
+ .word 0x800 | gdt limit=2048, 256 GDT entries
+ .word 512+gdt,0x9 | gdt base = 0X9xxxx
+
+.text
+endtext:
+.data
+enddata:
+.bss
+endbss: