Академический Документы
Профессиональный Документы
Культура Документы
POST
When a computer is switched on or reset, it runs through a series of diagnostics called POST -
Power-On Self-Test. This sequence culminates in locating a bootable device, such as a floppy,
cdrom or a harddisk in the order that the firmware is configured to.
The Bootsector
The first 512 bytes of a disk are known as the bootsector or Master Boot Record. The boot sector
is an area of the disk reserved for booting purposes. If the bootsector of a disk contains a valid boot
sector (the last word of the sector must contain the signature 0xAA55), then the disk is treated by
the BIOS as bootable.
To boot an operating system, the BIOS runtime searches for devices that are both active and
bootable in the order of preference defined by the complementary metal oxide semiconductor
(CMOS) settings. A boot device can be a floppy disk, a CD-ROM, a partition on a hard disk, a
device on the network, or even a USB flash memory stick.
Commonly, Linux is booted from a hard disk, where the Master Boot Record (MBR) contains the
primary boot loader. The MBR is a 512-byte sector, located in the first sector on the disk (sector 1
of cylinder 0, head 0). After the MBR is loaded into RAM, the BIOS yields control to it.
http://www.ibm.com/developerworks/library/l-linuxboot/index.html#resources
The great thing about GRUB is that it includes knowledge of Linux file systems. Instead of using
raw sectors on the disk, as LILO does, GRUB can load a Linux kernel from an ext2 or ext3 file
system. It does this by making the two-stage boot loader into a three-stage boot loader. Stage 1
(MBR) boots a stage 1.5 boot loader that understands the particular file system containing the Linux
kernel image. Examples include reiserfs_stage1_5 (to load from a Reiser journaling file
system) or e2fs_stage1_5 (to load from an ext2 or ext3 file system). When the stage 1.5 boot
loader is loaded and running, the stage 2 boot loader can be loaded.
With stage 2 loaded, GRUB can, upon request, display a list of available kernels (defined in
/etc/grub.conf, with soft links from /etc/grub/menu.lst and /etc/grub.conf).
You can select a kernel and even amend it with additional kernel parameters. Optionally, you can
use a command-line shell for greater manual control over the boot process.
With the second-stage boot loader in memory, the file system is consulted, and the default kernel
image and initrd image are loaded into memory. With the images ready, the stage 2 boot loader
invokes the kernel image.
Kernel
With the kernel image in memory and control given from the stage 2 boot loader, the kernel stage
begins. The kernel image isn't so much an executable kernel, but a compressed kernel image.
Typically this is a zImage (compressed image, less than 512KB) or a bzImage (big compressed
image, greater than 512KB), that has been previously compressed with zlib. At the head of this
kernel image is a routine that does some minimal amount of hardware setup and then decompresses
the kernel contained within the kernel image and places it into high memory. If an initial RAM disk
image is present, this routine moves it into memory and notes it for later use. The routine then calls
the kernel and the kernel boot begins.
When the bzImage (for an i386 image) is invoked, you begin at ./arch/i386/boot/head.S
in the start assembly routine (see Figure 3 for the major flow). This routine does some basic
hardware setup and invokes the startup_32 routine
in ./arch/i386/boot/compressed/head.S. This routine sets up a basic environment
(stack, etc.) and clears the Block Started by Symbol (BSS). The kernel is then decompressed
through a call to a C function called decompress_kernel (located
in ./arch/i386/boot/compressed/misc.c). When the kernel is decompressed into
memory, it is called. This is yet another startup_32 function, but this function is
in ./arch/i386/kernel/head.S.
In the new startup_32 function (also called the swapper or process 0), the page tables are
initialized and memory paging is enabled. The type of CPU is detected along with any optional
floating-point unit (FPU) and stored away for later use. The start_kernel function is then
invoked (init/main.c), which takes you to the non-architecture specific Linux kernel. This is,
in essence, the main function for the Linux kernel.
Memory Regions
Refer
http://www.brokenthorn.com/Resources/OSDev3.html
https://en.wikibooks.org/wiki/X86_Assembly/Bootloaders
http://viralpatel.net/taj/tutorial/hello_world_bootloader.php
http://wiki.osdev.org/Tutorials#Booting
http://www.ibm.com/developerworks/library/l-linuxboot/index.html#resources
http://mikeos.sourceforge.net/write-your-own-os.html
https://sourceforge.net/p/squeaknos/git/ci/bc73aeae09ef3ac8b1a9e708ba07589236b4bb15/tree/boot/
iso.template/boot/grub/stage2_eltorito
https://www.gnu.org/software/grub/manual/legacy/Making-a-GRUB-bootable-CD_002dROM.html
http://wiki.osdev.org/Bootable_El-Torito_CD_with_GRUB_Legacy
http://viralpatel.net/taj/tutorial/hello_world_bootloader.php
Steps for the lab
Download and install NASM from
http://www.osdever.net/downloads/assemblers/nasm-0.98.35-1.i386.rpm
sudo apt-get install nasm
Explanation:
[BITS 16]: Our code starts with [BITS 16] which is an assembler directive. This will tell
assembler that our code is a 16 bit code.
[ORG 0x7C00]: Then we have used [ORG 0x7C00] which tell assembler to assemble the
instructions from Origin 0x7C00. BIOS loads bootloader at physical address 0x7C00 hence we
have assemble our bootloader starting from that location.
JMP $: JMP at location $ means jumping to the same location. Thus this nothing but an infinite
loop. We just want to hang our code here.
TIMES 510 - ($ - $$) db 0: As bootloader is always of length 512 bytes, our code does
not fit in this size as its small. We need to use rest of memory and hence we clear it out using
TIMES directive. $ stands for start of instruction and $$ stands for start of program. Thus ($ - $$)
means length of our code.
DW 0xAA55: This is boot signature. This tells the BIOS that this is a valid bootloader. If bios does
not get 0x55 and 0xAA at the end of the bootloader than it will treat bootloader as invalid. Thus we
provide this two bytes at the end of our bootloader.
Compile the program
nasm firstBootLoader.asm -f bin -o boot.bin
Attach the floppy image to the Virtual machine and boot. You should see a blank screen
Once all the registers all filled with appropriate value, we can call interrupt.
MOV AL, 65
CALL PrintCharacter
JMP $ ;Infinite loop, hang it here.
HelloWorld db "Hello World. This is from the bootloader", 0x0d, 0x0a, 0x00
PrintHelloWorld:
mov si, HelloWorld
call PrintStr
ret
PrintStr:
push ax
mov ah, 0Eh
.loop:
lodsb
cmp al, 0x00
je .done
int 10h
jmp .loop
.done:
pop ax
ret
times 510-($-$$) db 0
dw 0xAA55
mkdir -p isofiles/boot/grub
Install a kernel
Get a kernel of your own choosing and copy it to wherever you like inside the isofiles folder.
Preferably it should be placed in the boot sub-folder. Now create a menu.lst file. This file
controls what menu entries GRUB should provide and how the kernels are booted. It must be placed
in the GRUB folder boot/grub and contain something like this:
Copy a compiled kernel from your machine – it will not work but explains how
default 0
#timeout 30
title My kernel
kernel /boot/vmlinuz-4.8.15-300.fc25.x86_64 # Edit it to the filename of your
kernel.
Design Review
https://www.cs.princeton.edu/courses/archive/fall12/cos318/projects/project1/
1.html#designreview
For this project, at your design review, we want you to write print_char and
print_string functions in assembly. The first outputs a single character to the
screen, and the second outputs a full string to the screen. Both should start
printing at the cursor and advance the cursor as a result. You may implement
these using any BIOS interrupts. Note that these are functions: they will be
called with call and return with ret, and they should save and restore any
modified registers. You may choose your own calling convention. The goal for
this part (what we're grading) is your understanding of the stack and using
interrupt calls. This is more important than getting the two functions to work
perfectly.
You should be able to describe:
• How to move the kernel from disk to memory
• Where to find it on disk
• Where to copy it in memory
• How to do the copying in assembly
• In what case must your bootloader be relocated?
• How to create the disk image
• Given an executable (ELF), show how to use the header info to find where the first
code segment begins
• Show how to determine where in the image file this segment must be placed.
• Where to write padding