четверг, 14 февраля 2013 г.

как копировать в директорию boot/grub

В конкретном случае возможны другие номера дисков и названия устройств. В конечном итоге компиляция и запуск виртуальной машины должны выполняться командой make start. Эта команда из makefile выполнит установку GRUB на флэшку с использованием скрипта grub_install.exp, а затем запустит виртуальную машину QEMU с нашей программой. Поскол

log_user 0 spawn grub expect "grub> " send "root (hd1,0)\r" expect "grub> " send "setup (hd1)\r" expect "grub> " send "quit\r" exit 0

Для установки GRUB-а на флешку используется expect-скрипт в файле grub_install.exp. Его содержимое:

timeout 5 default 0 title start_kernel root (hd0,0) kernel /boot/grub/kernel.bin

Теперь у нас есть ядро, которое можно загрузить. Пора проверить, что оно действительно загружается. Установим GRUB на флешку и скажем ему загружать наше ядро при старте. Для этого нужно выполнить следующие шаги: 1. Создать раздел на флешке, отформатировать его в файловую систему, поддерживаемую GRUB-ом (в нашем случае это файловая система FAT32). Мы воспользовались утилитой Disk Utility из комплекта Ubuntu, которая позволила создать раздел: 2. Примонтировать флешку и создать каталог /boot/grub/. Скопировать в него из /usr/lib файлы stage1, stage2, fat_stage1_5. Создать текстовый файл menu.lst в директории /boot/grub/ и записать в него

CC= gcc CFLAGS= -Wall -nostdlib -fno-builtin -nostartfiles -nodefaultlibs LD= ld OBJFILES = \ loader.o \ printf.o \ screen.o \ pci.o \ kernel.o start: all cp ./kernel.bin ./flash/boot/grub/ expect ./grub_install.exp qemu /dev/sdb all: kernel.bin .s.o: as -o $@ $< .c.o: $(CC) $(CFLAGS) -o $@ -c $< kernel.bin: $(OBJFILES) $(LD) -T linker.ld -o $@ $^ clean: rm $(OBJFILES) kernel.bin

Пока здесь нет ничего интересного. С точки зрения загрузки в нем не должно присутствовать ничего специфичного, только точка входа для кода на С. Для вывода на экран была добавлена реализация функции printf, найденная на просторах Интернета, и несколько функций для работы с видеопамятью, таких как putchar, clear_screen. Для сборки ядра будет использоваться следующий простой makefile:

#include "printf.h" #include "screen.h" void kmain(void) { clear_screen(); printf(" -- Kernel started! -- \n"); }

Заголовок должен включать в себя минимум 3 поля magic, flag, checksum. Поле magic является сигнатурой и, как уже было сказано выше, всегда равно 0x1BADB002. Поле flag содержит дополнительные требования к состоянию машины на момент передачи управления ОС. В зависимости от значения этого поля может меняться набор полей в структуре Multiboot Information. Указатель на структуру Multiboot Information содержит регистр EBX в момент передачи управления загружаемому ядру. В нашем случае поле flag имеет значение 0, и заголовок мультизагрузки состоит только из 3-ех полей. На момент передачи управления ядру процессор работает в защищенном режиме с выключенной страничной адресацией. Обработка прерываний от устройств отключена. GRUB не формирует стек для загружаемого ядра, и это первое что должна сделать операционная система. В нашем случае под стек выделяется 16Кб. Последней выполненной ассемблерной инструкцией будет инструкция call kmain, которая передает управление коду на C, а именно функции void kmain(void). Содержимое kernel.c:

GRUB после загрузки образа ядра с диска ищет в первых 8Кб загруженного образа сигнатуру 0x1BADB002. Сигнатура является первым полем заголовка мультизагрузки. Сам заголовок выглядит следующим образом:

.global loader .set FLAGS, 0x0 .set MAGIC, 0x1BADB002 .set CHECKSUM, -(MAGIC + FLAGS) .align 4 .long MAGIC .long FLAGS .long CHECKSUM # reserve initial kernel stack space .set STACKSIZE, 0x4000 .lcomm stack, STACKSIZE .comm mbd, 4 .comm magic, 4 loader: movl $(stack + STACKSIZE), %esp movl %eax, magic movl %ebx, mbd call kmain cli hang: hlt jmp hang

Скрипт компоновщика указывает, как слинковать уже скомпилированные объектные файлы. В первой строчке указано, что точкой входа в нашем ядре будет адрес с меткой «loader». Далее в скрипте указано, что начиная с адреса 0×00100000 (1Мб) будет располагаться секция text. Секции rodata, data и bss выровнены по 0×1000 (4Кб) и располагаются после секции text. Содержимое Loader.s:

ENTRY (loader) SECTIONS { . = 0x00100000; .text ALIGN (0x1000) : { *(.text) } .rodata ALIGN (0x1000) : { *(.rodata*) } .data ALIGN (0x1000) : { *(.data) } .bss : { sbss = .; *(COMMON) *(.bss) ebss = .; } }

В ходе работы нам периодически приходится сталкиваться с достаточно низкоуровневым взаимодействием с аппаратной частью. В данной статье мы хотим показать, каким образом происходит опрос PCI-устройств для их идентификации и загрузки соответствующих драйверов устройств. В качестве минимальной базы для работы с PCI-устройствами будем использовать ядро, поддерживающее спецификацию Multiboot. Так удастся избежать необходимости писать собственный загрузочный сектор и загрузчик (loader). Кроме того, этот вопрос и так отлично освещен в интернете. В качестве загрузчика будет выступать GRUB. Грузиться мы будем с флэшки, так как с нее удобно загружать и виртуальную, и реальную машину. В качестве виртуальной машины будем использовать QEMU. В качестве реальной машины должна выступать машина с обычным BIOS-ом (не UEFI), поддерживающим загрузку с USB-HDD (обычно присутствует опция Legacy USB support). Для работы понадобятся Ubuntu Linux со следующими программами: expect, qemu, grub (их можно легко установить при помощи команды sudo apt-get install). Используемый gcc должен компилировать 32х битный код. Рассмотрим первый шаг создание ядра, поддерживающего спецификацию Multiboot. В случае использования GRUB-а в качестве загрузчика ядро будет создаваться из 3-х файлов: Kernel.c основной файл с кодом нашей программы и процедурой main(); Loader.s содержит заголовок мультизагрузчика для GRUB; Linker.ld скрипт компоновщика ld, в котором в частности указывается, по какому адресу будет располагаться ядро. Содержимое Linker.ld:

Опубликовано автором

Как найти PCI устройства без операционной системы

Навигация по записям

Ещё одна копия хабора

Как найти PCI устройства без операционной системы | SavePearlHarbor

Комментариев нет:

Отправить комментарий