OSDev.org

The Place to Start for Operating System Developers
It is currently Tue Apr 23, 2024 3:30 pm

All times are UTC - 6 hours




Post new topic Reply to topic  [ 6 posts ] 
Author Message
 Post subject: Bootloader - LBA28 in Long Mode not working
PostPosted: Thu Aug 05, 2021 11:53 pm 
Offline

Joined: Thu Aug 05, 2021 11:50 pm
Posts: 2
After entering long mode from bootloader, copying the second sector in memory using LBA28 crashes the PC. The second sector was copied in memory in 32 bit mode. The crash happens when executing the instruction

Code:
rep insw

Is there a separate instruction for 64 bit mode?

I'm using Bochs as emualtor

Code:
Code:
   ; -- -----------------------------------------------------------------------------------------
   ; ----------------------------- Bootloader ( first sector ) ---------------------------------
   ; -------------------------------------------------------------------------------------------

   org 7C00h

   ; ---------------------------------------- Video Mode --------------------------------------------

   ; video mode 80x25:
    mov     ah, 00h
    mov     al, 03h
    int     10h

   ; hide blinking
    mov ch, 32
    mov ah, 1
    int 10h


   ; ---------------------------------------- 64 Bit Mode --------------------------------------------

   USE16

         cli                             ; disable the interrupts, just in
                                 ; case they are not disabled yet
         lgdt    [cs:GDTR]               ; load GDT register

         mov     eax,cr0                 ; switch to protected mode
         or      al,1
         mov     cr0,eax

         jmp     CODE_SELECTOR:pm_start


   NULL_SELECTOR = 0
   DATA_SELECTOR = 1 shl 3                 ; flat data selector (ring 0)
   CODE_SELECTOR = 2 shl 3                 ; 32-bit code selector (ring 0)
   LONG_SELECTOR = 3 shl 3                 ; 64-bit code selector (ring 0)

   GDTR:                                   ; Global Descriptors Table Register
     dw 4*8-1                              ; limit of GDT (size minus one)
     dq GDT                                ; linear address of GDT

   GDT rw 4                                ; null desciptor
      dw 0FFFFh,0,9200h,08Fh              ; flat data desciptor
      dw 0FFFFh,0,9A00h,0CFh              ; 32-bit code desciptor
      dw 0FFFFh,0,9A00h,0AFh              ; 64-bit code desciptor

         USE32

   pm_start:

         mov     eax,DATA_SELECTOR       ; load 4 GB data descriptor
         mov     ds,ax                   ; to all data segment registers
         mov     es,ax
         mov     fs,ax
         mov     gs,ax
         mov     ss,ax

         mov     eax,cr4
         or      eax,1 shl 5
         mov     cr4,eax                 ; enable physical-address extensions

         mov     edi,70000h
         mov     ecx,4000h shr 2
         xor     eax,eax
         rep     stosd                   ; clear the page tables

         mov     dword [70000h],71000h + 111b ; first PDP table
         mov     dword [71000h],72000h + 111b ; first page directory
         mov     dword [72000h],73000h + 111b ; first page table

         mov     edi,73000h              ; address of first page table
         mov     eax,0 + 111b
         mov     ecx,256                 ; number of pages to map (1 MB)
     make_page_entries:
         stosd
         add     edi,4
         add     eax,1000h
         loop    make_page_entries

         mov     eax,70000h
         mov     cr3,eax                 ; load page-map level-4 base

         mov     ecx,0C0000080h          ; EFER MSR
         rdmsr
         or      eax,1 shl 8             ; enable long mode
         wrmsr

         mov     eax,cr0
         or      eax,1 shl 31
         mov     cr0,eax                 ; enable paging

         jmp     LONG_SELECTOR:long_start

         USE64

   long_start:

         ; mov     rax,'L O N G '
         ;mov     [0B8000h],rax


   ; ---------------------------------------- Load Data --------------------------------------------

   mov     dx,0x1F1
   mov     al,0h
   out     dx,al

   mov     dx,1f2h
   mov     al,2          ; number of sectors to read
   out     dx,al


   mov     dx,1f3h
   mov     al,1        ; 4 8 8 [8]
   out     dx,al

   mov     dx,1f4h
   mov     al,0        ; 4 8 [8] 8
   out     dx,al

   mov     dx,1f5h        ; 4 [8] 8 8
   mov     al,0
   out     dx,al

   mov     dx,0x1F6
   mov     al,0xE0
   out     dx,al


   mov     dx,1f7h
   mov     al,20h   ; 20h read   30h write
   out     dx,al

   mov ecx, 4

   loop1:
         mov dx, 1F7h
         in al, dx

         test al, 10000000b
         jnz short retry
         test al, 00001000b
         jnz short data_ready
   retry:
         dec ecx
         jg short loop1
   loop2:
         mov dx, 1F7h
         in al, dx

         test al, 10000000b   ; Check BSY
         jnz short loop2
         test al, 00100001b   ; Check ERR and DF
         jnz short fail
   data_ready:

         mov dx, 0x1F0
         mov cx, 256*2
         mov edi, 2000000

         rep insw

         mov     rax,'L O N G '
         mov     [0B8000h],rax

        hlt

   fail:
         mov     rax,'F A I L '
         mov     [0B8000h],rax
   hlt


   ; fill witgh zeroes the rest
   times 510-($-$$) db 0
   dw 0xAA55

   ; -------------------------------------------------------------------------------------------
   ; ----------------------------- Kernel ( second sector ) ---------------------------------
   ; -------------------------------------------------------------------------------------------

   org 0


         mov     rax,'L O N 3 '
         mov     [0B8000h],rax


         hlt
    times 512*3-($-$$) db 0


Top
 Profile  
 
 Post subject: Re: Bootloader - LBA28 in Long Mode not working
PostPosted: Fri Aug 06, 2021 12:23 am 
Offline
Member
Member

Joined: Wed Mar 30, 2011 12:31 am
Posts: 676
Quote:
Code:
         mov     ecx,256                 ; number of pages to map (1 MB)

Quote:
Code:
         mov edi, 2000000

It sounds like you're only mapping the lowest 1MiB of memory but your destination starts around 1.9MiB.
Bochs should be able to tell you all the details of the fault that is occurring, such as if it is a page fault and what address.

_________________
toaruos on github | toaruos.org | gitlab | twitter | bim - a text editor


Top
 Profile  
 
 Post subject: Re: Bootloader - LBA28 in Long Mode not working
PostPosted: Fri Aug 06, 2021 12:53 am 
Offline

Joined: Thu Aug 05, 2021 11:50 pm
Posts: 2
I don't understand mapping. After testing, mov ecx, 256*2 ( I'm loading 2 sectors 512 Bytes each ) works for 1MB address location, it doesn't work for 2MB or greater. How do I load to larger addresses and how can I use 64 bit memory locations?

Jumping to the code loaded in memory worked in 32 bit mode by using

Code:
jmp CodeDescriptor:1000000


For 64 bit mode
Code:
jmp LONG_SELECTOR:1000000
or
Code:
jmp 1000000

doesn't work


Top
 Profile  
 
 Post subject: Re: Bootloader - LBA28 in Long Mode not working
PostPosted: Fri Aug 06, 2021 4:25 am 
Offline
Member
Member
User avatar

Joined: Sat Mar 31, 2012 3:07 am
Posts: 4594
Location: Chichester, UK
binary222 wrote:
I don't understand mapping.

And yet you are using page mapping.

This suggests that you are copy-pasting code without understanding what it is doing. This is not a good idea. I'd suggest that you read the appropriate Programmer's Manual, in particular the chapter(s) on memory management.


Top
 Profile  
 
 Post subject: Re: Bootloader - LBA28 in Long Mode not working
PostPosted: Fri Aug 06, 2021 9:08 am 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 5143
binary222 wrote:
using LBA28

And an IDE controller mapped at the legacy I/O ports. What will you do if the IDE controller is mapped at different ports, or the disk isn't attached to an IDE controller?

binary222 wrote:
insw

This instruction may read from the port without writing to memory if writing to memory causes an exception (such as a page fault).


Top
 Profile  
 
 Post subject: Re: Bootloader - LBA28 in Long Mode not working
PostPosted: Sat Aug 07, 2021 6:52 pm 
Offline
Member
Member

Joined: Mon Jul 05, 2021 6:57 pm
Posts: 118
binary222 wrote:
I don't understand mapping. After testing, mov ecx, 256*2 ( I'm loading 2 sectors 512 Bytes each ) works for 1MB address location, it doesn't work for 2MB or greater. How do I load to larger addresses and how can I use 64 bit memory locations?


I'm not sure what you mean by "works for 1MB address location", if you mean a location within the 1st MB, then that would make sense. As klange says, you've mapped only the 1st MB; anything beyond that will fault.

binary222 wrote:
The second sector was copied in memory in 32 bit mode


Without seeing the 32-bit code, it's impossible to say why it worked; if the only difference was 32-bit mode vs long mode, it shouldn't have worked for the same reason it doesn't work in long mode. Perhaps your 32-bit code was loading into <1MB range, or perhaps it hadn't enabled paging.

binary222 wrote:
I don't understand mapping


It sounds like it's time to take a step back. I suggest you go and read up on page mapping, starting with the relevant pages on the wiki, and ideally reading the relevant chapter in the Intel architecture manual (vol 3), until you understand what the code that sets up the page tables is actually doing. Then you should be able to see that it's not setting up a mapping for any address beyond 1MB.

With 4kb page tables each covering a linear address range of 1MB, you're going to need at least 2 pages to cover 2MB (should be enough for your current example), and more if you want to cover the rest of available RAM (assuming there is more than 2MB, which seems likely).


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 6 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: Google [Bot], Majestic-12 [Bot] and 129 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group