Feat: CPU Exceptions and load errors are now shown.

This commit is contained in:
AfonsoCMSousa 2025-11-18 22:58:28 +00:00
parent c1068d34e2
commit 9e4224793b
7 changed files with 692 additions and 238 deletions

BIN
SoraOS

Binary file not shown.

257
boot.asm
View File

@ -1,221 +1,94 @@
; File: boot.asm
[org 0x7c00] ; BIOS loads us at 0x7C00
[bits 16] ; We start in 16-bit Real Mode
; Stage 1 Bootloader (Master Boot Record - exactly 512 bytes)
; Job: Load Stage 2 from disk and jump to it
[org 0x7c00]
[bits 16]
STAGE2_OFFSET equ 0x7e00 ; Load stage2 right after boot sector
start:
; Set up segments
xor ax, ax
mov ds, ax
mov es, ax
mov ss, ax
mov sp, 0x7c00
; IMPORTANT: Save boot drive number (BIOS passes it in DL)
push dx
; Clear screen
mov ah, 0x00
mov al, 0x03
int 0x10
int 0x10
mov si, real_msg
; Print loading message
mov si, msg_loading
call print_string
cli
; Load Stage 2 from disk
; Read 5 sectors (sectors 2-6) - gives us 2.5KB for Stage 2
pop dx ; Restore boot drive
push dx ; Save it again for stage 2
mov bx, STAGE2_OFFSET ; Destination
mov dh, 5 ; Number of sectors
; DL already has drive number
call load_disk
lgdt [gdt_descriptor]
; Jump to Stage 2 (DL still has boot drive number)
pop dx ; Pass drive number to stage 2 in DL
jmp STAGE2_OFFSET
; ============================================================
; LOAD DISK - Read sectors using BIOS INT 0x13
; ============================================================
load_disk:
push dx
mov eax, cr0
or eax, 0x1
mov cr0, eax
mov ah, 0x02 ; Read function
mov al, dh ; Number of sectors
mov ch, 0 ; Cylinder 0
mov cl, 2 ; Start at sector 2
mov dh, 0 ; Head 0
int 0x13
jc disk_error
pop dx
cmp al, dh
jne disk_error
ret
; Far jump into 32-bit mode.
jmp 0x08:init_pm
disk_error:
mov si, msg_error
call print_string
jmp $
; --- Helper: Print String (BIOS INT 0x10) ---
; ============================================================
; PRINT STRING
; ============================================================
print_string:
pusha
mov ah, 0x0e ; INT 0x10 "Teletype Output" function
mov ah, 0x0e
.loop:
lodsb ; Load byte at [SI] into AL, increment SI
cmp al, 0 ; Check for null terminator
je .done
int 0x10 ; Call BIOS video interrupt
lodsb
test al, al
jz .done
int 0x10
jmp .loop
.done:
popa
ret
real_msg: db '[REAL] - Loaded successfully.', 0x0D, 0x0A, 0
; ============================================================
; DATA
; ============================================================
msg_loading: db '[STAGE1] Loading SoraOS...', 0x0D, 0x0A, 0
msg_error: db '[ERROR] Disk read failed!', 0x0D, 0x0A, 0
; --- GDT (Global Descriptor Table) ---
align 8
gdt_start:
gdt_null:
dq 0x0
gdt_code32: ; 32-bit code segment (selector 0x08)
dw 0xffff ; Limit 0:15
dw 0x0000 ; Base 0:15
db 0x00 ; Base 16:23
db 10011010b ; Access: present, ring 0, code, executable, readable
db 11001111b ; Flags: 4KB granularity, 32-bit | Limit 16:19
db 0x00 ; Base 24:31
gdt_data32: ; 32-bit data segment (selector 0x10)
dw 0xffff
dw 0x0000
db 0x00
db 10010010b ; Access: present, ring 0, data, writable
db 11001111b
db 0x00
gdt_code64: ; 64-bit code segment (selector 0x18)
dw 0xffff
dw 0x0000
db 0x00
db 10011010b ; Access: present, ring 0, code, executable, readable
db 10101111b ; Flags: 4KB granularity, 64-bit, limit 16:19
db 0x00
gdt_data64: ; 64-bit data segment (selector 0x20)
dw 0xffff
dw 0x0000
db 0x00
db 10010010b
db 10101111b
db 0x00
gdt_end:
gdt_descriptor:
dw gdt_end - gdt_start - 1
dd gdt_start
; ==================================================
; 32-BIT PROTECTED MODE
; ==================================================
[bits 32]
init_pm:
; Set up segments
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
mov esp, 0x90000
; Print message in Protected Mode
; Print to VGA memory
mov edi, 0xb8000
mov al, 'P'
mov ah, 0x0f
mov [edi], ax
add edi, 2
mov al, 'M'
mov [edi], ax
add edi, 2
mov al, '3'
mov [edi], ax
add edi, 2
mov al, '2'
mov [edi], ax
; Set up page tables for identity mapping first 2MB
; PML4[0] -> PDPT
mov edi, 0x1000
mov dword [edi], 0x2003 ; Present, Writable, points to 0x2000
add edi, 4
mov dword [edi], 0
; PDPT[0] -> PD
mov edi, 0x2000
mov dword [edi], 0x3003 ; Present, Writable, points to 0x3000
add edi, 4
mov dword [edi], 0
; PD[0] -> 2MB page at physical 0x0
mov edi, 0x3000
mov dword [edi], 0x83 ; Present, Writable, Page Size (2MB)
add edi, 4
mov dword [edi], 0
; Load CR3 with PML4 address
mov eax, 0x1000
mov cr3, eax
; Enable PAE (Physical Address Extension)
mov eax, cr4
or eax, 0x20
mov cr4, eax
; Enable Long Mode in EFER MSR
mov ecx, 0xC0000080
rdmsr
or eax, 0x100
wrmsr
; Enable Paging (activates Long Mode)
mov eax, cr0
or eax, 0x80000000
mov cr0, eax
; Far jump to 64-bit code
jmp 0x18:long_mode_start
jmp $
; --- 64-bit Long Mode ---
[bits 64]
long_mode_start:
; Set up segments (most are ignored in 64-bit mode)
mov ax, 0x20
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
; Set up stack
mov rsp, 0x90000
; Clear screen and print "SORA OS 64"
mov rdi, 0xb8000
mov rcx, 80*25
mov ax, 0x0f20 ; White space
rep stosw
; Print message
mov rdi, 0xb8000
mov rsi, long_msg
call print_string_64
; Hang
jmp $
; --- 64-bit Print String ---
print_string_64:
mov ah, 0x0f ; White on black
.loop:
lodsb
test al, al
jz .done
stosw ; Write character + attribute
jmp .loop
.done:
ret
long_msg: db 'SoraOS 64-BIT', 0
; --- The Magic Boot Sector Footer ---
; Fill the rest of the 512 bytes with zeros
; ============================================================
; BOOT SIGNATURE
; ============================================================
times 510-($-$$) db 0
; The BIOS signature (must be at the very end)
dw 0xAA55
section .bss
align 4096
pml4_table:
resb 4096
pdpt_table:
resb 4096
pd_table:
resb 4096

View File

@ -1,12 +1,71 @@
#!/bin/sh
export PATH=/usr/local/cross/bin:$PATH
#!/bin/bash
# Complete build script for SoraOS with 2-stage bootloader
# 1. Assemble raw binary
echo ">>> Assembling boot.asm to boot.bin..."
set -e # Exit on any error
echo "==================================="
echo " SoraOS Build System v1.0"
echo "==================================="
# Colors
GREEN='\033[0;32m'
BLUE='\033[0;34m'
YELLOW='\033[1;33m'
NC='\033[0m'
# Step 1: Assemble Stage 1 bootloader (MBR - 512 bytes)
echo -e "${BLUE}[1/6]${NC} Assembling Stage 1 bootloader (MBR)..."
nasm -f bin boot.asm -o boot.bin
# 2. Run QEMU as a raw disk drive
echo ">>> Running QEMU with boot.bin..."
qemu-system-x86_64 -drive format=raw,file=boot.bin
# Step 2: Assemble Stage 2 bootloader (extended loader)
echo -e "${BLUE}[2/6]${NC} Assembling Stage 2 bootloader..."
nasm -f bin elevator.asm -o elevator.bin
echo "Done!"
# Step 3: Assemble kernel entry point
echo -e "${BLUE}[3/6]${NC} Assembling kernel entry..."
nasm -f elf64 kernel.asm -o kernel.asm.o
# Step 4: Compile kernel C code
echo -e "${BLUE}[4/6]${NC} Compiling kernel..."
gcc -ffreestanding -c kernel.c -o kernel.c.o -mcmodel=large -mno-red-zone -fno-pic -fno-pie -static -fno-stack-protector -nostdlib -mno-mmx -mno-sse -mno-sse2 -m64
# Step 5: Link kernel
echo -e "${BLUE}[5/6]${NC} Linking kernel..."
ld -T linker.ld -o kernel.bin kernel.asm.o kernel.c.o --oformat binary
# Step 6: Create OS image
echo -e "${BLUE}[6/6]${NC} Creating OS image..."
cat boot.bin elevator.bin kernel.bin > os-image.bin
# Pad to floppy size (1.44MB)
truncate -s 1440K os-image.bin
echo ""
echo -e "${GREEN}✓ Build complete!${NC}"
echo ""
echo "==================================="
echo "File Layout:"
echo "==================================="
echo "Sector 1: Stage 1 (MBR)"
echo "Sectors 2-6: Stage 2 (Extended Bootloader)"
echo "Sectors 7+: Kernel"
echo ""
# Show sizes
echo "File Sizes:"
printf "%-15s %10s\n" "File" "Size"
printf "%-15s %10s\n" "----" "----"
printf "%-15s %10d bytes\n" "boot.bin" $(stat -f%z boot.bin 2>/dev/null || stat -c%s stage1.bin 2>/dev/null)
printf "%-15s %10d bytes\n" "elevator.bin" $(stat -f%z elevator.bin 2>/dev/null || stat -c%s stage2.bin 2>/dev/null)
printf "%-15s %10d bytes\n" "kernel.bin" $(stat -f%z kernel.bin 2>/dev/null || stat -c%s kernel.bin 2>/dev/null)
printf "%-15s %10d bytes\n" "os-image.bin" $(stat -f%z os-image.bin 2>/dev/null || stat -c%s os-image.bin 2>/dev/null)
echo ""
echo -e "${YELLOW}Running QEMU...${NC}"
echo "==================================="
echo "Press Ctrl+C to exit QEMU"
echo ""
qemu-system-x86_64 -drive format=raw,file=os-image.bin -no-reboot -d cpu_reset
echo -e "${GREEN}Done!${NC}"

490
elevator.asm Normal file
View File

@ -0,0 +1,490 @@
; File: elevator.asm
; Stage 2 Bootloader - No size limit!
; Job: Load kernel, set up GDT, switch to 64-bit mode, jump to kernel
[org 0x7e00]
[bits 16]
KERNEL_OFFSET equ 0x10000 ; Load kernel at 64KB (safer than 0x1000)
BOOT_DRIVE: db 0 ; Store boot drive number
ERROR_CODE: db 0 ; Store error code from disk read
stage2_start:
; Print stage 2 message
mov si, msg_stage2
call print_string
; Save boot drive number (passed from stage1 in DL)
mov [BOOT_DRIVE], dl
; Load kernel from disk
call load_kernel
; Verify kernel was loaded - check for signature
; Check if there's actual code at 0x10000
mov ax, 0x1000
mov es, ax
xor bx, bx
mov ax, [es:bx] ; Read first 2 bytes of kernel
; Show what we read (for debugging)
push ax
xor ax, ax
mov es, ax
mov si, msg_kernel_check
call print_string
pop ax
call print_hex_word ; Print the word we read
; If it's 0x0000, kernel didn't load
test ax, ax
jz kernel_load_failed
mov si, msg_kernel_ok
call print_string
; Disable interrupts
cli
; Load GDT
lgdt [gdt_descriptor]
; Enable Protected Mode
mov eax, cr0
or eax, 0x1
mov cr0, eax
; Far jump to 32-bit code
jmp 0x08:protected_mode
; ============================================================
; LOAD KERNEL FROM DISK
; ============================================================
load_kernel:
push ax
push bx
push cx
push dx
; Reset disk system first
mov ah, 0x00
mov dl, [BOOT_DRIVE]
int 0x13
; Set up ES:BX for the destination
; KERNEL_OFFSET is 0x10000, so we need ES=0x1000, BX=0x0000
mov ax, 0x1000
mov es, ax
xor bx, bx ; BX = 0, so ES:BX = 0x1000:0x0000 = 0x10000
; Now try loading kernel
mov ah, 0x02 ; Read function
mov al, 10 ; Number of sectors
mov ch, 0 ; Cylinder 0
mov cl, 7 ; Start at sector 7
mov dh, 0 ; Head 0
mov dl, [BOOT_DRIVE] ; Drive number
int 0x13
jc kernel_error
; Restore ES to 0
xor ax, ax
mov es, ax
pop dx
pop cx
pop bx
pop ax
ret
kernel_error:
; Restore ES
xor ax, ax
mov es, ax
; Save error code
mov byte [ERROR_CODE], ah
mov si, msg_kernel_error
call print_string
; Show error code
mov si, msg_error_code
call print_string
; Print error code as hex
mov al, [ERROR_CODE]
call print_hex
; Show drive number we tried to use
mov si, msg_drive
call print_string
mov al, [BOOT_DRIVE]
call print_hex
jmp $
kernel_load_failed:
xor ax, ax
mov es, ax
mov si, msg_verify_failed
call print_string
jmp $
; ============================================================
; PRINT STRING (16-bit)
; ============================================================
print_string:
pusha
mov ah, 0x0e
.loop:
lodsb
test al, al
jz .done
int 0x10
jmp .loop
.done:
popa
ret
; ============================================================
; PRINT HEX BYTE (for debugging)
; ============================================================
print_hex:
push ax
push bx
mov bl, al
shr al, 4 ; Get high nibble
call print_nibble
mov al, bl
and al, 0x0F ; Get low nibble
call print_nibble
pop bx
pop ax
ret
print_nibble:
cmp al, 9
jle .digit
add al, 7 ; Convert to A-F
.digit:
add al, '0'
mov ah, 0x0e
int 0x10
ret
; Print a 16-bit word as hex
print_hex_word:
push ax
mov al, ah ; Print high byte first
call print_hex
pop ax
call print_hex ; Print low byte
ret
; ============================================================
; MESSAGES
; ============================================================
msg_stage2: db '[STAGE2] Extended bootloader loaded', 0x0D, 0x0A, 0
msg_kernel_loaded: db '[STAGE2] Kernel loaded, switching to Protected Mode...', 0x0D, 0x0A, 0
msg_kernel_error: db '[ERROR] Kernel load failed!', 0x0D, 0x0A, 0
msg_kernel_check: db '[STAGE2] Verifying kernel load: Read word = 0x', 0
msg_kernel_ok: db '[STAGE2] Kernel load verified.', 0x0D, 0x0A, 0
msg_verify_failed: db '[ERROR] Kernel verification failed!', 0x0D, 0x0A, 0
msg_error_code: db ' Error code: 0x', 0
msg_drive: db ' Drive number: 0x', 0
; ============================================================
; GDT - Global Descriptor Table
; ============================================================
align 8
gdt_start:
gdt_null:
dq 0x0
gdt_code32: ; Selector 0x08
dw 0xffff
dw 0x0000
db 0x00
db 10011010b
db 11001111b
db 0x00
gdt_data32: ; Selector 0x10
dw 0xffff
dw 0x0000
db 0x00
db 10010010b
db 11001111b
db 0x00
gdt_code64: ; Selector 0x18
dw 0xffff
dw 0x0000
db 0x00
db 10011010b
db 10101111b
db 0x00
gdt_data64: ; Selector 0x20
dw 0xffff
dw 0x0000
db 0x00
db 10010010b
db 10101111b
db 0x00
gdt_end:
gdt_descriptor:
dw gdt_end - gdt_start - 1 ; Limit (size - 1)
dd gdt_start ; Base address (org already adjusts this)
; ============================================================
; 32-BIT PROTECTED MODE
; ============================================================
[bits 32]
protected_mode:
; Set up segments
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
mov esp, 0x90000
; Print to VGA
mov edi, 0xb8000
mov esi, pm_msg
call print_pm
; Clear page table area (12KB starting at 0x1000)
mov edi, 0x1000
mov ecx, 3072 ; 12KB / 4 bytes = 3072 dwords
xor eax, eax
rep stosd
; Set up page tables
; PML4[0] -> PDPT at 0x2000
mov dword [0x1000], 0x2003
; PDPT[0] -> PD at 0x3000
mov dword [0x2000], 0x3003
; Identity map first 4MB (two 2MB pages)
; PD[0] -> First 2MB
mov dword [0x3000], 0x00000083
mov dword [0x3004], 0x00000000
; PD[1] -> Second 2MB (covers 0x200000 - 0x3FFFFF)
mov dword [0x3008], 0x00200083
mov dword [0x300C], 0x00000000
; Load page table
mov eax, 0x1000
mov cr3, eax
; Enable PAE
mov eax, cr4
or eax, 0x20
mov cr4, eax
; Enable Long Mode
mov ecx, 0xC0000080
rdmsr
or eax, 0x100
wrmsr
; Enable Paging
mov eax, cr0
or eax, 0x80000000
mov cr0, eax
; Jump to 64-bit mode
jmp 0x18:long_mode
; Print in 32-bit protected mode
print_pm:
mov ah, 0x0f
.loop:
lodsb
test al, al
jz .done
stosw
jmp .loop
.done:
ret
pm_msg: db '[PM32] Setting up Long Mode...', 0
; ============================================================
; 64-BIT LONG MODE
; ============================================================
[bits 64]
long_mode:
; Set up segments
mov ax, 0x20
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
mov rsp, 0x90000
; Set up a minimal IDT to prevent triple faults
; Point all interrupts to a dummy handler
call setup_idt
; Print message on line 3
mov rdi, 0xb8000 + (160 * 2)
mov rsi, lm_msg
call print_64
; Write a marker before jumping to kernel (for debugging)
mov rdi, 0xb8000 + (160 * 3)
mov rsi, before_kernel_msg
call print_64
; JUMP TO KERNEL!
call KERNEL_OFFSET
; If kernel returns, show error
mov rdi, 0xb8000 + (160 * 4)
mov rsi, kernel_return_msg
call print_64
jmp $
; Set up a minimal IDT
setup_idt:
; Fill IDT with different handlers for different exceptions
mov rdi, 0x4000 ; IDT location
; Set up first 32 entries (CPU exceptions) with specific handlers
mov rcx, 32
mov rax, exception_handler
.fill_exceptions:
mov word [rdi], ax ; Offset low
mov word [rdi + 2], 0x18 ; Code segment
mov byte [rdi + 4], 0 ; IST
mov byte [rdi + 5], 0x8E ; Present, interrupt gate
shr rax, 16
mov word [rdi + 6], ax ; Offset middle
shr rax, 16
mov dword [rdi + 8], eax ; Offset high
mov dword [rdi + 12], 0 ; Reserved
mov rax, exception_handler ; Restore for next iteration
add rdi, 16
loop .fill_exceptions
; Fill remaining entries (32-255) with dummy handler
mov rcx, 224
mov rax, dummy_handler
.fill_rest:
mov word [rdi], ax
mov word [rdi + 2], 0x18
mov byte [rdi + 4], 0
mov byte [rdi + 5], 0x8E
shr rax, 16
mov word [rdi + 6], ax
shr rax, 16
mov dword [rdi + 8], eax
mov dword [rdi + 12], 0
mov rax, dummy_handler
add rdi, 16
loop .fill_rest
; Load IDT
lidt [idt_descriptor]
ret
; Exception handler - shows what went wrong
exception_handler:
; Save registers
push rax
push rbx
; Get exception number from stack
; (not perfectly accurate but good enough for debugging)
; Write "EXCEPTION!" in red at line 5
mov rbx, 0xb8000 + (160 * 5)
mov rax, 0x0C450C580C430C45 ; "ECXE" in red
mov [rbx], rax
mov rax, 0x0C4F0C490C540C50 ; "PTIO" in red
mov [rbx + 8], rax
mov word [rbx + 16], 0x0C21 ; "!" in red
; Show the instruction pointer where it failed
mov rax, [rsp + 16] ; Get RIP from stack (after our 2 pushes)
mov rbx, 0xb8000 + (160 * 6)
; Write "RIP: "
mov word [rbx], 0x0F52 ; 'R'
mov word [rbx + 2], 0x0F49 ; 'I'
mov word [rbx + 4], 0x0F50 ; 'P'
mov word [rbx + 6], 0x0F3A ; ':'
mov word [rbx + 8], 0x0F20 ; ' '
; Print RIP value as hex
mov rcx, 16
mov rbx, 0xb8000 + (160 * 6) + 10
.print_rip:
rol rax, 4
mov dl, al
and dl, 0x0F
cmp dl, 9
jle .digit
add dl, 7
.digit:
add dl, '0'
mov byte [rbx], dl
mov byte [rbx + 1], 0x0F
add rbx, 2
dec rcx
jnz .print_rip
; Restore and halt
pop rbx
pop rax
; Infinite loop instead of iretq
cli
hlt
jmp $
; Dummy interrupt handler for IRQs (not CPU exceptions)
dummy_handler:
iretq
idt_descriptor:
dw (256 * 16) - 1 ; Limit (256 entries * 16 bytes)
dq 0x4000 ; Base address
; Print in 64-bit mode
print_64:
mov ah, 0x0f
.loop:
lodsb
test al, al
jz .done
stosw
jmp .loop
.done:
ret
lm_msg: db '[64-BIT] Long mode active...', 0
before_kernel_msg: db '[64-BIT] Calling kernel...', 0
kernel_return_msg: db '[KERNEL] Returned unexpectedly!', 0

15
kernel.asm Normal file
View File

@ -0,0 +1,15 @@
; File: kernel.asm
; Assembly entry point for the kernel
[bits 64]
[extern kmain] ; kmain is defined in kernel.c
global _start ; Make _start visible to linker
_start:
; We're already in 64-bit mode with stack set up
; Just call the C kernel
call kmain
; If kmain returns, hang
jmp $

View File

@ -1,15 +1,42 @@
// file: kerlnel.c
// File: kernel.c
// SoraOS Kernel - Main entry point
// Simple helper to write a character at a specific position
static inline void write_char(int row, int col, char c, unsigned char color) {
volatile unsigned short *vga = (volatile unsigned short *)0xB8000;
int pos = (row * 80) + col;
vga[pos] = (color << 8) | c;
}
// Simple helper to write a string
static void write_string(int row, int col, const char *str, unsigned char color) {
int i = 0;
while (str[i] != '\0') {
write_char(row, col + i, str[i], color);
i++;
}
}
// Clear the entire screen
static void clear_screen(void) {
volatile unsigned short *vga = (volatile unsigned short *)0xB8000;
int i;
for (i = 0; i < 80 * 25; i++) {
vga[i] = (0x00 << 8) | ' ';
}
}
void kmain(void) {
// Kernel main function
// Set VGA memory address
volatile unsigned short *VGA_mem = (unsigned short *)0xB8000;
VGA_mem[0] = (0x07 << 8) | 'S';
VGA_mem[1] = (0x07 << 8) | 'O';
VGA_mem[2] = (0x07 << 8) | 'R';
VGA_mem[3] = (0x07 << 8) | 'A';
VGA_mem[4] = (0x07 << 8) | ' ';
VGA_mem[5] = (0x07 << 8) | 'O';
VGA_mem[6] = (0x07 << 8) | 'S';
// Clear screen
clear_screen();
// Write messages
write_string(10, 30, "SORA OS KERNEL", 0x0A); // Green
write_string(12, 25, "64-bit kernel running!", 0x0F); // White
write_string(14, 28, "System Initialized", 0x0E); // Yellow
// Infinite loop
while (1) {
__asm__ volatile ("hlt");
}
}

View File

@ -1,36 +1,26 @@
/* Linker script for SoraOS kernel */
OUTPUT_FORMAT(binary)
ENTRY(_start)
SECTIONS
{
/* Set the location counter to 0x100000 (1MB) */
. = 0x100000;
/* Kernel loaded at 0x10000 (64KB) by stage2 bootloader */
. = 0x10000;
.multiboot :
{
KEEP(*(.multiboot))
}
.text : {
*(.text)
}
/* Define the .text section at the current location */
.text :
{
/* Put all .text sections from all input files here */
*(.text)
}
.rodata : {
*(.rodata)
}
/* Define the .data section immediately after .text */
.data :
{
/* Put all .data sections §from all input files here */
*(.data)
}
.data : {
*(.data)
}
/* Define the .bss section immediately after .data */
.bss :
{
/* Put all .bss sections from all input files here */
*(.bss)
}
/* End of the linker script */
.bss : {
*(.bss)
*(COMMON)
}
}