Разработка операционной системы (ОС) — непростая задача, и вопрос «С чего мне хотя бы приступить к решению этой задачи?» может возникать несколько раз в ходе проекта по разным проблемам. В этой статье блога мы объясним, как написать небольшую операционную систему, которая отображает информацию об оборудовании компьютера. Поскольку это сложная задача, мы можем разделить всю задачу на несколько глав.

#1 — Настройка загрузочной части ОС

В этой главе мы научимся настраивать нашу среду разработки и загружать небольшую операционную систему.

Предпосылки

Прежде всего, давайте решим, какие инструменты и технологии мы будем использовать в нашей реализации, чтобы мы могли начать.

Основная операционная система. Нам нужна основная операционная система (например, Ubuntu) для разработки ОС, запуска ее как физически, так и виртуально. Хорошей практикой является установка хост-ОС на виртуальную машину, например VirtualBox, для виртуального тестирования вашей ОС. В этой статье мы используем Ubuntu 20.04, установленную на виртуальной машине, в качестве основной ОС.

Пакеты. После того, как ОС Ubuntu будет запущена и запущена, следующие пакеты должны быть установлены с помощью терминала. (Используйте команду ниже)

sudo apt-get install build-essential nasm genisoimage bochs bochs-sdl

Языки программирования —мы будем использовать язык программирования C с компилятором GCC для разработки наша ОС.

Мы будем использовать NASM в качестве ассемблера для написания ассемблерного кода. В качестве языка сценариев будет использоваться Bash.

Процесс загрузки

Чтобы создать операционную систему, важно понять, как она загружается. Эта глава проведет вас через процесс загрузки ОС.

Процесс загрузки операционной системы предполагает передачу управления через цепочку небольших программ, каждая из которых мощнее предыдущей. Основные программы, участвующие в этом процессе, включают BIOS, Bootloader и ОС. эм>. Операционная система последняя и самая мощная.

При включении компьютера запускается программа BIOS (Basic Input Output System), хранящаяся в ПЗУ. Прежде чем передать управление загрузчику, BIOS прежде всего выполняет раннюю диагностику.

Программа BIOS передаст управление компьютером загрузчику GRUB. Задача загрузчика — передать управление операционной системе. Однако из-за аппаратных и других ограничений загрузчик обычно делится на две части, называемые GRUB1 и GRUB2. В этом случае GRUB1 передаст управление GRUB2, который в конечном итоге передаст управление ОС.

Перейдя к ячейке памяти, GRUB передаст управление Операционной системе. GRUB будет искать магическое число перед переходом, чтобы гарантировать, что он переходит к ОС, а не к какому-то произвольному коду. Спецификация мультизагрузки, которой соответствует GRUB, включает это магическое число. После перехода ОС получает полный контроль над компьютером.

Написание и компиляция ОС

Теперь мы будем работать над созданием простейшей из возможных операционных систем. Единственное, что будет делать эта ОС, — это записывать OxCAFEBABE в регистр EAX.

Этот раздел ОС должен быть разработан на языке ассемблера. Язык программирования C использовать нельзя, так как для него требуется стек, которого нет.

Код ниже в файле должен быть сохранен как ‘loader.s’.

Согласно упомянутому ранее, эта ОС запишет определенное число 0xCAFEBABE в регистр EAX. Как только ОС загрузится, мы можем проверить, успешно ли был записан номер в реестр.

Затем следует использовать следующую команду для компиляции loader.s в 32-битный объектный файл ELF.

nasm -f elf32 loader.s

Связывание ядра

После компиляции кода его необходимо слинковать для создания исполняемого файла. Поскольку адреса менее 1 МБ используются GRUB, BIOS и вводом-выводом с отображением памяти, мы хотим, чтобы GRUB загружал ядро ​​​​по адресу памяти, большему или равному 0x00100000 (1 МБ). Мы можем использовать следующий скрипт в качестве компоновщика.

Должен быть создан файл с именем ‘link.ld’ со сценарием компоновщика. Используя следующую команду, теперь мы можем связать исполняемый файл:

ld -T link.ld -melf_i386 loader.o -o kernel.elf

Теперь мы видим файл с именем «kernel.elf», который является окончательным исполняемым файлом.

Получение GRUB

Мы будем использовать GRUB Legacy stage2_eltorito, созданный GRUB 0.97, в качестве загрузчика для реализации. Бинарный файл для вышеупомянутого загрузчика можно загрузить по указанной ссылке Github:

DylanOS_simple-OS/stage2_eltorito at main · Vidhush-920/DylanOS_simple-OS (github.com)

Файл «stage2_eltorito» следует скопировать в ваш рабочий каталог.

Создание образа ISO

Исполняемый файл должен храниться на носителе, который может прочитать виртуальная или физическая машина. Для этого мы будем использовать файлы образов ISO в нашем проекте. Мы можем использовать программу genisoimage для создания образа.

Должна быть создана папка, содержащая файлы, которые будут в образе ISO. Следующие команды используются для создания папки и копирования файлов в нужные места:

mkdir -p iso/boot/grub              # create the folder structure 
cp stage2_eltorito iso/boot/grub/   # copy the bootloader 
cp kernel.elf iso/boot/             # copy the kernel

Затем необходимо создать файл конфигурации GRUB с именем ‘menu.lst’. Этот файл должен указать GRUB, где найти ядро ​​и установить различные параметры. Вот следующая конфигурация файла:

Файл menu.lst будет помещен в папку iso/boot/grub/. Теперь папка «iso» должна содержать следующую структуру:

iso
|--boot
  |--grub
  ||--menu.lst
  ||--stage2_eltorito
  |--kernel.elf

Затем следующая команда будет использоваться для создания файла iso.

genisoimage -R \ 
-b boot/grub/stage2_eltorito \ 
-no-emul-boot \ 
-boot-load-size 4 \ 
-A os \ 
-input-charset utf8 \ 
-quiet \ 
-boot-info-table \ 
-o os.iso \ 
iso

Будет создан файл с именем os.iso. Он содержит исполняемый файл ядра, загрузчик GRUB и файл конфигурации.

Запуск эмулятора Bochs

В качестве последнего шага мы можем загрузить нашу ОС в эмуляторе Bochs, используя ISO-образ os.iso. Чтобы начать работу с Bochs, вам понадобится файл конфигурации. Ниже приведен простой файл конфигурации.

В зависимости от того, как вы установили Bochs, вам может потребоваться изменить путь к romimage и vgaromimage. Мы можем просмотреть официальный сайт Boch в качестве справки, чтобы узнать больше о конфигурации Boch. Файл конфигурации следует сохранить как ‘bochsrc.txt’ и запустить Bochs с помощью следующей команды:

bochs -f bochsrc.txt -q

Тогда вы можете видеть, как это,

Дайте продолжить на терминале

После этого вы можете видеть,

Теперь Bochs должен работать и отображать консоль с некоторой информацией о ней. Выйдите из Bochs и отобразите журнал, созданный Bochs, с помощью следующей команды:

cat bochslog.txt

Содержимое регистров ЦП, реплицированных Bochs, теперь должно появиться где-то в выводе. ОС успешно загрузилась, если в выводе мы видим RAX=00000000CAFEBABE или EAX=CAFEBABE.

Поздравляем! Мы только что создали простую операционную систему. В следующей главе мы увидим, как мы можем получить помощь языка программирования C для дальнейшей разработки нашей ОС.

Ссылки:

Маленькая книга по ОС: https://littleosbook.github.io/book.pdf

Дополнительная литература:

1. http://duartes.org/gustavo/blog/post/how-computers-boot-up

2. http://duartes.org/gustavo/blog/post/kernel-boot-process

3. http://wiki.osdev.org/Boot_Sequence

Спасибо за чтение!

Надеюсь увидеть вас снова в следующей главе.

-Видхуш Тамилчелван-