Magic с бутсектором.

Тема в разделе "WASM.OS.DEVEL", создана пользователем SadKo, 14 сен 2008.

  1. SadKo

    SadKo Владимир Садовников

    Публикаций:
    8
    Регистрация:
    4 июн 2007
    Сообщения:
    1.610
    Адрес:
    г. Санкт-Петербург
    В общем, объясняю ситуацию.
    Сделал утилиту, которая создаёт образ FAT16-диска.
    Сделал тестовую утилиту, которая читает бутсектор и выводит на экран (ну всё положено, с местом под FAT и BPB).
    Читаем через функцию 0x42 int 0x13.
    Компилю бутсектор - первые 0x3c байт - это jmp + заголовок FAT (нули) + BPB (тоже нули).
    1. Создаю образ (первые 0x3c байт утилита прописывает в соответствии с создаваемой ФС FAT16, как и ожидалось).
    Записываю образ на флешку, начиная с 0 сектора, и бутаюсь. Вместо корневого каталога (чётко прописан сектор - 0x41) читается какая-то ерунда.
    2. Пишу вместо 0 сектора скомпилированный boot, где нули вместо заголовка FAT и BPB. Бутаюсь с флешки, рутовый каталог читается как надо.

    При этом, к первым 0x3c байтам тестовый код бутсектора вообще не ссылается. Я уже весь код пересмотрел, перечитал. Эмуляторы (BOCHS, QEMU) отрабатывают корректно и в первой, и во второй ситуации. А вот BIOS не хочет. Может, кто-нибудь разъяснит, почему в первом случае BIOS отрабатывает некорректно, а во втором - корректно?

    Вот код:

    Код (Text):
    1. ; Some Constants
    2.  
    3. use16
    4. org 0x7c00
    5.  
    6. BOOT_SECTOR_SIZE    =   0x200
    7. FAT_LAST_CLUSTER    =   0xfff8
    8.  
    9. ;-------------------------------------------------------------------------------
    10. ; Main Entry Point
    11. start:
    12.         jmpBoot:            jmp     fat_start_load
    13.         jmp_dump:           nop
    14.         OEMName:            db      0,0,0,0,0,0,0,0
    15.         BytesPerSec:        dw      0
    16.         SecPerClus:         db      0
    17.         RsvdSecCnt:         dw      0
    18.         FATsCount:          db      0
    19.         RootEntries:        dw      0
    20.         TotalSectors:       dw      0
    21.         MediaType:          db      0
    22.         FATSize:            dw      0
    23.         SectsPerTrack:      dw      0
    24.         HeadsCount:         dw      0
    25.         HiddenSectors:      dd      0
    26.        
    27.         TotalSectors32:     dd      0
    28.  
    29.         DrvNum:             db      0
    30.         Reserved:           db      0
    31.         BootSig:            db      0
    32.         VolumeId:           db      0,0,0,0
    33.         DiskLabel:          db      0,0,0,0,0,0,0,0,0,0,0
    34.         FileSystem:         db      0,0,0,0,0,0,0,0
    35.  
    36. fat_start_load:
    37.  
    38. ; Change Segment Registers
    39.         cld
    40.         cli
    41.         xor     ax, ax
    42.         mov     ss, ax
    43.         mov     ds, ax
    44.         mov     es, ax
    45.         mov     sp, start
    46.         sti
    47.        
    48. ; Try to read data
    49.         xor     dx, dx
    50.         mov     ax, 0x41
    51.         mov     bx, disk_buffer
    52.         mov     cx, 2
    53.        
    54.         call    read_sectors_lba
    55.        
    56. ; Output buffer
    57.         mov     si, disk_buffer
    58.         mov     cx, 512
    59.        
    60. output_loop:
    61.         lodsb
    62.         test    al, 0xf0
    63.         jnz     cont_loop
    64.         mov     al,' '        
    65.        
    66. cont_loop:
    67.        
    68.         pusha
    69.         xor     bx, bx
    70.         mov     ah, 0x0e
    71.         int     0x10
    72.         popa
    73.        
    74.         loop    output_loop
    75.        
    76. end_loop:
    77.        
    78.         jmp     $
    79.        
    80. ; Read Sector In LBA Mode
    81. ;   DX:AX = sector lba number
    82. ;   ES:BX = buffer address
    83. ;   CX    = sector count
    84. read_sectors_lba:
    85.         pusha
    86.        
    87. ; Fill Disk Address Packet
    88.         mov     si, dap                 ; DS:SI -> dap
    89.         mov     [dap_lba], ax           ; dap.lba   = ax
    90.         mov     [dap_lba+2], dx         ; dap.lba+2 = dx
    91.         mov     [dap_buf_off], bx       ; dap.b_off = bx
    92.         mov     ax, es
    93.         mov     [dap_buf_seg], ax       ; dap.b_seg = es
    94.         mov     [dap_count], cx         ; dap.count = cx
    95.  
    96. ; Call Read Function Until Success
    97. retry_read:
    98.         mov     ah, 0x42
    99.         mov     dl, 0x80
    100.         int     0x13
    101.         jnc     ok_read
    102.  
    103.         pusha
    104.         xor     bx, bx
    105.         mov     ah, 0x0e
    106.         mov     al, '!'
    107.         int     0x10
    108.         popa        
    109.        
    110.         jmp     retry_read
    111.  
    112. ok_read:
    113.         popa
    114.         ret
    115.        
    116. ;-------------------------------------------------------------------------------
    117. ; Disk address packet
    118. SearchEntry:        db      'XLOAD   COM'
    119. FATSector:          dw      0xffff
    120.  
    121. dap:
    122. dap_size:           db      0x10
    123. dap_reserved:       db      0
    124. dap_count:          dw      0
    125. dap_buf_off:        dw      0
    126. dap_buf_seg:        dw      0
    127. dap_lba:            dd      0, 0
    128.  
    129. CluSize:            dw      1024   ; Variable for cluster size store
    130. FirstCluster:       dw      32+41
    131.  
    132. ;-------------------------------------------------------------------------------
    133. ; Align end to 512 bytes and put boot signature
    134. times   (BOOT_SECTOR_SIZE-2-VOLUME_INFO_SIZE-($-$$)) db  0xff
    135.  
    136. vol0_desc:  dd  0,0,0,0     ; Volume 0 Descriptor
    137. vol1_desc:  dd  0,0,0,0     ; Volume 1 Descriptor
    138. vol2_desc:  dd  0,0,0,0     ; Volume 2 Descriptor
    139. vol3_desc:  dd  0,0,0,0     ; Volume 3 Descriptor
    140.  
    141. dw      BOOT_SIGNATURE
    142.  
    143. disk_buffer:
     
  2. diamond

    diamond New Member

    Публикаций:
    0
    Регистрация:
    21 май 2004
    Сообщения:
    507
    Адрес:
    Russia
    А учитывается, что на флешках обычно существует MBR и при записи образа в логический диск \\.\X: сектор образа 0x41 попадает в совсем другой сектор физического диска? При тестировании в Bochs и qemu, возможно, образ использовался как таковой, а при физической записи на флешку это нужно учитывать.
     
  3. SadKo

    SadKo Владимир Садовников

    Публикаций:
    8
    Регистрация:
    4 июн 2007
    Сообщения:
    1.610
    Адрес:
    г. Санкт-Петербург
    В данном случае вам предоставлен код MBR. В 0x41-ом секторе я 100% знаю, какие находятся данные. Код MBR не выводит их, если первые 0x3c байт - не нули (исключая, конечно, jmp).
     
  4. int2eh

    int2eh Alexander Leevy

    Публикаций:
    0
    Регистрация:
    19 авг 2007
    Сообщения:
    106
    Адрес:
    Москва
    SadKo
    Сразу после jmp идет инфо о носителе затем код загрузчика (на него то jmp и нужен) и в конце таблица разделов, например, для дискеты 3.5" номер лог. сектора вычисляется по формуле (см. справочник Кулакова) и не как у флешки. Это я к тому - попробуйте использовать старый-добрый сервис/прерывание БИОС с использованием C:H:S
     
  5. int2eh

    int2eh Alexander Leevy

    Публикаций:
    0
    Регистрация:
    19 авг 2007
    Сообщения:
    106
    Адрес:
    Москва
    SadKo
    Ахтунг!!! Вычисляйте адреса в своём коде примерно так:
    Код (Text):
    1.     call label_base
    2. label_base:
    3.     pop eax
    4.     add eax, dap_buf_seg - label_base ; и теперь в eax будет правильный адрес для переменной/метки dap_buf_seg
     
  6. SadKo

    SadKo Владимир Садовников

    Публикаций:
    8
    Регистрация:
    4 июн 2007
    Сообщения:
    1.610
    Адрес:
    г. Санкт-Петербург
    А чем это лучше, если я просто задам org 0x7c00? Сорри, в коде не указал, что эта директива есть. Исправлю.
     
  7. SadKo

    SadKo Владимир Садовников

    Публикаций:
    8
    Регистрация:
    4 июн 2007
    Сообщения:
    1.610
    Адрес:
    г. Санкт-Петербург
    Старый добрый сервис работает у меня на дискете. Моя же задача - как раз написать загрузчик с исользованием расширенного дискового сервиса. Мало того, я не знаю параметров CHS моей флешки.
     
  8. int2eh

    int2eh Alexander Leevy

    Публикаций:
    0
    Регистрация:
    19 авг 2007
    Сообщения:
    106
    Адрес:
    Москва
    SadKo
    1. Адреса лучше программно находить, чем в коде их вписывать
    2. Очень выручит Вас книга В. Кулакова http://www.pcports.ru/files/lib/kulakov.rar
     
  9. SadKo

    SadKo Владимир Садовников

    Публикаций:
    8
    Регистрация:
    4 июн 2007
    Сообщения:
    1.610
    Адрес:
    г. Санкт-Петербург
    Спасибо, эта книжка у меня есть.
    Так всё же, объясните мне этот факт: код одинаковый, а вот bios в одном из случаев не хочет грузить.
     
  10. int2eh

    int2eh Alexander Leevy

    Публикаций:
    0
    Регистрация:
    19 авг 2007
    Сообщения:
    106
    Адрес:
    Москва
    Не знаю... ну, может LBA в БИОС отключен? :dntknw:
    - Проверьте это три раза (один раз - это секс, три раза -это уже наука :) ) и оставьте как есть ;)
     
  11. SadKo

    SadKo Владимир Садовников

    Публикаций:
    8
    Регистрация:
    4 июн 2007
    Сообщения:
    1.610
    Адрес:
    г. Санкт-Петербург
    Подтверждено эмпирически :).
    Если ситуация 1 - всё ОК, если ситуация 2 - полная лажа. В 100% случаев (а проверял я не раз и поочереди).
     
  12. SadKo

    SadKo Владимир Садовников

    Публикаций:
    8
    Регистрация:
    4 июн 2007
    Сообщения:
    1.610
    Адрес:
    г. Санкт-Петербург
    Так кто что ещё может мне посоветовать?
     
  13. diamond

    diamond New Member

    Публикаций:
    0
    Регистрация:
    21 май 2004
    Сообщения:
    507
    Адрес:
    Russia
    Может, утилита при создании образа немного портит бутсектор и не только изменяет первые 0x3c байт, но и по ошибке перезаписывает что-то в середине? Типа какого-нибудь выхода за границы какого-нибудь массива? Выглядит малоубедительно, но ошибки чтения в коде BIOS, появляющиеся только при ненулевых значениях в MBR - это уже что-то из области ненаучной фантастики.
    Кстати, несколько странно, что один и тот же сектор планируется и как MBR, и как BPB-содержащий - всё-таки таблица разделов не должна входить в указываемый самой собой раздел. Но BIOS вообще не в курсе существования разделов, так что к заданному вопросу это отношения не имеет.
     
  14. SadKo

    SadKo Владимир Садовников

    Публикаций:
    8
    Регистрация:
    4 июн 2007
    Сообщения:
    1.610
    Адрес:
    г. Санкт-Петербург
    Нет, я в этом уверен - лично сверял :).

    Вот и я тоже в недоумении: какое дело Биосу, что там в MBR творится?

    Это всего лишь следствие того, что я пока не написал MBR. Поэтому просто решил из флешки сделать диск без разделов, соответственно MBR == SMBR. А место под Volume Table всё равно надо оставлять (для extended-разделов).

    Я хотел проверить, как работает ФС. Сейчас заступорился на чтении сектора.
     
  15. SadKo

    SadKo Владимир Садовников

    Публикаций:
    8
    Регистрация:
    4 июн 2007
    Сообщения:
    1.610
    Адрес:
    г. Санкт-Петербург
    Значит, последние мои наблюдения: попытался вывести нулевой сектор диска. Что самое забавное, bios мне выдал содержимое нулевого сектора жёсткого диска, а не flash. Спрашивается - как можно узнать номер диска (который будет потом помещаться в dl), с которого производится загрузка?
     
  16. diamond

    diamond New Member

    Публикаций:
    0
    Регистрация:
    21 май 2004
    Сообщения:
    507
    Адрес:
    Russia
    Его BIOS помещает в dl непосредственно перед передачей управления бутсектору. Хотя вообще-то обычно BIOS'ы стараются делать так, чтобы идентификатор загрузочного диска был бы всегда 80h (или 0 для дискеты), перемешивая "настоящие" идентификаторы - для совместимости (стандартный MBR, например, всегда считает, что загрузка происходит с диска 80h).
     
  17. SadKo

    SadKo Владимир Садовников

    Публикаций:
    8
    Регистрация:
    4 июн 2007
    Сообщения:
    1.610
    Адрес:
    г. Санкт-Петербург
    Итак, шоу начинается...
    Случай 1 и случай 2, как водится. Случай 1 - состояние регистров:

    Код (Text):
    1. #   dx   cx   si   di
    2. 1  0000 0001 0003 0000
    3. 2  0080 0001 0005 0000
    И как это называется???
     
  18. Pavia

    Pavia Well-Known Member

    Публикаций:
    0
    Регистрация:
    17 июн 2003
    Сообщения:
    2.409
    Адрес:
    Fryazino
    SadKo
    Все верно. Флешку можно воспринимать как флопи и как диск. Зависит он настройки в биосе. А еще есть такая вещь как поддержка функции 42h ее лучше использовать для больших дисков а с малыми она может и не работать.
     
  19. int2eh

    int2eh Alexander Leevy

    Публикаций:
    0
    Регистрация:
    19 авг 2007
    Сообщения:
    106
    Адрес:
    Москва
    SadKo

    1. Я уже, правда, повторяюсь, но всёже: когда настанет время загрузить стандартный MBR (а у него тоже base = 0000:7C000h) и передать ему управление, Вы, тогда вспомните и обо мне, т.е. о моём 2 посте в данной теме. Ведь компилять свой код неудобно, например, с ORG (7С00h + 200h) и с самого начала и до переноса "самого себя" в новое место бояться использовать абсолютные адреса своих данных.
    2. По вопросу о разных значениях в DL номера привода из-за инфы о носителе в MBR могу сказать только одно: если пишите свой MBR на винт, то используйте 80h для ссылки на самого себя, а если на сменный носитель – 0. Хм... :) если что, то все ошибки можно всегда списать на Большой адронный коллайдер!
     
  20. SadKo

    SadKo Владимир Садовников

    Публикаций:
    8
    Регистрация:
    4 июн 2007
    Сообщения:
    1.610
    Адрес:
    г. Санкт-Петербург
    Ну вы меня уж совсем за идиота не держите. MBR копирует себя обычно адресом 0x200 ниже, чем 0x7c00, после чего передаёт туда управление. BIOS вообще должно быть до лампочки, что за код и данные находятся в MBR или SMBR. Она должна передать и успокоиться, ждать либо int 0x18, либо int 0x19.

    Вот в том-то и дело, что не 0. И не 0x80. Надо с разработчиками Award BIOS'а, наверное, связаться.