working on reading elf from initrd, and getting it launched with the new scheduler
This commit is contained in:
@@ -3,3 +3,4 @@
|
||||
mkdir -p output
|
||||
rm -rf output/*
|
||||
find . -depth -print | cpio -o -H newc > output/initrd.img
|
||||
cp output/initrd.img ../isodir/boot
|
||||
@@ -121,3 +121,5 @@ outsw:
|
||||
fetch_cr3:
|
||||
mov %cr3, %eax
|
||||
ret
|
||||
|
||||
.global set_cr3
|
||||
|
||||
@@ -34,7 +34,7 @@ static uint32_t cpio_read(struct vfs_node* node, uint32_t offset, uint32_t size,
|
||||
if (offset + size > node->size) {
|
||||
size = node->size - offset;
|
||||
}
|
||||
memcpy(buffer, (uint8_t*)(node->ptr) + offset, size);
|
||||
memcpy((uint8_t*)(node->data) + offset, buffer, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ vfs_node_t* cpio_read_fs(uint32_t _vaddr) {
|
||||
|
||||
current->flags = VFS_FILE;
|
||||
current->read = cpio_read;
|
||||
current->ptr = (vfs_node_t*)file_data;
|
||||
current->data = file_data;
|
||||
}
|
||||
|
||||
uint32_t next_header_offset = file_data_offset + filesize;
|
||||
|
||||
40
kernel/gdt.c
40
kernel/gdt.c
@@ -1,4 +1,4 @@
|
||||
#include <stdint.h>
|
||||
#include <gdt.h>
|
||||
|
||||
#define SEG_DESCTYPE(x) ((x) << 0x04) // Descriptor type (0 for system, 1 for code/data)
|
||||
#define SEG_PRES(x) ((x) << 0x07) // Present
|
||||
@@ -46,40 +46,10 @@ typedef struct __attribute__((packed)) {
|
||||
uint32_t base;
|
||||
} gdt_ptr_t;
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint32_t prev_tss;
|
||||
uint32_t esp0;
|
||||
uint32_t ss0;
|
||||
uint32_t esp1;
|
||||
uint32_t ss1;
|
||||
uint32_t esp2;
|
||||
uint32_t ss2;
|
||||
uint32_t cr3;
|
||||
uint32_t eip;
|
||||
uint32_t eflags;
|
||||
uint32_t eax;
|
||||
uint32_t ecx;
|
||||
uint32_t edx;
|
||||
uint32_t ebx;
|
||||
uint32_t esp;
|
||||
uint32_t ebp;
|
||||
uint32_t esi;
|
||||
uint32_t edi;
|
||||
uint32_t es;
|
||||
uint32_t cs;
|
||||
uint32_t ss;
|
||||
uint32_t ds;
|
||||
uint32_t fs;
|
||||
uint32_t gs;
|
||||
uint32_t ldt;
|
||||
uint16_t trap;
|
||||
uint16_t iomap_base;
|
||||
} tss_entry;
|
||||
|
||||
uint64_t gdt[6];
|
||||
gdt_ptr_t gdtr;
|
||||
|
||||
tss_entry tss;
|
||||
tss_entry_t tss;
|
||||
|
||||
extern void load_gdt();
|
||||
extern void tss_flush();
|
||||
@@ -126,14 +96,14 @@ void init_gdt() {
|
||||
gdt[3] = create_descriptor(0, 0x000FFFFF, (GDT_CODE_PL3));
|
||||
gdt[4] = create_descriptor(0, 0x000FFFFF, (GDT_DATA_PL3));
|
||||
|
||||
for (uint32_t i = 0; i < sizeof(tss_entry); i++) {
|
||||
for (uint32_t i = 0; i < sizeof(tss_entry_t); i++) {
|
||||
((char*)&tss)[i] = 0;
|
||||
}
|
||||
|
||||
tss.ss0 = 0x10;
|
||||
tss.iomap_base = sizeof(tss_entry);
|
||||
tss.iomap_base = sizeof(tss_entry_t);
|
||||
|
||||
gdt[5] = create_tss_descriptor((uint32_t)&tss, sizeof(tss_entry) - 1);
|
||||
gdt[5] = create_tss_descriptor((uint32_t)&tss, sizeof(tss_entry_t) - 1);
|
||||
|
||||
gdtr.limit = 6 * sizeof(uint64_t) - 1;
|
||||
gdtr.base = (uint32_t)&gdt;
|
||||
|
||||
34
kernel/gdt.h
34
kernel/gdt.h
@@ -1,6 +1,40 @@
|
||||
#ifndef KGDT_H
|
||||
#define KGDT_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint32_t prev_tss;
|
||||
uint32_t esp0;
|
||||
uint32_t ss0;
|
||||
uint32_t esp1;
|
||||
uint32_t ss1;
|
||||
uint32_t esp2;
|
||||
uint32_t ss2;
|
||||
uint32_t cr3;
|
||||
uint32_t eip;
|
||||
uint32_t eflags;
|
||||
uint32_t eax;
|
||||
uint32_t ecx;
|
||||
uint32_t edx;
|
||||
uint32_t ebx;
|
||||
uint32_t esp;
|
||||
uint32_t ebp;
|
||||
uint32_t esi;
|
||||
uint32_t edi;
|
||||
uint32_t es;
|
||||
uint32_t cs;
|
||||
uint32_t ss;
|
||||
uint32_t ds;
|
||||
uint32_t fs;
|
||||
uint32_t gs;
|
||||
uint32_t ldt;
|
||||
uint16_t trap;
|
||||
uint16_t iomap_base;
|
||||
} tss_entry_t;
|
||||
|
||||
void init_gdt();
|
||||
|
||||
extern tss_entry_t tss;
|
||||
|
||||
#endif
|
||||
@@ -1,34 +0,0 @@
|
||||
#include "initrd.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <lib/print.h>
|
||||
#include <lib/memory.h>
|
||||
|
||||
void parse_cpio(void *initrd_start) {
|
||||
cpio_header_t *head = (cpio_header_t *)initrd_start;
|
||||
|
||||
while (strncmp(head->c_magic, "070701", 6) == 0) {
|
||||
// If we hit the trailer, we are done
|
||||
char *filename = (char *)(head + 1);
|
||||
if (strncmp(filename, "TRAILER!!!", 10) == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
uint32_t filesize = parse_hex(head->c_filesize);
|
||||
uint32_t namesize = parse_hex(head->c_namesize);
|
||||
|
||||
kprintf("found file of size %d\n", filesize);
|
||||
|
||||
// Calculate where the data begins (accounting for 4-byte padding)
|
||||
uint32_t header_plus_name = 110 + namesize;
|
||||
header_plus_name = (header_plus_name + 3) & ~3; // Align to 4 bytes
|
||||
|
||||
char *file_data = (char *)head + header_plus_name;
|
||||
|
||||
uint32_t total_record_size = header_plus_name + filesize;
|
||||
total_record_size = (total_record_size + 3) & ~3; // Align to 4 bytes
|
||||
|
||||
head = (cpio_header_t *)((char *)head + total_record_size);
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
#ifndef KINITRD_H
|
||||
#define KINITRD_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct {
|
||||
char c_magic[6];
|
||||
char c_ino[8];
|
||||
char c_mode[8];
|
||||
char c_uid[8];
|
||||
char c_gid[8];
|
||||
char c_nlink[8];
|
||||
char c_mtime[8];
|
||||
char c_filesize[8];
|
||||
char c_devmajor[8];
|
||||
char c_devminor[8];
|
||||
char c_rdevmajor[8];
|
||||
char c_rdevminor[8];
|
||||
char c_namesize[8];
|
||||
char c_check[8];
|
||||
} cpio_header_t;
|
||||
|
||||
static inline uint32_t parse_hex(const char *s) {
|
||||
uint32_t val = 0;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
val <<= 4;
|
||||
if (s[i] >= '0' && s[i] <= '9') val += (s[i] - '0');
|
||||
else if (s[i] >= 'A' && s[i] <= 'F') val += (s[i] - 'A' + 10);
|
||||
else if (s[i] >= 'a' && s[i] <= 'f') val += (s[i] - 'a' + 10);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
void parse_cpio(void *initrd_start);
|
||||
|
||||
#endif
|
||||
@@ -44,15 +44,29 @@ ISR_ERRCODE 14 # Page Fault (Has Error Code!)
|
||||
.extern send_eoi_master # drivers/pic/pic.c
|
||||
isr32:
|
||||
cli
|
||||
|
||||
pushal
|
||||
|
||||
movw %ds, %ax
|
||||
pushl %eax
|
||||
|
||||
movw $0x10, %ax # Load Kernel Data Segment descriptor
|
||||
movw %ax, %ds
|
||||
movw %ax, %es
|
||||
movw %ax, %fs
|
||||
movw %ax, %gs
|
||||
|
||||
pushl %esp
|
||||
call switch_context
|
||||
movl %eax, %esp
|
||||
|
||||
call send_eoi_master
|
||||
|
||||
popl %eax
|
||||
movw %ax, %ds
|
||||
movw %ax, %es
|
||||
movw %ax, %fs
|
||||
movw %ax, %gs
|
||||
|
||||
popal
|
||||
sti
|
||||
iret
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "scheduler.h"
|
||||
#include "common.h"
|
||||
#include "vfs.h"
|
||||
#include "elf.h"
|
||||
|
||||
#include <lib/print.h>
|
||||
#include <lib/stream.h>
|
||||
@@ -51,26 +52,73 @@ vfs_node_t* load_initrd() {
|
||||
return cpio_read_fs(initrd_module->mod_start);
|
||||
}
|
||||
|
||||
void load_origin_program() {
|
||||
vfs_node_t* vfs_root = vfs_create_root();
|
||||
vfs_node_t* initrd_root = load_initrd();
|
||||
void load_program(const char* path) {
|
||||
void* cr3 = create_task_pd();
|
||||
load_pd(cr3);
|
||||
flush_tlb();
|
||||
|
||||
if (initrd_root) {
|
||||
mount(vfs_root, initrd_root);
|
||||
kprintf("initrd read, mounted @ /\n");
|
||||
|
||||
int fd = open("/origin.elf", 0);
|
||||
if (fd == -1) {
|
||||
kprintf("failed to read origin program\n");
|
||||
}
|
||||
|
||||
void* buf = kalloc(512);
|
||||
int rd = read(fd, buf, 512);
|
||||
if (rd > 0) {
|
||||
kprintf("read %d bytes from origin.elf\n", rd);
|
||||
}
|
||||
int fd = open(path, 0);
|
||||
if (fd == -1) {
|
||||
kprintf("failed to open program: %s\n", path);
|
||||
return;;
|
||||
}
|
||||
exit();
|
||||
elf_header_t* e_hdr = kalloc(sizeof(elf_header_t));
|
||||
memset((void*)e_hdr, 0, sizeof(elf_header_t));
|
||||
|
||||
uint32_t bytes_rd = read(fd, e_hdr, sizeof(elf_header_t));
|
||||
if (bytes_rd <= 0) {
|
||||
kprintf("failed to read program data for %s\n", path);
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t ph_table_ptr = e_hdr->e_phoff;
|
||||
elf_program_header_t* ph = kalloc(sizeof(elf_program_header_t));
|
||||
uint32_t heap_start = 0;
|
||||
|
||||
for (uint32_t i = 0; i < e_hdr->e_phnum; i++) {
|
||||
fseek(fd, ph_table_ptr);
|
||||
memset((void*)ph, 0, sizeof(elf_program_header_t));
|
||||
read(fd, ph, sizeof(elf_program_header_t));
|
||||
|
||||
if (ph->p_type == PT_LOAD) {
|
||||
uint32_t vstart = ph->p_vaddr;
|
||||
uint32_t vend = vstart + ph->p_memsz;
|
||||
|
||||
if (vend > heap_start) {
|
||||
heap_start = vend;
|
||||
}
|
||||
|
||||
uint32_t page_start = vstart & ~(PAGE_SIZE - 1);
|
||||
uint32_t page_end = (vend + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
|
||||
|
||||
for (uint32_t v = page_start; v < page_end; v += PAGE_SIZE) {
|
||||
void* phys_frame = p_alloc_frame();
|
||||
map_page(v, (uint32_t)phys_frame, 0x07);
|
||||
}
|
||||
|
||||
uint32_t data_ptr = ph->p_offset;
|
||||
fseek(fd, data_ptr);
|
||||
read(fd, (void*)vstart, ph->p_memsz);
|
||||
|
||||
// 0 out bss
|
||||
if (ph->p_memsz > ph->p_filesz) {
|
||||
size_t bss_size = ph->p_memsz - ph->p_filesz;
|
||||
memset((void*)(vstart + ph->p_filesz), 0, bss_size);
|
||||
}
|
||||
}
|
||||
|
||||
ph_table_ptr += sizeof(elf_program_header_t);
|
||||
}
|
||||
|
||||
uint32_t esp = 0xBFFF0000;
|
||||
void* pesp = p_alloc_frame();
|
||||
map_page(esp - PAGE_SIZE, (uint32_t)pesp, 0x07);
|
||||
|
||||
create_task(e_hdr->e_entry, fetch_cr3(), 1);
|
||||
}
|
||||
|
||||
void start_origin() {
|
||||
load_program("/origin.elf");
|
||||
}
|
||||
|
||||
void kmain(uint32_t magic, multiboot_info* mbi) {
|
||||
@@ -96,9 +144,19 @@ void kmain(uint32_t magic, multiboot_info* mbi) {
|
||||
|
||||
kprintf("basic initializations complete\n");
|
||||
|
||||
vfs_node_t* vfs_root = vfs_create_root();
|
||||
|
||||
vfs_node_t* initrd_root = load_initrd();
|
||||
if (!initrd_root) {
|
||||
kprintf("failed to load initrd\n");
|
||||
}
|
||||
mount(vfs_root, initrd_root);
|
||||
kprintf("initrd read, mounted @ /\n");
|
||||
|
||||
disable_interrupts();
|
||||
init_scheduler();
|
||||
enable_interrupts();
|
||||
|
||||
create_task((uint32_t)load_origin_program, fetch_cr3());
|
||||
kprintf("loading user program\n");
|
||||
start_origin();
|
||||
}
|
||||
|
||||
6
kernel/lib/string.h
Normal file
6
kernel/lib/string.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#ifndef KSTRING_H
|
||||
#define KSTRING_H
|
||||
|
||||
char* strtok_r(char* str, const char* delim, char** saveptr);
|
||||
|
||||
#endif
|
||||
49
kernel/lib/strtok.c
Normal file
49
kernel/lib/strtok.c
Normal file
@@ -0,0 +1,49 @@
|
||||
#include <lib/string.h>
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
static int is_delim(char c, const char* delim) {
|
||||
while (*delim) {
|
||||
if (c == *delim) {
|
||||
return 1;
|
||||
}
|
||||
delim++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
char* strtok_r(char* str, const char* delim, char** saveptr) {
|
||||
if (saveptr == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char* next_token = (str != NULL) ? str : *saveptr;
|
||||
|
||||
if (next_token == NULL || *next_token == '\0') {
|
||||
*saveptr = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while (*next_token && is_delim(*next_token, delim)) {
|
||||
next_token++;
|
||||
}
|
||||
|
||||
if (*next_token == '\0') {
|
||||
*saveptr = next_token;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char* token_start = next_token;
|
||||
|
||||
while (*next_token) {
|
||||
if (is_delim(*next_token, delim)) {
|
||||
*next_token = '\0'; // Destructively null-terminate the token
|
||||
*saveptr = next_token + 1; // Save the position right after the null-terminator
|
||||
return token_start;
|
||||
}
|
||||
next_token++;
|
||||
}
|
||||
|
||||
*saveptr = next_token;
|
||||
return token_start;
|
||||
}
|
||||
@@ -8,8 +8,6 @@ extern uint8_t __kernel_start;
|
||||
extern uint8_t __kernel_end;
|
||||
|
||||
extern uint32_t page_directory[1024];
|
||||
extern void flush_tlb();
|
||||
extern void disable_pae();
|
||||
|
||||
#define PAGE_SIZE 4096
|
||||
#define MAX_RAM 0xFFFFFFFF // 4GB
|
||||
|
||||
@@ -24,4 +24,9 @@ void* create_task_pd();
|
||||
|
||||
void map_page(uint32_t vaddr, uint32_t paddr, uint32_t flags);
|
||||
|
||||
void load_pd(void* paddr);
|
||||
|
||||
void flush_tlb();
|
||||
void disable_pae();
|
||||
|
||||
#endif
|
||||
|
||||
@@ -13,6 +13,7 @@ typedef enum {
|
||||
typedef struct {
|
||||
uint32_t pid;
|
||||
uint32_t esp;
|
||||
uint32_t esp0;
|
||||
uint32_t cr3;
|
||||
process_state_t state;
|
||||
uint32_t sleep;
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "common.h"
|
||||
#include "process.h"
|
||||
#include "scheduler.h"
|
||||
#include "gdt.h"
|
||||
|
||||
static process_t* process_table;
|
||||
|
||||
@@ -68,9 +69,10 @@ uint32_t switch_context(uint32_t current_esp) {
|
||||
|
||||
current_process = next_process;
|
||||
|
||||
tss.esp0 = process_table[current_process].esp0;
|
||||
|
||||
if (fetch_cr3() != process_table[current_process].cr3) {
|
||||
extern void load_pd(uint32_t table);
|
||||
load_pd(process_table[current_process].cr3);
|
||||
load_pd((void*)process_table[current_process].cr3);
|
||||
}
|
||||
|
||||
return process_table[current_process].esp;
|
||||
@@ -88,12 +90,12 @@ void init_scheduler() {
|
||||
process->sleep = 0;
|
||||
total_processes++;
|
||||
|
||||
create_task((uint32_t)idle_task, fetch_cr3());
|
||||
create_task((uint32_t)idle_task, fetch_cr3(), 0);
|
||||
|
||||
current_process = 0;
|
||||
}
|
||||
|
||||
int create_task(uint32_t entry_point, uint32_t cr3) {
|
||||
int create_task(uint32_t entry_point, uint32_t cr3, int user) {
|
||||
if (total_processes >= 16) {
|
||||
return 0;
|
||||
}
|
||||
@@ -117,10 +119,20 @@ int create_task(uint32_t entry_point, uint32_t cr3) {
|
||||
|
||||
void* stack_bottom = kalloc(4096);
|
||||
uint32_t* esp = (uint32_t*)((uint32_t)stack_bottom + 4096);
|
||||
process->esp0 = (uint32_t)esp;
|
||||
|
||||
*(--esp) = 0x0202; // EFLAGS
|
||||
*(--esp) = 0x08; // CS
|
||||
*(--esp) = entry_point; // EIP
|
||||
if (user) {
|
||||
*(--esp) = 0x23; // User Data Segment (SS) with RPL 3 (0x20 | 3)
|
||||
*(--esp) = 0xBFFFF000; // User Stack Pointer (ESP) - location mapped in user space
|
||||
*(--esp) = 0x0202; // EFLAGS (Interrupts enabled)
|
||||
*(--esp) = 0x1B; // User Code Segment (CS) with RPL 3 (0x18 | 3)
|
||||
*(--esp) = entry_point; // EIP
|
||||
} else {
|
||||
// IRET values for Ring 0
|
||||
*(--esp) = 0x0202; // EFLAGS
|
||||
*(--esp) = 0x08; // Kernel Code Segment (CS)
|
||||
*(--esp) = entry_point; // EIP
|
||||
}
|
||||
|
||||
*(--esp) = 0; // EAX
|
||||
*(--esp) = 0; // ECX
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
void init_scheduler();
|
||||
|
||||
int create_task(uint32_t entry_point, uint32_t cr3);
|
||||
int create_task(uint32_t entry_point, uint32_t cr3, int user);
|
||||
process_t* current_task();
|
||||
|
||||
void sleep(uint32_t ms);
|
||||
|
||||
30
kernel/vfs.c
30
kernel/vfs.c
@@ -22,22 +22,22 @@ vfs_node_t* vfs_create_root() {
|
||||
|
||||
void mount(vfs_node_t* _mnt, vfs_node_t* _fs) {
|
||||
if (!_fs || !_mnt || !(_mnt->flags & VFS_DIRECTORY)) return;
|
||||
_mnt->ptr = _fs;
|
||||
_mnt->mnt = _fs;
|
||||
}
|
||||
|
||||
static vfs_node_t* lookup(const char* path) {
|
||||
if (path[0] != '/') return NULL;
|
||||
vfs_node_t* current = root;
|
||||
|
||||
if (current->ptr) {
|
||||
current = current->ptr;
|
||||
if (current->mnt) {
|
||||
current = current->mnt;
|
||||
}
|
||||
|
||||
const char* component = path + 1;
|
||||
if (*component == '\0') return current;
|
||||
const char* cmp = path + 1;
|
||||
if (*cmp == '\0') return current;
|
||||
|
||||
if (current->finddir) {
|
||||
return current->finddir(current, component);
|
||||
return current->finddir(current, cmp);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
@@ -72,6 +72,22 @@ int read(int fd, void* buf, size_t sz) {
|
||||
return bytes_read;
|
||||
}
|
||||
|
||||
int fseek(int fd) {
|
||||
int fstat(int fd, file_t* dst) {
|
||||
if (fd < 0 || fd >= MAX_PROCESS_FDS || !fd_table[fd].node) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
file_t* src = &fd_table[fd];
|
||||
memcpy(src, dst, sizeof(file_t));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int fseek(int fd, size_t offset) {
|
||||
if (fd < 0 || fd >= MAX_PROCESS_FDS || !fd_table[fd].node) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
file_t* file = &fd_table[fd];
|
||||
file->offset = offset;
|
||||
return 1;
|
||||
}
|
||||
@@ -25,7 +25,8 @@ typedef struct vfs_node {
|
||||
write_type_t write;
|
||||
finddir_type_t finddir;
|
||||
|
||||
struct vfs_node* ptr;
|
||||
struct vfs_node* mnt;
|
||||
void* data;
|
||||
} vfs_node_t;
|
||||
|
||||
typedef struct {
|
||||
@@ -40,4 +41,7 @@ void mount(vfs_node_t* _mnt, vfs_node_t* _fs);
|
||||
int open(const char* path, int flags);
|
||||
int read(int fd, void* buf, size_t sz);
|
||||
|
||||
int fstat(int fd, file_t* _f);
|
||||
int fseek(int fd, size_t offset);
|
||||
|
||||
#endif
|
||||
@@ -1,8 +1,8 @@
|
||||
CC = i686-elf-gcc
|
||||
LD = i686-elf-ld
|
||||
|
||||
CFLAGS = -ffreestanding -O2 -Wall -Wextra -I../rocklibc/include
|
||||
LDFLAGS = -m elf_i386 -nostdlib
|
||||
CFLAGS = -ffreestanding -O2 -Wall -Wextra -ffunction-sections -fdata-sections -I../rocklibc/include
|
||||
LDFLAGS = -m elf_i386 -nostdlib --gc-sections
|
||||
|
||||
TARGET = origin.elf
|
||||
|
||||
@@ -16,6 +16,7 @@ main.o: main.c
|
||||
|
||||
$(TARGET): crt0.o main.o ../rocklibc/rlibc.a
|
||||
$(LD) $(LDFLAGS) -T linker.ld crt0.o main.o ../rocklibc/rlibc.a $(shell $(CC) -print-libgcc-file-name) -o $(TARGET)
|
||||
cp $(TARGET) ../initrd
|
||||
|
||||
clean:
|
||||
rm -f *.o $(TARGET)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
CC = i686-elf-gcc
|
||||
AR = i686-elf-ar
|
||||
CFLAGS = -ffreestanding -O2 -Wall -Wextra -Iinclude -DHAVE_MMAP=0 -DLACKS_SYS_MMAN_H=1 -DUSE_LOCKS=0 -DLACKS_SYS_PARAM_H=1
|
||||
CFLAGS += -ffunction-sections -fdata-sections
|
||||
TARGET = rlibc.a
|
||||
|
||||
SRCS = $(shell find src -name "*.c")
|
||||
|
||||
Reference in New Issue
Block a user