OSDev

для всех
Текущее время: 02 май 2024, 22:05

Часовой пояс: UTC + 3 часа




Начать новую тему Ответить на тему  [ Сообщений: 10 ] 
Автор Сообщение
 Заголовок сообщения: Проблема с иниализацией системы
СообщениеДобавлено: 20 июл 2009, 20:59 
Мной пишется вторичный загрузчик (BootStrap). Предполагается, что в его задачи будет входить подкачка в память загрузчика ядра и переход в защищенный режим. А вот сама суть проблеммы: при любой попытке загрузить редистр дескрипторной таблицы прерываний с помощью инструкции lidt я получаю stack fault in kernel mode и иду нервно курить. Есди кто имеет возность, то объясните пожалуйста природу этого явления и, соответственно, как его лечить.

вот тот рабочий код, который я сейчас пинаю:
Код:
.386P
.model tiny

    F_TASK_RAM_ADDRESS = 04500h  ; first task address in memory
    KERNEL_RAM_ADDRESS = 02500h  ; loader address in memory
    LOADER_RAM_ADDRESS = 08000h  ; loader address in memory

CODE segment byte public 'CODE' use16
 
    assume CS:CODE
    assume DS:CODE
    assume ES:CODE
    assume FS:CODE
    assume GS:CODE
    assume SS:CODE

    org 7C00h
 
START:
    cli
    cld

    ; Init segment registers
    xor AX, AX
    mov DS, AX
    mov ES, AX
    mov FS, AX
    mov GS, AX
    mov SS, AX
   
    ; Preparing for disk operations
    mov SI, 07E00h
    mov DX, 00010h

    mov [SI     ], DX
    mov [SI + 3h], AL
    mov [SI + 4h], AX

    mov AH, 42h
    mov DL, 80h
   
    ; Read loader from disk to memory
    mov  BL       , LOADER_SIZE
    mov [SI + 02h], BL
    mov  BX       , LOADER_RAM_ADDRESS
    mov [SI + 06h], BX
    mov EBX       , LOADER_HDD_ADDR_1
    mov [SI + 08h], EBX
    mov EBX       , LOADER_HDD_ADDR_2
    mov [SI + 0Ch], EBX
   
    int 13h
    jc  ERROR
   
    ; Read Kernel from disk to memory
    mov  BL       , KERNEL_SIZE
    mov [SI + 02h], BL
    mov  BX       , KERNEL_RAM_ADDRESS
    mov [SI + 06h], BX
    mov EBX       , KERNEL_HDD_ADDR_1
    mov [SI + 08h], EBX
    mov EBX       , KERNEL_HDD_ADDR_2
    mov [SI + 0Ch], EBX

    int 13h
    jc  ERROR

    ; Read First task from disk to memory
    mov  BL       , F_TASK_SIZE
    mov [SI + 02h], BL
    mov  BX       , F_TASK_RAM_ADDRESS
    mov [SI + 06h], BX
    mov EBX       , F_TASK_HDD_ADDR_1
    mov [SI + 08h], EBX
    mov EBX       , F_TASK_HDD_ADDR_2
    mov [SI + 0Ch], EBX
   
    int 13h
    jc  ERROR

; IDT
    xor EAX, EAX
    mov ECX, 0200h
    mov EDI, 0500h
    rep stosw

    lidt 0000h:7DA3h

; GDT
    mov BP, 0900h

    mov dword ptr [BP      ], 000000000h
    mov dword ptr [BP + 04h], 000000000h
    mov dword ptr [BP + 08h], 00000FFFFh;
    mov dword ptr [BP + 0Ch], 000CF9200h;
    mov dword ptr [BP + 0Fh], 00000FFFFh;
    mov dword ptr [BP + 14h], 000CF9A00h;

    mov CX, 001F4h
    mov DI, 00918h
    rep stosw

    lgdt GDT_TABLE
   
    mov BX, 00010h

    mov DS, BX
    mov SS, BX
    mov ES, BX
    mov FS, BX
    mov GS, BX

    mov EAX, CR0
    or  EAX, 01h
    mov CR0, EAX

    jmp FLUSH_PREFETCH_QUEUE

FLUSH_PREFETCH_QUEUE:
   
    jmp dword ptr DS:8000h

ERROR:
    lea SI, ERROR_STRING
PRINT:
    lodsb
    test AL, AL
HANG:
    jz HANG
   
    mov AH, 0Eh
    mov BX, 01h
   
    int 10h

    jmp PRINT

    PLACEHOLDER        db 092h DUP(0)
   
IDT_T:
    IDT_TABLE          df 0000000000000h
    GDT_TABLE          df 0000009000400h

    ERROR_STRING       db "Disk read ERROR ocurred on loading kernel loader!!!", 0
   
    F_TASK_SIZE        db 0000h
    F_TASK_HDD_ADDR_1  dd 0000h
    F_TASK_HDD_ADDR_2  dd 0000h

    KERNEL_SIZE        db 0000h
    KERNEL_HDD_ADDR_1  dd 0000h
    KERNEL_HDD_ADDR_2  dd 0000h

    LOADER_SIZE        db 0000h
    LOADER_HDD_ADDR_1  dd 0000h
    LOADER_HDD_ADDR_2  dd 0000h

    MAGIC_WORD         dw 0AA55h

CODE ENDS

END START


Вернуться к началу
  
 
СообщениеДобавлено: 21 июл 2009, 03:41 
тоже мне проблема... побольше конопли курить нада и поменьше пейсать гуано кода.


Вернуться к началу
  
 
СообщениеДобавлено: 21 июл 2009, 11:17 

Зарегистрирован: 28 окт 2007, 18:33
Сообщения: 1418
Пример перехода в защищёнку вроде есть в интеловском мануале. Насколько помню, после собственно перехода в него надо инициализировать TSS и загрузить соответствующим образом TR, и только потом заниматься всем прочим. Но смотреть в документацию лень :)

Пы.Сы. А нафиг _начальному_ загрузчику переходить в защищённый режим?


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 21 июл 2009, 17:13 
Вот пример из INTEL 80386 PROGRAMMER'S REFERENCE MANUAL 1986:

Код:
$TITLE ('Initial Task')
    NAME    INIT
init_stack  SEGMENT RW
            DW  20  DUP(?)
tos         LABEL   WORD
init_stack  ENDS
init_data   SEGMENT RW PUBLIC
            DW  20  DUP(?)
init_data   ENDS
init_code   SEGMENT ER PUBLIC
ASSUME      DS:init_data
    nop
    nop
    nop
init_start:
                                    ; set up stack
    mov ax, init_stack
    mov ss, ax
    mov esp, offset tos
    mov a1,1
blink:
    xor a1,1
    out 0e4h,a1
    mov cx,3FFFh
here:
    dec cx
    jnz here
    jmp SHORT blink
    hlt
init_code   ends
    END init_start, SS:init_stack, DS:init_data
$TITLE('Protected Mode Transition -- 386 initialization')
NAME  RESET
;*****************************************************************
; Upon reset the 386 starts executing at address 0FFFFFFF0H.  The
; upper 12 address bits remain high until a FAR call or jump is
; executed.
;
; Assume the following:
;
;
; -  a short jump at address 0FFFFFFF0H (placed there by the
;    system builder) causes execution to begin at START in segment
;    RESET_CODE.
;
;
; -  segment RESET_CODE is based at physical address 0FFFF0000H,
;    i.e.   at the start of the last  64K in the 4G address space.
;    Note that  this is the base of the CS register at reset.  If
;    you locate ROMcode above  this  address,  you  will  need  to
;    figure out an adjustment factor to address things within this
;    segment.
;
;*****************************************************************
$EJECT ;
; Define addresses to locate GDT and IDT in RAM.
; These addresses are also used in the BLD386 file that defines
; the GDT and IDT. If you change these addresses, make sure you
; change the base addresses specified in the build file.
GDTbase         EQU    00001000H   ; physical address for GDT base
IDTbase         EQU    00000400H   ; physical address for IDT base
PUBLIC     GDT_EPROM
PUBLIC     IDT_EPROM
PUBLIC     START
DUMMY      segment rw      ; ONLY for ASM386 main module stack init
           DW 0
DUMMY   ends
;*****************************************************************
;
; Note: RESET CODE must be USEl6 because the 386 initally executes
;       in real mode.
;
RESET_CODE segment er PUBLIC    USE16
ASSUME DS:nothing, ES:nothing
;
; 386 Descriptor template
DESC       STRUC
    lim_0_15    DW  0              ; limit bits (0..15)
    bas_0_15    DW  0              ; base bits (0..15)
    bas_16_23   DB  0              ; base bits (16..23)
    access      DB  0              ; access byte
    gran        DB  0              ; granularity byte
    bas_24_31   DB  0              ; base bits (24..31)
DESC       ENDS
; The following is the layout of the real GDT created by BLD386.
; It is located in EPROM and will be copied to RAM.
;
; GDT[O]      ...  NULL
; GDT[1]      ...  Alias for RAM GDT
; GDT[2]      ...  Alias for RAM IDT
; GDT[2]      ...  initial task TSS
; GDT[3]      ...  initial task TSS alias
; GDT[4]      ...  initial task LDT
; GDT[5]      ...  initial task LDT alias
;
; define entries in GDT and IDT.
GDT_ENTRIES    EQU    8
IDT_ENTRIES    EQU    32
; define some constants to index into the real GDT
GDT_ALIAS      EQU    1*SIZE DESC
IDT_ALIAS      EQU    2*SIZE DESC
INIT_TSS       EQU    3*SIZE DESC
INIT_TSS_A     EQU    4*SIZE DESC
INIT_LDT       EQU    5*SIZE DESC
INIT_LDT_A     EQU    6*SIZE DESC
;
; location of alias in INIT_LDT
INIT_LDT_ALIAS    EQU    1*SIZE DESC
;
; access rights byte for DATA and TSS descriptors
DS_ACCESS   EQU   010010010B
TSS_ACCESS  EQU   010001001B
;
; This temporary GDT will be used to set up the real GDT in RAM.
Temp_GDT    LABEL   BYTE        ; tag for begin of scratch GDT
NULL_DES    DESC <>             ; NULL descriptor
                                ; 32-Gigabyte data segment based at 0
FLAT_DES    DESC <0FFFFH,0,0,92h,0CFh,0>
GDT_eprom     DP    ?           ; Builder places GDT address and limit
                                ; in this 6 byte area.
IDT_eprom     DP    ?           ; Builder places IDT address and limit
                                ; in this 6 byte area.
;
; Prepare operand for loadings GDTR and LDTR.
TGDT_pword     LABEL  PWORD                 ; for temp GDT
        DW     end_Temp_GDT_Temp_GDT -1
        DD     0
GDT_pword      LABEL  PWORD                 ; for GDT in RAM
        DW     GDT_ENTRIES * SIZE DESC -1
        DD     GDTbase
IDT_pword      LABEL   PWORD                ; for IDT in RAM
        DW     IDT_ENTRIES * SIZE DESC -1
        DD     IDTbase
end_Temp_GDT   LABEL   BYTE
;
; Define equates for addressing convenience.
GDT_DES_FLAT        EQU DS:GDT_ALIAS +GDTbase
IDT_DES_FLAT        EQU DS:IDT_ALIAS +GDTbase
INIT_TSS_A_OFFSET   EQU DS:INIT_TSS_A
INIT_TSS_OFFSET     EQU DS:INIT_TSS
INIT_LDT_A_OFFSET   EQU DS:INIT_LDT_A
INIT_LDT_OFFSET     EQU DS:INIT_LDT
; define pointer for first task switch
ENTRY POINTER LABEL DWORD
             DW 0, INIT_TSS
;******************************************************************
;
;   Jump from reset vector to here.
START:
    CLI                ;disable interrupts
    CLD                ;clear direction flag
    LIDT    NULL_des   ;force shutdown on errors
;
;   move scratch GDT to RAM at physical 0
    XOR DI,DI
    MOV ES,DI           ;point ES:DI to physical location 0
    MOV SI,OFFSET Temp_GDT
    MOV CX,end_Temp_GDT-Temp_GDT        ;set byte count
    INC CX
;
;   move table
    REP MOVS BYTE PTR ES:[DI],BYTE PTR CS:[SI]
    LGDT    tGDT_pword                ;load GDTR for Temp. GDT
                                      ;(located at 0)
;   switch to protected mode
    MOV EAX,CR0                       ;get current CRO
    MOV EAX,1                         ;set PE bit
    MOV CRO,EAX                       ;begin protected mode
;
;   clear prefetch queue
    JMP SHORT flush
flush:
; set DS,ES,SS to address flat linear space (0 ... 4GB)
    MOV BX,FLAT_DES-Temp_GDT
    MOV US,BX
    MOV ES,BX
    MOV SS,BX
;
; initialize stack pointer to some (arbitrary) RAM location
    MOV ESP, OFFSET end_Temp_GDT
;
; copy eprom GDT to RAM
    MOV ESI,DWORD PTR GDT_eprom +2 ; get base of eprom GDT
                                   ; (put here by builder).
    MOV EDI,GDTbase                ; point ES:EDI to GDT base in RAM.
    MOV CX,WORD PTR gdt_eprom +0   ; limit of eprom GDT
    INC CX
    SHR CX,1                       ; easier to move words
    CLD
    REP MOVS   WORD PTR ES:[EDI],WORD PTR DS:[ESI]
;
; copy eprom IDT to RAM
;
    MOV ESI,DWORD PTR IDT_eprom +2 ; get base of eprom IDT
                                   ; (put here by builder)
    MOV EDI,IDTbase                ; point ES:EDI to IDT base in RAM.
    MOV CX,WORD PTR idt_eprom +0   ; limit of eprom IDT
    INC CX
    SHR CX,1
    CLD
    REP MOVS   WORD PTR ES:[EDI],WORD PTR DS:[ESI]
; switch to RAM GDT and IDT
;
    LIDT IDT_pword
    LGDT GDT_pword
;
    MOV BX,GDT_ALIAS               ; point DS to GDT alias
    MOV DS,BX
;
; copy eprom TSS to RAM
;
    MOV BX,INIT_TSS_A              ; INIT TSS A descriptor base
                                   ; has RAM location of INIT TSS.
    MOV ES,BX                      ; ES points to TSS in RAM
    MOV BX,INIT_TSS                ; get inital task selector
    LAR DX,BX                      ; save access byte
    MOV [BX].access,DS_ACCESS      ; set access as data segment
    MOV FS,BX                      ; FS points to eprom TSS
    XOR si,si                      ; FS:si points to eprom TSS
    XOR di,di                      ; ES:di points to RAM TSS
    MOV CX,[BX].lim_0_15           ; get count to move
    INC CX
;
; move INIT_TSS to RAM.
    REP MOVS BYTE PTR ES:[di],BYTE PTR FS:[si]
    MOV [BX].access,DH             ; restore access byte
;
; change base of INIT TSS descriptor to point to RAM.
    MOV AX,INIT_TSS_A_OFFSET.bas_0_15
    MOV INIT_TSS_OFFSET.bas_0_15,AX
    MOV AL,INIT_TSS_A_OFFSET.bas_16_23
    MOV INIT_TSS_OFFSET.bas_16_23,AL
    MOV AL,INIT_TSS_A_OFFSET.bas_24_31
    MOV INIT_TSS_OFFSET.bas_24_31,AL
;
; change INIT TSS A to form a save area for TSS on first task
; switch. Use RAM at location 0.
    MOV BX,INIT_TSS_A
    MOV WORD PTR [BX].bas_0_15,0
    MOV [BX].bas_16_23,0
    MOV [BX].bas_24_31,0
    MOV [BX].access,TSS_ACCESS
    MOV [BX].gran,O
    LTR BX                         ; defines save area for TSS
;
; copy eprom LDT to RAM
    MOV BX,INIT_LDT_A              ; INIT_LDT_A descriptor has
                                   ; base address in RAM for INIT_L
    MOV ES,BX                      ; ES points LDT location in RAM.
    MOV AH,[BX].bas_24_31
    MOV AL,[BX].bas_16_23
    SHL EAX,16
    MOV AX,[BX].bas_0_15           ; save INIT_LDT base (ram) in EA
    MOV BX,INIT_LDT                ; get inital LDT selector
    LAR DX,BX                      ; save access rights
    MOV [BX].access,DS_ACCESS      ; set access as data segment
    MOV FS,BX                      ; FS points to eprom LDT
    XOR si,si                      ; FS:SI points to eprom LDT
    XOR di,di                      ; ES:DI points to RAM LDT
    MOV CX,[BX].lim_0_15           ; get count to move
    INC CX
;
; move initial LDT to RAM
    REP MOVS BYTE PTR ES:[di],BYTE PTR FS:[si]
    MOV [BX].access,DH             ; restore access rights in
                                   ; INIT_LDT descriptor
;
; change base of alias (of INIT_LDT) to point to location in RAM.
    MOV ES:[INIT_LDT_ALIAS].bas_0_15,AX
    SHR EAX,16
    MOV ES:[INIT_LDT_ALIAS].bas_16_23,AL
    MOV ES:[INIT_LDT_ALIAS].bas_24_31,AH
;
; now set the base value in INIT_LDT descriptor
    MOV AX,INIT_LDT_A_OFFSET.bas_0_15
    MOV INIT_LDT_OFFSET.bas_0_15,AX
    MOV AL,INIT_LDT_A_OFFSET.bas_16_23
    MOV INIT_LDT_OFFSET.bas_16_23,AL
    MOV AL,INIT_LDT_A_OFFSET.bas_24_31
    MOV INIT_LDT_OFFSET.bas_24_31,AL
;
; Now GDT, IDT, initial TSS and initial LDT are all set up.
;
; Start the first task!
'
   JMP ENTRY_POINTER
RESET_CODE ends
   END START, SS:DUMMY,DS:DUMMY



Как видно из фрагмента
Код:
START:
    CLI                ;disable interrupts
    CLD                ;clear direction flag
    LIDT    NULL_des   ;force shutdown on errors


они инициализируют IDTR в самом начале и если делать как они, то тогда все работает. Но меня интересует ПОЧЕМУ это уже не работает в том месте в котором это делаю я?

Цитата:
Пы.Сы. А нафиг _начальному_ загрузчику переходить в защищённый режим?

А почему бы и нет? Свободное место в BootStrape позволяет это сделать. Предполагается, что, что загрузчик ядра будет уже 32-битным, поэтому первую фазу перехода в защищенный режим(инициализацию IDTR и GDTR) я делаю в BootStrap, при дальнем переходе на код загрузчика я одновременно перехожу и в 32-битный режим. Вторая фаза инициализации защищенного режима будет выполняться уже загрузчиком ядра.


Вернуться к началу
  
 
СообщениеДобавлено: 21 июл 2009, 17:17 
Цитата:
тоже мне проблема... побольше конопли курить нада и поменьше пейсать гуано кода.

Если ты пишешь такой хороший код и куришь так много конопли, чего ж ты тогда не можешь ответить на такой простой вопрос? Хвастаться своей крутизной иди в школу, там народ редко видел что-то кроме паскаля. Хотя по стилю ответа складывается такое ощущение, что ты там еще и учишься.


Вернуться к началу
  
 
СообщениеДобавлено: 21 июл 2009, 17:30 

Зарегистрирован: 28 окт 2007, 18:33
Сообщения: 1418
Цитата:
А почему бы и нет? Свободное место в BootStrape позволяет это сделать. Предполагается, что, что загрузчик ядра будет уже 32-битным, поэтому первую фазу перехода в защищенный режим(инициализацию IDTR и GDTR) я делаю в BootStrap


Потому что вменяемую ось не сделаешь, не обращаясь на начальном этапе к БИОСу, а это значит, что надо скакать из реального в защищённой и обратно (ну или делать V86).


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 21 июл 2009, 20:32 
На первом этапе так и предполагалось делать по двум причинам: 1) ядро должно быть пуританским (чрезвычайно маленьким) и драйвера в ядро не входят, 2) чтобы была возможность постоянно наблюдать работу системы


Вернуться к началу
  
 
СообщениеДобавлено: 22 июл 2009, 20:02 

Зарегистрирован: 21 сен 2007, 17:24
Сообщения: 1088
Откуда: Балаково
Может быть рабочий пример пригодится
http://express-os.narod.ru/files/bs-fat12.asm
Замечу только по поводу инициализации IDT - здесь строить пустую таблицу абсолютно бессмысленно.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 23 июл 2009, 19:16 
Всем спасибо за замечания и ответы. Корень проблемы был успешно найден и нейтрализован. Он заключался в том, что регистр IDTR используется процессором как в защищенном так и в реальном режимах. Только по разному. Поэтому после моей инициализации процессор жил до первого прерывания.


Вернуться к началу
  
 
СообщениеДобавлено: 23 июл 2009, 22:34 

Зарегистрирован: 28 окт 2007, 18:33
Сообщения: 1418
А ларчик просто открывался... Я мог бы и догадаться: ведь я читал про последовательность перехода из защищённого режима в реальный, где перед переходом выполняются определённые пляски с бубном вокруг IDTR. Но забыл-с. Вот что значит знать такие вещи главным образом в теории :)


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 10 ] 

Часовой пояс: UTC + 3 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 30


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  
Создано на основе phpBB® Forum Software © phpBB Group
Русская поддержка phpBB