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