создание img для Bochs'a

Тема в разделе "WASM.OS.DEVEL", создана пользователем Seppuku, 31 янв 2009.

  1. Phantom_84

    Phantom_84 New Member

    Публикаций:
    0
    Регистрация:
    6 июн 2007
    Сообщения:
    820
    Тема не совсем про bximage. Обычно подключают образ, созданный при помощи bximage, к эмулятору и уже в нем инсталлируют в образ все, что надо. bximage просто создает чистый бинарный файл определенного размера.
     
  2. Eugene22

    Eugene22 New Member

    Публикаций:
    0
    Регистрация:
    20 авг 2011
    Сообщения:
    9
    Ну да, это я понял, в принципе я могу скажем, подключить программу загрузки, просто указав в настройках бокса нужный com-файл, но тогда получается диск размером 512 байт и соответственно там будет только одна программа загрузки. Хотелось бы узнать как имеенно инсталлировать boot-сектор и другие файлы ос в образ, созданный с помощью bximage ?

    Или есть ли альтернативные варианты создания образов ос для бокса? Как я видел выше, есть пример для создания образа ос для флоппика, подойдет ли он для создания образа ос на основе жесткого диска или флешки, а не флоппика?
     
  3. Pavia

    Pavia Well-Known Member

    Публикаций:
    0
    Регистрация:
    17 июн 2003
    Сообщения:
    2.409
    Адрес:
    Fryazino
    Eugene22
    bximage создаёт *.img файл. Это простой бинарный файл который имеет размер кратный размеру сектора.
    По умолчанию размер сектора равен 512. Также для совместимости CHS размер файла кратен этим числам.
    CHS - способ адресации в котором адрес задаётся при помощи указания цилиндров, головок, секторов.

    Расширение никак не влияет на структуру. Поэтому в разных эмуляторах и программах может отличаться.
    Обычно расширения файлов такие
    *.img - образ жёсткого диска
    *.ima - образ дискеты

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

    Для того чтобы образ стал загрузочным на него надо записать загрузочный сектор. Сделать это можно различными средствами. Удобнее наверно написать свою программу. Которая в целевой образ записывает сектор - первые 512 байт при этом не изменяет служебные поля. Для первых экспериментов хватит и 16-тиричного редактора такого как WinHex.

    Загрузочный сектор для дискет и жёстких отличается структурой.
    Признаком того что сектор c LBA=0 является загрузочным является сигнатура по смещению 510=55h и по смещению 511=0AAh (по смещению считаются от 0).

    BIOS проверяет эту сигнатуру и если видит её то выполняет загрузку.
    В BIOS Bochs можно отключить проверку.

    Для образа дискеты важно присутствие структуры BPB. Для жёсткого ограничений нет.
    Некоторые BIOSы берут геометрию дискет из BPB поэтому важно когда ты будешь менять первые 512 байт в твоём образе дискеты чтобы BPB сохранялся.

    Когда ты создаёшь образ диска в bximage то ты указываешь. Это будет жёсткий диск или мягкий(дискета)
    Floppy - в пер с английского означает мягкий.

    MBR, BootRecord я записываю при помощи WinHex.
    Свою программу пока не делал.

    По поводу файлов. Для записи файлов надо понимать какую структуру имеет образ диска. Ограничений по логической структуре жесткого диска и его образа нет. Автор волен выбирать сам. Если брать классическую, то в образ будет отформатирован в одну из известных файловых систем (ФС). Для работы с FAT могу посоветовать
    WinImage и UltraISO. Правда лучше будет если ты опять таки сделаешь свою утилиту.

    В Линуксе и Юниксе всё проще. Образ с любой из распространенных ФС легко монтируется. И ты можешь записывать на него файлы обычными дисковыми утилитами.

    А запись сектора можно сделать при помощи команды "dd".
     
  4. Phantom_84

    Phantom_84 New Member

    Публикаций:
    0
    Регистрация:
    6 июн 2007
    Сообщения:
    820
    Это зависит от ОС, которую ты инсталлируешь. Ты должен в эмуляторе запустить программу установки этой ОС, загрузившись с другого носителя/образа. В случае установки моей оси на абсолютно чистый образ я, например, выполняю примерно такие действия, используя загрузочный диск DOS:
    fdisk
    format
    setupmbr
    setupldr
    copy

    Естественно, есть: OSDev Wiki и др. Хотя создание образа с таблицей разделов может оказаться не самым легким делом. mkfloppy.inc для создания образа жесткого диска использовать нельзя (можно попробовать сделать образ для флешки, если ты будешь ее использовать в "режиме флоппика"). Я сейчас доделываю включаемые файлы для создания образа жесткого диска/флешки с одним или даже несколькими разделами (!!!), содержащими FAT12 или FAT16. Если тебе файловая система не нужна вообще, то такой образ (все равно, с таблицей разделов или без) сделать не сложно. Все зависит от цели. Твой загрузчик и прочие файлы рассчитаны на какую/какие ФС?
     
  5. Eugene22

    Eugene22 New Member

    Публикаций:
    0
    Регистрация:
    20 авг 2011
    Сообщения:
    9
    Pavia, Phantom_84, спасибо за ответы, буду разбираться.

    Пока не на что не расчитаны, в принципе и файлов пока нет. Есть только собственно начальный загрузчик, так как у меня возникли некоторые проблемы связи загрузчика с другими файлами. В идеале хотелось бы самому написать какое-нибудь подобие файловой системы, а пока - как получится.
     
  6. Phantom_84

    Phantom_84 New Member

    Публикаций:
    0
    Регистрация:
    6 июн 2007
    Сообщения:
    820
    Если поддержки ФС пока нет ни на коком уровне, то образ диска сделать в fasm'е элементарно.

    1) без таблицы разделов:
    Код (Text):
    1. macro align value { db value-1 - ($ + value-1) mod (value) dup 0 }
    2.  
    3. HEADS = 16
    4. SPT = 63
    5.  
    6. file "boot.bin",512 ; твой загрузчик
    7.  
    8. file "module1.bin" ; твой первый файл
    9. align 512
    10.  
    11. ...
    12.  
    13. file "moduleN.bin" ; твой N-ый файл
    14. align 512
    15.  
    16. align HEADS*SPT*512
    2) с таблицей разделов:
    Код (Text):
    1. macro align value { db value-1 - ($ + value-1) mod (value) dup 0 }
    2.  
    3. PART_STATE = 80h
    4. PART_TYPE = 80h
    5. HEADS = 16
    6. SPT = 63
    7.  
    8. file "mbr.bin",440 ; любой "стандартный" MBR-загрузчик
    9. db ?,?,?,?,0,0
    10. db PART_STATE,1,1,0
    11. db PART_TYPE,HEADS-1,(CYLINDERS-1) and 300h shr 2 + SPT,(CYLINDERS-1) and 0FFh
    12. dd SPT,(CYLINDERS*HEADS-1)*SPT
    13. db 510-$ dup 0
    14. dw 0AA55h
    15.  
    16. rb SPT*512-$
    17.  
    18. file "boot.bin",512 ; твой загрузчик
    19.  
    20. file "module1.bin" ; твой первый файл
    21. align 512
    22.  
    23. ...
    24.  
    25. file "moduleN.bin" ; твой N-ый файл
    26. align 512
    27.  
    28. align HEADS*SPT*512
    29.  
    30. CYLINDERS=$/(HEADS*SPT*512)
     
  7. Eugene22

    Eugene22 New Member

    Публикаций:
    0
    Регистрация:
    20 авг 2011
    Сообщения:
    9
    Phantom_84, я попробовал использовать первый код - где без файловой системы, на выходе у меня создается файл c расширением bin, но при запуске бокс не находит загрузочного устройства - No bootable device. Не знаю, может я на фасме неправильно программу написал - я первый день работаю с фасмом, раньше только с масмом работал

    Программа выглядит так
    Код (Text):
    1. jmp Begin
    2. macro align value { db value-1 - ($ + value-1) mod (value) dup 0 }
    3. HEADS = 16
    4. SPT = 63
    5. Begin:
    6.     file "Eboot.exe",512 ; загрузчик
    7.     align HEADS*SPT*512
    Программа загрузки рабочая, что я делаю не так?
     
  8. Phantom_84

    Phantom_84 New Member

    Публикаций:
    0
    Регистрация:
    6 июн 2007
    Сообщения:
    820
    Второй тоже без файловой системы. "jmp Begin" убери - это все должно быть внутри "Eboot.exe" (exe? Надеюсь, это чистый программный код!)
     
  9. Eugene22

    Eugene22 New Member

    Публикаций:
    0
    Регистрация:
    20 авг 2011
    Сообщения:
    9
    Phantom_84, ага, спасибо, без "jmp Begin" все работает.
     
  10. Eugene22

    Eugene22 New Member

    Публикаций:
    0
    Регистрация:
    20 авг 2011
    Сообщения:
    9
    Phantom_84,

    еще один вопрос - сейчас пытаюсь подгрузить еще один файл из загрузчика
    то есть программа приняла вид
    Код (Text):
    1. macro align value { db value-1 - ($ + value-1) mod (value) dup 0 }
    2. HEADS = 16
    3. SPT = 63
    4. Begin:
    5.     file "eboot.com",512 ; загрузчик
    6. file "Kernel.com" ; твой первый файл
    7. align 512
    8.     align HEADS*SPT*512
    Как я понимаю, Kernel.com попадает во 2 сектор нулевого цилиндра нулевой головки? И еще создаваемый образ рассматривать как жесткий или как гибкий диск - то есть что в регистр dl должно быть при чтении сектора?
     
  11. Phantom_84

    Phantom_84 New Member

    Публикаций:
    0
    Регистрация:
    6 июн 2007
    Сообщения:
    820
    Верно. Хотя лучше сразу перейти к линейной адресации (LBA). Линейный номер сектора (а также при необходимости размер) можно вычислять тут же:
    Код (Text):
    1. align 512 ; если не уверен в правильности выравнивания тек. позиции
    2. kernel_sect=$/512
    3. file "kernel.com"
    4. align 512
    5. kernel_size=$/512-kernel_sect ; размер в секторах, если нужен
    Эти значения ты можешь использовать в загрузчике. Например, можно определить структуру для хранения местоположения и размера твоего ядра в строго определенном месте (по определенному смещению) внутри загрузчика и делать так:
    Код (Text):
    1. kernel_desc equ 40h ; к примеру смещение 40h
    2. store dword kernel_sect at kernel_desc
    3. store word kernel_size at kernel_desc+4
    Вообще ты вроде собирался делать образ для жесткого диска. В этом случае его номер практически всегда будет равен 80h. Ты можешь также определить байтовую ячейку для хранения этого номера по строго определенному смещению внутри загрузчика (так делает большинство загрузчиков) и в случае необходимости его менять (без перекомпиляции загрузчика). Ты также можешь использовать номер загрузочного диска, который передает твоему загрузчику BIOS в регистре dl. Это будет работать для жестких дисков и флешек с произвольным номером (так делают прогрессивные загрузчики). При этом ячейку для хранения номера диска внутри загрузчика можно сохранить (на случай использования глючного BIOS, не передающего номер диска в dl) и использовать какое-либо специальное значение для этой ячейки, к примеру 0xFF, указывающее на то, что номер диска нужно брать от BIOS (так делает GRUB).
     
  12. Eugene22

    Eugene22 New Member

    Публикаций:
    0
    Регистрация:
    20 авг 2011
    Сообщения:
    9
    Про LBA я немного читал, но решил пока идти от простого к сложному. Прочитать следующий сектор - то есть ядро вроде удалось, но возникла проблемка - ядро просто представляет программу вывода сообщения, но вот сообщение выводится совсем не теми символами, которыми бы надо. Причем сообщения загрузочного сектора отображаются как надо. Причем делал как на масме так и на фасме - результат один и тот же.

    Код загрузочного сектора

    Код (Text):
    1. org 7c00h  
    2. start:
    3.         cli ;запрещаем прерывания
    4.         xor ax,ax   ;обнуляем регистр ах
    5.         mov ds,ax   ;настраиваем сегмент данных на нулевой адрес
    6.         mov es,ax   ;настраиваем сегмент es на нулевой адрес
    7.         mov ss,ax   ;настраиваем сегмент стека на нулевой адрес
    8.         mov sp,07C00h   ;сегмент sp указывает на текущую вершину стека
    9.         sti ;разрешаем прерывания
    10.        
    11.         ;очищаем экран
    12.         mov al, 02h
    13.         mov ah, 00h
    14.         int 10h
    15.        
    16.         call GetCursorPos   ;получаем позицию курсора
    17.                                
    18.         mov bp, msg             ; Загрузка
    19.         mov cx, 13
    20.         call print                  ;Вывод на экран строки msg
    21.        
    22.         add dh,1    ;переходим на одну строку ниже
    23.         call SetCursorPos
    24.         mov bp, Con             ; Загрузка
    25.         mov cx, 23
    26.         call print
    27.                
    28. Char:    call Char_in
    29.                
    30.         cmp al, 0Dh ;Если нажимаем на Enter, то переходим к загрузке ядра
    31.         jz Kernel
    32.                
    33.         jmp $
    34. Kernel:
    35.                 mov     ax,0000h
    36.                 mov     es,ax
    37.                 mov     bx,8000h          ; Entry Point - KernelSEG:100h
    38.                 mov     ch,0            ;номер цилиндра - 0
    39.                 mov     cl,02h          ;начальный сектор - 2
    40.                 mov     dh,0            ;номер головки - 0
    41.                 mov     dl,80h          ;жесткий диск - 80h
    42.                 mov     al,01h          ;кол-во читаемых секторов -1
    43.                 mov     ah,02h
    44.                 int 13h
    45.                 jmp 0000:8000h
    46.                
    47. ;===================== Подпрограммы ===================================
    48.   print:                             ;в регистре  bp - строка, в регистре cx - длина этой строки
    49.         mov bl,04h                  ;в регистре  bl- атрибут
    50.         mov ax,1301h
    51.         int 10h
    52.         ret
    53.         ;----------------------------------
    54.   GetCursorPos: ;получаем текущее значение курсора функиция 3h прерывания 10h
    55.                         ; в bh страница
    56.         mov ah,3h
    57.         xor bh,bh
    58.         int 10h
    59.         ret
    60.         ;----------------------------------
    61.   SetCursorPos:        ;установка курсора : функция 02h прерывания 10h
    62.         mov ah,2h
    63.         xor bh,bh
    64.         int 10h
    65.         ret
    66.       ;----------------------------------
    67.   Char_in:              ;ожидание нажатой клавиши : функция 10h прерывания 16h
    68.          mov ah,10h
    69.          int 16h
    70.          ret
    71.            
    72.         ;===================== выводимые сообщения=====================
    73.         msg db 'OS Loading...',0    
    74.         Con db 'Press Enter to Continue',0
    75.  
    76. times(512-2-($-07C00h)) db 0
    77. db 055h,0AAh ;сигнатура, символизирующая о завершении загрузочного сектора
    Код как бы ядра, сообщения которого выводятся неправильно
    Код (Text):
    1. message:
    2.         mov ax, 0002h      
    3.         int 10h
    4.         mov bp, mg
    5.         mov cx, 15
    6.         mov bl,08h                 
    7.         xor bh,bh
    8.         mov ax,1301h
    9.         int 10h
    10.        
    11. mg db 'Hello Eugene....',0
    Вроде все правильно, но почему то выходит не то.

    И второй вопрос - какой диапазон памяти можно использовать для загрузки ядра в регистры es:bx?
     
  13. Pavia

    Pavia Well-Known Member

    Публикаций:
    0
    Регистрация:
    17 июн 2003
    Сообщения:
    2.409
    Адрес:
    Fryazino
    1. По поводу первого вопроса учи макрокоманду org.
    2. Ну тут 3 вопроса. Для загрузки ядра можно использовать всю доступную память.
    Можешь считать из переменных биоса размер базовой памяти, для определения доступной в первом мегабайте памяти за вычетом таблицы прерываний и самих переменных биоса ну и ещё 100h резервируем. т.е. 0 по 6FF включительно считай что занято. А для определения того что выше использовать прерывания биоса. Int 15 SMAP и другие функции.

    PS. Скачай книгу про Ассемблер и почитай.
     
  14. Phantom_84

    Phantom_84 New Member

    Публикаций:
    0
    Регистрация:
    6 июн 2007
    Сообщения:
    820
    Pavia прав (org 8000h в помощь; это корректнее называть директивой, а не макрокомандой). Хотя, как вариант jmp 800h:0 в загрузчике или jmp 800h:next_pos_disp в "ядре". Но я предпочитаю по минимуму работать с сегментными адресами реального режима, поэтому использую jmp 0:next_pos_disp в ядре - это позволяет оставаться в рамках линейной адресации и использовать код реального режима размером до 32 кб.

    startup.asc
    Код (Text):
    1. section startupcode16
    2. {
    3. Startup:
    4.         xor bx,bx
    5.         cli
    6.         mov ss,bx
    7.         mov sp,7C1Ch
    8.         sti
    9.  
    10. ; Сохраняем в стеке параметры, полученные от загрузчика.
    11.  
    12.         label .FSFileSize dword at 7C1Ch-4
    13.         push cx
    14.         push ax
    15.         push bx
    16.         push dx
    17.         jmp 0:@f
    18.         ...
    19. @@:
    20.         ...
    21. }
    kernel.asc
    Код (Text):
    1.   org 8000h
    2.   put startupcode16,initcode16,startupdata16,initdata16
    3.   virtual
    4.   rb 10000h-$
    5.   end virtual
    6.   ...
    Я файл ядра (и еще один дополнительный файл) первоначально загружаю в базовую память. Мои загрузчики используют int 12h для определения размера доступной базовой памяти (переменные BIOS должны дать аналогичный результат).
     
  15. Phantom_84

    Phantom_84 New Member

    Публикаций:
    0
    Регистрация:
    6 июн 2007
    Сообщения:
    820
    Еще вариант для com-файла (стартовое смещение 100h, т.е. нужно использовать org 100h):
    jmp 7F0h:100h в загрузчике или jmp 7F0h:next_pos_disp (имеется в виду 100h+) в "ядре".
     
  16. Eugene22

    Eugene22 New Member

    Публикаций:
    0
    Регистрация:
    20 авг 2011
    Сообщения:
    9
    Спасибо, более менее понятно становится. org 8000h - все работает, а jmp 800h:0 - этот вариант не прокатывает.

    По поводу диапазона адресов, просто в этой теме - http://www.wasm.ru/forum/viewtopic.php?id=30307 - говорится, что используемая оперативная память для ос и программ располагается в диапазоне 500h-9FFFFh, в то же время у Криса Касперски я прочитал
    - мне просто непонятно, почему у него нижняя граница 0080:0067h, просто интересно, какие допустимые значения можно использовать для регистров es и bx
     
  17. Phantom_84

    Phantom_84 New Member

    Публикаций:
    0
    Регистрация:
    6 июн 2007
    Сообщения:
    820
    Не прокатывает, потому что ты, видимо, делаешь com-файлы (org 100h). Для чистого бинарника с нулевым стартовым внутрисегментным смещением прокатывает. Для com-файлов я привел другой вариант (см. последний пост).

    Там много чего говорится. Но я по прежнему придерживаюсь своего мнения:
    - "Про память ниже первого мега рассказали подробно: начиная с 500h и до значения, возвращаемого функцией BIOS int 12h в килобайтах".
    - "9FC00h-9FFFFh - может быть и больше! - расширенная (дополнительная) область данных BIOS, нижнюю границу которой как раз и можно получить с помощью int 12h".
    - "В принципе в защищенном режиме, если работа BIOS полностью остановлена, то можно использовать и IVT, и BDA, и EBDA, но я бы не советовал это делать, потому что BIOS может работать даже тогда, когда это казалось бы невозможно, например, в режиме SMM".

    Мне тоже непонятно, откуда это взялось. Я всегда использовал базовую память, начиная с адреса 500h, и не имел никаких проблем. Можешь взять за основу адрес 600h - так делают очень многие. Можешь еще сильнее перестраховаться. Т.к. эти адреса обычно являются дном стека у первичных загрузчиков (хотя некоторые mbr- и первичные загрузчики их все-таки используют) и инициализационного кода ядра, до они практически не используются, а в своем "ядре" можешь вообще не использовать/не изменять первую страницу (4 кб) физической памяти.