|
/* 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 }
|