| ||||||
/* LILO'nun doğru yüklendiğinden emin olmak için imza kelimeleri */
#define SIG1 0xAA55
#define SIG2 0x5A5A
INITSEG = DEF_INITSEG # 0x9000, önyüklemeyi buraya taşır, yolun dışına
SYSSEG = DEF_SYSSEG # 0x1000, sistem 0x10000'a yüklenir (65536).
SETUPSEG = DEF_SETUPSEG # 0x9020, bu geçerli bölüttür
# ... ve CS'nin önceki içeriği
DELTA_INITSEG = SETUPSEG - INITSEG # 0x0020
.code16
.text
///////////////////////////////////////////////////////////////////////////////
start:
{
goto trampoline(); // sıradaki başlığı atla
}
# Bu setup başlığıdır ve %cs:2 (old 0x9020:2) adresinden başlamalıdır
.ascii "HdrS" # başlık imzası
.word 0x0203 # başlık sürüm numarası (>= 0x0105)
# yoksa eski loadlin-1.5 başarısız olur
realmode_swtch: .word 0, 0 # default_switch, SETUPSEG
start_sys_seg: .word SYSSEG
.word kernel_version # çekirdek sürüm dizgesini göstererek
# yukarıdaki başlık bölümü
# loadlin-1.5 (başlık v1.5) ile uyumlu.
# Değiştirmeyin
// kernel_version defined below
type_of_loader: .byte 0 # = 0, eski (LILO, Loadlin,
# Bootlin, SYSLX, bootsect...)
# atanmış id değerleri için
# bakınız Documentation/i386/boot.txt
# bayraklar, kullanılmayan bitler 0 olmalı, (RFU) loadflags arasındaki bitler
loadflags:
LOADED_HIGH = 1 # Sıfır değilse, çekirdek yüksek yüklenmiştir
CAN_USE_HEAP = 0x80 # Sıfır değilse, yükleyici ayrıca setup.S'nin
# gerisinde ne kadar alanın yığın (heap)
# olarak kullanılacağını tutmak için
# heap_end_ptr'ye sahiptir.
# Neyin boş olduğunu sadece yükleyici bilir
#ifndef __BIG_KERNEL__
.byte 0
#else
.byte LOADED_HIGH
#endif
setup_move_size: .word 0x8000 # kurulum 0x90000'ye yüklenmediğinde
# taşıma boyutu. Çekirdeğe sıçramadan
# hemen önce kurulumu 0x90000'a taşıyacağız.
# Bununla birlikte geride bıraktığımız
# ne kadar yüklenmesi gereken veri
# bulunduğunu sadece yükleyici bilir.
# burada yükleyiciler 32-bit kod
code32_start: # için farklı başlangıç
# adresleri koyarlar.
#ifndef __BIG_KERNEL__
.long 0x1000 # 0x1000 = zImage için varsayılan
#else
.long 0x100000 # 0x100000 = büyük çekirdek için öntanımlı
#endif
ramdisk_image: .long 0 # yüklü ramdisk görüntüsünün adresi
# Burada yükleyici görüntüyü yüklediği
# 32-bit adresi koyar. Bu sadece
# çekirdek tarafından okunacaktır.
ramdisk_size: .long 0 # boyutu bayt cinsindendir
bootsect_kludge:
.word bootsect_helper, SETUPSEG
heap_end_ptr: .word modelist+1024 # (Başlık sürümü 0x0201 veya daha büyük)
# buradan sonra kurulum sonuna kadar
# boşluklar (özel) kurulum tarafından
# yerel yığın amaçları için kullanılabilir.
// modelist .text bölümünün sonundadır
pad1: .word 0
cmd_line_ptr: .long 0 # (Başlık sürümü 0x0202 veya daha büyük)
# Sıfır değilse, çekirdek komut
# satırına 32-bit bir gösterici.
# Komut satırı kurulumun başı ile
# alçak bellek arasına (0xa0000)
# yerleştirilmeli veya okunmadan önce
# üzerine yazılmalı. Eğer bu alan
# kullanılırsa, 0x90000 bölütüyle ilgili
# sihirli birşey kalmaz; kurulum
# alçak bellekte 0x10000 veya
# daha yüksek herhangi bir
# yere yerleştirilebilir.
ramdisk_max: .long __MAXMEM-1 # (Başlık sürümü 0x0203 veya daha büyük)
# initrd içeriği için en
# yüksek güvenli adres
/* * 0xC0000000'ın bir __PAGE_OFFSET değeri çekirdeğin bir gigabayt * sanal adres boşluğuna sahip olduğu anlamına gelir ki bu da * kullanabileceğiniz fiziksel bellek miktarını 950MB'a sınırlar */ #define __PAGE_OFFSET (0xC0000000) /* * Bu kadar adres boşluğu vmalloc() ve iomap() olduğu kadar * "fixmap" eşleştirmeleri (mappings) için de tahsis edilir. */ #define __VMALLOC_RESERVE (128 << 20) #define __MAXMEM (-__PAGE_OFFSET-__VMALLOC_RESERVE)
Konum Proto İsim Anlamı /Boyut 0200/2 2.00+ jump Sıçrama komutu 0202/4 2.00+ header Sihirli imza "HdrS" 0206/2 2.00+ version Desteklene önyükleme protokolü sürümü 0208/4 2.00+ realmode_swtch Önyükleme yükleyici çengeli (hook) 020C/2 2.00+ start_sys load-low bölütü (0x1000) (modası geçmiş) 020E/2 2.00+ kernel_version Çekirdek sürüm dizgesi göstericisi 0210/1 2.00+ type_of_loader Önyükleme yükleyici belirteci 0211/1 2.00+ loadflags Önyükleme protokolü seçenek bayrakları 0212/2 2.00+ setup_move_size Yüksek bellek boyutuna taşı (çengellerle kullanılır) 0214/4 2.00+ code32_start Önyükleyici çengeli 0218/4 2.00+ ramdisk_image initrd yükleme adresi (önyükleyici tarafından atanır) 021C/4 2.00+ ramdisk_size initrd boyutu (önyükleyici tarafından atanır) 0220/4 2.00+ bootsect_kludge KULLANMAYIN - sadece bootsect.S kullanımı için 0224/2 2.01+ heap_end_ptr kurulum bittikten sonra boş bellek 0226/2 N/A pad1 Kullanılmaz 0228/4 2.02+ cmd_line_ptr çekirdek komut satırına 32-bit gösterici 022C/4 2.03+ initrd_addr_max En yüksek yasal initrd adresi
///////////////////////////////////////////////////////////////////////////////
trampoline()
{
start_of_setup(); // asla dönmez
.space 1024;
}
///////////////////////////////////////////////////////////////////////////////
// tüm kodun yüklenip yüklenmediğini görmek için imzayı kontrol et
start_of_setup()
{
// Bootlin bunun daha önce yapılmasına bağlıdır, bakınız bootlin:technic.doc
int13/AH=15h(AL=0, DL=0x81);
// int13/AH=15h: DİSK - DİSK TÜRÜNÜ AL
#ifdef SAFE_RESET_DISK_CONTROLLER
int13/AH=0(AL=0, DL=0x80);
// int13/AH=00h: DİSK - DİSK SİSTEMİNİ RESETLE
#endif
DS = CS;
// kurulum sonunda imzayı kontrol et
if (setup_sig1!=SIG1 || setup_sig2!=SIG2) {
goto bad_sig;
}
goto goodsig1;
}
///////////////////////////////////////////////////////////////////////////////
// bazı küçük işlevler
prtstr(); /* DS:SI'teki ascii'leri yaz */
prtsp2(); /* çift boşluk yaz */
prtspc(); /* tek boşluk yaz */
prtchr(); /* AL'deki ascii'leri yaz */
beep(); /* CTRL-G yaz, örn. bip */
no_sig_mess: .string "No setup signature found ..."
goodsig1:
goto goodsig; // yakın sıçrama yap
///////////////////////////////////////////////////////////////////////////////
// kalan setup kodunu SYSSEG:0'dan CS:0800'e taşı
bad_sig()
DELTA_INITSEG = 0x0020 (= SETUPSEG - INITSEG)
SYSSEG = 0x1000
word start_sys_seg = SYSSEG; // kurulum başlığında tanımlı
{
DS = CS - DELTA_INITSEG; // INITSEG olarak da bilinir
BX = (byte)(DS:[497]); // örn. setup_sects
// ilk 4 sekctör zaten yüklü
CX = (BX - 4) << 8; // kelime cinsinden kalan kod (2-bayt)
start_sys_seg = (CX >> 3) + SYSSEG; // gerçek sistem kodu başlangıcı
move SYSSEG:0 to CS:0800 (CX*2 bytes);
if (setup_sig1!=SIG1 || setup_sig2!=SIG2) {
no_sig:
prtstr("No setup signature found ...");
no_sig_loop:
hlt;
goto no_sig_loop;
}
}
///////////////////////////////////////////////////////////////////////////////
good_sig()
char loadflags; // setup başlığı içinde
char type_of_loader; // setup başlığı içinde
LOADHIGH = 1
{
DS = CS - DELTA_INITSEG; // INITSEG olarak da bilinir
if ( (loadflags & LOADHIGH) && !type_of_loader ) {
// Hata, eski yükleyiciler büyük-çekirdek yüklemeye çalışırlar
prtstr("Wrong loader, giving up...");
goto no_sig_loop; // yukarıda bad_sig()'de tanımlı
}
}
loader_panic_mess: .string "Wrong loader, giving up..."
///////////////////////////////////////////////////////////////////////////////
// bellek boyunu al
loader_ok()
E820NR = 0x1E8
E820MAP = 0x2D0
{
// bu işleve girerken, DS = CS-DELTA_INITSEG; INITSEG olarak da bilinir
(long)DS:[0x1E0] = 0;
#ifndef STANDARD_MEMORY_BIOS_CALL
(byte)DS:[0x1E8] = 0; // E820NR
/* method E820H: bakınız ACPI spec
* bellek haritası (from hell). e820h belleği farklı türlerden
* bir bütün deste olarak sınıflandırılmış şekilde döndürür, ve
* bellek deliklerine ve herşeye izin verir. Biz bu bellek
* haritasını tararız ve ilk 32 bellek alanının listesini oluştururuz,
* [E820MAP]'den döneriz. */
meme820:
EBX = 0;
DI = 0x02D0; // E820MAP
do {
jmpe820:
int15/EAX=E820h(EDX='SMAP', EBX, ECX=20, ES:DI=DS:DI);
// int15/AX=E820h: GET SYSTEM MEMORY MAP
if (failed || 'SMAP'!=EAX) break;
// if (1!=DS:[DI+16]) continue; // kullanışsız
good820:
if (DS:[1E8]>=32) break; // entry# > E820MAX
DS:[0x1E8]++; // entry# ++;
DI += 20; // tamponu sonraki için ayarla
again820:
} while (!EBX) // bitmedi
bail820:
/* method E801H:
* 1k parça boyutuyla bellek boyutu, loadlin karıştırmamak için.
* 0xe801 bellek boyutunu tamamen farklı bir yerde tutarız
* çünkü muhtemelen 16 bitten daha uzun olacaktır
* (1e0 kullanınız çünkü bu Larry Augustine'in alternatif bellek
* tespit şemasını kullanma yöntemidir ve bu yöntem
* herşeyi aynı yere yazma konusunda hassastır.) */
meme801:
stc; // hatalı BIOSlar için uğraş
CX = DX = 0;
int15/AX=E801h;
/* int15/AX=E801h: >64M YAPILANDIRMALAR İÇİN BELLEK BOYUTUNU AL
* AX = K cinsinden 1M ve 16M arasında bellek boyutu (en çok 3C00 = 15MB)
* BX = genişletilmiş bellek, 16M üzeri, 64K bloklar halinde
* CX = K cinsinden 1M'dan 16M'a yapılandırılmış bellek
* DX = 16M üzeri yapılandırılmış bellek, 64K bloklar halinde */
if (failed) goto mem88;
if (!CX && !DX) {
CX = AX;
DX = BX;
}
e801usecxdx:
(long)DS:[0x1E0] = ((EDX & 0xFFFF) << 6) + (ECX & 0xFFFF); // in K
#endif
mem88: // eski geleneksel yöntem
int15/AH=88h;
/* int15/AH=88h: SİSTEM - GENİŞLETİLMİŞ BELLEK BOYUTU
* AX = mutlak 100000h adresinden başlayan sürekli kB'ların sayısı */
DS:[2] = AX;
}{
// klavye tekrarlama oranını en çoğa ayarla
int16/AX=0305h(BX=0);
// int16/AH=03h: KEYBOARD - SET TYPEMATIC RATE AND DELAY
/* Ekran kiplerini kullanıcıya göstermek için
* ekran kartını ve parametrelerini kontrol et. */
video(); // see video.S
// hd0 ve hd1 verisini al
hd0 verisini (*int41)'dan CS-DELTA_INITSEG:0080'ya (16 bytes) kopyala;
// int41: SYSTEM DATA - HARD DISK 0 PARAMETRE TABLO ADRESİ
hd1 verisini (*int46)'dan CS-DELTA_INITSEG:0090'ya (16 bytes) kopyala;
// int46: SYSTEM DATA - HARD DISK 1 PARAMETRE TABLE ADRESİ
// hd1 var mı kontrol et
int13/AH=15h(AL=0, DL=0x81);
// int13/AH=15h: DISK - DİSK TÜRÜNÜ AL
if (failed || AH!=03h) { // AH==03h eğer harddisk ise
no_disk1:
temizle CS-DELTA_INITSEG:0090 (16 bytes);
}
is_disk1:
// Mikro Kanal veriyolu (Micro Channel-MCA bus) için kontrol et
CS-DELTA_INITSEG:[0xA0] = 0; // tablo uzunluğunu 0'a ayarla
int15/AH=C0h;
/* int15/AH=C0h: SİSTEM - YAPILANDIRMAYI AL
* ES:BX = ROM yapılandırma tablosu */
if (failed) goto no_mca;
ROM yapılandırma tablosunu (ES:BX)'den CS-DELTA_INITSEG:00A0 adresine taşı;
// CX = (table length<14)? CX:16; sadece ilk 16 bayt
no_mca:
// PS/2 noktalama cihazlarını (pointing device) kontrol et
CS-DELTA_INITSEG:[0x1FF] = 0; // varsayılan noktalama cihazı 0
int11h();
// int11h: BIOS - EKİPMAN LİSTESİNİ AL
if (AL & 0x04) { // fare kuruldu
DS:[0x1FF] = 0xAA;
}
}
#if defined(CONFIG_APM) || defined(CONFIG_APM_MODULE)
{
DS:[0x40] = 0; // sürüm = 0 APM BIOS olmadığı anlamına gelir
int15/AX=5300h(BX=0);
// int15/AX=5300h: Advanced Power Management v1.0+ - INSTALLATION CHECK
if (failed || 'PM'!=BX || !(CX & 0x02)) goto done_apm_bios;
// (CX & 0x02) 32 bit desteklendiği anlamına gelir
int15/AX=5304h(BX=0);
// int15/AX=5304h: Advanced Power Management v1.0+ - DISCONNECT INTERFACE
EBX = CX = DX = ESI = DI = 0;
int15/AX=5303h(BX=0);
/* int15/AX=5303h: Advanced Power Management v1.0+
* - CONNECT 32-BIT PROTMODE INTERFACE */
if (failed) {
no_32_apm_bios: // no_32_apm_bios etiketini buraya taşıdım
DS:[0x4C] &= ~0x0002; // 32 bit destekleme bitini kaldır
goto done_apm_bios;
}
DS:[0x42] = AX, 32-bit kod bölütü temel adresi;
DS:[0x44] = EBX, giriş noktası konumu;
DS:[0x48] = CX, 16-bit kod bölütü temel adresi;
DS:[0x4A] = DX, 16-bit veri bölütü temel adresi;
DS:[0x4E] = ESI, APM BIOS kod bölütü uzunluğu;
DS:[0x52] = DI, APM BIOS veri bölütü uzunluğu;
int15/AX=5300h(BX=0); // tekrar kontrol et
// int15/AX=5300h: Advanced Power Management v1.0+ - INSTALLATION CHECK
if (success && 'PM'==BX) {
DS:[0x40] = AX, APM version;
DS:[0x4C] = CX, APM flags;
} else {
apm_disconnect:
int15/AX=5304h(BX=0);
/* int15/AX=5304h: Advanced Power Management v1.0+
* - DISCONNECT INTERFACE */
}
done_apm_bios:
}
#endif
// kip seçiciyi çağır
{
if (realmode_swtch) {
realmode_swtch(); // kip seçme çengeli
} else {
rmodeswtch_normal:
default_switch() {
cli; // hiçbir kesmeye izin yok
outb(0x80, 0x70); // NMI etkinleştirmeyi kaldır
}
}
rmodeswtch_end:
}
// gerekliyse kodu tekrar konumla
{
(long)code32 = code32_start;
if (!(loadflags & LOADED_HIGH)) { // düşük yüklü zImage
// 0x0100 <= start_sys_seg < CS-DELTA_INITSEG
do_move0:
AX = 0x100;
BP = CS - DELTA_INITSEG; // INITSEG olarak da bilinir
BX = start_sys_seg;
do_move:
sistem imgesini (start_sys_seg:0 .. CS-DELTA_INITSEG:0)'dan
0100:0'a taşı; // her seferinde 0x1000 bayt taşı
}
end_move:
DS = CS; // SETUPSEG olarak da bilinir
// sürüm <=201 ile geriye dönük uyumluluğa ihtiyacımız olup olmadığını kontrol et
if (!cmd_line_ptr && 0x20!=type_of_loader && SETUPSEG!=CS) {
cli; // taşınırken kesme olarak yığıtı kullanabilir
// store new SS in DX
AX = CS - DELTA_INITSEG;
DX = SS;
if (DX>=AX) { // yığıt çerçevesi birlikte taşınacak
DX = DX + INITSEG - AX; // i.e. SS-CS+SETUPSEG
}
move_self_1:
/* CS-DELTA_INITSEG:0'dan INITSEG:0'ya taşı (setup_move_size bayt)
* CS:IP üzerindeki kodun üzerine yazmamak için iki adımda
* (src < dest) taşı fakat aşağıya doğru ("std") */
move CS-DELTA_INITSEG:move_self_here+0x200
to INITSEG:move_self_here+0x200,
setup_move_size-(move_self_here+0x200) bytes;
// INITSEG:move_self_here+0x200 == SETUPSEG:move_self_here
goto SETUPSEG:move_self_here; // artık CS=SETUPSEG
move_self_here:
move CS-DELTA_INITSEG:0 to INITSEG:0,
move_self_here+0x200 bytes; // goto'dan önce eski CS anlamında
DS = SETUPSEG;
SS = DX;
}
end_move_self:
}
A20_TEST_LOOPS = 32 # Bekleme başına adım sayısı
A20_ENABLE_LOOPS = 255 # deneme için toplam döngü
{
#if defined(CONFIG_MELAN)
// Enable A20. AMD Elan bug fix.
outb(0x02, 0x92); // outb(val, port)
a20_elan_wait:
while (!a20_test()); // testi geçemedi
goto a20_done;
#endif
a20_try_loop:
// Önce, A20 kapısı olmayan bir sistemde olup olmadığımıza bak.
a20_none:
if (a20_test()) goto a20_done; // testi geçti
// Sonra, BIOS'u (INT 0x15, AX=0x2401) dene
a20_bios:
int15/AX=2401h;
// Int15/AX=2401h: SYSTEM - later PS/2s - ENABLE A20 GATE
if (a20_test()) goto a20_done; // testi geçti
// Klavye denetleyici üzerinden A20'yi etkinleştirmeye çalış
a20_kbc:
empty_8042();
if (a20_test()) goto a20_done; // BIOS gecikmesi durumunda testi tekrarla
outb(0xD1, 0x64); // komut yaz
empty_8042();
outb(0xDF, 0x60); // A20 etkin
empty_8042();
// a20 gerçekten etkin olana kadar bekle
a20_kbc_wait:
CX = 0;
a20_kbc_wait_loop:
do {
if (a20_test()) goto a20_done; // testi geçti
} while (--CX)
// Son girişim: "yapılandırma portu A"'yı kullan
outb((inb(0x92) | 0x02) & 0xFE, 0x92);
// yapılandırma portu A etkilenene kadar bekle
a20_fast_wait:
CX = 0;
a20_fast_wait_loop:
do {
if (a20_test()) goto a20_done; // testi geçti
} while (--CX)
// A20 hala cevap vermiyor. Tekrar ayarlamayı dene.
if (--a20_tries) goto a20_try_loop;
prtstr("linux: fatal error: A20 gate not responding!");
a20_die:
hlt;
goto a20_die;
}
a20_tries:
.byte A20_ENABLE_LOOPS // i.e. 255
a20_err_msg:
.ascii "linux: fatal error: A20 gate not responding!"
.byte 13, 10, 0
a20_done:
{
lidt idt_48; // load idt with 0, 0;
// DS:gdt'yi doğrusal göstericiye dönüştür
*(long*)(gdt_48+2) = DS << 4 + &gdt;
lgdt gdt_48;
// yardımcı işlemciyi sıfırla
outb(0, 0xF0);
delay();
outb(0, 0xF1);
delay();
// kesmeleri yeniden programla
outb(0xFF, 0xA1); // tüm kesmeleri maskele
delay();
outb(0xFB, 0x21); // irq2 dışında tüm irq'ları maskele
// korumalı kip!
AX = 1;
lmsw ax; // makina durumu kelimesi (word), CR0'ın 0'dan 15'e
// kadar bitleri sadece PE, MP, EM ve TS bayraklarını
// etkiler
goto flush_instr;
flush_instr:
BX = 0; // bir önyükleme gösteren bayrak
ESI = (CS - DELTA_INITSEG) << 4; // gerçek kip kod göstericisi
/* NOT: Yüksek yüklenen büyük çekirdekler için
* jmpi 0x100000,__KERNEL_CS'ye gereksinim duyarız
*
* fakat henüz CS yazmacını yüklemedik,
* bu yüzden hedef konumun varsayılan boyutu hala 16 bit.
* Bununla birlikte, bir terim öneki (0x66) kullanarak,
* CPU bizim 48 bit uzak göstericimizi uygun bir şekilde alır.
* Bakınız (INTeL 80386 Programmer's Reference Manual,
* Mixing 16-bit and 32-bit code, page 16-6) */
// __KERNEL_CS:[(uint32*)code32]'e git;
.byte 0x66, 0xea
code32: .long 0x1000 // Korumalı Kip için Hazırlık
// içinde üstüne yazılır
.word __KERNEL_CS // bölüt 0x10
// bakınız linux/arch/i386/boot/compressed/head.S:startup_32
}
/* linux/Makefile hedefleri tarafından oluşturulan makrolar:
* include/linux/compile.h ve include/linux/version.h */
kernel_version: .ascii UTS_RELEASE
.ascii " ("
.ascii LINUX_COMPILE_BY
.ascii "@"
.ascii LINUX_COMPILE_HOST
.ascii ") "
.ascii UTS_VERSION
.byte 0
///////////////////////////////////////////////////////////////////////////////
default_switch() { cli; outb(0x80, 0x70); } /* Kesmeleri ve NMI'yi iptal et */
bootsect_helper(ES:BX); /* bkz. Bootsect Yardımcısı */
///////////////////////////////////////////////////////////////////////////////
a20_test()
{
FS = 0;
GS = 0xFFFF;
CX = A20_TEST_LOOPS; // i.e. 32
AX = FS:[0x200];
do {
a20_test_wait:
FS:[0x200] = ++AX;
delay();
} while (AX==GS:[0x210] && --CX);
return (AX!=GS[0x210]);
// ZF==0 (i.e. NZ/NE, a20_test!=0) means test passed
}
///////////////////////////////////////////////////////////////////////////////
// klavye komut kuyruğu boş mu, bak
empty_8042()
{
int timeout = 100000;
for (;;) {
empty_8042_loop:
if (!--timeout) return;
delay();
inb(0x64, &AL); // 8042 durum portu
if (AL & 1) { // çıktı
delay();
inb(0x60, &AL); // oku
no_output:} else if (!(AL & 2)) return; // girdi yok
}
}
///////////////////////////////////////////////////////////////////////////////
// CMOS saatini oku, AL'den saniyeyi döndür, video.S'de kullanılır
gettime()
{
int1A/AH=02h();
/* int1A/AH=02h: SAAT - GERÇEK SAAT ZAMANINI AL
* DH = BCD gösterimli saniye*/
AL = DH & 0x0F;
AH = DH >> 4;
aad;
}
///////////////////////////////////////////////////////////////////////////////
delay() { outb(AL, 0x80); } // I/O yaptıktan sonra gerekli
// Tanımlayıcı tablo
gdt:
.word 0, 0, 0, 0 # dummy
.word 0, 0, 0, 0 # kullanılmadı
// bölüt 0x10, __KERNEL_CS
.word 0xFFFF # 4Gb - (0x100000*0x1000 = 4Gb)
.word 0 # taban adres = 0
.word 0x9A00 # kodu oku/çalıştır
.word 0x00CF # tanelilik (granularity) = 4096, 386
# (sınırın 5. yarım baytı)
// bölüt 0x18, __KERNEL_DS
.word 0xFFFF # 4Gb - (0x100000*0x1000 = 4Gb)
.word 0 # taban adres = 0
.word 0x9200 # veri oku/yaz
.word 0x00CF # tanelilik = 4096, 386
# (sınırın 5. yarım baytı)
idt_48:
.word 0 # idt sınırı = 0
.word 0, 0 # idt tabanı = 0L
/* [gdt_48] komutla eşleşmesi için 0x0800 (2048) olmalı,
* Linux 2.2.22'nin yaptığı gibi. */
gdt_48:
.word 0x8000 # gdt sınırı=2048,
# 256 GDT girdisi
.word 0, 0 # gdt tabanı (daha sonra doldurulur)
#include "video.S"
// setup.S'nin sonundaki imza:
{
setup_sig1: .word SIG1 // 0xAA55
setup_sig2: .word SIG2 // 0x5A5A
modelist:
}
ASK_VGA = 0xFFFD // defined in linux/include/asm-i386/boot.h
///////////////////////////////////////////////////////////////////////////////
video()
{
pushw DS; // farklı bölütler kullan
FS = DS;
DS = ES = CS;
GS = 0;
cld;
basic_detect(); // temel kart türü testi (EGA/VGA/MDA/CGA)
#ifdef CONFIG_VIDEO_SELECT
if (FS:[0x01FA]!=ASK_VGA) { // kullanıcı seçimli video kipi
mode_set();
if (failed) {
prtstr("You passed an undefined mode number.\n");
mode_menu();
}
} else {
vid2:
mode_menu();
}
vid1:
#ifdef CONFIG_VIDEO_RETAIN
restore_screen(); // ekran içeriğini geri yükle
#endif /* CONFIG_VIDEO_RETAIN */
#endif /* CONFIG_VIDEO_SELECT */
mode_params(); // kip parametrelerini sakla
popw ds; // orjinal DS'yi geri yükle
}
| |||||||||