diff --git a/.gitattributes b/.gitattributes index b06f0493..03f8ea80 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1 +1 @@ -image/disk.img filter=lfs diff=lfs merge=lfs -text +image/disk.img filter=lfs diff=lfs merge=lfs -text \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json index 6662a7ee..6bcc9db5 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -6,11 +6,82 @@ "configurations": [ { - "name": "hello with GDB", + "name": "cmd with GDB", + "type": "cppdbg", + "request": "launch", + "miDebuggerServerAddress": "localhost:1234", + // "program": "${workspaceRoot}/app/hello/hello", + "program": "${workspaceRoot}/app/cmd/ls", + "cwd": "${workspaceRoot}", + "args": [], + "sourceFileMap": { + "": "" + }, + "targetArchitecture": "x86", + "MIMode": "gdb", + "miDebuggerPath": "/opt/local/bin/ggdb", + "miDebuggerArgs": "", + "customLaunchSetupCommands": [ + // { + // "text": "target remote localhost:1234", + // "description": "Connect to QEMU remote debugger" + // } + ], + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + }, + { + "text": "set architecture i386:intel ", + "description": "set architecture i386" + }, + + ], + "preLaunchTask": "Build and run" + }, + { + "name": "launcher with GDB", "type": "cppdbg", "request": "launch", "miDebuggerServerAddress": "localhost:1234", // "program": "${workspaceRoot}/app/hello/hello", + "program": "${workspaceRoot}/app/launcher/launcher", + "cwd": "${workspaceRoot}", + "args": [], + "sourceFileMap": { + "": "" + }, + "targetArchitecture": "x86", + "MIMode": "gdb", + "miDebuggerPath": "/opt/local/bin/ggdb", + "miDebuggerArgs": "", + "customLaunchSetupCommands": [ + // { + // "text": "target remote localhost:1234", + // "description": "Connect to QEMU remote debugger" + // } + ], + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + }, + { + "text": "set architecture i386:intel ", + "description": "set architecture i386" + }, + + ], + "preLaunchTask": "Build and run" + }, + { + "name": "hello with GDB", + "type": "cppdbg", + "request": "launch", + "miDebuggerServerAddress": "localhost:1234", "program": "${workspaceRoot}/app/hello/hello", "cwd": "${workspaceRoot}", "args": [], @@ -41,6 +112,42 @@ ], "preLaunchTask": "Build and run" }, + { + "name": "gnuboy with GDB", + "type": "cppdbg", + "request": "launch", + "miDebuggerServerAddress": "localhost:1234", + // "program": "${workspaceRoot}/app/hello/hello", + "program": "${workspaceRoot}/app/gnuboy/gnuboy", + "cwd": "${workspaceRoot}", + "args": [], + "sourceFileMap": { + "": "" + }, + "targetArchitecture": "x86", + "MIMode": "gdb", + "miDebuggerPath": "/opt/local/bin/ggdb", + "miDebuggerArgs": "", + "customLaunchSetupCommands": [ + // { + // "text": "target remote localhost:1234", + // "description": "Connect to QEMU remote debugger" + // } + ], + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + }, + { + "text": "set architecture i386:intel ", + "description": "set architecture i386" + }, + + ], + "preLaunchTask": "Build and run" + }, { "name": "gui with GDB", "type": "cppdbg", @@ -187,7 +294,7 @@ "request": "launch", "miDebuggerServerAddress": "localhost:1234", // "program": "${workspaceRoot}/app/hello/hello", - "program": "${workspaceRoot}/app/test/test", + "program": "${workspaceRoot}/app/test/test-mem", "cwd": "${workspaceRoot}", "args": [], "sourceFileMap": { @@ -324,6 +431,42 @@ ], "preLaunchTask": "Build and run" }, + { + "name": "sdl2 with GDB", + "type": "cppdbg", + "request": "launch", + "miDebuggerServerAddress": "localhost:1234", + // "program": "${workspaceRoot}/app/hello/hello", + "program": "${workspaceRoot}/app/sdl2/sdl2", + "cwd": "${workspaceRoot}", + "args": [], + "sourceFileMap": { + "": "" + }, + "targetArchitecture": "x86", + "MIMode": "gdb", + "miDebuggerPath": "/opt/local/bin/ggdb", + "miDebuggerArgs": "", + "customLaunchSetupCommands": [ + // { + // "text": "target remote localhost:1234", + // "description": "Connect to QEMU remote debugger" + // } + ], + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + }, + { + "text": "set architecture i386:intel ", + "description": "set architecture i386" + }, + + ], + "preLaunchTask": "Build and run" + }, { "name": "file with GDB", "type": "cppdbg", @@ -444,7 +587,7 @@ "request": "launch", "miDebuggerServerAddress": "localhost:1234", // "program": "${workspaceRoot}/app/hello/hello", - "program": "${workspaceRoot}/init/kernel.elf", + "program": "${workspaceRoot}/duck/init/kernel.elf", "cwd": "${workspaceRoot}", "args": [], "sourceFileMap": { @@ -477,7 +620,7 @@ "type": "cppdbg", "request": "launch", "miDebuggerServerAddress": "localhost:1234", - "program": "${workspaceRoot}/boot/x86/init", + "program": "${workspaceRoot}/boot/x86/init.elf", "cwd": "${workspaceRoot}", "args": [], "sourceFileMap": { @@ -972,7 +1115,7 @@ "type": "cppdbg", "request": "launch", "miDebuggerServerAddress": "localhost:1234", - "program": "${workspaceRoot}/init/kernel.elf", + "program": "${workspaceRoot}/duck/init/kernel.elf", // "program": "${workspaceRoot}/app/launcher/launcher", // "program": "${workspaceRoot}/app/hello/hello", diff --git a/Sconstruct b/Sconstruct index 955f46b5..756448cb 100644 --- a/Sconstruct +++ b/Sconstruct @@ -13,9 +13,9 @@ from xenv.env import * Import('env') -duck=SConscript(dirs=['duck'], exports='env') -boot=SConscript(dirs=['boot'], exports='env') -image=SConscript(dirs=['image'], exports='env') +duck=SConscript(dirs=['duck']) +boot=SConscript(dirs=['boot']) +image=SConscript(dirs=['image']) Depends(boot, duck) Depends(image, boot) @@ -23,8 +23,8 @@ Depends(image, duck) if default_apps: - eggs=SConscript(dirs=['eggs'], exports='env') - app=SConscript(dirs=['app'], exports='env') + eggs=SConscript(dirs=['eggs']) + app=SConscript(dirs=['app']) Depends(app, eggs) diff --git a/app b/app index c284d7d3..ac749e30 160000 --- a/app +++ b/app @@ -1 +1 @@ -Subproject commit c284d7d3ccf78734483b7d8eaf5cd7660f877345 +Subproject commit ac749e30c8e5d31bf81d76585f6324ccf95d1ae4 diff --git a/boot/SConscript b/boot/SConscript index 72f461f3..d77e134b 100644 --- a/boot/SConscript +++ b/boot/SConscript @@ -16,4 +16,4 @@ if arch_type in 'arm': elif arch_type in 'xtensa': boot=SConscript(dirs=['xtensa'], exports='env') else: - boot=SConscript(dirs=[arch], exports='env') \ No newline at end of file + boot=SConscript(dirs=[arch_type], exports='env') \ No newline at end of file diff --git a/boot/arm/config.h b/boot/arm/config.h index 16322c1d..9c1f0572 100644 --- a/boot/arm/config.h +++ b/boot/arm/config.h @@ -1,5 +1,5 @@ #ifndef BOOT_ARM_CONFIG_H #define BOOT_ARM_CONFIG_H -#define KERNEL_BLOCK_SIZE 169 -#define KERNEL_SIZE 172996 +#define KERNEL_BLOCK_SIZE 208 +#define KERNEL_SIZE 212932 #endif diff --git a/boot/arm/init.c b/boot/arm/init.c index 9fb37912..1584e120 100644 --- a/boot/arm/init.c +++ b/boot/arm/init.c @@ -155,14 +155,14 @@ char uart_getc() { void init_uart() {} void uart_send(unsigned int c) { - while (((io_read32(0x20000000 + 0x60014)) & 0x20) == 0); - io_write32(0x20000000 + 0x60000,c); + while (((io_read32(0x20000000 + 0x60014)) & 0x20) == 0) + ; + io_write32(0x20000000 + 0x60000, c); } char uart_getc() { - if((io_read32(0x20000000 + 0x60014) & 0x01) == 0) - return 0; - return io_read32(0x20000000 + 0x60000); + if ((io_read32(0x20000000 + 0x60014) & 0x01) == 0) return 0; + return io_read32(0x20000000 + 0x60000); } #endif @@ -249,6 +249,8 @@ void printf(const char* format, ...) { } } +extern void* _stack_svc; + void init_boot_info() { boot_info = &boot_data; boot_info->version = BOOT_VERSION; @@ -257,6 +259,8 @@ void init_boot_info() { boot_info->kernel_size = KERNEL_BLOCK_SIZE * READ_BLOCK_SIZE * 2; boot_info->tss_number = MAX_CPU; boot_info->second_boot_entry = SECOND_BOOT_ENTRY; + boot_info->segments_number = 0; + boot_info->kernel_stack = _stack_svc; } void init_disk() { @@ -294,7 +298,7 @@ void init_memory() { count++; #elif defined(CUBIEBOARD2) ptr->base = 0x40000000; - ptr->length = 0x10000000*4;//256m*4 + ptr->length = 0x10000000 * 4; // 256m*4 ptr->type = 1; boot_info->total_memory += ptr->length; ptr++; @@ -316,7 +320,7 @@ void init_memory() { count++; ptr->type = 1; - ptr->base = (u32)boot_info->kernel_base+ (u32)boot_info->kernel_size; + ptr->base = (u32)boot_info->kernel_base + (u32)boot_info->kernel_size; ptr->length = 0xf000000; boot_info->total_memory += ptr->length; ptr++; @@ -403,11 +407,17 @@ void load_elf(Elf32_Ehdr* elf_header) { for (int i = 0; i < elf_header->e_phnum; i++) { printf("type:%d\n\r", phdr[i].p_type); switch (phdr[i].p_type) { - case PT_NULL: + case PT_NULL:{ + char* vaddr = phdr[i].p_vaddr; // printf(" %s %x %x %x %s %x %x \r\n", "NULL", phdr[i].p_offset, // phdr[i].p_vaddr, phdr[i].p_paddr, "", phdr[i].p_filesz, // phdr[i].p_memsz); - break; + + // int num = boot_data.segments_number++; + // boot_data.segments[num].start = vaddr; + // boot_data.segments[num].size = phdr[i].p_memsz; + // boot_data.segments[num].type = 1; + } break; case PT_LOAD: { // printf(" %s %x %x %x %s %x %x \r\n", "LOAD", phdr[i].p_offset, // phdr[i].p_vaddr, phdr[i].p_paddr, "", phdr[i].p_filesz, @@ -419,6 +429,12 @@ void load_elf(Elf32_Ehdr* elf_header) { phdr[i].p_filesz); memmove32(vaddr, start, phdr[i].p_memsz); printf("move end\n\r"); + + int num = boot_data.segments_number++; + boot_data.segments[num].start = vaddr; + boot_data.segments[num].size = phdr[i].p_memsz; + boot_data.segments[num].type = 1; + } break; default: break; @@ -431,6 +447,12 @@ void load_elf(Elf32_Ehdr* elf_header) { if (SHT_NOBITS == shdr[i].sh_type) { char* vaddr = shdr[i].sh_addr; memset(vaddr, 0, shdr[i].sh_size); + + // int num = boot_data.segments_number++; + // boot_data.segments[num].start = vaddr; + // boot_data.segments[num].size = phdr[i].p_memsz; + // boot_data.segments[num].type = 1; + // map_alignment(page,vaddr,buf,shdr[i].sh_size); } else if (entry != shdr[i].sh_addr && SHT_PROGBITS == shdr[i].sh_type && shdr[i].sh_flags & SHF_ALLOC && shdr[i].sh_flags) { @@ -441,6 +463,11 @@ void load_elf(Elf32_Ehdr* elf_header) { u32* phstart = (u32)elf + shdr[i].sh_offset; memset(vaddr, 0, shdr->sh_size); memmove32(phstart, vaddr, shdr[i].sh_size); + + // int num = boot_data.segments_number++; + // boot_data.segments[num].start = vaddr; + // boot_data.segments[num].size = phdr[i].p_memsz; + // boot_data.segments[num].type = 1; } } } diff --git a/boot/x86-duck/SConscript b/boot/x86-duck/SConscript index 8e134606..e9568ee2 100644 --- a/boot/x86-duck/SConscript +++ b/boot/x86-duck/SConscript @@ -12,7 +12,7 @@ Import('env') gcc_env = Environment(CC='gcc-mp-8',tools=['default'],ENV=os.environ) -env.GenerateKernelSize('config.h', ['../../init/kernel']) +env.GenerateKernelSize('config.h',['../../duck/init/kernel']) gcc_env.ParseConfig('sdl2-config --cflags --libs') diff --git a/boot/x86/SConscript b/boot/x86/SConscript index d9d5280a..1ffce875 100644 --- a/boot/x86/SConscript +++ b/boot/x86/SConscript @@ -20,9 +20,22 @@ nasm_env.StaticObject('boot', ['boot.s'],ASFLAGS='-f bin') Import('env') -env.GenerateKernelSize('config.h',['../../init/kernel']) +env.GenerateKernelSize('config.h',['../../duck/init/kernel']) + + +include=[ + '.', + 'include', + '../../duck', + '../../duck/platform/'+env['PLATFORM'] +] + + +source=['init.c','config.h'] + env.Program('init.elf', - ['init.c','config.h'], + source, + CPPPATH=include, CFLAGS='$CFLAGS -I. -Iinclude -Iarch -std=c99 -std=gnu99 -w ', LINKFLAGS= '$LINKFLAGS -T boot/x86/link.ld ') #-Ttext 0x0500 -Wl,-section-start=.apu_boot=0x1000 diff --git a/boot/x86/config.h b/boot/x86/config.h index 5bc3e2f3..c2e2b3f6 100644 --- a/boot/x86/config.h +++ b/boot/x86/config.h @@ -1,5 +1,5 @@ #ifndef BOOT_X86_CONFIG_H #define BOOT_X86_CONFIG_H -#define KERNEL_BLOCK_SIZE 106 -#define KERNEL_SIZE 107768 +#define KERNEL_BLOCK_SIZE 354 +#define KERNEL_SIZE 361684 #endif diff --git a/boot/x86/init.c b/boot/x86/init.c index a85ba4db..244d31fa 100644 --- a/boot/x86/init.c +++ b/boot/x86/init.c @@ -17,7 +17,7 @@ boot_info_t* boot_info = NULL; boot_info_t boot_data; u8 kernel_stack[1024]; // 1k u8 kernel_stack_top[0]; -int cpu_id=0; +int cpu_id = 0; void cls() { // clear screen @@ -125,6 +125,9 @@ void init_boot_info() { boot_info->gdt_number = GDT_NUMBER; boot_info->pdt_base = PDT_BASE; boot_info->tss_number = CPU_NUMBER; + boot_info->segments_number = 0; + boot_info->kernel_stack=kernel_stack; + boot_info->kernel_stack_size=kernel_stack_top -kernel_stack; } void init_disk() { @@ -152,8 +155,7 @@ void* memmove(void* s1, const void* s2, u32 n) { u8 disk_read(u16 disk, u16 head, u16 cylinder, u16 sector, u16 number, u32 addr, u8* status) { u8 carry = 0; - u16 cx = - ((cylinder & 0xff) << 8) | (sector & 0xff); + u16 cx = ((cylinder & 0xff) << 8) | (sector & 0xff); u16 bx = (addr & 0xffff); u16 es = ((addr >> 4) & 0xf000); u16 dx = (head << 8) | disk; @@ -180,7 +182,8 @@ u8 disk_read_lba(u32 lba, u32 addr, u8* status) { u32 sector = (lba % boot_info->disk.spt) + 1; // todo read by disk type - //printf("addr:%x lba:%d CHS = (%d, %d, %d)\r\n", addr,lba,cylinder,head,sector); + // printf("addr:%x lba:%d CHS = (%d, %d, %d)\r\n", + // addr,lba,cylinder,head,sector); u8 ret = disk_read(0, head, cylinder, sector, 1, addr, status); if (ret == 0) { // printf("addr %x ", addr); @@ -191,16 +194,15 @@ u8 disk_read_lba(u32 lba, u32 addr, u8* status) { return ret; } -void __attribute__((naked)) apu_boot(){ +void __attribute__((naked)) apu_boot() { #if defined(__WIN32__) -asm("jmpl $0x0000, $_init_apu_boot\n"); + asm("jmpl $0x0000, $_init_apu_boot\n"); #else -asm("jmpl $0x0000, $init_apu_boot\n"); + asm("jmpl $0x0000, $init_apu_boot\n"); #endif } - -void init_apu_boot(){ +void init_apu_boot() { cls(); printf("boot apu info addr %x\n\r", boot_info); init_gdt(); @@ -210,9 +212,9 @@ void init_apu_boot(){ "movl %0, %%esp\n" "mov %%esp,%%ebp\n" : - : "m"(kernel_stack_top));\ + : "m"(kernel_stack_top)); -#if defined(__WIN32__) +#if defined(__WIN32__) asm("jmpl %0, $_start_apu_kernel" ::"i"(GDT_ENTRY_32BIT_CS * GDT_SIZE)); #else asm("jmpl %0, $start_apu_kernel" ::"i"(GDT_ENTRY_32BIT_CS * GDT_SIZE)); @@ -270,9 +272,9 @@ void read_kernel() { ; } - //move apu entry - memmove(SECOND_BOOT_ENTRY,&apu_boot,32*8); - boot_info->second_boot_entry=SECOND_BOOT_ENTRY; + // move apu entry + memmove(SECOND_BOOT_ENTRY, &apu_boot, 32 * 8); + boot_info->second_boot_entry = SECOND_BOOT_ENTRY; } static inline void enable_a20() { @@ -387,9 +389,9 @@ void init_boot() { "movl %0, %%esp\n" "mov %%esp,%%ebp\n" : - : "m"(kernel_stack_top));\ - -#if defined(__WIN32__) + : "m"(kernel_stack_top)); + +#if defined(__WIN32__) asm("jmpl %0, $_start_kernel" ::"i"(GDT_ENTRY_32BIT_CS * GDT_SIZE)); #else asm("jmpl %0, $start_kernel" ::"i"(GDT_ENTRY_32BIT_CS * GDT_SIZE)); @@ -400,8 +402,6 @@ void init_boot() { ; } - - asm(".code32\n"); void* load_kernel() { @@ -444,6 +444,12 @@ void* memmove32(void* s1, const void* s2, u32 n) { } } +void* memset(void* s, int c, size_t n) { + int i; + for (i = 0; i < n; i++) ((char*)s)[i] = c; + return s; +} + void load_elf(Elf32_Ehdr* elf_header) { // printf("e_phnum:%d\n\r", elf_header->e_phnum); u16* elf = elf_header; @@ -453,11 +459,16 @@ void load_elf(Elf32_Ehdr* elf_header) { for (int i = 0; i < elf_header->e_phnum; i++) { // printf("type:%d\n\r", phdr[i].p_type); switch (phdr[i].p_type) { - case PT_NULL: + case PT_NULL: { + char* vaddr = phdr[i].p_vaddr; // printf(" %s %x %x %x %s %x %x \r\n", "NULL", phdr[i].p_offset, // phdr[i].p_vaddr, phdr[i].p_paddr, "", phdr[i].p_filesz, // phdr[i].p_memsz); - break; + int num = boot_data.segments_number++; + boot_data.segments[num].start = vaddr; + boot_data.segments[num].size = phdr[i].p_memsz; + boot_data.segments[num].type = 1; + } break; case PT_LOAD: { // printf(" %s %x %x %x %s %x %x \r\n", "LOAD", phdr[i].p_offset, // phdr[i].p_vaddr, phdr[i].p_paddr, "", phdr[i].p_filesz, @@ -467,6 +478,11 @@ void load_elf(Elf32_Ehdr* elf_header) { // printf("load start:%x vaddr:%x size:%x \n\r", start, vaddr, // phdr[i].p_filesz); memmove32(vaddr, start, phdr[i].p_filesz); + + int num = boot_data.segments_number++; + boot_data.segments[num].start = vaddr; + boot_data.segments[num].size = phdr[i].p_memsz; + boot_data.segments[num].type = 1; // printf("move end\n\r"); } break; // case PT_DYNAMIC: @@ -533,6 +549,32 @@ void load_elf(Elf32_Ehdr* elf_header) { break; } } + Elf32_Shdr* shdr = (elf + elf_header->e_shoff / 2); + for (int i = 0; i < elf_header->e_shnum; i++) { + if (SHT_NOBITS == shdr[i].sh_type) { + char* vaddr = shdr[i].sh_addr; + char* start = shdr[i].sh_offset; + if (shdr[i].sh_flags & SHF_ALLOC) { + memset(vaddr, 0, shdr[i].sh_size); + int num = boot_data.segments_number++; + boot_data.segments[num].start = vaddr; + boot_data.segments[num].size = shdr[i].sh_size; + boot_data.segments[num].type = 1; + } + } else if ((shdr[i].sh_type & SHT_PROGBITS == SHT_PROGBITS) && + (shdr[i].sh_flags & + SHF_ALLOC == SHF_ALLOC)) { //&& (shdr[i].sh_flags & + // SHF_WRITE==SHF_WRITE) + char* start = shdr[i].sh_offset; + char* vaddr = shdr[i].sh_addr; + //memmove32(vaddr, start, shdr[i].sh_size); + + int num = boot_data.segments_number++; + boot_data.segments[num].start = vaddr; + boot_data.segments[num].size = shdr[i].sh_size; + boot_data.segments[num].type = 1; + } + } } // start kernel @@ -554,7 +596,7 @@ void start_kernel() { start(argc, argv, envp); } -//start kernel +// start kernel void start_apu_kernel() { asm volatile("cli\n"); asm volatile("movl %0, %%ss" : : "r"(GDT_ENTRY_32BIT_DS * GDT_SIZE)); diff --git a/boot/xtensa/SConscript b/boot/xtensa/SConscript index 7fdd1a76..1874b2b7 100644 --- a/boot/xtensa/SConscript +++ b/boot/xtensa/SConscript @@ -9,7 +9,7 @@ import os Import('env') -env.GenerateKernelSize('config.h',['../../init/kernel']) +env.GenerateKernelSize('config.h',['../../duck/init/kernel']) env.Object('boot', ['boot.s'],ASFLAGS='') diff --git a/docs/develop/image/2022-11-19-19-30-22.png b/docs/develop/image/2022-11-19-19-30-22.png new file mode 100644 index 00000000..74e40c15 Binary files /dev/null and b/docs/develop/image/2022-11-19-19-30-22.png differ diff --git a/docs/develop/image/2022-11-19-19-35-15.png b/docs/develop/image/2022-11-19-19-35-15.png new file mode 100644 index 00000000..591c0e08 Binary files /dev/null and b/docs/develop/image/2022-11-19-19-35-15.png differ diff --git a/docs/develop/image/2022-11-19-20-41-32.png b/docs/develop/image/2022-11-19-20-41-32.png new file mode 100644 index 00000000..e9a045e6 Binary files /dev/null and b/docs/develop/image/2022-11-19-20-41-32.png differ diff --git a/docs/develop/image/2022-11-27-00-34-44.png b/docs/develop/image/2022-11-27-00-34-44.png new file mode 100644 index 00000000..b22ea85a Binary files /dev/null and b/docs/develop/image/2022-11-27-00-34-44.png differ diff --git a/docs/develop/image/2022-11-27-00-36-53.png b/docs/develop/image/2022-11-27-00-36-53.png new file mode 100644 index 00000000..e2464d3e Binary files /dev/null and b/docs/develop/image/2022-11-27-00-36-53.png differ diff --git a/docs/develop/image/2022-11-27-00-45-11.png b/docs/develop/image/2022-11-27-00-45-11.png new file mode 100644 index 00000000..0989883a Binary files /dev/null and b/docs/develop/image/2022-11-27-00-45-11.png differ diff --git "a/docs/develop/\345\206\205\346\240\270\345\274\200\345\217\221.md" "b/docs/develop/\345\206\205\346\240\270\345\274\200\345\217\221.md" index 224deff6..4b559b9a 100644 --- "a/docs/develop/\345\206\205\346\240\270\345\274\200\345\217\221.md" +++ "b/docs/develop/\345\206\205\346\240\270\345\274\200\345\217\221.md" @@ -1,24 +1,315 @@ # 内核开发 +在YiYiYa操作系统,使用的是鸭内核duck kernel。内核项目是单独的,所以在开发中可以仅仅更新内核,而不需要修改其他地方的源码,方便内核迭代升级。 + +鸭内核使用的是模块化的设计,和一般的os概念差别不是特别明显。 + ## 进程管理 +在鸭内核,进程统一是特定主题的集合,名字叫thread。所有thread开头的函数都是进程相关的操作。 + +不管是内核进程和用户进程,两个概念是一致的,区别在于进程的运行内核等级不一样,内核进程权限高,而用户进程在用户空间中,没有特别的权限访问内核资源,保证了内核的可靠性,防止进行非法操作。 + +### 进程创建 + +理解进程中一个重要的结构是thread_t。thread_t包括了进程的名字和拥有的资源和权限等。 + +```c +typedef struct thread { + u32 id;//进程id + u8* name;//进程名称 + int priority;//进程优先级 + int counter;//进程运行tick数 + int state;//进程状态 + int sleep_counter; + struct thread_s* next;//下一个进程 + void* data;//私有数据 + void* exec;//运行参数 + context_t context;//进程上下文 + vmemory_area_t* vmm;//进程虚拟内存范围 + u32 pid;//父进程 + u32** fds;//拥有的文件 + u32 fd_size;//文件最大数量 + u32 fd_number;//文件数量 + u32 lock; + u32 code;//错误码 + u32 fault_count; + vfs_t* vfs;//当前文件路径 + u32 level;//进程等级 + u32 cpu_id;//所在哪个cpu上运行 + u32 mem;//进程内存使用量 +} thread_t; +``` + +使用thread_create_name_level创建带权限等级的进程,KERNEL_MODE表示是内核进程。内核进程为kernel id为0。在shell中使用ps命令可以看到。shell进程是普通的用户进程,运行在用户空间,有单独的堆栈和页目录。 + +thread_create_name经常用来创建用户进程。创建后需要调用thread_run,让这个进程运行。 + +```c +int kmain(int argc, char* argv[]) { + kernel_init(); + + thread_t* t1 = thread_create_name_level("kernel", (u32*)&do_kernel_thread, + NULL, KERNEL_MODE); + thread_t* t2 = thread_create_name("shell", (u32*)&do_shell_thread, NULL); + thread_run(t1); + thread_run(t2); + ... + return 0; +} +``` + +id为0的是内核进程,做内核初始化和模块加载等功能。id为1的是用户进程,是shell进程,用户和YiYiYa操作系统交互的主要途径。 + +![](image/2022-11-19-20-41-32.png) + +### 进程停止 + +进程可以通过thread_stop和thread_exit进行停止运行或者退出运行。thread_stop会修改进程状态为stop。thread_exit会修改返回code错误码。 + +如下所示,为一个系统调用退出,供c语言中的exit(0),功能等效。 + +```c + +void sys_exit(int status) { + thread_t* current = thread_current(); + thread_exit(current, status); + // thread_dumps(); + log_debug("sys exit tid %d %s status %d\n", current->id, current->name, + status); +} +``` + ## 文件系统 +在鸭内核中,文件系统使用的是Virtual File System,简称VFS,为什么要使用VFS,主要是可以实现多种文件系统的支持和扩展。 + +在文件系统中,最小的单位是vnode_t,它定义了一个最基本的文件,这个文件可以是设备,也可以是文件,或者其他的虚拟等等。所有的操作,都通过vnode进行。 + +```c +typedef struct vnode { + char *name; // The filename. + u32 mask; // The permissions mask. + u32 uid; // The owning user. + u32 gid; // The owning group. + u32 flags; // Includes the node type. See #defines above. + u32 inode; // This is device-specific - provides a way for a filesystem to + // identify files. + u32 length; // Size of the file, in bytes. + u32 impl; // An implementation-defined number. + vnode_t *parent; // Used by mountpoints and symlinks. + vnode_t **child; + vnode_t *super; + size_t child_number; + size_t child_size; + void *data; + void *device; + voperator_t *op;//文件操作辅助功能 +} vnode_t; +``` + + +### 文件的创建 + +创建一个时间设备文件,通过先创建文件节点vfs_create_node,后定义op操作,然后就完成了文件创建。 + +```c +// time +device_t* rtc_dev = device_find(DEVICE_RTC); +if (rtc_dev != NULL) { + vnode_t* time = vfs_create_node("time", V_FILE); + vfs_mount(NULL, "/dev", time); + time->device = rtc_dev; + time->op = &device_operator; +} else { + kprintf("dev time not found\n"); +} + +``` + +### 文件挂载操作 + +在鸭内核中,挂载通过vfs_mount来实现,挂载到特定目录。创建时间设备后,通过vfs_mount传入,挂载的文件地址,就可以挂载时间为一个文件,最后路径是/dev/time,在应用层,就可以对它进行读写操作。 + +```c +vfs_mount(NULL, "/dev", time); +``` + + ## 内存管理 +鸭内核使用的内存管理,比较简单,一个最基本的物理内存管理,和基于内存池的页式内存管理。 + +在内核中使用通过kmalloc函数进行内存申请,kfree进行内存释放。缺页的管理是内核自动托管,不需要手工处理。 + +鸭内核可以扩展物理内存管理,目前有2套物理内存管理方法。 + +### 物理内存使用 + +通过定义arch/memory.c文件中的memory_manager_t结构,可以自定义物理内存管理。 + +```c +void mm_init() { + kprintf("mm init\n"); + mmt.init = ya_alloc_init;//设置内存分配初始化函数 + mmt.alloc = ya_alloc;//设置内存分配函数 + mmt.free = ya_free;//设置内存释放函数 + mmt.blocks = NULL; + mmt.blocks_tail = NULL; + mmt.g_block_list = NULL; + mmt.g_block_list_last = NULL; + mmt.alloc_count = 0; + mmt.alloc_size = 0; + mmt.last_map_addr = 0; + mmt.extend_phy_count = 0; + ... +} + + +void* mm_alloc(size_t size) { + return mmt.alloc(size); +} + +void mm_free(void* p) { + return mmt.free(p); +} + +``` + +### 虚拟内存使用 + +鸭内核中,虚拟内存使用,通过kmalloc进行的,kmalloc根据标志,分配物理内存还是虚拟内存。 + +物理内存时候,调用phy_alloc,虚拟内存时候调用vm_alloc。用法比较简单。 + +```c +void* kmalloc(size_t size, u32 flag) { + void* addr = NULL; + if (flag & KERNEL_TYPE || flag & DEVICE_TYPE) { + addr = phy_alloc(size); + } else { + addr = vm_alloc(size); + } + return addr; +} +``` + +另外缺页内存分配,使用的是valloc,当应用程序访问某个地址的时候,内核发现地址不存在,就会进行页分配。最后会调用valloc 尝试分配一个物理内存,同时映射到虚拟内存地址。 + +```c + +void *phy = virtual_to_physic(current->context.upage, fault_addr); +if (phy == NULL) { + valloc(fault_addr, PAGE_SIZE); +} else { + log_error("%s phy: %x remap memory fault at %x\n", current->name, phy, + fault_addr); + context_dump_fault(context, fault_addr); + thread_exit(current, -1); + cpu_halt(); +} + +``` + ## 模块管理 -## 平台模块 +由于YiYiYa使用模块化的的实现,所以大部分要做的事情是定义模块。基本的过程是定义模块,然后注册模块。 + +在新增内核功能,特别是驱动,都是通过模块的管理,方便内核的功能裁剪,可以动态编译添加所需模块。 +### 定义模块 +引入内核头kernel.h,定义一个hello_module模块,为moudle_t的类型。 + +```c +#include "kernel/kernel.h" + +int hello_init(void) { + kprintf("Hello World\n"); + //驱动设备初始化 + serial_init(); + ... + return 0; +} + +void hello_exit(void) { kprintf("hello exit\n"); } + +module_t hello_module = { + .name ="hello", + .init=hello_init, + .exit=hello_exit +}; +``` + +### 注册模块 + +在内核中需要在内核启动的线程中注册,这样YiYiYa操作系统就会识别到模块,然后在内核线程启动的时候,完成了模块的加载,就可以运行在内核中了。 + +```c +//引入模块 +extern module_t hello_module; + +void modules_init(void) { + ... + //注册模块 + module_regist(&hello_module); +} + +``` +## 系统功能 + +在鸭内核中,用户态用到的功能都是在sysfn下,每次使用都会进行系统调用。在添加新的内核功能时候,需要在系统调用表中syscall_table定义和使用。 + +```c + +void sys_fn_init(void** syscall_table) { + syscall_table[SYS_READ] = &sys_read; + syscall_table[SYS_WRITE] = &sys_write; + syscall_table[SYS_YIELD] = &sys_yeild; + syscall_table[SYS_PRINT] = &sys_print; + syscall_table[SYS_PRINT_AT] = &sys_print_at; + syscall_table[SYS_IOCTL] = &sys_ioctl; + syscall_table[SYS_OPEN] = &sys_open; + syscall_table[SYS_CLOSE] = &sys_close; + syscall_table[SYS_DEV_READ] = &dev_read; + syscall_table[SYS_DEV_WRITE] = &dev_write; + syscall_table[SYS_DEV_IOCTL] = &dev_ioctl; + syscall_table[SYS_EXEC] = &sys_exec; + syscall_table[SYS_TEST] = &sys_test; + syscall_table[SYS_EXIT] = &sys_exit; + syscall_table[SYS_MAP] = &sys_vmap; + syscall_table[SYS_UMAP] = &sys_vumap; + syscall_table[SYS_SEEK] = &sys_seek; + syscall_table[SYS_VALLOC] = &sys_valloc; + syscall_table[SYS_VFREE] = &sys_vfree; + syscall_table[SYS_VHEAP] = &sys_vheap; + syscall_table[SYS_FORK] = &sys_fork; + syscall_table[SYS_PIPE] = &sys_pipe; + syscall_table[SYS_GETPID] = &sys_getpid; + syscall_table[SYS_GETPPID] = &sys_getppid; + syscall_table[SYS_DUP] = &sys_dup; + syscall_table[SYS_DUP2] = &sys_dup2; + ... +} +``` ## 进程间通信 +目前的进程有管道。通过pipe管道,可以在用户间进行进程通信。 + + ## 同步原语 +## 多核 + +鸭os支持多核方式,需要配置内核platform/platform.h文件开启动多核模式。这样在内核进程中会提示mp init,然后,在进行其他cpu的启动。 + +```c +#define MP_ENABLE 1 //多cpu +``` \ No newline at end of file diff --git "a/docs/develop/\345\256\236\344\276\213Demo.md" "b/docs/develop/\345\256\236\344\276\213Demo.md" index e69de29b..2534c088 100644 --- "a/docs/develop/\345\256\236\344\276\213Demo.md" +++ "b/docs/develop/\345\256\236\344\276\213Demo.md" @@ -0,0 +1,4 @@ +# 实例 + +## ls应用 + diff --git "a/docs/develop/\345\272\224\347\224\250\345\274\200\345\217\221.md" "b/docs/develop/\345\272\224\347\224\250\345\274\200\345\217\221.md" index e69de29b..e65ed566 100644 --- "a/docs/develop/\345\272\224\347\224\250\345\274\200\345\217\221.md" +++ "b/docs/develop/\345\272\224\347\224\250\345\274\200\345\217\221.md" @@ -0,0 +1,4 @@ +# 应用开发 + +在YiYiYa中应用开发,主要涉及到app目录和eggs目录。app目录是先有的各种应用集合。而eggs是很多基础库。 + diff --git "a/docs/develop/\346\272\220\347\240\201\347\233\256\345\275\225.md" "b/docs/develop/\346\272\220\347\240\201\347\233\256\345\275\225.md" index e69de29b..08d8e84f 100644 --- "a/docs/develop/\346\272\220\347\240\201\347\233\256\345\275\225.md" +++ "b/docs/develop/\346\272\220\347\240\201\347\233\256\345\275\225.md" @@ -0,0 +1,2 @@ +# 源码目录 + diff --git "a/docs/develop/\347\241\254\344\273\266\350\260\203\350\257\225.md" "b/docs/develop/\347\241\254\344\273\266\350\260\203\350\257\225.md" new file mode 100644 index 00000000..ada45871 --- /dev/null +++ "b/docs/develop/\347\241\254\344\273\266\350\260\203\350\257\225.md" @@ -0,0 +1,58 @@ +# 硬件调试 + +正常情况下,在qemu上开发好后,在真实硬件下运行,然而现实免不了出错,这时候就需要用到硬件调试,来定位问题和错误。针对不同的开发板子,涉及到的调试是不太一样的,以下是YiYiYa中涉及的硬件调试,可以参考。 + +## V3S 开发版本调试 + +1、uboot 编译成无mmc模式 + +修改uboot的v3s版本的配置文件`LicheePi_Zero_480x272LCD_defconfig` + +>CONFIG_SPL_MMC_SUPPORT=n +>CONFIG_MMC=n + +2、uboot编译 + +```sh +cd uboot +export CROSS_COMPILE=arm-none-eabi- +export ARCH=armv7a +gmake LicheePi_Zero_480x272LCD_defconfig +gmake -j8 +``` + +如果mac下编译,出现python3版本报错,运行以下的命令后再编译。 + +```sh +export HOSTLDFLAGS="-lpython3.8 -dynamclib" +export LDFLAGS=`python3.4-config --cflags --ldflags` +``` + +3、硬件Jlink连接 + +JLink的1,2两引脚,1脚为3.3v,2脚为GND。 + +|SD卡引脚|JTAG引脚|SD卡信号| +|-----|------|-----| +|8 |GND |GND | +|1 |TCK |D2 | +|8 |TMS |D1 | +|7 |TDI |D0 | +|3 |TDO |CMD | +|4 |VT |VCC | + +启动jlinkgdbserver,配置成cortex-a7 就可以直接连了。 + +![](image/2022-11-19-19-35-15.png) + +4、启动运行 + +在vscode中选择,点击调试运行。 + +![](image/2022-11-19-19-30-22.png) + + +可以直接通过命令运行 +```sh +scons --run=v3s +``` \ No newline at end of file diff --git "a/docs/develop/\347\247\273\346\244\215\351\200\202\351\205\215.md" "b/docs/develop/\347\247\273\346\244\215\351\200\202\351\205\215.md" index e69de29b..fc579489 100644 --- "a/docs/develop/\347\247\273\346\244\215\351\200\202\351\205\215.md" +++ "b/docs/develop/\347\247\273\346\244\215\351\200\202\351\205\215.md" @@ -0,0 +1,106 @@ +# 移植适配 + +## X86 移植 + + +## ARMV7-A Cortext-a7 移植 + +移植适配资料请参考DDI0406C_d_armv7ar_arm.pdf官方文件。 + +### 几个重要的寄存器 + +堆栈,r13(sp)每个模式都有各自独立的堆栈, +链接,r14(lr)保存跳转前返回的地址,每个模式下都有各自的lr,bl、bx时候会把pc+4 地址给到lr。 + + +根据文档 B1.8.3 Overview of exception entry章节 + +异常模式时候,异常模式的r14用来保存异常返回地址。 + +![](image/2022-11-27-00-34-44.png) + + +pl1 模式就是特权模式(FIQ、IRQ,Abort 、svc,und,system),pl0是用户权限,pl2是hyp模式。所以如下图,irq中,lr保存的地址为pc+4 + +![](image/2022-11-27-00-36-53.png) + + +IRQ异常时候流程,参考B1.9.10 IRQ exception的Pseudocode description of taking the IRQ exception。 +异常时候,保存cpsr值到spsr,同时在arm下lr存的地址,为异常时候的pc-4。修改cpsr的m标志为irq模式。最后,跳转到向量地址运行异常程序。 + +![](image/2022-11-27-00-45-11.png) + + +ldm{cond} mode rn{!}, reglist{^} +stm{cond} mode rn{!}, reglist{^} + +^ : 如果reglist有pc寄存器,它表示指令执行后,spsr寄存器的值将自动复制到cpsr寄存器 + + +根据文档,cortex-a7不会像x86一样自动push到堆栈,所以保存上下文,需要自己处理,定义上下文结构: + +``` +// manual push +u32 no; +u32 code; + +u32 psr; +u32 pc; // return to user addr + +u32 r0; +u32 r1; +u32 r2; +u32 r3; +u32 r4; +u32 r5; +u32 r6; +u32 r7; +u32 r8; +u32 r9; +u32 r10; +u32 r11; // fp +u32 r12; // ip +u32 sp; // r13 user sp +u32 lr; // r14 user lr +``` + +压入堆栈操作,保存切换的上下文 + +```c +#define interrupt_entering_code(VEC, CODE) \ + asm volatile( \ + "stmfd sp, {r0-r12,sp,lr}^\n" \ + "subs sp,sp,#60\n" \ + "mrs r0,spsr\n" \ + "stmfd sp!, {r0,lr} \n" \ + "mov r1,%0\n" \ + "mov r2,%1\n" \ + "stmfd sp!, {r1,r2} \n" \ + "mov r0,sp\n" \ + : \ + : "i"(VEC), "i"(CODE)) +``` + +恢复上下文操作。 + +```c +#define interrupt_exit_context(duck_context) \ + asm volatile( \ + "ldr sp,%0 \n" \ + "ldmfd sp!,{r1,r2}\n" \ + "ldmfd sp!,{r0,lr}\n" \ + "msr spsr,r0\n" \ + "ldmfd sp,{r0-r12,sp,lr}^\n" \ + "add sp,sp,#60\n" \ + "subs pc,lr,#4\n" \ + : \ + : "m"(duck_context->ksp)) +``` + + +## RISC-V 移植 + + + + + diff --git "a/docs/develop/\351\251\261\345\212\250\345\274\200\345\217\221.md" "b/docs/develop/\351\251\261\345\212\250\345\274\200\345\217\221.md" index e69de29b..b712ff13 100644 --- "a/docs/develop/\351\251\261\345\212\250\345\274\200\345\217\221.md" +++ "b/docs/develop/\351\251\261\345\212\250\345\274\200\345\217\221.md" @@ -0,0 +1,142 @@ +# 驱动开发 + +在YiYiYa中,对设备的操作就会涉及到驱动开发,常见的开发有LCD屏幕、串口驱动等。这就涉及到YiYiYa的模块组件,模块可以是一个驱动设备,也可以是一个软件设备,或者特定内核功能。 + +## 模块 + +由于YiYiYa使用模块化的的实现,所以大部分要做的事情是定义模块。基本的过程是定义模块,然后注册模块。 + + +1、定义模块 + +引入内核头kernel.h,定义一个hello_module模块,为moudle_t的类型。 + +```c +#include "kernel/kernel.h" + +int hello_init(void) { + kprintf("Hello World\n"); + //驱动设备初始化 + serial_init(); + ... + return 0; +} + +void hello_exit(void) { kprintf("hello exit\n"); } + +module_t hello_module = { + .name ="hello", + .init=hello_init, + .exit=hello_exit +}; +``` + +2、注册模块 + +在内核中需要在内核启动的线程中注册,这样YiYiYa操作系统就会识别到模块,然后在内核线程启动的时候,完成了模块的加载,就可以运行在内核中了。 + +```c +//引入模块 +extern module_t hello_module; + +void modules_init(void) { + ... + //注册模块 + module_regist(&hello_module); +} + +``` + + +## 驱动开发相关函数 + +在使用内核过程中,需要使用到相关的内核功能。下面就介绍基础的函数和使用方式。 + +### 设备类型device_t + +device_t是驱动中重要的概念,是设备特有的结构,里面存设备的信息,设备的类型字符char,block块设备,显示器设备等,也包含定义了读写操作等。当你初始化一个设备后,通过device_add添加到设备管理列表中,在其他地方就可以使用了,通过device_find_name查找。 + +```c +//设备device_t定义 +typedef struct device { + char* name; + u32 id; + u32 type; // char block vga + dev_read_fn read; + dev_write_fn write; + dev_ioctl_fn ioctl; + dev_stat_fn stat; + void* data; // data +} device_t; + +//创建一个设备 +device_t* serial=device_create("serial",DEVICE_SERIAL,DEVICE_TYPE_CHAR); + +//添加到设备列表中 +device_add(serial); + +//根据设备名字查找 +device_t* serial= device_find_name("serial"); + +``` + + + + +### 内存分配kmalloc、kfree + +在内核驱动开发中,初始化一般在module init 方式,通过kmalloc分配一个设备类型的结构,后续可以对这个设备类型进行初始化,并添加到设备列表中。 + +```c +int serial_init(void) { + //申请一个设备类型 + device_t* dev = kmalloc(sizeof(device_t),DEFAULT_TYPE);//等同 device_create + //初始化 + dev->name = "serial"; + dev->read = read; + dev->write = write; + dev->id = DEVICE_SERIAL; + dev->type = DEVICE_TYPE_CHAR; + //添加到设备列表中 + device_add(dev); + ... +} +``` + + +### 文件系统相关vfs_create_node、vfs_mount + + +vfs_create_node创建一个文件节点,这个文件系统节点就可以进行挂载操作,通过vfs_mount挂载到特定目录下。这样,在文件系统访问路径/dev/serial就可以对设备进行读写操作了。 + + +```c +int serial_init(void) { + device_t* dev = kmalloc(sizeof(device_t),DEFAULT_TYPE); + dev->name = "serial"; + dev->read = read; + dev->write = write; + dev->id = DEVICE_SERIAL; + dev->type = DEVICE_TYPE_CHAR; + device_add(dev); + + //挂载设备文件系统到dev目录下,名字为series + vnode_t* series = vfs_create_node("series", V_FILE); + vfs_mount(NULL, "/dev", series); + series->device = dev; + series->op = &device_operator; + + return 0; +} +``` + +### 内存操作map_page + +当有些设备,需要映射到特定地址,让程序访问,这时候就需要使用到map_page操作,以页为单位。如映射显存地址。如果不映射,会存在操作系统会报错page fault。这样你就访问不到设备了。 + +```c +for (int i = 0; i < size * vga->framebuffer_count / PAGE_SIZE/8; i++) { + map_page(addr, addr, PAGE_P | PAGE_USU | PAGE_RWW); + addr += PAGE_SIZE; +} +``` \ No newline at end of file diff --git a/duck b/duck index e7c39dd2..27ac32e1 160000 --- a/duck +++ b/duck @@ -1 +1 @@ -Subproject commit e7c39dd2b45b69be65ccbe084699e9ae7e1c27ce +Subproject commit 27ac32e13bf5e2df7f4f877cddfbcc188e752203 diff --git a/eggs b/eggs index 1a9d69f9..d2a0106b 160000 --- a/eggs +++ b/eggs @@ -1 +1 @@ -Subproject commit 1a9d69f9c26ef1c0694c4f77e507d77ac491cdc9 +Subproject commit d2a0106b126b807ea669d2d469778a06e35978d1 diff --git a/image/SConscript b/image/SConscript index 94524608..e8653204 100644 --- a/image/SConscript +++ b/image/SConscript @@ -48,9 +48,9 @@ if env.get('ARCHTYPE')=='x86': debug_qemu_cmd='ggdb '+run_qemu_cmd pass else: - run_qemu_cmd='qemu-system-i386 -smp 1,sockets=1 -m 512M -name YiYiYa -rtc base=localtime,clock=host -boot a -fda $SOURCE -serial stdio -D ./qemu.log -drive id=disk,file=image/disk.img,format=raw,if=none -device ahci,id=ahci -device ide-hd,drive=disk,bus=ahci.0 -soundhw sb16 -net user -net nic,model=e1000 ' #-d in_asm -d cpu_reset -d in_asm,int,mmu -chardev socket,id=monitor,path=monitor.sock,server,nowait -monitor chardev:monitor + run_qemu_cmd='qemu-system-i386 -smp 1,sockets=1 -m 512M -name YiYiYa -rtc base=localtime,clock=host -boot a -fda $SOURCE -serial stdio -D ./qemu.log -drive id=disk,file=image/disk.img,format=raw,if=none -device ahci,id=ahci -device ide-hd,drive=disk,bus=ahci.0 -device sb16 -net user -net nic,model=e1000 ' #-d in_asm -d cpu_reset -d in_asm,int,mmu -chardev socket,id=monitor,path=monitor.sock,server,nowait -monitor chardev:monitor # run_qemu_cmd =run_qemu_cmd+' -monitor tcp:127.0.0.1:55555,server,nowait' - debug_qemu_cmd = 'qemu-system-i386 -smp 2,sockets=1 -m 512M -name YiYiYa -rtc base=localtime -boot a -S -s -fda $SOURCE -serial stdio -D ./qemu.log -drive id=disk,file=image/disk.img,format=raw,if=none -device ahci,id=ahci -device ide-hd,drive=disk,bus=ahci.0 -soundhw sb16 -net user -net nic,model=e1000 ' #-d in_asm -d cpu_reset -d in_asm,int,mmu + debug_qemu_cmd = 'qemu-system-i386 -smp 2,sockets=1 -m 512M -name YiYiYa -rtc base=localtime -boot a -S -s -fda $SOURCE -serial stdio -D ./qemu.log -drive id=disk,file=image/disk.img,format=raw,if=none -device ahci,id=ahci -device ide-hd,drive=disk,bus=ahci.0 -device sb16 -net user -net nic,model=e1000 ' #-d in_asm -d cpu_reset -d in_asm,int,mmu debug_qemu_cmd =debug_qemu_cmd+' -monitor tcp:127.0.0.1:55555,server,nowait' pass elif env.get('ARCHTYPE') =='arm': diff --git a/image/kernel-v3s.its b/image/kernel-v3s.its index 129a96ff..7be15993 100644 --- a/image/kernel-v3s.its +++ b/image/kernel-v3s.its @@ -24,7 +24,7 @@ }; kernel { description = "YiYiYa kernel"; - data = /incbin/("../init/kernel.elf"); + data = /incbin/("../duck/init/kernel.elf"); type = "ramdisk"; arch = "arm"; os = "linux"; diff --git a/image/kernel.its b/image/kernel.its index c4808401..15f53700 100644 --- a/image/kernel.its +++ b/image/kernel.its @@ -11,7 +11,7 @@ images { kernel { description = "duck kernel"; - data = /incbin/("../main/kernel"); + data = /incbin/("../duck/init/kernel.elf"); type = "kernel"; arch = "x86"; os = "linux"; diff --git a/tools/mksunxi/mksunxiboot b/tools/mksunxi/mksunxiboot deleted file mode 100755 index 9c4cb40b..00000000 Binary files a/tools/mksunxi/mksunxiboot and /dev/null differ diff --git a/xenv/config.py b/xenv/config.py index 1d2fe765..d51f9fe6 100644 --- a/xenv/config.py +++ b/xenv/config.py @@ -9,7 +9,7 @@ # board select platform,选择你要编译的平台 # dmulator pc v3s raspi2 esp32 stm32f4xx raspi3 rk3128 rk3288 cubieboard2 dummy rk3288 orangepi-pc -platform = 'raspi2' +platform = 'v3s' # 是否要构建应用 default_apps = True @@ -31,7 +31,7 @@ ARFLAGS = 'rc' OBJCOPYFLAGS = ' -S -g' LINKFLAGS = '-nostdlib -nostartfiles -e start -g ' -LINKLD = ' -T xlinker/link.ld' +LINKLD = 'link-'+platform+'.ld'+ '' # -Map=kernel.map # ******************************************************************** # @@ -60,12 +60,10 @@ AS = CC_PREFIX+'as' OBJCOPY = CC_PREFIX+'objcopy' RANLIB = CC_PREFIX+'ranlib' -CFLAGS = '' +CFLAGS = '-DMALLOC_TRACE' LDFLAGS=' ' LINKLD = 'link-'+platform+'.ld'+ '' # -Map=kernel.map - - -default_apps = True +default_apps = False # osx i368 配置实例 @@ -77,8 +75,12 @@ # AS='i386-elf-as' # OBJCOPY='i386-elf-objcopy' # RANLIB='i386-elf-ranlib' -# CFLAGS='-march=i486' +# CFLAGS='-march=i486 -DMALLOC_TRACE' #-DMALLOC_TRACE -fsanitize=leak -fsanitize=address -lasan -fno-omit-frame-pointer +# LDFLAGS=' ' +# LINKLD = 'link.ld'+ ' -Xlinker -Map=kernel.map ' # +# # default_libc = 'libmusl' +# default_apps = True # windows arm 配置实例 @@ -91,19 +93,23 @@ # AS = CC_PREFIX+'as' # OBJCOPY = CC_PREFIX+'objcopy' # RANLIB = CC_PREFIX+'ranlib' - +# LDFLAGS=' ' +# LINKLD = 'link.ld'+ '' # -Map=kernel.map +# CFLAGS='' # windows i386 配置实例 - -# CC_PATH='' +# CC_PATH='D:\\app\\gcc\\bin\\' # CC_PREFIX='i686-elf-' +# CC = CC_PATH+CC_PREFIX+'gcc' # CC_LIB_PATH ='D:\\app\\gcc\\lib\\gcc\\i686-elf\\7.1.0\\' -# CC = CC_PREFIX+'gcc' -# AR = CC_PREFIX+'ar' -# LD = CC_PREFIX+'ld' -# AS = CC_PREFIX+'as' -# OBJCOPY = CC_PREFIX+'objcopy' -# RANLIB = CC_PREFIX+'ranlib' +# AR = CC_PATH+CC_PREFIX+'ar' +# LD= CC_PATH+CC_PREFIX+'ld' +# AS= CC_PATH+CC_PREFIX+'as' +# OBJCOPY = CC_PATH+CC_PREFIX+'objcopy' +# RANLIB = CC_PATH+CC_PREFIX+'ranlib' +# CFLAGS='-march=i486' +# LDFLAGS=' ' +# LINKLD = 'link.ld'+ '' # -Map=kernel.map # windows arm 配置实例 diff --git a/xenv/env.py b/xenv/env.py index 4b46070c..2f4e97ce 100644 --- a/xenv/env.py +++ b/xenv/env.py @@ -45,8 +45,7 @@ project_path=os.path.abspath(os.curdir) libc=['libc.a'] -libcflags='-DLIBYC' - +libcflags='' def get_arch(arch): archs={} @@ -59,16 +58,6 @@ def get_arch(arch): arch_type=get_arch(arch) archs=supports_archs[arch_type] - -if default_libc=='libmusl': - libc=[project_path+'/app/libmusl/lib/libc.a']#'/opt/local/lib/gcc/i386-elf/9.2.0/libgcc.a' - libcflags=' -D__LIB_MUSL__ -Iapp/libmusl/include/ -Iapp/libmusl/obj/include/ -Iapp/libmusl/arch/generic/ ' - if arch=='x86': - libcflags+=' -Iapp/libmusl/arch/i386/ ' - elif arch_type=='arm': - libcflags+=' -Iapp/libmusl/arch/arm/ ' - else: - print('no support libmusl type %s'%(arch)) print('welcome to yiyiya os build') print('your select platform: %s arch: %s support archs: %s build env:%s'%(platform,arch, archs, plt)) @@ -96,6 +85,7 @@ def get_arch(arch): env = Environment( ENV=os.environ, APP=default_apps, + CC_PREFIX=CC_PREFIX, CC = CC, LD= LD, CXX=CXX, @@ -117,7 +107,7 @@ def get_arch(arch): MYLIB=None, LIBC=libc, LIBCFLAGS=libcflags, - USER='--entry main -Tapp/xlinker/user.ld', + USER=' -Tapp/xlinker/user.ld', ARCHS=archs, ARCHTYPE=arch_type, CPPPATH=[], @@ -133,14 +123,16 @@ def get_arch(arch): env['MYLIB']='libgcc.a' pass elif plt=='Windows': - env['LINKFLAGS']='-nostdlib ', - env['CFLAGS']= env['CFLAGS']+' -fno-stack-protector -mno-stack-arg-probe ' #-ffreestanding -nostdlib + if arch=='x86': + env['CFLAGS']= env['CFLAGS']+' -fno-stack-protector -mno-stack-arg-probe ' #-ffreestanding -nostdlib env['USER']='--entry main -Tapp/xlinker/user.ld ' env['MYLIB']='libgcc.a' env['PROGSUFFIX'] = '' elif plt=='Darwin': env['MYLIB']='libgcc.a' +if env.get('DEFAULT_LIBC') == 'libmusl': + env['CFLAGS']+=' -DLIBC_POSIX ' if arch_type == 'x86': if platform=='x86_duck': @@ -149,7 +141,7 @@ def get_arch(arch): env['CFLAGS']+=' -march=i486 ' pass elif arch_type == 'arm': - env['USER']=' --entry main -Tapp/xlinker/user-arm.ld ' + env['USER']=' -Tapp/xlinker/user-arm.ld ' # -nostdlib -nostdinc -fno-builtin -DMALLOC_TRACE -mcpu=cortex-a7 -mtune=cortex-a7 -mfpu=vfpv4 -mfloat-abi=hard -mfloat-abi=softfp #env['CFLAGS']= env['CFLAGS']+ ' -fno-omit-fram e-pointer -mapcs -mno-sched-prolog ' #for debug backtrace @@ -159,12 +151,10 @@ def get_arch(arch): elif platform =='stm32f4xx': env['APP']=False env['CFLAGS']= env['CFLAGS']+ ' -specs=nosys.specs -mcpu=cortex-m4 -nolibc -nostdlib -nostdinc -fno-builtin -DUSE_HAL_DRIVER -mthumb -mthumb-interwork -mfloat-abi=soft -mfpu=vfpv4-d16 -DSTM32F401xC'# -DSTM32F401xC -Wl,--gc-sections -fdata-sections -ffunction-sections -mfpu=fpv4-sp-d16 -mcpu=cortex-m4 -ffreestanding -nostdlib -mfloat-abi=hard -mfpu=fpv4-sp-d16 # -mfloat-abi=hard -mfloat-abi=softfp -mfloat-abi=softfp - env['LINKLD']='xlinker/link-'+platform+'.ld' arch='armv7e-m' else: - env['USER']='--entry main -Tapp/xlinker/user-'+platform+'.ld' + env['USER']=' -Tapp/xlinker/user-'+platform+'.ld' env['CFLAGS']= env['CFLAGS']+ ' -mcpu=cortex-a7 -mtune=cortex-a7 -mfpu=vfpv4 -mfloat-abi=softfp ' - env['LINKLD']='xlinker/link-'+platform+'.ld' #env['CFLAGS']= ' -march='+arch elif arch_type=='xtensa': @@ -224,4 +214,9 @@ def generate_kernel_size(env,target,source): }) +bootEnv = env.Clone() +appEnv = env.Clone() + +Export('bootEnv') +Export('appEnv') Export('env') \ No newline at end of file