Search     or:     and:
 LINUX 
 Language 
 Kernel 
 Package 
 Book 
 Test 
 OS 
 Forum 
 iakovlev.org 
 Kernels
 Boot 
 Memory 
 File system
 0.01
 1.0 
 2.0 
 2.4 
 2.6 
 3.x 
 4.x 
 5.x 
 6.x 
 Интервью 
 Kernel
 HOW-TO 1
 Ptrace
 Kernel-Rebuild-HOWTO
 Runlevel
 Linux daemons
 FAQ
NEWS
Последние статьи :
  Тренажёр 16.01   
  Эльбрус 05.12   
  Алгоритмы 12.04   
  Rust 07.11   
  Go 25.12   
  EXT4 10.11   
  FS benchmark 15.09   
  Сетунь 23.07   
  Trees 25.06   
  Apache 03.02   
 
TOP 20
 Linux Kernel 2.6...5164 
 Trees...935 
 Максвелл 3...861 
 Go Web ...814 
 William Gropp...795 
 Ethreal 3...779 
 Ethreal 4...766 
 Gary V.Vaughan-> Libtool...765 
 Rodriguez 6...756 
 Steve Pate 1...749 
 Clickhouse...748 
 Ext4 FS...748 
 Ethreal 1...736 
 Secure Programming for Li...721 
 C++ Patterns 3...711 
 Ulrich Drepper...693 
 Assembler...687 
 DevFS...655 
 Стивенс 9...644 
 MySQL & PosgreSQL...621 
 
  01.01.2024 : 3621733 посещений 

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 )
 
Оставьте свой комментарий !

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

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