From 4f670845ff9ab6c48bcb5f7bf4d4ef6dc3c3064b Mon Sep 17 00:00:00 2001 From: manuel Date: Tue, 27 Mar 2012 11:51:08 +0200 Subject: reorganize file structure to match the upstream requirements --- pintos-progos/threads/loader.S | 263 ----------------------------------------- 1 file changed, 263 deletions(-) delete mode 100644 pintos-progos/threads/loader.S (limited to 'pintos-progos/threads/loader.S') diff --git a/pintos-progos/threads/loader.S b/pintos-progos/threads/loader.S deleted file mode 100644 index dd87ea1..0000000 --- a/pintos-progos/threads/loader.S +++ /dev/null @@ -1,263 +0,0 @@ -#include "threads/loader.h" - -#### Kernel loader. - -#### This code should be stored in the first sector of a hard disk. -#### When the BIOS runs, it loads this code at physical address -#### 0x7c00-0x7e00 (512 bytes) and jumps to the beginning of it, -#### in real mode. The loader loads the kernel into memory and jumps -#### to its entry point, which is the start function in start.S. -#### -#### The BIOS passes in the drive that the loader was read from as -#### DL, with floppy drives numbered 0x00, 0x01, ... and hard drives -#### numbered 0x80, 0x81, ... We want to support booting a kernel on -#### a different drive from the loader, so we don't take advantage of -#### this. - -# Runs in real mode, which is a 16-bit segment. - .code16 - -# Set up segment registers. -# Set stack to grow downward from 60 kB (after boot, the kernel -# continues to use this stack for its initial thread). - - sub %ax, %ax - mov %ax, %ds - mov %ax, %ss - mov $0xf000, %esp - -# Configure serial port so we can report progress without connected VGA. -# See [IntrList] for details. - sub %dx, %dx # Serial port 0. - mov $0xe3, %al # 9600 bps, N-8-1. - # AH is already 0 (Initialize Port). - int $0x14 # Destroys AX. - - call puts - .string "PiLo" - -#### Read the partition table on each system hard disk and scan for a -#### partition of type 0x20, which is the type that we use for a -#### Pintos kernel. -#### -#### Read [Partitions] for a description of the partition table format -#### that we parse. -#### -#### We print out status messages to show the disk and partition being -#### scanned, e.g. hda1234 as we scan four partitions on the first -#### hard disk. - - mov $0x80, %dl # Hard disk 0. -read_mbr: - sub %ebx, %ebx # Sector 0. - mov $0x2000, %ax # Use 0x20000 for buffer. - mov %ax, %es - call read_sector - jc no_such_drive - - # Print hd[a-z]. - call puts - .string " hd" - mov %dl, %al - add $'a' - 0x80, %al - call putc - - # Check for MBR signature--if not present, it's not a - # partitioned hard disk. - cmpw $0xaa55, %es:510 - jne next_drive - - mov $446, %si # Offset of partition table entry 1. - mov $'1', %al -check_partition: - # Is it an unused partition? - cmpl $0, %es:(%si) - je next_partition - - # Print [1-4]. - call putc - - # Is it a Pintos kernel partition? - cmpb $0x20, %es:4(%si) - jne next_partition - - # Is it a bootable partition? - cmpb $0x80, %es:(%si) - je load_kernel - -next_partition: - # No match for this partition, go on to the next one. - add $16, %si # Offset to next partition table entry. - inc %al - cmp $510, %si - jb check_partition - -next_drive: - # No match on this drive, go on to the next one. - inc %dl - jnc read_mbr - -no_such_drive: -no_boot_partition: - # Didn't find a Pintos kernel partition anywhere, give up. - call puts - .string "\rNot found\r" - - # Notify BIOS that boot failed. See [IntrList]. - int $0x18 - -#### We found a kernel. The kernel's drive is in DL. The partition -#### table entry for the kernel's partition is at ES:SI. Our job now -#### is to read the kernel from disk and jump to its start address. - -load_kernel: - call puts - .string "\rLoading" - - # Figure out number of sectors to read. A Pintos kernel is - # just an ELF format object, which doesn't have an - # easy-to-read field to identify its own size (see [ELF1]). - # But we limit Pintos kernels to 512 kB for other reasons, so - # it's easy enough to just read the entire contents of the - # partition or 512 kB from disk, whichever is smaller. - mov %es:12(%si), %ecx # EBP = number of sectors - cmp $1024, %ecx # Cap size at 512 kB - jbe 1f - mov $1024, %cx -1: - - mov %es:8(%si), %ebx # EBX = first sector - mov $0x2000, %ax # Start load address: 0x20000 - -next_sector: - # Read one sector into memory. - mov %ax, %es # ES:0000 -> load address - call read_sector - jc read_failed - - # Print '.' as progress indicator once every 16 sectors == 8 kB. - test $15, %bl - jnz 1f - call puts - .string "." -1: - - # Advance memory pointer and disk sector. - add $0x20, %ax - inc %bx - loop next_sector - - call puts - .string "\r" - -#### Transfer control to the kernel that we loaded. We read the start -#### address out of the ELF header (see [ELF1]) and convert it from a -#### 32-bit linear address into a 16:16 segment:offset address for -#### real mode, then jump to the converted address. The 80x86 doesn't -#### have an instruction to jump to an absolute segment:offset kept in -#### registers, so in fact we store the address in a temporary memory -#### location, then jump indirectly through that location. To save 4 -#### bytes in the loader, we reuse 4 bytes of the loader's code for -#### this temporary pointer. - - mov $0x2000, %ax - mov %ax, %es - mov %es:0x18, %dx - mov %dx, start - movw $0x2000, start + 2 - ljmp *start - -read_failed: -start: - # Disk sector read failed. - call puts -1: .string "\rBad read\r" - - # Notify BIOS that boot failed. See [IntrList]. - int $0x18 - -#### Print string subroutine. To save space in the loader, this -#### subroutine takes its null-terminated string argument from the -#### code stream just after the call, and then returns to the byte -#### just after the terminating null. This subroutine preserves all -#### general-purpose registers. - -puts: xchg %si, %ss:(%esp) - push %ax -next_char: - mov %cs:(%si), %al - inc %si - test %al, %al - jz 1f - call putc - jmp next_char -1: pop %ax - xchg %si, %ss:(%esp) - ret - -#### Character output subroutine. Prints the character in AL to the -#### VGA display and serial port 0, using BIOS services (see -#### [IntrList]). Preserves all general-purpose registers. -#### -#### If called upon to output a carriage return, this subroutine -#### automatically supplies the following line feed. - -putc: pusha - -1: sub %bh, %bh # Page 0. - mov $0x0e, %ah # Teletype output service. - int $0x10 - - mov $0x01, %ah # Serial port output service. - sub %dx, %dx # Serial port 0. -2: int $0x14 # Destroys AH. - test $0x80, %ah # Output timed out? - jz 3f - movw $0x9090, 2b # Turn "int $0x14" above into NOPs. - -3: - cmp $'\r', %al - jne popa_ret - mov $'\n', %al - jmp 1b - -#### Sector read subroutine. Takes a drive number in DL (0x80 = hard -#### disk 0, 0x81 = hard disk 1, ...) and a sector number in EBX, and -#### reads the specified sector into memory at ES:0000. Returns with -#### carry set on error, clear otherwise. Preserves all -#### general-purpose registers. - -read_sector: - pusha - sub %ax, %ax - push %ax # LBA sector number [48:63] - push %ax # LBA sector number [32:47] - push %ebx # LBA sector number [0:31] - push %es # Buffer segment - push %ax # Buffer offset (always 0) - push $1 # Number of sectors to read - push $16 # Packet size - mov $0x42, %ah # Extended read - mov %sp, %si # DS:SI -> packet - int $0x13 # Error code in CF - popa # Pop 16 bytes, preserve flags -popa_ret: - popa - ret # Error code still in CF - -#### Command-line arguments and their count. -#### This is written by the `pintos' utility and read by the kernel. -#### The loader itself does not do anything with the command line. - .org LOADER_ARG_CNT - LOADER_BASE - .fill LOADER_ARG_CNT_LEN, 1, 0 - - .org LOADER_ARGS - LOADER_BASE - .fill LOADER_ARGS_LEN, 1, 0 - -#### Partition table. - .org LOADER_PARTS - LOADER_BASE - .fill LOADER_PARTS_LEN, 1, 0 - -#### Boot-sector signature for BIOS inspection. - .org LOADER_SIG - LOADER_BASE - .word 0xaa55 -- cgit v1.2.3