Traditional 'cannot load < 1 MB' grub error message

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.
Post Reply
uzytkownik
Posts: 14
Joined: Sat Nov 15, 2008 3:39 pm

Traditional 'cannot load < 1 MB' grub error message

Post by uzytkownik »

I'm starting the adventures with OS dev. I tried to move the kernel into highier half. I tried to follow more or less Higher Half With GDT.

Code: Select all

% cat multiboot.S
#define STACK_SIZE 0x4000

.text
	.globl  start, _start
start:
_start:
	jmp     multiboot_entry
	.align  4
multiboot_header:
	.long 	0x1BADB002 			/* Magick */
	.long 	0x00010003 			/* Flags [ELF] */
	.long 	-(0x1BADB002 + 0x00010003) 	/* Checksum */
	.long 	multiboot_header
	.long 	code
	.long 	data
	.long 	end
	.long 	multiboot_entry

	.globl  start, _start
multiboot_entry:	
	lgdt    (startgdt)
	movw    $0x10, %ax
	movw    %ax,   %ds
	movw    %ax,   %es
	movw    %ax,   %fs
	movw    %ax,   %gs
	movw    %ax,   %ss

	ljmp    $0x08, $hh_start
hh_start:	
	movl 	$(stack + STACK_SIZE), %esp  	/* Initalize stack pointer */

	pushl   $0				/* Reset EFLAGS */
	popf

	pushl	%ebx
	pushl	%eax

	call	kstart

	.lcomm stack, STACK_SIZE
	
.section .setup
startgdt:
	.byte 0x00, 0x00, 0, 0, 0, 0b00000000, 0b00000000, 0x00
	.byte 0xFF, 0xFF, 0, 0, 0, 0b10011010, 0b11001111, 0x40
	.byte 0xFF, 0xFF, 0, 0, 0, 0b10010010, 0b11001111, 0x40
gdt_end:
% cat linker.ld
OUTPUT_FORMAT("elf32-i386")
ENTRY(start)
phys = 0x00100000;
virt = 0xC0000000;
SECTIONS
{
	. = phys;
	.setup :
	{
		*(.setup)
	}
	. += virt;
	. = ALIGN(0x1000);
	.text : AT(ADDR(.text) - virt)
	{
		code = .;
		*(.text)
	}
	. = ALIGN(0x1000);
	.data : AT(ADDR(.data) - virt)
	{
		data = .;
		*(.data)
	}
	. = ALIGN(0x1000);
	.bss : AT(ADDR(.bss) - virt)
	{
		bss = .;
		*(COMMON)
		*(.bss)
	}
	. = ALIGN(0x1000);
	end = .;
}
% readelf -a nios
ELF Header:
  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF32
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           Intel 80386
  Version:                           0x1
  Entry point address:               0xc0101000
  Start of program headers:          52 (bytes into file)
  Start of section headers:          4292 (bytes into file)
  Flags:                             0x0
  Size of this header:               52 (bytes)
  Size of program headers:           32 (bytes)
  Number of program headers:         4
  Size of section headers:           40 (bytes)
  Number of section headers:         8
  Section header string table index: 5

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .setup            PROGBITS        00100000 001056 000018 00      0   0  1
  [ 2] .text             PROGBITS        c0101000 001000 000056 00  AX  0   0  4
  [ 3] .bss              NOBITS          c0102000 002000 004000 00  WA  0   0  8
  [ 4] .comment          PROGBITS        00000000 00106e 000020 00      0   0  1
  [ 5] .shstrtab         STRTAB          00000000 00108e 000036 00      0   0  1
  [ 6] .symtab           SYMTAB          00000000 001204 000150 10      7  12  4
  [ 7] .strtab           STRTAB          00000000 001354 00007a 00      0   0  1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings)
  I (info), L (link order), G (group), x (unknown)
  O (extra OS processing required) o (OS specific), p (processor specific)

There are no section groups in this file.

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  LOAD           0x001000 0xc0101000 0x00101000 0x00056 0x00056 R E 0x1000
  LOAD           0x002000 0xc0102000 0x00102000 0x00000 0x04000 RW  0x1000
  GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RWE 0x4
  PAX_FLAGS      0x000000 0x00000000 0x00000000 0x00000 0x00000     0x4

 Section to Segment mapping:
  Segment Sections...
   00     .text 
   01     .bss 
   02     
   03     

There is no dynamic section in this file.

There are no relocations in this file.

There are no unwind sections in this file.

Symbol table '.symtab' contains 21 entries:
   Num:    Value  Size Type    Bind   Vis      Ndx Name
     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 00100000     0 SECTION LOCAL  DEFAULT    1 
     2: c0101000     0 SECTION LOCAL  DEFAULT    2 
     3: c0102000     0 SECTION LOCAL  DEFAULT    3 
     4: 00000000     0 SECTION LOCAL  DEFAULT    4 
     5: c0101024     0 NOTYPE  LOCAL  DEFAULT    2 multiboot_entry
     6: c0101004     0 NOTYPE  LOCAL  DEFAULT    2 multiboot_header
     7: 00100000     0 NOTYPE  LOCAL  DEFAULT    1 startgdt
     8: c0101040     0 NOTYPE  LOCAL  DEFAULT    2 hh_start
     9: c0102000 16384 OBJECT  LOCAL  DEFAULT    3 stack
    10: 00100018     0 NOTYPE  LOCAL  DEFAULT    1 gdt_end
    11: 00000000     0 FILE    LOCAL  DEFAULT  ABS start.c
    12: 00100000     0 NOTYPE  GLOBAL DEFAULT  ABS phys
    13: c0000000     0 NOTYPE  GLOBAL DEFAULT  ABS virt
    14: c0106000     0 NOTYPE  GLOBAL DEFAULT  ABS end
    15: c0101000     0 NOTYPE  GLOBAL DEFAULT    2 _start
    16: c0102000     0 NOTYPE  GLOBAL DEFAULT    3 bss
    17: c0101050     6 FUNC    GLOBAL DEFAULT    2 kstart
    18: c0102000     0 NOTYPE  GLOBAL DEFAULT    3 data
    19: c0101000     0 NOTYPE  GLOBAL DEFAULT    2 code
    20: c0101000     0 NOTYPE  GLOBAL DEFAULT    2 start

No version information found in this file.

What is wrong?
JohnnyTheDon
Member
Member
Posts: 524
Joined: Sun Nov 09, 2008 2:55 am
Location: Pennsylvania, USA

Re: Traditional 'cannot load < 1 MB' grub error message

Post by JohnnyTheDon »

You used '.text' to declare that the entry code is in the .text. It souldn't be, it should be in .setup so grub loads it properly. Change '.text' to '.section .setup' and add '.section .text' right before hh_start.

However, I'm not sure why that would give you a "cannot load below 1MB message". Another issue might be making grub think you're trying to load below 1MB. The only thing I can think of is the STACK program header. You might want to add the -ffreestanding option when you run ld.
uzytkownik
Posts: 14
Joined: Sat Nov 15, 2008 3:39 pm

Re: Traditional 'cannot load < 1 MB' grub error message

Post by uzytkownik »

Thanks. The multiboot specifications requires physical adresses. For ELF it just uses the inside informations.

Still I have a a problem with GDT (despite finding one error) but I hope it will solve it soon.
JohnnyTheDon
Member
Member
Posts: 524
Joined: Sun Nov 09, 2008 2:55 am
Location: Pennsylvania, USA

Re: Traditional 'cannot load < 1 MB' grub error message

Post by JohnnyTheDon »

I think i found your problem. Your higher half kernel has its base at 0xc0000000. Unless I'm reading your code wrong, the GDT has its base at 0x40000000. That would certainly cause issues.
User avatar
Owen
Member
Member
Posts: 1700
Joined: Fri Jun 13, 2008 3:21 pm
Location: Cambridge, United Kingdom
Contact:

Re: Traditional 'cannot load < 1 MB' grub error message

Post by Owen »

0xC0000000 + 0x40000000 = 0x0000000. It's the higher half with GDT trick.
uzytkownik
Posts: 14
Joined: Sat Nov 15, 2008 3:39 pm

Re: Traditional 'cannot load < 1 MB' grub error message

Post by uzytkownik »

Code: Select all

#define STACK_SIZE 0x4000

.section .setup
	.globl start, _start
start:
_start:
	jmp multiboot_entry
	.align  4
multiboot_header:
	.long 	0x1BADB002 			/* Magick */
	.long 	0x00000003 			/* Flags [ELF] */
	.long 	-(0x1BADB002 + 0x00000003) 	/* Checksum */
multiboot_entry:
	lgdt    (start_gdt)
	movw    $0x10, %ax
	movw    %ax,   %ds
	movw    %ax,   %es
	movw    %ax,   %fs
	movw    %ax,   %gs
	movw    %ax,   %ss

	ljmp    $0x08, $hh_start

.text
hh_start:	
	movl 	$(stack + STACK_SIZE), %esp  	/* Initalize stack pointer */

	pushl   $0				/* Reset EFLAGS */
	popf

	pushl	%ebx
	pushl	%eax

	call	kstart

	.lcomm stack, STACK_SIZE
	
.section .setup
	.align 4
	.globl start_gdt, start_gdt_start
start_gdt:
	.word 2
	.long start_gdt_start
	.align 4
start_gdt_start:
	.byte 0x00, 0x00, 0, 0, 0, 0b00000000, 0b00000000, 0x00
	.byte 0xFF, 0xFF, 0, 0, 0, 0b10011010, 0b11001111, 0x40 /* 0x08 */
	.byte 0xFF, 0xFF, 0, 0, 0, 0b10010010, 0b11001111, 0x40 /* 0x10 */
start_gdt_end:
The problems seems to occure in lgdt. So the problem is in gdt table. If I chane 0x40 into 0x00 (and phys to 0x00000000) all seems to work.

Even if table looks like:

Code: Select all

start_gdt_start:
	.byte 0x00, 0x00, 0, 0, 0, 0b00000000, 0b00000000, 0x00
	.byte 0xFF, 0xFF, 0, 0, 0, 0b10011010, 0b11001111, 0x00 /* 0x08 */
	.byte 0xFF, 0xFF, 0, 0, 0, 0b10010010, 0b11001111, 0x00 /* 0x10 */
	.byte 0xFF, 0xFF, 0, 0, 0, 0b10011010, 0b11001111, 0x40 /* 0x18 */
	.byte 0xFF, 0xFF, 0, 0, 0, 0b10010010, 0b11001111, 0x40 /* 0x20 */
start_gdt_end:
It do not help.

What's wrong?
Post Reply