OS memory structure

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Pestilence

Re:OS memory structure

Post by Pestilence »

Silverhawk wrote: So, according to you, this is the only way to do the job being full multiboot compliant ?
No, I don't know if it's the only way, there may be better ones. Depends on how you want to do it.
Silverhawk

Re:OS memory structure

Post by Silverhawk »

So, as I've promised, I've tried to code :

1) For setting up a temporary GDT with segments with bases of 0x40100000, I need to have my piece of code linked at 0x100000 in order to grub gives me the hand. no ?

2) Then, if I want my kernel to be located at virtual address 0xC0000000, I need to link the other part of my kernel at 0xC0000000.

The result is that I've my kernel covering 0x100000 to 0xC0000000 and a little more... So Bochs gives me the following error : "Error 28 : Selected Item cannot fit into memory" that seems normal !

What's the correct way to do it ?

Here's my code :

Code: Select all


[bits 32]

[global startAfterGrub]    ; Entry point for the linker script
[extern paging_enable]      ; Function that enables paging (in paging_enable.asm)
[extern startKernel]      ; Entry point for the C kernel

[global gdt]         ; GDT start address
[global idt]         ; IDT start address

section .trampoline
startAfterGrub :

   ; We use a temporary GDT in order to jump at kernel virual address
   lgdt [gdt48_ptr]
   
   mov ax,GDT48_DATA_SEL
   mov ds,ax
   mov es,ax
   mov ss,ax
   mov fs,ax
   mov gs,ax
   jmp GDT48_CODE_SEL:startKernelASM

gdt48:

; NULL descriptor
   dw 0         ; limit 15:0
   dw 0         ; base 15:0
   db 0         ; base 23:16
   db 0         ; type
   db 0         ; limit 19:16, flags
   db 0         ; base 31:24

GDT48_CODE_SEL   equ   $-gdt48   ; use a base segment of 0x40100000, so the MMU will
   dw 0FFFFh      ; transform the offset startKernelASM = 0xC0000000
   dw 0         ; in 0xC0000000 + 0x40100000 = 4Gb + 1Mb, that will be
   db 10h         ; truncate into 1Mb...
   db 9Ah         ; present,ring 0,code,non-conforming,readable
   db 0CFh         ; page-granular (4 gig limit), 32-bit
   db 40h

GDT48_DATA_SEL   equ   $-gdt48
   dw 0FFFFh
   dw 0
   db 10h
   db 92h         ; present, ring 0, data, expand-up, writable
   db 0CFh         ; page-granular (4 gig limit), 32-bit
   db 40h
   
gdt48_end:

gdt48_ptr:
   dw gdt48_end - gdt48 - 1
   dd gdt48

;-----------------------------------------------------------------------------;
;-----------------------------------------------------------------------------;
Section .text

startKernelASM : /* linked at 0xC0000000*/

   [...]

Section .multiboot
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Multiboot header for GRUB bootloader. This must be in the first 8K
; of the kernel file. We use the aout kludge so it works with ELF,
; DJGPP COFF, Win32 PE, or other formats.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

MULTIBOOT_PAGE_ALIGN   equ 1<<0
MULTIBOOT_MEMORY_INFO   equ 1<<1
MULTIBOOT_AOUT_KLUDGE   equ 1<<16
MULTIBOOT_HEADER_MAGIC   equ 0x1BADB002
MULTIBOOT_HEADER_FLAGS   equ MULTIBOOT_PAGE_ALIGN | MULTIBOOT_MEMORY_INFO | MULTIBOOT_AOUT_KLUDGE
MULTIBOOT_CHECKSUM   equ -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)

; these are in the linker script file
extern code, erodata, ebss

align 4
mboot:
   dd MULTIBOOT_HEADER_MAGIC
   dd MULTIBOOT_HEADER_FLAGS
   dd MULTIBOOT_CHECKSUM
; aout kludge. These must be PHYSICAL addresses
    dd mboot      ; Start address of the multiboot header
    dd code         ; Physical address of the begining of the code segment
    dd erodata      ; Physical address of end of data data segment
    dd ebss         ; Physical address of end of bss segment
    dd startAfterGrub   ; Physical address where boot loader give us the hand

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;-----------------------------------------------------------------------------;
;-----------------------------------------------------------------------------;
Section .data

[...] /* definitive GDT and IDT */

;-----------------------------------------------------------------------------;
;-----------------------------------------------------------------------------;
Section .bss

  resd 1024         ; 4ko Stack
stack:

And my linker script file :

Code: Select all

/* Generating elf binary format */
OUTPUT_FORMAT("elf32-i386","elf32-i386","elf32-i386")

/* Target architecture is i386 */
OUTPUT_ARCH("i386")

/* Entry point is startAfterGrub defined in jumToKernel.asm */
ENTRY(startAfterGrub)

/* Physical start address for the kernel */
Phys_Addr = 0x100000;    /* 1 mega */
Virt_Addr = 0xc0000000;

SECTIONS
{
  . = Phys_Addr;

  .multiboot ALIGN(4) :
  {
    *(.multiboot)
    . = ALIGN(4);
  }
  .trampoline :
  {
    *(.trampoline)
  }
  
  . = Virt_Addr;
  /* Section .text for code */
  .text ALIGN(4096) :
  {   
      code = .;
      *(.text*)
  }

  [...] /* and so on... */


All comments and criticals are welcomed !
Silverhawk

Re:OS memory structure

Post by Silverhawk »

Hi !
For those who are interested, I think I found a solution to my problem into grub tutorial : http://www.openbg.net/sto/os/xml/grub.html.

a solution may be, I quote :

Code: Select all

If the load address is beyond the end of RAM, you get error #28: Selected item cannot fit into memory.
[...]
Normally, the physical address is the same as the VMA, and is set either in the linker script or on the linker command line ("ld -Ttext=0x100000 ..."). If your version of 'ld' supports it, the physical and virtual addresses can be specified separately in the linker script using 'AT'
[...]
The remaining is in the page linked above.

I've try it, and it seems to work...
But I've another little problem, gdb now doesn't seem to stop on break point ! (for debugging, I use bochs gdb's stub)

see you.
Post Reply