Fat32 lba что это
У меня Freebsd 5.4.
Диск разбит на 3 раздела.
На втором стоит freebsd. И fdisk-ом его файловая система определяется как 0ха5. Так и должно быть. Тут все понятно.
На первом стоит windows. Файловая система fat32. Fdisk-ом он определяется как 0х0b. Это fat32. Это раздел объемом 7 ГБ.
И третий раздел без ОС отформатирован в fat32. Он fdisk-ом определяется как 0х0с. Это far32 режим LBA.
Почему на одном харде один раздел определяется как fat32 а другой как fat32 режим LBA?
Это нравится: 0Да / 0Нет
08.03.2006 21:26:50
zagler,
У тебя третий раздел находится в extended ?
Это нравится: 0Да / 0Нет
09.03.2006 06:46:04
Нет. У меня все три первичные разделы.
Это нравится: 0Да / 0Нет
16.03.2006 07:19:13
Что никто неподскажет?
Это нравится: 0Да / 0Нет
16.03.2006 11:47:59
2 zagler
Потому что при создании раздела ему был присвоин тип 0х0с. И больше не почему. Вопрос-то в чем?
Это нравится: 0Да / 0Нет
17.03.2006 06:19:56
| Цитата |
|---|
| zagler пишет: Почему на одном харде один раздел определяется как fat32 а другой как fat32 режим LBA? |
Вот в чем вопрос.
Что значит был присвоен тип 0х0с? Насколько я понимаю режим LBA или поддерживается биосом или нет. И он относится к харду а не к разделу.
Что такое файловая система FAT32 — подробное руководство
Файловая система является основой любого цифрового устройства. Нет смысла хранить гигабайты или даже терабайты данных, если вы не можете получить к ним доступ или эффективно использовать их. Несмотря на многочисленные попытки разработать наиболее эффективный и интуитивно понятный пользовательский интерфейс, именно компания Microsoft взяла на себя инициативу по созданию файловой системы, которая нашла свое применение во всех сферах хранения данных. В следующем видеоролике объясняется, что такое файловая система:
Для Windows XP/Vista/7/8/10/11
Для macOS X 10.10 — macOS 13
Если говорить о проверке временем, то файловая система FAT32 является ярким примером. Этот формат был доступен в течение десятилетий и до сих пор используется в некоторых приложениях. Из этого руководства вы узнаете все о формате FAT32, о том, как он появился, и об особенностях, которые делают его таким универсальным для различных производителей компьютеров.
В этой статье
Часть 1. Что такое файловая система FAT32
При форматировании внешних жестких дисков или флешек в Windows вам предлагается выбрать FAT32, NTFS или exFAT. Вы можете выбрать подходящую файловую систему, которая подходит для любых файлов, хранящихся на этом накопителе, в соответствии с вашими требованиями.

Как и его предшественник, Файловая система FAT16, FAT32 использует систему статического распределения, которая хранит информацию в виде кластеров. «FAT32» означает «Таблица размещения файлов 32-бит«. В соответствии со своим названием, она состоит из таблицы распределения файлов, содержащей данные для каждого кластера (единицы, занимающей определенное место на диске). В зависимости от размера файла она может занимать один или несколько кластеров.
FAT32 — это формат статического распределения, который работает только с кластерами, выделенными под файл. Хотя по современным стандартам он может показаться упрощенным, FAT32 поддерживает все стандартные операционные системы и устройства на сегодняшний день.
История возникновения FAT32
Воплощая в жизнь идею создания ОС с графическим интерфейсом, файловая система FAT32 впервые появилась в Windows 95 в августе 1996 года. Разработанная совместно компаниями Microsoft и Caldera, она была отличной модернизацией FAT16, которая поддерживала увеличенные размеры файлов и большие разделы, сохраняя при этом большую часть оригинального кода.
До 1995 года файловые системы работали по схеме CHS, которая позволяла получать данные из хранилищ, расположенных на диске. Однако в Windows 95 была введена система «LBA (Logical Block Allocation)» для размещения архива за пределами диска, что повысило эффективность хранения данных. Это также означало, что для удовлетворения растущих потребностей в хранении данных требовалась новая система, способная работать с объемом памяти больше 8 ГБ.
Файловая система FAT32 создает для каждого файла запись, состоящую из 32 бит вместо прежних 16. Дополнительная информация позволяет создавать большие разделы диска при сохранении высокой скорости чтения/записи. Это также ценно для отслеживания дополнительной информации о файлах, такой как размер значков и цветовые схемы, которые используются в графическом интерфейсе. Он был настолько эффективен, что его до сих пор можно использовать для современных компьютеров.
Улучшения в FAT32 в сравнении с FAT16

Что касается усовершенствований, то FAT32 добилась больших успехов в хранении и обработке файлов. Благодаря увеличенной емкости архива, она может обозначать кластеры 32-битными номерами без ущерба для распределения. Из этих 32 бит 28 отводится под номер кластера, что позволяет хранить миллионы файлов одного типа без ущерба для стабильности. Это также единственная файловая система, которая может работать одновременно с MS-DOS, Windows и macOS, что никогда не было возможно с FAT16.
Длинная строка номеров кластеров обеспечивает более быстрое восстановление данных. Рассмотрим случай, когда у вас поврежден диск и вы хотите восстановить определенные файлы из поврежденного раздела. Было бы проще найти и извлечь более подробный файл записи папки. Файловая система также добавляет несколько функций, отсутствующих в FAT16 и ее предшественниках. Подробнее об этом позже.
Форматирование USB-накоптеля в FAT32
Это самый простой способ, но не всегда контроллер видит накопители, отформатированные таким образом:
- Откройте проводник Windows и перейдите в Мой компьютер.
- Выберите нужный накопитель и правой кнопкой мыши откройте контекстное меню.
- В меню выберите пункт Форматировать….
- Укажите параметры форматирования:
- Файловая система — FAT32.
- Размер единицы распределения — 8192 байт.
- Метка тома — любое слово.
- Быстрое форматирование — флажок установлен.
- Нажмите кнопку Начать и дождитесь окончания операции.
Готово. Накопитель отформатирован в FAT32.

Контекстное меню проводника Windows

Окно выбора параметров форматирования
Утилита Rufus
Если контроллер не видит накопитель отформатированный встроенными средствами, то вы можете использовать утилиту Rufus:
- Скачайте утилиту Rufus и запустите её.
- Укажите параметры форматирования:
- Device — выберите накопитель, который нужно отформатировать.
- Boot selection — Non bootable.
- Volume label — любое слово.
- File system — FAT32.
- Cluster size — 8192 байт.
- Quick format — флажок установлен.
- Create extended label and icon files — флажок снят.
- Check device fo bad sectors — флажок снят.
- Нажмите кнопку START и дождитесь окончания операции.
Готово. Накопитель отформатирован в FAT32.

Настройки для форматирования накопителя

Форматирование успешно завершено
ОС Linux
Этим способом можно отформатировать накопитель с помощью контроллера или компьютера с ОС Linux.
Для создания разделов и форматирования мы будем использовать встроенную в ОС Linux утилиту fdisk:
- Важно правильно определить путь к накопителю:
- Не вставляя накопитель, выполните команду lsblk :
~# lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT mmcblk0 179:0 0 7.1G 0 disk |-mmcblk0p1 179:1 0 16M 0 part |-mmcblk0p2 179:2 0 1G 0 part / |-mmcblk0p3 179:3 0 1G 0 part |-mmcblk0p4 179:4 0 1K 0 part |-mmcblk0p5 179:5 0 256M 0 part [SWAP] `-mmcblk0p6 179:6 0 4.8G 0 part /mnt/data mmcblk0boot0 179:8 0 16M 1 disk mmcblk0boot1 179:16 0 16M 1 disk
- Вставьте накопитель и снова выполните команду lsblk :
~# lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT sda 8:0 1 14.5G 0 disk `-sda1 8:1 1 14.5G 0 part mmcblk0 179:0 0 7.1G 0 disk |-mmcblk0p1 179:1 0 16M 0 part |-mmcblk0p2 179:2 0 1G 0 part / |-mmcblk0p3 179:3 0 1G 0 part |-mmcblk0p4 179:4 0 1K 0 part |-mmcblk0p5 179:5 0 256M 0 part [SWAP] `-mmcblk0p6 179:6 0 4.8G 0 part /mnt/data mmcblk0boot0 179:8 0 16M 1 disk mmcblk0boot1 179:16 0 16M 1 disk
~# fdisk /dev/sda Command (m for help): p Disk /dev/sda: 14.5 GiB, 15525216256 bytes, 30322688 sectors Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disklabel type: dos Disk identifier: 0x00000000 Device Boot Start End Sectors Size Id Type /dev/sda1 2048 30322687 30320640 14.5G c W95 FAT32 (LBA)
Command (m for help): d Selected partition 1 Partition 1 has been deleted.
Command (m for help): n Partition type p primary (0 primary, 0 extended, 4 free) e extended (container for logical partitions) Select (default p): p Partition number (1-4, default 1): First sector (2048-30322687, default 2048): Last sector, +sectors or +sizeK,M,G,T,P> (2048-30322687, default 30322687): Created a new partition 1 of type 'Linux' and of size 14.5 GiB. Partition #1 contains a vfat signature. Do you want to remove the signature? [Y]es/[N]o: y The signature will be removed by a write command.
Command (m for help): p Disk /dev/sda: 14.5 GiB, 15525216256 bytes, 30322688 sectors Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disklabel type: dos Disk identifier: 0x00000000 Device Boot Start End Sectors Size Id Type /dev/sda1 2048 30322687 30320640 14.5G 83 Linux
Command (m for help): t Selected partition 1 Partition type (type L to list all types): b Changed type of partition 'Linux' to 'W95 FAT32'.
Command (m for help): p Disk /dev/sda: 14.5 GiB, 15525216256 bytes, 30322688 sectors Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disklabel type: dos Disk identifier: 0x00000000 Device Boot Start End Sectors Size Id Type /dev/sda1 2048 30322687 30320640 14.5G b W95 FAT32
Command (m for help): a Selected partition 1 The bootable flag on partition 1 is enabled now.
Command (m for help): w The partition table has been altered. Calling ioctl() to re-read partition table. Syncing disks.
Теперь отформатируйте накопитель:
-
Установите утилиту dosfstools :
apt install dosfstools
# mkfs.fat -F 32 /dev/sda1 mkfs.fat 4.1 (2017-01-24
Готово. Накопитель отформатирован в FAT32.
Как запустить программу без операционной системы: часть 6. Поддержка работы с дисками с файловой системой FAT
В пятой части нашей серии статей мы показали, как можно использовать прерывания BIOS’а после перехода в защищенный режим, и в качестве примера определили размер оперативной памяти. Сегодня мы разовьем этот успех и реализуем полноценную поддержку работы с дисками с файловой системой FAT16 и FAT32. Работу с файлами на диске можно разбить на 2 части: работа с файловой системой и работа с диском на уровне чтения/записи секторов. Можно сказать, что для этого нам нужно написать «драйвер» файловой системы и «драйвер» диска.
Работа с диском на уровне чтения/записи секторов
Для начала научимся работать с диском.
Итак, мы можем вызывать прерывания BIOS’а. Помимо прочих возможностей, BIOS предоставляет интерфейс для работы с диском, а именно — прерывание int 0x13. Со списком сервисов, предоставляемых прерыванием, можно ознакомиться на википедии. Нас интересуют сервисы чтения и записи дисков.
Существует два способа адресации сектора на диске, с которыми работает BIOS – CHS(cylinder-head-sector) и LBA(logical block addressing). Адресация CHS основана на использовании геометрии диска, и адресом сектора является совокупность трех координат: цилиндр, головка, сектор. Способ позволяет адресовать до 8Гб. Прерывание int0x13 предоставляет возможность читать и писать на диск с использованием этой адресации.
Понятно, что 8Гб — это очень мало, и данный способ адресации является устаревшим, а все современные (и не очень) контроллеры жестких дисков поддерживают адресацию LBA. Адресация LBA абстрагируется от геометрии диска и присваивает каждому сектору собственный номер. Нумерация секторов начинается с нуля. LBA для задания номера блока использует 48 бит, что позволяет адресовать 128 ПиБ, с учетом размера сектора в 512 байт. Прерывание int0x13 предоставляет два сервиса для чтения и записи секторов на диск с использованием LBA. Их мы и будем использовать. Для чтения сектора прерывание in0x13 ожидает следующие параметры:


Прерывание возвращает следующие значения:

Один из параметров – номер диска. Нужно как-то узнать номер диска, с которым мы собрались работать. Нумерация происходит следующим образом: флоппи-диски (fdd), и все, что эмулируется как флоппи, нумеруются с нуля, а жесткие диски (hdd), и все, что эмулируется как они(usb-флешки, например), нумеруются с 0x80. Этот номер никак не связан с последовательностью загрузки в настройках BIOS’а. В нашем случае, диск, с которым мы собираемся работать, является тем диском, с которого мы загрузились.
Когда BIOS передает управление MBR, он загружает его по адресу 0000h:7C00h, а в регистре DL передает нужный нам номер загрузочного устройства. Это является частью интерфейса взаимодействия между BIOS и MBR. Таким образом, этот номер попадает в GRUB, где далее используется для работы с диском. GRUB, в свою очередь, передает этот номер ОС как часть структуры Multiboot information.
Сразу после передачи управления от GRUB’а к ОС в регистре EBX находится указатель на эту структуру. Первое поле структуры – это flags, и если в нем выставлен 2-й бит, то поле boot_device корректно. Это поле так же принадлежит структуре Multiboot information и в его старшем байте (размер поля – 4 байта) хранится нужный нам номер диска, который понимает прерывание int0x13. Таким образом, используя GRUB, мы получили недостающий параметр для чтения/записи секторов на диск.
Мы научились читать и писать сектора на диск, это, безусловно, важно. Но файловая система привязана не к целому диску, а только к его части – разделу. Для работы с файловой системой нужно найти сектор, с которого начинается раздел, на котором она располагается. Информация об имеющихся на диске секторах хранится в первом секторе диска, там же, где располагается MBR. Существует много различных форматов MBR, но для всех них верна следующая структура:

Информация о разделах хранится в таблице разделов. На диске может быть только 4 первичных раздела, с которых можно загрузиться. На запись о разделе приходится 8 байт. Первый байт — это флаги, если его значение 0x80, то раздел загрузочный. Код MBR в процессе своей работы пробегает по этим 4-м разделам в поиске загрузочного раздела. После его обнаружения, MBR копирует содержимое первого сектора этого раздела на адрес 0000h:7C00h и передает туда управление. Нас интересует LBA адрес первого сектора загрузочного раздела, так как именно на нем располагается наше ядро, и присутствует файловая система, которую мы собираемся читать. Для того чтобы получить этот адрес, нужно прочитать первый сектор диска, найти на нем таблицу разделов, в таблице разделов найти загрузочный раздел, а из его записи прочитать нужное поле.
Итак, у нас есть механизм для чтения сектора с диска и знание о расположении нужного нам раздела на диске. Осталось научиться работать с файловой системой на этом разделе.
Работа с файловой системой
Для работы с файловой системой мы будем использовать библиотеку fat_io_lib. Библиотека доступна под лицензией GPL. Она предоставляет интерфейс для работы с файлами и директориями, аналогичный имеющемуся в libc. Реализованы такие функции, как fopen(), fgets(), fputc(), fread(), fwrite() и т.д. Библиотека для своей работы требует всего лишь две функции: записать сектор и прочитать сектор, причем первая является необязательной. Функции имеют следующий прототип:
int media_read(uint32 sector, uint8 *buffer, uint32 sector_count); int media_write(uint32 sector, uint8 *buffer, uint32 sector_count); Return: int, 1 = success, 0 = failure.
Библиотека написана на чистом С, что опять-таки нам на руку. Для использования в своей мини-ОС нам не придется менять в ней ни строчки. Библиотека ожидает, что чтение секторов происходит в рамках раздела с файловой системой.
Итак, у нас есть функции чтения/записи сектора на раздел и есть библиотека для работы с FAT16/32, которая использует эти функции. Осталось собрать все воедино и продемонстрировать результат. Но прежде чем перейти к коду, хотелось бы показать, что подход, который мы собираемся использовать, вполне применим в реальной жизни. Ниже представлена небольшая часть VBR windows 7, в которой происходит чтение сектора диска посредством прерывания int0x13. Этот код многократно вызывается в процессе загрузки системы, вплоть до момента отрисовки загрузочной анимации.

Для вызова этого кода, Windows 7, подобно тому, как это делаем мы, переходит из защищенного режима в реальный, и обратно. Это несложно проверить, запустив Windows 7 в QEMU. QEMU должен ожидать подключения отладчика. После подключения отладчика (gdb) ставим breakpoint на адрес (0x7c00 + 0x11d). Срабатывание breakpoint’а будет означать вызов этой функции. Кстати в Windows XP этот механизм отсутствует, для вызова прерываний BIOS’а там переходят в режим VM86.
! ВАЖНО! Все дальнейшие действия могут успешно осуществляться только после успешного прохождения всех шагов из пятой части нашей серии статей
Шаг 1. Изменим основную логику в kernel.c
1. Добавим в файле kernel.c следующие объявления:
#include "multiboot.h" #include "fat_io_lib/fat_filelib.h" // переменные определены в loader.s extern u32 mbd; extern u32 magic;
Код, печатающий размер оперативной памяти
u64 ram_size = GetRamsize(); printf("ram_size = %llu(%lluMb)\n", ram_size, ram_size / 0x100000);
заменим на следующий код:
// проверяем, что были загружены grub-ом if (magic != MULTIBOOT_BOOTLOADER_MAGIC) < printf("Invalid magic number: 0x%x\n", magic); return; >multiboot_info_t *p_multiboot_info = (multiboot_info_t*)mbd; // Is boot_device valid? if ((p_multiboot_info->flags & 2) == 0) < printf("Error: boot_device(2) flag is clear\n"); return; >// ищем первый сектор загрузочного раздела if (InitBootMedia(p_multiboot_info->boot_device >> 24) == 0) < printf("Error: InitBootMedia failed.\n"); return; >// инициализируем библиотеку fat_io_lib fl_init(); if (fl_attach_media(ReadBootMedia, WriteBootMedia) != FAT_INIT_OK) < printf("Error: Media attach failed.\n"); return; >// выводим список файлов в папке /boot/grub fl_listdirectory("/boot/grub"); // выводим содержимое /boot/grub/menu.lst на экран char str[64]; void *file = fl_fopen("/boot/grub/menu.lst", "r"); if (file == 0) < printf("Error: can not open file.\n"); return; >printf("\nConntent of the file /boot/grub/menu.lst:\n"); while (fl_fgets(str, sizeof(str), file))
Память под переменные mbd и magic зарезервирована в файле loader.s, так что их можно использовать аналогично глобальным переменным из кода на С. Переменная magic содержит сигнатуру, подтверждающую, что для загрузки использовался стандарт Multiboot, эталонной реализацией которого является GRUB. Переменная mbd указывает на структуру multiboot_info_t, которая объявлена в multiboot.h. Номер загрузочного диска определяется следующим выражением — p_multiboot_info->boot_device >> 24. Функция InitBootMedia запоминает номер диска и ищет первый сектор файловой системы, чтобы затем все смещения считать от него.
Библиотека fat_io_lib для инициализации требует вызова двух функций: fl_init и fl_attach_media. Первая функция обнуляет внутренние структуры библиотеки, а вторая получает в качестве параметров функции чтения и записи секторов на диск, которые затем используются для обращения к файлам. Далее идет демонстрация работы с библиотекой: выводится список файлов в папке /boot/grub и распечатывается содержимое файла menu.lst.
2. Добавляем файл multiboot.h в папку include. Содержимое файла берем с сайта спецификации предыдущей версии.
Шаг 2. Добавим функции для работы с диском
1. В файл include\callrealmode.h добавим прототипы следующих функций:
u32 InitBootMedia(u8 bootDevice); int ReadBootMedia(unsigned long sector, unsigned char *buffer, unsigned long sectorCount); int WriteBootMedia(unsigned long sector, unsigned char *buffer, unsigned long sectorCount);
2. В файле include\callrealmode_asm.h добавим в enum callrealmode_Func новое значение так, чтобы получилось следующее:
enum callrealmode_Func < CALLREALMODE_FUNC_GETSYSMEMMAP = 0, CALLREALMODE_FUNC_READ_DISK = 1 >; Добавим структуру, которая будет использоваться для обращения к диску: struct callrealmode_read_disk < u64 start_sector_lba; u32 buff_addr; u32 sectors_count; u16 disk_number; u8 ret_code; >__attribute__ ((packed));
Добавим в union внутри структуры callrealmode_Data только что объявленную структуру callrealmode_read_disk. Должно получиться следующее:
struct callrealmode_Data < enum callrealmode_Func func : 16; union < struct callrealmode_GetSysMemMap getsysmemmap; struct callrealmode_read_disk readdisk; >; > __attribute__ ((packed));
3. В файл include\string.h добавим функции strncmp и strncpy, используемые в библиотеке fat_io_lib.
static inline int strncmp ( const char * str1, const char * str2, unsigned int num ) < for ( ; num >0; str1++, str2++, --num) < if (*str1 != *str2) return ((*(unsigned char *)str1 < *(unsigned char *)str2) ? -1 : +1); else if (*str1 == '\0') return 0; >return 0; > static inline char* strncpy ( char * dst, const char * src, unsigned int num ) < if (num != 0) < char *d = dst; const char *s = src; do < if ((*d++ = *s++) == 0) < while (--num) *d++ = 0; break; >> while (--num); > return dst; >
4. Добавим в файл callrealmode.c следующие объявления:
#include "fat_io_lib/fat_opts.h" #include "mbr.h" u64 g_BootPartitionStart = 0; // номер первого сектора раздела с файловой системой u32 g_BootDeviceInt13Num = 0; // номер загрузочного диска
И несколько функций:
// Чтение сектора с диска int ReadBootMedia(unsigned long sector, unsigned char *buffer, unsigned long sectorCount) < struct callrealmode_Data param; // структура, в которой передаются параметры // для кода в RM, и возвращается результат param.func = CALLREALMODE_FUNC_READ_DISK; // Чтение сектора с диска происходит путем вызова прерывания int13. // Но таким образом можно записать прочитанный сектор только в // диапазон памяти ниже 1Mb, но адрес "buffer" может быть выше этой границы. // В качестве решения используется временная область по адресу "low_mem_buff", // которая расположена сразу после RM кода, копируемого по адресу CALLREALMODE_OFFSET < 1Mb int i; void *low_mem_buff = CALLREALMODE_OFFSET + (&callrealmode_end - &callrealmode_start); for (i = 0; i < sectorCount; i++) < param.readdisk.start_sector_lba = sector + g_BootPartitionStart + i; param.readdisk.buff_addr = (u32)low_mem_buff; param.readdisk.disk_number = g_BootDeviceInt13Num; param.readdisk.sectors_count = 1; callrealmode_Call(¶m); // int 0x13 с параметрами из "param" if (param.readdisk.ret_code) < return 0; // error >memcpy(buffer + i * FAT_SECTOR_SIZE, low_mem_buff, FAT_SECTOR_SIZE); > return 1; // success > // Запись сектора на диск. Заглушка int WriteBootMedia(unsigned long sector, unsigned char *buffer, unsigned long sectorCount) < return 0; // error >// Функция инициализации u32 InitBootMedia(u8 bootDevice) < g_BootDeviceInt13Num = bootDevice; // Читаем первый сектор диска MBRSector_t mbr; if (ReadBootMedia(0, (u8*)&mbr, 1) == 0) < return 0; >// проверяем сигнатуру if (mbr.mbr_sign[0] != 0x55 || mbr.mbr_sign[1] != 0xaa) < return 0; >// ищем загрузочный раздел int i; for (i = 0; i < 4; i++) < if (mbr.part[i].boot_indicator == 0x80) break; >if (i == 4) < return 0; >// сохраняем номер первого сектора загрузочного раздела g_BootPartitionStart = mbr.part[i].start_lva; printf("start sector = %lld boot dev int13 num = 0x%x\n", g_BootPartitionStart, g_BootDeviceInt13Num); return 1; >
Функции ReadBootMedia и WriteBootMedia используются библиотекой fat_io_lib для чтения/записи секторов. Функция WriteBootMedia не обязательная и является заглушкой, так как в данном примере нет записи на диск. Ее реализация выглядела бы аналогично функции ReadBootMedia. Функция ReadBootMedia похожа на функцию GetRamsize из прошлой статьи с точностью до типа param.func, а вместо param.getsysmemmap используется param.readdisk. Функция InitBootMedia должна быть вызвана раньше двух остальных, так как она инициализирует значения g_BootPartitionStart и g_BootDeviceInt13Num.
5. Изменим callrealmode_asm.s. Добавим еще один тип CALLREALMODE_FUNC_READ_DISK вызываемых функций, должно получиться следующее:
# это объявления из enum callrealmode_Func CALLREALMODE_FUNC_GETSYSMEMMAP = 0x0 CALLREALMODE_FUNC_READ_DISK = 0x1
Далее добавим еще одну проверку на тип функции и непосредственно код, читающий с диска. Должно получиться следующее:
callrealmode_switch: OFF_FUNC = 44 # на таком смещении относительно %bp # находится поле func структуры callrealmode_Data # Which function? movw OFF_FUNC(%bp),%ax cmp $CALLREALMODE_FUNC_GETSYSMEMMAP,%ax je getsysmemmap cmp $CALLREALMODE_FUNC_READ_DISK,%ax je readdisk ret readdisk: OFF_START_SECTOR = 50 # смещение до поля start_sector_lba структуры callrealmode_Data OFF_BUFFER_ADDR = 58 # смещение до поля buff_addr структуры callrealmode_Data OFF_SECTORS_COUNT = 62 # смещение до поля sectors_count структуры callrealmode_Data OFF_DISK_NUMBER = 66 # смещение до поля disk_number структуры callrealmode_Data OFF_RETURN_CODE = 68 # смещение до поля ret_code структуры callrealmode_Data push %bp mov %sp,%bp # формируем на стеке структуру DAP pushl OFF_START_SECTOR+4(%bp) pushl OFF_START_SECTOR+0(%bp) pushl OFF_BUFFER_ADDR(%bp) pushw OFF_SECTORS_COUNT(%bp) pushw $0x10 mov %sp,%si # ds:si указываем на вершину стека, т.е. на DAP mov OFF_DISK_NUMBER(%bp),%dl # номер диска в dl mov $0x42,%ah # EXTENDED READ int $0x13 # CALL DISK BIOS mov %ah,OFF_RETURN_CODE(%bp) # сохраняем результат add $0x10,%sp # очищаем стек от DAP pop %bp ret
Метка readdisk указывает на код, который формирует структуру DAP из структуры callrealmode_Data и вызывает int0x13. В коде после метки callrealmode_switch добавилось 2 инструкции, проверяющие, не нужно ли вызывать readdisk.
6. Добавим файл include\mbr.h, содержащий определения для работы с MBR. Его содержимое:
#ifndef _MBR_H_ #define _MBR_H_ #include "types.h" struct MBRPartitionEntry < unsigned char boot_indicator; unsigned char start_head; unsigned short start_sector : 6; unsigned short start_cylinder : 10; unsigned char sys_id; unsigned char end_head; unsigned short end_sector : 6; unsigned short end_cylinder : 10; unsigned int start_lva; unsigned int size_in_sectors; >__attribute__ ((packed)); typedef struct MBRPartitionEntry MBRPartitionEntry_t; struct MBRSector < u8 code[446]; MBRPartitionEntry_t part[4]; u8 mbr_sign[2]; >__attribute__ ((packed)); typedef struct MBRSector MBRSector_t;
Структура MBRSector используется в функции InitBootMedia.
Шаг 3. Добавим библиотеку fat_io_lib и запустим
1. Скачаем архив fat_io_lib.zip и распакуем его в папку fat_io_lib в корне проекта.
2. Добавим пустые файлы assert.h и stdlib.h в папку include. Они нужны, что бы библиотека скомпилировалась.
3. Исправим Makefile. Добавим файлы из библиотеки в список целей для компиляции. Должно получиться следующее:
FAT_LIB_OBJFILES = \ ./fat_io_lib/fat_access.o \ ./fat_io_lib/fat_cache.o \ ./fat_io_lib/fat_filelib.o \ ./fat_io_lib/fat_format.o \ ./fat_io_lib/fat_misc.o \ ./fat_io_lib/fat_string.o \ ./fat_io_lib/fat_table.o \ ./fat_io_lib/fat_write.o OBJFILES = \ loader.o \ common/printf.o \ common/screen.o \ common/string.o \ kernel.o \ callrealmode.o \ callrealmode_asm.o \ descriptor.o \ $(FAT_LIB_OBJFILES)
@dd if=/dev/zero of=./hdd.img bs=512 count=16065 1>/dev/null 2>&1
@dd if=/dev/zero of=./hdd.img bs=1M count=10 1>/dev/null 2>&1
Теперь размер образа равен 10Mb. Это делается для того, чтобы команда mkdosfs отформатировала раздел в FAT16 вместо FAT12. FAT12 не поддерживается библиотекой fat_io_lib.
$(CC) -Iinclude $(CFLAGS) -o $@ -c $
$(CC) -Iinclude -DFAT_PRINTF_NOINC_STDIO $(CFLAGS) -o $@ -c $
С этим дефайном библиотека не будет включать stdio.h, но будет использовать готовый прототип функции printf, который совпадает с нашим, и который уже реализован.
4. Пересоберем проект
make rebuild
sudo make image
sudo qemu-system-i386 -hda hdd.img
Должно получиться следующее:

Как и в предыдущих частях, можно сделать dd образа hdd.img на флешку и проверить код на реальном железе, загрузившись с нее.
В результате мы реализовали работу с файловыми системами FAT16 и FAT32. Мы немного схитрили, использовав готовую библиотеку, но разбираться в устройстве FAT'а было бы менее интересно, да и вряд ли бы мы тогда уложились в 1 статью. Надеюсь, вам было интересно читать. Пишите в комментариях, если у вас возникнут проблемы в прохождении описанных шагов!
- Как запустить программу без операционной системы
- Как запустить программу без операционной системы: часть 2
- Как запустить программу без операционной системы: часть 3: Графика
- Как запустить программу без операционной системы: часть 4. Параллельные вычисления
- Как запустить программу без операционной системы: часть 5. Обращение к BIOS из ОС
- Блог компании НеоБИТ
- Системное программирование