PDA

View Full Version : توضیحات در مورد Boot Loader



reza10203045
جمعه 01 خرداد 1388, 14:04 عصر
سلام دوستان من توی یکی از تاپیک ها موضوعی را دیدم به اسم فرآیند بوت که توش یک مقاله بود .توی مقاله بعد توضیحات یک نمونه کدی نوشته شده بود با زبان اسمبلی من زیاد از ساختار برنامه نفهمیدم نه اینکه کد ها شو نفهمیدم چون من تا حدود کمی اسمبلی می دونم ولی با توضیحاتی که داده بود من درباره کدها زیاد حالی نشدم که روش کارش چه جوری اگه میشه در مورد boot loader و نحوه نوشتن اون کمک کنید
البته در مورد این کد که در بالا گفتم هم اگر میشود یکم توضیح بدید.

[BITS 16]
[ORG 0x7C00]
push cs
pop ds ;make sure ds=cs
mov ah,0
int 16h ;wait for any key
times 510-($-$$) db 0 ;Fill up the file with zeros
dw 0AA55h

خوب یک سوال اگر بوت لودر کارش بار کردن کرنل سیستم عامله کجای این کد این کار رو انجام میده من که نفهمیدم
چون من بعضی از بوت لودر ها رو نگاه کردم خیلی پیچیده تر از این بودند

Bootsector authoring by Gareth Owen
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-=- gaz@athene.co.uk -=-

Requirements
============
During this article I assume that you have good knowledge of the
assembly language and intel architecture.
If not, read an assembly tutorial, they aren't hard to find...

Start
=====

Creating your own bootsector is simpler than you may think,
the only requirement is that the bootsector is 512 bytes long, and at
offset 0x1FE (decimal=510), the word 0xAA55 is placed. This is the first
thing the BIOS does when the PC boots up, it first looks on the first
floppy drive at the first sector for 0xAA55 at the end, and if it finds it
then it loads it into memory, and starts executing it, otherwise it trys the
primary harddisk, and if that isn't found it just bombs out with an error.

You should place your boot sector at:
Sector 1
Cylinder 0
Head 0

I recommend you start playing about with floppys first instead of your hard disk
because the hard disk bootsector stores information about the file system if you
are running DOS/Windows, if you overrite that, then you have just lost your
hard disk contents :-)

The BIOS loads the bootsector at linear offset 0x7C00, the state of
the registers are:

DL = Boot drive, 1h = floppy1, 80h = primary harddisk, etc
CS = 0
IP = 0x7c00

So instead of adding [ORG 7C00h] to the top of your file, you can add:

mov ax, 0x7C0
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax

And that will set-up the segment registers so they point to the start of
your bootsector..

Most boot sectors usually just store the boot drive, load the kernel
from disk, and jump to it.. Some will also load protected mode.

Since most people find it easier looking at source code and figuring
it out than reading documentation i have included sources for a boot
sector and a boot sector writter.

Here is the bootsector...

;******************* START ************************

; Boot sector authoring example by Gareth Owen (gaz@athene.co.uk)
; This should be accompanied with an article explaining bootsectors

[BITS 16] ; the bios starts out in 16-bit real mode
[ORG 0] ; Data offset = 0

jmp start ; skip over our data and functions, we cannot execute data :-),
; well, you can, but i am not held responsible for the results :)

; Boot sector authoring example by Gareth Owen (gaz@athene.co.uk)
; This should be accompanied with an article explaining bootsectors

[BITS 16] ; the bios starts out in 16-bit real mode
[ORG 0] ; Data offset = 0

jmp start ; skip over our data and functions, we cannot execute data :-),
; well, you can, but i am not held responsible for the results :)

; -------------------------------------
; Data used in the boot-loading process
; ------------------------------------------------------------------------
bootdrv db 0
bootmsg db 'Gareth Owen',39,'s Boot Sector Example',13,10,0

rebootmsg db 'Press any key to reboot',13,10,0

; these are used in the processor identification
processormsg db 'Checking for 386+ processor: ',0
need386 db 'Sorry... 386+ required!',13,10,0
found386 db 'Found!',13,10,0

whatever db 'Insert your code to do something here',13,10,0

;*******************************************
; Functions we are going to use ...
;*******************************************
detect_cpu:
mov si, processormsg ; tell the user what we're doing
call message

; test if 8088/8086 is present (flag bits 12-15 will be set)
pushf ; save the flags original value

xor ah,ah ; ah = 0
push ax ; copy ax into the flags
popf ; with bits 12-15 clear

pushf ; Read flags back into ax
pop ax
and ah,0f0h ; check if bits 12-15 are set
cmp ah,0f0h
je no386 ; no 386 detected (8088/8086 present)

; check for a 286 (bits 12-15 are clear)
mov ah,0f0h ; set bits 12-15
push ax ; copy ax onto the flags
popf

pushf ; copy the flags into ax
pop ax
and ah,0f0h ; check if bits 12-15 are clear
jz no386 ; no 386 detected (80286 present)
popf ; pop the original flags back

mov si, found386
call message

ret ; no 8088/8086 or 286, so ateast 386
no386:
mov si,need386 ; tell the user the problem
call message
jmp reboot ; and reboot when key pressed

; ************************************************** ******************
message: ; Dump ds:si to screen.
lodsb ; load byte at ds:si into al
or al,al ; test if character is 0 (end)
jz done
mov ah,0eh ; put character
mov bx,0007 ; attribute
int 0x10 ; call BIOS
jmp message
done:
ret
; ************************************************** ******************
getkey:
mov ah, 0 ; wait for key
int 016h
ret

; ************************************************** ******************
reboot:
mov si, rebootmsg ; be polite, and say we're rebooting
call message
call getkey ; and even wait for a key :)

db 0EAh ; machine language to jump to FFFF:0000 (reboot)

dw 0000h
dw 0FFFFh
; no ret required; we're rebooting! (Hey, I just saved a byte :)

; *******************************************
; The actual code of our boot loading process
; *******************************************
start:
mov ax,0x7c0 ; BIOS puts us at 0:07C00h, so set DS accordinly
mov ds,ax ; Therefore, we don't have to add 07C00h to all our
data

mov [bootdrv], dl ; quickly save what drive we booted from

cli ; clear interrupts while we setup a stack
mov ax,0x9000 ; this seems to be the typical place for a stack
mov ss,ax
mov sp,0xffff ; let's use the whole segment. Why not? We can :)
sti ; put our interrupts back on

; Interestingly enough, apparently the processor will disable
; interupts itself when you directly access the stack segment!
; Atleast it does in protected mode, I'm not sure about real mode.

mov si,bootmsg ; display our startup message
call message

call detect_cpu ; check if we've got a 386

.386 ; use 386 instructions from now on (I don't want to manually include
; operand-size(66h) or address-size(67h) prefixes... it's annoying :)

mov si,whatever ; tell the user we're not doing anything interesting here
call message
call getkey

call reboot

times 510-($-$$) db 0
dw 0xAA55

;******************** GBOOTSECT END *************************

Here is the code for writting the bootsector to a floppy disk.
It has been compiled with DJGPP for DOS.
It writes the file 'bootsect', onto Sector 1, Cylinder 0, Head 0 of
the floppy drive.

//***************START****************
#include <bios.h>
#include <stdio.h>

void main()
{
FILE *in;
unsigned char buffer[520];

if((in = fopen("bootsect", "rb"))==NULL)
{
printf("Error loading file\n");
exit(0);
}

fread(&buffer, 512, 1, in);

while(biosdisk(3, 0, 0, 0, 1, 1, buffer));

fclose(in);
}
//*************END****************************

Well, if you still don't understand something, then mail me
at gaz@athene.co.uk and i'll help you out

- Gareth Owen

reza10203045
جمعه 01 خرداد 1388, 14:06 عصر
البته یادم رفت این مقاله نوشته آقای مهرداد فرخ منش هستش

pswin.pooya
دوشنبه 04 خرداد 1388, 00:26 صبح
سلام
برنامه بوت توی اولیت سکتور دیسک یعنی سکتور 1 هد صفر کلاستر 0 دیسک قرار می گیره. برای اینکه بایوس سیستم متوجه شه برنامه ای که در این سکتر قرار داره یک برنامه بوت هستش به انتهای آن کلمه AA55 رو اضافه می کنن. پس از اونجا که هر سکتور 512 بایت هستش. و نشانه بوت دو بایت هست. میشه نتیجه گرفت که این برنامه باید توی 510 بایت خلاصه بشه. که در نتیجه یه برنامه که قرار هست کرنل رو لود کنه نمی تونه توی این فضا جا بگیره در نتیجه این برنامه یک فایل رو از روی دیسک لود میکنه و به اول محلی که اون فایل رو در اون لود کرده یک پرش انجام میده تا محتویاتش اجرا بشن به این برنامه ثانویه که روی دیسک برای لود کرنل هست اصطلاحا کرنل لودر میگن. توی سیستم عاملهای قدیمی 16 بیتی کرنل لودر وجود نداشت اما با پیدایش سیستم عاملهای 32 بیتس این برنامه هم همراه اونها اومد.

خوب تمام برنامه های بوت از آدرس 0x7c00 حافظه شروع میشن. ( بایوس اونها رو در این آدرس لود میکنه). پس اول برنامت باید اعلام کنی که تانسب آدرسها از این آدرس هستش:


org 0x7c00

انتهای تمام برنامه های بوت هم باید کلمه 0xAA55 باشه در نتیجه به اسمبلر میکیم که اندازه برنامه رو منهای 510 بکنه و تمام فضای خالی رو صفر بذاره و در انتها کلمه 0x7c00 رو قرار میدیم:



times 510-($-$$) db 0 ;Fill up the file with zeros

dw 0xAA55

خوب حالا کد برنامه رو باید مابین این دو قسمت قرار بدی. این کد باید جدول سیستم فایلی رو ( FAT12,FAT32, NTFS, ex3و ...) رو بخونه و از اونجا فایل کرنل لودر رو پیدا کنه و درون حافظه قرار یده و اگر این فایل وجود نداشت اعلام خطا بکنه و سیستم رو ریست کنه.

خوب این دوستمون این قسمت کار رو یه مقدار بد نوشته.

این برنامه ای که گذاشتی خیلی راحت هستش. ما توی دانشگاه آزاد تبریز داریم یک جزوه درباره ی همین برنامه آماده می کنیم. که به احتمال زیاد تا یک ماه آینده حاضر بشه. تو این جزوه ریز مطالب ساخت بوت لودر توضیح داده شده. و فقط قسمت مقدمات اون 30 صفحه هستش و بعد از اون قدم به قدم طراحی یک بوت لودر رو توضیح میده.

اگر به نوشتن سیستم عامل علاقه دارید. میتونید به اکیپ طراحی سیستم عامل دانشگاه آزاد تبریز ملحق بشین اما قبل از اون باید حتمی زبان اسمبلی و سی رو یاد بگیرید و کتاب تننباوم رو مطالعه کامل کرده باشین.

اکیپ ما فعلا در حال طراحی HAL سیستم هستش که بعد از اتمام اون شروع به طراحی کرنل میکنه.

reza10203045
سه شنبه 12 آبان 1388, 21:38 عصر
یک سوالی برای من پیش اومده به کد بوت لودر زیر نگاه کنید.

[ORG 0]

jmp 07C0h:start ; Goto segment 07C0

start:
; Update the segment registers
mov ax, cs
mov ds, ax
mov es, ax


reset: ; Reset the floppy drive
mov ax, 0 ;
mov dl, 0 ; Drive=0 (=A)
int 13h ;
jc reset ; ERROR => reset again


read:
mov ax, 800h ; ES:BX = 800:0000
mov es, ax ;
mov bx, 0 ;

mov ah, 2 ; Load disk data to ES:BX
mov al, 16 ; Load 16 sectors
mov ch, 0 ; Cylinder=0
mov cl, 2 ; Sector=2
mov dh, 0 ; Head=0
mov dl, 0 ; Drive=0
int 13h ; Read!
jc read ; ERROR => Try again
call setup

stop_floppy_motor:
cli
mov dx,3f2h
mov al, 0
out dx,al
sti
ret

change_vid_mode:
mov ah,0x00
mov al,0x13
int 10h
ret

color_screen:
mov ax,0xa000
mov es,ax
mov cx,0xfa00

fill_screen:
mov bx,cx
mov byte [es:bx],0xe5
loop fill_screen
ret
setup:
call change_vid_mode
call color_screen
call stop_floppy_motor
jmp 800h:0000

times 510-($-$$) db 0
dw 0AA55h


در این بوت لودر کدام خط کرنل رو فراخوانی می کنه . ممنون میشم پاسخ بدید

reza10203045
پنج شنبه 14 آبان 1388, 22:57 عصر
در آخر چون کسی به سوال ما جواب نداد . مجبور شدیم تا خودمان جوابشو بنویسیم.
قسمت :read
برای فراخوانی قسمت های دیگه سیستم عامل باید آنها از روی سکتور ها خوانده و فراخوانی شود برای همین کار ما باید اول فلاپی دیسک رو ریست کنم که این کار با استفاده از interrupt 0x12 امکان پذیر است.
و برای خواندن از interrupt 0x13 و function 0x02 استفاده می شود.

MG_69_2
سه شنبه 01 دی 1388, 19:49 عصر
اگر در نوشته ها از منابع هم نامی بود ، عالی بود...