Search     or:     and:
 LINUX 
 Language 
 Kernel 
 Package 
 Book 
 Test 
 OS 
 Forum 
iakovlev.org
 ================================================================
                      THE LINUX/I386 BOOT PROTOCOL
 ================================================================
                     H. Peter Anvin 
 
 На данный момент существуют 4 версии  boot-протоколов .
 
 Старые ядра:  поддержка только zImage/Image .  
  Ранние версии ядер не поддерживают командную строку.
 
 Protocol 2.00:   Добавлен формат bzImage и поддерживается initrd 
                 для взаимодействия между загрузчиком и ядром .
                 Файл  setup.S становится перемещаемым .
 
 Protocol 2.01:  (Kernel 1.3.76) Добавлено heap overrun warning.
 
 Protocol 2.02:  (Kernel 2.4.0) Новый протокол командной строки
 
 **** Память
 Таблица памяти для загрузчиков типа Image или zImage выглядит так :
 
         |                        |
 0A0000  +------------------------+
         |  Reserved for BIOS     |      Не используется
 09A000  +------------------------+
         |  Stack/heap/cmdline    |      kernel real-mode code.
 098000  +------------------------+
         |  Kernel setup          |      kernel real-mode code.
 090200  +------------------------+
         |  Kernel boot sector    |      kernel legacy boot sector.
 090000  +------------------------+
         |  Protected-mode kernel |      kernel image.
 010000  +------------------------+
         |  Boot loader           |      boot-сектор 0000:7C00
 001000  +------------------------+
         |  Reserved for MBR/BIOS |
 000800  +------------------------+
         |  Typically used by MBR |
 000600  +------------------------+
         |  BIOS use only         |
 000000  +------------------------+
 
 При использовании  bzImage, ядро грузится выше адреса   
 0x100000 ("high memory"), остальные блоки (boot sector,setup, stack/heap) - 
 ниже адреса 0x100000. 
  Биосы выделяют память типа Extended BIOS Data Area как раз
 ниже этой планки . Для проверки количества такой памяти 
 загрузчик должен вызывать "INT 12h" .
  Для форматов zImage или bzImage память выше отметки 0x90000 
 недоступна .
 
 
 ****  REAL-MODE KERNEL HEADER
 
 В загрузчике тип "sector" ссылается на 512 байт.  
 Первое , что нужно сделать при загрузке ядра - загрузить
 real-mode часть кода (boot-sector и setup code) 
 и сделать проверку по смещению  0x01f1.  
 real-mode code может прыгнуть на 32K, 
 хотя сам загрузчик для загрузки может использовать только
 первые 2 сектора (1K) .
 
 Хидер выглядит так:
 
 Offset  Proto   Name            Meaning
 Size
 
 01F1/1  ALL     setup_sects     Размер setup в секторах
 01F2/2  ALL     root_flags      Если этот флаг установлен, 
                                 root онтирован readonly
 01F4/2  ALL     syssize         используется в bootsect.S 
 01F6/2  ALL     swap_dev        не используется
 01F8/2  ALL     ram_size        используется в bootsect.S 
 01FA/2  ALL     vid_mode        Video mode control
 01FC/2  ALL     root_dev        Default root device number
 01FE/2  ALL     boot_flag       0xAA55 magic number
 0200/2  2.00+   jump            Jump instruction
 0202/4  2.00+   header          Magic signature "HdrS"
 0206/2  2.00+   version         Boot protocol version supported
 0208/4  2.00+   realmode_swtch  Boot loader hook (see below)
 020C/4  2.00+   start_sys       версия ядра
 0210/1  2.00+   type_of_loader  тип загрузчика
 0211/1  2.00+   loadflags       флаги boot-протокола
 0212/2  2.00+   setup_move_size переход в верхнюю память
 0214/4  2.00+   code32_start    Boot loader hook (see below)
 0218/4  2.00+   ramdisk_image   адрес загрузки initrd 
 021C/4  2.00+   ramdisk_size    размер initrd 
 0220/4  2.00+   bootsect_kludge используется в bootsect.S 
 0224/4  2.01+   heap_end_ptr    свободная память после setup 
 0226/2  N/A     pad1            не используется
 0228/4  2.02+   cmd_line_ptr    32-bit указатель на командную строку
 
 
 Если магическое число "HdrS" (0x53726448) не найдено по смещению 0x202,
 версия boot protocol старая - "old" , т.е.  
         Image type = zImage
         initrd не поддерживается
         Real-mode kernel загружается по адресу 0x90000.
 
 Загрузчик как правило загружает ядро сразу по адресу назначения .        
 Следующие поля нужно проинициализировать :
   type_of_loader:
         прописывается в arch/i386/boot/setup.S, иначе это       0xFF .
 
 initrd  обычно размещается в верхней памяти насколько это возможно
 и как правило выше  0x3C000000 .
 
   cmd_line_ptr:
 Для протоколов 2.02 и выше, это 32-bit указатель на 
 командную строку .  Она размещается после setup и между 0xA0000.
         
 **** KERNEL COMMAND LINE
 
  С его помощью загрузчик взаимодействует с ядром .
 Она представляет из себя строку длиной 255 плюс null.
 Для протокола 2.02 ее адрес в хидере - поле cmd_line_ptr .
 Для остальных протоколов :
 По смещению 0x0020 (word), "cmd_line_magic", число 0xA33F.
 Эта строка должна находиться внутри региона , определенного
 с помощью  setup_move_size.
 
 **** Простая конфигурация загрузчика
 
 Рассмотрим сегмент:
 
         0x0000-0x7FFF   Real mode kernel
         0x8000-0x8FFF   Stack и heap
         0x9000-0x90FF   Kernel command line
 
 Необходимо в хидере прописать следующие поля :
 
         unsigned long base_ptr; /* базовый адрес real-mode segment */
 
         if ( setup_sects == 0 ) {
                 setup_sects = 4;
         }
 
         if ( protocol >= 0x0200 ) {
                 type_of_loader = ;
                 if ( loading_initrd ) {
                         ramdisk_image = ;
                         ramdisk_size = ;
                 }
                 if ( protocol >= 0x0201 ) {
                         heap_end_ptr = 0x9000 - 0x200;
                         loadflags |= 0x80; /* CAN_USE_HEAP */
                 }
                 if ( protocol >= 0x0202 ) {
                         cmd_line_ptr = base_ptr + 0x9000;
                 } else {
                         cmd_line_magic  = 0xA33F;
                         cmd_line_offset = 0x9000;
                         setup_move_size = 0x9100;
                 }
         } else {
                 /* Very old kernel */
 
                 cmd_line_magic  = 0xA33F;
                 cmd_line_offset = 0x9000;
 
                 /* старые ядра ДОЛЖНЫ загружаться в 0x90000 */
 
                 if ( base_ptr != 0x90000 ) {
                         /* Copy the real-mode kernel */
                         memcpy(0x90000, base_ptr, (setup_sects+1)*512);
                         /* Copy the command line */
                         memcpy(0x99000, base_ptr+0x9000, 256);
 
                         base_ptr = 0x90000;              /* Relocated */
                 }
 
                 /* очистка памяти 32K  */
                 memset(0x90000 + (setup_sects-1)*512, 0,
                        (64-setup_sects-1)*512);
         }
 
 
 **** Загрузка ядра
 
 non-real-mode kernel стартует по адресу (setup_sects+1)*512 
 в image-файле (если setup_sects == 0 , то это 4.)  
 Ядро грузится по адресу 0x10000 для Image/zImage kernels 
 и по адресу 0x100000 для bzImage .
 
 Ядро = bzImage , если протокол >= 2.00 и бит 0x01 (LOAD_HIGH) 
 установлен:
 
         is_bzImage = (protocol >= 0x0200) && (loadflags & 0x01);
         load_address = is_bzImage ? 0x100000 : 0x10000;
 
 Ядра Image/zImage могут иметь размер до 512K , и они используют
 адреса 0x10000-0x90000 . 
 
 **** Опции командной строки
 
   vga=
          это либо число либо строка "normal" , "ext" , "ask"
 
   mem=
          - число , следующее за буквой  K, M или G ( << 10, << 20  << 30).
         Определяет размер памяти . Параметр можно разместить в initrd.
 
   initrd=
 
   BOOT_IMAGE=
         имя загружаемого файла boot image . 
 
   auto
         загрузка ядра без участия пользователя
 
 
 **** Запуск ядра
 
  Ядро прыгает в смещение 0x20 от начала сегмента real mode kernel.
 Т.е. если например вы загрузили ядро по адресу 0x90000, 
 оно стартует с 9020:0000.
 Далее происходит инициализация кодовых сегментов
    ds = es = ss = fs = gs 
 которые указывают на  0x9000 , если код загружен в 0x90000 
         seg = base_ptr >> 4;
         cli();  /* Прерывания запрещены ! */
 
         /* Инициализация стека */
         _SS = seg;
         _SP = 0x9000;   /* Загрузка SP после SS! */
 
         _DS = _ES = _FS = _GS = seg;
         jmp_far(seg+0x20, 0);   /* старт ядра */
 
 **** Нюансы загрузки
 
 Следующие операции предусматривают стековую обработку регистров
 %ebp, %esi , %edi.
 
   realmode_swtch:
         переключение из защищенного в реальный режим
 
   code32_start:
         переход в защищенный режим сразу после того как 
         разархивируется ядро.
         Регистр KERNEL_DS =0x18 .
 
 
 Термин empty_zero_page используется для передачи параметров
 из 16-bit realmode code в  32-битный код .
 Ссылки на него можно найти в : 
   arch/i386/boot/setup.S
   arch/i386/boot/video.S
   arch/i386/kernel/head.S
   arch/i386/kernel/setup.c
 
 
 Offset  Type            Description
 ------  ----            -----------
     0   32 bytes        struct screen_info, SCREEN_INFO
                         ATTENTION, overlaps the following !!!
     2   unsigned short  EXT_MEM_K, extended memory size in Kb (from int 0x15)
  0x20   unsigned short  CL_MAGIC, commandline magic number (=0xA33F)
  0x22   unsigned short  CL_OFFSET, commandline offset
                         Address of commandline is calculated:
                           0x90000 + contents of CL_OFFSET
                         (only taken, when CL_MAGIC = 0xA33F)
  0x40   20 bytes        struct apm_bios_info, APM_BIOS_INFO
  0x80   16 bytes        hd0-disk-parameter from intvector 0x41
  0x90   16 bytes        hd1-disk-parameter from intvector 0x46
 
  0xa0   16 bytes        System description table truncated to 16 bytes.
                         ( struct sys_desc_table_struct )
  0xb0 - 0x1df           Free. Add more parameters here if you really need them.
 
 0x1e0   unsigned long   ALT_MEM_K, alternative mem check, in Kb
 0x1f1   char            size of setup.S, number of sectors
 0x1f2   unsigned short  MOUNT_ROOT_RDONLY (if !=0)
 0x1f4   unsigned short  size of compressed kernel-part in the
                         (b)zImage-file (in 16 byte units, rounded up)
 0x1f6   unsigned short  swap_dev (unused AFAIK)
 0x1f8   unsigned short  RAMDISK_FLAGS
 0x1fa   unsigned short  VGA-Mode (old one)
 0x1fc   unsigned short  ORIG_ROOT_DEV (high=Major, low=minor)
 0x1ff   char            AUX_DEVICE_INFO
 
 0x200   short jump to start of setup code aka "reserved" field.
 0x202   4 bytes         Signature for SETUP-header, ="HdrS"
 0x206   unsigned short  Version number of header format
                         Current version is 0x0201...
 0x208   8 bytes         (used by setup.S for communication with boot loader
                          look there)
 0x210   char            LOADER_TYPE, = 0, old one
                         else it is set by the loader:
                         0xTV: T=0 for LILO
                                 1 for Loadlin
                                 2 for bootsect-loader
                                 3 for SYSLINUX
                                 4 for ETHERBOOT
                                 V = version
 0x211   char            loadflags:
                         bit0 = 1: kernel is loaded high (bzImage)
                         bit7 = 1: Heap and pointer (see below) set by boot
                                   loader.
 0x212   unsigned short  (setup.S)
 0x214   unsigned long   KERNEL_START, where the loader started the kernel
 0x218   unsigned long   INITRD_START, address of loaded ramdisk image
 0x21c   unsigned long   INITRD_SIZE, size in bytes of ramdisk image
 0x220   4 bytes         (setup.S)
 0x224   unsigned short  setup.S heap end pointer
 0x226 - 0x7ff           setup.S code.
 
 0x800   string, 2K max  COMMAND_LINE, the kernel commandline as
                         copied using CL_OFFSET.
                         Note: this will be copied once more by setup.c
                         into a local buffer which is only 256 bytes long.
                         ( #define COMMAND_LINE_SIZE 256 )
 
Оставьте свой комментарий !

Ваше имя:
Комментарий:
Оба поля являются обязательными

 Автор  Комментарий к данной статье