0

When using rep insw in 32-bit protected mode to load my kernel from disk to memory, how do I properly write the data to memory, and then execute it?

If I understand correctly, the data segment can be written to, but not executed, and the code segment can be executed but not written to.

I'm not having any problems doing this below the 1MB memory mark, but I want to load it right at 0x00100000.

My loading subroutine:

edi - destination in memory

esi - source LBA

ecx - number of sectors to write

ebx - return point

load32_source dd 0

load32:
    mov dword [load32_source], esi

    mov al, byte [load32_source + 3]
    or al, 0xe0
    mov dx, 0x1f6
    out dx, al

    mov dx, 0x1f1
    mov al, 0x00                    ; null to error
    out dx, al

    mov dx, 0x1f2                   ; sector count
    mov al, cl
    out dx, al

    mov al, byte [load32_source]
    mov dx, 0x1f3
    out dx, al

    mov al, byte [load32_source + 1]
    mov dx, 0x1f4
    out dx, al

    mov al, byte [load32_source + 2]
    mov dx, 0x1f5
    out dx, al

    mov dx, 0x1f7
    mov al, 0x20                    ; read sectors
    out dx, al

waitforit:
    in      al, dx
    test    al, 0x08
    jz      waitforit
    mov     eax, ecx
    mov     ecx, 0x00000100
    mul     ecx
    mov     ecx, eax
    mov     edx, 0x000001f0
    rep     insw

    jmp     ebx
Wyllow Wulf
  • 410
  • 4
  • 23
  • You should firstly load content of the code segment, and then protect it from writting. – Tsyvarev Sep 05 '17 at 20:36
  • Does that mean I have to load the kernel before entering protected mode? Or can I change the GDT after loading the kernel – Wyllow Wulf Sep 05 '17 at 20:40
  • Write using a data segment and execute using a code segment. – Margaret Bloom Sep 05 '17 at 20:43
  • 3
    You need to use a data segment that overlaps the code segment so you can use the data segment to write to the same memory the code segments uses. Normally 32-bit protected mode operating systems use a "flat" segmentation model where both the data segment and code segments have a base of 0 and a limit of 4 gigabytes. – Ross Ridge Sep 05 '17 at 21:08
  • `rep insw` . Did you write an ATA driver to read from the hard disk in protected mode? – Michael Petch Sep 05 '17 at 21:26
  • Normally the VBR remains in real mode uses the BIOS to read the disk so the code can be device independent. Supporting a wide range of boot devices takes more code than you can fit into a 512 byte boot block. – Ross Ridge Sep 05 '17 at 22:58
  • I wouldn't say a driver, but its a subroutine that uses ports and LBA to move from disk to memory. I'm still in the VBR, trying to load the kernel. I'll include it above. I can include my entire VBR code, but it's 4 pages – Wyllow Wulf Sep 05 '17 at 22:59
  • Yeah, I should probably use BIOS in the VBR, and wait until kernel to go to protected mode, I just hate using CHS, prefer LBA.. is INT 13h AH=42h widely supported? – Wyllow Wulf Sep 05 '17 at 23:03
  • The EDD interfaces are widely supported, since the older CHS interfaces only support drives up to 8GB, and it's been a long time since you could buy a hard disk that small. – Ross Ridge Sep 06 '17 at 00:36
  • weird thing is, whenever I try to load it to 0x00100000, it ends up at 0x00000000, is there something that would be preventing me from using above 1mb? If i use the exact same code but put 0x00030000 in EDI it works fine – Wyllow Wulf Sep 06 '17 at 03:55
  • 3
    Did you enable the A20 line? – Michael Petch Sep 06 '17 at 05:02
  • okay that was my problem, not enabling a20. Not having any problem writing and jumping to 0x00100000 now... thanks y'all! – Wyllow Wulf Sep 06 '17 at 22:08

0 Answers0