diff --git a/.blib.c.swp b/.blib.c.swp new file mode 100644 index 0000000..1e277a1 Binary files /dev/null and b/.blib.c.swp differ diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..360cd8e --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.vscode +*.o +runbin diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..58d26f9 --- /dev/null +++ b/Makefile @@ -0,0 +1,46 @@ +ENDIAN := EL + +QEMU := qemu-system-mipsel +CROSS_COMPILE := mips-linux-gnu- +CC := $(CROSS_COMPILE)gcc +CFLAGS += --std=gnu99 -$(ENDIAN) -G 0 -mno-abicalls -fno-pic \ + -ffreestanding -fno-stack-protector -fno-builtin \ + -Wa,-xgot -Wall -mxgot -mno-fix-r4000 -march=4kc -g -ggdb +LD := $(CROSS_COMPILE)ld +LDFLAGS += -$(ENDIAN) -G 0 -static -n -nostdlib --fatal-warnings +INCLUDES := -I./include + +qemu_flags += -cpu 4Kc -m 64 -nographic -M malta -no-reboot + +qemu_files += $(target) + +link_script := linker.lds +target := runbin + +objs := blib.o machine.o start.o test.o + +all: $(objs) + $(LD) $(LDFLAGS) -o $(target) -N -T $(link_script) $(objs) + +%.o: %.c + $(CC) $(CFLAGS) $(INCLUDES) -c $< + +%.o: %.S + $(CC) $(CFLAGS) $(INCLUDES) -c $< + +dbg_run: qemu_flags += -s -S +dbg_run: run + +dbg: + make dbg_run >/dev/null 2>&1 & + gdb-multiarch $(target) -ex "target remote localhost:1234" + killall $(QEMU) + +run: + $(QEMU) $(qemu_flags) -kernel $(qemu_files) + +clean: + rm -f *.o $(target) + +.PHONY: all clean run + diff --git a/README.md b/README.md deleted file mode 100644 index 6b6b764..0000000 --- a/README.md +++ /dev/null @@ -1 +0,0 @@ -2024春季北航操作系统课程代码,不同实验位于不同分支下,谨慎参考! diff --git a/blib.c b/blib.c new file mode 100644 index 0000000..40592fe --- /dev/null +++ b/blib.c @@ -0,0 +1,142 @@ +#include + +size_t strlen(const char *s) { + size_t i = 0; + while(s[i] != '\0') { + i++; + } + return i; +} + +char *strcpy(char *dst, const char *src) { + char *res = dst; + while ((*dst++ = *src++)) + ; + return res; +} + +char *strncpy(char *dst, const char *src, size_t n) { + char *res = dst; + while (*src && n--) { + *dst++ = *src++; + } + *dst = '\0'; + return res; +} + +int strcmp(const char *str1, const char *str2) { + while (*str1 && (*str1 == *str2)) { + str1++; + str2++; + } + return *(unsigned char *)str1 - *(unsigned char *)str2; +} + +int strncmp(const char *s1, const char *s2, size_t n) { + while (n--) { + if (*s1 != *s2) { + return *s1 - *s2; + } + if (*s1 == 0) { + break; + } + s1++; + s2++; + } + return 0; +} + +char *strcat(char *dst, const char *src) { + char *temp = dst; + while(*temp != '\0'){ + temp++; + } + while(*src != '\0'){ + *temp = *src; + temp++; + src++; + } + *temp = '\0'; + return dst; +} + +char *strncat(char *dst, const char *src, size_t n){ + size_t oplength = n; + if(strlen(src) < n) { + oplength = strlen(src); + } + char * temp = dst; + while(*temp != '\0') { + temp++; + } + for(size_t i = 0;i < oplength;i++) { + *temp++ = *src++; + } + *temp = '\0'; + return dst; +} + +char *strchr(const char *str, int character){ + while (*str != '\0') { + if (*str == (char)character) { + return (char *)str; + } + str++; + } + + return NULL; +} + +char* strsep(char** stringp, const char* delim){ + char *temp = *stringp; + char *preStringp = *stringp; + if(temp == NULL) { + return NULL; + } else { + while(*temp != '\0') { + const char* delete = delim; + while(*delete != '\0') { + if(*delete == *temp) { + *temp = '\0'; + *stringp = temp + 1; + return preStringp; + } + delete++; + } + temp++; + } + if(*temp == '\0'){ + *stringp = NULL; + } + return preStringp; + } +} + + +void *memset(void *s, int c, size_t n) { + unsigned char *p = s; + while (n--) { + *p++ = (unsigned char)c; + } + return s; +} + +void *memcpy(void *out, const void *in, size_t n) { + char *csrc = (char *)in; + char *cdst = (char *)out; + for (size_t i = 0; i < n; i++) { + cdst[i] = csrc[i]; + } + return out; +} + +int memcmp(const void *s1, const void *s2, size_t n) { + const unsigned char *p1 = s1, *p2 = s2; + while (n--) { + if (*p1 != *p2) { + return *p1 - *p2; + } + p1++, p2++; + } + return 0; +} diff --git a/include/asm/asm.h b/include/asm/asm.h new file mode 100644 index 0000000..90480f2 --- /dev/null +++ b/include/asm/asm.h @@ -0,0 +1,41 @@ +#include +#include + +/* + * LEAF - declare leaf routine + */ +#define LEAF(symbol) \ + .globl symbol; \ + .align 2; \ + .type symbol, @function; \ + .ent symbol; \ + symbol: \ + .frame sp, 0, ra + +/* + * NESTED - declare nested routine entry point + */ +#define NESTED(symbol, framesize, rpc) \ + .globl symbol; \ + .align 2; \ + .type symbol, @function; \ + .ent symbol; \ + symbol: \ + .frame sp, framesize, rpc + +/* + * END - mark end of function + */ +#define END(function) \ + .end function; \ + .size function, .- function + +#define EXPORT(symbol) \ + .globl symbol; \ + symbol: + +#define FEXPORT(symbol) \ + .globl symbol; \ + .type symbol, @function; \ + symbol: + diff --git a/include/asm/cp0regdef.h b/include/asm/cp0regdef.h new file mode 100644 index 0000000..2000dff --- /dev/null +++ b/include/asm/cp0regdef.h @@ -0,0 +1,52 @@ +#ifndef _cp0regdef_h_ +#define _cp0regdef_h_ + +#define CP0_INDEX $0 +#define CP0_RANDOM $1 +#define CP0_ENTRYLO0 $2 +#define CP0_ENTRYLO1 $3 +#define CP0_CONTEXT $4 +#define CP0_PAGEMASK $5 +#define CP0_WIRED $6 +#define CP0_BADVADDR $8 +#define CP0_COUNT $9 +#define CP0_ENTRYHI $10 +#define CP0_COMPARE $11 +#define CP0_STATUS $12 +#define CP0_CAUSE $13 +#define CP0_EPC $14 +#define CP0_PRID $15 +#define CP0_EBASE $15, 1 +#define CP0_CONFIG $16 +#define CP0_LLADDR $17 +#define CP0_WATCHLO $18 +#define CP0_WATCHHI $19 +#define CP0_XCONTEXT $20 +#define CP0_FRAMEMASK $21 +#define CP0_DIAGNOSTIC $22 +#define CP0_PERFORMANCE $25 +#define CP0_ECC $26 +#define CP0_CACHEERR $27 +#define CP0_TAGLO $28 +#define CP0_TAGHI $29 +#define CP0_ERROREPC $30 + +#define STATUS_CU3 0x80000000 +#define STATUS_CU2 0x40000000 +#define STATUS_CU1 0x20000000 +#define STATUS_CU0 0x10000000 +#define STATUS_BEV 0x00400000 +#define STATUS_IM0 0x0100 +#define STATUS_IM1 0x0200 +#define STATUS_IM2 0x0400 +#define STATUS_IM3 0x0800 +#define STATUS_IM4 0x1000 +#define STATUS_IM5 0x2000 +#define STATUS_IM6 0x4000 +#define STATUS_IM7 0x8000 +#define STATUS_UM 0x0010 +#define STATUS_R0 0x0008 +#define STATUS_ERL 0x0004 +#define STATUS_EXL 0x0002 +#define STATUS_IE 0x0001 +#endif diff --git a/include/asm/regdef.h b/include/asm/regdef.h new file mode 100644 index 0000000..2b73ed2 --- /dev/null +++ b/include/asm/regdef.h @@ -0,0 +1,43 @@ +#ifndef __ASM_MIPS_REGDEF_H +#define __ASM_MIPS_REGDEF_H + +/* + * Symbolic register names for 32 bit ABI + */ +#define zero $0 /* wired zero */ +#define AT $1 /* assembler temp - uppercase because of ".set at" */ +#define v0 $2 /* return value */ +#define v1 $3 +#define a0 $4 /* argument registers */ +#define a1 $5 +#define a2 $6 +#define a3 $7 +#define t0 $8 /* caller saved */ +#define t1 $9 +#define t2 $10 +#define t3 $11 +#define t4 $12 +#define t5 $13 +#define t6 $14 +#define t7 $15 +#define s0 $16 /* callee saved */ +#define s1 $17 +#define s2 $18 +#define s3 $19 +#define s4 $20 +#define s5 $21 +#define s6 $22 +#define s7 $23 +#define t8 $24 /* caller saved */ +#define t9 $25 +#define jp $25 /* PIC jump register */ +#define k0 $26 /* kernel scratch */ +#define k1 $27 +#define gp $28 /* global pointer */ +#define sp $29 /* stack pointer */ +#define fp $30 /* frame pointer */ +#define s8 $30 /* same like fp! */ +#define ra $31 /* return address */ + +#endif /* __ASM_MIPS_REGDEF_H */ + diff --git a/include/blib.h b/include/blib.h new file mode 100644 index 0000000..1fd866f --- /dev/null +++ b/include/blib.h @@ -0,0 +1,24 @@ +#ifndef _BLIB_H +#define _BLIB_H + +#include +#include + +typedef unsigned int size_t; +#define NULL 0 + + +size_t strlen(const char *s); +char *strcpy(char *dst, const char *src); +char *strncpy(char *dst, const char *src, size_t n); +char *strcat(char *dst, const char *src); +char *strncat(char *dest, const char *src, size_t n); +int strcmp(const char *s1, const char *s2); +int strncmp(const char *s1, const char *s2, size_t n); +char *strchr(const char *str, int character); +char* strsep(char** stringp, const char* delim); +void *memset(void *s, int c, size_t n); +void *memcpy(void *dst, const void *src, size_t n); +int memcmp(const void *s1, const void *s2, size_t n); + +#endif diff --git a/include/blib_macros.h b/include/blib_macros.h new file mode 100644 index 0000000..3c082c0 --- /dev/null +++ b/include/blib_macros.h @@ -0,0 +1,28 @@ +#ifndef _BLIB_MACROS_H__ +#define _BLIB_MACROS_H__ + +#define STRINGIFY(s) #s +#define TOSTRING(s) STRINGIFY(s) + +#define putstr(s) \ + ({ \ + for (const char *p = s; *p; p++) \ + m_putch(*p); \ + }) + + + +#define panic_on(cond, s) \ + ({ \ + if (cond) { \ + putstr("panic: "); \ + putstr(s); \ + putstr(" @ " __FILE__ ":" TOSTRING(__LINE__) " \n"); \ + m_halt(); \ + } \ + }) + +#define panic(s) panic_on(1, s) + + +#endif /* _printk_h_ */ diff --git a/include/machine.h b/include/machine.h new file mode 100644 index 0000000..56c2120 --- /dev/null +++ b/include/machine.h @@ -0,0 +1,55 @@ +#ifndef _MACHINE_H +#define _MACHINE_H + +// Memory segments (32-bit kernel mode addresses) +#define KUSEG 0x00000000U +#define KSEG0 0x80000000U +#define KSEG1 0xA0000000U +#define KSEG2 0xC0000000U + +/* + * QEMU MMIO address definitions. + */ +#define MALTA_PCIIO_BASE 0x18000000 +#define MALTA_FPGA_BASE 0x1f000000 + +/* + * 16550 Serial UART device definitions. + */ +#define MALTA_SERIAL_BASE (MALTA_PCIIO_BASE + 0x3f8) +#define MALTA_SERIAL_DATA (MALTA_SERIAL_BASE + 0x0) +#define MALTA_SERIAL_LSR (MALTA_SERIAL_BASE + 0x5) +#define MALTA_SERIAL_DATA_READY 0x1 + +/* + * Intel PIIX4 IDE Controller device definitions. + * Hardware documentation available at + * https://www.intel.com/Assets/PDF/datasheet/290562.pdf + */ +#define MALTA_IDE_BASE (MALTA_PCIIO_BASE + 0x01f0) +#define MALTA_IDE_DATA (MALTA_IDE_BASE + 0x00) +#define MALTA_IDE_ERR (MALTA_IDE_BASE + 0x01) +#define MALTA_IDE_NSECT (MALTA_IDE_BASE + 0x02) +#define MALTA_IDE_LBAL (MALTA_IDE_BASE + 0x03) +#define MALTA_IDE_LBAM (MALTA_IDE_BASE + 0x04) +#define MALTA_IDE_LBAH (MALTA_IDE_BASE + 0x05) +#define MALTA_IDE_DEVICE (MALTA_IDE_BASE + 0x06) +#define MALTA_IDE_STATUS (MALTA_IDE_BASE + 0x07) +#define MALTA_IDE_LBA 0xE0 +#define MALTA_IDE_BUSY 0x80 +#define MALTA_IDE_CMD_PIO_READ 0x20 /* Read sectors with retry */ +#define MALTA_IDE_CMD_PIO_WRITE 0x30 /* write sectors with retry */ + +/* + * MALTA Power Management device definitions. + */ +#define MALTA_FPGA_HALT (MALTA_FPGA_BASE + 0x500) + + +/* IO function */ +void m_putch(char ch); +char m_getch(void); +/* when call this func, gxemul will quit */ +void m_halt(void); + +#endif diff --git a/linker.lds b/linker.lds new file mode 100644 index 0000000..577e97e --- /dev/null +++ b/linker.lds @@ -0,0 +1,25 @@ +/* + * Set the architecture to mips. + */ +OUTPUT_ARCH(mips) + +/* + * Set the ENTRY point of the program to _start. + */ +ENTRY(_start) + +SECTIONS { + . = 0x80020000; + + .text : { + *(.text) + } + + .data : { + *(.data) + } + + .bss : { + *(.bss) + } +} diff --git a/machine.c b/machine.c new file mode 100644 index 0000000..6c256c1 --- /dev/null +++ b/machine.c @@ -0,0 +1,21 @@ +#include +#include + +void m_putch(char ch) { + *((volatile char *)(KSEG1 + MALTA_SERIAL_DATA)) = ch; +} + +char m_getch(void) { + if (*((volatile char *)(KSEG1 + MALTA_SERIAL_LSR)) & MALTA_SERIAL_DATA_READY) { + return *((volatile char *)(KSEG1 + MALTA_SERIAL_DATA)); + } + return 0; +} + +void m_halt(void) { + *(char *)(KSEG1 + MALTA_FPGA_HALT) = 0x42; + putstr("machine.c:\thalt is not supported in this machine!\n"); + while (1) { + ; + } +} diff --git a/start.S b/start.S new file mode 100644 index 0000000..a59dd37 --- /dev/null +++ b/start.S @@ -0,0 +1,11 @@ +#include + +.text +EXPORT(_start) +.set at +.set reorder + + mtc0 zero, CP0_STATUS + li sp, 0x80400000 + jal main + j m_halt diff --git a/test.c b/test.c new file mode 100644 index 0000000..876a336 --- /dev/null +++ b/test.c @@ -0,0 +1,65 @@ +#include + +char str[] = "324234+sdfsd+-dsfsffsd/sdfsd*/sdfsdfsdf*3224324///"; +const char *sarray[] = { + "324234", + "sdfsd", + "", + "dsfsffsd", + "sdfsd", + "", + "sdfsdfsdf", + "3224324", + "", + "", + "" + }; + +int main() { + putstr("begin check string\n"); + + panic_on((strlen(str) != 50), "check failed at"); + panic_on((strlen(sarray[2]) != 0), "check failed at"); + + char destination[20] = "Hello, "; + const char *source = "World!"; + char *s = strcat(destination,source); + panic_on((strcmp(s,"Hello, World!") != 0),"check failed at"); + panic_on((strcmp(destination,"Hello, World!") != 0),"check failed at"); + + char destination2[20] = "Hello, "; + const char *source2 = "World!World!World!"; + s = strncat(destination2,source2,6); + panic_on((strcmp(s,"Hello, World!") != 0),"check failed at"); + panic_on((strcmp(destination2,"Hello, World!") != 0),"check failed at"); + + char destination3[20] = "Hello, "; + const char *source3 = "World!"; + s = strncat(destination3,source3,200); + panic_on((strcmp(s,"Hello, World!") != 0),"check failed at"); + panic_on((strcmp(destination3,"Hello, World!") != 0),"check failed at"); + + char destination4[20] = "Hello, "; + const char *source4 = "World!"; + s = strncat(destination4,source4,0); + panic_on((strcmp(s,"Hello, ") != 0),"check failed at"); + panic_on((strcmp(destination4,"Hello, ") != 0),"check failed at"); + + char destination5[20] = ""; + const char *source5 = "Hello World!"; + s = strncat(destination5,source5,12); + panic_on((strcmp(s,"Hello World!") != 0),"check failed at"); + panic_on((strcmp(destination5,"Hello World!") != 0),"check failed at"); + + + char *token; + char *rest = str; + const char *delimiters = "+-*/"; + int index = 0; + while ((token = strsep(&rest, delimiters)) != NULL) { + panic_on((strcmp(sarray[index++],token) != 0), "check failed at"); + } + + putstr("string test pass!\n"); + return 0; +}