The origins of all things--linux on the starting process (1) __linux

Source: Internet
Author: User

Important NOTE: The main information of this article is from Dr. Zhao's "Linux kernel full annotation" book, the other part of the information from the Internet. This article should be a form of reading experience, but also hope to provide some information for the enthusiasts.

Before reading the source code, the operating system is always mysterious, always think the operating system is very mysterious things. In fact, for a programmer with a certain programming foundation and system knowledge, the operating system is not something that can not be expected. The ultimate goal of the operating system is just a layer of coordination between the application level and the hardware level, which may be a bit one-sided, but it should be easier to read the code in such an idea.
As a result of the development to now, Linux has been able to support a variety of platforms, this article is mainly aimed at an "old" version of--0.11--to discuss, this is Dr. Zhao in the "Linux kernel full annotation" in a book to do the use of the version, because I am also a beginner, do not dare to I will occasionally add some of my own understanding of 2.6 in the course of the following analysis.

Linux startup process mainly involves three source files: Bootsect.s Head.s SETUP.S
In the 0.11 release, these three files are located in the linux/boot/directory, and in the latest version, because of the diversity of supported platforms, we can find them under linux/arch/i386/.
The starting process for the I386 architecture is basically this: the machine first goes into real mode and executes from the address 0xffff0, which is typically in the BIOS, so the BIOS program does some self-test work on the machine. After that, the machine that is normally booted from the disk reads the launcher into the memory 0x07c00 location from the first sector of the bootable device. and jump to the place to continue. The first area of content that is read from disk is actually the binary code of BOOTSECT.S after compilation, that is to say, The system starts with BOOTSECT.S in the sense of the OS. Before viewing the BOOTSECT.S source code, let's look at how the operating system is going to work after the opportunity:
Linus is not satisfied with the location of the BOOTSECT.S, in fact it is not a good place. 0X07C00 is a fairly low position, Linus expects the actual kernel portion of the operating system to start from 0x00000 and occupy the lowest position in the entire memory area. The contents of the boot program will only be run once when the machine is started, and will not be used in the future. Now, Bootsect.s is in 0X07C00 's position, apparently "blocking" the operating system's "road". You know, even the 0.11 version of Linux, the length of the kernel (which should be more accurately referred to as the system module, rather than the Linux kernel in its broadest sense). This concept goes down and jumps there to execute. Also reached the 0x3000, and in 2.6, is to reach the 0x7f00 of many. So, naturally, the first thing we have to do is move the BOOTSECT.S position, move it to a higher address, and jump there to execute it.
After the migration, the second thing Bootsect.s needs to do is to load the following code in. This part of the code is SETUP.S, and its binary encoding should be stored in the second sector of the boot device, with a length of 4 sectors. Load this program is not as difficult as imagined, the program through the int 0x13 to complete. The SETUP.S will be placed in the memory area immediately following the BOOTSECT.S.
Now that the position, Bootsect.s and SETUP.S have been placed in the desired position, what needs to be done is to put the main part of the operating system, the real system module load, which will be placed on the lowest bit of memory, both 0x0000 the starting position. Linux uses a seemingly more "winding" approach: Linux first places the system module in the 0x10000 position. And after the BOOTSECT.S runs, the program counter jumps to the SETUP.S range, and the system moves to the low To the 0x00000. I am also a new contact with Linux soon, this can not be solved. Because at this time the Bootsect has been moved to the 0x90000 place, both the system module should be placed in the 0x00000 should not affect the operation of the systems, Why not just write it down to the lowest level? Personal conjecture because the system placed the interrupt vector table in the 0x00000 at the BIOS initial session level, this vector table may still need to be used at this stage. It's just a guess, if anyone knows the rationale, please tell me the real reason. My e-mail: J.h_zhang@163.com, not very grateful.
To this location, Bootsect.s's task is basically completed, in version 0.11, Bootsect.s finally to determine the root device number. Then is to jump to the setupseg, both 0x9020 address, run immediately after the Bootsect.s binary code, the previous load came in Setup.s.

Let's take a look at Bootsect.s's source code to see how the operating system at the beginning of the form. It should be noted that the machine is still in real mode. There will be some of my comments, please refer to "Linux kernel full comment" For those who wish to see Dr. Zhao's detailed comments. In addition, To make it easier to differentiate, I add a comment with two "!" Start with a "!" note in the program that originally existed. Beginning:
!
! Sys_size is the number of clicks (bytes) to be loaded.
! 0x3000 is 0x30000 bytes = 196kB, more than enough to current
! Versions of Linux
!
Syssize = 0x3000
!
! Bootsect.s (C) 1991 Linus Torvalds
!
! Bootsect.s is loaded in 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 is no
! Problem, even in the future. I want to keep it simple. This MB
! Kernel size should is 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'll result in a unbreakable loop. Reboot by hand. It
! Loads pretty fast by getting whole sectors in a time whenever possible.

. Globl Begtext, Begdata, BEGBSS, Endtext, Enddata, ENDBSS
. text
Begtext:
. Data
Begdata:
. BSS
BEGBSS:
. text

!! Defines a number of symbols that are used to mark various constants during system startup.
!! Like what:
!! BOOTSEG the instruction address for the first run when the system starts
!! INITSEG is the address that Linux wants to move Bootsect.s to
!! Setupseg the head address of the SETUP.S immediately after Bootsect.s
!! Sysseg to temporarily store the header address of the system module while the BOOTSECT.S is running, and the system moves to 0x00000 at SETUP.S
!! The address is present as a base address, that is, in real mode, when address addressing is used, the address is first shifted to the left 4 digits, and then the offset is added.
!! So, "bootseg = 0x07c0" actually means the 0X07C00 address.
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 the drive etc
Root_dev = 0x306

Entry _start
!! The beginning of the program, the origin of everything. ^_^
_start:
!! The purpose of the paragraph is to move Bootsect to Initseg (0x90000)
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!! Already migrated, jump to high address to continue running.
!! Initseg is the base address. Go is an offset.
!! After the migration, the relative updates the values of some registers.
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 which ' es ' is already set up.

!! The code starting from Load_setup is to read SETUP.S into memory, in a position that follows Bootsect.
!! Use 0x13 interrupts to complete this feature.
Load_setup:
MOV dx, #0x0000! Drive 0, head 0.
MOV cx, #0x0002! Sector 2, Track 0
MOV bx, #0x0200! Address = 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

!! SETUP.S has been load completed, read some parameters about the drive.
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 and now
! We want to load the system (at 0x10000)
!! The starting point here is to load the system module to the 0x10000 location.

mov ax, #SYSSEG
MOV Es,ax! Segment of 0x010000
Call Read_it!! This is the process call, Read_it specifically implemented below.
Call Kill_motor

! After this we check which root-device to use. If the device is
! Defined (!= 0), the "is" and the given device is used.
! Otherwise, EITHER/DEV/PS0 (2,28) or/dev/at0 (2,8), depending
! On the number of sectors the BIOS reports currently.
!! The root device number is then checked.
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 this (everyting loaded), we jump to
! The Setup-routine loaded directly after
! The Bootblock:

Jmpi 0,setupseg!! Jump into the SETUP.S, so far, Bootsect's task is complete.

! This is 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 to 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
! * 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:

On the 2.6 Note: The above we see the source code is in the 0.11 version of Linux, in the 2.6 version, BOOTSECT.S has changed a lot. First, the above code is written using the Intel 80x86 assembly code, but the GNU ASM (gas) used in 2.6 Written. The bigger difference is that after 2.6, Linux no longer supports booting directly from disk, but must boot with grub or LILO, so we find that the BOOTSECT.S in the 2.6 code basically doesn't work.

The above is my initial understanding of Linux startup, only after the completion of the BOOTSECT.S, after entering SETUP.S, I will be in the second story. And then I want enough time and power to tell the whole Linux startup process, Even after that, there are a number of other aspects that can be involved. To this location, Linux only completes a small part of the work, even the system module in the memory location is not correct, the initialization is not completed. My understanding of the role of BOOTSECT.S is that it exists as an interface to the hardware mechanism of the operating system, and it makes a slightly more cluttered memory location, and gets the parameters of the drive and reads the contents of the disk into memory. Bootsect.s must be present in the first sector of the disk so that the BIOS can find it.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.